001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.configuration; 018 019 import org.apache.commons.logging.Log; 020 import org.apache.commons.logging.LogFactory; 021 022 import java.io.InputStream; 023 import java.io.File; 024 import java.io.IOException; 025 import java.io.OutputStream; 026 import java.io.FileOutputStream; 027 import java.io.FileNotFoundException; 028 import java.net.URL; 029 import java.net.URLConnection; 030 import java.net.HttpURLConnection; 031 import java.net.MalformedURLException; 032 033 /** 034 * FileSystem that uses java.io.File or HttpClient 035 * @since 1.7 036 * @author <a 037 * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a> 038 */ 039 public class DefaultFileSystem extends FileSystem 040 { 041 /** 042 * The Log for diagnostic messages. 043 */ 044 private Log log = LogFactory.getLog(DefaultFileSystem.class); 045 046 public InputStream getInputStream(String basePath, String fileName) 047 throws ConfigurationException 048 { 049 try 050 { 051 URL url = ConfigurationUtils.locate(this, basePath, fileName); 052 053 if (url == null) 054 { 055 throw new ConfigurationException("Cannot locate configuration source " + fileName); 056 } 057 return getInputStream(url); 058 } 059 catch (ConfigurationException e) 060 { 061 throw e; 062 } 063 catch (Exception e) 064 { 065 throw new ConfigurationException("Unable to load the configuration file " + fileName, e); 066 } 067 } 068 069 public InputStream getInputStream(URL url) throws ConfigurationException 070 { 071 // throw an exception if the target URL is a directory 072 File file = ConfigurationUtils.fileFromURL(url); 073 if (file != null && file.isDirectory()) 074 { 075 throw new ConfigurationException("Cannot load a configuration from a directory"); 076 } 077 078 try 079 { 080 return url.openStream(); 081 } 082 catch (Exception e) 083 { 084 throw new ConfigurationException("Unable to load the configuration from the URL " + url, e); 085 } 086 } 087 088 public OutputStream getOutputStream(URL url) throws ConfigurationException 089 { 090 // file URLs have to be converted to Files since FileURLConnection is 091 // read only (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4191800) 092 File file = ConfigurationUtils.fileFromURL(url); 093 if (file != null) 094 { 095 return getOutputStream(file); 096 } 097 else 098 { 099 // for non file URLs save through an URLConnection 100 OutputStream out; 101 try 102 { 103 URLConnection connection = url.openConnection(); 104 connection.setDoOutput(true); 105 106 // use the PUT method for http URLs 107 if (connection instanceof HttpURLConnection) 108 { 109 HttpURLConnection conn = (HttpURLConnection) connection; 110 conn.setRequestMethod("PUT"); 111 } 112 113 out = connection.getOutputStream(); 114 115 // check the response code for http URLs and throw an exception if an error occured 116 if (connection instanceof HttpURLConnection) 117 { 118 out = new HttpOutputStream(out, (HttpURLConnection) connection); 119 } 120 return out; 121 } 122 catch (IOException e) 123 { 124 throw new ConfigurationException("Could not save to URL " + url, e); 125 } 126 } 127 } 128 129 public OutputStream getOutputStream(File file) throws ConfigurationException 130 { 131 try 132 { 133 // create the file if necessary 134 createPath(file); 135 return new FileOutputStream(file); 136 } 137 catch (FileNotFoundException e) 138 { 139 throw new ConfigurationException("Unable to save to file " + file, e); 140 } 141 } 142 143 public String getPath(File file, URL url, String basePath, String fileName) 144 { 145 String path = null; 146 // if resource was loaded from jar file may be null 147 if (file != null) 148 { 149 path = file.getAbsolutePath(); 150 } 151 152 // try to see if file was loaded from a jar 153 if (path == null) 154 { 155 if (url != null) 156 { 157 path = url.getPath(); 158 } 159 else 160 { 161 try 162 { 163 path = getURL(basePath, fileName).getPath(); 164 } 165 catch (Exception e) 166 { 167 // simply ignore it and return null 168 ; 169 } 170 } 171 } 172 173 return path; 174 } 175 176 public String getBasePath(String path) 177 { 178 URL url; 179 try 180 { 181 url = getURL(null, path); 182 return ConfigurationUtils.getBasePath(url); 183 } 184 catch (Exception e) 185 { 186 return null; 187 } 188 } 189 190 public String getFileName(String path) 191 { 192 URL url; 193 try 194 { 195 url = getURL(null, path); 196 return ConfigurationUtils.getFileName(url); 197 } 198 catch (Exception e) 199 { 200 return null; 201 } 202 } 203 204 205 public URL getURL(String basePath, String file) throws MalformedURLException 206 { 207 File f = new File(file); 208 if (f.isAbsolute()) // already absolute? 209 { 210 return ConfigurationUtils.toURL(f); 211 } 212 213 try 214 { 215 if (basePath == null) 216 { 217 return new URL(file); 218 } 219 else 220 { 221 URL base = new URL(basePath); 222 return new URL(base, file); 223 } 224 } 225 catch (MalformedURLException uex) 226 { 227 return ConfigurationUtils.toURL(ConfigurationUtils.constructFile(basePath, file)); 228 } 229 } 230 231 232 public URL locateFromURL(String basePath, String fileName) 233 { 234 try 235 { 236 URL url; 237 if (basePath == null) 238 { 239 return new URL(fileName); 240 //url = new URL(name); 241 } 242 else 243 { 244 URL baseURL = new URL(basePath); 245 url = new URL(baseURL, fileName); 246 247 // check if the file exists 248 InputStream in = null; 249 try 250 { 251 in = url.openStream(); 252 } 253 finally 254 { 255 if (in != null) 256 { 257 in.close(); 258 } 259 } 260 return url; 261 } 262 } 263 catch (IOException e) 264 { 265 if (log.isDebugEnabled()) 266 { 267 log.debug("Could not locate file " + fileName + " at " + basePath + ": " + e.getMessage()); 268 } 269 return null; 270 } 271 } 272 273 /** 274 * Create the path to the specified file. 275 * 276 * @param file the target file 277 */ 278 private void createPath(File file) 279 { 280 if (file != null) 281 { 282 // create the path to the file if the file doesn't exist 283 if (!file.exists()) 284 { 285 File parent = file.getParentFile(); 286 if (parent != null && !parent.exists()) 287 { 288 parent.mkdirs(); 289 } 290 } 291 } 292 } 293 /** 294 * Wraps the output stream so errors can be detected in the HTTP response. 295 * @since 1.7 296 * @author <a 297 * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a> 298 */ 299 private static class HttpOutputStream extends VerifiableOutputStream 300 { 301 /** The wrapped OutputStream */ 302 private final OutputStream stream; 303 304 /** The HttpURLConnection */ 305 private final HttpURLConnection connection; 306 307 public HttpOutputStream(OutputStream stream, HttpURLConnection connection) 308 { 309 this.stream = stream; 310 this.connection = connection; 311 } 312 313 public void write(byte[] bytes) throws IOException 314 { 315 stream.write(bytes); 316 } 317 318 public void write(byte[] bytes, int i, int i1) throws IOException 319 { 320 stream.write(bytes, i, i1); 321 } 322 323 public void flush() throws IOException 324 { 325 stream.flush(); 326 } 327 328 public void close() throws IOException 329 { 330 stream.close(); 331 } 332 333 public void write(int i) throws IOException 334 { 335 stream.write(i); 336 } 337 338 public String toString() 339 { 340 return stream.toString(); 341 } 342 343 public void verify() throws IOException 344 { 345 if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) 346 { 347 throw new IOException("HTTP Error " + connection.getResponseCode() 348 + " " + connection.getResponseMessage()); 349 } 350 } 351 } 352 }