001package org.apache.commons.jcs.utils.props;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.InputStream;
023import java.util.Properties;
024
025/**
026 * I modified this class to work with .ccf files in particular. I also removed
027 * the resource bundle functionality.
028 * <p>
029 * A simple class for loading java.util.Properties backed by .ccf files deployed
030 * as classpath resources. See individual methods for details.
031 * <p>
032 * The original source is from:
033 * <p>
034 * @author (C) <a
035 *         href="http://www.javaworld.com/columns/jw-qna-index.shtml">Vlad
036 *         Roubtsov </a>, 2003
037 */
038public abstract class PropertyLoader
039{
040    /** throw an error if we can load the file */
041    private static final boolean THROW_ON_LOAD_FAILURE = true;
042
043    /** File suffix. */
044    private static final String SUFFIX = ".ccf";
045
046    /** property suffix */
047    private static final String SUFFIX_PROPERTIES = ".properties";
048
049    /**
050     * Looks up a resource named 'name' in the classpath. The resource must map
051     * to a file with .ccf extention. The name is assumed to be absolute and can
052     * use either "/" or "." for package segment separation with an optional
053     * leading "/" and optional ".ccf" suffix.
054     * <p>
055     * The suffix ".ccf" will be appended if it is not set. This can also handle
056     * .properties files
057     * <p>
058     * Thus, the following names refer to the same resource:
059     *
060     * <pre>
061     *
062     *       some.pkg.Resource
063     *       some.pkg.Resource.ccf
064     *       some/pkg/Resource
065     *       some/pkg/Resource.ccf
066     *       /some/pkg/Resource
067     *       /some/pkg/Resource.ccf
068     * </pre>
069     *
070     * @param name
071     *            classpath resource name [may not be null]
072     * @param loader
073     *            classloader through which to load the resource [null is
074     *            equivalent to the application loader]
075     * @return resource converted to java.util.properties [may be null if the
076     *         resource was not found and THROW_ON_LOAD_FAILURE is false]
077     * @throws IllegalArgumentException
078     *             if the resource was not found and THROW_ON_LOAD_FAILURE is
079     *             true
080     */
081    public static Properties loadProperties( String name, ClassLoader loader )
082    {
083        boolean isCCFSuffix = true;
084
085        if ( name == null )
086            throw new IllegalArgumentException( "null input: name" );
087
088        ClassLoader classLoader = ( loader == null ) ? ClassLoader.getSystemClassLoader() : loader;
089
090        String fileName = name.startsWith( "/" ) ? name.substring( 1 ) : name;
091
092        if ( fileName.endsWith( SUFFIX ) )
093        {
094            fileName = fileName.substring( 0, fileName.length() - SUFFIX.length() );
095        }
096
097        if ( fileName.endsWith( SUFFIX_PROPERTIES ) )
098        {
099            fileName = fileName.substring( 0, fileName.length() - SUFFIX_PROPERTIES.length() );
100            isCCFSuffix = false;
101        }
102
103        Properties result = null;
104
105        InputStream in = null;
106        try
107        {
108            fileName = fileName.replace( '.', '/' );
109
110            if ( !fileName.endsWith( SUFFIX ) && isCCFSuffix )
111            {
112                fileName = fileName.concat( SUFFIX );
113            }
114            else if ( !fileName.endsWith( SUFFIX_PROPERTIES ) && !isCCFSuffix )
115            {
116                fileName = fileName.concat( SUFFIX_PROPERTIES );
117            }
118
119            // returns null on lookup failures:
120            in = classLoader.getResourceAsStream( fileName );
121            if ( in != null )
122            {
123                result = new Properties();
124                result.load( in ); // can throw IOException
125            }
126        }
127        catch ( Exception e )
128        {
129            result = null;
130        }
131        finally
132        {
133            if ( in != null )
134                try
135                {
136                    in.close();
137                }
138                catch ( Throwable ignore )
139                {
140                    // swallow
141                }
142        }
143
144        if ( THROW_ON_LOAD_FAILURE && result == null )
145        {
146            throw new IllegalArgumentException( "could not load [" + fileName + "]" + " as " + "a classloader resource" );
147        }
148
149        return result;
150    }
151
152    /**
153     * A convenience overload of {@link #loadProperties(String, ClassLoader)}
154     * that uses the current thread's context classloader. A better strategy
155     * would be to use techniques shown in
156     * http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
157     * <p>
158     * @param name
159     * @return Properties
160     */
161    public static Properties loadProperties( final String name )
162    {
163        return loadProperties( name, Thread.currentThread().getContextClassLoader() );
164    }
165
166    /**
167     * Can't use this one.
168     */
169    private PropertyLoader()
170    {
171        super();
172    } // this class is not extentible
173
174}