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      /** 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          if ( name.startsWith( "/" ) )
89          {
90              name = name.substring( 1 );
91          }
92  
93          if ( name.endsWith( SUFFIX ) )
94          {
95              name = name.substring( 0, name.length() - SUFFIX.length() );
96          }
97  
98          if ( name.endsWith( SUFFIX_PROPERTIES ) )
99          {
100             name = name.substring( 0, name.length() - SUFFIX_PROPERTIES.length() );
101             isCCFSuffix = false;
102         }
103 
104         Properties result = null;
105 
106         InputStream in = null;
107         try
108         {
109             if ( loader == null )
110             {
111                 loader = ClassLoader.getSystemClassLoader();
112             }
113 
114             name = name.replace( '.', '/' );
115 
116             if ( !name.endsWith( SUFFIX ) && isCCFSuffix )
117             {
118                 name = name.concat( SUFFIX );
119             }
120             else if ( !name.endsWith( SUFFIX_PROPERTIES ) && !isCCFSuffix )
121             {
122                 name = name.concat( SUFFIX_PROPERTIES );
123             }
124 
125             // returns null on lookup failures:
126             in = loader.getResourceAsStream( name );
127             if ( in != null )
128             {
129                 result = new Properties();
130                 result.load( in ); // can throw IOException
131             }
132         }
133         catch ( Exception e )
134         {
135             result = null;
136         }
137         finally
138         {
139             if ( in != null )
140                 try
141                 {
142                     in.close();
143                 }
144                 catch ( Throwable ignore )
145                 {
146                     // swallow
147                 }
148         }
149 
150         if ( THROW_ON_LOAD_FAILURE && ( result == null ) )
151         {
152             throw new IllegalArgumentException( "could not load [" + name + "]" + " as " + "a classloader resource" );
153         }
154 
155         return result;
156     }
157 
158     /**
159      * A convenience overload of {@link #loadProperties(String, ClassLoader)}
160      * that uses the current thread's context classloader. A better strategy
161      * would be to use techniques shown in
162      * http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
163      * <p>
164      * @param name
165      * @return Properties
166      */
167     public static Properties loadProperties( final String name )
168     {
169         return loadProperties( name, Thread.currentThread().getContextClassLoader() );
170     }
171 
172     /**
173      * Can't use this one.
174      */
175     private PropertyLoader()
176     {
177         super();
178     } // this class is not extentible
179 
180 }