    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    }