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.log4j.chainsaw.receivers;
    18
    19
    20  import java.beans.BeanInfo;
    21  import java.beans.Introspector;
    22  import java.beans.PropertyDescriptor;
    23  import java.io.File;
    24  import java.io.FileOutputStream;
    25  import java.io.IOException;
    26  import java.io.InputStreamReader;
    27  import java.io.LineNumberReader;
    28  import java.net.URL;
    29  import java.util.ArrayList;
    30  import java.util.Arrays;
    31  import java.util.Collections;
    32  import java.util.Iterator;
    33  import java.util.List;
    34
    35  import javax.xml.parsers.DocumentBuilder;
    36  import javax.xml.parsers.DocumentBuilderFactory;
    37  import javax.xml.transform.OutputKeys;
    38  import javax.xml.transform.Transformer;
    39  import javax.xml.transform.TransformerFactory;
    40  import javax.xml.transform.dom.DOMSource;
    41  import javax.xml.transform.stream.StreamResult;
    42
    43  import org.apache.log4j.LogManager;
    44  import org.apache.log4j.Logger;
    45  import org.apache.log4j.chainsaw.plugins.PluginClassLoaderFactory;
    46  import org.apache.log4j.plugins.Plugin;
    47  import org.apache.log4j.plugins.PluginRegistry;
    48  import org.apache.log4j.plugins.Receiver;
    49  import org.apache.log4j.spi.LoggerRepository;
    50  import org.apache.log4j.spi.LoggerRepositoryEx;
    51  import org.w3c.dom.Document;
    52  import org.w3c.dom.Element;
    53
    54
    55  /**
    56   * Helper class to assisit with all the known Receivers.
    57   *
    58   * A local resource 'known.receivers' is read in on initialization
    59   * with each line representing the FQN of the Class that is a recognised Receiver.
    60   *
    61   * @author Paul Smith &lt;psmith@apache.org&gt;
    62   *
    63   */
    64  public class ReceiversHelper {
    65
    66      private static final ReceiversHelper instance = new ReceiversHelper();
    67
    68      private final Logger logger = LogManager.getLogger(ReceiversHelper.class);
    69      private List receiverClassList = new ArrayList();
    70      /**
    71       *
    72       */
    73      private ReceiversHelper() {
    74
    75          URL url = this.getClass().getClassLoader().getResource(
    76              this.getClass().getPackage().getName().replace('.','/') + "/known.receivers");
    77          if (url == null) {
    78              logger.warn("Failed to locate known.receivers file");
    79              return;
    80          }
    81          LineNumberReader stream = null;
    82          try {
    83
    84              stream = new LineNumberReader(new InputStreamReader(url.openStream()));
    85              String line;
    86              // we need the special Classloader, because under Web start, optional jars might be local
    87              // to this workstation
    88              ClassLoader classLoader = PluginClassLoaderFactory.getInstance().getClassLoader();
    89
    90              while ((line = stream.readLine()) != null) {
    91
    92              	try {
    93              		if (line.startsWith("#") || (line.length() == 0)) {
    94              			continue;
    95              		}
    96              		Class receiverClass = classLoader.loadClass(line);
    97              		receiverClassList.add(receiverClass);
    98              		logger.debug("Located known Receiver class " + receiverClass.getName());
    99              	} catch (ClassNotFoundException e) {
    100             		logger.warn("Failed to locate Receiver class:" + line);
    101             	}
    102             	catch (NoClassDefFoundError e) {
    103             		logger.error("Failed to locate Receiver class:" + line + ", looks like a dependent class is missing from the classpath", e);
    104             	}
    105             }
    106         } catch (Exception e) {
    107             e.printStackTrace();
    108         } finally {
    109             if (stream != null) {
    110                 try {
    111                     stream.close();
    112                 } catch (IOException ioe) {
    113                     ioe.printStackTrace();
    114                 }
    115             }
    116         }
    117     }
    118
    119
    120     public static ReceiversHelper getInstance() {
    121         return instance;
    122     }
    123
    124
    125     /**
    126      * Returns an unmodifiable list of Class objects which represent all the 'known'
    127      * Receiver classes.
    128      * @return known receiver classes
    129      */
    130     public List getKnownReceiverClasses() {
    131       return Collections.unmodifiableList(receiverClassList);
    132     }
    133
    134
    135   public void saveReceiverConfiguration(File file) {
    136     LoggerRepository repo = LogManager.getLoggerRepository();
    137     PluginRegistry pluginRegistry = ((LoggerRepositoryEx) repo).getPluginRegistry();
    138     List fullPluginList = pluginRegistry.getPlugins();
    139     List pluginList = new ArrayList();
    140     for (Iterator iter = fullPluginList.iterator();iter.hasNext();) {
    141         Plugin thisPlugin = (Plugin)iter.next();
    142         if (thisPlugin instanceof Receiver) {
    143             pluginList.add(thisPlugin);
    144         }
    145     }
    146     //remove everything that isn't a receiver..otherwise, we'd create an empty config file
    147     try {
    148         if (pluginList.size() > 0) {
    149             //we programmatically register the ZeroConf plugin in the plugin registry
    150             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    151             factory.setNamespaceAware(true);
    152             DocumentBuilder builder = factory.newDocumentBuilder();
    153             Document document = builder.newDocument();
    154             Element rootElement = document.createElementNS("http://jakarta.apache.org/log4j/", "configuration");
    155             rootElement.setPrefix("log4j");
    156             rootElement.setAttribute("xmlns:log4j", "http://jakarta.apache.org/log4j/");
    157             rootElement.setAttribute("debug", "true");
    158
    159             for (int i = 0; i < pluginList.size(); i++) {
    160                 Receiver receiver;
    161
    162                 if (pluginList.get(i) instanceof Receiver) {
    163                     receiver = (Receiver) pluginList.get(i);
    164                 } else {
    165                     continue;
    166                 }
    167
    168                 Element pluginElement = document.createElement("plugin");
    169                 pluginElement.setAttribute("name", receiver.getName());
    170                 pluginElement.setAttribute("class", receiver.getClass().getName());
    171
    172                 BeanInfo beanInfo = Introspector.getBeanInfo(receiver.getClass());
    173                 List list = new ArrayList(Arrays.asList(beanInfo.getPropertyDescriptors()));
    174
    175                 for (int j = 0; j < list.size(); j++) {
    176                     PropertyDescriptor d = (PropertyDescriptor) list.get(j);
    177                     //don't serialize the loggerRepository property for subclasses of componentbase..
    178                     //easier to change this than tweak componentbase right now..
    179                     if (d.getReadMethod().getName().equals("getLoggerRepository")) {
    180                         continue;
    181                     }
    182                     Object o = d.getReadMethod().invoke(receiver, new Object[] {} );
    183                     if (o != null) {
    184                         Element paramElement = document.createElement("param");
    185                         paramElement.setAttribute("name", d.getName());
    186                         paramElement.setAttribute("value", o.toString());
    187                         pluginElement.appendChild(paramElement);
    188                     }
    189                 }
    190
    191                 rootElement.appendChild(pluginElement);
    192
    193             }
    194
    195             TransformerFactory transformerFactory = TransformerFactory.newInstance();
    196             Transformer transformer = transformerFactory.newTransformer();
    197             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    198             transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    199             DOMSource source = new DOMSource(rootElement);
    200             FileOutputStream stream = new FileOutputStream(file);
    201             StreamResult result = new StreamResult(stream);
    202             transformer.transform(source, result);
    203             stream.close();
    204         }
    205
    206     } catch (Exception e) {
    207         e.printStackTrace();
    208     }
    209   }
    210 }