1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.configuration2.io; 18 19 import java.net.URL; 20 import java.util.ArrayList; 21 import java.util.Collection; 22 import java.util.Collections; 23 24 /** 25 * <p> 26 * A specialized implementation of a {@code FileLocationStrategy} which encapsulates an arbitrary number of 27 * {@code FileLocationStrategy} objects. 28 * </p> 29 * <p> 30 * A collection with the wrapped {@code FileLocationStrategy} objects is passed at construction time. During a 31 * [{@code locate()} operation the wrapped strategies are called one after the other until one returns a non <b>null</b> 32 * URL. This URL is returned. If none of the wrapped strategies is able to resolve the passed in {@link FileLocator}, 33 * result is <b>null</b>. This is similar to the <em>chain of responsibility</em> design pattern. 34 * </p> 35 * <p> 36 * This class, together with the provided concrete {@code FileLocationStrategy} implementations, offers a convenient way 37 * to customize the lookup for configuration files: Just add the desired concrete strategies to a 38 * {@code CombinedLocationStrategy} object. If necessary, custom strategies can be implemented if there are specific 39 * requirements. Note that the order in which strategies are added to a {@code CombinedLocationStrategy} matters: sub 40 * strategies are queried in the same order as they appear in the collection passed to the constructor. 41 * </p> 42 * 43 * @since 2.0 44 */ 45 public class CombinedLocationStrategy implements FileLocationStrategy { 46 /** A collection with all sub strategies managed by this object. */ 47 private final Collection<FileLocationStrategy> subStrategies; 48 49 /** 50 * Creates a new instance of {@code CombinedLocationStrategy} and initializes it with the provided sub strategies. The 51 * passed in collection must not be <b>null</b> or contain <b>null</b> elements. 52 * 53 * @param subs the collection with sub strategies 54 * @throws IllegalArgumentException if the collection is <b>null</b> or has <b>null</b> elements 55 */ 56 public CombinedLocationStrategy(final Collection<? extends FileLocationStrategy> subs) { 57 if (subs == null) { 58 throw new IllegalArgumentException("Collection with sub strategies must not be null!"); 59 } 60 subStrategies = Collections.unmodifiableCollection(new ArrayList<>(subs)); 61 if (subStrategies.contains(null)) { 62 throw new IllegalArgumentException("Collection with sub strategies contains null entry!"); 63 } 64 } 65 66 /** 67 * Gets a (unmodifiable) collection with the sub strategies managed by this object. 68 * 69 * @return the sub {@code FileLocationStrategy} objects 70 */ 71 public Collection<FileLocationStrategy> getSubStrategies() { 72 return subStrategies; 73 } 74 75 /** 76 * {@inheritDoc} This implementation tries to locate the file by delegating to the managed sub strategies. 77 */ 78 @Override 79 public URL locate(final FileSystem fileSystem, final FileLocator locator) { 80 for (final FileLocationStrategy sub : getSubStrategies()) { 81 final URL url = sub.locate(fileSystem, locator); 82 if (url != null) { 83 return url; 84 } 85 } 86 87 return null; 88 } 89 }