    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 }