View Javadoc

1   package org.apache.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      private static final boolean THROW_ON_LOAD_FAILURE = true;
41  
42      private static final String SUFFIX = ".ccf";
43  
44      private static final String SUFFIX_PROPERTIES = ".properties";
45  
46      /***
47       * Looks up a resource named 'name' in the classpath. The resource must map
48       * to a file with .ccf extention. The name is assumed to be absolute and can
49       * use either "/" or "." for package segment separation with an optional
50       * leading "/" and optional ".ccf" suffix.
51       * <p>
52       * The suffix ".ccf" will be appended if it is not set. This can also handle
53       * .properties files
54       * <p>
55       * Thus, the following names refer to the same resource:
56       *
57       * <pre>
58       *
59       *       some.pkg.Resource
60       *       some.pkg.Resource.ccf
61       *       some/pkg/Resource
62       *       some/pkg/Resource.ccf
63       *       /some/pkg/Resource
64       *       /some/pkg/Resource.ccf
65       * </pre>
66       *
67       * @param name
68       *            classpath resource name [may not be null]
69       * @param loader
70       *            classloader through which to load the resource [null is
71       *            equivalent to the application loader]
72       * @return resource converted to java.util.properties [may be null if the
73       *         resource was not found and THROW_ON_LOAD_FAILURE is false]
74       * @throws IllegalArgumentException
75       *             if the resource was not found and THROW_ON_LOAD_FAILURE is
76       *             true
77       */
78      public static Properties loadProperties( String name, ClassLoader loader )
79      {
80          boolean isCCFSuffix = true;
81  
82          if ( name == null )
83              throw new IllegalArgumentException( "null input: name" );
84  
85          if ( name.startsWith( "/" ) )
86          {
87              name = name.substring( 1 );
88          }
89  
90          if ( name.endsWith( SUFFIX ) )
91          {
92              name = name.substring( 0, name.length() - SUFFIX.length() );
93          }
94  
95          if ( name.endsWith( SUFFIX_PROPERTIES ) )
96          {
97              name = name.substring( 0, name.length() - SUFFIX_PROPERTIES.length() );
98              isCCFSuffix = false;
99          }
100 
101         Properties result = null;
102 
103         InputStream in = null;
104         try
105         {
106             if ( loader == null )
107             {
108                 loader = ClassLoader.getSystemClassLoader();
109             }
110 
111             name = name.replace( '.', '/' );
112 
113             if ( !name.endsWith( SUFFIX ) && isCCFSuffix )
114             {
115                 name = name.concat( SUFFIX );
116             }
117             else if ( !name.endsWith( SUFFIX_PROPERTIES ) && !isCCFSuffix )
118             {
119                 name = name.concat( SUFFIX_PROPERTIES );
120             }
121 
122             // returns null on lookup failures:
123             in = loader.getResourceAsStream( name );
124             if ( in != null )
125             {
126                 result = new Properties();
127                 result.load( in ); // can throw IOException
128             }
129         }
130         catch ( Exception e )
131         {
132             result = null;
133         }
134         finally
135         {
136             if ( in != null )
137                 try
138                 {
139                     in.close();
140                 }
141                 catch ( Throwable ignore )
142                 {
143                     // swallow
144                 }
145         }
146 
147         if ( THROW_ON_LOAD_FAILURE && ( result == null ) )
148         {
149             throw new IllegalArgumentException( "could not load [" + name + "]" + " as " + "a classloader resource" );
150         }
151 
152         return result;
153     }
154 
155     /***
156      * A convenience overload of {@link #loadProperties(String, ClassLoader)}
157      * that uses the current thread's context classloader. A better strategy
158      * would be to use techniques shown in
159      * http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
160      * <p>
161      * @param name
162      * @return Properties
163      */
164     public static Properties loadProperties( final String name )
165     {
166         return loadProperties( name, Thread.currentThread().getContextClassLoader() );
167     }
168 
169     /***
170      * Can't use this one.
171      */
172     private PropertyLoader()
173     {
174         super();
175     } // this class is not extentible
176 
177 }