org.apache.wicket.core.util.resource.locator.ResourceStreamLocator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.core.util.resource.locator.ResourceStreamLocator.java

Source

/*
 * 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 org.apache.wicket.core.util.resource.locator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import org.apache.wicket.Application;
import org.apache.wicket.core.util.file.WebApplicationPath;
import org.apache.wicket.util.file.IResourceFinder;
import org.apache.wicket.util.file.Path;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.ResourceUtils;
import org.apache.wicket.util.resource.ResourceUtils.PathLocale;
import org.apache.wicket.util.string.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Locates Wicket resources.
 *
 * <p>
 * Contains the logic to locate a resource based on a path, a variation, a style (see
 * {@link org.apache.wicket.Session}), a locale and an extension string. The full filename will be
 * built like: &lt;path&gt;_&lt;variation&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;.
 * <p>
 * Resource matches will be attempted in the following order:
 * <ol>
 * <li>&lt;path&gt;_&lt;variation&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
 * <li>&lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
 * <li>&lt;path&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
 * <li>&lt;path&gt;_&lt;style&gt;.&lt;extension&gt;</li>
 * <li>&lt;path&gt;.&lt;extension&gt;</li>
 * </ol>
 * <p>
 * Locales may contain a language, a country and a region or variant. Combinations of these
 * components will be attempted in the following order:
 * <ol>
 * <li>locale.toString() see javadoc for Locale for more details</li>
 * <li>&lt;language&gt;_&lt;country&gt;</li>
 * <li>&lt;language&gt;</li>
 * </ol>
 * <p>
 * Resources will be actually loaded by the {@link IResourceFinder}s defined in the resource
 * settings. By default there are finders that look in the classpath and in the classpath in
 * META-INF/resources. You can add more by adding {@link WebApplicationPath}s or {@link Path}s to
 * {@link org.apache.wicket.settings.ResourceSettings#getResourceFinders()}.
 * 
 * @author Juergen Donnerstag
 * @author Jonathan Locke
 */
public class ResourceStreamLocator implements IResourceStreamLocator {
    /** Logging */
    private static final Logger log = LoggerFactory.getLogger(ResourceStreamLocator.class);

    private static final Iterable<String> NO_EXTENSIONS = new ArrayList<>(0);

    /** If null, the application registered finder will be used */
    private List<IResourceFinder> finders;

    /**
     * Constructor
     */
    public ResourceStreamLocator() {
        this((List<IResourceFinder>) null);
    }

    /**
     * Constructor
     * 
     * @param finders
     *            resource finders. These will be tried in the given order.
     */
    public ResourceStreamLocator(final IResourceFinder... finders) {
        this(Arrays.asList(finders));
    }

    /**
     * Constructor
     * 
     * @param finders
     *            resource finders. These will be tried in the given order.
     */
    public ResourceStreamLocator(final List<IResourceFinder> finders) {
        this.finders = finders;
    }

    /**
     * 
     * @see org.apache.wicket.core.util.resource.locator.IResourceStreamLocator#locate(java.lang.Class,
     *      java.lang.String)
     */
    @Override
    public IResourceStream locate(final Class<?> clazz, final String path) {
        // First try with the resource finder registered with the application
        // (allows for markup reloading)
        if (finders == null) {
            finders = Application.get().getResourceSettings().getResourceFinders();
        }

        IResourceStream result;
        for (IResourceFinder finder : finders) {
            log.debug("Attempting to locate resource '{}' using finder'{}'", path, finder);
            result = finder.find(clazz, path);
            if (result != null) {
                return result;
            }
        }
        return null;
    }

    /**
     * 
     * @see org.apache.wicket.core.util.resource.locator.IResourceStreamLocator#locate(java.lang.Class,
     *      java.lang.String, java.lang.String, java.lang.String, java.util.Locale,
     *      java.lang.String, boolean)
     */
    @Override
    public IResourceStream locate(final Class<?> clazz, String path, final String style, final String variation,
            Locale locale, final String extension, final boolean strict) {
        // If path contains a locale, then it'll replace the locale provided to this method
        PathLocale data = ResourceUtils.getLocaleFromFilename(path);
        if ((data != null) && (data.locale != null)) {
            path = data.path;
            locale = data.locale;
        }

        // Try the various combinations of style, locale and extension to find the resource.
        IResourceNameIterator iter = newResourceNameIterator(path, locale, style, variation, extension, strict);
        while (iter.hasNext()) {
            String newPath = iter.next();

            IResourceStream stream = locate(clazz, newPath);
            if (stream != null) {
                stream.setLocale(iter.getLocale());
                stream.setStyle(iter.getStyle());
                stream.setVariation(iter.getVariation());
                return stream;
            }
        }

        return null;
    }

    /**
     * 
     * @see org.apache.wicket.core.util.resource.locator.IResourceStreamLocator#newResourceNameIterator(java.lang.String,
     *      java.util.Locale, java.lang.String, java.lang.String, java.lang.String, boolean)
     */
    @Override
    public IResourceNameIterator newResourceNameIterator(final String path, final Locale locale, final String style,
            final String variation, final String extension, final boolean strict) {
        final Iterable<String> extensions;

        final String realPath;

        if ((extension == null) && (path != null) && (path.indexOf('.') != -1)) {
            // extract the path and extension
            realPath = Strings.beforeLast(path, '.');
            String realExtension = Strings.afterLast(path, '.');
            if (realExtension.indexOf(',') > -1) {
                // multiple extensions are not allowed in the path parameter
                // it could be an attack, so ignore it and pretend there are no resources
                return new EmptyResourceNameIterator();
            }

            // add a minimized file to the resource lookup if necessary
            if (Application.exists() && Application.get().getResourceSettings().getUseMinifiedResources()) {
                extensions = Arrays.asList("min." + realExtension, realExtension);
            } else {
                extensions = Collections.singleton(realExtension);
            }
        } else {
            realPath = path;
            if (extension == null) {
                extensions = NO_EXTENSIONS;
            } else {
                String[] commaSeparated = Strings.split(extension, ',');
                List<String> nonMinifiedExtensions = Arrays.asList(commaSeparated);

                // add a minimized file to the resource lookup if necessary
                if (Application.exists() && Application.get().getResourceSettings().getUseMinifiedResources()) {
                    ArrayList<String> minifiedExtensions = new ArrayList<>();
                    for (String nonMinifiedExtension : nonMinifiedExtensions) {
                        minifiedExtensions.add("min." + nonMinifiedExtension);
                        minifiedExtensions.add(nonMinifiedExtension);
                    }
                    extensions = minifiedExtensions;
                } else {
                    extensions = nonMinifiedExtensions;
                }
            }
        }

        return newResourceNameIterator(realPath, locale, style, variation, extensions, strict);
    }

    // TODO Wicket 7 Add this method to IResourceStreamLocator interface.
    public IResourceNameIterator newResourceNameIterator(final String path, final Locale locale, final String style,
            final String variation, final Iterable<String> extensions, final boolean strict) {
        return new ResourceNameIterator(path, style, variation, locale, extensions, strict);
    }
}