DefaultFileSystem.java

  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.configuration2.io;

  18. import java.io.File;
  19. import java.io.FileNotFoundException;
  20. import java.io.FileOutputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.OutputStream;
  24. import java.net.HttpURLConnection;
  25. import java.net.MalformedURLException;
  26. import java.net.URL;
  27. import java.net.URLConnection;

  28. import org.apache.commons.configuration2.ex.ConfigurationException;

  29. /**
  30.  * FileSystem that uses java.io.File or HttpClient.
  31.  *
  32.  * @since 1.7
  33.  */
  34. public class DefaultFileSystem extends FileSystem {

  35.     /**
  36.      * Wraps the output stream so errors can be detected in the HTTP response.
  37.      *
  38.      * @since 1.7
  39.      */
  40.     private static final class HttpOutputStream extends VerifiableOutputStream {
  41.         /** The wrapped OutputStream */
  42.         private final OutputStream stream;

  43.         /** The HttpURLConnection */
  44.         private final HttpURLConnection connection;

  45.         public HttpOutputStream(final OutputStream stream, final HttpURLConnection connection) {
  46.             this.stream = stream;
  47.             this.connection = connection;
  48.         }

  49.         @Override
  50.         public void close() throws IOException {
  51.             stream.close();
  52.         }

  53.         @Override
  54.         public void flush() throws IOException {
  55.             stream.flush();
  56.         }

  57.         @Override
  58.         public String toString() {
  59.             return stream.toString();
  60.         }

  61.         @Override
  62.         public void verify() throws IOException {
  63.             if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
  64.                 throw new IOException("HTTP Error " + connection.getResponseCode() + " " + connection.getResponseMessage());
  65.             }
  66.         }

  67.         @Override
  68.         public void write(final byte[] bytes) throws IOException {
  69.             stream.write(bytes);
  70.         }

  71.         @Override
  72.         public void write(final byte[] bytes, final int i, final int i1) throws IOException {
  73.             stream.write(bytes, i, i1);
  74.         }

  75.         @Override
  76.         public void write(final int i) throws IOException {
  77.             stream.write(i);
  78.         }
  79.     }

  80.     /**
  81.      * Create the path to the specified file.
  82.      *
  83.      * @param file the target file
  84.      * @throws ConfigurationException if the path cannot be created
  85.      */
  86.     private void createPath(final File file) throws ConfigurationException {
  87.         // create the path to the file if the file doesn't exist
  88.         if (file != null && !file.exists()) {
  89.             final File parent = file.getParentFile();
  90.             if (parent != null && !parent.exists() && !parent.mkdirs()) {
  91.                 throw new ConfigurationException("Cannot create path: " + parent);
  92.             }
  93.         }
  94.     }

  95.     @Override
  96.     public String getBasePath(final String path) {
  97.         final URL url;
  98.         try {
  99.             url = getURL(null, path);
  100.             return FileLocatorUtils.getBasePath(url);
  101.         } catch (final Exception e) {
  102.             return null;
  103.         }
  104.     }

  105.     @Override
  106.     public String getFileName(final String path) {
  107.         final URL url;
  108.         try {
  109.             url = getURL(null, path);
  110.             return FileLocatorUtils.getFileName(url);
  111.         } catch (final Exception e) {
  112.             return null;
  113.         }
  114.     }

  115.     @Override
  116.     public InputStream getInputStream(final URL url) throws ConfigurationException {
  117.         return getInputStream(url, null);
  118.     }

  119.     @Override
  120.     public InputStream getInputStream(final URL url, final URLConnectionOptions urlConnectionOptions) throws ConfigurationException {
  121.         // throw an exception if the target URL is a directory
  122.         final File file = FileLocatorUtils.fileFromURL(url);
  123.         if (file != null && file.isDirectory()) {
  124.             throw new ConfigurationException("Cannot load a configuration from a directory");
  125.         }

  126.         try {
  127.             return urlConnectionOptions == null ? url.openStream() : urlConnectionOptions.openConnection(url).getInputStream();
  128.         } catch (final Exception e) {
  129.             throw new ConfigurationException("Unable to load the configuration from the URL " + url, e);
  130.         }
  131.     }

  132.     @Override
  133.     public OutputStream getOutputStream(final File file) throws ConfigurationException {
  134.         try {
  135.             // create the file if necessary
  136.             createPath(file);
  137.             return new FileOutputStream(file);
  138.         } catch (final FileNotFoundException e) {
  139.             throw new ConfigurationException("Unable to save to file " + file, e);
  140.         }
  141.     }

  142.     @Override
  143.     public OutputStream getOutputStream(final URL url) throws ConfigurationException {
  144.         // file URLs have to be converted to Files since FileURLConnection is
  145.         // read only (https://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4191800)
  146.         final File file = FileLocatorUtils.fileFromURL(url);
  147.         if (file != null) {
  148.             return getOutputStream(file);
  149.         }
  150.         // for non file URLs save through an URLConnection
  151.         OutputStream out;
  152.         try {
  153.             final URLConnection connection = url.openConnection();
  154.             connection.setDoOutput(true);

  155.             // use the PUT method for http URLs
  156.             if (connection instanceof HttpURLConnection) {
  157.                 final HttpURLConnection conn = (HttpURLConnection) connection;
  158.                 conn.setRequestMethod("PUT");
  159.             }

  160.             out = connection.getOutputStream();

  161.             // check the response code for http URLs and throw an exception if an error occurred
  162.             if (connection instanceof HttpURLConnection) {
  163.                 out = new HttpOutputStream(out, (HttpURLConnection) connection);
  164.             }
  165.             return out;
  166.         } catch (final IOException e) {
  167.             throw new ConfigurationException("Could not save to URL " + url, e);
  168.         }
  169.     }

  170.     @Override
  171.     public String getPath(final File file, final URL url, final String basePath, final String fileName) {
  172.         String path = null;
  173.         // if resource was loaded from jar file may be null
  174.         if (file != null) {
  175.             path = file.getAbsolutePath();
  176.         }

  177.         // try to see if file was loaded from a jar
  178.         if (path == null) {
  179.             if (url != null) {
  180.                 path = url.getPath();
  181.             } else {
  182.                 try {
  183.                     path = getURL(basePath, fileName).getPath();
  184.                 } catch (final Exception e) {
  185.                     // simply ignore it and return null
  186.                     if (getLogger().isDebugEnabled()) {
  187.                         getLogger().debug(String.format("Could not determine URL for " + "basePath = %s, fileName = %s: %s", basePath, fileName, e));
  188.                     }
  189.                 }
  190.             }
  191.         }

  192.         return path;
  193.     }

  194.     @Override
  195.     public URL getURL(final String basePath, final String file) throws MalformedURLException {
  196.         final File f = new File(file);
  197.         // already absolute?
  198.         if (f.isAbsolute()) {
  199.             return FileLocatorUtils.toURL(f);
  200.         }

  201.         try {
  202.             if (basePath == null) {
  203.                 return new URL(file);
  204.             }
  205.             final URL base = new URL(basePath);
  206.             return new URL(base, file);
  207.         } catch (final MalformedURLException uex) {
  208.             return FileLocatorUtils.toURL(FileLocatorUtils.constructFile(basePath, file));
  209.         }
  210.     }

  211.     @Override
  212.     public URL locateFromURL(final String basePath, final String fileName) {
  213.         try {
  214.             final URL url;
  215.             if (basePath == null) {
  216.                 return new URL(fileName);
  217.                 // url = new URL(name);
  218.             }
  219.             final URL baseURL = new URL(basePath);
  220.             url = new URL(baseURL, fileName);

  221.             // check if the file exists
  222.             try (InputStream in = url.openStream()) {
  223.                 // nothing
  224.                 in.available();
  225.             }
  226.             return url;
  227.         } catch (final IOException e) {
  228.             if (getLogger().isDebugEnabled()) {
  229.                 getLogger().debug("Could not locate file " + fileName + " at " + basePath + ": " + e.getMessage());
  230.             }
  231.             return null;
  232.         }
  233.     }
  234. }