/******************************************************************************* * * Copyright 2011-2014 Spiffy UI Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.spiffyui.server.filter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; /** * Filter that will substitute the various markers in retrieved * xml and jnlp files with values retrieved from the servlet * context. */ public abstract class GWTLocaleBundleFilter extends GWTLocaleFilter { /** * This is the map of files and locales. There is a map for each resource name with * the key of the locale and value of the file name. We cache the results on the first * request so we only have to build the map once. */ private static final Map<String, Map<Locale, String>> RESOURCES = new HashMap<String, Map<Locale, String>>(); private static final List<String> ALL_RESOURCES = new ArrayList<String>(); @Override public void init(final FilterConfig filterConfig) { populateMap(filterConfig.getServletContext(), getResourcePath()); } /** * Get the path to the localization resources to determine the supported locales from * * @return the localization path */ protected abstract String getResourcePath(); /** * Get the list of locales supported for this application. * * @return the list of supported locales */ @Override protected List<Locale> getMinimumSupportedLocales() { Map<Locale, String> map = null; for (String file : RESOURCES.keySet()) { Map<Locale, String> m = RESOURCES.get(file); if (map == null) { map = m; } else if (m.size() > 1 && m.size() < map.size()) { map = m; } } if (map == null) { throw new IllegalArgumentException("No files found at " + getResourcePath()); } ArrayList<Locale> locales = new ArrayList<Locale>(); for (Locale l : map.keySet()) { locales.add(l); } return locales; } private static Map<Locale, String> getMap(String fileName) { Map<Locale, String> map = RESOURCES.get(fileName); if (map == null) { map = new HashMap<Locale, String>(); RESOURCES.put(fileName, map); } return map; } private static synchronized void populateMap(ServletContext context, String resourcePath) { if (RESOURCES.size() > 0) { /* * Then we have already populated the map */ return; } Set<String> set = context.getResourcePaths(resourcePath); Iterator<String> iter = set.iterator(); while (iter.hasNext()) { String file = iter.next().toString(); file = file.substring(file.lastIndexOf('/') + 1); ALL_RESOURCES.add(file); /* * At this point the file should look like this: * UIStrings.properties or like this UIStrings_fr.properties. */ int dash = file.indexOf('_'); if (dash == -1) { /* * The file with no locale is English. */ if (file.indexOf('.') > -1) { getMap(file.substring(0, file.indexOf('.'))).put(new Locale("en"), file); } continue; } String fileName = file.substring(0, dash); String language = null; String country = null; int index = dash + 1; int dashCount = 0; for (int i = dash + 1; i < file.length(); i++) { char c = file.charAt(i); if (c == '-' || c == '_') { if (dashCount == 0) { /* * Then we are after the first dash and before the second * one. That makes this the language code. */ language = file.substring(index, i); } else { /* * This means the file has more than two dashes. That means * we don't know hoe to deal with it and we will ignore it. */ fileName = null; break; } index = i + 1; dashCount++; } else if (c == '.') { if (dashCount == 0) { /* * Then we are after the first dash and before the ending * dot. That makes this the language code in a file with * no country code. */ language = file.substring(index, i); } else if (dashCount == 1) { /* * Then we are after the second dash and before the ending * dot. That makes this the country code */ country = file.substring(index, i); } /* * Either way, when we hit the dot we are done with * the file. */ break; } } if (fileName == null) { continue; } if (language != null) { if (country == null) { getMap(fileName).put(new Locale(language), file); } else { getMap(fileName).put(new Locale(language, country), file); } } } } }