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