Return-Path: Delivered-To: apmail-incubator-wicket-commits-archive@locus.apache.org Received: (qmail 66071 invoked from network); 1 Mar 2007 08:09:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 1 Mar 2007 08:09:46 -0000 Received: (qmail 66739 invoked by uid 500); 1 Mar 2007 08:09:55 -0000 Delivered-To: apmail-incubator-wicket-commits-archive@incubator.apache.org Received: (qmail 66730 invoked by uid 500); 1 Mar 2007 08:09:55 -0000 Mailing-List: contact wicket-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: wicket-dev@incubator.apache.org Delivered-To: mailing list wicket-commits@incubator.apache.org Received: (qmail 66721 invoked by uid 99); 1 Mar 2007 08:09:55 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Mar 2007 00:09:55 -0800 X-ASF-Spam-Status: No, hits=-98.6 required=10.0 tests=ALL_TRUSTED,INFO_TLD,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Mar 2007 00:09:43 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 6C6571A981A; Thu, 1 Mar 2007 00:09:23 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r513221 - in /incubator/wicket/trunk/wicket/src: main/java/wicket/ main/java/wicket/markup/html/ main/java/wicket/resource/ main/java/wicket/resource/loader/ main/java/wicket/settings/ main/java/wicket/util/resource/locator/ test/java/wicke... Date: Thu, 01 Mar 2007 08:09:21 -0000 To: wicket-commits@incubator.apache.org From: jdonnerstag@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070301080923.6C6571A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jdonnerstag Date: Thu Mar 1 00:09:19 2007 New Revision: 513221 URL: http://svn.apache.org/viewvc?view=rev&rev=513221 Log: reworked Localizer Added: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesChangeListener.java - copied, changed from r500779, incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesReloadListener.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ComponentStringResourceLoader.java - copied, changed from r500779, incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/AbstractStringResourceLoader.java incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceNameIterator.java (with props) Removed: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesReloadListener.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/AbstractStringResourceLoader.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ApplicationStringResourceLoader.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/WicketBundleStringResourceLoader.java incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/IWicketResourceNameIterator.java Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/Localizer.java incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/AjaxServerAndClientTimeFilter.java incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/ServerAndClientTimeFilter.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesFactory.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/Properties.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/PropertiesFactory.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ClassStringResourceLoader.java incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/IStringResourceLoader.java incubator/wicket/trunk/wicket/src/main/java/wicket/settings/Settings.java incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ExtensionResourceNameIterator.java incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/LocaleResourceNameIterator.java incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceStreamFactory.java incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java incubator/wicket/trunk/wicket/src/test/java/wicket/ApplicationSettingsTest.java incubator/wicket/trunk/wicket/src/test/java/wicket/LocalizerTest.java incubator/wicket/trunk/wicket/src/test/java/wicket/WicketMessageAttributeTest.java incubator/wicket/trunk/wicket/src/test/java/wicket/properties/PropertiesTest.java incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ApplicationStringResourceLoaderTest.java incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ComponentStringResourceLoaderTest.java Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/Localizer.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/Localizer.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/Localizer.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/Localizer.java Thu Mar 1 00:09:19 2007 @@ -16,20 +16,13 @@ */ package wicket; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; import java.util.Locale; import java.util.MissingResourceException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import wicket.model.IModel; import wicket.resource.loader.IStringResourceLoader; import wicket.settings.IResourceSettings; import wicket.util.string.AppendingStringBuffer; -import wicket.util.string.Strings; import wicket.util.string.interpolator.PropertyVariableInterpolator; /** @@ -49,13 +42,10 @@ * * @author Chris Turner * @author Juergen Donnerstag + * @todo implement properties caching */ public class Localizer { - /** Log */ - @SuppressWarnings("unused") - private static final Logger log = LoggerFactory.getLogger(Localizer.class); - /** * Create the utils instance class backed by the configuration information * contained within the supplied application object. @@ -79,7 +69,7 @@ public String getString(final String key, final Component component) throws MissingResourceException { - return getString(key, component, null, null, null, null); + return getString(key, component, null, null); } /** @@ -100,30 +90,7 @@ public String getString(final String key, final Component component, final IModel model) throws MissingResourceException { - return getString(key, component, model, null, null, null); - } - - /** - * @see #getString(String, Component, IModel, Locale, String, String) - * - * @param key - * The key to obtain the resource for - * @param component - * The component to get the resource for - * @param model - * The model to use for property substitutions in the strings - * (optional) - * @param defaultValue - * The default value (optional) - * @return The string resource - * @throws MissingResourceException - * If resource not found and configuration dictates that - * exception should be thrown - */ - public String getString(final String key, final Component component, final IModel model, - final String defaultValue) throws MissingResourceException - { - return getString(key, component, model, null, null, defaultValue); + return getString(key, component, model, null); } /** @@ -143,7 +110,7 @@ public String getString(final String key, final Component component, final String defaultValue) throws MissingResourceException { - return getString(key, component, null, null, null, defaultValue); + return getString(key, component, null, defaultValue); } /** @@ -159,11 +126,6 @@ * The component to get the resource for (optional) * @param model * The model to use for substitutions in the strings (optional) - * @param locale - * The locale to get the resource for (optional) - * @param style - * The style to get the resource for (optional) (see - * {@link wicket.Session}) * @param defaultValue * The default value (optional) * @return The string resource @@ -172,48 +134,21 @@ * exception should be thrown */ public String getString(final String key, final Component component, final IModel model, - Locale locale, String style, final String defaultValue) throws MissingResourceException + final String defaultValue) throws MissingResourceException { - final List searchStack; - final String path; - if (component != null) - { - // The reason why we need to create that stack is because we need to - // walk it downwards starting with Page down to the Component - searchStack = getComponentStack(component); - path = Strings.replaceAll(component.getPageRelativePath(), ":", ".").toString(); - - if (locale == null) - { - locale = component.getLocale(); - } - - if (style == null) - { - style = component.getStyle(); - } - } - else + // Iterate over all registered string resource loaders until the + // property has been found + String string = null; + for (IStringResourceLoader loader : Application.get().getResourceSettings() + .getStringResourceLoaders()) { - searchStack = null; - path = null; - - Session session = Session.get(); - if (locale == null) - { - locale = session.getLocale(); - } - - if (style == null) + string = loader.loadStringResource(component, key); + if (string != null) { - style = session.getStyle(); + break; } } - // Iterate over all registered string resource loaders until the - // property has been found - String string = visitResourceLoaders(key, path, searchStack, locale, style); - // If a property value has been found, than replace the placeholder // and we are done if (string != null) @@ -242,73 +177,8 @@ throw new MissingResourceException(message.toString(), (component != null ? component .getClass().getName() : ""), key); } - else - { - return "[Warning: String resource for '" + key + "' not found]"; - } - } - - /** - * Note: This implementation does NOT perform variable substitution - * - * @param key - * The key to obtain the resource for - * @param searchStack - * A stack of classes to get the resource for - * @param path - * A (file) path to the resource containing the key - * @param locale - * The locale to get the resource for (optional) - * @param style - * The style to get the resource for (optional) (see - * {@link wicket.Session}) - * @return The string resource - * @throws MissingResourceException - * If resource not found and configuration dictates that - * exception should be thrown - */ - private String getString(final String key, final String path, final Locale locale, - final String style) throws MissingResourceException - { - return visitResourceLoaders(key, path, null, locale, style); - } - - /** - * Traverse the component hierachy up to the Page and add each component - * class to the list (stack) returned - * - * @param component - * The component to evaluate - * @return The stack of classes - */ - public static List getComponentStack(final Component component) - { - // No component, no stack - if (component == null) - { - return null; - } - - // Build the search stack - final List searchStack = new ArrayList(); - searchStack.add(component.getClass()); - - if (!(component instanceof Page)) - { - // Add all the component on the way to the Page - MarkupContainer container = component.getParent(); - while (container != null) - { - searchStack.add(container.getClass()); - if (container instanceof Page) - { - break; - } - container = container.getParent(); - } - } - return searchStack; + return "[Warning: String resource for '" + key + "' not found]"; } /** @@ -329,89 +199,6 @@ { return PropertyVariableInterpolator.interpolate(string, model.getObject()); } - return string; - } - - /** - * For each StringResourceLoader registered with the application, load the - * properties file associated with the classes in the searchStack, the - * locale and the style. The searchStack is traversed in reverse order. - *

