001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.i18n; 017 018import java.net.URL; 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Locale; 022import org.modeshape.common.util.CheckArg; 023 024/** 025 * Class that loads a properties file from the classpath of the supplied {@link ClassLoader class loader}. 026 * <p> 027 * This repository for a property file by building locations of the form "path/to/class_locale.properties", where "path/to/class" 028 * is created from the fully-qualified classname and all "." replaced with "/" characters, "locale" is the a variant of the locale 029 * (first the full locale, then subsequently with the last segment removed). As soon as a property file is found, its URL is 030 * returned immediately. 031 * </p> 032 * named with a name that matches 033 */ 034public final class ClasspathLocalizationRepository { 035 036 private ClasspathLocalizationRepository() { 037 } 038 039 /** 040 * Obtain the URL to the properties file containing the localized messages given the supplied bundle name. This method is 041 * responsible for searching to find the most appropriate localized messages given the locale, but does not need to search 042 * using the {@link Locale#getDefault() default locale} (as that is done by the {@link I18n#text(Object...) calling} method. 043 * 044 * @param classLoader the classloader that should be used to load the localization bundles 045 * @param bundleName the name of the bundle of properties; never null 046 * @param locale the locale for which the properties file URL is desired 047 * @return the URL to the properties file containing the localized messages for the named bundle, or null if no such bundle 048 * could be found 049 */ 050 public static URL getLocalizationBundle( ClassLoader classLoader, 051 String bundleName, 052 Locale locale ) { 053 CheckArg.isNotNull(classLoader, "classLoader"); 054 URL url = null; 055 List<String> paths = getPathsToSearchForBundle(bundleName, locale); 056 for (String path : paths) { 057 url = classLoader.getResource(path); 058 if (url != null) { 059 return url; 060 } 061 } 062 return url; 063 } 064 065 /** 066 * Returns a list of paths (as string) of the different bundles searched in the 067 * {@link ClasspathLocalizationRepository#getLocalizationBundle(ClassLoader, String, java.util.Locale)} method. 068 * 069 * @param bundleName the name of the bundle of properties; never null 070 * @param locale the locale for which the properties file URL is desired 071 * @return a list of paths which the repository would look at. 072 */ 073 static List<String> getPathsToSearchForBundle( String bundleName, 074 Locale locale ) { 075 List<String> result = new ArrayList<String>(); 076 String pathPrefix = bundleName.replaceAll("\\.", "/"); 077 String localeVariant = '_' + locale.toString(); 078 int ndx = localeVariant.lastIndexOf('_'); 079 080 while (ndx >= 0) { 081 String path = pathPrefix + localeVariant + ".properties"; 082 result.add(path); 083 localeVariant = localeVariant.substring(0, ndx); 084 ndx = localeVariant.lastIndexOf('_'); 085 } 086 result.add(pathPrefix + localeVariant + ".properties"); 087 return result; 088 } 089}