View Javadoc

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  package org.apache.commons.configuration;
18  
19  import java.io.File;
20  import java.io.FileNotFoundException;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.net.HttpURLConnection;
26  import java.net.MalformedURLException;
27  import java.net.URL;
28  import java.net.URLConnection;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  /**
34   * FileSystem that uses java.io.File or HttpClient
35   * @since 1.7
36   * @author <a
37   * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
38   */
39  public class DefaultFileSystem extends FileSystem
40  {
41      /**
42       * The Log for diagnostic messages.
43       */
44      private Log log = LogFactory.getLog(DefaultFileSystem.class);
45  
46      @Override
47      public InputStream getInputStream(String basePath, String fileName)
48          throws ConfigurationException
49      {
50          try
51          {
52              URL url = ConfigurationUtils.locate(this, basePath, fileName);
53  
54              if (url == null)
55              {
56                  throw new ConfigurationException("Cannot locate configuration source " + fileName);
57              }
58              return getInputStream(url);
59          }
60          catch (ConfigurationException e)
61          {
62              throw e;
63          }
64          catch (Exception e)
65          {
66              throw new ConfigurationException("Unable to load the configuration file " + fileName, e);
67          }
68      }
69  
70      @Override
71      public InputStream getInputStream(URL url) throws ConfigurationException
72      {
73          // throw an exception if the target URL is a directory
74          File file = ConfigurationUtils.fileFromURL(url);
75          if (file != null && file.isDirectory())
76          {
77              throw new ConfigurationException("Cannot load a configuration from a directory");
78          }
79  
80          try
81          {
82              return url.openStream();
83          }
84          catch (Exception e)
85          {
86              throw new ConfigurationException("Unable to load the configuration from the URL " + url, e);
87          }
88      }
89  
90      @Override
91      public OutputStream getOutputStream(URL url) throws ConfigurationException
92      {
93          // file URLs have to be converted to Files since FileURLConnection is
94          // read only (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4191800)
95          File file = ConfigurationUtils.fileFromURL(url);
96          if (file != null)
97          {
98              return getOutputStream(file);
99          }
100         else
101         {
102             // for non file URLs save through an URLConnection
103             OutputStream out;
104             try
105             {
106                 URLConnection connection = url.openConnection();
107                 connection.setDoOutput(true);
108 
109                 // use the PUT method for http URLs
110                 if (connection instanceof HttpURLConnection)
111                 {
112                     HttpURLConnection conn = (HttpURLConnection) connection;
113                     conn.setRequestMethod("PUT");
114                 }
115 
116                 out = connection.getOutputStream();
117 
118                 // check the response code for http URLs and throw an exception if an error occured
119                 if (connection instanceof HttpURLConnection)
120                 {
121                     out = new HttpOutputStream(out, (HttpURLConnection) connection);
122                 }
123                 return out;
124             }
125             catch (IOException e)
126             {
127                 throw new ConfigurationException("Could not save to URL " + url, e);
128             }
129         }
130     }
131 
132     @Override
133     public OutputStream getOutputStream(File file) throws ConfigurationException
134     {
135         try
136         {
137             // create the file if necessary
138             createPath(file);
139             return new FileOutputStream(file);
140         }
141         catch (FileNotFoundException e)
142         {
143             throw new ConfigurationException("Unable to save to file " + file, e);
144         }
145     }
146 
147     @Override
148     public String getPath(File file, URL url, String basePath, String fileName)
149     {
150         String path = null;
151         // if resource was loaded from jar file may be null
152         if (file != null)
153         {
154             path = file.getAbsolutePath();
155         }
156 
157         // try to see if file was loaded from a jar
158         if (path == null)
159         {
160             if (url != null)
161             {
162                 path = url.getPath();
163             }
164             else
165             {
166                 try
167                 {
168                     path = getURL(basePath, fileName).getPath();
169                 }
170                 catch (Exception e)
171                 {
172                     // simply ignore it and return null
173                     if (log.isDebugEnabled())
174                     {
175                         log.debug(String.format("Could not determine URL for "
176                                 + "basePath = %s, fileName = %s.", basePath,
177                                 fileName), e);
178                     }
179                 }
180             }
181         }
182 
183         return path;
184     }
185 
186     @Override
187     public String getBasePath(String path)
188     {
189         URL url;
190         try
191         {
192             url = getURL(null, path);
193             return ConfigurationUtils.getBasePath(url);
194         }
195         catch (Exception e)
196         {
197             return null;
198         }
199     }
200 
201     @Override
202     public String getFileName(String path)
203     {
204         URL url;
205         try
206         {
207             url = getURL(null, path);
208             return ConfigurationUtils.getFileName(url);
209         }
210         catch (Exception e)
211         {
212             return null;
213         }
214     }
215 
216 
217     @Override
218     public URL getURL(String basePath, String file) throws MalformedURLException
219     {
220         File f = new File(file);
221         if (f.isAbsolute()) // already absolute?
222         {
223             return ConfigurationUtils.toURL(f);
224         }
225 
226         try
227         {
228             if (basePath == null)
229             {
230                 return new URL(file);
231             }
232             else
233             {
234                 URL base = new URL(basePath);
235                 return new URL(base, file);
236             }
237         }
238         catch (MalformedURLException uex)
239         {
240             return ConfigurationUtils.toURL(ConfigurationUtils.constructFile(basePath, file));
241         }
242     }
243 
244 
245     @Override
246     public URL locateFromURL(String basePath, String fileName)
247     {
248         try
249         {
250             URL url;
251             if (basePath == null)
252             {
253                 return new URL(fileName);
254                 //url = new URL(name);
255             }
256             else
257             {
258                 URL baseURL = new URL(basePath);
259                 url = new URL(baseURL, fileName);
260 
261                 // check if the file exists
262                 InputStream in = null;
263                 try
264                 {
265                     in = url.openStream();
266                 }
267                 finally
268                 {
269                     if (in != null)
270                     {
271                         in.close();
272                     }
273                 }
274                 return url;
275             }
276         }
277         catch (IOException e)
278         {
279             if (log.isDebugEnabled())
280             {
281                 log.debug("Could not locate file " + fileName + " at " + basePath + ": " + e.getMessage());
282             }
283             return null;
284         }
285     }
286 
287     /**
288      * Create the path to the specified file.
289      *
290      * @param file the target file
291      */
292     private void createPath(File file)
293     {
294         if (file != null)
295         {
296             // create the path to the file if the file doesn't exist
297             if (!file.exists())
298             {
299                 File parent = file.getParentFile();
300                 if (parent != null && !parent.exists())
301                 {
302                     parent.mkdirs();
303                 }
304             }
305         }
306     }
307     /**
308      * Wraps the output stream so errors can be detected in the HTTP response.
309      * @since 1.7
310      * @author <a
311      * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
312      */
313     private static class HttpOutputStream extends VerifiableOutputStream
314     {
315         /** The wrapped OutputStream */
316         private final OutputStream stream;
317 
318         /** The HttpURLConnection */
319         private final HttpURLConnection connection;
320 
321         public HttpOutputStream(OutputStream stream, HttpURLConnection connection)
322         {
323             this.stream = stream;
324             this.connection = connection;
325         }
326 
327         @Override
328         public void write(byte[] bytes) throws IOException
329         {
330             stream.write(bytes);
331         }
332 
333         @Override
334         public void write(byte[] bytes, int i, int i1) throws IOException
335         {
336             stream.write(bytes, i, i1);
337         }
338 
339         @Override
340         public void flush() throws IOException
341         {
342             stream.flush();
343         }
344 
345         @Override
346         public void close() throws IOException
347         {
348             stream.close();
349         }
350 
351         @Override
352         public void write(int i) throws IOException
353         {
354             stream.write(i);
355         }
356 
357         @Override
358         public String toString()
359         {
360             return stream.toString();
361         }
362 
363         @Override
364         public void verify() throws IOException
365         {
366             if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST)
367             {
368                 throw new IOException("HTTP Error " + connection.getResponseCode()
369                         + " " + connection.getResponseMessage());
370             }
371         }
372     }
373 }