View Javadoc

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