1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.PrintStream;
23 import java.io.PrintWriter;
24 import java.io.StringWriter;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.net.URLDecoder;
28 import java.util.Iterator;
29
30 import org.apache.commons.lang.StringUtils;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34 /***
35 * Miscellaneous utility methods for configurations.
36 *
37 * @see ConfigurationConverter Utility methods to convert configurations.
38 *
39 * @author <a href="mailto:herve.quiroz@esil.univ-mrs.fr">Herve Quiroz</a>
40 * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
41 * @author Emmanuel Bourg
42 * @version $Revision$, $Date: 2005-12-14 16:20:30 +0100 (Wed, 14 Dec 2005) $
43 */
44 public final class ConfigurationUtils
45 {
46 /*** Constant for the file URL protocol.*/
47 static final String PROTOCOL_FILE = "file";
48
49 /*** The logger.*/
50 private static Log log = LogFactory.getLog(ConfigurationUtils.class);
51
52 /***
53 * Private constructor. Prevents instances from being created.
54 */
55 private ConfigurationUtils()
56 {
57
58 }
59
60 /***
61 * Dump the configuration key/value mappings to some ouput stream.
62 *
63 * @param configuration the configuration
64 * @param out the output stream to dump the configuration to
65 */
66 public static void dump(Configuration configuration, PrintStream out)
67 {
68 dump(configuration, new PrintWriter(out));
69 }
70
71 /***
72 * Dump the configuration key/value mappings to some writer.
73 *
74 * @param configuration the configuration
75 * @param out the writer to dump the configuration to
76 */
77 public static void dump(Configuration configuration, PrintWriter out)
78 {
79 Iterator keys = configuration.getKeys();
80 while (keys.hasNext())
81 {
82 String key = (String) keys.next();
83 Object value = configuration.getProperty(key);
84 out.print(key);
85 out.print("=");
86 out.print(value);
87
88 if (keys.hasNext())
89 {
90 out.println();
91 }
92 }
93
94 out.flush();
95 }
96
97 /***
98 * Get a string representation of the key/value mappings of a
99 * configuration.
100 *
101 * @param configuration the configuration
102 * @return a string representation of the configuration
103 */
104 public static String toString(Configuration configuration)
105 {
106 StringWriter writer = new StringWriter();
107 dump(configuration, new PrintWriter(writer));
108 return writer.toString();
109 }
110
111 /***
112 * Copy all properties from the source configuration to the target
113 * configuration. Properties in the target configuration are replaced with
114 * the properties with the same key in the source configuration.
115 * <em>Note:</em> This method won't work well on hierarchical configurations
116 * because it is not able to copy information about the properties'
117 * structure. So when dealing with hierarchical configuration objects their
118 * <code>{@link HierarchicalConfiguration#clone() clone()}</code> methods
119 * should be used.
120 *
121 * @param source the source configuration
122 * @param target the target configuration
123 * @since 1.1
124 */
125 public static void copy(Configuration source, Configuration target)
126 {
127 Iterator keys = source.getKeys();
128 while (keys.hasNext())
129 {
130 String key = (String) keys.next();
131 target.setProperty(key, source.getProperty(key));
132 }
133 }
134
135 /***
136 * Append all properties from the source configuration to the target
137 * configuration. Properties in the source configuration are appended to
138 * the properties with the same key in the target configuration.
139 *
140 * @param source the source configuration
141 * @param target the target configuration
142 * @since 1.1
143 */
144 public static void append(Configuration source, Configuration target)
145 {
146 Iterator keys = source.getKeys();
147 while (keys.hasNext())
148 {
149 String key = (String) keys.next();
150 target.addProperty(key, source.getProperty(key));
151 }
152 }
153
154 /***
155 * Constructs a URL from a base path and a file name. The file name can
156 * be absolute, relative or a full URL. If necessary the base path URL is
157 * applied.
158 *
159 * @param basePath the base path URL (can be <b>null</b>)
160 * @param file the file name
161 * @return the resulting URL
162 * @throws MalformedURLException if URLs are invalid
163 */
164 public static URL getURL(String basePath, String file) throws MalformedURLException
165 {
166 File f = new File(file);
167 if (f.isAbsolute())
168 {
169 return f.toURL();
170 }
171
172 try
173 {
174 if (basePath == null)
175 {
176 return new URL(file);
177 }
178 else
179 {
180 URL base = new URL(basePath);
181 return new URL(base, file);
182 }
183 }
184 catch (MalformedURLException uex)
185 {
186 return constructFile(basePath, file).toURL();
187 }
188 }
189
190 /***
191 * Helper method for constructing a file object from a base path and a
192 * file name. This method is called if the base path passed to
193 * <code>getURL()</code> does not seem to be a valid URL.
194 *
195 * @param basePath the base path
196 * @param fileName the file name
197 * @return the resulting file
198 */
199 static File constructFile(String basePath, String fileName)
200 {
201 File file = null;
202
203 File absolute = null;
204 if (fileName != null)
205 {
206 absolute = new File(fileName);
207 }
208
209 if (StringUtils.isEmpty(basePath) || (absolute != null && absolute.isAbsolute()))
210 {
211 file = new File(fileName);
212 }
213 else
214 {
215 StringBuffer fName = new StringBuffer();
216 fName.append(basePath);
217
218
219 if (!basePath.endsWith(File.separator))
220 {
221 fName.append(File.separator);
222 }
223
224
225
226
227
228
229
230 if (fileName.startsWith("." + File.separator))
231 {
232 fName.append(fileName.substring(2));
233 }
234 else
235 {
236 fName.append(fileName);
237 }
238
239 file = new File(fName.toString());
240 }
241
242 return file;
243 }
244
245 /***
246 * Return the location of the specified resource by searching the user home
247 * directory, the current classpath and the system classpath.
248 *
249 * @param name the name of the resource
250 *
251 * @return the location of the resource
252 */
253 public static URL locate(String name)
254 {
255 return locate(null, name);
256 }
257
258 /***
259 * Return the location of the specified resource by searching the user home
260 * directory, the current classpath and the system classpath.
261 *
262 * @param base the base path of the resource
263 * @param name the name of the resource
264 *
265 * @return the location of the resource
266 */
267 public static URL locate(String base, String name)
268 {
269 if (name == null)
270 {
271
272 return null;
273 }
274
275 URL url = null;
276
277
278 try
279 {
280 if (base == null)
281 {
282 url = new URL(name);
283 }
284 else
285 {
286 URL baseURL = new URL(base);
287 url = new URL(baseURL, name);
288
289
290 InputStream in = null;
291 try
292 {
293 in = url.openStream();
294 }
295 finally
296 {
297 if (in != null)
298 {
299 in.close();
300 }
301 }
302 }
303
304 log.debug("Configuration loaded from the URL " + url);
305 }
306 catch (IOException e)
307 {
308 url = null;
309 }
310
311
312 if (url == null)
313 {
314 File file = new File(name);
315 if (file.isAbsolute() && file.exists())
316 {
317 try
318 {
319 url = file.toURL();
320 log.debug("Configuration loaded from the absolute path " + name);
321 }
322 catch (MalformedURLException e)
323 {
324 e.printStackTrace();
325 }
326 }
327 }
328
329
330 if (url == null)
331 {
332 try
333 {
334 File file = constructFile(base, name);
335 if (file != null && file.exists())
336 {
337 url = file.toURL();
338 }
339
340 if (url != null)
341 {
342 log.debug("Configuration loaded from the base path " + name);
343 }
344 }
345 catch (IOException e)
346 {
347 e.printStackTrace();
348 }
349 }
350
351
352 if (url == null)
353 {
354 try
355 {
356 File file = constructFile(System.getProperty("user.home"), name);
357 if (file != null && file.exists())
358 {
359 url = file.toURL();
360 }
361
362 if (url != null)
363 {
364 log.debug("Configuration loaded from the home path " + name);
365 }
366
367 }
368 catch (IOException e)
369 {
370 e.printStackTrace();
371 }
372 }
373
374
375 if (url == null)
376 {
377 ClassLoader loader = Thread.currentThread().getContextClassLoader();
378 url = loader.getResource(name);
379
380 if (url != null)
381 {
382 log.debug("Configuration loaded from the context classpath (" + name + ")");
383 }
384 }
385
386
387 if (url == null)
388 {
389 url = ClassLoader.getSystemResource(name);
390
391 if (url != null)
392 {
393 log.debug("Configuration loaded from the system classpath (" + name + ")");
394 }
395 }
396
397 return url;
398 }
399
400 /***
401 * Return the path without the file name, for example http://xyz.net/foo/bar.xml
402 * results in http://xyz.net/foo/
403 *
404 * @param url the URL from which to extract the path
405 * @return the path component of the passed in URL
406 */
407 static String getBasePath(URL url)
408 {
409 if (url == null)
410 {
411 return null;
412 }
413
414 String s = url.toString();
415
416 if (s.endsWith("/") || StringUtils.isEmpty(url.getPath()))
417 {
418 return s;
419 }
420 else
421 {
422 return s.substring(0, s.lastIndexOf("/") + 1);
423 }
424 }
425
426 /***
427 * Extract the file name from the specified URL.
428 *
429 * @param url the URL from which to extract the file name
430 * @return the extracted file name
431 */
432 static String getFileName(URL url)
433 {
434 if (url == null)
435 {
436 return null;
437 }
438
439 String path = url.getPath();
440
441 if (path.endsWith("/") || StringUtils.isEmpty(path))
442 {
443 return null;
444 }
445 else
446 {
447 return path.substring(path.lastIndexOf("/") + 1);
448 }
449 }
450
451 /***
452 * Tries to convert the specified base path and file name into a file object.
453 * This method is called e.g. by the save() methods of file based
454 * configurations. The parameter strings can be relative files, absolute
455 * files and URLs as well.
456 *
457 * @param basePath the base path
458 * @param fileName the file name
459 * @return the file object (<b>null</b> if no file can be obtained)
460 */
461 public static File getFile(String basePath, String fileName)
462 {
463
464 URL url;
465 try
466 {
467 url = new URL(new URL(basePath), fileName);
468 }
469 catch (MalformedURLException mex1)
470 {
471 try
472 {
473 url = new URL(fileName);
474 }
475 catch (MalformedURLException mex2)
476 {
477 url = null;
478 }
479 }
480
481 if (url != null)
482 {
483 return fileFromURL(url);
484 }
485
486 return constructFile(basePath, fileName);
487 }
488
489 /***
490 * Tries to convert the specified URL to a file object. If this fails,
491 * <b>null</b> is returned.
492 *
493 * @param url the URL
494 * @return the resulting file object
495 */
496 public static File fileFromURL(URL url)
497 {
498 if (PROTOCOL_FILE.equals(url.getProtocol()))
499 {
500 return new File(URLDecoder.decode(url.getPath()));
501 }
502 else
503 {
504 return null;
505 }
506 }
507 }