001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.core.util.resource;
018
019import java.net.URL;
020
021import org.apache.wicket.util.file.IResourceFinder;
022import org.apache.wicket.util.lang.Args;
023import org.apache.wicket.util.resource.IResourceStream;
024import org.apache.wicket.util.string.Strings;
025
026/**
027 * An {@link IResourceFinder} that looks in a folder in the classpath.
028 * 
029 * @author Carl-Eric Menzel
030 */
031public class ClassPathResourceFinder implements IResourceFinder
032{
033        private final String prefix;
034
035        /**
036         * @param prefix
037         *            The path prefix. May be null or empty to look in the classpath root.
038         */
039        public ClassPathResourceFinder(String prefix)
040        {
041                if (Strings.isEmpty(prefix))
042                {
043                        this.prefix = "";
044                }
045                else if (prefix.endsWith("/"))
046                {
047                        this.prefix = prefix;
048                }
049                else
050                {
051                        this.prefix = prefix + "/";
052                }
053        }
054
055        @Override
056        public IResourceStream find(Class<?> clazz, String path)
057        {
058                Args.notEmpty(path, "path");
059                String fullPath = prefix + (path.startsWith("/") ? path.substring(1) : path);
060                IResourceStream resourceStream;
061                if (clazz != null)
062                {
063                        resourceStream = getResourceStreamWithClassLoader(clazz.getClassLoader(), fullPath);
064                        if (resourceStream != null)
065                        {
066                                return resourceStream;
067                        }
068                }
069
070                // use context classloader when no specific classloader is set
071                // (package resources for instance)
072                resourceStream = getResourceStreamWithClassLoader(Thread.currentThread()
073                        .getContextClassLoader(), fullPath);
074                if (resourceStream != null)
075                {
076                        return resourceStream;
077                }
078
079                // use Wicket classloader when no specific classloader is set
080                resourceStream = getResourceStreamWithClassLoader(getClass().getClassLoader(), fullPath);
081                if (resourceStream != null)
082                {
083                        return resourceStream;
084                }
085
086                return null;
087        }
088
089        private IResourceStream getResourceStreamWithClassLoader(ClassLoader classLoader, String path)
090        {
091                if (classLoader != null)
092                {
093                        URL url = classLoader.getResource(path);
094                        if (url != null)
095                        {
096                                return new UrlResourceStream(url);
097                        }
098                }
099                return null;
100        }
101
102        @Override
103        public String toString()
104        {
105                if (Strings.isEmpty(prefix))
106                {
107                        return "[classpath]";
108                }
109                else
110                {
111                        return "[classpath: " + prefix + "]";
112                }
113        }
114}