You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2012/09/28 19:54:34 UTC
svn commit: r1391574 - in /commons/proper/configuration/trunk/src:
main/java/org/apache/commons/configuration/
main/java/org/apache/commons/configuration/io/
test/java/org/apache/commons/configuration/io/
Author: oheger
Date: Fri Sep 28 17:54:34 2012
New Revision: 1391574
URL: http://svn.apache.org/viewvc?rev=1391574&view=rev
Log:
Started rework of file-based configurations:
- Added new FileBased interface
- Created FileHandler class which manages a location and a FileBased object
Added:
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java (with props)
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java (with props)
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java (with props)
Modified:
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ConfigurationUtils.java
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ConfigurationUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ConfigurationUtils.java?rev=1391574&r1=1391573&r2=1391574&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ConfigurationUtils.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ConfigurationUtils.java Fri Sep 28 17:54:34 2012
@@ -571,7 +571,7 @@ public final class ConfigurationUtils
* @param url the URL from which to extract the path
* @return the path component of the passed in URL
*/
- static String getBasePath(URL url)
+ public static String getBasePath(URL url)
{
if (url == null)
{
@@ -600,7 +600,7 @@ public final class ConfigurationUtils
* @param url the URL from which to extract the file name
* @return the extracted file name
*/
- static String getFileName(URL url)
+ public static String getFileName(URL url)
{
if (url == null)
{
@@ -721,7 +721,7 @@ public final class ConfigurationUtils
*
* @param file the file to be converted into an URL
*/
- static URL toURL(File file) throws MalformedURLException
+ public static URL toURL(File file) throws MalformedURLException
{
return file.toURI().toURL();
}
Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java?rev=1391574&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java (added)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java Fri Sep 28 17:54:34 2012
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.io;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+
+import org.apache.commons.configuration.ConfigurationException;
+
+/**
+ * <p>
+ * Definition of an interface to be implemented by objects which know how to
+ * read and write themselves from or to a character stream.
+ * </p>
+ * <p>
+ * This interface is implemented by special implementations of the
+ * {@code Configuration} interface which are associated with a file. It demands
+ * only basic methods for doing I/O based on character stream objects. Based on
+ * these methods it is possible to implement other methods which operate on
+ * files, file names, URLs, etc.
+ * </p>
+ *
+ * @version $Id$
+ */
+public interface FileBased
+{
+ /**
+ * Reads the content of this object from the given reader.
+ *
+ * @param in the reader
+ * @throws IOException if an I/O error occurs
+ * @throws ConfigurationException if a non-I/O related problem occurs, e.g.
+ * the data read does not have the expected format
+ */
+ void read(Reader in) throws ConfigurationException, IOException;
+
+ /**
+ * Writes the content of this object to the given writer.
+ *
+ * @param out the writer
+ * @throws IOException if an I/O error occurs
+ * @throws ConfigurationException if a non-I/O related problem occurs, e.g.
+ * the data read does not have the expected format
+ */
+ void write(Writer out) throws ConfigurationException, IOException;
+}
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileBased.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java?rev=1391574&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java (added)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java Fri Sep 28 17:54:34 2012
@@ -0,0 +1,1056 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.io;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.ConfigurationUtils;
+import org.apache.commons.configuration.FileSystem;
+
+/**
+ * <p>
+ * A class that manages persistence of an associated {@link FileBased} object.
+ * </p>
+ * <p>
+ * Instances of this class can be used to load and save arbitrary objects
+ * implementing the {@code FileBased} interface in a convenient way from and to
+ * various locations. At construction time the {@code FileBased} object to
+ * manage is passed in. Basically, this object is assigned a location from which
+ * it is loaded and to which it can be saved. The following possibilities exist
+ * to specify such a location:
+ * <ul>
+ * <li>URLs: With the method {@code setURL()} a full URL to the configuration
+ * source can be specified. This is the most flexible way. Note that the
+ * {@code save()} methods support only <em>file:</em> URLs.</li>
+ * <li>Files: The {@code setFile()} method allows to specify the configuration
+ * source as a file. This can be either a relative or an absolute file. In the
+ * former case the file is resolved based on the current directory.</li>
+ * <li>As file paths in string form: With the {@code setPath()} method a full
+ * path to a configuration file can be provided as a string.</li>
+ * <li>Separated as base path and file name: This is the native form in which
+ * the location is stored. The base path is a string defining either a local
+ * directory or a URL. It can be set using the {@code setBasePath()} method. The
+ * file name, non surprisingly, defines the name of the configuration file.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * An instance stores a location. The {@code load()} and {@code save()} methods
+ * that do not take an argument make use of this internal location.
+ * Alternatively, it is also possible to use overloaded variants of
+ * {@code load()} and {@code save()} which expect a location. In these cases the
+ * location specified takes precedence over the internal one; the internal
+ * location is not changed.
+ * </p>
+ * <p>
+ * This class is thread-safe.
+ * </p>
+ *
+ * @version $Id$
+ */
+public class FileHandler
+{
+ /** Constant for the URI scheme for files. */
+ private static final String FILE_SCHEME = "file:";
+
+ /** Constant for the URI scheme for files with slashes. */
+ private static final String FILE_SCHEME_SLASH = FILE_SCHEME + "//";
+
+ /** The file-based object managed by this handler. */
+ private final FileBased content;
+
+ /** Stores the location of the associated file. */
+ private final FileSpec fileSpec;
+
+ /**
+ * Creates a new instance of {@code FileHandler} which is not associated
+ * with a {@code FileBased} object and thus does not have a content. Objects
+ * of this kind can be used to define a file location, but it is not
+ * possible to actually load or save data.
+ */
+ public FileHandler()
+ {
+ this(null);
+ }
+
+ /**
+ * Creates a new instance of {@code FileHandler} and sets the managed
+ * {@code FileBased} object.
+ *
+ * @param obj the file-based object to manage
+ */
+ public FileHandler(FileBased obj)
+ {
+ content = obj;
+ fileSpec = new FileSpec();
+ }
+
+ /**
+ * Creates a new instance of {@code FileHandler} which is associated with
+ * the given {@code FileBased} object and the location defined for the given
+ * {@code FileHandler} object. A copy of the location of the given
+ * {@code FileHandler} is created. This constructor is a possibility to
+ * associate a file location with a {@code FileBased} object.
+ *
+ * @param obj the {@code FileBased} object to manage
+ * @param c the {@code FileHandler} from which to copy the location (must
+ * not be <b>null</b>)
+ * @throws IllegalArgumentException if the {@code FileHandler} is
+ * <b>null</b>
+ */
+ public FileHandler(FileBased obj, FileHandler c)
+ {
+ content = obj;
+ fileSpec = c.snapshotFileSpec();
+ }
+
+ /**
+ * Returns the {@code FileBased} object associated with this
+ * {@code FileHandler}.
+ *
+ * @return the associated {@code FileBased} object
+ */
+ public final FileBased getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Return the name of the file.
+ *
+ * @return the file name
+ */
+ public String getFileName()
+ {
+ synchronized (fileSpec)
+ {
+ return fileSpec.getFileName();
+ }
+ }
+
+ /**
+ * Set the name of the file. The passed in file name can contain a relative
+ * path. It must be used when referring files with relative paths from
+ * classpath. Use {@code setPath()} to set a full qualified file name.
+ *
+ * @param fileName the name of the file
+ */
+ public void setFileName(String fileName)
+ {
+ String name = normalizeFileURL(fileName);
+ synchronized (fileSpec)
+ {
+ fileSpec.setFileName(name);
+ fileSpec.setSourceURL(null);
+ }
+ }
+
+ /**
+ * Return the base path.
+ *
+ * @return the base path
+ */
+ public String getBasePath()
+ {
+ synchronized (fileSpec)
+ {
+ return fileSpec.getBasePath();
+ }
+ }
+
+ /**
+ * Sets the base path. The base path is typically either a path to a
+ * directory or a URL. Together with the value passed to the
+ * {@code setFileName()} method it defines the location of the configuration
+ * file to be loaded. The strategies for locating the file are quite
+ * tolerant. For instance if the file name is already an absolute path or a
+ * fully defined URL, the base path will be ignored. The base path can also
+ * be a URL, in which case the file name is interpreted in this URL's
+ * context. If other methods are used for determining the location of the
+ * associated file (e.g. {@code setFile()} or {@code setURL()}), the base
+ * path is automatically set.
+ *
+ * @param basePath the base path.
+ */
+ public void setBasePath(String basePath)
+ {
+ String path = normalizeFileURL(basePath);
+ synchronized (fileSpec)
+ {
+ fileSpec.setBasePath(path);
+ fileSpec.setSourceURL(null);
+ }
+ }
+
+ /**
+ * Returns the location of the associated file as a {@code File} object. If
+ * the base path is a URL with a protocol different than "file",
+ * or the file is within a compressed archive, the return value will not
+ * point to a valid file object.
+ *
+ * @return the location as {@code File} object; this can be <b>null</b>
+ */
+ public File getFile()
+ {
+ String fileName;
+ String basePath;
+ URL sourceURL;
+
+ synchronized (fileSpec)
+ {
+ fileName = fileSpec.getFileName();
+ basePath = fileSpec.getBasePath();
+ sourceURL = fileSpec.getSourceURL();
+ }
+
+ if (fileName == null && sourceURL == null)
+ {
+ return null;
+ }
+ else if (sourceURL != null)
+ {
+ return ConfigurationUtils.fileFromURL(sourceURL);
+ }
+ else
+ {
+ return ConfigurationUtils.getFile(basePath, fileName);
+ }
+ }
+
+ /**
+ * Sets the location of the associated file as a {@code File} object. The
+ * passed in {@code File} is made absolute if it is not yet. Then the file's
+ * path component becomes the base path and its name component becomes the
+ * file name.
+ *
+ * @param file the location of the associated file
+ */
+ public void setFile(File file)
+ {
+ synchronized (fileSpec)
+ {
+ fileSpec.setFileName(file.getName());
+ fileSpec.setBasePath((file.getParentFile() != null) ? file
+ .getParentFile().getAbsolutePath() : null);
+ fileSpec.setSourceURL(null);
+ }
+ }
+
+ /**
+ * Returns the full path to the associated file. The return value is a valid
+ * {@code File} path only if this location is based on a file on the local
+ * disk. If the file was loaded from a packed archive, the returned value is
+ * the string form of the URL from which the file was loaded.
+ *
+ * @return the full path to the associated file
+ */
+ public String getPath()
+ {
+ FileSpec spec;
+ File file;
+ synchronized (fileSpec)
+ {
+ spec = snapshotFileSpec();
+ file = getFile();
+ }
+
+ return spec.getFileSystem().getPath(file, spec.getSourceURL(),
+ spec.getBasePath(), spec.getFileName());
+ }
+
+ /**
+ * Sets the location of the associated file as a full or relative path name.
+ * The passed in path should represent a valid file name on the file system.
+ * It must not be used to specify relative paths for files that exist in
+ * classpath, either plain file system or compressed archive, because this
+ * method expands any relative path to an absolute one which may end in an
+ * invalid absolute path for classpath references.
+ *
+ * @param path the full path name of the associated file
+ */
+ public void setPath(String path)
+ {
+ setFile(new File(path));
+ }
+
+ /**
+ * Returns the location of the associated file as a URL.
+ *
+ * @return a URL to the associated file; can be <b>null</b> if the location
+ * is unspecified
+ */
+ public URL getURL()
+ {
+ URL sourceURL;
+ FileSystem fileSystem;
+ String basePath;
+ String fileName;
+ synchronized (fileSpec)
+ {
+ sourceURL = fileSpec.getSourceURL();
+ fileSystem = fileSpec.getFileSystem();
+ basePath = fileSpec.getBasePath();
+ fileName = fileSpec.getFileName();
+ }
+
+ return (sourceURL != null) ? sourceURL : ConfigurationUtils.locate(
+ fileSystem, basePath, fileName);
+ }
+
+ /**
+ * Sets the location of the associated file as a URL. For loading this can
+ * be an arbitrary URL with a supported protocol. If the file is to be
+ * saved, too, a URL with the "file" protocol should be provided.
+ *
+ * @param url the location of the file as URL
+ */
+ public void setURL(URL url)
+ {
+ String basePath = ConfigurationUtils.getBasePath(url);
+ String fileName = ConfigurationUtils.getFileName(url);
+ synchronized (fileSpec)
+ {
+ fileSpec.setBasePath(basePath);
+ fileSpec.setFileName(fileName);
+ fileSpec.setSourceURL(url);
+ }
+ }
+
+ /**
+ * Returns the encoding of the associated file. Result can be <b>null</b> if
+ * no encoding has been set.
+ *
+ * @return the encoding of the associated file
+ */
+ public String getEncoding()
+ {
+ synchronized (fileSpec)
+ {
+ return fileSpec.getEncoding();
+ }
+ }
+
+ /**
+ * Sets the encoding of the associated file. The encoding applies if binary
+ * files are loaded.
+ *
+ * @param encoding the encoding of the associated file
+ */
+ public void setEncoding(String encoding)
+ {
+ synchronized (fileSpec)
+ {
+ fileSpec.setEncoding(encoding);
+ }
+ }
+
+ /**
+ * Returns the {@code FileSystem} to be used by this object when locating
+ * files. Result is never <b>null</b>; if no file system has been set, the
+ * default file system is returned.
+ *
+ * @return the used {@code FileSystem}
+ */
+ public FileSystem getFileSystem()
+ {
+ synchronized (fileSpec)
+ {
+ return fileSpec.getFileSystem();
+ }
+ }
+
+ /**
+ * Sets the {@code FileSystem} to be used by this object when locating
+ * files. If a <b>null</b> value is passed in, the file system is reset to
+ * the default file system.
+ *
+ * @param fileSystem the {@code FileSystem}
+ */
+ public void setFileSystem(FileSystem fileSystem)
+ {
+ FileSystem fs =
+ (fileSystem != null) ? fileSystem : FileSystem
+ .getDefaultFileSystem();
+ synchronized (fileSpec)
+ {
+ fileSpec.setFileSystem(fs);
+ }
+ }
+
+ /**
+ * Resets the {@code FileSystem} used by this object. It is set to the
+ * default file system.
+ */
+ public void resetFileSystem()
+ {
+ setFileSystem(null);
+ }
+
+ /**
+ * Loads the associated file from the underlying location. If no location
+ * has been set, an exception is thrown.
+ *
+ * @throws ConfigurationException if loading of the configuration fails
+ */
+ public void load() throws ConfigurationException
+ {
+ load(checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Loads the associated file from the given file name. The file name is
+ * interpreted in the context of the already set location (e.g. if it is a
+ * relative file name, a base path is applied if available). The underlying
+ * location is not changed.
+ *
+ * @param fileName the name of the file to be loaded
+ * @throws ConfigurationException if an error occurs
+ */
+ public void load(String fileName) throws ConfigurationException
+ {
+ load(fileName, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Loads the associated file from the specified {@code File}.
+ *
+ * @param file the file to load
+ * @throws ConfigurationException if an error occurs
+ */
+ public void load(File file) throws ConfigurationException
+ {
+ URL url;
+ try
+ {
+ url = ConfigurationUtils.toURL(file);
+ }
+ catch (MalformedURLException e1)
+ {
+ throw new ConfigurationException("Cannot create URL from file "
+ + file);
+ }
+
+ load(url);
+ }
+
+ /**
+ * Loads the associated file from the specified URL. The location stored in
+ * this object is not changed.
+ *
+ * @param url the URL of the file to be loaded
+ * @throws ConfigurationException if an error occurs
+ */
+ public void load(URL url) throws ConfigurationException
+ {
+ load(url, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Loads the associated file from the specified stream, using the encoding
+ * returned by {@link #getEncoding()}.
+ *
+ * @param in the input stream
+ * @throws ConfigurationException if an error occurs during the load
+ * operation
+ */
+ public void load(InputStream in) throws ConfigurationException
+ {
+ load(in, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Loads the associated file from the specified stream, using the specified
+ * encoding. If the encoding is <b>null</b>, the default encoding is used.
+ *
+ * @param in the input stream
+ * @param encoding the encoding used, {@code null} to use the default
+ * encoding
+ * @throws ConfigurationException if an error occurs during the load
+ * operation
+ */
+ public void load(InputStream in, String encoding)
+ throws ConfigurationException
+ {
+ checkContent();
+ Reader reader = null;
+
+ if (encoding != null)
+ {
+ try
+ {
+ reader = new InputStreamReader(in, encoding);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new ConfigurationException(
+ "The requested encoding is not supported, try the default encoding.",
+ e);
+ }
+ }
+
+ if (reader == null)
+ {
+ reader = new InputStreamReader(in);
+ }
+
+ loadFromReader(reader);
+ }
+
+ /**
+ * Loads the associated file from the specified reader.
+ *
+ * @param in the reader
+ * @throws ConfigurationException if an error occurs during the load
+ * operation
+ */
+ public void load(Reader in) throws ConfigurationException
+ {
+ checkContent();
+ loadFromReader(in);
+ }
+
+ /**
+ * Saves the associated file to the current location set for this object.
+ * Before this method can be called a valid location must have been set.
+ *
+ * @throws ConfigurationException if an error occurs or no location has been
+ * set yet
+ */
+ public void save() throws ConfigurationException
+ {
+ save(checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Saves the associated file to the specified file name. This does not
+ * change the location of this object (use {@link #setFileName(String)} if
+ * you need it).
+ *
+ * @param fileName the file name
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ public void save(String fileName) throws ConfigurationException
+ {
+ save(fileName, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Saves the associated file to the specified URL. This does not change the
+ * location of this object (use {@link #setURL(URL)} if you need it).
+ *
+ * @param url the URL
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ public void save(URL url) throws ConfigurationException
+ {
+ save(url, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Saves the associated file to the specified {@code File}. The file is
+ * created automatically if it doesn't exist. This does not change the
+ * location of this object (use {@link #setFile} if you need it).
+ *
+ * @param file the target file
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ public void save(File file) throws ConfigurationException
+ {
+ save(file, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Saves the associated file to the specified stream using the encoding
+ * returned by {@link #getEncoding()}.
+ *
+ * @param out the output stream
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ public void save(OutputStream out) throws ConfigurationException
+ {
+ save(out, checkContentAndCreateSnapshotFileSpec());
+ }
+
+ /**
+ * Saves the associated file to the specified stream using the specified
+ * encoding. If the encoding is <b>null</b>, the default encoding is used.
+ *
+ * @param out the output stream
+ * @param encoding the encoding to be used, {@code null} to use the default
+ * encoding
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ public void save(OutputStream out, String encoding)
+ throws ConfigurationException
+ {
+ checkContent();
+ Writer writer = null;
+
+ if (encoding != null)
+ {
+ try
+ {
+ writer = new OutputStreamWriter(out, encoding);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new ConfigurationException(
+ "The requested encoding is not supported, try the default encoding.",
+ e);
+ }
+ }
+
+ if (writer == null)
+ {
+ writer = new OutputStreamWriter(out);
+ }
+
+ saveToWriter(writer);
+ }
+
+ /**
+ * Saves the associated file to the given {@code Writer}.
+ *
+ * @param out the {@code Writer}
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ public void save(Writer out) throws ConfigurationException
+ {
+ checkContent();
+ saveToWriter(out);
+ }
+
+ /**
+ * Internal helper method for loading the associated file from the location
+ * specified in the given {@code FileSpec}.
+ *
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs
+ */
+ private void load(FileSpec spec) throws ConfigurationException
+ {
+ if (spec.getSourceURL() != null)
+ {
+ load(spec.getSourceURL(), spec);
+ }
+ else
+ {
+ load(spec.getFileName(), spec);
+ }
+ }
+
+ /**
+ * Internal helper method for loading a file from the given URL.
+ *
+ * @param url the URL
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs
+ */
+ private void load(URL url, FileSpec spec) throws ConfigurationException
+ {
+ InputStream in = null;
+
+ try
+ {
+ in = spec.getFileSystem().getInputStream(url);
+ load(in, spec);
+ }
+ catch (ConfigurationException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException(
+ "Unable to load the configuration from the URL " + url, e);
+ }
+ finally
+ {
+ closeSilent(in);
+ }
+ }
+
+ /**
+ * Internal helper method for loading a file from a file name.
+ *
+ * @param fileName the file name
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs
+ */
+ private void load(String fileName, FileSpec spec)
+ throws ConfigurationException
+ {
+ URL url =
+ ConfigurationUtils.locate(spec.getFileSystem(),
+ spec.getBasePath(), fileName);
+
+ if (url == null)
+ {
+ throw new ConfigurationException(
+ "Cannot locate configuration source " + fileName);
+ }
+ load(url);
+ }
+
+ /**
+ * Internal helper method for loading a file from the given input stream.
+ *
+ * @param in the input stream
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs
+ */
+ private void load(InputStream in, FileSpec spec)
+ throws ConfigurationException
+ {
+ load(in, spec.getEncoding());
+ }
+
+ /**
+ * Internal helper method for loading a file from the given reader.
+ *
+ * @param in the reader
+ * @throws ConfigurationException if an error occurs
+ */
+ private void loadFromReader(Reader in) throws ConfigurationException
+ {
+ try
+ {
+ getContent().read(in);
+ }
+ catch (IOException ioex)
+ {
+ throw new ConfigurationException(ioex);
+ }
+ }
+
+ /**
+ * Internal helper method for saving data to the internal location stored
+ * for this object.
+ *
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ private void save(FileSpec spec) throws ConfigurationException
+ {
+ if (spec.getFileName() == null)
+ {
+ throw new ConfigurationException("No file name has been set!");
+ }
+
+ if (spec.getSourceURL() != null)
+ {
+ save(spec.getSourceURL(), spec);
+ }
+ else
+ {
+ save(spec.getFileName(), spec);
+ }
+ }
+
+ /**
+ * Internal helper method for saving data to the given file name.
+ *
+ * @param fileName the path to the target file
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ private void save(String fileName, FileSpec spec)
+ throws ConfigurationException
+ {
+ URL url;
+ try
+ {
+ url = spec.getFileSystem().getURL(spec.getBasePath(), fileName);
+ }
+ catch (MalformedURLException e)
+ {
+ throw new ConfigurationException(e);
+ }
+
+ if (url == null)
+ {
+ throw new ConfigurationException(
+ "Cannot locate configuration source " + fileName);
+ }
+ save(url, spec);
+ }
+
+ /**
+ * Internal helper method for saving data to the given URL.
+ *
+ * @param url the target URL
+ * @param spec the {@code FileSpec}
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ private void save(URL url, FileSpec spec) throws ConfigurationException
+ {
+ OutputStream out = null;
+ try
+ {
+ out = spec.getFileSystem().getOutputStream(url);
+ save(out, spec);
+ }
+ finally
+ {
+ closeSilent(out);
+ }
+ }
+
+ /**
+ * Internal helper method for saving data to the given {@code File}.
+ *
+ * @param file the target file
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ private void save(File file, FileSpec spec) throws ConfigurationException
+ {
+ OutputStream out = null;
+
+ try
+ {
+ out = spec.getFileSystem().getOutputStream(file);
+ save(out, spec);
+ }
+ finally
+ {
+ closeSilent(out);
+ }
+ }
+
+ /**
+ * Internal helper method for saving a file to the given output stream.
+ *
+ * @param out the output stream
+ * @param spec the current {@code FileSpec}
+ * @throws ConfigurationException if an error occurs during the save
+ * operation
+ */
+ private void save(OutputStream out, FileSpec spec)
+ throws ConfigurationException
+ {
+ save(out, spec.getEncoding());
+ }
+
+ /**
+ * Internal helper method for saving a file into the given writer.
+ *
+ * @param out the writer
+ * @throws ConfigurationException if an error occurs
+ */
+ private void saveToWriter(Writer out) throws ConfigurationException
+ {
+ try
+ {
+ getContent().write(out);
+ }
+ catch (IOException ioex)
+ {
+ throw new ConfigurationException(ioex);
+ }
+ }
+
+ /**
+ * Creates a snapshot of the current location data of the associated file.
+ * This snapshot can be used in code which does not have to synchronize on
+ * the internal {@code FileSpec} object.
+ *
+ * @return a snapshot of the current file location
+ */
+ private FileSpec snapshotFileSpec()
+ {
+ synchronized (fileSpec)
+ {
+ return fileSpec.clone();
+ }
+ }
+
+ /**
+ * Checks whether a content object is available. If not, an exception is
+ * thrown. This method is called whenever the content object is accessed.
+ *
+ * @throws ConfigurationException if not content object is defined
+ */
+ private void checkContent() throws ConfigurationException
+ {
+ if (getContent() == null)
+ {
+ throw new ConfigurationException("No content available!");
+ }
+ }
+
+ /**
+ * Checks whether a content object is available and creates a snapshot from
+ * the current file specification. If there is no content object, an
+ * exception is thrown. This is a typical operation to be performed before a
+ * load() or save() operation.
+ *
+ * @return a snapshot of the current file location
+ */
+ private FileSpec checkContentAndCreateSnapshotFileSpec()
+ throws ConfigurationException
+ {
+ checkContent();
+ return snapshotFileSpec();
+ }
+
+ /**
+ * Normalizes URLs to files. Ensures that file URLs start with the correct
+ * protocol.
+ *
+ * @param fileName the string to be normalized
+ * @return the normalized file URL
+ */
+ private static String normalizeFileURL(String fileName)
+ {
+ if (fileName != null && fileName.startsWith(FILE_SCHEME)
+ && !fileName.startsWith(FILE_SCHEME_SLASH))
+ {
+ fileName =
+ FILE_SCHEME_SLASH
+ + fileName.substring(FILE_SCHEME.length());
+ }
+ return fileName;
+ }
+
+ /**
+ * A helper method for closing a stream. Occurring exceptions will be
+ * ignored.
+ *
+ * @param cl the stream to be closed (may be <b>null</b>)
+ */
+ private static void closeSilent(Closeable cl)
+ {
+ try
+ {
+ if (cl != null)
+ {
+ cl.close();
+ }
+ }
+ catch (IOException e)
+ {
+ // ignore
+ }
+ }
+
+ /**
+ * A bean class defining the location of a file.
+ */
+ private static class FileSpec implements Cloneable
+ {
+ /** Stores the file name. */
+ private String fileName;
+
+ /** Stores the base path. */
+ private String basePath;
+
+ /** Stores the URL of the associated file. */
+ private URL sourceURL;
+
+ /** Stores the encoding for binary streams. */
+ private String encoding;
+
+ /** The FileSystem being used for this Configuration */
+ private FileSystem fileSystem = FileSystem.getDefaultFileSystem();
+
+ public String getFileName()
+ {
+ return fileName;
+ }
+
+ public void setFileName(String fileName)
+ {
+ this.fileName = fileName;
+ }
+
+ public String getBasePath()
+ {
+ return basePath;
+ }
+
+ public void setBasePath(String basePath)
+ {
+ this.basePath = basePath;
+ }
+
+ public URL getSourceURL()
+ {
+ return sourceURL;
+ }
+
+ public void setSourceURL(URL sourceURL)
+ {
+ this.sourceURL = sourceURL;
+ }
+
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding)
+ {
+ this.encoding = encoding;
+ }
+
+ public FileSystem getFileSystem()
+ {
+ return fileSystem;
+ }
+
+ public void setFileSystem(FileSystem fileSystem)
+ {
+ this.fileSystem = fileSystem;
+ }
+
+ @Override
+ protected FileSpec clone()
+ {
+ try
+ {
+ return (FileSpec) super.clone();
+ }
+ catch (CloneNotSupportedException cex)
+ {
+ // should not happen
+ throw new AssertionError("Could not clone!");
+ }
+ }
+ }
+}
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java?rev=1391574&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java (added)
+++ commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java Fri Sep 28 17:54:34 2012
@@ -0,0 +1,790 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.configuration.ConfigurationAssert;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.FileSystem;
+import org.easymock.EasyMock;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Test class for {@code FileHandler}.
+ *
+ * @version $Id$
+ */
+public class TestFileHandler
+{
+ /** Constant for the name of a test file. */
+ private static final String TEST_FILENAME = "test.properties";
+
+ /** Constant for content of the test file. */
+ private static final String CONTENT =
+ "TestFileHandler: This is test content.";
+
+ /** Helper object for managing temporary files. */
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ /**
+ * Creates a test file test content and allows specifying a file name.
+ *
+ * @param f the file to be created (may be <b>null</b>)
+ * @return the File object pointing to the test file
+ */
+ private File createTestFile(File f)
+ {
+ Writer out = null;
+ File file = f;
+ try
+ {
+ if (file == null)
+ {
+ file = folder.newFile();
+ }
+ out = new FileWriter(file);
+ out.write(CONTENT);
+ }
+ catch (IOException ioex)
+ {
+ fail("Could not create test file: " + ioex);
+ return null; // cannot happen
+ }
+ finally
+ {
+ if (out != null)
+ {
+ try
+ {
+ out.close();
+ }
+ catch (IOException ioex)
+ {
+ // ignore
+ }
+ }
+ }
+ return file;
+ }
+
+ /**
+ * Creates a test file with the test content.
+ *
+ * @return the File object pointing to the test file
+ */
+ private File createTestFile()
+ {
+ return createTestFile(null);
+ }
+
+ /**
+ * Reads the content of the specified reader into a string.
+ *
+ * @param in the reader
+ * @return the read content
+ * @throws IOException if an error occurs
+ */
+ private static String readReader(Reader in) throws IOException
+ {
+ StringBuilder buf = new StringBuilder();
+ int c;
+ while ((c = in.read()) != -1)
+ {
+ buf.append((char) c);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Reads the content of the specified file into a string
+ *
+ * @param f the file to be read
+ * @return the content of this file
+ */
+ private static String readFile(File f)
+ {
+ Reader in = null;
+ try
+ {
+ in = new FileReader(f);
+ return readReader(in);
+ }
+ catch (IOException ioex)
+ {
+ fail("Could not read file: " + ioex);
+ return null; // cannot happen
+ }
+ finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch (IOException ioex)
+ {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests whether a newly created instance has a default file system.
+ */
+ @Test
+ public void testGetFileSystemDefault()
+ {
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ assertEquals("Wrong default file system",
+ FileSystem.getDefaultFileSystem(), handler.getFileSystem());
+ }
+
+ /**
+ * Tests whether a null file system can be set to reset this property.
+ */
+ @Test
+ public void testSetFileSystemNull()
+ {
+ FileSystem sys = EasyMock.createMock(FileSystem.class);
+ EasyMock.replay(sys);
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setFileSystem(sys);
+ assertSame("File system not set", sys, handler.getFileSystem());
+ handler.setFileSystem(null);
+ assertEquals("Not default file system",
+ FileSystem.getDefaultFileSystem(), handler.getFileSystem());
+ }
+
+ /**
+ * Tests whether the file system can be reset.
+ */
+ @Test
+ public void testResetFileSystem()
+ {
+ FileSystem sys = EasyMock.createMock(FileSystem.class);
+ EasyMock.replay(sys);
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setFileSystem(sys);
+ handler.resetFileSystem();
+ assertEquals("Not default file system",
+ FileSystem.getDefaultFileSystem(), handler.getFileSystem());
+ }
+
+ /**
+ * Tests whether a URL can be set.
+ */
+ @Test
+ public void testSetURL() throws Exception
+ {
+ FileHandler handler = new FileHandler();
+ handler.setURL(new URL(
+ "http://commons.apache.org/configuration/index.html"));
+
+ assertEquals("base path", "http://commons.apache.org/configuration/",
+ handler.getBasePath());
+ assertEquals("file name", "index.html", handler.getFileName());
+
+ // file URL - This url is invalid, a valid url would be
+ // file:///temp/test.properties.
+ handler.setURL(new URL("file:/temp/test.properties"));
+ assertEquals("base path", "file:///temp/", handler.getBasePath());
+ assertEquals("file name", TEST_FILENAME, handler.getFileName());
+ }
+
+ /**
+ * Tests whether a URL with parameters can be set.
+ */
+ @Test
+ public void testSetURLWithParams() throws Exception
+ {
+ FileHandler handler = new FileHandler();
+ URL url =
+ new URL(
+ "http://issues.apache.org/bugzilla/show_bug.cgi?id=37886");
+ handler.setURL(url);
+ assertEquals("Base path incorrect",
+ "http://issues.apache.org/bugzilla/", handler.getBasePath());
+ assertEquals("File name incorrect", "show_bug.cgi",
+ handler.getFileName());
+ assertEquals("URL was not correctly stored", url, handler.getURL());
+ }
+
+ /**
+ * Tests whether the location can be set as a file.
+ */
+ @Test
+ public void testSetFile()
+ {
+ FileHandler handler = new FileHandler();
+ File directory = ConfigurationAssert.TEST_DIR;
+ File file = ConfigurationAssert.getTestFile(TEST_FILENAME);
+ handler.setFile(file);
+ assertEquals("Wrong base path", directory.getAbsolutePath(),
+ handler.getBasePath());
+ assertEquals("Wrong file name", TEST_FILENAME, handler.getFileName());
+ assertEquals("Wrong path", file.getAbsolutePath(), handler.getPath());
+ }
+
+ /**
+ * Tests whether the location can be set as a file.
+ */
+ @Test
+ public void testSetPath() throws MalformedURLException
+ {
+ FileHandler config = new FileHandler();
+ config.setPath(ConfigurationAssert.TEST_DIR_NAME + File.separator
+ + TEST_FILENAME);
+ assertEquals("Wrong file name", TEST_FILENAME, config.getFileName());
+ assertEquals("Wrong base path",
+ ConfigurationAssert.TEST_DIR.getAbsolutePath(),
+ config.getBasePath());
+ File file = ConfigurationAssert.getTestFile(TEST_FILENAME);
+ assertEquals("Wrong path", file.getAbsolutePath(), config.getPath());
+ assertEquals("Wrong URL", file.toURI().toURL(), config.getURL());
+ }
+
+ /**
+ * Tests whether the location can be set using file name and base path.
+ */
+ @Test
+ public void testSetFileName()
+ {
+ FileHandler config = new FileHandler();
+ config.setBasePath(null);
+ config.setFileName(TEST_FILENAME);
+ assertNull("Got a base path", config.getBasePath());
+ assertEquals("Wrong file name", TEST_FILENAME, config.getFileName());
+ }
+
+ /**
+ * Tries to call a load() method if no content object is available.
+ */
+ @Test(expected = ConfigurationException.class)
+ public void testLoadNoContent() throws ConfigurationException
+ {
+ FileHandler handler = new FileHandler();
+ StringReader reader = new StringReader(CONTENT);
+ handler.load(reader);
+ }
+
+ /**
+ * Tests whether an IOException is handled when loading data from a reader.
+ */
+ @Test
+ public void testLoadFromReaderIOException() throws IOException,
+ ConfigurationException
+ {
+ FileBased content = EasyMock.createMock(FileBased.class);
+ Reader in = new StringReader(CONTENT);
+ IOException ioex = new IOException("Test exception");
+ content.read(in);
+ EasyMock.expectLastCall().andThrow(ioex);
+ EasyMock.replay(content);
+ FileHandler handler = new FileHandler(content);
+ try
+ {
+ handler.load(in);
+ fail("IOException not detected!");
+ }
+ catch (ConfigurationException cex)
+ {
+ assertEquals("Wrong root cause", ioex, cex.getCause());
+ }
+ EasyMock.verify(content);
+ }
+
+ /**
+ * Tests whether data from a File can be loaded.
+ */
+ @Test
+ public void testLoadFromFile() throws ConfigurationException
+ {
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ File file = createTestFile();
+ FileHandler handler = new FileHandler(content);
+ handler.load(file);
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tries to load data from a File if no content object was set.
+ */
+ @Test
+ public void testLoadFromFileNoContent() throws ConfigurationException
+ {
+ FileHandler handler = new FileHandler();
+ File file = createTestFile();
+ try
+ {
+ handler.load(file);
+ fail("Missing content not detected!");
+ }
+ catch (ConfigurationException cex)
+ {
+ assertEquals("Wrong message", "No content available!",
+ cex.getMessage());
+ }
+ }
+
+ /**
+ * Checks that loading a directory instead of a file throws an exception.
+ */
+ @Test(expected = ConfigurationException.class)
+ public void testLoadDirectoryString() throws ConfigurationException
+ {
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.load(ConfigurationAssert.TEST_DIR.getAbsolutePath());
+ }
+
+ /**
+ * Tests that it is not possible to load a directory using the load() method
+ * which expects a File.
+ */
+ @Test(expected = ConfigurationException.class)
+ public void testLoadDirectoryFile() throws ConfigurationException
+ {
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.load(ConfigurationAssert.TEST_DIR);
+ }
+
+ /**
+ * Tests whether whether data can be loaded from class path.
+ */
+ @Test
+ public void testLoadFromClassPath() throws ConfigurationException
+ {
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler config1 = new FileHandler(content);
+ config1.setFileName("config/deep/deeptest.properties");
+ config1.load();
+ assertTrue("No data loaded", content.getContent().length() > 0);
+ }
+
+ /**
+ * Tests whether data from a URL can be loaded.
+ */
+ @Test
+ public void testLoadFromURL() throws Exception
+ {
+ File file = createTestFile();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ handler.load(file.toURI().toURL());
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tests whether data from an absolute path can be loaded.
+ */
+ @Test
+ public void testLoadFromFilePath() throws ConfigurationException
+ {
+ File file = createTestFile();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ handler.load(file.getAbsolutePath());
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tests whether data from an input stream can be read.
+ */
+ @Test
+ public void testLoadFromStream() throws Exception
+ {
+ File file = createTestFile();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ FileInputStream in = new FileInputStream(file);
+ try
+ {
+ handler.load(in);
+ }
+ finally
+ {
+ in.close();
+ }
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tests whether data from a reader can be read.
+ */
+ @Test
+ public void testLoadFromReader() throws Exception
+ {
+ File file = createTestFile();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ Reader in = new FileReader(file);
+ try
+ {
+ handler.load(in);
+ }
+ finally
+ {
+ in.close();
+ }
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tests a load operation using the current location which is a URL.
+ */
+ @Test
+ public void testLoadFromURLLocation() throws Exception
+ {
+ File file = createTestFile();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ handler.setURL(file.toURI().toURL());
+ handler.load();
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tests a load operation using the current location which is a file name.
+ */
+ @Test
+ public void testLoadFromFileNameLocation() throws ConfigurationException
+ {
+ File file = createTestFile();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ handler.setBasePath(file.getParentFile().getAbsolutePath());
+ handler.setFileName(file.getName());
+ handler.load();
+ assertEquals("Wrong content", CONTENT, content.getContent());
+ }
+
+ /**
+ * Tries to load data if no location has been set.
+ */
+ @Test(expected = ConfigurationException.class)
+ public void testLoadNoLocation() throws ConfigurationException
+ {
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ handler.load();
+ }
+
+ /**
+ * Tests whether data can be saved into a Writer.
+ */
+ @Test
+ public void testSaveToWriter() throws ConfigurationException
+ {
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ StringWriter out = new StringWriter();
+ handler.save(out);
+ assertEquals("Wrong content", CONTENT, out.toString());
+ }
+
+ /**
+ * Tests whether an I/O exception during a save operation to a Writer is
+ * handled correctly.
+ */
+ @Test
+ public void testSaveToWriterIOException() throws ConfigurationException,
+ IOException
+ {
+ FileBased content = EasyMock.createMock(FileBased.class);
+ StringWriter out = new StringWriter();
+ IOException ioex = new IOException("Test exception!");
+ content.write(out);
+ EasyMock.expectLastCall().andThrow(ioex);
+ EasyMock.replay(content);
+ FileHandler handler = new FileHandler(content);
+ try
+ {
+ handler.save(out);
+ fail("IOException not detected!");
+ }
+ catch (ConfigurationException cex)
+ {
+ assertEquals("Wrong cause", ioex, cex.getCause());
+ }
+ EasyMock.verify(content);
+ }
+
+ /**
+ * Tries to save something to a Writer if no content is set.
+ */
+ @Test(expected = ConfigurationException.class)
+ public void testSaveToWriterNoContent() throws ConfigurationException
+ {
+ FileHandler handler = new FileHandler();
+ handler.save(new StringWriter());
+ }
+
+ /**
+ * Tests whether data can be saved to a stream.
+ */
+ @Test
+ public void testSaveToStream() throws ConfigurationException, IOException
+ {
+ File file = folder.newFile();
+ FileOutputStream out = new FileOutputStream(file);
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ try
+ {
+ handler.save(out);
+ }
+ finally
+ {
+ out.close();
+ }
+ assertEquals("Wrong content", CONTENT, readFile(file));
+ }
+
+ /**
+ * Tests whether data can be saved to a file.
+ */
+ @Test
+ public void testSaveToFile() throws ConfigurationException, IOException
+ {
+ File file = folder.newFile();
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.save(file);
+ assertEquals("Wrong content", CONTENT, readFile(file));
+ }
+
+ /**
+ * Tests whether data can be saved to a URL.
+ */
+ @Test
+ public void testSaveToURL() throws Exception
+ {
+ File file = folder.newFile();
+ URL url = file.toURI().toURL();
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.save(url);
+ assertEquals("Wrong content", CONTENT, readFile(file));
+ }
+
+ /**
+ * Tests whether data can be saved to a file name.
+ */
+ @Test
+ public void testSaveToFileName() throws ConfigurationException, IOException
+ {
+ File file = folder.newFile();
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.save(file.getAbsolutePath());
+ assertEquals("Wrong content", CONTENT, readFile(file));
+ }
+
+ /**
+ * Tests whether a URL exception is handled when saving a file to a file
+ * name.
+ */
+ @Test
+ public void testSaveToFileNameURLException() throws ConfigurationException,
+ IOException
+ {
+ FileSystem fs = EasyMock.createMock(FileSystem.class);
+ File file = folder.newFile();
+ String basePath = "some base path";
+ MalformedURLException urlex =
+ new MalformedURLException("Test exception");
+ EasyMock.expect(fs.getURL(basePath, file.getName())).andThrow(urlex);
+ EasyMock.replay(fs);
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setBasePath(basePath);
+ handler.setFileSystem(fs);
+ try
+ {
+ handler.save(file.getName());
+ fail("URL exception not detected!");
+ }
+ catch (ConfigurationException cex)
+ {
+ assertEquals("Wrong cause", urlex, cex.getCause());
+ }
+ EasyMock.verify(fs);
+ }
+
+ /**
+ * Tries to save data to a file name if the name cannot be located.
+ */
+ @Test
+ public void testSaveToFileNameURLNotResolved()
+ throws ConfigurationException, IOException
+ {
+ FileSystem fs = EasyMock.createMock(FileSystem.class);
+ File file = folder.newFile();
+ EasyMock.expect(fs.getURL(null, file.getName())).andReturn(null);
+ EasyMock.replay(fs);
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setFileSystem(fs);
+ try
+ {
+ handler.save(file.getName());
+ fail("Unresolved URL not detected!");
+ }
+ catch (ConfigurationException cex)
+ {
+ EasyMock.verify(fs);
+ }
+ }
+
+ /**
+ * Tests whether data can be saved to the internal location if it is a file
+ * name.
+ */
+ @Test
+ public void testSaveToFileNameLocation() throws ConfigurationException,
+ IOException
+ {
+ File file = folder.newFile();
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setFileName(file.getAbsolutePath());
+ handler.save();
+ assertEquals("Wrong content", CONTENT, readFile(file));
+ }
+
+ /**
+ * Tests whether data can be saved to the internal location if it is a URL.
+ */
+ @Test
+ public void testSaveToURLLocation() throws ConfigurationException,
+ IOException
+ {
+ File file = folder.newFile();
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setURL(file.toURI().toURL());
+ handler.save();
+ assertEquals("Wrong content", CONTENT, readFile(file));
+ }
+
+ /**
+ * Tries to save the handler if no location has been set.
+ */
+ @Test(expected = ConfigurationException.class)
+ public void testSaveNoLocation() throws ConfigurationException
+ {
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.save();
+ }
+
+ /**
+ * Tests loading and saving a configuration file with a complicated path
+ * name including spaces. (related to issue 35210)
+ */
+ @Test
+ public void testPathWithSpaces() throws ConfigurationException, IOException
+ {
+ File path = folder.newFolder("path with spaces");
+ File confFile = new File(path, "config-test.properties");
+ File testFile = createTestFile(confFile);
+ URL url = testFile.toURI().toURL();
+ FileBasedTestImpl content = new FileBasedTestImpl();
+ FileHandler handler = new FileHandler(content);
+ handler.setURL(url);
+ handler.load();
+ assertEquals("Wrong data read", CONTENT, content.getContent());
+ File out = new File(path, "out.txt");
+ handler.save(out);
+ assertEquals("Wrong data written", CONTENT, readFile(out));
+ }
+
+ /**
+ * Tests whether file names containing a "+" character are handled
+ * correctly. This test is related to CONFIGURATION-415.
+ */
+ @Test
+ public void testPathWithPlus() throws ConfigurationException, IOException
+ {
+ File saveFile = folder.newFile("test+config.properties");
+ FileHandler handler = new FileHandler(new FileBasedTestImpl());
+ handler.setFile(saveFile);
+ handler.save();
+ assertEquals("Wrong content", CONTENT, readFile(saveFile));
+ }
+
+ /**
+ * Tests whether a FileHandler object can be used to specify a location and
+ * later be assigned to a FileBased object.
+ */
+ @Test
+ public void testAssignWithFileBased()
+ {
+ FileHandler h1 = new FileHandler();
+ File f = new File("testfile.txt");
+ h1.setFile(f);
+ FileBased content = new FileBasedTestImpl();
+ FileHandler h2 = new FileHandler(content, h1);
+ h1.setFileName("someOtherFile.txt");
+ assertSame("Content not set", content, h2.getContent());
+ assertEquals("Wrong location", f, h2.getFile());
+ }
+
+ /**
+ * An implementation of the FileBased interface used for test purposes.
+ */
+ private static class FileBasedTestImpl implements FileBased
+ {
+ /** The content read from a reader. */
+ private String content;
+
+ /**
+ * Returns the content read from a reader.
+ *
+ * @return the read content
+ */
+ public String getContent()
+ {
+ return content;
+ }
+
+ public void read(Reader in) throws ConfigurationException, IOException
+ {
+ content = readReader(in);
+ }
+
+ public void write(Writer out) throws ConfigurationException,
+ IOException
+ {
+ out.write(CONTENT);
+ out.flush();
+ }
+ }
+}
Propchange: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain