org.geoserver.web.GeoServerResourceStreamLocator.java Source code

Java tutorial

Introduction

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

Source

/* (c) 2014 - 2016 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.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import org.apache.commons.io.FilenameUtils;
import org.apache.wicket.core.util.resource.locator.IResourceNameIterator;
import org.apache.wicket.core.util.resource.locator.ResourceNameIterator;
import org.apache.wicket.core.util.resource.locator.ResourceStreamLocator;
import org.apache.wicket.util.resource.AbstractResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.geotools.util.logging.Logging;

/**
 * A custom resource stream locator which supports loading i18n properties files on a single file
 * per module basis. It also works around https://issues.apache.org/jira/browse/WICKET-2534.
 * <p>
 * This class also tries to optimize resource lookups (which are slower with the wicket 7 upgrade) by skipping the 
 * mechanism that looks up static files (markup, css, etc...) with the locale specific prefixes.
 * </p>
 */
public class GeoServerResourceStreamLocator extends ResourceStreamLocator {
    public static Logger LOGGER = Logging.getLogger("org.geoserver.web");

    static Pattern GS_PROPERTIES = Pattern.compile("GeoServerApplication.*.properties");

    static Pattern GS_LOCAL_I18N = Pattern.compile("org/geoserver/.*(\\.properties|\\.xml)]");

    @SuppressWarnings({ "serial" })
    @Override
    public IResourceStream locate(Class<?> clazz, String path) {
        int i = path.lastIndexOf("/");
        if (i != -1) {
            String p = path.substring(i + 1);
            if (GS_PROPERTIES.matcher(p).matches()) {
                try {
                    // process the classpath for property files
                    Enumeration<URL> urls = getClass().getClassLoader().getResources(p);

                    // build up a single properties file
                    Properties properties = new Properties();

                    while (urls.hasMoreElements()) {
                        URL url = urls.nextElement();

                        InputStream in = url.openStream();
                        properties.load(in);
                        in.close();
                    }

                    // transform the properties to a stream
                    final ByteArrayOutputStream out = new ByteArrayOutputStream();
                    properties.store(out, "");

                    return new AbstractResourceStream() {
                        public InputStream getInputStream() throws ResourceStreamNotFoundException {
                            return new ByteArrayInputStream(out.toByteArray());
                        }

                        public void close() throws IOException {
                            out.close();
                        }
                    };
                } catch (IOException e) {
                    LOGGER.log(Level.WARNING, "", e);
                }
            } else if (GS_LOCAL_I18N.matcher(path).matches()) {
                return null;
            } else if (path.matches("org/geoserver/.*" + clazz.getName() + ".*_.*.html")) {
                return null;
            }
        }

        return super.locate(clazz, path);
    }

    static Map<String, List<String>> PREFIXES = new HashMap<>();
    static {
        PREFIXES.put("html", Arrays.asList("html"));
        PREFIXES.put("css", Arrays.asList("css"));
        PREFIXES.put("png", Arrays.asList("png"));
        PREFIXES.put("js", Arrays.asList("js"));
        PREFIXES.put("ico", Arrays.asList("ico"));
    }

    @Override
    public IResourceNameIterator newResourceNameIterator(String path, Locale locale, String style, String variation,
            String extension, boolean strict) {

        Iterable<String> extensions = null;

        // if the resource under the geoserver or wicket namespace?
        if (path.startsWith("org/geoserver") || path.startsWith("org/apache/wicket")) {
            String ext = extension;
            if (ext == null) {
                // no extension passed in, strip it from the path
                ext = FilenameUtils.getExtension(path);
            }

            if (ext != null) {
                // we have an extension, look it up in the whitelist
                extensions = PREFIXES.get(ext);
            }
        }

        if (extensions != null) {
            // ensure the path doesn't contain the extension, sometimes this method is called with extension == null, 
            // in which case the extension is usually in the path
            path = FilenameUtils.getPathNoEndSeparator(path) + "/" + FilenameUtils.getBaseName(path);
            return new ResourceNameIterator(path, style, variation, null, extensions, false);
        }

        // couldn't optimize, just pass through to parent
        return super.newResourceNameIterator(path, locale, style, variation, extension, strict);
    }
}