diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f78855b27..949b38e15 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -30,6 +30,9 @@ Fix LRUMap exception message. + + Create a PropertiesFactory and SortedPropertiesFactory. + diff --git a/src/main/java/org/apache/commons/collections4/properties/AbstractPropertiesFactory.java b/src/main/java/org/apache/commons/collections4/properties/AbstractPropertiesFactory.java new file mode 100644 index 000000000..7c89f604e --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/properties/AbstractPropertiesFactory.java @@ -0,0 +1,174 @@ +/* + * 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.collections4.properties; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URI; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +/** + * Subclasses create and load {@link Properties} and subclasses of {@link Properties} like {@link SortedProperties}. + * + * @param {@link Properties} or a subclass like {@link SortedProperties}. + * @see Properties + * @since 4.4 + */ +public abstract class AbstractPropertiesFactory { + + /** + * Constructs an instance. + */ + protected AbstractPropertiesFactory() { + // no init. + } + + /** + * Subclasses override to provide customized properties instances. + * + * @return a new Properties instance. + */ + protected abstract T createProperties(); + + /** + * Creates and loads properties from the given file. + * + * @param classLoader the class loader to use to get the named resource. + * @param name the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final ClassLoader classLoader, final String name) throws IOException { + try (final InputStream inputStream = classLoader.getResourceAsStream(name)) { + return load(inputStream); + } + } + + /** + * Creates and loads properties from the given file. + * + * @param file the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + * @throws FileNotFoundException Thrown if the file does not exist, is a directory, or cannot be opened for + * reading. + * @throws SecurityException Thrown if a security manager's {@code checkRead} method denies read access to + * the file. + */ + public T load(final File file) throws FileNotFoundException, IOException { + try (final FileInputStream inputStream = new FileInputStream(file)) { + return load(inputStream); + } + } + + /** + * Creates and loads properties from the given input stream. + * + * @param inputStream the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final InputStream inputStream) throws IOException { + if (inputStream == null) { + return null; + } + final T properties = createProperties(); + properties.load(inputStream); + return properties; + } + + /** + * Creates and loads properties from the given path. + * + * @param path the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final Path path) throws IOException { + try (final InputStream inputStream = Files.newInputStream(path)) { + return load(inputStream); + } + } + + /** + * Creates and loads properties from the given reader. + * + * @param reader the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final Reader reader) throws IOException { + final T properties = createProperties(); + properties.load(reader); + return properties; + } + + /** + * Creates and loads properties from the given file name. + * + * @param name the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final String name) throws IOException { + try (final FileInputStream inputStream = new FileInputStream(name)) { + return load(inputStream); + } + } + + /** + * Creates and loads properties from the given URI. + * + * @param uri the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final URI uri) throws IOException { + return load(Paths.get(uri)); + } + + /** + * Creates and loads properties from the given URL. + * + * @param url the location of the properties file. + * @return a new properties object. + * @throws IOException Thrown if an error occurred reading the input stream. + * @throws IllegalArgumentException Thrown if the input contains a malformed Unicode escape sequence. + */ + public T load(final URL url) throws IOException { + try (final InputStream inputStream = url.openStream()) { + return load(inputStream); + } + } + +} diff --git a/src/main/java/org/apache/commons/collections4/properties/PropertiesFactory.java b/src/main/java/org/apache/commons/collections4/properties/PropertiesFactory.java new file mode 100644 index 000000000..04de759d2 --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/properties/PropertiesFactory.java @@ -0,0 +1,52 @@ +/* + * 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.collections4.properties; + +import java.util.Properties; + +/** + * Creates and loads {@link Properties}. + * + * @see Properties + * @since 4.4 + */ +public class PropertiesFactory extends AbstractPropertiesFactory { + + /** + * The singleton instance. + */ + public static final PropertiesFactory INSTANCE = new PropertiesFactory(); + + /** + * Constructs an instance. + */ + private PropertiesFactory() { + // There is only one instance. + } + + /** + * Subclasses override to provide customized properties instances. + * + * @return a new Properties instance. + */ + @Override + protected Properties createProperties() { + return new Properties(); + } + +} diff --git a/src/main/java/org/apache/commons/collections4/properties/SortedPropertiesFactory.java b/src/main/java/org/apache/commons/collections4/properties/SortedPropertiesFactory.java new file mode 100644 index 000000000..010562600 --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/properties/SortedPropertiesFactory.java @@ -0,0 +1,50 @@ +/* + * 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.collections4.properties; + +/** + * Creates and loads {@link SortedProperties}. + * + * @see SortedProperties + * @since 4.4 + */ +public class SortedPropertiesFactory extends AbstractPropertiesFactory { + + /** + * The singleton instance. + */ + public static final SortedPropertiesFactory INSTANCE = new SortedPropertiesFactory(); + + /** + * Constructs an instance. + */ + private SortedPropertiesFactory() { + // There is only one instance. + } + + /** + * Subclasses override to provide customized properties instances. + * + * @return a new Properties instance. + */ + @Override + protected SortedProperties createProperties() { + return new SortedProperties(); + } + +} diff --git a/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java b/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java new file mode 100644 index 000000000..3e68a65b9 --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java @@ -0,0 +1,98 @@ +/* + * 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.collections4.properties; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +public abstract class AbstractPropertiesFactoryTest { + + private static final String PATH_STRING = "src/test/resources/properties/test.properties"; + + private final AbstractPropertiesFactory factory; + + protected AbstractPropertiesFactoryTest(final AbstractPropertiesFactory factory) { + super(); + this.factory = factory; + } + + private void assertContents(final T properties) { + Assert.assertEquals("value1", properties.getProperty("key1")); + Assert.assertEquals("value2", properties.getProperty("key2")); + } + + @Test + public void testInstance() { + Assert.assertNotNull(PropertiesFactory.INSTANCE); + } + + @Test + public void testLoadClassLoaderMissingResource() throws Exception { + Assert.assertNull(factory.load(ClassLoader.getSystemClassLoader(), "missing/test.properties")); + } + + @Test + public void testLoadClassLoaderResource() throws Exception { + assertContents(factory.load(ClassLoader.getSystemClassLoader(), "properties/test.properties")); + } + + @Test + public void testLoadFile() throws Exception { + assertContents(factory.load(Paths.get(PATH_STRING).toFile())); + } + + @Test + public void testLoadFileName() throws Exception { + assertContents(factory.load(PATH_STRING)); + } + + @Test + public void testLoadInputStream() throws Exception { + try (final FileInputStream inputStream = new FileInputStream(PATH_STRING)) { + assertContents(factory.load(inputStream)); + } + } + + @Test + public void testLoadPath() throws Exception { + assertContents(factory.load(Paths.get(PATH_STRING))); + } + + @Test + public void testLoadReader() throws Exception { + try (final BufferedReader inputStream = Files.newBufferedReader(Paths.get(PATH_STRING))) { + assertContents(factory.load(inputStream)); + } + } + + @Test + public void testLoadUri() throws Exception { + assertContents(factory.load(Paths.get(PATH_STRING).toUri())); + } + + @Test + public void testLoadUrl() throws Exception { + assertContents(factory.load(Paths.get(PATH_STRING).toUri().toURL())); + } +} diff --git a/src/test/java/org/apache/commons/collections4/properties/PropertiesFactoryTest.java b/src/test/java/org/apache/commons/collections4/properties/PropertiesFactoryTest.java new file mode 100644 index 000000000..83133d06d --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/properties/PropertiesFactoryTest.java @@ -0,0 +1,36 @@ +/* + * 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.collections4.properties; + +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +public class PropertiesFactoryTest extends AbstractPropertiesFactoryTest { + + public PropertiesFactoryTest() { + super(PropertiesFactory.INSTANCE); + } + + @Override + @Test + public void testInstance() { + Assert.assertNotNull(PropertiesFactory.INSTANCE); + } +} diff --git a/src/test/java/org/apache/commons/collections4/properties/SortedPropertiesFactoryTest.java b/src/test/java/org/apache/commons/collections4/properties/SortedPropertiesFactoryTest.java new file mode 100644 index 000000000..19e1429ff --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/properties/SortedPropertiesFactoryTest.java @@ -0,0 +1,34 @@ +/* + * 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.collections4.properties; + +import org.junit.Assert; +import org.junit.Test; + +public class SortedPropertiesFactoryTest extends AbstractPropertiesFactoryTest { + + public SortedPropertiesFactoryTest() { + super(SortedPropertiesFactory.INSTANCE); + } + + @Override + @Test + public void testInstance() { + Assert.assertNotNull(SortedPropertiesFactory.INSTANCE); + } +} diff --git a/src/test/resources/properties/test.properties b/src/test/resources/properties/test.properties new file mode 100644 index 000000000..94a377e0f --- /dev/null +++ b/src/test/resources/properties/test.properties @@ -0,0 +1,25 @@ +# 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. +key1 = value1 +key2 = value2 +key3 = value3 +key4 = value4 +key5 = value5 +key6 = value6 +key7 = value7 +key8 = value8 +key9 = value9 +key10 = value10 +key11 = value11