- * The property is identified by the 'key' or 'path'+'key'. 'path' is - * shortened (last element removed) to always represent the page relative - * path of the original component associate with it. - * - * @param key - * The key to obtain the resource for - * @param path - * The component id path relative to the page - * @param searchStack - * A stack of classes to get the resource for - * @param locale - * The locale to get the resource for (optional) - * @param style - * The style to get the resource for (optional) (see - * {@link wicket.Session}) - * @return The string resource - */ - private String visitResourceLoaders(final String key, final String path, - final List searchStack, final Locale locale, final String style) - { - // Search each loader in turn and return the string if it is found - final Iterator iterator = Application.get().getResourceSettings() - .getStringResourceLoaders().iterator(); - - // The return value - String string = null; - - // Iterate until a property has been found - while (iterator.hasNext() && (string == null)) - { - IStringResourceLoader loader = iterator.next(); - - // The key prefix is equal to the component path relativ to the - // current component on the top of the stack. - String prefix = path; - if ((searchStack != null) && (searchStack.size() > 0)) - { - // Walk the component hierarchy down from page to the component - for (int i = searchStack.size() - 1; (i >= 0) && (string == null); i--) - { - Class clazz = (Class)searchStack.get(i); - - // First check if a property with the 'key' provided by the - // user is available. - string = loader.loadStringResource(clazz, key, locale, style); - - // If not, prepend the component relativ path to the key - if ((string == null) && (path != null) && (prefix.length() > 0)) - { - string = loader - .loadStringResource(clazz, prefix + '.' + key, locale, style); - - // If still not found, adjust the component relativ path - // for the next component on the path from the page - // down. - if (string == null) - { - prefix = Strings.afterFirst(prefix, '.'); - } - } - } - } - else - { - // A default string resource loader, e.g. the - // ApplicationStringResourceLoader, - // does not necessarily require the component hierachy - string = loader.loadStringResource(null, key, locale, style); - if ((string == null) && (prefix != null) && (prefix.length() > 0)) - { - string = loader.loadStringResource(null, prefix + '.' + key, locale, style); - } - } - } - return string; } } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/AjaxServerAndClientTimeFilter.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/AjaxServerAndClientTimeFilter.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/AjaxServerAndClientTimeFilter.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/AjaxServerAndClientTimeFilter.java Thu Mar 1 00:09:19 2007 @@ -25,18 +25,15 @@ import wicket.Application; import wicket.IResponseFilter; import wicket.RequestCycle; -import wicket.Session; -import wicket.model.Model; import wicket.util.string.AppendingStringBuffer; import wicket.util.string.JavascriptUtils; /** * This is a filter that injects javascript code to the top head portion and * after the body so that the time can me measured what the client parse time - * was for this page and for ajax calls done on the page. - * It also reports the total server parse/response time in the client and logs - * the server response time and response size it took for a specific response - * in the server log. + * was for this page and for ajax calls done on the page. It also reports the + * total server parse/response time in the client and logs the server response + * time and response size it took for a specific response in the server log. * * You can specify what the status text should be like this: * ServerAndClientTimeFilter.statustext=My Application, Server parsetime: @@ -100,16 +97,25 @@ */ private String getStatusString(long timeTaken, String resourceKey) { - Map map = new HashMap(4); - map.put("clienttime", "' + (new Date().getTime() - clientTimeVariable)/1000 + 's"); - map.put("servertime", ((double)timeTaken) / 1000 + "s"); - AppendingStringBuffer defaultValue = new AppendingStringBuffer(128); - defaultValue.append("Server parsetime: "); - defaultValue.append(((double)timeTaken) / 1000); - defaultValue.append("s, Client parsetime: ' + (new Date().getTime() - clientTimeVariable)/1000 + 's"); - String txt = Application.get().getResourceSettings().getLocalizer().getString(resourceKey, - null, Model.valueOf(map), Session.get().getLocale(), Session.get().getStyle(), - defaultValue.toString()); + String txt = Application.get().getResourceSettings().getLocalizer().getString(resourceKey, null); + if (txt == null) + { + Map map = new HashMap(4); + map.put("clienttime", "' + (new Date().getTime() - clientTimeVariable)/1000 + 's"); + map.put("servertime", ((double)timeTaken) / 1000 + "s"); + + txt = map.get(resourceKey); + } + if (txt == null) + { + AppendingStringBuffer defaultValue = new AppendingStringBuffer(128); + defaultValue.append("Server parsetime: "); + defaultValue.append(((double)timeTaken) / 1000); + defaultValue.append("s, Client parsetime: ' + (new Date().getTime() - clientTimeVariable)/1000 + 's"); + + txt = defaultValue.toString(); + } + return txt; } } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/ServerAndClientTimeFilter.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/ServerAndClientTimeFilter.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/ServerAndClientTimeFilter.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/ServerAndClientTimeFilter.java Thu Mar 1 00:09:19 2007 @@ -26,7 +26,6 @@ import wicket.Application; import wicket.IResponseFilter; import wicket.RequestCycle; -import wicket.Session; import wicket.model.Model; import wicket.util.string.AppendingStringBuffer; import wicket.util.string.JavascriptUtils; @@ -70,7 +69,7 @@ String txt = Application.get().getResourceSettings().getLocalizer().getString( "ServerAndClientTimeFilter.statustext", null, Model.valueOf(map), - Session.get().getLocale(), Session.get().getStyle(), defaultValue.toString()); + defaultValue.toString()); AppendingStringBuffer endScript = new AppendingStringBuffer(150); endScript.append("\n").append(JavascriptUtils.SCRIPT_OPEN_TAG); endScript.append("\nwindow.defaultStatus='"); Copied: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesChangeListener.java (from r500779, incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesReloadListener.java) URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesChangeListener.java?view=diff&rev=513221&p1=incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesReloadListener.java&r1=500779&p2=incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesChangeListener.java&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesReloadListener.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesChangeListener.java Thu Mar 1 00:09:19 2007 @@ -18,16 +18,16 @@ /** * To be implemented by listeners interested in PropertiesFactory events fired - * after a new properties files has been loaded + * after a change to the properties has been detected * * @author Juergen Donnerstag */ -public abstract interface IPropertiesReloadListener +public abstract interface IPropertiesChangeListener { /** - * Fired after a new properties files has been loaded + * Fired after a properties file change has been detected * * @param key */ - void propertiesLoaded(final String key); + void propertiesChanged(final String key); } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesFactory.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesFactory.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesFactory.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/IPropertiesFactory.java Thu Mar 1 00:09:19 2007 @@ -16,34 +16,39 @@ */ package wicket.resource; -import java.util.Locale; /** - * Interface to be implemented by properties loaders + * IPropertyiesFactory is not a 100% replacement for java.util.Properties as it + * does not provide the same interface. But it serves kind of the same purpose + * with Wicket specific features. E.g. besides Locale it take 'styles' and + * 'variations' into account as well, it allows to register listeners which get + * called when a property resource has changed and it allows to clear the + * locally cached properties. + * + * @see wicket.resource.Properties * * @author Juergen Donnerstag */ public interface IPropertiesFactory { /** - * Add a listener which will be called after properties have been reloaded + * Add a listener which will be called when a change to the underlying + * resource stream (e.g. properties file) has been detected * * @param listener */ - void addListener(final IPropertiesReloadListener listener); + void addListener(final IPropertiesChangeListener listener); /** - * Get the properties for ... + * Load the properties associated with the path * * @param clazz - * The class that resources are bring loaded for - * @param style - * The style to load resources for (see {@link wicket.Session}) - * @param locale - * The locale to load reosurces for + * The class requesting the properties + * @param path + * The path to identify the resource * @return The properties */ - Properties get(final Class clazz, final String style, final Locale locale); + Properties load(final Class clazz, final String path); /** * Remove all cached properties Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/Properties.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/Properties.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/Properties.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/Properties.java Thu Mar 1 00:09:19 2007 @@ -19,17 +19,18 @@ import wicket.util.value.ValueMap; /** - * Reloadable properties. It is not a 100% replacement for java.util.Properties - * as it does not provide the same interface. But is serves kind of the same - * purpose with Wicket specific features. + * Kind of like java.util.Properties but based on Wicket's ValueMap and thus + * benefiting from all its nice build-in type converters and without parent + * properties. * * @author Juergen Donnerstag */ public final class Properties { - /** Log. */ - // private static final Logger log = LoggerFactory.getLogger(Properties.class); - /** The resource key for the properties file */ + /** Empty Properties */ + public static final Properties EMPTY_PROPERTIES = new Properties("NULL", ValueMap.EMPTY_MAP); + + /** A unique key for this specific group of properties. */ private final String key; /** Property values */ @@ -50,7 +51,7 @@ } /** - * Get all values from the properties file + * Get direct access to all values from the properties file. * * @return map */ @@ -60,7 +61,7 @@ } /** - * Get the property message identified by 'key' + * Get the property value identified by its 'key'. * * @param key * @return property message @@ -71,7 +72,6 @@ } /** - * * @see java.lang.Object#toString() */ @Override Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/PropertiesFactory.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/PropertiesFactory.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/PropertiesFactory.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/PropertiesFactory.java Thu Mar 1 00:09:19 2007 @@ -20,23 +20,21 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import wicket.Application; -import wicket.Component; import wicket.settings.IResourceSettings; import wicket.util.listener.IChangeListener; import wicket.util.resource.IFixedLocationResourceStream; import wicket.util.resource.IResourceStream; import wicket.util.resource.ResourceStreamNotFoundException; -import wicket.util.string.AppendingStringBuffer; +import wicket.util.resource.locator.ResourceStreamFactory; import wicket.util.string.Strings; import wicket.util.value.ValueMap; import wicket.util.watch.ModificationWatcher; @@ -44,9 +42,11 @@ /** * Reloadable properties. It is not a 100% replacement for java.util.Properties * as it does not provide the same interface. But is serves kind of the same - * purpose with Wicket specific features. PropertiesFactory actually loads and - * reloads the Properties and maintaines a cache. Hence properties files are - * loaded just once. + * purpose with Wicket specific features as it take Locale, style and variations + * into account. PropertiesFactory loads and reloads the Properties and + * maintaines a cache. Hence property files are loaded just once, but are + * reloaded if a change to a property file has been detected (actually the cache + * gets cleared which forces a reload on demand). * * @see wicket.settings.IResourceSettings#getPropertiesFactory() * @@ -57,29 +57,40 @@ /** Log. */ private static final Logger log = LoggerFactory.getLogger(PropertiesFactory.class); - /** Cache for all properties files loaded */ - private final Map propertiesCache = new HashMap(); + /** Cache for all property files loaded */ + private final Map propertiesCache = new ConcurrentHashMap(); - /** Listeners will be invoked after properties have been reloaded */ - private final List afterReloadListeners = new ArrayList(); + /** + * Listeners will be invoked after changes to property file have been + * detected + */ + private final List afterReloadListeners = new ArrayList(); /** Resource Settings */ private final IResourceSettings resourceSettings; /** * Construct. + */ + public PropertiesFactory() + { + this.resourceSettings = Application.get().getResourceSettings(); + } + + /** + * Little helper * - * @param application + * @return The properties factory registered with the application */ - public PropertiesFactory(final Application application) + public static IPropertiesFactory get() { - this.resourceSettings = application.getResourceSettings(); + return Application.get().getResourceSettings().getPropertiesFactory(); } /** - * @see wicket.resource.IPropertiesFactory#addListener(wicket.resource.IPropertiesReloadListener) + * @see wicket.resource.IPropertiesFactory#addListener(wicket.resource.IPropertiesChangeListener) */ - public void addListener(final IPropertiesReloadListener listener) + public void addListener(final IPropertiesChangeListener listener) { // Make sure listeners are added only once if (afterReloadListeners.contains(listener) == false) @@ -89,31 +100,39 @@ } /** - * @see wicket.resource.IPropertiesFactory#get(java.lang.Class, - * java.lang.String, java.util.Locale) + * @see wicket.resource.IPropertiesFactory#load(java.lang.Class, + * java.lang.String) */ - public Properties get(final Class clazz, final String style, final Locale locale) + public Properties load(final Class clazz, final String path) { - final String key = createResourceKey(clazz, locale, style); - Properties props = propertiesCache.get(key); - if ((props == null) && (propertiesCache.containsKey(key) == false)) + // Check the cache + Properties properties = propertiesCache.get(path); + if (properties != null) { - final IResourceStream resource = resourceSettings.getResourceStreamFactory().newResourceStream( - clazz, clazz.getName().replace('.', '/'), style, locale, "properties,xml"); - - if (resource != null) + // Return null, if no resource stream was found + if (properties == Properties.EMPTY_PROPERTIES) { - props = loadPropertiesFileAndWatchForChanges(key, resource, clazz, style, locale); + properties = null; } + return properties; + } - // add the markup to the cache - synchronized (propertiesCache) + // If not in the cache than try to load the resource stream + IResourceStream stream = ResourceStreamFactory.get().newResourceStream(clazz, path); + if (stream != null) + { + // Load the properties from the stream + properties = loadPropertiesFileAndWatchForChanges(path, stream); + if (properties != null) { - propertiesCache.put(key, props); + this.propertiesCache.put(path, properties); + return properties; } } - return props; + // Add a placeholder to the cache. Null is not a valid value to add. + this.propertiesCache.put(path, Properties.EMPTY_PROPERTIES); + return null; } /** @@ -135,69 +154,16 @@ } /** - * Create a unique key to identify the properties file in the cache - * - * @param componentClass - * The class that resources are bring loaded for - * @param locale - * The locale to load reosurces for - * @param style - * The style to load resources for (see {@link wicket.Session}) - * @return The resource key - */ - public final String createResourceKey(final Class componentClass, final Locale locale, - final String style) - { - final AppendingStringBuffer buffer = new AppendingStringBuffer(80); - if (componentClass != null) - { - buffer.append(componentClass.getName()); - } - if (style != null) - { - buffer.append(Component.PATH_SEPARATOR); - buffer.append(style); - } - if (locale != null) - { - buffer.append(Component.PATH_SEPARATOR); - boolean l = locale.getLanguage().length() != 0; - boolean c = locale.getCountry().length() != 0; - boolean v = locale.getVariant().length() != 0; - buffer.append(locale.getLanguage()); - if (c || (l && v)) - { - // This may just append '_' - buffer.append('_').append(locale.getCountry()); - } - if (v && (l || c)) - { - buffer.append('_').append(locale.getVariant()); - } - } - - final String id = buffer.toString(); - return id; - } - - /** * Helper method to do the actual loading of resources if required. * * @param key * The key for the resource * @param resourceStream * The properties file stream to load and begin to watch - * @param componentClass - * The class that resources are bring loaded for - * @param style - * The style to load resources for (see {@link wicket.Session}) - * @param locale - * The locale to load reosurces for * @return The map of loaded resources */ private synchronized Properties loadPropertiesFile(final String key, - final IResourceStream resourceStream, final Class componentClass, final String style, - final Locale locale) + final IResourceStream resourceStream) { // Make sure someone else didn't load our resources while we were // waiting for the synchronized lock on the method @@ -222,8 +188,11 @@ { try { + // Get the InputStream BufferedInputStream in = new BufferedInputStream(resourceStream .getInputStream()); + + // Determine if resource is a XML File boolean loadAsXml = false; if (resourceStream instanceof IFixedLocationResourceStream) { @@ -238,6 +207,8 @@ } } } + + // Load the properties if (loadAsXml) { properties.loadFromXML(in); @@ -246,6 +217,8 @@ { properties.load(in); } + + // Copy the properties into the ValueMap strings = new ValueMap(); Enumeration enumeration = properties.propertyNames(); while (enumeration.hasMoreElements()) @@ -285,17 +258,10 @@ * The key for the resource * @param resourceStream * The properties file stream to load and begin to watch - * @param componentClass - * The class that resources are bring loaded for - * @param style - * The style to load resources for (see {@link wicket.Session}) - * @param locale - * The locale to load reosurces for * @return The map of loaded resources */ private final Properties loadPropertiesFileAndWatchForChanges(final String key, - final IResourceStream resourceStream, final Class componentClass, final String style, - final Locale locale) + final IResourceStream resourceStream) { // Watch file modifications final ModificationWatcher watcher = resourceSettings.getResourceWatcher(true); @@ -309,22 +275,20 @@ + "from the cache. Resource: " + resourceStream); // Clear the whole cache as associated localized files may - // be affected and may need reloading as well. We make it - // easy. Usually the watcher is activ in dev mode only - // anyway. + // be affected and may need reloading as well. clearCache(); // Inform all listeners for (Iterator iter = afterReloadListeners.iterator(); iter.hasNext();) { - IPropertiesReloadListener listener = (IPropertiesReloadListener)iter.next(); + IPropertiesChangeListener listener = (IPropertiesChangeListener)iter.next(); try { - listener.propertiesLoaded(key); + listener.propertiesChanged(key); } catch (Throwable ex) { - log.error("PropertiesReloadListener throw an exception: " + log.error("PropertiesReloadListener has thrown an exception: " + ex.getMessage()); } } @@ -333,6 +297,6 @@ } log.info("Loading properties files from " + resourceStream); - return loadPropertiesFile(key, resourceStream, componentClass, style, locale); + return loadPropertiesFile(key, resourceStream); } } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ClassStringResourceLoader.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ClassStringResourceLoader.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ClassStringResourceLoader.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ClassStringResourceLoader.java Thu Mar 1 00:09:19 2007 @@ -18,18 +18,22 @@ import java.util.Locale; -import wicket.Application; +import wicket.Component; +import wicket.Session; /** * This string resource loader attempts to find a single resource bundle that - * has the same name and location as the clazz. If this bundle is found then - * strings are obtained from here. This implementation is fully aware of both - * locale and style values when trying to obtain the appropriate bundle. + * has the same name and location as the clazz provided in the constructor. If + * the bundle is found than strings are obtained from here. This implementation + * is fully aware of both locale and style values when trying to obtain the + * appropriate bundle. + *

+ * An instance of this loader is registered with the Application by default. * * @author Chris Turner * @author Juergen Donnerstag */ -public class ClassStringResourceLoader extends AbstractStringResourceLoader +public class ClassStringResourceLoader extends ComponentStringResourceLoader { /** The application we are loading for. */ private final Class clazz; @@ -37,15 +41,11 @@ /** * Create and initialise the resource loader. * - * @param application - * Wickets application object * @param clazz * The class that this resource loader is associated with */ - public ClassStringResourceLoader(final Application application, final Class clazz) + public ClassStringResourceLoader(final Class clazz) { - super(application); - if (clazz == null) { throw new IllegalArgumentException("Parameter 'clazz' must not be null"); @@ -54,12 +54,28 @@ } /** - * @inheritDoc + * @see wicket.resource.loader.ComponentStringResourceLoader#loadStringResource(java.lang.Class, + * java.lang.String, java.util.Locale, java.lang.String) */ @Override public String loadStringResource(final Class clazz, final String key, final Locale locale, final String style) { return super.loadStringResource(this.clazz, key, locale, style); + } + + /** + * @see wicket.resource.loader.ComponentStringResourceLoader#loadStringResource(wicket.Component, + * java.lang.String) + */ + @Override + public String loadStringResource(Component component, String key) + { + if (component == null) + { + return loadStringResource(null, key, Session.get().getLocale(), Session.get() + .getStyle()); + } + return super.loadStringResource(component, key); } } Copied: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ComponentStringResourceLoader.java (from r500779, incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/AbstractStringResourceLoader.java) URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ComponentStringResourceLoader.java?view=diff&rev=513221&p1=incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/AbstractStringResourceLoader.java&r1=500779&p2=incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ComponentStringResourceLoader.java&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/AbstractStringResourceLoader.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/ComponentStringResourceLoader.java Thu Mar 1 00:09:19 2007 @@ -16,6 +16,8 @@ */ package wicket.resource.loader; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import org.slf4j.Logger; @@ -29,22 +31,16 @@ import wicket.markup.html.WebMarkupContainer; import wicket.markup.html.WebPage; import wicket.resource.Properties; -import wicket.util.value.ValueMap; +import wicket.resource.PropertiesFactory; +import wicket.util.resource.locator.ResourceNameIterator; +import wicket.util.string.Strings; /** - * This abstract string resource loader provides two helper functions to - * retrieve the message associated with a key, a locale and a style. The simple - * one uses the Class provided and its parent classes to find the - * associated message. The more complex one uses in addition the component - * provided and its parent containers. + * This is Wicket's default string resource loader. *

* The component based string resource loader attempts to find the resource from * a bundle that corresponds to the supplied component object or one of its - * parent containers. Generally the component will be an instance of - * Page, but it may also be an instance of any reusable - * component that is packaged along with its own resource files. If the - * component is not an instance of Page then it must be a - * component that has already been added to a page. + * parent containers. *

* The search order for resources is built around the containers that hold the * component (if it is not a page). Consider a Page that contains a Panel that @@ -75,15 +71,18 @@ * property in the following order: * *

- *       page1.properties => form1.input1.RequiredValidator
- *       page1.properties => RequiredValidator
- *       form1.properties => input1.RequiredValidator
- *       form1.properties => RequiredValidator
- *       input1.properties => RequiredValidator
- *       myApplication.properties => page1.form1.input1.RequiredValidator
- *       myApplication.properties => RequiredValidator
+ *        page1.properties => form1.input1.RequiredValidator
+ *        page1.properties => RequiredValidator
+ *        form1.properties => input1.RequiredValidator
+ *        form1.properties => RequiredValidator
+ *        input1.properties => RequiredValidator
+ *        myApplication.properties => page1.form1.input1.RequiredValidator
+ *        myApplication.properties => RequiredValidator
  * 
* + * Note that the latter two property files are only checked if the + * ClassStringResourceLoader has been registered with Application as well, which + * is the default. *

* In addition to the above search order, each component that is being searched * for a resource also includes the resources from any parent classes that it @@ -95,29 +94,26 @@ * resources and then developers implementing subclasses to either override or * extend these in their own resource bundle. *

+ * This implementation can be subclassed to implement modified behavior. The new + * implementation must be registered with the Application (ResourceSettings) + * though. + *

* You may enable log debug messages for this class to fully understand the * search order. * * @author Chris Turner * @author Juergen Donnerstag */ -public abstract class AbstractStringResourceLoader implements IStringResourceLoader +public class ComponentStringResourceLoader implements IStringResourceLoader { /** Log. */ - private static final Logger log = LoggerFactory.getLogger(AbstractStringResourceLoader.class); - - /** Wickets application object */ - protected final Application application; + private static final Logger log = LoggerFactory.getLogger(ComponentStringResourceLoader.class); /** * Create and initialise the resource loader. - * - * @param application - * Wickets application object */ - public AbstractStringResourceLoader(final Application application) + public ComponentStringResourceLoader() { - this.application = application; } /** @@ -145,33 +141,37 @@ return null; } - String value = null; while (true) { - // Get (or load) the properties associated with clazz, locale and - // style - final Properties props = getProperties(clazz, locale, style); - if (props != null) + // Create the base path + String path = clazz.getName().replace('.', '/'); + + // Iterator over all the combinations + ResourceNameIterator iter = new ResourceNameIterator(path, style, locale, + "properties,xml"); + while (iter.hasNext()) { - ValueMap strings = props.getAll(); + String newPath = iter.next(); - // Lookup value - if (log.isDebugEnabled()) + // Load the properties associated with the path + final Properties props = PropertiesFactory.get().load(clazz, newPath); + if (props != null) { - log.debug("Try to load resource from: " + props + "; key: " + key); - } - value = strings.getString(key); - if (value != null) - { - if (log.isDebugEnabled()) + // Lookup the value + String value = props.getString(key); + if (value != null) { - log.debug("Found resource from: " + props + "; key: " + key); - } + if (log.isDebugEnabled()) + { + log.debug("Found resource from: " + props + "; key: " + key); + } - break; + return value; + } } } + // Didn't find the key yet, continue searching if possible if (isStopResourceSearch(clazz)) { break; @@ -181,26 +181,8 @@ clazz = clazz.getSuperclass(); } - // Return the resource value (may be null if resource was not found) - return value; - } - - /** - * Get (or load) the properties associated with clazz, locale and style. - * - * @param clazz - * The class to find resources to be loaded - * @param locale - * The locale identifying the resource set to select the strings - * from - * @param style - * The (optional) style identifying the resource set to select - * the strings from (see {@link wicket.Session}) - * @return The string resource value or null if resource not found - */ - protected Properties getProperties(final Class clazz, final Locale locale, final String style) - { - return application.getResourceSettings().getPropertiesFactory().get(clazz, style, locale); + // not found + return null; } /** @@ -228,5 +210,89 @@ // Stop at all wicket base classes return clazz.equals(Page.class) || clazz.equals(MarkupContainer.class) || clazz.equals(Component.class); + } + + /** + * + * @see wicket.resource.loader.IStringResourceLoader#loadStringResource(wicket.Component, + * java.lang.String) + */ + public String loadStringResource(final Component component, final String key) + { + if (component == null) + { + return null; + } + + // The return value + String string = null; + Locale locale = component.getLocale(); + String style = component.getStyle(); + + // The key prefix is equal to the component path relativ to the + // current component on the top of the stack. + String prefix = Strings.replaceAll(component.getPageRelativePath(), ":", ".").toString(); + + // The reason why we need to create that stack is because we need to + // walk it downwards starting with Page down to the Component + List searchStack = getComponentStack(component); + + // Walk the component hierarchy down from page to the component + for (int i = searchStack.size() - 1; (i >= 0) && (string == null); i--) + { + Class clazz = (Class)searchStack.get(i); + + // First check if a property with the 'key' provided by the + // user is available. + string = loadStringResource(clazz, key, locale, style); + + // If not, prepend the component relativ path to the key + if ((string == null) && (prefix != null) && (prefix.length() > 0)) + { + string = loadStringResource(clazz, prefix + '.' + key, locale, style); + + // If still not found, adjust the component relativ path + // for the next component on the path from the page + // down. + if (string == null) + { + prefix = Strings.afterFirst(prefix, '.'); + } + } + } + + return string; + } + + /** + * Traverse the component hierachy up to the Page and add each component + * class to the list (stack) returned + * + * @param component + * The component to evaluate + * @return The stack of classes + */ + private List getComponentStack(final Component component) + { + // Build the search stack + final List searchStack = new ArrayList(); + searchStack.add(component.getClass()); + + if (!(component instanceof Page)) + { + // Add all the component on the way to the Page + MarkupContainer container = component.getParent(); + while (container != null) + { + searchStack.add(container.getClass()); + if (container instanceof Page) + { + break; + } + + container = container.getParent(); + } + } + return searchStack; } } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/IStringResourceLoader.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/IStringResourceLoader.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/IStringResourceLoader.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/resource/loader/IStringResourceLoader.java Thu Mar 1 00:09:19 2007 @@ -18,36 +18,36 @@ import java.util.Locale; +import wicket.Component; + /** * The string resource loader interface allows a strategy pattern to be applied * to the loading of resource strings for an application. The loader (or chain - * of loaders) that are used is configured via the - * ApplicationSettings class. + * of loaders) that are used is configured via the application settings. *

* Each particular implementation of this interface may define its own mechanism * for searching for resources. Please see the documents for each particular - * implementation to determine this behavior and to see how it can be - * configured. + * implementation to determine its behavior and to see how it can be configured. *

* It is important to note that if a resource is not found by a particular - * loader then the loader should return null rather than throw an + * loader than the loader should return null rather than throw an * exception. The reason for this is that loaders can be arranged in a chain and * it would be very inefficient for loaders earlier in the chain to throw * exceptions that must be caught and handled each time until the correct loader * in the chain is reached. * - * @author Chris Turner * @see wicket.settings.IResourceSettings + * + * @author Chris Turner + * @author Juergen Donnerstag */ public interface IStringResourceLoader { /** * Get the string resource for the given combination of component class, - * resource key, locale and style. The component is provided used to allow - * implementation of component specific resource loading (e.g. per page or - * per reusable component). It also allows the resource loader - * implementation to get access to the application settings and the root - * application object if necessary. The key should be a String containing a + * resource key, locale and style. The component class provided is used to + * allow implementation of component specific resource loading (e.g. per + * page or per reusable component). The key should be a String containing a * lookup key into a resource bundle. The locale should contain the locale * of the current operation so that the appopriate set of resources can be * selected. The style allows the set of resources to select to be varied by @@ -56,15 +56,34 @@ * @param clazz * The class to get the string resource for * @param key - * The key to obtain the string for + * The key should be a String containing a lookup key into a + * resource bundle * @param locale - * The locale identifying the resource set to select the strings - * from + * The locale should contain the locale of the current operation + * so that the appopriate set of resources can be selected * @param style - * The (optional) style identifying the resource set to select - * the strings from (see {@link wicket.Session}) + * The style identifying the resource set to select the strings + * from (see {@link wicket.Session}) * @return The string resource value or null if the resource could not be * loaded by this loader */ String loadStringResource(Class clazz, String key, Locale locale, String style); + + /** + * Get the string resource for the given combination of component and + * resource key. The component provided is used to allow implementation of + * component specific resource loading (e.g. per page or per reusable + * component). The key should be a String containing a lookup key into a + * resource bundle. The Locale and the style will be taken from the + * Component provided. + * + * @param component + * The component to get the string resource for + * @param key + * The key should be a String containing a lookup key into a + * resource bundle + * @return The string resource value or null if the resource could not be + * loaded by this loader + */ + String loadStringResource(Component component, String key); } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/settings/Settings.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/settings/Settings.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/settings/Settings.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/settings/Settings.java Thu Mar 1 00:09:19 2007 @@ -309,9 +309,8 @@ public Settings(final Application application) { this.application = application; - stringResourceLoaders.add(new ComponentStringResourceLoader(application)); - stringResourceLoaders.add(new ClassStringResourceLoader(application, this.application - .getClass())); + stringResourceLoaders.add(new ComponentStringResourceLoader()); + stringResourceLoaders.add(new ClassStringResourceLoader(this.application.getClass())); } /** @@ -644,7 +643,7 @@ { if (propertiesFactory == null) { - propertiesFactory = new PropertiesFactory(this.application); + propertiesFactory = new PropertiesFactory(); } return propertiesFactory; } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ExtensionResourceNameIterator.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ExtensionResourceNameIterator.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ExtensionResourceNameIterator.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ExtensionResourceNameIterator.java Thu Mar 1 00:09:19 2007 @@ -16,7 +16,7 @@ */ package wicket.util.resource.locator; -import java.util.Locale; +import java.util.Iterator; import wicket.util.string.Strings; @@ -44,7 +44,7 @@ * @author Juergen Donnerstag * @author Jonathan Locke */ -public class ExtensionResourceNameIterator implements IWicketResourceNameIterator +public class ExtensionResourceNameIterator implements Iterator { /** The base path */ private final String path; @@ -83,14 +83,6 @@ this.path = path; this.index = 0; - } - - /** - * @see wicket.util.resource.locator.IWicketResourceNameIterator#getLocale() - */ - public Locale getLocale() - { - return null; } /** Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/LocaleResourceNameIterator.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/LocaleResourceNameIterator.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/LocaleResourceNameIterator.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/LocaleResourceNameIterator.java Thu Mar 1 00:09:19 2007 @@ -16,6 +16,7 @@ */ package wicket.util.resource.locator; +import java.util.Iterator; import java.util.Locale; import wicket.util.string.Strings; @@ -44,7 +45,7 @@ * @author Juergen Donnerstag * @author Jonathan Locke */ -public class LocaleResourceNameIterator implements IWicketResourceNameIterator +public class LocaleResourceNameIterator implements Iterator { /** The base path */ private final String path; @@ -78,7 +79,7 @@ } /** - * @see wicket.util.resource.locator.IWicketResourceNameIterator#getLocale() + * @return Locale */ public Locale getLocale() { Added: incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceNameIterator.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceNameIterator.java?view=auto&rev=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceNameIterator.java (added) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceNameIterator.java Thu Mar 1 00:09:19 2007 @@ -0,0 +1,179 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 wicket.util.resource.locator; + +import java.util.Iterator; +import java.util.Locale; + +import wicket.WicketRuntimeException; + +/** + * Contains the logic to locate a resource based on a path, a style (see + * {@link wicket.Session}), a locale and a extension strings. The full filename + * will be built like: + * <path>_<style>_<locale>.<extension>. + *

+ * Resource matches will be attempted in the following order: + *

    + *
  1. 1. <path>_<style>_<locale>.<extension>
  2. + *
  3. 2. <path>_<locale>.<extension>
  4. + *
  5. 3. <path>_<style>.<extension>
  6. + *
  7. 4. <path>.<extension>
  8. + *
+ *

+ * Locales may contain a language, a country and a region or variant. + * Combinations of these components will be attempted in the following order: + *

    + *
  1. locale.toString() see javadoc for Locale for more details
  2. + *
  3. <language>_<country>
  4. + *
  5. <language>
  6. + *
+ *

+ * Extensions may be a comma separated list of extensions, e.g. "properties,xml" + * + * @author Juergen Donnerstag + */ +public class ResourceNameIterator implements Iterator +{ + // The locale to search for the resource file + private final Locale locale; + + // The extensions (comma separated) to search for the resource file + private final String extensions; + + // The various iterators used to locate the resource file + private Iterator styleIterator; + private LocaleResourceNameIterator localeIterator; + private Iterator extenstionsIterator; + + // The latest exact Locale used + private Locale currentLocale; + + /** + * Construct. + * + * @param path + * The path of the resource without extension + * @param style + * A theme or style (see {@link wicket.Session}) + * @param locale + * The Locale to apply + * @param extensions + * the filname's extensions (comma separated) + */ + public ResourceNameIterator(String path, final String style, final Locale locale, + final String extensions) + { + this.locale = locale; + this.extensions = extensions; + + this.styleIterator = new StyleAndVariationResourceNameIterator(path, style, null); + } + + /** + * Get the exact Locale which has been used for the latest resource path. + * + * @return current Locale + */ + public final Locale getLocale() + { + return this.currentLocale; + } + + /** + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() + { + // Most inner loop. Loop through all extensions provided + if (this.extenstionsIterator != null) + { + if (this.extenstionsIterator.hasNext() == true) + { + return true; + } + + // If there are no more extensions, than return to the next outer + // loop (locale), get the next value from that loop and start + // over again with the first extension in the list. + extenstionsIterator = null; + } + + // 2nd inner loop: Loop through all Locale combinations + if (this.localeIterator != null) + { + while (this.localeIterator.hasNext()) + { + // Get the next Locale from the iterator and start the next + // inner iterator over again. + String newPath = this.localeIterator.next(); + this.currentLocale = this.localeIterator.getLocale(); + this.extenstionsIterator = new ExtensionResourceNameIterator(newPath, + this.extensions); + if (this.extenstionsIterator.hasNext() == true) + { + return true; + } + } + this.localeIterator = null; + } + + // Most outer loop: Loop through all combinations of styles and + // variations + while (this.styleIterator.hasNext()) + { + String newPath = this.styleIterator.next(); + + this.localeIterator = new LocaleResourceNameIterator(newPath, this.locale); + while (this.localeIterator.hasNext()) + { + newPath = this.localeIterator.next(); + this.currentLocale = this.localeIterator.getLocale(); + this.extenstionsIterator = new ExtensionResourceNameIterator(newPath, + this.extensions); + if (this.extenstionsIterator.hasNext() == true) + { + return true; + } + } + } + + // No more combinations found. End of iteration. + return false; + } + + /** + * @see java.util.Iterator#next() + */ + public String next() + { + if (extenstionsIterator != null) + { + return extenstionsIterator.next(); + } + throw new WicketRuntimeException( + "Illegal call of next(). Iterator not properly initialized"); + } + + /** + * @see java.util.Iterator#remove() + */ + public void remove() + { + // ignore + } +} Propchange: incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceNameIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceStreamFactory.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceStreamFactory.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceStreamFactory.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/ResourceStreamFactory.java Thu Mar 1 00:09:19 2007 @@ -17,7 +17,6 @@ package wicket.util.resource.locator; import java.net.URL; -import java.util.Iterator; import java.util.Locale; import org.slf4j.Logger; @@ -111,31 +110,16 @@ { // Try the various combinations of style, locale and extension to find // the resource. - - // Most outer loop are the styles and variations - Iterator styleIter = new StyleAndVariationResourceNameIterator(path, style, null); - while (styleIter.hasNext()) + ResourceNameIterator iter = new ResourceNameIterator(path, style, locale, extension); + while (iter.hasNext()) { - String newPath = styleIter.next(); - - // next is the Locale - LocaleResourceNameIterator localeIter = new LocaleResourceNameIterator(newPath, locale); - while (localeIter.hasNext()) + String newPath = iter.next(); + + IResourceStream stream = newResourceStream(clazz, newPath); + if (stream != null) { - newPath = localeIter.next(); - - // and than the possible resource extensions - Iterator extIter = new ExtensionResourceNameIterator(newPath, extension); - while (extIter.hasNext()) - { - newPath = extIter.next(); - IResourceStream stream = newResourceStream(clazz, newPath); - if (stream != null) - { - stream.setLocale(localeIter.getLocale()); - return stream; - } - } + stream.setLocale(iter.getLocale()); + return stream; } } Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java (original) +++ incubator/wicket/trunk/wicket/src/main/java/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java Thu Mar 1 00:09:19 2007 @@ -16,7 +16,7 @@ */ package wicket.util.resource.locator; -import java.util.Locale; +import java.util.Iterator; /** * Contains the logic to build the various combinations of file path, style and @@ -42,7 +42,7 @@ * @author Juergen Donnerstag * @author Jonathan Locke */ -public class StyleAndVariationResourceNameIterator implements IWicketResourceNameIterator +public class StyleAndVariationResourceNameIterator implements Iterator { /** The base path */ private final String path; @@ -71,14 +71,6 @@ this.path = path; this.style = style; this.variation = variation; - } - - /** - * @see wicket.util.resource.locator.IWicketResourceNameIterator#getLocale() - */ - public Locale getLocale() - { - return null; } /** Modified: incubator/wicket/trunk/wicket/src/test/java/wicket/ApplicationSettingsTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/ApplicationSettingsTest.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/test/java/wicket/ApplicationSettingsTest.java (original) +++ incubator/wicket/trunk/wicket/src/test/java/wicket/ApplicationSettingsTest.java Thu Mar 1 00:09:19 2007 @@ -129,7 +129,7 @@ Settings settings = new Settings(dummy); settings.addStringResourceLoader(new BundleStringResourceLoader( "wicket.resource.DummyResources")); - settings.addStringResourceLoader(new ComponentStringResourceLoader(dummy)); + settings.addStringResourceLoader(new ComponentStringResourceLoader()); List loaders = settings.getStringResourceLoaders(); Assert.assertEquals("There should be 2 overridden loaders", 2, loaders.size()); Assert.assertTrue("First loader one should be the bundle one", Modified: incubator/wicket/trunk/wicket/src/test/java/wicket/LocalizerTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/LocalizerTest.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/test/java/wicket/LocalizerTest.java (original) +++ incubator/wicket/trunk/wicket/src/test/java/wicket/LocalizerTest.java Thu Mar 1 00:09:19 2007 @@ -70,7 +70,7 @@ public void testGetStringValidString() { Assert.assertEquals("Expected string should be returned", "This is a test", localizer - .getString("test.string", null, null, null, null, "DEFAULT")); + .getString("test.string", null, null, "DEFAULT")); } /** @@ -80,7 +80,7 @@ { settings.setUseDefaultOnMissingResource(true); Assert.assertEquals("Default string should be returned", "DEFAULT", localizer.getString( - "unknown.string", null, null, null, null, "DEFAULT")); + "unknown.string", null, null, "DEFAULT")); } /** @@ -93,7 +93,7 @@ Assert.assertEquals("Wrapped key should be returned on no default", "[Warning: String resource for 'unknown.string' not found]", localizer.getString( - "unknown.string", null, null, null, null, null)); + "unknown.string", null, null, null)); } /** @@ -105,7 +105,7 @@ settings.setThrowExceptionOnMissingResource(false); Assert.assertEquals("Wrapped key should be returned on not using default and no exception", "[Warning: String resource for 'unknown.string' not found]", localizer.getString( - "unknown.string", null, null, null, null, "DEFAULT")); + "unknown.string", null, null, "DEFAULT")); } /** @@ -117,7 +117,7 @@ settings.setThrowExceptionOnMissingResource(true); try { - localizer.getString("unknown.string", null, null, null, null, "DEFAULT"); + localizer.getString("unknown.string", null, null, "DEFAULT"); Assert.fail("MissingResourceException expected"); } catch (MissingResourceException e) @@ -135,7 +135,7 @@ vm.put("user", "John Doe"); Model model = new Model(vm); Assert.assertEquals("Property substitution should occur", "Welcome, John Doe", localizer - .getString("test.substitute", null, model, null, null, null)); + .getString("test.substitute", null, model, null)); } /** @@ -154,7 +154,7 @@ Session.get().setLocale(Locale.ENGLISH); MyMockPage page = new MyMockPage(); Application.get().getResourceSettings().addStringResourceLoader( - new ComponentStringResourceLoader(Application.get())); + new ComponentStringResourceLoader()); Localizer localizer = Application.get().getResourceSettings().getLocalizer(); String drop1 = localizer.getString("null", page.drop1); Modified: incubator/wicket/trunk/wicket/src/test/java/wicket/WicketMessageAttributeTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/WicketMessageAttributeTest.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/test/java/wicket/WicketMessageAttributeTest.java (original) +++ incubator/wicket/trunk/wicket/src/test/java/wicket/WicketMessageAttributeTest.java Thu Mar 1 00:09:19 2007 @@ -16,13 +16,11 @@ */ package wicket; -import java.util.Locale; - import wicket.markup.IMarkupResourceStreamProvider; import wicket.markup.html.WebPage; import wicket.markup.html.basic.Label; +import wicket.resource.IPropertiesChangeListener; import wicket.resource.IPropertiesFactory; -import wicket.resource.IPropertiesReloadListener; import wicket.resource.Properties; import wicket.util.resource.IResourceStream; import wicket.util.resource.StringResourceStream; @@ -59,11 +57,10 @@ { return ""; } - }; + new Label(page, "label", "i am label"); - tester.startPage(page); TagTester tagTester = tester.getTagByWicketId("label"); assertTrue("title-value".equals(tagTester.getAttribute("title"))); @@ -86,8 +83,8 @@ { return ""; } - }; + new Label(page, "label", "i am label"); tester.startPage(page); @@ -111,8 +108,8 @@ { return ""; } - }; + tester.startPage(page); String response = tester.getServletResponse().getDocument(); assertTrue(response.contains("title=\"title-value\"")); @@ -135,8 +132,8 @@ { return ""; } - }; + new Label(page, "label", "[[SUCCESS]]"); tester.startPage(page); @@ -153,7 +150,6 @@ */ private static abstract class TestPage extends WebPage implements IMarkupResourceStreamProvider { - protected abstract String getMarkupString(); public final IResourceStream getMarkupResourceStream(MarkupContainer container, @@ -161,7 +157,6 @@ { return new StringResourceStream("" + getMarkupString() + ""); } - } /** @@ -178,8 +173,7 @@ private static Properties PAGE = new Properties("key2", new ValueMap( "title-key=title-value,style-key=style-value")); - - public void addListener(IPropertiesReloadListener listener) + public void addListener(IPropertiesChangeListener listener) { // noop } @@ -189,18 +183,14 @@ // noop } - public Properties get(Class clazz, String style, Locale locale) + public Properties load(Class clazz, String path) { if (Page.class.isAssignableFrom(clazz)) { return PAGE; } - else - { - return EMPTY; - } + return EMPTY; } - } } Modified: incubator/wicket/trunk/wicket/src/test/java/wicket/properties/PropertiesTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/properties/PropertiesTest.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/test/java/wicket/properties/PropertiesTest.java (original) +++ incubator/wicket/trunk/wicket/src/test/java/wicket/properties/PropertiesTest.java Thu Mar 1 00:09:19 2007 @@ -20,7 +20,6 @@ import wicket.WicketTestCase; import wicket.protocol.http.WebRequestCycle; -import wicket.resource.loader.WicketBundleStringResourceLoader; import wicket.util.tester.WicketTester; /** @@ -51,11 +50,6 @@ */ public void test_1() { - // Add the string resource loader with the special Bundle like - // behavior - tester.getApplication().getResourceSettings().addStringResourceLoader( - new WicketBundleStringResourceLoader(tester.getApplication())); - tester.setupRequestAndResponse(); WebRequestCycle cycle = tester.createRequestCycle(); TestPage page = new TestPage(); @@ -74,11 +68,6 @@ */ public void test_2() { - // Add the string resource loader with the special Bundle like - // behavior - tester.getApplication().getResourceSettings().addStringResourceLoader( - new WicketBundleStringResourceLoader(tester.getApplication())); - tester.setupRequestAndResponse(); WebRequestCycle cycle = tester.createRequestCycle(); cycle.getSession().setLocale(Locale.GERMANY); Modified: incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ApplicationStringResourceLoaderTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ApplicationStringResourceLoaderTest.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ApplicationStringResourceLoaderTest.java (original) +++ incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ApplicationStringResourceLoaderTest.java Thu Mar 1 00:09:19 2007 @@ -52,7 +52,7 @@ @Override protected IStringResourceLoader createLoader() { - return new ClassStringResourceLoader(application, application.getClass()); + return new ClassStringResourceLoader(application.getClass()); } /** Modified: incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ComponentStringResourceLoaderTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ComponentStringResourceLoaderTest.java?view=diff&rev=513221&r1=513220&r2=513221 ============================================================================== --- incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ComponentStringResourceLoaderTest.java (original) +++ incubator/wicket/trunk/wicket/src/test/java/wicket/resource/ComponentStringResourceLoaderTest.java Thu Mar 1 00:09:19 2007 @@ -51,7 +51,7 @@ @Override protected IStringResourceLoader createLoader() { - return new ComponentStringResourceLoader(this.application); + return new ComponentStringResourceLoader(); } /** @@ -65,7 +65,7 @@ { private static final long serialVersionUID = 1L; }; - IStringResourceLoader loader = new ComponentStringResourceLoader(this.application); + IStringResourceLoader loader = new ComponentStringResourceLoader(); Assert.assertNull("Missing resource should return null", loader.loadStringResource(c .getClass(), "test.string.bad", Locale.getDefault(), null)); } @@ -87,7 +87,7 @@ MockComponentStringResourceLoaderTestPage p = new MockComponentStringResourceLoaderTestPage(); WebMarkupContainer panel = new WebMarkupContainer(p, "component"); DummyComponent c = new DummyComponent(panel, "hello", application); - IStringResourceLoader loader = new ComponentStringResourceLoader(this.application); + IStringResourceLoader loader = new ComponentStringResourceLoader(); Assert.assertEquals("Valid resourse string should be found", "Component string", loader .loadStringResource(c.getClass(), "component.string", Locale.getDefault(), null)); } @@ -98,7 +98,7 @@ public void testLoadDirectFromPage() { DummyPage p = new DummyPage(); - IStringResourceLoader loader = new ComponentStringResourceLoader(this.application); + IStringResourceLoader loader = new ComponentStringResourceLoader(); Assert .assertEquals("Valid resourse string should be found", "Another string", loader .loadStringResource(p.getClass(), "another.test.string", Locale @@ -111,7 +111,7 @@ public void testSearchClassHierarchyFromPage() { DummySubClassPage p = new DummySubClassPage(); - IStringResourceLoader loader = new ComponentStringResourceLoader(this.application); + IStringResourceLoader loader = new ComponentStringResourceLoader(); Assert.assertEquals("Valid resource string should be found", "SubClass Test String", loader.loadStringResource(p.getClass(), "subclass.test.string", Locale.getDefault(), null));