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.apache.commons.configuration2.TempDirUtils.newFile;
20  import static org.apache.commons.configuration2.TempDirUtils.newFolder;
21  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertFalse;
24  import static org.junit.jupiter.api.Assertions.assertNotNull;
25  import static org.junit.jupiter.api.Assertions.assertNull;
26  import static org.junit.jupiter.api.Assertions.assertSame;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  import static org.junit.jupiter.api.Assertions.assertTrue;
29  import static org.mockito.Mockito.doThrow;
30  import static org.mockito.Mockito.mock;
31  import static org.mockito.Mockito.verify;
32  import static org.mockito.Mockito.verifyNoMoreInteractions;
33  import static org.mockito.Mockito.when;
34  
35  import java.io.ByteArrayInputStream;
36  import java.io.ByteArrayOutputStream;
37  import java.io.File;
38  import java.io.FileInputStream;
39  import java.io.FileOutputStream;
40  import java.io.FileReader;
41  import java.io.FileWriter;
42  import java.io.IOException;
43  import java.io.InputStream;
44  import java.io.Reader;
45  import java.io.StringReader;
46  import java.io.StringWriter;
47  import java.io.Writer;
48  import java.net.MalformedURLException;
49  import java.net.URL;
50  import java.nio.charset.StandardCharsets;
51  import java.util.Arrays;
52  import java.util.HashMap;
53  import java.util.List;
54  import java.util.Map;
55  
56  import org.apache.commons.configuration2.ConfigurationAssert;
57  import org.apache.commons.configuration2.PropertiesConfiguration;
58  import org.apache.commons.configuration2.SynchronizerTestImpl;
59  import org.apache.commons.configuration2.SynchronizerTestImpl.Methods;
60  import org.apache.commons.configuration2.ex.ConfigurationException;
61  import org.junit.jupiter.api.Test;
62  import org.junit.jupiter.api.io.TempDir;
63  
64  /**
65   * Test class for {@code FileHandler}.
66   */
67  public class TestFileHandler {
68      /**
69       * A FileBased implementation which also implements FileLocatorAware. This class adds information about the current file
70       * locator to the content read and written.
71       */
72      private static final class FileBasedFileLocatorAwareTestImpl extends FileBasedTestImpl implements FileLocatorAware {
73          /** Stores the passed in file locator. */
74          private FileLocator locator;
75  
76          /**
77           * Returns the locator.
78           *
79           * @return the file locator
80           */
81          public FileLocator getLocator() {
82              return locator;
83          }
84  
85          @Override
86          public void initFileLocator(final FileLocator loc) {
87              this.locator = loc;
88          }
89  
90          @Override
91          public void read(final Reader in) throws ConfigurationException, IOException {
92              super.read(in);
93              setContent(String.valueOf(locator.getSourceURL()) + ": " + getContent());
94          }
95  
96          @Override
97          public void write(final Writer out) throws ConfigurationException, IOException {
98              out.write(String.valueOf(locator.getSourceURL()) + ": ");
99              super.write(out);
100         }
101     }
102 
103     /**
104      * A test implementation of FileBased which can also read from input streams.
105      * <p>
106      * Cannot be final for Mockito.
107      * </p>
108      */
109     private static class FileBasedInputStreamSupportTestImpl extends FileBasedTestImpl implements InputStreamSupport {
110         @Override
111         public void read(final InputStream in) throws ConfigurationException, IOException {
112             final ByteArrayOutputStream bos = new ByteArrayOutputStream();
113             int c;
114             while ((c = in.read()) != -1) {
115                 bos.write(c);
116             }
117             setContent("InputStream = " + bos.toString());
118         }
119     }
120 
121     /**
122      * An implementation of the FileBased interface used for test purposes.
123      */
124     private static class FileBasedTestImpl implements FileBased {
125         /** The content read from a reader. */
126         private String content = CONTENT;
127 
128         /**
129          * Returns the content read from a reader.
130          *
131          * @return the read content
132          */
133         public String getContent() {
134             return content;
135         }
136 
137         @Override
138         public void read(final Reader in) throws ConfigurationException, IOException {
139             content = readReader(in);
140         }
141 
142         /**
143          * Allows setting the content.
144          *
145          * @param content the content
146          */
147         public void setContent(final String content) {
148             this.content = content;
149         }
150 
151         @Override
152         public void write(final Writer out) throws ConfigurationException, IOException {
153             out.write(getContent());
154             out.flush();
155         }
156     }
157 
158     /**
159      * A test listener implementation.
160      */
161     private static final class FileHandlerListenerTestImpl extends FileHandlerListenerAdapter {
162         /** The expected file handler. */
163         private final FileHandler expHandler;
164 
165         /** A buffer for recording method invocations. */
166         private final StringBuilder methods;
167 
168         public FileHandlerListenerTestImpl(final FileHandler fh) {
169             expHandler = fh;
170             methods = new StringBuilder();
171         }
172 
173         /**
174          * Tests whether the expected listener methods have been called.
175          *
176          * @param expMethods the expected methods as plain string
177          */
178         public void checkMethods(final String expMethods) {
179             assertEquals(expMethods, methods.toString());
180         }
181 
182         @Override
183         public void loaded(final FileHandler handler) {
184             super.loaded(handler);
185             methodCalled(handler, "loaded");
186         }
187 
188         @Override
189         public void loading(final FileHandler handler) {
190             super.loading(handler);
191             methodCalled(handler, "loading");
192         }
193 
194         @Override
195         public void locationChanged(final FileHandler handler) {
196             super.locationChanged(handler);
197             methodCalled(handler, "locationChanged");
198         }
199 
200         /**
201          * One of the listener methods was called. Records this invocation.
202          *
203          * @param handler the file handler
204          * @param method the called method
205          */
206         private void methodCalled(final FileHandler handler, final String method) {
207             assertEquals(expHandler, handler);
208             methods.append(method);
209         }
210 
211         @Override
212         public void saved(final FileHandler handler) {
213             super.saved(handler);
214             methodCalled(handler, "saved");
215         }
216 
217         @Override
218         public void saving(final FileHandler handler) {
219             super.saving(handler);
220             methodCalled(handler, "saving");
221         }
222     }
223 
224     /** Constant for the name of a test file. */
225     private static final String TEST_FILENAME = "test.properties";
226 
227     /** Constant for content of the test file. */
228     private static final String CONTENT = "TestFileHandler: This is test content.";
229 
230     /**
231      * Checks a FileLocator which is expected to contain no data.
232      *
233      * @param content the data object which was passed the locator
234      */
235     private static void checkEmptyLocator(final FileBasedFileLocatorAwareTestImpl content) {
236         assertNull(content.getLocator().getSourceURL());
237         assertNull(content.getLocator().getBasePath());
238         assertNull(content.getLocator().getFileName());
239     }
240 
241     /**
242      * Reads the content of the specified file into a string
243      *
244      * @param f the file to be read
245      * @return the content of this file
246      */
247     private static String readFile(final File f) {
248         return assertDoesNotThrow(() -> {
249             try (Reader in = new FileReader(f)) {
250                 return readReader(in);
251             }
252         });
253     }
254 
255     /**
256      * Reads the content of the specified reader into a string.
257      *
258      * @param in the reader
259      * @return the read content
260      * @throws IOException if an error occurs
261      */
262     private static String readReader(final Reader in) throws IOException {
263         final StringBuilder buf = new StringBuilder();
264         int c;
265         while ((c = in.read()) != -1) {
266             buf.append((char) c);
267         }
268         return buf.toString();
269     }
270 
271     /** A folder for temporary files. */
272     @TempDir
273     public File tempFolder;
274 
275     /**
276      * Creates a test file with the test content.
277      *
278      * @return the File object pointing to the test file
279      */
280     private File createTestFile() {
281         return createTestFile(null);
282     }
283 
284     /**
285      * Creates a test file with test content and allows specifying a file name.
286      *
287      * @param f the file to be created (may be <b>null</b>)
288      * @return the File object pointing to the test file
289      */
290     private File createTestFile(final File f) {
291         return assertDoesNotThrow(() -> {
292             File file = f;
293             if (file == null) {
294                 file = newFile(tempFolder);
295             }
296             try (Writer out = new FileWriter(file)) {
297                 out.write(CONTENT);
298             }
299             return file;
300         });
301     }
302 
303     /**
304      * Tries to add a null listener.
305      */
306     @Test
307     public void testAddFileHandlerListenerNull() {
308         final FileHandler fileHandler = new FileHandler();
309         assertThrows(IllegalArgumentException.class, () -> fileHandler.addFileHandlerListener(null));
310     }
311 
312     /**
313      * Tries to invoke the assignment constructor with a null handler.
314      */
315     @Test
316     public void testAssignNullHandler() {
317         final FileBased obj = new FileBasedTestImpl();
318         assertThrows(IllegalArgumentException.class, () -> new FileHandler(obj, null));
319     }
320 
321     /**
322      * Tests whether a FileHandler object can be used to specify a location and later be assigned to a FileBased object.
323      */
324     @Test
325     public void testAssignWithFileBased() {
326         final FileHandler h1 = new FileHandler();
327         final File f = new File("testfile.txt");
328         h1.setFile(f);
329         final FileBased content = new FileBasedTestImpl();
330         final FileHandler h2 = new FileHandler(content, h1);
331         h1.setFileName("someOtherFile.txt");
332         assertSame(content, h2.getContent());
333         assertEquals(f, h2.getFile());
334     }
335 
336     /**
337      * Tests whether the location can be cleared.
338      */
339     @Test
340     public void testClearLocation() {
341         final FileHandler handler = new FileHandler();
342         handler.setFile(createTestFile());
343         handler.clearLocation();
344         assertFalse(handler.isLocationDefined());
345         assertNull(handler.getFile());
346         assertNull(handler.getURL());
347         assertNull(handler.getBasePath());
348         assertNull(handler.getPath());
349     }
350 
351     /**
352      * Tests getBasePath() if no information is available.
353      */
354     @Test
355     public void testGetBasePathUndefined() {
356         assertNull(new FileHandler().getBasePath());
357     }
358 
359     /**
360      * Tests getFileName() if no information is set.
361      */
362     @Test
363     public void testGetFileNameUndefined() {
364         assertNull(new FileHandler().getFileName());
365     }
366 
367     /**
368      * Tests whether a newly created instance has a default file system.
369      */
370     @Test
371     public void testGetFileSystemDefault() {
372         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
373         assertEquals(FileLocatorUtils.DEFAULT_FILE_SYSTEM, handler.getFileSystem());
374     }
375 
376     /**
377      * Tests whether a newly created instance uses the default location strategy.
378      */
379     @Test
380     public void testGetLocationStrategyDefault() {
381         final FileHandler handler = new FileHandler();
382         assertNull(handler.getFileLocator().getLocationStrategy());
383         assertSame(FileLocatorUtils.DEFAULT_LOCATION_STRATEGY, handler.getLocationStrategy());
384     }
385 
386     /**
387      * Tests whether an instance can be created from a map with the properties of a FileLocator.
388      */
389     @Test
390     public void testInitFromMap() {
391         final FileLocator locator = FileLocatorUtils.fileLocator().fileName(TEST_FILENAME).basePath("someBasePath").encoding("someEncoding").create();
392         final Map<String, Object> map = new HashMap<>();
393         FileLocatorUtils.put(locator, map);
394         final FileHandler handler = FileHandler.fromMap(map);
395         assertEquals(locator, handler.getFileLocator());
396     }
397 
398     /**
399      * Tests whether the initialization of properties is safe even if performed in multiple threads.
400      */
401     @Test
402     public void testInitPropertiesMultiThreaded() throws InterruptedException {
403         final String encoding = "TestEncoding";
404         final FileSystem fileSystem = new DefaultFileSystem();
405         final FileLocationStrategy locationStrategy = new ProvidedURLLocationStrategy();
406         final int loops = 8;
407 
408         for (int i = 0; i < loops; i++) {
409             final FileHandler handler = new FileHandler();
410             final Thread t1 = new Thread(() -> handler.setFileSystem(fileSystem));
411             final Thread t2 = new Thread(() -> handler.setFileName(TEST_FILENAME));
412             final Thread t3 = new Thread(() -> handler.setEncoding(encoding));
413             final Thread t4 = new Thread(() -> handler.setLocationStrategy(locationStrategy));
414             final List<Thread> threads = Arrays.asList(t1, t2, t3, t4);
415             for (final Thread t : threads) {
416                 t.start();
417             }
418             for (final Thread t : threads) {
419                 t.join();
420             }
421             final FileLocator locator = handler.getFileLocator();
422             assertEquals(TEST_FILENAME, locator.getFileName());
423             assertNull(locator.getSourceURL());
424             assertEquals(encoding, locator.getEncoding());
425             assertSame(fileSystem, locator.getFileSystem());
426             assertSame(locationStrategy, locator.getLocationStrategy());
427         }
428     }
429 
430     /**
431      * Tests isLocationDefined() if only a base path is set.
432      */
433     @Test
434     public void testIsLocationDefinedBasePathOnly() {
435         final FileHandler handler = new FileHandler();
436         handler.setBasePath(createTestFile().getParent());
437         assertFalse(handler.isLocationDefined());
438     }
439 
440     /**
441      * Tests whether an undefined location can be queried.
442      */
443     @Test
444     public void testIsLocationDefinedFalse() {
445         final FileHandler handler = new FileHandler();
446         assertFalse(handler.isLocationDefined());
447     }
448 
449     /**
450      * Tests isLocationDefined() if a File has been set.
451      */
452     @Test
453     public void testIsLocationDefinedFile() {
454         final FileHandler handler = new FileHandler();
455         handler.setFile(createTestFile());
456         assertTrue(handler.isLocationDefined());
457     }
458 
459     /**
460      * Tests isLocationDefined() if a file name has been set.
461      */
462     @Test
463     public void testIsLocationDefinedFileName() {
464         final FileHandler handler = new FileHandler();
465         handler.setFileName(createTestFile().getName());
466         assertTrue(handler.isLocationDefined());
467     }
468 
469     /**
470      * Tests isLocationDefined() if a path has been set.
471      */
472     @Test
473     public void testIsLocationDefinedPath() {
474         final FileHandler handler = new FileHandler();
475         handler.setPath(createTestFile().getAbsolutePath());
476         assertTrue(handler.isLocationDefined());
477     }
478 
479     /**
480      * Tests isLocationDefined() if a URL has been set.
481      */
482     @Test
483     public void testIsLocationDefinedURL() throws IOException {
484         final FileHandler handler = new FileHandler();
485         handler.setURL(createTestFile().toURI().toURL());
486         assertTrue(handler.isLocationDefined());
487     }
488 
489     /**
490      * Tests that it is not possible to load a directory using the load() method which expects a File.
491      */
492     @Test
493     public void testLoadDirectoryFile() {
494         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
495         assertThrows(ConfigurationException.class, () -> handler.load(ConfigurationAssert.TEST_DIR));
496     }
497 
498     /**
499      * Checks that loading a directory instead of a file throws an exception.
500      */
501     @Test
502     public void testLoadDirectoryString() {
503         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
504         final String fileName = ConfigurationAssert.TEST_DIR.getAbsolutePath();
505         assertThrows(ConfigurationException.class, () -> handler.load(fileName));
506     }
507 
508     /**
509      * Tests notifications about load operations.
510      */
511     @Test
512     public void testLoadEvents() throws ConfigurationException {
513         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
514         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
515         handler.addFileHandlerListener(listener);
516         handler.load(createTestFile());
517         listener.checkMethods("loadingloaded");
518     }
519 
520     /**
521      * Tests whether a FileLocatorAware object is initialized correctly when loading data.
522      */
523     @Test
524     public void testLoadFileLocatorAware() throws IOException, ConfigurationException {
525         final File file = createTestFile();
526         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
527         final FileHandler handler = new FileHandler(content);
528         handler.setFile(file);
529         handler.load();
530         assertEquals(file.toURI().toURL().toString() + ": " + CONTENT, content.getContent());
531     }
532 
533     /**
534      * Tests a load operation with a FileLocatorAware object if data is loaded from a reader.
535      */
536     @Test
537     public void testLoadFileLocatorAwareReader() throws ConfigurationException {
538         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
539         final FileHandler handler = new FileHandler(content);
540         handler.load(new StringReader(CONTENT));
541         checkEmptyLocator(content);
542     }
543 
544     /**
545      * Tests loading with a FileLocatorAware object if data is loaded from a stream.
546      */
547     @Test
548     public void testLoadFileLocatorAwareStream() throws ConfigurationException {
549         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
550         final FileHandler handler = new FileHandler(content);
551         final ByteArrayInputStream bos = new ByteArrayInputStream(CONTENT.getBytes());
552         handler.load(bos);
553         checkEmptyLocator(content);
554     }
555 
556     /**
557      * Tests whether whether data can be loaded from class path.
558      */
559     @Test
560     public void testLoadFromClassPath() throws ConfigurationException {
561         final FileBasedTestImpl content = new FileBasedTestImpl();
562         final FileHandler config1 = new FileHandler(content);
563         config1.setFileName("config/deep/deeptest.properties");
564         config1.load();
565         assertFalse(content.getContent().isEmpty());
566     }
567 
568     /**
569      * Tests whether data from a File can be loaded.
570      */
571     @Test
572     public void testLoadFromFile() throws ConfigurationException {
573         final FileBasedTestImpl content = new FileBasedTestImpl();
574         final File file = createTestFile();
575         final FileHandler handler = new FileHandler(content);
576         handler.load(file);
577         assertEquals(CONTENT, content.getContent());
578     }
579 
580     /**
581      * Tests a load operation using the current location which is a file name.
582      */
583     @Test
584     public void testLoadFromFileNameLocation() throws ConfigurationException {
585         final File file = createTestFile();
586         final FileBasedTestImpl content = new FileBasedTestImpl();
587         final FileHandler handler = new FileHandler(content);
588         handler.setBasePath(file.getParentFile().getAbsolutePath());
589         handler.setFileName(file.getName());
590         handler.load();
591         assertEquals(CONTENT, content.getContent());
592     }
593 
594     /**
595      * Tries to load data from a File if no content object was set.
596      */
597     @Test
598     public void testLoadFromFileNoContent() {
599         final FileHandler handler = new FileHandler();
600         final File file = createTestFile();
601         final ConfigurationException cex = assertThrows(ConfigurationException.class, () -> handler.load(file));
602         assertEquals("No content available!", cex.getMessage());
603     }
604 
605     /**
606      * Tests whether data from an absolute path can be loaded.
607      */
608     @Test
609     public void testLoadFromFilePath() throws ConfigurationException {
610         final File file = createTestFile();
611         final FileBasedTestImpl content = new FileBasedTestImpl();
612         final FileHandler handler = new FileHandler(content);
613         handler.load(file.getAbsolutePath());
614         assertEquals(CONTENT, content.getContent());
615     }
616 
617     /**
618      * Tests that a load() operation with a file path overrides a URL which might have been set.
619      */
620     @Test
621     public void testLoadFromFilePathWithURLDefined() throws ConfigurationException {
622         final File file = createTestFile();
623         final FileBasedTestImpl content = new FileBasedTestImpl();
624         final FileHandler handler = new FileHandler(content);
625         handler.setURL(ConfigurationAssert.getTestURL("test.xml"));
626         handler.load(file.getAbsolutePath());
627         assertEquals(CONTENT, content.getContent());
628     }
629 
630     /**
631      * Tests whether data from a reader can be read.
632      */
633     @Test
634     public void testLoadFromReader() throws Exception {
635         final File file = createTestFile();
636         final FileBasedTestImpl content = new FileBasedTestImpl();
637         final FileHandler handler = new FileHandler(content);
638         try (Reader in = new FileReader(file)) {
639             handler.load(in);
640         }
641         assertEquals(CONTENT, content.getContent());
642     }
643 
644     /**
645      * Tests whether an IOException is handled when loading data from a reader.
646      */
647     @Test
648     public void testLoadFromReaderIOException() throws IOException, ConfigurationException {
649         final FileBased content = mock(FileBased.class);
650         final Reader in = new StringReader(CONTENT);
651         final IOException ioex = new IOException("Test exception");
652 
653         doThrow(ioex).when(content).read(in);
654 
655         final FileHandler handler = new FileHandler(content);
656         final ConfigurationException cex = assertThrows(ConfigurationException.class, () -> handler.load(in));
657         assertEquals(ioex, cex.getCause());
658 
659         verify(content).read(in);
660         verifyNoMoreInteractions(content);
661     }
662 
663     /**
664      * Tests whether data from an input stream can be read.
665      */
666     @Test
667     public void testLoadFromStream() throws Exception {
668         final File file = createTestFile();
669         final FileBasedTestImpl content = new FileBasedTestImpl();
670         final FileHandler handler = new FileHandler(content);
671         try (FileInputStream in = new FileInputStream(file)) {
672             handler.load(in);
673         }
674         assertEquals(CONTENT, content.getContent());
675     }
676 
677     /**
678      * Tests whether data from a URL can be loaded.
679      */
680     @Test
681     public void testLoadFromURL() throws Exception {
682         final File file = createTestFile();
683         final FileBasedTestImpl content = new FileBasedTestImpl();
684         final FileHandler handler = new FileHandler(content);
685         handler.load(file.toURI().toURL());
686         assertEquals(CONTENT, content.getContent());
687     }
688 
689     /**
690      * Tests a load operation using the current location which is a URL.
691      */
692     @Test
693     public void testLoadFromURLLocation() throws Exception {
694         final File file = createTestFile();
695         final FileBasedTestImpl content = new FileBasedTestImpl();
696         final FileHandler handler = new FileHandler(content);
697         handler.setURL(file.toURI().toURL());
698         handler.load();
699         assertEquals(CONTENT, content.getContent());
700     }
701 
702     /**
703      * Tests whether data can be read from an input stream.
704      */
705     @Test
706     public void testLoadInputStreamSupport() throws ConfigurationException {
707         final FileBasedInputStreamSupportTestImpl content = new FileBasedInputStreamSupportTestImpl();
708         final FileHandler handler = new FileHandler(content);
709         final ByteArrayInputStream bin = new ByteArrayInputStream(CONTENT.getBytes());
710         handler.load(bin);
711         assertEquals("InputStream = " + CONTENT, content.getContent());
712     }
713 
714     /**
715      * Tests whether an IOException is handled when reading from an input stream.
716      */
717     @Test
718     public void testLoadInputStreamSupportIOException() throws ConfigurationException, IOException {
719         final FileBasedInputStreamSupportTestImpl content = mock(FileBasedInputStreamSupportTestImpl.class);
720         final ByteArrayInputStream bin = new ByteArrayInputStream(CONTENT.getBytes());
721         final IOException ioex = new IOException();
722 
723         doThrow(ioex).when(content).read(bin);
724 
725         final FileHandler handler = new FileHandler(content);
726         final ConfigurationException cex = assertThrows(ConfigurationException.class, () -> handler.load(bin));
727         assertEquals(ioex, cex.getCause());
728 
729         verify(content).read(bin);
730         verifyNoMoreInteractions(content);
731     }
732 
733     /**
734      * Tries to call a load() method if no content object is available.
735      */
736     @Test
737     public void testLoadNoContent() {
738         final FileHandler handler = new FileHandler();
739         final StringReader reader = new StringReader(CONTENT);
740         assertThrows(ConfigurationException.class, () -> handler.load(reader));
741     }
742 
743     /**
744      * Tries to load data if no location has been set.
745      */
746     @Test
747     public void testLoadNoLocation() {
748         final FileBasedTestImpl content = new FileBasedTestImpl();
749         final FileHandler handler = new FileHandler(content);
750         assertThrows(ConfigurationException.class, handler::load);
751     }
752 
753     /**
754      * Tests whether a load() operation is correctly synchronized.
755      */
756     @Test
757     public void testLoadSynchronized() throws ConfigurationException {
758         final PropertiesConfiguration config = new PropertiesConfiguration();
759         final SynchronizerTestImpl sync = new SynchronizerTestImpl();
760         config.setSynchronizer(sync);
761         final FileHandler handler = new FileHandler(config);
762         handler.load(ConfigurationAssert.getTestFile("test.properties"));
763         sync.verifyStart(Methods.BEGIN_WRITE);
764         sync.verifyEnd(Methods.END_WRITE);
765     }
766 
767     /**
768      * Tests a successful locate() operation.
769      */
770     @Test
771     public void testLocateSuccess() throws ConfigurationException {
772         final FileHandler handler = new FileHandler();
773         handler.setFileName(TEST_FILENAME);
774         assertTrue(handler.locate());
775         final FileLocator locator = handler.getFileLocator();
776         assertNotNull(locator.getSourceURL());
777         assertNotNull(locator.getBasePath());
778         assertEquals(TEST_FILENAME, locator.getFileName());
779 
780         // check whether the correct URL was obtained
781         final PropertiesConfiguration config = new PropertiesConfiguration();
782         final FileHandler h2 = new FileHandler(config);
783         h2.setURL(locator.getSourceURL());
784         h2.load();
785         assertTrue(config.getBoolean("configuration.loaded"));
786     }
787 
788     /**
789      * Tests a locate() operation if there is not enough information.
790      */
791     @Test
792     public void testLocateUndefinedLocator() {
793         final FileHandler handler = new FileHandler();
794         handler.setBasePath("only/a/base/path");
795         final FileLocator locator = handler.getFileLocator();
796         assertFalse(handler.locate());
797         assertSame(locator, handler.getFileLocator());
798     }
799 
800     /**
801      * Tests a locate() operation if the specified file cannot be resolved.
802      */
803     @Test
804     public void testLocateUnknownFile() {
805         final FileHandler handler = new FileHandler();
806         handler.setFileName("unknown file");
807         final FileLocator locator = handler.getFileLocator();
808         assertFalse(handler.locate());
809         assertSame(locator, handler.getFileLocator());
810     }
811 
812     /**
813      * Tests a notification about a changed base path.
814      */
815     @Test
816     public void testLocationChangedBasePath() {
817         final FileHandler handler = new FileHandler();
818         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
819         handler.addFileHandlerListener(listener);
820         handler.setBasePath(TEST_FILENAME);
821         listener.checkMethods("locationChanged");
822     }
823 
824     /**
825      * Tests a notification about a changed encoding.
826      */
827     @Test
828     public void testLocationChangedEncoding() {
829         final FileHandler handler = new FileHandler();
830         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
831         handler.addFileHandlerListener(listener);
832         handler.setEncoding(StandardCharsets.UTF_8.name());
833         listener.checkMethods("locationChanged");
834     }
835 
836     /**
837      * Tests a notification about a changed file.
838      */
839     @Test
840     public void testLocationChangedFile() throws IOException {
841         final FileHandler handler = new FileHandler();
842         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
843         handler.addFileHandlerListener(listener);
844         handler.setFile(newFile(tempFolder));
845         listener.checkMethods("locationChanged");
846     }
847 
848     /**
849      * Tests a notification about a changed file name.
850      */
851     @Test
852     public void testLocationChangedFileName() {
853         final FileHandler handler = new FileHandler();
854         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
855         handler.addFileHandlerListener(listener);
856         handler.setFileName(TEST_FILENAME);
857         listener.checkMethods("locationChanged");
858     }
859 
860     /**
861      * Tests a notification about a changed file system.
862      */
863     @Test
864     public void testLocationChangedFileSystem() {
865         final FileSystem fs = mock(FileSystem.class);
866         final FileHandler handler = new FileHandler();
867         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
868         handler.addFileHandlerListener(listener);
869         handler.setFileSystem(fs);
870         listener.checkMethods("locationChanged");
871     }
872 
873     /**
874      * Tests whether a notification is sent if the whole locator was changed.
875      */
876     @Test
877     public void testLocationChangedLocator() {
878         final FileHandler handler = new FileHandler();
879         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
880         handler.addFileHandlerListener(listener);
881         handler.setFileLocator(FileLocatorUtils.fileLocator().fileName(TEST_FILENAME).create());
882         listener.checkMethods("locationChanged");
883     }
884 
885     /**
886      * Tests a notification about a changed path.
887      */
888     @Test
889     public void testLocationChangedPath() {
890         final FileHandler handler = new FileHandler();
891         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
892         handler.addFileHandlerListener(listener);
893         handler.setPath(TEST_FILENAME);
894         listener.checkMethods("locationChanged");
895     }
896 
897     /**
898      * Tests a notification about a changed URL.
899      */
900     @Test
901     public void testLocationChangedURL() throws IOException {
902         final FileHandler handler = new FileHandler();
903         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
904         handler.addFileHandlerListener(listener);
905         final URL url = newFile(tempFolder).toURI().toURL();
906         handler.setURL(url);
907         listener.checkMethods("locationChanged");
908     }
909 
910     /**
911      * Tests that the locator injected into the content object has an encoding set.
912      */
913     @Test
914     public void testLocatorAwareEncoding() throws ConfigurationException {
915         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
916         final FileHandler handler = new FileHandler(content);
917         final String encoding = "testEncoding";
918         handler.setEncoding(encoding);
919         handler.save(new StringWriter());
920         assertEquals(encoding, content.getLocator().getEncoding());
921     }
922 
923     /**
924      * Tests whether file names containing a "+" character are handled correctly. This test is related to CONFIGURATION-415.
925      */
926     @Test
927     public void testPathWithPlus() throws ConfigurationException, IOException {
928         final File saveFile = newFile("test+config.properties", tempFolder);
929         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
930         handler.setFile(saveFile);
931         handler.save();
932         assertEquals(CONTENT, readFile(saveFile));
933     }
934 
935     /**
936      * Tests loading and saving a configuration file with a complicated path name including spaces. (related to issue 35210)
937      */
938     @Test
939     public void testPathWithSpaces() throws ConfigurationException, IOException {
940         final File path = newFolder("path with spaces", tempFolder);
941         final File confFile = new File(path, "config-test.properties");
942         final File testFile = createTestFile(confFile);
943         final URL url = testFile.toURI().toURL();
944         final FileBasedTestImpl content = new FileBasedTestImpl();
945         final FileHandler handler = new FileHandler(content);
946         handler.setURL(url);
947         handler.load();
948         assertEquals(CONTENT, content.getContent());
949         final File out = new File(path, "out.txt");
950         handler.save(out);
951         assertEquals(CONTENT, readFile(out));
952     }
953 
954     /**
955      * Tests whether the file system can be reset.
956      */
957     @Test
958     public void testResetFileSystem() {
959         final FileSystem sys = mock(FileSystem.class);
960         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
961         handler.setFileSystem(sys);
962         handler.resetFileSystem();
963         assertEquals(FileLocatorUtils.DEFAULT_FILE_SYSTEM, handler.getFileSystem());
964     }
965 
966     /**
967      * Tests notifications about save operations.
968      */
969     @Test
970     public void testSaveEvents() throws IOException, ConfigurationException {
971         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
972         final FileHandlerListenerTestImpl listener = new FileHandlerListenerTestImpl(handler);
973         handler.addFileHandlerListener(listener);
974         final File f = newFile(tempFolder);
975         handler.save(f);
976         listener.checkMethods("savingsaved");
977     }
978 
979     /**
980      * Tests whether a FileLocatorAware is correctly handled when saving data.
981      */
982     @Test
983     public void testSaveFileLocatorAware() throws ConfigurationException, IOException {
984         final File file = newFile(tempFolder);
985         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
986         final FileHandler handler = new FileHandler(content);
987         handler.save(file);
988         assertEquals(file.toURI().toURL() + ": " + CONTENT, readFile(file));
989     }
990 
991     /**
992      * Tests a save operation with a FileLocatorAware object if the target is a stream.
993      */
994     @Test
995     public void testSaveFileLocatorAwareToStream() throws ConfigurationException {
996         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
997         final FileHandler handler = new FileHandler(content);
998         handler.save(new ByteArrayOutputStream());
999         checkEmptyLocator(content);
1000     }
1001 
1002     /**
1003      * Tests a save operation with a FileLocatorAware object if the target is a writer.
1004      */
1005     @Test
1006     public void testSaveFileLocatorAwareToWriter() throws ConfigurationException {
1007         final FileBasedFileLocatorAwareTestImpl content = new FileBasedFileLocatorAwareTestImpl();
1008         final FileHandler handler = new FileHandler(content);
1009         handler.save(new StringWriter());
1010         checkEmptyLocator(content);
1011     }
1012 
1013     /**
1014      * Tries to save the locator if no location has been set.
1015      */
1016     @Test
1017     public void testSaveNoLocation() {
1018         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1019         assertThrows(ConfigurationException.class, handler::save);
1020     }
1021 
1022     /**
1023      * Tests whether a save() operation is correctly synchronized.
1024      */
1025     @Test
1026     public void testSaveSynchronized() throws ConfigurationException, IOException {
1027         final PropertiesConfiguration config = new PropertiesConfiguration();
1028         config.addProperty("test.synchronized", Boolean.TRUE);
1029         final SynchronizerTestImpl sync = new SynchronizerTestImpl();
1030         config.setSynchronizer(sync);
1031         final FileHandler handler = new FileHandler(config);
1032         final File f = newFile(tempFolder);
1033         handler.save(f);
1034         sync.verify(Methods.BEGIN_WRITE, Methods.END_WRITE);
1035     }
1036 
1037     /**
1038      * Tests whether data can be saved to a file.
1039      */
1040     @Test
1041     public void testSaveToFile() throws ConfigurationException, IOException {
1042         final File file = newFile(tempFolder);
1043         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1044         handler.save(file);
1045         assertEquals(CONTENT, readFile(file));
1046     }
1047 
1048     /**
1049      * Tests whether data can be saved to a file name.
1050      */
1051     @Test
1052     public void testSaveToFileName() throws ConfigurationException, IOException {
1053         final File file = newFile(tempFolder);
1054         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1055         handler.save(file.getAbsolutePath());
1056         assertEquals(CONTENT, readFile(file));
1057     }
1058 
1059     /**
1060      * Tests whether data can be saved to the internal location if it is a file name.
1061      */
1062     @Test
1063     public void testSaveToFileNameLocation() throws ConfigurationException, IOException {
1064         final File file = newFile(tempFolder);
1065         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1066         handler.setFileName(file.getAbsolutePath());
1067         handler.save();
1068         assertEquals(CONTENT, readFile(file));
1069     }
1070 
1071     /**
1072      * Tests whether a URL exception is handled when saving a file to a file name.
1073      */
1074     @Test
1075     public void testSaveToFileNameURLException() throws IOException {
1076         final FileSystem fs = mock(FileSystem.class);
1077         final File file = newFile(tempFolder);
1078         final String basePath = "some base path";
1079         final MalformedURLException urlex = new MalformedURLException("Test exception");
1080         final String fileName = file.getName();
1081 
1082         when(fs.getURL(basePath, fileName)).thenThrow(urlex);
1083 
1084         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1085         handler.setBasePath(basePath);
1086         handler.setFileSystem(fs);
1087         final ConfigurationException cex = assertThrows(ConfigurationException.class, () -> handler.save(fileName));
1088         assertEquals(urlex, cex.getCause());
1089 
1090         verify(fs).getURL(basePath, fileName);
1091         verifyNoMoreInteractions(fs);
1092     }
1093 
1094     /**
1095      * Tries to save data to a file name if the name cannot be located.
1096      */
1097     @Test
1098     public void testSaveToFileNameURLNotResolved() throws IOException {
1099         final FileSystem fs = mock(FileSystem.class);
1100         final File file = newFile(tempFolder);
1101         final String fileName = file.getName();
1102 
1103         when(fs.getURL(null, fileName)).thenReturn(null);
1104 
1105         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1106         handler.setFileSystem(fs);
1107         assertThrows(ConfigurationException.class, () -> handler.save(fileName));
1108 
1109         verify(fs).getURL(null, fileName);
1110         verifyNoMoreInteractions(fs);
1111     }
1112 
1113     /**
1114      * Tests whether data can be saved to a stream.
1115      */
1116     @Test
1117     public void testSaveToStream() throws ConfigurationException, IOException {
1118         final File file = newFile(tempFolder);
1119         try (FileOutputStream out = new FileOutputStream(file)) {
1120             final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1121             handler.save(out);
1122         }
1123         assertEquals(CONTENT, readFile(file));
1124     }
1125 
1126     /**
1127      * Tests whether data can be saved to a URL.
1128      */
1129     @Test
1130     public void testSaveToURL() throws Exception {
1131         final File file = newFile(tempFolder);
1132         final URL url = file.toURI().toURL();
1133         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1134         handler.save(url);
1135         assertEquals(CONTENT, readFile(file));
1136     }
1137 
1138     /**
1139      * Tests whether data can be saved to the internal location if it is a URL.
1140      */
1141     @Test
1142     public void testSaveToURLLocation() throws ConfigurationException, IOException {
1143         final File file = newFile(tempFolder);
1144         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1145         handler.setURL(file.toURI().toURL());
1146         handler.save();
1147         assertEquals(CONTENT, readFile(file));
1148     }
1149 
1150     /**
1151      * Tests whether data can be saved into a Writer.
1152      */
1153     @Test
1154     public void testSaveToWriter() throws ConfigurationException {
1155         final FileBasedTestImpl content = new FileBasedTestImpl();
1156         final FileHandler handler = new FileHandler(content);
1157         final StringWriter out = new StringWriter();
1158         handler.save(out);
1159         assertEquals(CONTENT, out.toString());
1160     }
1161 
1162     /**
1163      * Tests whether an I/O exception during a save operation to a Writer is handled correctly.
1164      */
1165     @Test
1166     public void testSaveToWriterIOException() throws ConfigurationException, IOException {
1167         final FileBased content = mock(FileBased.class);
1168         final StringWriter out = new StringWriter();
1169         final IOException ioex = new IOException("Test exception!");
1170 
1171         doThrow(ioex).when(content).write(out);
1172 
1173         final FileHandler handler = new FileHandler(content);
1174         final ConfigurationException cex = assertThrows(ConfigurationException.class, () -> handler.save(out));
1175         assertEquals(ioex, cex.getCause());
1176 
1177         verify(content).write(out);
1178         verifyNoMoreInteractions(content);
1179     }
1180 
1181     /**
1182      * Tries to save something to a Writer if no content is set.
1183      */
1184     @Test
1185     public void testSaveToWriterNoContent() {
1186         final FileHandler handler = new FileHandler();
1187         final StringWriter writer = new StringWriter();
1188         assertThrows(ConfigurationException.class, () -> handler.save(writer));
1189     }
1190 
1191     /**
1192      * Tests whether a base path can be set and whether this removes an already set URL.
1193      */
1194     @Test
1195     public void testSetBasePath() {
1196         final FileHandler handler = new FileHandler();
1197         handler.setURL(ConfigurationAssert.getTestURL(TEST_FILENAME));
1198         final String basePath = ConfigurationAssert.TEST_DIR_NAME;
1199         handler.setBasePath(basePath);
1200         final FileLocator locator = handler.getFileLocator();
1201         assertEquals(basePath, locator.getBasePath());
1202         assertNull(locator.getSourceURL());
1203         assertNull(locator.getFileName());
1204     }
1205 
1206     /**
1207      * Tests whether the file scheme is corrected when setting the base path.
1208      */
1209     @Test
1210     public void testSetBasePathFileScheme() {
1211         final FileHandler handler = new FileHandler();
1212         handler.setBasePath("file:/test/path/");
1213         assertEquals("file:///test/path/", handler.getFileLocator().getBasePath());
1214     }
1215 
1216     /**
1217      * Tests whether the location can be set as a file.
1218      */
1219     @Test
1220     public void testSetFile() {
1221         final FileHandler handler = new FileHandler();
1222         final File directory = ConfigurationAssert.TEST_DIR;
1223         final File file = ConfigurationAssert.getTestFile(TEST_FILENAME);
1224         handler.setFile(file);
1225         assertEquals(directory.getAbsolutePath(), handler.getBasePath());
1226         assertEquals(TEST_FILENAME, handler.getFileName());
1227         assertEquals(file.getAbsolutePath(), handler.getPath());
1228     }
1229 
1230     /**
1231      * Tests whether the handler can be initialized using a FileLocator.
1232      */
1233     @Test
1234     public void testSetFileLocator() {
1235         final FileLocator locator = FileLocatorUtils.fileLocator().fileName(TEST_FILENAME).create();
1236         final FileHandler handler = new FileHandler();
1237         handler.setFileLocator(locator);
1238         assertEquals(TEST_FILENAME, handler.getFileName());
1239     }
1240 
1241     /**
1242      * Tries to set the FileLocator to null.
1243      */
1244     @Test
1245     public void testSetFileLocatorNull() {
1246         final FileHandler handler = new FileHandler();
1247         assertThrows(IllegalArgumentException.class, () -> handler.setFileLocator(null));
1248     }
1249 
1250     /**
1251      * Tests whether the location can be set using file name and base path.
1252      */
1253     @Test
1254     public void testSetFileName() {
1255         final FileHandler handler = new FileHandler();
1256         handler.setURL(ConfigurationAssert.getTestURL(TEST_FILENAME));
1257         handler.setFileName(TEST_FILENAME);
1258         assertNull(handler.getBasePath());
1259         assertEquals(TEST_FILENAME, handler.getFileName());
1260         assertEquals(TEST_FILENAME, handler.getFileLocator().getFileName());
1261         assertNull(handler.getFileLocator().getSourceURL());
1262     }
1263 
1264     /**
1265      * Tests whether the file scheme is corrected when setting the file name.
1266      */
1267     @Test
1268     public void testSetFileNameFileScheme() {
1269         final FileHandler handler = new FileHandler();
1270         handler.setFileName("file:/test/path/test.txt");
1271         assertEquals("file:///test/path/test.txt", handler.getFileLocator().getFileName());
1272     }
1273 
1274     /**
1275      * Tests whether a null file system can be set to reset this property.
1276      */
1277     @Test
1278     public void testSetFileSystemNull() {
1279         final FileSystem sys = mock(FileSystem.class);
1280         final FileHandler handler = new FileHandler(new FileBasedTestImpl());
1281         handler.setFileSystem(sys);
1282         assertSame(sys, handler.getFileSystem());
1283         handler.setFileSystem(null);
1284         assertEquals(FileLocatorUtils.DEFAULT_FILE_SYSTEM, handler.getFileSystem());
1285     }
1286 
1287     /**
1288      * Tests whether the location strategy can be changed.
1289      */
1290     @Test
1291     public void testSetLocationStrategy() {
1292         final FileLocationStrategy strategy = mock(FileLocationStrategy.class);
1293         final FileHandler handler = new FileHandler();
1294         handler.setLocationStrategy(strategy);
1295         assertSame(strategy, handler.getFileLocator().getLocationStrategy());
1296         assertSame(strategy, handler.getLocationStrategy());
1297     }
1298 
1299     /**
1300      * Tests whether the location can be set as a file.
1301      */
1302     @Test
1303     public void testSetPath() throws MalformedURLException {
1304         final FileHandler handler = new FileHandler();
1305         handler.setPath(ConfigurationAssert.TEST_DIR_NAME + File.separator + TEST_FILENAME);
1306         assertEquals(TEST_FILENAME, handler.getFileName());
1307         assertEquals(ConfigurationAssert.TEST_DIR.getAbsolutePath(), handler.getBasePath());
1308         final File file = ConfigurationAssert.getTestFile(TEST_FILENAME);
1309         assertEquals(file.getAbsolutePath(), handler.getPath());
1310         assertEquals(file.toURI().toURL(), handler.getURL());
1311         assertNull(handler.getFileLocator().getSourceURL());
1312     }
1313 
1314     /**
1315      * Additional tests for setting file names in various ways. (Copied from the test for XMLConfiguration)
1316      */
1317     @Test
1318     public void testSettingFileNames() {
1319         final String testProperties = ConfigurationAssert.getTestFile("test.xml").getAbsolutePath();
1320         final String testBasePath = ConfigurationAssert.TEST_DIR.getAbsolutePath();
1321 
1322         final FileHandler handler = new FileHandler();
1323         handler.setFileName(testProperties);
1324         assertEquals(testProperties.toString(), handler.getFileName());
1325 
1326         handler.setBasePath(testBasePath);
1327         handler.setFileName("hello.xml");
1328         assertEquals("hello.xml", handler.getFileName());
1329         assertEquals(testBasePath.toString(), handler.getBasePath());
1330         assertEquals(new File(testBasePath, "hello.xml"), handler.getFile());
1331 
1332         handler.setBasePath(testBasePath);
1333         handler.setFileName("subdir/hello.xml");
1334         assertEquals("subdir/hello.xml", handler.getFileName());
1335         assertEquals(testBasePath.toString(), handler.getBasePath());
1336         assertEquals(new File(testBasePath, "subdir/hello.xml"), handler.getFile());
1337     }
1338 
1339     /**
1340      * Tests whether a URL can be set.
1341      */
1342     @Test
1343     public void testSetURL() throws Exception {
1344         final FileHandler handler = new FileHandler();
1345         handler.setURL(new URL("https://commons.apache.org/configuration/index.html"));
1346 
1347         assertEquals("https://commons.apache.org/configuration/", handler.getBasePath());
1348         assertEquals("index.html", handler.getFileName());
1349         assertNull(handler.getFileLocator().getFileName());
1350     }
1351 
1352     /**
1353      * Tests whether the correct file scheme is applied.
1354      */
1355     @Test
1356     public void testSetURLFileScheme() throws MalformedURLException {
1357         final FileHandler handler = new FileHandler();
1358         // file URL - This url is invalid, a valid url would be
1359         // file:///temp/test.properties.
1360         handler.setURL(new URL("file:/temp/test.properties"));
1361         assertEquals("file:///temp/", handler.getBasePath());
1362         assertEquals(TEST_FILENAME, handler.getFileName());
1363     }
1364 
1365     /**
1366      * Tests whether a null URL can be set.
1367      */
1368     @Test
1369     public void testSetURLNull() {
1370         final FileHandler handler = new FileHandler();
1371         handler.setURL(ConfigurationAssert.getTestURL(TEST_FILENAME));
1372         handler.setURL(null);
1373         final FileLocator locator = handler.getFileLocator();
1374         assertNull(locator.getBasePath());
1375         assertNull(locator.getFileName());
1376         assertNull(locator.getSourceURL());
1377     }
1378 
1379     /**
1380      * Tests whether a URL with parameters can be set.
1381      */
1382     @Test
1383     public void testSetURLWithParams() throws Exception {
1384         final FileHandler handler = new FileHandler();
1385         final URL url = new URL("https://issues.apache.org/bugzilla/show_bug.cgi?id=37886");
1386         handler.setURL(url);
1387         assertEquals("https://issues.apache.org/bugzilla/", handler.getBasePath());
1388         assertEquals("show_bug.cgi", handler.getFileName());
1389         assertEquals(url, handler.getURL());
1390     }
1391 }