Source code: javatools/util/Props.java
1 /*
2 Javatools (modified version) - Some useful general classes.
3 Copyright (C) 2002-2003 Chris Bitmead (original) Antonio Petrelli (modified)
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Contact me at: brenmcguire@users.sourceforge.net
20 */
21 package javatools.util;
22 import java.util.*;
23 import java.io.*;
24 import java.net.URI;
25
26 /**
27 * An extended version of Properties class. It allows reading Properties files
28 * from the classpath or resource file. It uses ClassLoader.getResourceAsStream
29 * to find a properties file, so that means it either has to be on the
30 * classpath or bundled into the jar. <P>
31 *
32 * It is intended that you only pass a single string to find the properties
33 * like "foo". That will cause Props to search for a file called
34 * foo.properties. The directory it searches in will be by default the "res/"
35 * directory. That means that it will search your classpath or jar file for a
36 * file res/foo.properties. If you run your software in different environments
37 * you can pass a system property to the java virtual machine called
38 * "environment". In that case the searching will descend another directory
39 * level. e.g. if you pass -Denvironment=development, then it will first look
40 * for a file res/development/foo.properties. If you are using servlets your
41 * servlet engine should have a means to pass in system variables. <P>
42 *
43 * This makes it easy to integrate properties into your code. All you do is use
44 * Props to find a certain class of property, like "foo" and it will take care
45 * of where to physically find the file. And you can set up different
46 * properties for different environments. <P>
47 *
48 * TODO: make it combine the environment and non-environment specific
49 * properties into the one set.
50 *
51 * Last modification: 16/02/2003 12.49
52 *
53 * @author Chris Bitmead (original) Antonio Petrelli (modified)
54 * @created November 23, 2001
55 * @version 0.2.0
56 * @commentedby Antonio Petrelli
57 */
58
59 public class Props extends Properties implements Resetable {
60 // Hashtable because it's synchronized
61 /** Contains a map for the keys.
62 */
63 static Hashtable map = new Hashtable();
64 // static String localConfigDir = getLocalConfigDir();
65 /** Contains a file representing where is the local configuration directory.
66 */
67 static File localConfigDirFile;
68 /** The local configuration file for this Props.
69 */
70 static String defaultLocalConfigDir = null;
71
72 File localConfigFile;
73 /** The name for this Props.
74 */
75 String name;
76 /** The complete name for this Props.
77 */
78 String fullName;
79 /** Contains a flag indicating if this Props is valid.
80 */
81 boolean valid = true;
82 boolean openAsResource;
83 String propsURL;
84
85 private Props(String name, boolean openAsResource) throws IOException {
86 this.openAsResource = openAsResource;
87 this.name = name;
88 localConfigFile = new File(localConfigDirFile, name + ".properties");
89 load(openAsResource);
90 }
91
92 private Props(String name, boolean load, boolean openAsResource) throws IOException {
93 this.openAsResource = openAsResource;
94 this.name = name;
95 localConfigFile = new File(localConfigDirFile, name + ".properties");
96 }
97
98 /** Returns a brand new Props object referencing properties of the given name.
99 * @param name The name of properties file to load.
100 * @throws IOException If they cannot be loaded.
101 * @return The Props object.
102 */
103 public static Props singleton(String name, boolean openAsResource) throws IOException {
104 if (localConfigDirFile == null)
105 localConfigDirFile = new File(getLocalConfigDir());
106 Props rtn = (Props) map.get(name);
107 if (rtn == null) {
108 synchronized (Props.class) {
109 if (rtn == null) {
110 rtn = new Props(name, openAsResource);
111 map.put(name, rtn);
112 }
113 }
114 }
115 return rtn;
116 }
117
118 public static Props singleton(String name) throws IOException {
119 return singleton(name, true);
120 }
121
122 public static void setDefaultLocalConfigDir(String defaultLocalConfigDir) {
123 Props.defaultLocalConfigDir = defaultLocalConfigDir;
124 }
125
126 /** Returns the local configuration directory.
127 * @return The local configuration directory path.
128 */
129 public static String getLocalConfigDir(){
130 File tempFile;
131 String tempDir;
132 ClassLoader cl;
133
134 tempDir = null;
135 try {
136 Props props = new Props("props", false, true);
137 props.loadResources(true);
138 tempDir = props.getProperty("localConfigDir");
139 tempFile = new File(tempDir);
140 if (!tempFile.isAbsolute()) {
141 try {
142 tempFile = new File(new URI(props.propsURL));
143 tempDir = tempFile.getParentFile().getParentFile().getAbsolutePath() + "/" + tempDir;
144 }
145 catch (java.net.URISyntaxException e) {
146 if (defaultLocalConfigDir != null) {
147 tempFile = new File(defaultLocalConfigDir);
148 if (!tempFile.exists())
149 tempFile.mkdir();
150 tempDir = tempFile.getAbsolutePath();
151 }
152 else
153 tempDir = null;
154 }
155 catch (IllegalArgumentException e) {
156 if (defaultLocalConfigDir != null) {
157 tempFile = new File(defaultLocalConfigDir);
158 if (!tempFile.exists())
159 tempFile.mkdir();
160 tempDir = tempFile.getAbsolutePath();
161 }
162 else
163 tempDir = null;
164 }
165 }
166 } catch (IOException e) {
167 System.out.println("No local Config Dir specified");
168 }
169 if (tempDir != null)
170 localConfigDirFile = new File(tempDir);
171 return tempDir;
172 }
173
174 public static String getLocalDir() {
175 File tempFile;
176 String tempDir;
177 ClassLoader cl;
178
179 tempDir = null;
180 try {
181 Props props = new Props("props", false, true);
182 props.loadResources(true);
183 try {
184 tempFile = new File(new URI(props.propsURL));
185 tempDir = tempFile.getParentFile().getParentFile().getAbsolutePath();
186 }
187 catch (java.net.URISyntaxException e) {
188 if (defaultLocalConfigDir != null) {
189 tempFile = new File(defaultLocalConfigDir);
190 if (!tempFile.exists())
191 tempFile.mkdir();
192 tempDir = tempFile.getAbsolutePath();
193 }
194 else
195 tempDir = null;
196 }
197 catch (IllegalArgumentException e) {
198 if (defaultLocalConfigDir != null) {
199 tempFile = new File(defaultLocalConfigDir);
200 if (!tempFile.exists())
201 tempFile.mkdir();
202 tempDir = tempFile.getAbsolutePath();
203 }
204 else
205 tempDir = null;
206 }
207 } catch (IOException e) {
208 System.out.println("No props file found!");
209 }
210 return tempDir;
211 }
212
213 /** Returns the full name for this Props.
214 * @return The full name.
215 */
216 public String getFullName() {
217 return fullName;
218 }
219
220 /** Resets all this Props.
221 * @throws ResetException If something goes wrong.
222 */
223 public void reset() throws ResetException {
224 try {
225 load();
226 } catch (IOException e) {
227 throw new ResetException(e);
228 }
229 }
230
231 public void load() throws IOException {
232 load(true);
233 }
234
235 /** Loads properties.
236 * @throws IOException If properties cannot be loaded.
237 */
238 public void load(boolean openAsResource) throws IOException {
239 try {
240 loadResources(openAsResource);
241 }
242 catch (IOException e) {
243 // System.out.println("Properties file not found, working without a file");
244 }
245 loadLocalConfig();
246 }
247
248 /** Stores properties in a file.
249 * @throws IOException If properties cannot be stored.
250 */
251 public void store() throws IOException {
252 Props resProps = new Props(name, false, openAsResource);
253 try {
254 resProps.loadResources(openAsResource);
255 }
256 catch (IOException e) {
257 }
258 Properties localConfigProps = new Properties();
259 Iterator it = entrySet().iterator();
260 while (it.hasNext()) {
261 Map.Entry entry = (Map.Entry) it.next();
262 String value = resProps.getProperty((String) entry.getKey());
263 // if (value == null || !value.equals(entry.getValue())) { // BEFORE
264 localConfigProps.setProperty((String) entry.getKey(), (String) entry.getValue());
265 // } // BEFORE
266 }
267 OutputStream fos = null;
268 try {
269 // problemi qui!!!
270 fos = new FileOutputStream(localConfigFile);
271 localConfigProps.store(fos, localConfigFile.getName());
272 } finally {
273 if (fos != null) {
274 fos.close();
275 }
276 }
277 }
278
279 /** Loads local configuration file.
280 * @throws IOException If file cannot be found.
281 */
282 public void loadLocalConfig() throws IOException {
283 // File file = new File(localConfigDir, name + ".properties");
284 FileInputStream fis = null;
285 try {
286 fis = new FileInputStream(localConfigFile);
287 load(fis);
288 } catch (IOException e) {
289 // Don't worry about it.
290 } finally {
291 if (fis != null) {
292 fis.close();
293 }
294 }
295 }
296
297 /** Loads resources (aka properties).
298 * @throws IOException If properties cannot be loaded.
299 */
300 public void loadResources(boolean openAsResource) throws IOException {
301 String pname = "res/";
302 String pname2 = pname;
303 try {
304 if (openAsResource) {
305 String env = System.getProperty("environment");
306 if (env != null) {
307 pname2 += env + "/";
308 }
309 pname += name + ".properties";
310 pname2 += name + ".properties";
311 ClassLoader cl = getClass().getClassLoader();
312 fullName = pname + " or " + pname2;
313 // The single '|' below is correct.
314 if (!(loadOne(cl, pname) | loadOne(cl, pname2))) {
315 throw new IOException("Can't find either " + fullName);
316 }
317 }
318 else {
319 loadAsFile(name+".properties");
320 }
321 } catch (IOException e) {
322 String error = "Error loading properties file: '" + fullName + "' : " + e;
323 // Don't use FileLog here. That uses Props, which would be recursive.
324 // System.out.println(error);
325 throw new IOException(error);
326 }
327 }
328
329 /** Loads one properties file.
330 * @param cl The class loader to use.
331 * @param props The props name to use.
332 * @throws IOException If properties file cannot be loaded.
333 * @return <CODE>true</CODE>: something has gone wrong;
334 * <CODE>false</CODE>: everything is OK.
335 */
336 boolean loadOne(ClassLoader cl, String props) throws IOException {
337 java.net.URL tempURL;
338 boolean rtn = false;
339 tempURL = cl.getResource(props);
340 if (tempURL != null)
341 propsURL = tempURL.toString();
342 else
343 propsURL = null;
344 InputStream is = cl.getResourceAsStream(props);
345 if (is != null) {
346 load(is);
347 is.close();
348 rtn = true;
349 }
350 return rtn;
351 }
352
353 protected void loadAsFile(String props) throws IOException {
354 File tempFile;
355 FileInputStream is;
356
357 tempFile = new File(localConfigDirFile, props);
358 is = new FileInputStream(tempFile);
359 if (is != null) {
360 load(is);
361 is.close();
362 }
363 }
364 }