View Javadoc
1   package org.apache.commons.jcs.utils.props;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.InputStream;
23  import java.util.Properties;
24  
25  /**
26   * I modified this class to work with .ccf files in particular. I also removed
27   * the resource bundle functionality.
28   * <p>
29   * A simple class for loading java.util.Properties backed by .ccf files deployed
30   * as classpath resources. See individual methods for details.
31   * <p>
32   * The original source is from:
33   * <p>
34   * @author (C) <a
35   *         href="http://www.javaworld.com/columns/jw-qna-index.shtml">Vlad
36   *         Roubtsov </a>, 2003
37   */
38  public abstract class PropertyLoader
39  {
40      /** throw an error if we can load the file */
41      private static final boolean THROW_ON_LOAD_FAILURE = true;
42  
43      /** File suffix. */
44      private static final String SUFFIX = ".ccf";
45  
46      /** property suffix */
47      private static final String SUFFIX_PROPERTIES = ".properties";
48  
49      /**
50       * Looks up a resource named 'name' in the classpath. The resource must map
51       * to a file with .ccf extention. The name is assumed to be absolute and can
52       * use either "/" or "." for package segment separation with an optional
53       * leading "/" and optional ".ccf" suffix.
54       * <p>
55       * The suffix ".ccf" will be appended if it is not set. This can also handle
56       * .properties files
57       * <p>
58       * Thus, the following names refer to the same resource:
59       *
60       * <pre>
61       *
62       *       some.pkg.Resource
63       *       some.pkg.Resource.ccf
64       *       some/pkg/Resource
65       *       some/pkg/Resource.ccf
66       *       /some/pkg/Resource
67       *       /some/pkg/Resource.ccf
68       * </pre>
69       *
70       * @param name
71       *            classpath resource name [may not be null]
72       * @param loader
73       *            classloader through which to load the resource [null is
74       *            equivalent to the application loader]
75       * @return resource converted to java.util.properties [may be null if the
76       *         resource was not found and THROW_ON_LOAD_FAILURE is false]
77       * @throws IllegalArgumentException
78       *             if the resource was not found and THROW_ON_LOAD_FAILURE is
79       *             true
80       */
81      public static Properties loadProperties( String name, ClassLoader loader )
82      {
83          boolean isCCFSuffix = true;
84  
85          if ( name == null )
86              throw new IllegalArgumentException( "null input: name" );
87  
88          ClassLoader classLoader = ( loader == null ) ? ClassLoader.getSystemClassLoader() : loader;
89  
90          String fileName = name.startsWith( "/" ) ? name.substring( 1 ) : name;
91  
92          if ( fileName.endsWith( SUFFIX ) )
93          {
94              fileName = fileName.substring( 0, fileName.length() - SUFFIX.length() );
95          }
96  
97          if ( fileName.endsWith( SUFFIX_PROPERTIES ) )
98          {
99              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 }