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