View Javadoc
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 static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  import static org.mockito.ArgumentMatchers.any;
28  import static org.mockito.Mockito.mock;
29  import static org.mockito.Mockito.verify;
30  import static org.mockito.Mockito.verifyNoMoreInteractions;
31  import static org.mockito.Mockito.when;
32  
33  import java.io.File;
34  import java.net.MalformedURLException;
35  import java.net.URI;
36  import java.net.URISyntaxException;
37  import java.net.URL;
38  import java.nio.charset.StandardCharsets;
39  import java.util.HashMap;
40  import java.util.Iterator;
41  import java.util.Map;
42  
43  import org.apache.commons.configuration2.ConfigurationAssert;
44  import org.apache.commons.configuration2.XMLConfiguration;
45  import org.apache.commons.configuration2.ex.ConfigurationException;
46  import org.junit.jupiter.api.BeforeAll;
47  import org.junit.jupiter.api.Test;
48  
49  /**
50   * Test class for {@code FileLocatorUtils}.
51   */
52  public class TestFileLocatorUtils {
53  
54      /** Constant for a file name. */
55      private static final String FILE_NAME = "test.xml";
56  
57      /** Constant for a base path. */
58      private static final String BASE_PATH = "/etc/test/path/";
59  
60      /** Constant for a test encoding. */
61      private static final String ENCODING = StandardCharsets.UTF_8.name();
62  
63      /** A test URL. */
64      private static URL sourceURL;
65  
66      /** A test file system. */
67      private static FileSystem fileSystem;
68  
69      /**
70       * Checks whether the specified locator points to the expected test configuration file.
71       *
72       * @param locator the locator to check
73       * @throws ConfigurationException if an error occurs
74       */
75      private static void checkFullyInitializedLocator(final FileLocator locator) throws ConfigurationException {
76          assertNotNull(locator.getBasePath());
77          assertNotNull(locator.getFileName());
78          assertNotNull(locator.getSourceURL());
79  
80          FileHandler handler = new FileHandler();
81          handler.setBasePath(locator.getBasePath());
82          handler.setFileName(locator.getFileName());
83          checkTestConfiguration(handler);
84  
85          handler = new FileHandler();
86          handler.setURL(locator.getSourceURL());
87          checkTestConfiguration(handler);
88      }
89  
90      /**
91       * Checks whether the expected test configuration can be loaded using the specified handler.
92       *
93       * @param handler the file handler
94       * @throws ConfigurationException if an error occurs
95       */
96      private static void checkTestConfiguration(final FileHandler handler) throws ConfigurationException {
97          final XMLConfiguration config = new XMLConfiguration();
98          final FileHandler h2 = new FileHandler(config, handler);
99          h2.load();
100         assertEquals("value", config.getString("element"));
101     }
102 
103     @BeforeAll
104     public static void setUpOnce() throws Exception {
105         sourceURL = ConfigurationAssert.getTestURL(FILE_NAME);
106         fileSystem = mock(FileSystem.class);
107     }
108 
109     /**
110      * Tests a successful conversion from a file to a URL.
111      */
112     @Test
113     void testConvertFileToURL() throws ConfigurationException {
114         final File file = ConfigurationAssert.getTestFile(FILE_NAME);
115         final FileHandler handler = new FileHandler();
116         handler.setURL(FileLocatorUtils.convertFileToURL(file));
117         checkTestConfiguration(handler);
118     }
119 
120     /**
121      * Tests whether exceptions are handled when converting a URI to a URL.
122      */
123     @Test
124     void testConvertToURIException() throws URISyntaxException {
125         final URI uri = new URI("test://test/path/file.tst");
126         assertNull(FileLocatorUtils.convertURIToURL(uri));
127     }
128 
129     /**
130      * Tests the definition of the default location strategy.
131      */
132     @Test
133     void testDefaultFileLocationStrategy() {
134         final CombinedLocationStrategy strategy = (CombinedLocationStrategy) FileLocatorUtils.DEFAULT_LOCATION_STRATEGY;
135         final Iterator<FileLocationStrategy> it = strategy.getSubStrategies().iterator();
136         assertInstanceOf(ProvidedURLLocationStrategy.class, it.next());
137         assertInstanceOf(FileSystemLocationStrategy.class, it.next());
138         assertInstanceOf(AbsoluteNameLocationStrategy.class, it.next());
139         assertInstanceOf(BasePathLocationStrategy.class, it.next());
140         FileLocationStrategy sub = it.next();
141         HomeDirectoryLocationStrategy subStrategy = assertInstanceOf(HomeDirectoryLocationStrategy.class, sub);
142         assertTrue(subStrategy.isEvaluateBasePath());
143         sub = it.next();
144         subStrategy = assertInstanceOf(HomeDirectoryLocationStrategy.class, sub);
145         assertFalse(subStrategy.isEvaluateBasePath());
146         assertInstanceOf(ClasspathLocationStrategy.class, it.next());
147     }
148 
149     /**
150      * Tests whether fileFromURL() handles null URLs correctly.
151      */
152     @Test
153     void testFileFromURLNull() throws Exception {
154         assertNull(FileLocatorUtils.fileFromURL(null));
155     }
156 
157     /**
158      * Tests whether an encoded "%" character in the file name is handled correctly by fileFromURL(). This test is related
159      * to CONFIGURATION-521.
160      */
161     @Test
162     void testFileFromURLWithEncodedPercent() throws MalformedURLException {
163         final File file = new File("https%3A%2F%2Fwww.apache.org%2F.url").getAbsoluteFile();
164         final URL fileURL = file.toURI().toURL();
165         final File file2 = FileLocatorUtils.fileFromURL(fileURL);
166         assertEquals(file, file2);
167     }
168 
169     /**
170      * Tests whether a "+" character in the file name is handled correctly by fileFromURL(). This test is related to
171      * CONFIGURATION-415.
172      */
173     @Test
174     void testFileFromURLWithPlus() throws MalformedURLException {
175         final File file = new File(new File("target"), "foo+bar.txt").getAbsoluteFile();
176         final URL fileURL = file.toURI().toURL();
177         final File file2 = FileLocatorUtils.fileFromURL(fileURL);
178         assertEquals(file, file2);
179     }
180 
181     /**
182      * Tests whether fromMap() can handle a null map.
183      */
184     @Test
185     void testFromMapNoMap() {
186         final FileLocator fileLocator = FileLocatorUtils.fromMap(null);
187         assertEquals(FileLocatorUtils.fileLocator().create(), fileLocator);
188     }
189 
190     /**
191      * Tests fullyInitializedLocator() if the locator is already fully initialized.
192      */
193     @Test
194     void testFullyInitializedLocatorAlreadyComplete() {
195         final FileLocator locator = FileLocatorUtils.fileLocator().fileName(FILE_NAME).create();
196         final FileLocator fullLocator = FileLocatorUtils.fullyInitializedLocator(locator);
197         assertSame(fullLocator, FileLocatorUtils.fullyInitializedLocator(fullLocator));
198     }
199 
200     /**
201      * Tests whether a fully initialized locator can be obtained if a file name is available.
202      */
203     @Test
204     void testFullyInitializedLocatorFileName() throws ConfigurationException {
205         final FileLocator locator = FileLocatorUtils.fileLocator().fileName(FILE_NAME).create();
206         checkFullyInitializedLocator(FileLocatorUtils.fullyInitializedLocator(locator));
207     }
208 
209     /**
210      * Tests fullyInitializedLocator() if a locate() operation fails.
211      */
212     @Test
213     void testFullyInitializedLocatorLocateFails() {
214         final FileLocator locator = FileLocatorUtils.fileLocator().fileName("non existing file").create();
215         assertNull(FileLocatorUtils.fullyInitializedLocator(locator));
216     }
217 
218     /**
219      * Tries to obtain a fully initialized locator if the source locator is not defined.
220      */
221     @Test
222     void testFullyInitializedLocatorUndefined() {
223         assertNull(FileLocatorUtils.fullyInitializedLocator(FileLocatorUtils.fileLocator().create()));
224     }
225 
226     /**
227      * Tests whether a fully initialized locator can be obtained if a URL is available.
228      */
229     @Test
230     void testFullyInitializedLocatorURL() throws ConfigurationException {
231         final FileLocator locator = FileLocatorUtils.fileLocator().sourceURL(sourceURL).create();
232         checkFullyInitializedLocator(FileLocatorUtils.fullyInitializedLocator(locator));
233     }
234 
235     @Test
236     void testGetBasePath() throws Exception {
237         URL url = new URL("http://xyz.net/foo/bar.xml");
238         assertEquals("http://xyz.net/foo/", FileLocatorUtils.getBasePath(url));
239 
240         url = new URL("http://xyz.net/foo/");
241         assertEquals("http://xyz.net/foo/", FileLocatorUtils.getBasePath(url));
242 
243         url = new URL("http://xyz.net/foo");
244         assertEquals("http://xyz.net/", FileLocatorUtils.getBasePath(url));
245 
246         url = new URL("http://xyz.net/");
247         assertEquals("http://xyz.net/", FileLocatorUtils.getBasePath(url));
248 
249         url = new URL("http://xyz.net");
250         assertEquals("http://xyz.net", FileLocatorUtils.getBasePath(url));
251     }
252 
253     @Test
254     void testGetFile() throws Exception {
255         final File directory = new File("target");
256         final File reference = new File(directory, "test.txt").getAbsoluteFile();
257 
258         assertEquals(FileLocatorUtils.getFile(null, reference.getAbsolutePath()), reference);
259         assertEquals(FileLocatorUtils.getFile(directory.getAbsolutePath(), reference.getAbsolutePath()), reference);
260         assertEquals(FileLocatorUtils.getFile(directory.getAbsolutePath(), reference.getName()), reference);
261         assertEquals(FileLocatorUtils.getFile(directory.toURI().toURL().toString(), reference.getName()), reference);
262         assertEquals(FileLocatorUtils.getFile("invalid", reference.toURI().toURL().toString()), reference);
263         assertEquals(FileLocatorUtils.getFile("jar:file:/C:/myjar.jar!/my-config.xml/someprops.properties", reference.getAbsolutePath()), reference);
264     }
265 
266     @Test
267     void testGetFileName() throws Exception {
268         assertNull(FileLocatorUtils.getFileName(null));
269 
270         URL url = new URL("http://xyz.net/foo/");
271         assertNull(FileLocatorUtils.getFileName(url));
272 
273         url = new URL("http://xyz.net/foo/bar.xml");
274         assertEquals("bar.xml", FileLocatorUtils.getFileName(url));
275     }
276 
277     /**
278      * Tests whether a missing base path is detected when checking for a fully initialized locator.
279      */
280     @Test
281     void testIsFullyInitializedNoBasePath() {
282         final FileLocator locator = FileLocatorUtils.fileLocator().sourceURL(ConfigurationAssert.getTestURL(FILE_NAME)).fileName(FILE_NAME).create();
283         assertFalse(FileLocatorUtils.isFullyInitialized(locator));
284     }
285 
286     /**
287      * Tests isFullyInitialized() for null input.
288      */
289     @Test
290     void testIsFullyInitializedNull() {
291         assertFalse(FileLocatorUtils.isFullyInitialized(null));
292     }
293 
294     /**
295      * Tests isLocationDefined() if no location is defined.
296      */
297     @Test
298     void testIsLocationDefinedFalse() {
299         final FileLocator locator = FileLocatorUtils.fileLocator().encoding(ENCODING).basePath(BASE_PATH).fileSystem(FileLocatorUtils.DEFAULT_FILE_SYSTEM)
300             .create();
301         assertFalse(FileLocatorUtils.isLocationDefined(locator));
302     }
303 
304     /**
305      * Tests isLocationDefined() if a file name is set.
306      */
307     @Test
308     void testIsLocationDefinedFileName() {
309         final FileLocator locator = FileLocatorUtils.fileLocator().fileName(FILE_NAME).create();
310         assertTrue(FileLocatorUtils.isLocationDefined(locator));
311     }
312 
313     /**
314      * Tests whether isLocationDefined() can handle null input.
315      */
316     @Test
317     void testIsLocationDefinedNull() {
318         assertFalse(FileLocatorUtils.isLocationDefined(null));
319     }
320 
321     /**
322      * Tests isLocationDefined() if a URL is set.
323      */
324     @Test
325     void testIsLocationDefinedURL() {
326         final FileLocator locator = FileLocatorUtils.fileLocator().sourceURL(ConfigurationAssert.getTestURL(FILE_NAME)).create();
327         assertTrue(FileLocatorUtils.isLocationDefined(locator));
328     }
329 
330     /**
331      * Tests a locate() operation with a null locator.
332      */
333     @Test
334     void testLocateNullLocator() {
335         assertNull(FileLocatorUtils.locate(null));
336     }
337 
338     /**
339      * Tests whether an exception is thrown for a failed locate() operation.
340      */
341     @Test
342     void testLocateOrThrowFailed() {
343         final FileLocationStrategy strategy = mock(FileLocationStrategy.class);
344 
345         when(strategy.locate(any(), any())).thenReturn(null);
346 
347         final FileLocator locator = FileLocatorUtils.fileLocator().locationStrategy(strategy).create();
348         assertThrows(ConfigurationException.class, () -> FileLocatorUtils.locateOrThrow(locator));
349     }
350 
351     /**
352      * Tests a successful locate() operation that uses defaults for location strategy and file system.
353      */
354     @Test
355     void testLocateSuccessWithDefaults() {
356         final FileLocator locator = FileLocatorUtils.fileLocator().sourceURL(sourceURL).create();
357         assertSame(sourceURL, FileLocatorUtils.locate(locator));
358     }
359 
360     /**
361      * Tests a successful locate() operation if the passed in locator contains a strategy and a file system.
362      */
363     @Test
364     void testLocateSuccessWithStrategyAndFileSystem() throws ConfigurationException {
365         final FileSystem fs = mock(FileSystem.class);
366         final FileLocationStrategy strategy = mock(FileLocationStrategy.class);
367         final FileLocator locator = FileLocatorUtils.fileLocator().fileSystem(fs).locationStrategy(strategy).create();
368 
369         when(strategy.locate(fs, locator)).thenReturn(sourceURL);
370 
371         assertSame(sourceURL, FileLocatorUtils.locateOrThrow(locator));
372 
373         verify(strategy).locate(fs, locator);
374         verifyNoMoreInteractions(strategy);
375     }
376 
377     /**
378      * Tests a successful locate() operation if the passed in locator contains a strategy, but no file system.
379      */
380     @Test
381     void testLocateSuccessWithStrategyDefaultFileSystem() throws ConfigurationException {
382         final FileLocationStrategy strategy = mock(FileLocationStrategy.class);
383         final FileLocator locator = FileLocatorUtils.fileLocator().locationStrategy(strategy).create();
384 
385         when(strategy.locate(FileLocatorUtils.DEFAULT_FILE_SYSTEM, locator)).thenReturn(sourceURL);
386 
387         assertSame(sourceURL, FileLocatorUtils.locateOrThrow(locator));
388 
389         verify(strategy).locate(FileLocatorUtils.DEFAULT_FILE_SYSTEM, locator);
390         verifyNoMoreInteractions(strategy);
391     }
392 
393     @Test
394     void testLocateWithNullTCCL() throws Exception {
395         final ClassLoader cl = Thread.currentThread().getContextClassLoader();
396         try {
397             Thread.currentThread().setContextClassLoader(null);
398             assertNull(FileLocatorUtils.locate(FileLocatorUtils.fileLocator().basePath("abase").fileName("aname").create()));
399         } finally {
400             Thread.currentThread().setContextClassLoader(cl);
401         }
402     }
403 
404     /**
405      * Tests whether the default file system is returned if it is not set in a locator.
406      */
407     @Test
408     void testObtainFileSystemNotSetInLocator() {
409         assertSame(FileLocatorUtils.DEFAULT_FILE_SYSTEM, FileLocatorUtils.getFileSystem(FileLocatorUtils.fileLocator().create()));
410     }
411 
412     /**
413      * Tests whether obtainFileSystem() can handle a null locator.
414      */
415     @Test
416     void testObtainFileSystemNullLocator() {
417         assertSame(FileLocatorUtils.DEFAULT_FILE_SYSTEM, FileLocatorUtils.getFileSystem(null));
418     }
419 
420     /**
421      * Tests whether obtainFileSystem() returns the file system stored in the locator.
422      */
423     @Test
424     void testObtainFileSystemSetInLocator() {
425         final FileSystem fs = mock(FileSystem.class);
426         final FileLocator locator = FileLocatorUtils.fileLocator().fileSystem(fs).create();
427         assertSame(fs, FileLocatorUtils.getFileSystem(locator));
428     }
429 
430     /**
431      * Tests whether a location strategy can be obtained if it is not defined by the locator.
432      */
433     @Test
434     void testObtainLocationStrategyNotSetInLocator() {
435         final FileLocator locator = FileLocatorUtils.fileLocator().create();
436         assertSame(FileLocatorUtils.DEFAULT_LOCATION_STRATEGY, FileLocatorUtils.getLocationStrategy(locator));
437     }
438 
439     /**
440      * Tests whether a location strategy can be obtained if a null locator is passed.
441      */
442     @Test
443     void testObtainLocationStrategyNullLocator() {
444         assertSame(FileLocatorUtils.DEFAULT_LOCATION_STRATEGY, FileLocatorUtils.getLocationStrategy(null));
445     }
446 
447     /**
448      * Tests whether a location strategy can be obtained if it is defined by the locator.
449      */
450     @Test
451     void testObtainLocationStrategySetInLocator() {
452         final FileLocationStrategy strategy = mock(FileLocationStrategy.class);
453         final FileLocator locator = FileLocatorUtils.fileLocator().locationStrategy(strategy).create();
454         assertSame(strategy, FileLocatorUtils.getLocationStrategy(locator));
455     }
456 
457     /**
458      * Tests whether put() deals with a null locator.
459      */
460     @Test
461     void testPutNoLocator() {
462         final Map<String, Object> map = new HashMap<>();
463         FileLocatorUtils.put(null, map);
464         assertTrue(map.isEmpty());
465     }
466 
467     /**
468      * Tries to call put() without a map.
469      */
470     @Test
471     void testPutNoMap() {
472         final FileLocator fileLocator = FileLocatorUtils.fileLocator().create();
473         assertThrows(IllegalArgumentException.class, () -> FileLocatorUtils.put(fileLocator, null));
474     }
475 
476     /**
477      * Tests whether a file locator can be stored in a map and read again from there.
478      */
479     @Test
480     void testStoreFileLocatorInMap() {
481         final FileLocationStrategy strategy = mock(FileLocationStrategy.class);
482         final FileLocator locator = FileLocatorUtils.fileLocator().basePath(BASE_PATH).encoding(ENCODING).fileName(FILE_NAME).fileSystem(fileSystem)
483             .locationStrategy(strategy).sourceURL(sourceURL).create();
484         final Map<String, Object> map = new HashMap<>();
485         FileLocatorUtils.put(locator, map);
486         final FileLocator locator2 = FileLocatorUtils.fromMap(map);
487         assertEquals(locator, locator2);
488     }
489 }