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.log4j;
18  
19  import java.io.File;
20  import java.io.FileInputStream;
21  import java.io.FileOutputStream;
22  import java.io.FileWriter;
23  import java.io.IOException;
24  import java.net.URL;
25  import java.util.Properties;
26  import java.util.zip.ZipEntry;
27  import java.util.zip.ZipOutputStream;
28  
29  import junit.framework.TestCase;
30  
31  import org.apache.log4j.spi.Filter;
32  import org.apache.log4j.spi.LoggingEvent;
33  import org.apache.log4j.spi.OptionHandler;
34  import org.apache.log4j.spi.ThrowableRenderer;
35  import org.apache.log4j.spi.ThrowableRendererSupport;
36  import org.apache.log4j.varia.LevelRangeFilter;
37  
38  /**
39   * Test property configurator.
40   *
41   */
42  public class PropertyConfiguratorTest extends TestCase {
43      public PropertyConfiguratorTest(final String testName) {
44          super(testName);
45      }
46  
47      /**
48       * Test for bug 40944.
49       * Did not catch IllegalArgumentException on Properties.load
50       * and close input stream.
51       * @throws IOException if IOException creating properties file.
52       */
53      public void testBadUnicodeEscape() throws IOException {
54          String fileName = "output/badescape.properties";
55          FileWriter writer = new FileWriter(fileName);
56          writer.write("log4j.rootLogger=\\uXX41");
57          writer.close();
58          PropertyConfigurator.configure(fileName);
59          File file = new File(fileName);
60          assertTrue(file.delete()) ;
61          assertFalse(file.exists());
62      }
63  
64      /**
65       * Test for bug 40944.
66       * configure(URL) never closed opened stream.
67       * @throws IOException if IOException creating properties file.
68       */
69          public void testURL() throws IOException {
70          File file = new File("output/unclosed.properties");
71          FileWriter writer = new FileWriter(file);
72          writer.write("log4j.rootLogger=debug");
73          writer.close();
74          URL url = file.toURL();
75          PropertyConfigurator.configure(url);
76          assertTrue(file.delete());
77          assertFalse(file.exists());
78      }
79  
80      /**
81       * Test for bug 40944.
82       * configure(URL) did not catch IllegalArgumentException and
83       * did not close stream.
84       * @throws IOException if IOException creating properties file.
85       */
86          public void testURLBadEscape() throws IOException {
87          File file = new File("output/urlbadescape.properties");
88          FileWriter writer = new FileWriter(file);
89          writer.write("log4j.rootLogger=\\uXX41");
90          writer.close();
91          URL url = file.toURL();
92          PropertyConfigurator.configure(url);
93          assertTrue(file.delete());
94          assertFalse(file.exists());
95      }
96  
97      /**
98       * Tests configuring Log4J from an InputStream.
99       * 
100      * @since 1.2.17
101      */
102     public void testInputStream() throws IOException {
103         File file = new File("input/filter1.properties");
104         assertTrue(file.exists());
105         FileInputStream inputStream = new FileInputStream(file);
106         try {
107             PropertyConfigurator.configure(inputStream);
108         } finally {
109             inputStream.close();
110         }
111         this.validateNested();
112         LogManager.resetConfiguration();
113     }
114 
115     public void validateNested() {
116         RollingFileAppender rfa = (RollingFileAppender)
117                 Logger.getLogger("org.apache.log4j.PropertyConfiguratorTest")
118                    .getAppender("ROLLING");
119         FixedWindowRollingPolicy rollingPolicy = (FixedWindowRollingPolicy) rfa.getRollingPolicy();
120         assertEquals("filterBase-test1.log", rollingPolicy.getActiveFileName());
121         assertEquals("filterBased-test1.%i", rollingPolicy.getFileNamePattern());
122         assertEquals(0, rollingPolicy.getMinIndex());
123         assertTrue(rollingPolicy.isActivated());
124         FilterBasedTriggeringPolicy triggeringPolicy =
125                 (FilterBasedTriggeringPolicy) rfa.getTriggeringPolicy();
126         LevelRangeFilter filter = (LevelRangeFilter) triggeringPolicy.getFilter();
127         assertTrue(Level.INFO.equals(filter.getLevelMin()));        
128     }
129     
130     /**
131      * Test for bug 47465.
132      * configure(URL) did not close opened JarURLConnection.
133      * @throws IOException if IOException creating properties jar.
134      */
135     public void testJarURL() throws IOException {
136         File dir = new File("output");
137         dir.mkdirs();
138         File file = new File("output/properties.jar");
139         ZipOutputStream zos =
140             new ZipOutputStream(new FileOutputStream(file));
141         zos.putNextEntry(new ZipEntry(LogManager.DEFAULT_CONFIGURATION_FILE));
142         zos.write("log4j.rootLogger=debug".getBytes());
143         zos.closeEntry();
144         zos.close();
145         URL url = new URL("jar:" + file.toURL() + "!/" +
146                 LogManager.DEFAULT_CONFIGURATION_FILE);
147         PropertyConfigurator.configure(url);
148         assertTrue(file.delete());
149         assertFalse(file.exists());
150     }
151 
152     /**
153      * Test processing of log4j.reset property, see bug 17531.
154      *
155      */
156     public void testReset() {
157         VectorAppender appender = new VectorAppender();
158         appender.setName("A1");
159         Logger.getRootLogger().addAppender(appender);
160         Properties props = new Properties();
161         props.put("log4j.reset", "true");
162         PropertyConfigurator.configure(props);
163         assertNull(Logger.getRootLogger().getAppender("A1"));
164         LogManager.resetConfiguration();
165     }
166 
167 
168     /**
169      * Mock definition of org.apache.log4j.rolling.RollingPolicy
170      * from extras companion.
171      */
172     public static class RollingPolicy implements OptionHandler {
173         private boolean activated = false;
174 
175         public RollingPolicy() {
176 
177         }
178         public void activateOptions() {
179             activated = true;
180         }
181 
182         public final boolean isActivated() {
183             return activated;
184         }
185 
186     }
187 
188     /**
189      * Mock definition of FixedWindowRollingPolicy from extras companion.
190      */
191     public static final class FixedWindowRollingPolicy extends RollingPolicy {
192         private String activeFileName;
193         private String fileNamePattern;
194         private int minIndex;
195 
196         public FixedWindowRollingPolicy() {
197             minIndex = -1;
198         }
199 
200         public String getActiveFileName() {
201             return activeFileName;
202         }
203         public void setActiveFileName(final String val) {
204             activeFileName = val;
205         }
206 
207         public String getFileNamePattern() {
208             return fileNamePattern;
209         }
210         public void setFileNamePattern(final String val) {
211             fileNamePattern = val;
212         }
213 
214         public int getMinIndex() {
215             return minIndex;
216         }
217 
218         public void setMinIndex(final int val) {
219             minIndex = val;
220         }
221     }
222 
223     /**
224      * Mock definition of TriggeringPolicy from extras companion.
225      */
226     public static class TriggeringPolicy implements OptionHandler {
227         private boolean activated = false;
228 
229         public TriggeringPolicy() {
230 
231         }
232         public void activateOptions() {
233             activated = true;
234         }
235 
236         public final boolean isActivated() {
237             return activated;
238         }
239 
240     }
241 
242     /**
243      * Mock definition of FilterBasedTriggeringPolicy from extras companion.
244      */
245     public static final class FilterBasedTriggeringPolicy extends TriggeringPolicy {
246         private Filter filter;
247         public FilterBasedTriggeringPolicy() {
248         }
249 
250         public void setFilter(final Filter val) {
251              filter = val;
252         }
253 
254         public Filter getFilter() {
255             return filter;
256 
257         }
258     }
259 
260     /**
261      * Mock definition of org.apache.log4j.rolling.RollingFileAppender
262      * from extras companion.
263      */
264     public static final class RollingFileAppender extends AppenderSkeleton {
265         private RollingPolicy rollingPolicy;
266         private TriggeringPolicy triggeringPolicy;
267         private boolean append;
268 
269         public RollingFileAppender() {
270 
271         }
272 
273         public RollingPolicy getRollingPolicy() {
274             return rollingPolicy;
275         }
276 
277         public void setRollingPolicy(final RollingPolicy policy) {
278             rollingPolicy = policy;
279         }
280 
281         public TriggeringPolicy getTriggeringPolicy() {
282             return triggeringPolicy;
283         }
284 
285         public void setTriggeringPolicy(final TriggeringPolicy policy) {
286             triggeringPolicy = policy;
287         }
288 
289         public boolean getAppend() {
290             return append;
291         }
292 
293         public void setAppend(boolean val) {
294             append = val;
295         }
296 
297         public void close() {
298 
299         }
300 
301         public boolean requiresLayout() {
302             return true;
303         }
304 
305         public void append(final LoggingEvent event) {
306 
307         }
308     }
309 
310     /**
311      * Tests processing of nested objects, see bug 36384.
312      */
313     public void testNested() {
314         try {
315             PropertyConfigurator.configure("input/filter1.properties");
316             this.validateNested();
317         } finally {
318             LogManager.resetConfiguration();
319         }
320     }
321 
322 
323     /**
324      * Mock ThrowableRenderer for testThrowableRenderer.  See bug 45721.
325      */
326     public static class MockThrowableRenderer implements ThrowableRenderer, OptionHandler {
327         private boolean activated = false;
328         private boolean showVersion = true;
329 
330         public MockThrowableRenderer() {
331         }
332 
333         public void activateOptions() {
334             activated = true;
335         }
336 
337         public boolean isActivated() {
338             return activated;
339         }
340 
341         public String[] doRender(final Throwable t) {
342             return new String[0];
343         }
344 
345         public void setShowVersion(boolean v) {
346             showVersion = v;
347         }
348 
349         public boolean getShowVersion() {
350             return showVersion;
351         }
352     }
353 
354     /**
355      * Test of log4j.throwableRenderer support.  See bug 45721.
356      */
357     public void testThrowableRenderer() {
358         Properties props = new Properties();
359         props.put("log4j.throwableRenderer", "org.apache.log4j.PropertyConfiguratorTest$MockThrowableRenderer");
360         props.put("log4j.throwableRenderer.showVersion", "false");
361         PropertyConfigurator.configure(props);
362         ThrowableRendererSupport repo = (ThrowableRendererSupport) LogManager.getLoggerRepository();
363         MockThrowableRenderer renderer = (MockThrowableRenderer) repo.getThrowableRenderer();
364         LogManager.resetConfiguration();
365         assertNotNull(renderer);
366         assertEquals(true, renderer.isActivated());
367         assertEquals(false, renderer.getShowVersion());
368     }
369 }