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