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