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 }