##### Coverage Report - org.apache.commons.configuration.ConfigurationUtils

Classes in this File | Line Coverage | Branch Coverage | Complexity
ConfigurationUtils |
85% | 153/179
100% | 39/39
| 4.65;4,65
ConfigurationUtils$1 |
100% | 2/2
N/A | N/A
| 4.65;4,65

1 |  |
     /*
2 |  |
      * Licensed to the Apache Software Foundation (ASF) under one or more
3 |  |
      * contributor license agreements.  See the NOTICE file distributed with
4 |  |
      * this work for additional information regarding copyright ownership.
5 |  |
      * The ASF licenses this file to You under the Apache License, Version 2.0
6 |  |
      * (the "License"); you may not use this file except in compliance with
7 |  |
      * the License.  You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      * Unless required by applicable law or agreed to in writing, software
12 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      * See the License for the specific language governing permissions and
15 |  |
      * limitations under the License.
16 |  |
      */
17 |  |
18 |  |
     package org.apache.commons.configuration;
19 |  |
20 |  |
     import java.io.File;
21 |  |
     import java.io.IOException;
22 |  |
     import java.io.InputStream;
23 |  |
     import java.io.PrintStream;
24 |  |
     import java.io.PrintWriter;
25 |  |
     import java.io.StringWriter;
26 |  |
     import java.lang.reflect.InvocationTargetException;
27 |  |
     import java.lang.reflect.Method;
28 |  |
     import java.net.MalformedURLException;
29 |  |
     import java.net.URL;
30 |  |
     import java.net.URLDecoder;
31 |  |
     import java.util.Iterator;
32 |  |
33 |  |
     import org.apache.commons.configuration.event.ConfigurationErrorEvent;
34 |  |
     import org.apache.commons.configuration.event.ConfigurationErrorListener;
35 |  |
     import org.apache.commons.configuration.event.EventSource;
36 |  |
     import org.apache.commons.lang.StringUtils;
37 |  |
     import org.apache.commons.logging.Log;
38 |  |
     import org.apache.commons.logging.LogFactory;
39 |  |
40 |  |
     /**
41 |  |
      * Miscellaneous utility methods for configurations.
42 |  |
      *
43 |  |
      * @see ConfigurationConverter Utility methods to convert configurations.
44 |  |
      *
45 |  |
      * @author <a href="mailto:herve.quiroz@esil.univ-mrs.fr">Herve Quiroz</a>
46 |  |
      * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
47 |  |
      * @author Emmanuel Bourg
48 |  |
      * @version $Revision: 567771 $, $Date: 2007-08-20 19:57:08 +0200 (Mo, 20 Aug 2007) $
49 |  |
      */
50 |  |
     public final class ConfigurationUtils
