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 2013/09/22 19:51:29 UTC
svn commit: r1525402 - in /commons/proper/configuration/trunk/src:
main/java/org/apache/commons/configuration/io/CombinedLocationStrategy.java
test/java/org/apache/commons/configuration/io/TestCombinedLocationStrategy.java
Author: oheger
Date: Sun Sep 22 17:51:28 2013
New Revision: 1525402
URL: http://svn.apache.org/r1525402
Log:
Added CombinedLocationStrategy class.
This class allows the creation of a custom FileLocationStrategy based on other
"primitive" strategies. Arbitrary combinations can be created to adapt the
location algorithm to very specific requirements.
Added:
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/CombinedLocationStrategy.java
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestCombinedLocationStrategy.java
Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/CombinedLocationStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/CombinedLocationStrategy.java?rev=1525402&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/CombinedLocationStrategy.java (added)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/CombinedLocationStrategy.java Sun Sep 22 17:51:28 2013
@@ -0,0 +1,112 @@
+/*
+ * 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.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * <p>
+ * A specialized implementation of a {@code FileLocationStrategy} which
+ * encapsulates an arbitrary number of {@code FileLocationStrategy} objects.
+ * </p>
+ * <p>
+ * A collection with the wrapped {@code FileLocationStrategy} objects is passed
+ * at construction time. During a [{@code locate()} operation the wrapped
+ * strategies are called one after the other until one returns a non <b>null</b>
+ * URL. This URL is returned. If none of the wrapped strategies is able to
+ * resolve the passed in {@link FileLocator}, result is <b>null</b>. This is
+ * similar to the <em>chain of responsibility</em> design pattern.
+ * </p>
+ * <p>
+ * This class, together with the provided concrete {@code FileLocationStrategy}
+ * implementations, offers a convenient way to customize the lookup for
+ * configuration files: Just add the desired concrete strategies to a
+ * {@code CombinedLocationStrategy} object. If necessary, custom strategies can
+ * be implemented if there are specific requirements. Note that the order in
+ * which strategies are added to a {@code CombinedLocationStrategy} matters: sub
+ * strategies are queried in the same order as they appear in the collection
+ * passed to the constructor.
+ * </p>
+ *
+ * @version $Id: $
+ * @since 2.0
+ */
+public class CombinedLocationStrategy implements FileLocationStrategy
+{
+ /** A collection with all sub strategies managed by this object. */
+ private final Collection<FileLocationStrategy> subStrategies;
+
+ /**
+ * Creates a new instance of {@code CombinedLocationStrategy} and
+ * initializes it with the provided sub strategies. The passed in collection
+ * must not be <b>null</b> or contain <b>null</b> elements.
+ *
+ * @param subs the collection with sub strategies
+ * @throws IllegalArgumentException if the collection is <b>null</b> or has
+ * <b>null</b> elements
+ */
+ public CombinedLocationStrategy(
+ Collection<? extends FileLocationStrategy> subs)
+ {
+ if (subs == null)
+ {
+ throw new IllegalArgumentException(
+ "Collection with sub strategies must not be null!");
+ }
+ subStrategies =
+ Collections
+ .unmodifiableCollection(new ArrayList<FileLocationStrategy>(
+ subs));
+ if (subStrategies.contains(null))
+ {
+ throw new IllegalArgumentException(
+ "Collection with sub strategies contains null entry!");
+ }
+ }
+
+ /**
+ * Returns a (unmodifiable) collection with the sub strategies managed by
+ * this object.
+ *
+ * @return the sub {@code FileLocationStrategy} objects
+ */
+ public Collection<FileLocationStrategy> getSubStrategies()
+ {
+ return subStrategies;
+ }
+
+ /**
+ * {@inheritDoc} This implementation tries to locate the file by delegating
+ * to the managed sub strategies.
+ */
+ public URL locate(FileSystem fileSystem, FileLocator locator)
+ {
+ for (FileLocationStrategy sub : getSubStrategies())
+ {
+ URL url = sub.locate(fileSystem, locator);
+ if (url != null)
+ {
+ return url;
+ }
+ }
+
+ return null;
+ }
+}
Added: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestCombinedLocationStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestCombinedLocationStrategy.java?rev=1525402&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestCombinedLocationStrategy.java (added)
+++ commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestCombinedLocationStrategy.java Sun Sep 22 17:51:28 2013
@@ -0,0 +1,237 @@
+/*
+ * 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 java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.apache.commons.configuration.ConfigurationAssert;
+import org.easymock.EasyMock;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test class for {@code CombinedLocationStrategy}.
+ *
+ * @version $Id: $
+ */
+public class TestCombinedLocationStrategy
+{
+ /** A test locator. */
+ private static FileLocator locator;
+
+ /** A URL indicating a successful locate() operation. */
+ private static URL locateURL;
+
+ /** A mock for the file system. */
+ private FileSystem fileSystem;
+
+ /** An array with mock sub strategies. */
+ private FileLocationStrategy[] subStrategies;
+
+ @BeforeClass
+ public static void setUpOnce() throws Exception
+ {
+ locator =
+ FileLocatorUtils.fileLocator().fileName("testFile.tst")
+ .create();
+ locateURL = ConfigurationAssert.getTestURL("test.xml");
+ }
+
+ /**
+ * Returns the mock file system. It is created on demand.
+ *
+ * @return the mock file system
+ */
+ private FileSystem getFileSystem()
+ {
+ if (fileSystem == null)
+ {
+ fileSystem = EasyMock.createMock(FileSystem.class);
+ EasyMock.replay(fileSystem);
+ }
+ return fileSystem;
+ }
+
+ /**
+ * Returns an array with mock objects for sub strategies.
+ *
+ * @return the array with mock strategies
+ */
+ private FileLocationStrategy[] getSubStrategies()
+ {
+ if (subStrategies == null)
+ {
+ subStrategies = new FileLocationStrategy[2];
+ for (int i = 0; i < subStrategies.length; i++)
+ {
+ subStrategies[i] =
+ EasyMock.createMock(FileLocationStrategy.class);
+ }
+ }
+ return subStrategies;
+ }
+
+ /**
+ * Replays the mock objects for the sub strategies.
+ */
+ private void replaySubStrategies()
+ {
+ EasyMock.replay((Object[]) getSubStrategies());
+ }
+
+ /**
+ * Verifies the mock objects for the sub strategies.
+ */
+ private void verifySubStrategies()
+ {
+ EasyMock.verify((Object[]) getSubStrategies());
+ }
+
+ /**
+ * Checks whether the passed in combined strategy contains the expected sub
+ * strategies.
+ *
+ * @param strategy the combined strategy to check
+ */
+ private void checkSubStrategies(CombinedLocationStrategy strategy)
+ {
+ Collection<FileLocationStrategy> subs = strategy.getSubStrategies();
+ assertEquals("Wrong number of strategies", getSubStrategies().length,
+ subs.size());
+ int idx = 0;
+ for (FileLocationStrategy strat : subs)
+ {
+ assertEquals("Wrong sub strategy at " + idx,
+ getSubStrategies()[idx++], strat);
+ }
+ }
+
+ /**
+ * Helper method for creating a combined strategy with the mock sub
+ * strategies.
+ *
+ * @return the newly created combined strategy
+ */
+ private CombinedLocationStrategy createCombinedStrategy()
+ {
+ return new CombinedLocationStrategy(Arrays.asList(getSubStrategies()));
+ }
+
+ /**
+ * Tries to create an instance with a null collection.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInitNullCollection()
+ {
+ new CombinedLocationStrategy(null);
+ }
+
+ /**
+ * Tries to create an instance containing a null element.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInitCollectionWithNullEntries()
+ {
+ Collection<FileLocationStrategy> col =
+ new LinkedList<FileLocationStrategy>(
+ Arrays.asList(getSubStrategies()));
+ col.add(null);
+ new CombinedLocationStrategy(col);
+ }
+
+ /**
+ * Tests whether a defensive copy of the collection with sub strategies is
+ * made.
+ */
+ @Test
+ public void testInitDefensiveCopy()
+ {
+ Collection<FileLocationStrategy> col =
+ new LinkedList<FileLocationStrategy>(
+ Arrays.asList(getSubStrategies()));
+ CombinedLocationStrategy strategy = new CombinedLocationStrategy(col);
+ col.add(EasyMock.createMock(FileLocationStrategy.class));
+ checkSubStrategies(strategy);
+ }
+
+ /**
+ * Tests that the collection with sub strategies cannot be modified.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetSubStrategiesModify()
+ {
+ CombinedLocationStrategy strategy = createCombinedStrategy();
+ strategy.getSubStrategies().clear();
+ }
+
+ /**
+ * Tests a successful locate() operation if the first sub strategy can
+ * locate the file.
+ */
+ @Test
+ public void testLocateSuccessFirstSubStrategy()
+ {
+ EasyMock.expect(getSubStrategies()[0].locate(getFileSystem(), locator))
+ .andReturn(locateURL);
+ replaySubStrategies();
+ CombinedLocationStrategy strategy = createCombinedStrategy();
+ assertSame("Wrong result", locateURL,
+ strategy.locate(getFileSystem(), locator));
+ verifySubStrategies();
+ }
+
+ /**
+ * Tests a successful locate() operation if the 2nd sub strategy can locate
+ * the file.
+ */
+ @Test
+ public void testLocateSuccessSecondSubStrategy()
+ {
+ EasyMock.expect(getSubStrategies()[0].locate(getFileSystem(), locator))
+ .andReturn(null);
+ EasyMock.expect(getSubStrategies()[1].locate(getFileSystem(), locator))
+ .andReturn(locateURL);
+ replaySubStrategies();
+ CombinedLocationStrategy strategy = createCombinedStrategy();
+ assertSame("Wrong result", locateURL,
+ strategy.locate(getFileSystem(), locator));
+ verifySubStrategies();
+ }
+
+ /**
+ * Tests a failed locate() operation.
+ */
+ @Test
+ public void testLocateFailed()
+ {
+ EasyMock.expect(getSubStrategies()[0].locate(getFileSystem(), locator))
+ .andReturn(null);
+ EasyMock.expect(getSubStrategies()[1].locate(getFileSystem(), locator))
+ .andReturn(null);
+ replaySubStrategies();
+ CombinedLocationStrategy strategy = createCombinedStrategy();
+ assertNull("Got a URL", strategy.locate(getFileSystem(), locator));
+ verifySubStrategies();
+ }
+}