org.geoserver.web.GeoServerStringResourceLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.web.GeoServerStringResourceLoader.java

Source

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
 * (c) 2001 - 2013 OpenPlans
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.web;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Logger;

import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.resource.IPropertiesFactory;
import org.apache.wicket.resource.Properties;
import org.apache.wicket.resource.loader.ComponentStringResourceLoader;
import org.apache.wicket.resource.loader.IStringResourceLoader;
import org.apache.wicket.util.resource.locator.ResourceNameIterator;
import org.geotools.util.logging.Logging;

/**
 * A custom localizer, heavily inspired by {@link ComponentStringResourceLoader},
 * which considers two peculiarities of the GeoServer i18n subsystem:
 * <ul>
 *   <li>All resources are loaded in GeoServer*.properties files located in the root of each jar</li>
 *   <li>Component resources are qualified by component or by page name</li>
 * @author Andrea Aime - OpenGeo
 * @author Justin Deoliveria - OpenGeo 
 */
public class GeoServerStringResourceLoader implements IStringResourceLoader {
    /** Log. */
    private static final Logger log = Logging.getLogger(GeoServerStringResourceLoader.class);

    /**
     * Create and initialize the resource loader.
     */
    public GeoServerStringResourceLoader() {
    }

    /**
     * Get the string resource for the given combination of class, key, locale and style. The
     * information is obtained from a resource bundle associated with the provided Class (or one of
     * its super classes).
     * 
     * @param clazz
     *            The Class to find resources to be loaded (might be null if we want a context-less search)
     * @param key
     *            The key to obtain the string for
     * @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 org.apache.wicket.Session})
     * @return The string resource value or null if resource not found
     */
    public String loadStringResource(Class clazz, final String key, final Locale locale, final String style) {
        // Load the properties associated with the path
        IPropertiesFactory propertiesFactory = Application.get().getResourceSettings().getPropertiesFactory();

        // All GeoServer releated resources are loaded into a GeoServerApplication*.properties file
        String path = "/GeoServerApplication";
        while (true) {
            // Iterator over all the combinations
            ResourceNameIterator iter = new ResourceNameIterator(path, style, locale, ",properties,xml");
            while (iter.hasNext()) {
                String newPath = (String) iter.next();

                final Properties props = propertiesFactory.load(clazz, newPath);
                if (props != null) {
                    // Lookup the qualified key
                    String qualifiedKey = clazz != null ? clazz.getSimpleName() + "." + key : key;
                    String value = props.getString(qualifiedKey);
                    if (value != null)
                        return value;
                }
            }

            // Didn't find the key yet, continue searching if possible
            if (isStopResourceSearch(clazz)) {
                break;
            }

            // Move to the next superclass
            clazz = clazz.getSuperclass();

            if (clazz == null) {
                // nothing more to search, done
                break;
            }
        }

        // not found
        return null;
    }

    /**
     * 
     * @see org.apache.wicket.resource.loader.IStringResourceLoader#loadStringResource(org.apache.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 reason why we need to create that stack is because we need to
        // walk it downwards starting with Page down to the Component
        List containmentStack = getComponentStack(component);

        // Walk the component hierarchy down from page to the component
        for (int i = containmentStack.size() - 1; (i >= 0) && (string == null); i--) {
            Class clazz = (Class) containmentStack.get(i);

            // First, try the fully qualified resource name relative to the
            // component on the path from page down.
            string = loadStringResource(clazz, key, locale, style);
        }

        // If not found, than check if a property with the 'key' provided by
        // the user can be found.
        if (string == null) {
            string = loadStringResource(null, key, locale, style);
        }

        return string;
    }

    /**
     * Traverse the component hierarchy 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;
    }

    /**
     * Check the supplied class to see if it is one that we shouldn't bother further searches up the
     * class hierarchy for properties.
     * 
     * @param clazz
     *            The class to check
     * @return Whether to stop the search
     */
    protected boolean isStopResourceSearch(final Class clazz) {
        if (clazz == null || clazz.equals(Object.class) || clazz.equals(Application.class)) {
            return true;
        }

        // Stop at all html markup base classes
        if (clazz.equals(WebPage.class) || clazz.equals(WebMarkupContainer.class)
                || clazz.equals(WebComponent.class)) {
            return true;
        }

        // Stop at all wicket base classes
        return clazz.equals(Page.class) || clazz.equals(MarkupContainer.class) || clazz.equals(Component.class);
    }
}