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.io;
18
19 import java.net.URL;
20 import java.util.Objects;
21
22 /**
23 * <p>
24 * A class describing the location of a file.
25 * </p>
26 * <p>
27 * An instance of this class provides information for locating and accessing a file. The file location can be defined
28 * </p>
29 * <ul>
30 * <li>as a URL; this identifies a file in a unique way</li>
31 * <li>as a combination of base path and file name; if this variant is used, there may be an additional location step
32 * required in order to identify the referenced file (for instance, the file name may be interpreted as the name of a
33 * resource to be loaded from class path).</li>
34 * </ul>
35 * <p>
36 * In addition, other properties are available which are also needed for loading or saving a file, like the underlying
37 * {@link FileSystem}. The encoding to be used when accessing the represented data is also part of the data contained in
38 * an instance; if no encoding is set explicitly, the platform's default encoding is used.
39 * <p>
40 * Instances of this class are immutable and thus can be safely shared between arbitrary components. {@link FileHandler}
41 * also uses an instance to reference the associated file. Instances are created using a <em>builder</em>.
42 * {@link FileLocatorUtils} offers convenience methods for obtaining such a builder.
43 * </p>
44 *
45 * @since 2.0
46 */
47 public final class FileLocator {
48
49 /**
50 * A typical <em>builder</em> implementation for creating {@code FileLocator} objects. An instance of this class is
51 * returned by the {@code fileLocator()} method of {link FileLocatorUtils}. It can be used to define the various
52 * components of the {@code FileLocator} object. By calling {@code create()} the new immutable {@code FileLocator}
53 * instance is created.
54 */
55 public static final class FileLocatorBuilder {
56
57 /** The base path. */
58 private String basePath;
59
60 /** The encoding. */
61 private String encoding;
62
63 /** The file name. */
64 private String fileName;
65
66 /** The file system. */
67 private FileSystem fileSystem;
68
69 /** The location strategy. */
70 private FileLocationStrategy locationStrategy;
71
72 /** The URL. */
73 private URL sourceURL;
74
75 /** The URL connection options. */
76 private URLConnectionOptions urlConnectionOptions;
77
78 /**
79 * Creates a new instance of {@code FileLocatorBuilder} and initializes the builder's properties from the passed in
80 * {@code FileLocator} object.
81 *
82 * @param src the source {@code FileLocator} (may be <strong>null</strong>)
83 */
84 FileLocatorBuilder(final FileLocator src) {
85 if (src != null) {
86 initBuilder(src);
87 }
88 }
89
90 /**
91 * Specifies the base path of the new {@code FileLocator}.
92 *
93 * @param path the base path
94 * @return a reference to this builder for method chaining
95 */
96 public FileLocatorBuilder basePath(final String path) {
97 basePath = path;
98 return this;
99 }
100
101 /**
102 * Creates a new immutable {@code FileLocatorImpl} object based on the properties set so far for this builder.
103 *
104 * @return the newly created {@code FileLocator} object, never null.
105 */
106 public FileLocator create() {
107 return new FileLocator(this);
108 }
109
110 /**
111 * Specifies the encoding of the new {@code FileLocator}.
112 *
113 * @param enc the encoding
114 * @return a reference to this builder for method chaining
115 */
116 public FileLocatorBuilder encoding(final String enc) {
117 encoding = enc;
118 return this;
119 }
120
121 /**
122 * Specifies the file name of the new {@code FileLocator}.
123 *
124 * @param name the file name
125 * @return a reference to this builder for method chaining
126 */
127 public FileLocatorBuilder fileName(final String name) {
128 fileName = name;
129 return this;
130 }
131
132 /**
133 * Specifies the {@code FileSystem} of the new {@code FileLocator}.
134 *
135 * @param fs the {@code FileSystem}
136 * @return a reference to this builder for method chaining
137 */
138 public FileLocatorBuilder fileSystem(final FileSystem fs) {
139 fileSystem = fs;
140 return this;
141 }
142
143 /**
144 * Initializes the properties of this builder from the passed in locator object.
145 *
146 * @param src the source {@code FileLocator}
147 */
148 private void initBuilder(final FileLocator src) {
149 basePath = src.getBasePath();
150 fileName = src.getFileName();
151 sourceURL = src.getSourceURL();
152 urlConnectionOptions = src.getURLConnectionOptions();
153 encoding = src.getEncoding();
154 fileSystem = src.getFileSystem();
155 locationStrategy = src.getLocationStrategy();
156 }
157
158 /**
159 * Specifies the {@code FileLocationStrategy} to be used when the referenced file is to be located.
160 *
161 * @param strategy the {@code FileLocationStrategy}
162 * @return a reference to this builder for method chaining
163 */
164 public FileLocatorBuilder locationStrategy(final FileLocationStrategy strategy) {
165 locationStrategy = strategy;
166 return this;
167 }
168
169 /**
170 * Specifies the source URL of the new {@code FileLocator}.
171 *
172 * @param url the source URL
173 * @return a reference to this builder for method chaining
174 */
175 public FileLocatorBuilder sourceURL(final URL url) {
176 this.sourceURL = url;
177 return this;
178 }
179
180 /**
181 * Specifies the source URL connection options of the new {@code FileLocator}.
182 *
183 * @param urlConnectionOptions the source URL connection options.
184 * @return a reference to this builder for method chaining
185 */
186 public FileLocatorBuilder urlConnectionOptions(final URLConnectionOptions urlConnectionOptions) {
187 this.urlConnectionOptions = urlConnectionOptions;
188 return this;
189
190 }
191 }
192
193 /** The base path. */
194 private final String basePath;
195
196 /** The encoding. */
197 private final String encoding;
198
199 /** The file name. */
200 private final String fileName;
201
202 /** The file system. */
203 private final FileSystem fileSystem;
204
205 /** The file location strategy. */
206 private final FileLocationStrategy locationStrategy;
207
208 /** The source URL. */
209 private final URL sourceURL;
210
211 /** The source URL connection options. */
212 private final URLConnectionOptions urlConnectionOptions;
213
214 /**
215 * Creates a new instance of {@code FileLocatorImpl} and initializes it from the given builder instance
216 *
217 * @param builder the builder
218 */
219 public FileLocator(final FileLocatorBuilder builder) {
220 fileName = builder.fileName;
221 basePath = builder.basePath;
222 sourceURL = builder.sourceURL;
223 urlConnectionOptions = builder.urlConnectionOptions;
224 encoding = builder.encoding;
225 fileSystem = builder.fileSystem;
226 locationStrategy = builder.locationStrategy;
227 }
228
229 /**
230 * Compares this object with another one. Two instances of {@code FileLocatorImpl} are considered equal if all of their
231 * properties are equal.
232 *
233 * @param obj the object to compare to
234 * @return a flag whether these objects are equal
235 */
236 @Override
237 public boolean equals(final Object obj) {
238 if (this == obj) {
239 return true;
240 }
241 if (!(obj instanceof FileLocator)) {
242 return false;
243 }
244 final FileLocator other = (FileLocator) obj;
245 return Objects.equals(basePath, other.basePath) && Objects.equals(encoding, other.encoding) && Objects.equals(fileName, other.fileName)
246 && Objects.equals(fileSystem, other.fileSystem) && Objects.equals(locationStrategy, other.locationStrategy)
247 && Objects.equals(sourceURL, other.sourceURL) && Objects.equals(urlConnectionOptions, other.urlConnectionOptions);
248 }
249
250 /**
251 * Gets the base path stored in this locator or <strong>null</strong> if it is undefined.
252 *
253 * @return the base path
254 */
255 public String getBasePath() {
256 return basePath;
257 }
258
259 /**
260 * Gets the encoding stored in this locator or <strong>null</strong> if it is undefined.
261 *
262 * @return the encoding
263 */
264 public String getEncoding() {
265 return encoding;
266 }
267
268 /**
269 * Gets the file name stored in this locator or <strong>null</strong> if it is undefined.
270 *
271 * @return the file name
272 */
273 public String getFileName() {
274 return fileName;
275 }
276
277 /**
278 * Gets the {@code FileSystem} to be used for accessing the file referenced by this locator or <strong>null</strong> if it is
279 * undefined.
280 *
281 * @return the {@code FileSystem}
282 */
283 public FileSystem getFileSystem() {
284 return fileSystem;
285 }
286
287 /**
288 * Gets the {@code FileLocationStrategy} to be used for locating the referenced file. If no specific
289 * {@code FileLocationStrategy} has been set, result is <strong>null</strong>. This means that the default strategy should be
290 * used.
291 *
292 * @return the {@code FileLocationStrategy} to be used
293 */
294 public FileLocationStrategy getLocationStrategy() {
295 return locationStrategy;
296 }
297
298 /**
299 * Gets the URL pointing to the referenced source file or <strong>null</strong> if it is undefined.
300 *
301 * @return the source URL
302 */
303 public URL getSourceURL() {
304 return sourceURL;
305 }
306
307 /**
308 * Gets the URLConnectionOptions
309 *
310 * @return the URLConnectionOptions
311 */
312 public URLConnectionOptions getURLConnectionOptions() {
313 return urlConnectionOptions;
314 }
315
316 /**
317 * Returns a hash code for this object.
318 *
319 * @return a hash code for this object
320 */
321 @Override
322 public int hashCode() {
323 return Objects.hash(basePath, encoding, fileName, fileSystem, locationStrategy, sourceURL, urlConnectionOptions);
324 }
325
326 @Override
327 public String toString() {
328 return "FileLocator [basePath=" + basePath + ", encoding=" + encoding + ", fileName=" + fileName + ", fileSystem=" + fileSystem + ", locationStrategy="
329 + locationStrategy + ", sourceURL=" + sourceURL + ", urlConnectionOptions=" + urlConnectionOptions + "]";
330 }
331 }