51 |  |
     {
52 |  |
         /** Constant for the file URL protocol.*/
53 |  |
         static final String PROTOCOL_FILE = "file";
54 |  |
55 |  |
         /** Constant for the resource path separator.*/
56 |  |
         static final String RESOURCE_PATH_SEPARATOR = "/";
57 |  |
58 |  |
         /** Constant for the name of the clone() method.*/
59 |  |
         private static final String METHOD_CLONE = "clone";
60 |  |
61 |  |
         /** The logger.*/
62 | 64 |
         private static Log log = LogFactory.getLog(ConfigurationUtils.class);
63 |  |
64 |  |
         /**
65 |  |
          * Private constructor. Prevents instances from being created.
66 |  |
          */
67 |  |
         private ConfigurationUtils()
68 | 0 |
         {
69 |  |
             // to prevent instanciation...
70 | 0 |
         }
71 |  |
72 |  |
         /**
73 |  |
          * Dump the configuration key/value mappings to some ouput stream.
74 |  |
          *
75 |  |
          * @param configuration the configuration
76 |  |
          * @param out the output stream to dump the configuration to
77 |  |
          */
78 |  |
         public static void dump(Configuration configuration, PrintStream out)
79 |  |
         {
80 | 0 |
             dump(configuration, new PrintWriter(out));
81 | 0 |
         }
82 |  |
83 |  |
         /**
84 |  |
          * Dump the configuration key/value mappings to some writer.
85 |  |
          *
86 |  |
          * @param configuration the configuration
87 |  |
          * @param out the writer to dump the configuration to
88 |  |
          */
89 |  |
         public static void dump(Configuration configuration, PrintWriter out)
90 |  |
         {
91 | 5 |
             Iterator keys = configuration.getKeys();
92 | 11 |
             while (keys.hasNext())
93 |  |
             {
94 | 6 |
                 String key = (String) keys.next();
95 | 6 |
                 Object value = configuration.getProperty(key);
96 | 6 |
                 out.print(key);
97 | 6 |
                 out.print("=");
98 | 6 |
                 out.print(value);
99 |  |
100 | 6 |
                 if (keys.hasNext())
101 |  |
                 {
102 | 2 |
                     out.println();
103 |  |
                 }
104 | 6 |
             }
105 |  |
106 | 5 |
             out.flush();
107 | 5 |
         }
108 |  |
109 |  |
         /**
110 |  |
          * Get a string representation of the key/value mappings of a
111 |  |
          * configuration.
112 |  |
          *
113 |  |
          * @param configuration the configuration
114 |  |
          * @return a string representation of the configuration
115 |  |
          */
116 |  |
         public static String toString(Configuration configuration)
117 |  |
         {
118 | 5 |
             StringWriter writer = new StringWriter();
119 | 5 |
             dump(configuration, new PrintWriter(writer));
120 | 5 |
             return writer.toString();
121 |  |
         }
122 |  |
123 |  |
         /**
124 |  |
          * <p>Copy all properties from the source configuration to the target
125 |  |
          * configuration. Properties in the target configuration are replaced with
126 |  |
          * the properties with the same key in the source configuration.</p>
127 |  |
          * <p><em>Note:</em> This method is not able to handle some specifics of
128 |  |
          * configurations derived from <code>AbstractConfiguration</code> (e.g.
129 |  |
          * list delimiters). For a full support of all of these features the
130 |  |
          * <code>copy()</code> method of <code>AbstractConfiguration</code> should
131 |  |
          * be used. In a future release this method might become deprecated.</p>
132 |  |
          *
133 |  |
          * @param source the source configuration
134 |  |
          * @param target the target configuration
135 |  |
          * @since 1.1
136 |  |
          */
137 |  |
         public static void copy(Configuration source, Configuration target)
138 |  |
         {
139 | 54 |
             Iterator keys = source.getKeys();
140 | 1162 |
             while (keys.hasNext())
141 |  |
             {
142 | 1108 |
                 String key = (String) keys.next();
143 | 1108 |
                 target.setProperty(key, source.getProperty(key));
144 | 1108 |
             }
145 | 54 |
         }
146 |  |
147 |  |
         /**
148 |  |
          * <p>Append all properties from the source configuration to the target
149 |  |
          * configuration. Properties in the source configuration are appended to
150 |  |
          * the properties with the same key in the target configuration.</p>
151 |  |
          * <p><em>Note:</em> This method is not able to handle some specifics of
152 |  |
          * configurations derived from <code>AbstractConfiguration</code> (e.g.
153 |  |
          * list delimiters). For a full support of all of these features the
154 |  |
          * <code>copy()</code> method of <code>AbstractConfiguration</code> should
155 |  |
          * be used. In a future release this method might become deprecated.</p>
156 |  |
          *
157 |  |
          * @param source the source configuration
158 |  |
          * @param target the target configuration
159 |  |
          * @since 1.1
160 |  |
          */
161 |  |
         public static void append(Configuration source, Configuration target)
162 |  |
         {
163 | 1 |
             Iterator keys = source.getKeys();
164 | 3 |
             while (keys.hasNext())
165 |  |
             {
166 | 2 |
                 String key = (String) keys.next();
167 | 2 |
                 target.addProperty(key, source.getProperty(key));
168 | 2 |
             }
169 | 1 |
         }
170 |  |
171 |  |
         /**
172 |  |
          * Converts the passed in configuration to a hierarchical one. If the
173 |  |
          * configuration is already hierarchical, it is directly returned. Otherwise
174 |  |
          * all properties are copied into a new hierarchical configuration.
175 |  |
          *
176 |  |
          * @param conf the configuration to convert
177 |  |
          * @return the new hierarchical configuration (the result is <b>null</b> if
178 |  |
          * and only if the passed in configuration is <b>null</b>)
179 |  |
          * @since 1.3
180 |  |
          */
181 |  |
         public static HierarchicalConfiguration convertToHierarchical(
182 |  |
                 Configuration conf)
183 |  |
         {
184 | 94 |
             if (conf == null)
185 |  |
             {
186 | 1 |
                 return null;
187 |  |
             }
188 |  |
189 | 93 |
             if (conf instanceof HierarchicalConfiguration)
190 |  |
             {
191 | 48 |
                 return (HierarchicalConfiguration) conf;
192 |  |
             }
193 |  |
             else
194 |  |
             {
195 | 45 |
                 HierarchicalConfiguration hc = new HierarchicalConfiguration();
196 |  |
                 // Workaround for problem with copy()
197 | 45 |
                 boolean delimiterParsingStatus = hc.isDelimiterParsingDisabled();
198 | 45 |
                 hc.setDelimiterParsingDisabled(true);
199 | 45 |
                 ConfigurationUtils.copy(conf, hc);
200 | 45 |
                 hc.setDelimiterParsingDisabled(delimiterParsingStatus);
201 | 45 |
                 return hc;
202 |  |
             }
203 |  |
         }
204 |  |
205 |  |
         /**
206 |  |
          * Clones the given configuration object if this is possible. If the passed
207 |  |
          * in configuration object implements the <code>Cloneable</code>
208 |  |
          * interface, its <code>clone()</code> method will be invoked. Otherwise
209 |  |
          * an exception will be thrown.
210 |  |
          *
211 |  |
          * @param config the configuration object to be cloned (can be <b>null</b>)
212 |  |
          * @return the cloned configuration (<b>null</b> if the argument was
213 |  |
          * <b>null</b>, too)
214 |  |
          * @throws ConfigurationRuntimeException if cloning is not supported for
215 |  |
          * this object
216 |  |
          * @since 1.3
217 |  |
          */
218 |  |
         public static Configuration cloneConfiguration(Configuration config)
219 |  |
                 throws ConfigurationRuntimeException
220 |  |
         {
221 | 12 |
             if (config == null)
222 |  |
             {
223 | 1 |
                 return null;
224 |  |
             }
225 |  |
             else
226 |  |
             {
227 |  |
                 try
228 |  |
                 {
229 | 11 |
                     return (Configuration) clone(config);
230 |  |
                 }
231 | 2 |
                 catch (CloneNotSupportedException cnex)
232 |  |
                 {
233 | 2 |
                     throw new ConfigurationRuntimeException(cnex);
234 |  |
                 }
235 |  |
             }
236 |  |
         }
237 |  |
238 |  |
         /**
239 |  |
          * An internally used helper method for cloning objects. This implementation
240 |  |
          * is not very sophisticated nor efficient. Maybe it can be replaced by an
241 |  |
          * implementation from Commons Lang later. The method checks whether the
242 |  |
          * passed in object implements the <code>Cloneable</code> interface. If
243 |  |
          * this is the case, the <code>clone()</code> method is invoked by
244 |  |
          * reflection. Errors that occur during the cloning process are re-thrown as
245 |  |
          * runtime exceptions.
246 |  |
          *
247 |  |
          * @param obj the object to be cloned
248 |  |
          * @return the cloned object
249 |  |
          * @throws CloneNotSupportedException if the object cannot be cloned
250 |  |
          */
251 |  |
         static Object clone(Object obj) throws CloneNotSupportedException
252 |  |
         {
253 | 23 |
             if (obj instanceof Cloneable)
254 |  |
             {
255 |  |
                 try
256 |  |
                 {
257 | 21 |
                     Method m = obj.getClass().getMethod(METHOD_CLONE, null);
258 | 21 |
                     return m.invoke(obj, null);
259 |  |
                 }
260 | 0 |
                 catch (NoSuchMethodException nmex)
261 |  |
                 {
262 | 0 |
                     throw new CloneNotSupportedException(
263 |  |
                             "No clone() method found for class"
264 |  |
                                     + obj.getClass().getName());
265 |  |
                 }
266 | 0 |
                 catch (IllegalAccessException iaex)
267 |  |
                 {
268 | 0 |
                     throw new ConfigurationRuntimeException(iaex);
269 |  |
                 }
270 | 0 |
                 catch (InvocationTargetException itex)
271 |  |
                 {
272 | 0 |
                     throw new ConfigurationRuntimeException(itex);
273 |  |
                 }
274 |  |
             }
275 |  |
             else
276 |  |
             {
277 | 2 |
                 throw new CloneNotSupportedException(obj.getClass().getName()
278 |  |
                         + " does not implement Cloneable");
279 |  |
             }
280 |  |
         }
281 |  |
282 |  |
         /**
283 |  |
          * Constructs a URL from a base path and a file name. The file name can
284 |  |
          * be absolute, relative or a full URL. If necessary the base path URL is
285 |  |
          * applied.
286 |  |
          *
287 |  |
          * @param basePath the base path URL (can be <b>null</b>)
288 |  |
          * @param file the file name
289 |  |
          * @return the resulting URL
290 |  |
          * @throws MalformedURLException if URLs are invalid
291 |  |
          */
292 |  |
         public static URL getURL(String basePath, String file) throws MalformedURLException
293 |  |
         {
294 | 8 |
             File f = new File(file);
295 | 8 |
             if (f.isAbsolute()) // already absolute?
296 |  |
             {
297 | 2 |
                 return f.toURL();
298 |  |
             }
299 |  |
300 |  |
             try
301 |  |
             {
302 | 6 |
                 if (basePath == null)
303 |  |
                 {
304 | 2 |
                     return new URL(file);
305 |  |
                 }
306 |  |
                 else
307 |  |
                 {
308 | 4 |
                     URL base = new URL(basePath);
309 | 3 |
                     return new URL(base, file);
310 |  |
                 }
311 |  |
             }
312 | 2 |
             catch (MalformedURLException uex)
313 |  |
             {
314 | 2 |
                 return constructFile(basePath, file).toURL();
315 |  |
             }
316 |  |
         }
317 |  |
318 |  |
         /**
319 |  |
          * Helper method for constructing a file object from a base path and a
320 |  |
          * file name. This method is called if the base path passed to
321 |  |
          * <code>getURL()</code> does not seem to be a valid URL.
322 |  |
          *
323 |  |
          * @param basePath the base path
324 |  |
          * @param fileName the file name
325 |  |
          * @return the resulting file
326 |  |
          */
327 |  |
         static File constructFile(String basePath, String fileName)
328 |  |
         {
329 | 553 |
             File file = null;
330 |  |
331 | 553 |
             File absolute = null;
332 | 553 |
             if (fileName != null)
333 |  |
             {
334 | 553 |
                 absolute = new File(fileName);
335 |  |
             }
336 |  |
337 | 553 |
             if (StringUtils.isEmpty(basePath) || (absolute != null && absolute.isAbsolute()))
338 |  |
             {
339 | 57 |
                 file = new File(fileName);
340 | 57 |
             }
341 |  |
             else
342 |  |
             {
343 | 496 |
                 StringBuffer fName = new StringBuffer();
344 | 496 |
                 fName.append(basePath);
345 |  |
346 |  |
                 // My best friend. Paranoia.
347 | 496 |
                 if (!basePath.endsWith(File.separator))
348 |  |
                 {
349 | 496 |
                     fName.append(File.separator);
350 |  |
                 }
351 |  |
352 |  |
                 //
353 |  |
                 // We have a relative path, and we have
354 |  |
                 // two possible forms here. If we have the
355 |  |
                 // "./" form then just strip that off first
356 |  |
                 // before continuing.
357 |  |
                 //
358 | 496 |
                 if (fileName.startsWith("." + File.separator))
359 |  |
                 {
360 | 0 |
                     fName.append(fileName.substring(2));
361 | 0 |
                 }
362 |  |
                 else
363 |  |
                 {
364 | 496 |
                     fName.append(fileName);
365 |  |
                 }
366 |  |
367 | 496 |
                 file = new File(fName.toString());
368 |  |
             }
369 |  |
370 | 553 |
             return file;
371 |  |
         }
372 |  |
373 |  |
         /**
374 |  |
          * Return the location of the specified resource by searching the user home
375 |  |
          * directory, the current classpath and the system classpath.
376 |  |
          *
377 |  |
          * @param name the name of the resource
378 |  |
          *
379 |  |
          * @return the location of the resource
380 |  |
          */
381 |  |
         public static URL locate(String name)
382 |  |
         {
383 | 0 |
             return locate(null, name);
384 |  |
         }
385 |  |
386 |  |
         /**
387 |  |
          * Return the location of the specified resource by searching the user home
388 |  |
          * directory, the current classpath and the system classpath.
389 |  |
          *
390 |  |
          * @param base the base path of the resource
391 |  |
          * @param name the name of the resource
392 |  |
          *
393 |  |
          * @return the location of the resource
394 |  |
          */
395 |  |
         public static URL locate(String base, String name)
396 |  |
         {
397 | 1140 |
             if (log.isDebugEnabled())
398 |  |
             {
399 | 0 |
                 StringBuffer buf = new StringBuffer();
400 | 0 |
                 buf.append("ConfigurationUtils.locate(): base is ").append(base);
401 | 0 |
                 buf.append(", name is ").append(name);
402 | 0 |
                 log.debug(buf.toString());
403 |  |
             }
404 |  |
405 | 1140 |
             if (name == null)
406 |  |
             {
407 |  |
                 // undefined, always return null
408 | 4 |
                 return null;
409 |  |
             }
410 |  |
411 | 1136 |
             URL url = null;
412 |  |
413 |  |
             // attempt to create an URL directly
414 |  |
             try
415 |  |
             {
416 | 1136 |
                 if (base == null)
417 |  |
                 {
418 | 329 |
                     url = new URL(name);
419 | 0 |
                 }
420 |  |
                 else
421 |  |
                 {
422 | 807 |
                     URL baseURL = new URL(base);
423 | 410 |
                     url = new URL(baseURL, name);
424 |  |
425 |  |
                     // check if the file exists
426 | 408 |
                     InputStream in = null;
427 |  |
                     try
428 |  |
                     {
429 | 408 |
                         in = url.openStream();
430 |  |
                     }
431 |  |
                     finally
432 |  |
                     {
433 | 408 |
                         if (in != null)
434 |  |
                         {
435 | 390 |
                             in.close();
436 | 390 |
                         }
437 | 18 |
                     }
438 |  |
                 }
439 |  |
440 | 390 |
                 log.debug("Loading configuration from the URL " + url);
441 |  |
             }
442 | 746 |
             catch (IOException e)
443 |  |
             {
444 | 746 |
                 url = null;
445 | 390 |
             }
446 |  |
447 |  |
             // attempt to load from an absolute path
448 | 1136 |
             if (url == null)
449 |  |
             {
450 | 746 |
                 File file = new File(name);
451 | 746 |
                 if (file.isAbsolute() && file.exists()) // already absolute?
452 |  |
                 {
453 |  |
                     try
454 |  |
                     {
455 | 282 |
                         url = file.toURL();
456 | 282 |
                         log.debug("Loading configuration from the absolute path " + name);
457 |  |
                     }
458 | 0 |
                     catch (MalformedURLException e)
459 |  |
                     {
460 | 0 |
                         log.warn("Could not obtain URL from file", e);
461 | 282 |
                     }
462 |  |
                 }
463 |  |
             }
464 |  |
465 |  |
             // attempt to load from the base directory
466 | 1136 |
             if (url == null)
467 |  |
             {
468 |  |
                 try
469 |  |
                 {
470 | 464 |
                     File file = constructFile(base, name);
471 | 464 |
                     if (file != null && file.exists())
472 |  |
                     {
473 | 413 |
                         url = file.toURL();
474 |  |
                     }
475 |  |
476 | 464 |
                     if (url != null)
477 |  |
                     {
478 | 413 |
                         log.debug("Loading configuration from the path " + file);
479 |  |
                     }
480 |  |
                 }
481 | 0 |
                 catch (MalformedURLException e)
482 |  |
                 {
483 | 0 |
                     log.warn("Could not obtain URL from file", e);
484 | 464 |
                 }
485 |  |
             }
486 |  |
487 |  |
             // attempt to load from the user home directory
488 | 1136 |
             if (url == null)
489 |  |
             {
490 |  |
                 try
491 |  |
                 {
492 | 51 |
                     File file = constructFile(System.getProperty("user.home"), name);
493 | 51 |
                     if (file != null && file.exists())
494 |  |
                     {
495 | 1 |
                         url = file.toURL();
496 |  |
                     }
497 |  |
498 | 51 |
                     if (url != null)
499 |  |
                     {
500 | 1 |
                         log.debug("Loading configuration from the home path " + file);
501 |  |
                     }
502 |  |
503 |  |
                 }
504 | 0 |
                 catch (MalformedURLException e)
505 |  |
                 {
506 | 0 |
                     log.warn("Could not obtain URL from file", e);
507 | 51 |
                 }
508 |  |
             }
509 |  |
510 |  |
             // attempt to load from classpath
511 | 1136 |
             if (url == null)
512 |  |
             {
513 | 50 |
                 url = locateFromClasspath(name);
514 |  |
             }
515 | 1136 |
             return url;
516 |  |
         }
517 |  |
518 |  |
         /**
519 |  |
          * Tries to find a resource with the given name in the classpath.
520 |  |
          * @param resourceName the name of the resource
521 |  |
          * @return the URL to the found resource or <b>null</b> if the resource
522 |  |
          * cannot be found
523 |  |
          */
524 |  |
         static URL locateFromClasspath(String resourceName)
525 |  |
         {
526 | 50 |
             URL url = null;
527 |  |
             // attempt to load from the context classpath
528 | 50 |
             ClassLoader loader = Thread.currentThread().getContextClassLoader();
529 | 50 |
             if (loader != null)
530 |  |
             {
531 | 49 |
                 url = loader.getResource(resourceName);
532 |  |
533 | 49 |
                 if (url != null)
534 |  |
                 {
535 | 20 |
                     log.debug("Loading configuration from the context classpath (" + resourceName + ")");
536 |  |
                 }
537 |  |
             }
538 |  |
539 |  |
             // attempt to load from the system classpath
540 | 50 |
             if (url == null)
541 |  |
             {
542 | 30 |
                 url = ClassLoader.getSystemResource(resourceName);
543 |  |
544 | 30 |
                 if (url != null)
545 |  |
                 {
546 | 0 |
                     log.debug("Loading configuration from the system classpath (" + resourceName + ")");
547 |  |
                 }
548 |  |
             }
549 | 50 |
             return url;
550 |  |
         }
551 |  |
552 |  |
         /**
553 |  |
          * Return the path without the file name, for example http://xyz.net/foo/bar.xml
554 |  |
          * results in http://xyz.net/foo/
555 |  |
          *
556 |  |
          * @param url the URL from which to extract the path
557 |  |
          * @return the path component of the passed in URL
558 |  |
          */
559 |  |
         static String getBasePath(URL url)
560 |  |
         {
561 | 20 |
             if (url == null)
562 |  |
             {
563 | 0 |
                 return null;
564 |  |
             }
565 |  |
566 | 20 |
             String s = url.toString();
567 |  |
568 | 20 |
             if (s.endsWith("/") || StringUtils.isEmpty(url.getPath()))
569 |  |
             {
570 | 3 |
                 return s;
571 |  |
             }
572 |  |
             else
573 |  |
             {
574 | 17 |
                 return s.substring(0, s.lastIndexOf("/") + 1);
575 |  |
             }
576 |  |
         }
577 |  |
578 |  |
         /**
579 |  |
          * Extract the file name from the specified URL.
580 |  |
          *
581 |  |
          * @param url the URL from which to extract the file name
582 |  |
          * @return the extracted file name
583 |  |
          */
584 |  |
         static String getFileName(URL url)
585 |  |
         {
586 | 18 |
             if (url == null)
587 |  |
             {
588 | 1 |
                 return null;
589 |  |
             }
590 |  |
591 | 17 |
             String path = url.getPath();
592 |  |
593 | 17 |
             if (path.endsWith("/") || StringUtils.isEmpty(path))
594 |  |
             {
595 | 1 |
                 return null;
596 |  |
             }
597 |  |
             else
598 |  |
             {
599 | 16 |
                 return path.substring(path.lastIndexOf("/") + 1);
600 |  |
             }
601 |  |
         }
602 |  |
603 |  |
         /**
604 |  |
          * Tries to convert the specified base path and file name into a file object.
605 |  |
          * This method is called e.g. by the save() methods of file based
606 |  |
          * configurations. The parameter strings can be relative files, absolute
607 |  |
          * files and URLs as well. This implementation checks first whether the passed in
608 |  |
          * file name is absolute. If this is the case, it is returned. Otherwise
609 |  |
          * further checks are performed whether the base path and file name can be
610 |  |
          * combined to a valid URL or a valid file name. <em>Note:</em> The test
611 |  |
          * if the passed in file name is absolute is performed using
612 |  |
          * <code>java.io.File.isAbsolute()</code>. If the file name starts with a
613 |  |
          * slash, this method will return <b>true</b> on Unix, but <b>false</b> on
614 |  |
          * Windows. So to ensure correct behavior for relative file names on all
615 |  |
          * platforms you should never let relative paths start with a slash. E.g.
616 |  |
          * in a configuration definition file do not use something like that:
617 |  |
          * <pre>
618 |  |
          * &lt;properties fileName="/subdir/my.properties"/&gt;
619 |  |
          * </pre>
620 |  |
          * Under Windows this path would be resolved relative to the configuration
621 |  |
          * definition file. Under Unix this would be treated as an absolute path
622 |  |
          * name.
623 |  |
          *
624 |  |
          * @param basePath the base path
625 |  |
          * @param fileName the file name
626 |  |
          * @return the file object (<b>null</b> if no file can be obtained)
627 |  |
          */
628 |  |
         public static File getFile(String basePath, String fileName)
629 |  |
         {
630 |  |
             // Check if the file name is absolute
631 | 49 |
             File f = new File(fileName);
632 | 49 |
             if (f.isAbsolute())
633 |  |
             {
634 | 8 |
                 return f;
635 |  |
             }
636 |  |
637 |  |
             // Check if URLs are involved
638 |  |
             URL url;
639 |  |
             try
640 |  |
             {
641 | 41 |
                 url = new URL(new URL(basePath), fileName);
642 |  |
             }
643 | 38 |
             catch (MalformedURLException mex1)
644 |  |
             {
645 |  |
                 try
646 |  |
                 {
647 | 38 |
                     url = new URL(fileName);
648 |  |
                 }
649 | 36 |
                 catch (MalformedURLException mex2)
650 |  |
                 {
651 | 36 |
                     url = null;
652 | 2 |
                 }
653 | 3 |
             }
654 |  |
655 | 41 |
             if (url != null)
656 |  |
             {
657 | 5 |
                 return fileFromURL(url);
658 |  |
             }
659 |  |
660 | 36 |
             return constructFile(basePath, fileName);
661 |  |
         }
662 |  |
663 |  |
         /**
664 |  |
          * Tries to convert the specified URL to a file object. If this fails,
665 |  |
          * <b>null</b> is returned.
666 |  |
          *
667 |  |
          * @param url the URL
668 |  |
          * @return the resulting file object
669 |  |
          */
670 |  |
         public static File fileFromURL(URL url)
671 |  |
         {
672 | 1421 |
             if (PROTOCOL_FILE.equals(url.getProtocol()))
673 |  |
             {
674 | 1415 |
                 return new File(URLDecoder.decode(url.getPath()));
675 |  |
             }
676 |  |
             else
677 |  |
             {
678 | 6 |
                 return null;
679 |  |
             }
680 |  |
         }
681 |  |
682 |  |
         /**
683 |  |
          * Enables runtime exceptions for the specified configuration object. This
684 |  |
          * method can be used for configuration implementations that may face errors
685 |  |
          * on normal property access, e.g. <code>DatabaseConfiguration</code> or
686 |  |
          * <code>JNDIConfiguration</code>. Per default such errors are simply
687 |  |
          * logged and then ignored. This implementation will register a special
688 |  |
          * <code>{@link ConfigurationErrorListener}</code> that throws a runtime
689 |  |
          * exception (namely a <code>ConfigurationRuntimeException</code>) on
690 |  |
          * each received error event.
691 |  |
          *
692 |  |
          * @param src the configuration, for which runtime exceptions are to be
693 |  |
          * enabled; this configuration must be derived from
694 |  |
          * <code>{@link EventSource}</code>
695 |  |
          */
696 |  |
         public static void enableRuntimeExceptions(Configuration src)
697 |  |
         {
698 | 3 |
             if (!(src instanceof EventSource))
699 |  |
             {
700 | 2 |
                 throw new IllegalArgumentException(
701 |  |
                         "Configuration must be derived from EventSource!");
702 |  |
             }
703 | 1 |
             ((EventSource) src).addErrorListener(new ConfigurationErrorListener()
704 |  |
             {
705 | 1 |
                 public void configurationError(ConfigurationErrorEvent event)
706 |  |
                 {
707 |  |
                     // Throw a runtime exception
708 | 1 |
                     throw new ConfigurationRuntimeException(event.getCause());
709 |  |
                 }
710 |  |
             });
711 | 1 |
         }
712 |  |
     }