blob: ee4c8d60c7380fa3d4201679340951755c4b3130 [file] [log] [blame]
/*
* 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.configuration2.io;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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.InputStream;
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 java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.configuration2.ConfigurationAssert;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.SynchronizerTestImpl;
import org.apache.commons.configuration2.SynchronizerTestImpl.Methods;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.easymock.EasyMock;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
* Test class for {@code FileHandler}.
*
*/
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 with 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(final File f)
{
Writer out = null;
File file = f;
try
{
if (file == null)
{
file = folder.newFile();
}
out = new FileWriter(file);
out.write(CONTENT);
}
catch (final IOException ioex)
{
fail("Could not create test file: " + ioex);
return null; // cannot happen
}
finally
{
if (out != null)
{
try
{
out.close();
}
catch (final 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(final Reader in) throws IOException
{
final 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(final File f)
{
Reader in = null;
try
{
in = new FileReader(f);
return readReader(in);
}
catch (final IOException ioex)
{
fail("Could not read file: " + ioex);
return null; // cannot happen
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (final IOException ioex)
{
// ignore
}
}
}
}
/**
* Tests whether a newly created instance has a default file system.
*/
@Test
public void testGetFileSystemDefault()
{
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
assertEquals("Wrong default file system",
FileLocatorUtils.DEFAULT_FILE_SYSTEM, handler.getFileSystem());
}
/**
* Tests whether a null file system can be set to reset this property.
*/
@Test
public void testSetFileSystemNull()
{
final FileSystem sys = EasyMock.createMock(FileSystem.class);
EasyMock.replay(sys);
final 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",
FileLocatorUtils.DEFAULT_FILE_SYSTEM, handler.getFileSystem());
}
/**
* Tests whether the file system can be reset.
*/
@Test
public void testResetFileSystem()
{
final FileSystem sys = EasyMock.createMock(FileSystem.class);
EasyMock.replay(sys);
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
handler.setFileSystem(sys);
handler.resetFileSystem();
assertEquals("Not default file system",
FileLocatorUtils.DEFAULT_FILE_SYSTEM, handler.getFileSystem());
}
/**
* Tests whether a newly created instance uses the default location
* strategy.
*/
@Test
public void testGetLocationStrategyDefault()
{
final FileHandler handler = new FileHandler();
assertNull("Strategy in locator", handler.getFileLocator()
.getLocationStrategy());
assertSame("Wrong default strategy",
FileLocatorUtils.DEFAULT_LOCATION_STRATEGY,
handler.getLocationStrategy());
}
/**
* Tests whether the location strategy can be changed.
*/
@Test
public void testSetLocationStrategy()
{
final FileLocationStrategy strategy =
EasyMock.createMock(FileLocationStrategy.class);
EasyMock.replay(strategy);
final FileHandler handler = new FileHandler();
handler.setLocationStrategy(strategy);
assertSame("Wrong strategy in locator", strategy, handler
.getFileLocator().getLocationStrategy());
assertSame("Wrong strategy", strategy, handler.getLocationStrategy());
}
/**
* Tests whether a URL can be set.
*/
@Test
public void testSetURL() throws Exception
{
final FileHandler handler = new FileHandler();
handler.setURL(new URL(
"https://commons.apache.org/configuration/index.html"));
assertEquals("base path", "https://commons.apache.org/configuration/",
handler.getBasePath());
assertEquals("file name", "index.html", handler.getFileName());
assertNull("Got a file name in locator", handler.getFileLocator()
.getFileName());
}
/**
* Tests whether the correct file scheme is applied.
*/
@Test
public void testSetURLFileScheme() throws MalformedURLException
{
final FileHandler handler = new FileHandler();
// 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
{
final FileHandler handler = new FileHandler();
final URL url =
new URL(
"https://issues.apache.org/bugzilla/show_bug.cgi?id=37886");
handler.setURL(url);
assertEquals("Base path incorrect",
"https://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 a null URL can be set.
*/
@Test
public void testSetURLNull()
{
final FileHandler handler = new FileHandler();
handler.setURL(ConfigurationAssert.getTestURL(TEST_FILENAME));
handler.setURL(null);
final FileLocator locator = handler.getFileLocator();
assertNull("Got a base path", locator.getBasePath());
assertNull("Got a file name", locator.getFileName());
assertNull("Got a URL", locator.getSourceURL());
}
/**
* Tests whether the location can be set as a file.
*/
@Test
public void testSetFile()
{
final FileHandler handler = new FileHandler();
final File directory = ConfigurationAssert.TEST_DIR;
final 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
{
final FileHandler handler = new FileHandler();
handler.setPath(ConfigurationAssert.TEST_DIR_NAME + File.separator
+ TEST_FILENAME);
assertEquals("Wrong file name", TEST_FILENAME, handler.getFileName());
assertEquals("Wrong base path",
ConfigurationAssert.TEST_DIR.getAbsolutePath(),
handler.getBasePath());
final File file = ConfigurationAssert.getTestFile(TEST_FILENAME);
assertEquals("Wrong path", file.getAbsolutePath(), handler.getPath());
assertEquals("Wrong URL", file.toURI().toURL(), handler.getURL());
assertNull("Got a URL", handler.getFileLocator().getSourceURL());
}
/**
* Tests whether the location can be set using file name and base path.
*/
@Test
public void testSetFileName()
{
final FileHandler handler = new FileHandler();
handler.setURL(ConfigurationAssert.getTestURL(TEST_FILENAME));
handler.setFileName(TEST_FILENAME);
assertNull("Got a base path", handler.getBasePath());
assertEquals("Wrong file name", TEST_FILENAME, handler.getFileName());
assertEquals("Wrong file name in locator", TEST_FILENAME, handler
.getFileLocator().getFileName());
assertNull("Got a URL", handler.getFileLocator().getSourceURL());
}
/**
* Tests whether the file scheme is corrected when setting the file name.
*/
@Test
public void testSetFileNameFileScheme()
{
final FileHandler handler = new FileHandler();
handler.setFileName("file:/test/path/test.txt");
assertEquals("Wrong file name", "file:///test/path/test.txt", handler
.getFileLocator().getFileName());
}
/**
* Tests getFileName() if no information is set.
*/
@Test
public void testGetFileNameUndefined()
{
assertNull("Got a file name", new FileHandler().getFileName());
}
/**
* Tests whether a base path can be set and whether this removes an already
* set URL.
*/
@Test
public void testSetBasePath()
{
final FileHandler handler = new FileHandler();
handler.setURL(ConfigurationAssert.getTestURL(TEST_FILENAME));
final String basePath = ConfigurationAssert.TEST_DIR_NAME;
handler.setBasePath(basePath);
final FileLocator locator = handler.getFileLocator();
assertEquals("Wrong base path", basePath, locator.getBasePath());
assertNull("Got a URL", locator.getSourceURL());
assertNull("Got a file name", locator.getFileName());
}
/**
* Tests whether the file scheme is corrected when setting the base path.
*/
@Test
public void testSetBasePathFileScheme()
{
final FileHandler handler = new FileHandler();
handler.setBasePath("file:/test/path/");
assertEquals("Wrong base path", "file:///test/path/", handler
.getFileLocator().getBasePath());
}
/**
* Tests getBasePath() if no information is available.
*/
@Test
public void testGetBasePathUndefined()
{
assertNull("Got a base path", new FileHandler().getBasePath());
}
/**
* Additional tests for setting file names in various ways. (Copied from the
* test for XMLConfiguration)
*/
@Test
public void testSettingFileNames()
{
final String testProperties =
ConfigurationAssert.getTestFile("test.xml").getAbsolutePath();
final String testBasePath = ConfigurationAssert.TEST_DIR.getAbsolutePath();
final FileHandler handler = new FileHandler();
handler.setFileName(testProperties);
assertEquals(testProperties.toString(), handler.getFileName());
handler.setBasePath(testBasePath);
handler.setFileName("hello.xml");
assertEquals("hello.xml", handler.getFileName());
assertEquals(testBasePath.toString(), handler.getBasePath());
assertEquals(new File(testBasePath, "hello.xml"), handler.getFile());
handler.setBasePath(testBasePath);
handler.setFileName("subdir/hello.xml");
assertEquals("subdir/hello.xml", handler.getFileName());
assertEquals(testBasePath.toString(), handler.getBasePath());
assertEquals(new File(testBasePath, "subdir/hello.xml"),
handler.getFile());
}
/**
* Tries to call a load() method if no content object is available.
*/
@Test(expected = ConfigurationException.class)
public void testLoadNoContent() throws ConfigurationException
{
final FileHandler handler = new FileHandler();
final 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
{
final FileBased content = EasyMock.createMock(FileBased.class);
final Reader in = new StringReader(CONTENT);
final IOException ioex = new IOException("Test exception");
content.read(in);
EasyMock.expectLastCall().andThrow(ioex);
EasyMock.replay(content);
final FileHandler handler = new FileHandler(content);
try
{
handler.load(in);
fail("IOException not detected!");
}
catch (final 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
{
final FileBasedTestImpl content = new FileBasedTestImpl();
final File file = createTestFile();
final 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()
{
final FileHandler handler = new FileHandler();
final File file = createTestFile();
try
{
handler.load(file);
fail("Missing content not detected!");
}
catch (final 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
{
final 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
{
final 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
{
final FileBasedTestImpl content = new FileBasedTestImpl();
final 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
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final 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
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
handler.load(file.getAbsolutePath());
assertEquals("Wrong content", CONTENT, content.getContent());
}
/**
* Tests that a load() operation with a file path overrides a URL which
* might have been set.
*/
@Test
public void testLoadFromFilePathWithURLDefined()
throws ConfigurationException
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
handler.setURL(ConfigurationAssert.getTestURL("test.xml"));
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
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
final 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
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
final 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
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final 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
{
final File file = createTestFile();
final FileBasedTestImpl content = new FileBasedTestImpl();
final 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
{
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
handler.load();
}
/**
* Tests whether data can be saved into a Writer.
*/
@Test
public void testSaveToWriter() throws ConfigurationException
{
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
final 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
{
final FileBased content = EasyMock.createMock(FileBased.class);
final StringWriter out = new StringWriter();
final IOException ioex = new IOException("Test exception!");
content.write(out);
EasyMock.expectLastCall().andThrow(ioex);
EasyMock.replay(content);
final FileHandler handler = new FileHandler(content);
try
{
handler.save(out);
fail("IOException not detected!");
}
catch (final 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
{
final FileHandler handler = new FileHandler();
handler.save(new StringWriter());
}
/**
* Tests whether data can be saved to a stream.
*/
@Test
public void testSaveToStream() throws ConfigurationException, IOException
{
final File file = folder.newFile();
final FileOutputStream out = new FileOutputStream(file);
final 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
{
final File file = folder.newFile();
final 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
{
final File file = folder.newFile();
final URL url = file.toURI().toURL();
final 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
{
final File file = folder.newFile();
final 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 IOException
{
final FileSystem fs = EasyMock.createMock(FileSystem.class);
final File file = folder.newFile();
final String basePath = "some base path";
final MalformedURLException urlex =
new MalformedURLException("Test exception");
EasyMock.expect(fs.getURL(basePath, file.getName())).andThrow(urlex);
EasyMock.replay(fs);
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
handler.setBasePath(basePath);
handler.setFileSystem(fs);
try
{
handler.save(file.getName());
fail("URL exception not detected!");
}
catch (final 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 IOException
{
final FileSystem fs = EasyMock.createMock(FileSystem.class);
final File file = folder.newFile();
EasyMock.expect(fs.getURL(null, file.getName())).andReturn(null);
EasyMock.replay(fs);
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
handler.setFileSystem(fs);
try
{
handler.save(file.getName());
fail("Unresolved URL not detected!");
}
catch (final 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
{
final File file = folder.newFile();
final 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
{
final File file = folder.newFile();
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
handler.setURL(file.toURI().toURL());
handler.save();
assertEquals("Wrong content", CONTENT, readFile(file));
}
/**
* Tries to save the locator if no location has been set.
*/
@Test(expected = ConfigurationException.class)
public void testSaveNoLocation() throws ConfigurationException
{
final 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
{
final File path = folder.newFolder("path with spaces");
final File confFile = new File(path, "config-test.properties");
final File testFile = createTestFile(confFile);
final URL url = testFile.toURI().toURL();
final FileBasedTestImpl content = new FileBasedTestImpl();
final FileHandler handler = new FileHandler(content);
handler.setURL(url);
handler.load();
assertEquals("Wrong data read", CONTENT, content.getContent());
final 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
{
final File saveFile = folder.newFile("test+config.properties");
final 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()
{
final FileHandler h1 = new FileHandler();
final File f = new File("testfile.txt");
h1.setFile(f);
final FileBased content = new FileBasedTestImpl();
final FileHandler h2 = new FileHandler(content, h1);
h1.setFileName("someOtherFile.txt");
assertSame("Content not set", content, h2.getContent());
assertEquals("Wrong location", f, h2.getFile());
}
/**
* Tries to invoke the assignment constructor with a null handler.
*/
@Test(expected = IllegalArgumentException.class)
public void testAssignNullHandler()
{
new FileHandler(new FileBasedTestImpl(), null);
}
/**
* Tests isLocationDefined() if a File has been set.
*/
@Test
public void testIsLocationDefinedFile()
{
final FileHandler handler = new FileHandler();
handler.setFile(createTestFile());
assertTrue("Location not defined", handler.isLocationDefined());
}
/**
* Tests isLocationDefined() if a URL has been set.
*/
@Test
public void testIsLocationDefinedURL() throws IOException
{
final FileHandler handler = new FileHandler();
handler.setURL(createTestFile().toURI().toURL());
assertTrue("Location not defined", handler.isLocationDefined());
}
/**
* Tests isLocationDefined() if a path has been set.
*/
@Test
public void testIsLocationDefinedPath()
{
final FileHandler handler = new FileHandler();
handler.setPath(createTestFile().getAbsolutePath());
assertTrue("Location not defined", handler.isLocationDefined());
}
/**
* Tests isLocationDefined() if a file name has been set.
*/
@Test
public void testIsLocationDefinedFileName()
{
final FileHandler handler = new FileHandler();
handler.setFileName(createTestFile().getName());
assertTrue("Location not defined", handler.isLocationDefined());
}
/**
* Tests whether an undefined location can be queried.
*/
@Test
public void testIsLocationDefinedFalse()
{
final FileHandler handler = new FileHandler();
assertFalse("Location defined", handler.isLocationDefined());
}
/**
* Tests isLocationDefined() if only a base path is set.
*/
@Test
public void testIsLocationDefinedBasePathOnly()
{
final FileHandler handler = new FileHandler();
handler.setBasePath(createTestFile().getParent());
assertFalse("Location defined", handler.isLocationDefined());
}
/**
* Tests whether the location can be cleared.
*/
@Test
public void testClearLocation()
{
final FileHandler handler = new FileHandler();
handler.setFile(createTestFile());
handler.clearLocation();
assertFalse("Location defined", handler.isLocationDefined());
assertNull("Got a file", handler.getFile());
assertNull("Got a URL", handler.getURL());
assertNull("Got a base path", handler.getBasePath());
assertNull("Got a path", handler.getPath());
}
/**
* Tests whether a FileLocatorAware object is initialized correctly when
* loading data.
*/
@Test
public void testLoadFileLocatorAware() throws IOException,
ConfigurationException
{
final File file = createTestFile();
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
handler.setFile(file);
handler.load();
assertEquals("Wrong result", file.toURI().toURL().toString() + ": "
+ CONTENT, content.getContent());
}
/**
* Checks a FileLocator which is expected to contain no data.
*
* @param content the data object which was passed the locator
*/
private static void checkEmptyLocator(
final FileBasedFileLocatorAwareTestImpl content)
{
assertNull("Got a URL", content.getLocator().getSourceURL());
assertNull("Got a base path", content.getLocator().getBasePath());
assertNull("Got a file name", content.getLocator().getFileName());
}
/**
* Tests loading with a FileLocatorAware object if data is loaded from a
* stream.
*/
@Test
public void testLoadFileLocatorAwareStream() throws ConfigurationException
{
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
final ByteArrayInputStream bos = new ByteArrayInputStream(CONTENT.getBytes());
handler.load(bos);
checkEmptyLocator(content);
}
/**
* Tests a load operation with a FileLocatorAware object if data is loaded
* from a reader.
*/
@Test
public void testLoadFileLocatorAwareReader() throws ConfigurationException
{
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
handler.load(new StringReader(CONTENT));
checkEmptyLocator(content);
}
/**
* Tests whether a FileLocatorAware is correctly handled when saving data.
*/
@Test
public void testSaveFileLocatorAware() throws ConfigurationException,
IOException
{
final File file = folder.newFile();
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
handler.save(file);
assertEquals("Wrong file content", file.toURI().toURL() + ": "
+ CONTENT, readFile(file));
}
/**
* Tests a save operation with a FileLocatorAware object if the target is a
* stream.
*/
@Test
public void testSaveFileLocatorAwareToStream()
throws ConfigurationException
{
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
handler.save(new ByteArrayOutputStream());
checkEmptyLocator(content);
}
/**
* Tests a save operation with a FileLocatorAware object if the target is a
* writer.
*/
@Test
public void testSaveFileLocatorAwareToWriter()
throws ConfigurationException
{
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
handler.save(new StringWriter());
checkEmptyLocator(content);
}
/**
* Tests that the locator injected into the content object has an encoding
* set.
*/
@Test
public void testLocatorAwareEncoding() throws ConfigurationException
{
final FileBasedFileLocatorAwareTestImpl content =
new FileBasedFileLocatorAwareTestImpl();
final FileHandler handler = new FileHandler(content);
final String encoding = "testEncoding";
handler.setEncoding(encoding);
handler.save(new StringWriter());
assertEquals("Encoding not set", encoding, content.getLocator()
.getEncoding());
}
/**
* Tries to add a null listener.
*/
@Test(expected = IllegalArgumentException.class)
public void testAddFileHandlerListenerNull()
{
new FileHandler().addFileHandlerListener(null);
}
/**
* Tests notifications about load operations.
*/
@Test
public void testLoadEvents() throws ConfigurationException
{
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.load(createTestFile());
listener.checkMethods("loadingloaded");
}
/**
* Tests notifications about save operations.
*/
@Test
public void testSaveEvents() throws IOException, ConfigurationException
{
final FileHandler handler = new FileHandler(new FileBasedTestImpl());
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
final File f = folder.newFile();
handler.save(f);
listener.checkMethods("savingsaved");
}
/**
* Tests a notification about a changed file name.
*/
@Test
public void testLocationChangedFileName()
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setFileName(TEST_FILENAME);
listener.checkMethods("locationChanged");
}
/**
* Tests a notification about a changed base path.
*/
@Test
public void testLocationChangedBasePath()
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setBasePath(TEST_FILENAME);
listener.checkMethods("locationChanged");
}
/**
* Tests a notification about a changed file.
*/
@Test
public void testLocationChangedFile() throws IOException
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setFile(folder.newFile());
listener.checkMethods("locationChanged");
}
/**
* Tests a notification about a changed path.
*/
@Test
public void testLocationChangedPath()
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setPath(TEST_FILENAME);
listener.checkMethods("locationChanged");
}
/**
* Tests a notification about a changed file system.
*/
@Test
public void testLocationChangedFileSystem()
{
final FileSystem fs = EasyMock.createMock(FileSystem.class);
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setFileSystem(fs);
listener.checkMethods("locationChanged");
}
/**
* Tests a notification about a changed URL.
*/
@Test
public void testLocationChangedURL() throws IOException
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
final URL url = folder.newFile().toURI().toURL();
handler.setURL(url);
listener.checkMethods("locationChanged");
}
/**
* Tests a notification about a changed encoding.
*/
@Test
public void testLocationChangedEncoding()
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setEncoding("UTF-8");
listener.checkMethods("locationChanged");
}
/**
* Tests whether a notification is sent if the whole locator was changed.
*/
@Test
public void testLocationChangedLocator()
{
final FileHandler handler = new FileHandler();
final FileHandlerListenerTestImpl listener =
new FileHandlerListenerTestImpl(handler);
handler.addFileHandlerListener(listener);
handler.setFileLocator(FileLocatorUtils.fileLocator()
.fileName(TEST_FILENAME).create());
listener.checkMethods("locationChanged");
}
/**
* Tests whether data can be read from an input stream.
*/
@Test
public void testLoadInputStreamSupport() throws ConfigurationException
{
final FileBasedInputStreamSupportTestImpl content =
new FileBasedInputStreamSupportTestImpl();
final FileHandler handler = new FileHandler(content);
final ByteArrayInputStream bin = new ByteArrayInputStream(CONTENT.getBytes());
handler.load(bin);
assertEquals("Wrong content", "InputStream = " + CONTENT,
content.getContent());
}
/**
* Tests whether an IOException is handled when reading from an input
* stream.
*/
@Test
public void testLoadInputStreamSupportIOException()
throws ConfigurationException, IOException
{
final FileBasedInputStreamSupportTestImpl content =
EasyMock.createMock(FileBasedInputStreamSupportTestImpl.class);
final ByteArrayInputStream bin = new ByteArrayInputStream(CONTENT.getBytes());
final IOException ioex = new IOException();
content.read(bin);
EasyMock.expectLastCall().andThrow(ioex);
EasyMock.replay(content);
final FileHandler handler = new FileHandler(content);
try
{
handler.load(bin);
fail("IOException not detected!");
}
catch (final ConfigurationException cex)
{
assertEquals("Wrong cause", ioex, cex.getCause());
}
EasyMock.verify(content);
}
/**
* Tests whether a load() operation is correctly synchronized.
*/
@Test
public void testLoadSynchronized() throws ConfigurationException
{
final PropertiesConfiguration config = new PropertiesConfiguration();
final SynchronizerTestImpl sync = new SynchronizerTestImpl();
config.setSynchronizer(sync);
final FileHandler handler = new FileHandler(config);
handler.load(ConfigurationAssert.getTestFile("test.properties"));
sync.verifyStart(Methods.BEGIN_WRITE);
sync.verifyEnd(Methods.END_WRITE);
}
/**
* Tests whether a save() operation is correctly synchronized.
*/
@Test
public void testSaveSynchronized() throws ConfigurationException, IOException
{
final PropertiesConfiguration config = new PropertiesConfiguration();
config.addProperty("test.synchronized", Boolean.TRUE);
final SynchronizerTestImpl sync = new SynchronizerTestImpl();
config.setSynchronizer(sync);
final FileHandler handler = new FileHandler(config);
final File f = folder.newFile();
handler.save(f);
sync.verify(Methods.BEGIN_WRITE, Methods.END_WRITE);
}
/**
* Tests whether the initialization of properties is safe even if performed
* in multiple threads.
*/
@Test
public void testInitPropertiesMultiThreaded() throws InterruptedException
{
final String encoding = "TestEncoding";
final FileSystem fileSystem = new DefaultFileSystem();
final FileLocationStrategy locationStrategy =
new ProvidedURLLocationStrategy();
final int loops = 8;
for (int i = 0; i < loops; i++)
{
final FileHandler handler = new FileHandler();
final Thread t1 = new Thread()
{
@Override
public void run()
{
handler.setFileSystem(fileSystem);
}
};
final Thread t2 = new Thread()
{
@Override
public void run()
{
handler.setFileName(TEST_FILENAME);
}
};
final Thread t3 = new Thread()
{
@Override
public void run()
{
handler.setEncoding(encoding);
}
};
final Thread t4 = new Thread()
{
@Override
public void run()
{
handler.setLocationStrategy(locationStrategy);
}
};
final List<Thread> threads = Arrays.asList(t1, t2, t3, t4);
for (final Thread t : threads)
{
t.start();
}
for (final Thread t : threads)
{
t.join();
}
final FileLocator locator = handler.getFileLocator();
assertEquals("Wrong file name", TEST_FILENAME,
locator.getFileName());
assertNull("Got a URL", locator.getSourceURL());
assertEquals("Wrong encoding", encoding, locator.getEncoding());
assertSame("Wrong file system", fileSystem, locator.getFileSystem());
assertSame("Wrong location strategy", locationStrategy,
locator.getLocationStrategy());
}
}
/**
* Tries to set the FileLocator to null.
*/
@Test(expected = IllegalArgumentException.class)
public void testSetFileLocatorNull()
{
final FileHandler handler = new FileHandler();
handler.setFileLocator(null);
}
/**
* Tests whether the handler can be initialized using a FileLocator.
*/
@Test
public void testSetFileLocator()
{
final FileLocator locator =
FileLocatorUtils.fileLocator().fileName(TEST_FILENAME).create();
final FileHandler handler = new FileHandler();
handler.setFileLocator(locator);
assertEquals("Handler not initialized", TEST_FILENAME,
handler.getFileName());
}
/**
* Tests a successful locate() operation.
*/
@Test
public void testLocateSuccess() throws ConfigurationException
{
final FileHandler handler = new FileHandler();
handler.setFileName(TEST_FILENAME);
assertTrue("Wrong result", handler.locate());
final FileLocator locator = handler.getFileLocator();
assertNotNull("URL not filled", locator.getSourceURL());
assertNotNull("Base path not filled", locator.getBasePath());
assertEquals("Wrong file name", TEST_FILENAME, locator.getFileName());
// check whether the correct URL was obtained
final PropertiesConfiguration config = new PropertiesConfiguration();
final FileHandler h2 = new FileHandler(config);
h2.setURL(locator.getSourceURL());
h2.load();
assertTrue("Configuration not loaded",
config.getBoolean("configuration.loaded"));
}
/**
* Tests a locate() operation if the specified file cannot be resolved.
*/
@Test
public void testLocateUnknownFile()
{
final FileHandler handler = new FileHandler();
handler.setFileName("unknown file");
final FileLocator locator = handler.getFileLocator();
assertFalse("Wrong result", handler.locate());
assertSame("Locator was changed", locator, handler.getFileLocator());
}
/**
* Tests a locate() operation if there is not enough information.
*/
@Test
public void testLocateUndefinedLocator()
{
final FileHandler handler = new FileHandler();
handler.setBasePath("only/a/base/path");
final FileLocator locator = handler.getFileLocator();
assertFalse("Wrong result", handler.locate());
assertSame("Locator was changed", locator, handler.getFileLocator());
}
/**
* Tests whether an instance can be created from a map with the properties
* of a FileLocator.
*/
@Test
public void testInitFromMap()
{
final FileLocator locator =
FileLocatorUtils.fileLocator().fileName(TEST_FILENAME)
.basePath("someBasePath").encoding("someEncoding")
.create();
final Map<String, Object> map = new HashMap<>();
FileLocatorUtils.put(locator, map);
final FileHandler handler = FileHandler.fromMap(map);
assertEquals("Wrong locator", locator, handler.getFileLocator());
}
/**
* 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 = CONTENT;
/**
* Returns the content read from a reader.
*
* @return the read content
*/
public String getContent()
{
return content;
}
/**
* Allows setting the content.
*
* @param content the content
*/
public void setContent(final String content)
{
this.content = content;
}
@Override
public void read(final Reader in) throws ConfigurationException, IOException
{
content = readReader(in);
}
@Override
public void write(final Writer out) throws ConfigurationException,
IOException
{
out.write(getContent());
out.flush();
}
}
/**
* A test implementation of FileBased which can also read from input
* streams.
*/
private static class FileBasedInputStreamSupportTestImpl extends
FileBasedTestImpl implements InputStreamSupport
{
@Override
public void read(final InputStream in) throws ConfigurationException,
IOException
{
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
int c;
while ((c = in.read()) != -1)
{
bos.write(c);
}
setContent("InputStream = " + bos.toString());
}
}
/**
* A FileBased implementation which also implements FileLocatorAware. This
* class adds information about the current file locator to the content read
* and written.
*/
private static final class FileBasedFileLocatorAwareTestImpl extends
FileBasedTestImpl implements FileLocatorAware
{
/** Stores the passed in file locator. */
private FileLocator locator;
/**
* Returns the locator.
*
* @return the file locator
*/
public FileLocator getLocator()
{
return locator;
}
@Override
public void initFileLocator(final FileLocator loc)
{
this.locator = loc;
}
@Override
public void read(final Reader in) throws ConfigurationException, IOException
{
super.read(in);
setContent(String.valueOf(locator.getSourceURL()) + ": " + getContent());
}
@Override
public void write(final Writer out) throws ConfigurationException,
IOException
{
out.write(String.valueOf(locator.getSourceURL()) + ": ");
super.write(out);
}
}
/**
* A test listener implementation.
*/
private static class FileHandlerListenerTestImpl extends
FileHandlerListenerAdapter
{
/** The expected file handler. */
private final FileHandler expHandler;
/** A buffer for recording method invocations. */
private final StringBuilder methods;
public FileHandlerListenerTestImpl(final FileHandler fh)
{
expHandler = fh;
methods = new StringBuilder();
}
/**
* Tests whether the expected listener methods have been called.
*
* @param expMethods the expected methods as plain string
*/
public void checkMethods(final String expMethods)
{
assertEquals("Wrong listener methods", expMethods,
methods.toString());
}
@Override
public void loading(final FileHandler handler)
{
super.loading(handler);
methodCalled(handler, "loading");
}
@Override
public void loaded(final FileHandler handler)
{
super.loaded(handler);
methodCalled(handler, "loaded");
}
@Override
public void saving(final FileHandler handler)
{
super.saving(handler);
methodCalled(handler, "saving");
}
@Override
public void saved(final FileHandler handler)
{
super.saved(handler);
methodCalled(handler, "saved");
}
@Override
public void locationChanged(final FileHandler handler)
{
super.locationChanged(handler);
methodCalled(handler, "locationChanged");
}
/**
* One of the listener methods was called. Records this invocation.
*
* @param handler the file handler
* @param method the called method
*/
private void methodCalled(final FileHandler handler, final String method)
{
assertEquals("Wrong file handler", expHandler, handler);
methods.append(method);
}
}
}