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 * https://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.builder;
18
19 import java.io.File;
20 import java.net.URL;
21 import java.util.Map;
22
23 import org.apache.commons.configuration2.io.FileHandler;
24 import org.apache.commons.configuration2.io.FileLocationStrategy;
25 import org.apache.commons.configuration2.io.FileSystem;
26 import org.apache.commons.configuration2.io.URLConnectionOptions;
27
28 /**
29 * <p>
30 * An implementation of {@code BuilderParameters} which contains parameters related to {@code Configuration}
31 * implementations that are loaded from files.
32 * </p>
33 * <p>
34 * The parameters defined here are interpreted by builder implementations that can deal with file-based configurations.
35 * Note that these parameters are typically no initialization properties of configuration objects (i.e. they are not
36 * passed to set methods after the creation of the result configuration). Rather, the parameters object is stored as a
37 * whole in the builder's map with initialization parameters and can be accessed from there.
38 * </p>
39 * <p>
40 * This class is not thread-safe. It is intended that an instance is constructed and initialized by a single thread
41 * during configuration of a {@code ConfigurationBuilder}.
42 * </p>
43 *
44 * @since 2.0
45 */
46 public class FileBasedBuilderParametersImpl extends BasicBuilderParameters implements FileBasedBuilderProperties<FileBasedBuilderParametersImpl> {
47 /** Constant for the key in the parameters map used by this class. */
48 private static final String PARAM_KEY = RESERVED_PARAMETER_PREFIX + "fileBased";
49
50 /** Property name for the reloading refresh delay. */
51 private static final String PROP_REFRESH_DELAY = "reloadingRefreshDelay";
52
53 /** Property name of the reloading detector factory. */
54 private static final String PROP_DETECTOR_FACTORY = "reloadingDetectorFactory";
55
56 /**
57 * Creates a new {@code FileBasedBuilderParametersImpl} object from the content of the given map. While
58 * {@code fromParameters()} expects that an object already exists and is stored in the given map, this method creates a
59 * new instance based on the content of the map. The map can contain properties of a {@code FileHandler} and some
60 * additional settings which are stored directly in the newly created object. If the map is <strong>null</strong>, an
61 * uninitialized instance is returned.
62 *
63 * @param map the map with properties (must not be <strong>null</strong>)
64 * @return the newly created instance
65 * @throws ClassCastException if the map contains invalid data
66 */
67 public static FileBasedBuilderParametersImpl fromMap(final Map<String, ?> map) {
68 final FileBasedBuilderParametersImpl params = new FileBasedBuilderParametersImpl(FileHandler.fromMap(map));
69 if (map != null) {
70 params.setReloadingRefreshDelay((Long) map.get(PROP_REFRESH_DELAY));
71 params.setReloadingDetectorFactory((ReloadingDetectorFactory) map.get(PROP_DETECTOR_FACTORY));
72 }
73 return params;
74 }
75
76 /**
77 * Looks up an instance of this class in the specified parameters map. This is equivalent to
78 * {@code fromParameters(params, false};}
79 *
80 * @param params the map with parameters (must not be <strong>null</strong>
81 * @return the instance obtained from the map or <strong>null</strong>
82 * @throws IllegalArgumentException if the map is <strong>null</strong>
83 */
84 public static FileBasedBuilderParametersImpl fromParameters(final Map<String, ?> params) {
85 return fromParameters(params, false);
86 }
87
88 /**
89 * Looks up an instance of this class in the specified parameters map and optionally creates a new one if none is found.
90 * This method can be used to obtain an instance of this class which has been stored in a parameters map. It is
91 * compatible with the {@code getParameters()} method.
92 *
93 * @param params the map with parameters (must not be <strong>null</strong>
94 * @param createIfMissing determines the behavior if no instance is found in the map; if <strong>true</strong>, a new instance
95 * with default settings is created; if <strong>false</strong>, <strong>null</strong> is returned
96 * @return the instance obtained from the map or <strong>null</strong>
97 * @throws IllegalArgumentException if the map is <strong>null</strong>
98 */
99 public static FileBasedBuilderParametersImpl fromParameters(final Map<String, ?> params, final boolean createIfMissing) {
100 if (params == null) {
101 throw new IllegalArgumentException("Parameters map must not be null!");
102 }
103
104 FileBasedBuilderParametersImpl instance = (FileBasedBuilderParametersImpl) params.get(PARAM_KEY);
105 if (instance == null && createIfMissing) {
106 instance = new FileBasedBuilderParametersImpl();
107 }
108 return instance;
109 }
110
111 /**
112 * Stores the associated file handler for the location of the configuration.
113 */
114 private FileHandler fileHandler;
115
116 /** The factory for reloading detectors. */
117 private ReloadingDetectorFactory reloadingDetectorFactory;
118
119 /** The refresh delay for reloading support. */
120 private Long reloadingRefreshDelay;
121
122 /**
123 * Creates a new instance of {@code FileBasedBuilderParametersImpl} with an uninitialized {@code FileHandler} object.
124 */
125 public FileBasedBuilderParametersImpl() {
126 this(null);
127 }
128
129 /**
130 * Creates a new instance of {@code FileBasedBuilderParametersImpl} and associates it with the given {@code FileHandler}
131 * object. If the handler is <strong>null</strong>, a new handler instance is created.
132 *
133 * @param handler the associated {@code FileHandler} (can be <strong>null</strong>)
134 */
135 public FileBasedBuilderParametersImpl(final FileHandler handler) {
136 fileHandler = handler != null ? handler : new FileHandler();
137 }
138
139 /**
140 * {@inheritDoc} This implementation also creates a copy of the {@code FileHandler}.
141 */
142 @Override
143 public FileBasedBuilderParametersImpl clone() {
144 final FileBasedBuilderParametersImpl copy = (FileBasedBuilderParametersImpl) super.clone();
145 copy.fileHandler = new FileHandler(fileHandler.getContent(), fileHandler);
146 return copy;
147 }
148
149 /**
150 * Gets the {@code FileHandler} managed by this object. This object is updated every time the file location is
151 * changed.
152 *
153 * @return the managed {@code FileHandler}
154 */
155 public FileHandler getFileHandler() {
156 return fileHandler;
157 }
158
159 /**
160 * {@inheritDoc} This implementation returns a map which contains this object itself under a specific key. The static
161 * {@code fromParameters()} method can be used to extract an instance from a parameters map. Of course, the properties
162 * inherited from the base class are also added to the result map.
163 */
164 @Override
165 public Map<String, Object> getParameters() {
166 final Map<String, Object> params = super.getParameters();
167 params.put(PARAM_KEY, this);
168 return params;
169 }
170
171 /**
172 * Gets the {@code ReloadingDetectorFactory}. Result may be <strong>null</strong> which means that the default factory is to be
173 * used.
174 *
175 * @return the {@code ReloadingDetectorFactory}
176 */
177 public ReloadingDetectorFactory getReloadingDetectorFactory() {
178 return reloadingDetectorFactory;
179 }
180
181 /**
182 * Gets the refresh delay for reload operations. Result may be <strong>null</strong> if this value has not been set.
183 *
184 * @return the reloading refresh delay
185 */
186 public Long getReloadingRefreshDelay() {
187 return reloadingRefreshDelay;
188 }
189
190 /**
191 * {@inheritDoc} This implementation takes some properties defined in this class into account.
192 */
193 @Override
194 public void inheritFrom(final Map<String, ?> source) {
195 super.inheritFrom(source);
196
197 final FileBasedBuilderParametersImpl srcParams = fromParameters(source);
198 if (srcParams != null) {
199 setFileSystem(srcParams.getFileHandler().getFileSystem());
200 setLocationStrategy(srcParams.getFileHandler().getLocationStrategy());
201 if (srcParams.getFileHandler().getEncoding() != null) {
202 setEncoding(srcParams.getFileHandler().getEncoding());
203 }
204 if (srcParams.getReloadingDetectorFactory() != null) {
205 setReloadingDetectorFactory(srcParams.getReloadingDetectorFactory());
206 }
207 if (srcParams.getReloadingRefreshDelay() != null) {
208 setReloadingRefreshDelay(srcParams.getReloadingRefreshDelay());
209 }
210 }
211 }
212
213 @Override
214 public FileBasedBuilderParametersImpl setBasePath(final String path) {
215 getFileHandler().setBasePath(path);
216 return this;
217 }
218
219 @Override
220 public FileBasedBuilderParametersImpl setEncoding(final String enc) {
221 getFileHandler().setEncoding(enc);
222 return this;
223 }
224
225 @Override
226 public FileBasedBuilderParametersImpl setFile(final File file) {
227 getFileHandler().setFile(file);
228 return this;
229 }
230
231 @Override
232 public FileBasedBuilderParametersImpl setFileName(final String name) {
233 getFileHandler().setFileName(name);
234 return this;
235 }
236
237 @Override
238 public FileBasedBuilderParametersImpl setFileSystem(final FileSystem fs) {
239 getFileHandler().setFileSystem(fs);
240 return this;
241 }
242
243 @Override
244 public FileBasedBuilderParametersImpl setLocationStrategy(final FileLocationStrategy strategy) {
245 getFileHandler().setLocationStrategy(strategy);
246 return this;
247 }
248
249 @Override
250 public FileBasedBuilderParametersImpl setPath(final String path) {
251 getFileHandler().setPath(path);
252 return this;
253 }
254
255 @Override
256 public FileBasedBuilderParametersImpl setReloadingDetectorFactory(final ReloadingDetectorFactory reloadingDetectorFactory) {
257 this.reloadingDetectorFactory = reloadingDetectorFactory;
258 return this;
259 }
260
261 @Override
262 public FileBasedBuilderParametersImpl setReloadingRefreshDelay(final Long reloadingRefreshDelay) {
263 this.reloadingRefreshDelay = reloadingRefreshDelay;
264 return this;
265 }
266
267 @Override
268 public FileBasedBuilderParametersImpl setURL(final URL url) {
269 getFileHandler().setURL(url);
270 return this;
271 }
272
273 @Override
274 public FileBasedBuilderParametersImpl setURL(final URL url, final URLConnectionOptions urlConnectionOptions) {
275 getFileHandler().setURL(url, urlConnectionOptions);
276 return this;
277 }
278 }