Return-Path: Delivered-To: apmail-logging-general-archive@www.apache.org Received: (qmail 83859 invoked from network); 24 Aug 2007 05:45:41 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 24 Aug 2007 05:45:41 -0000 Received: (qmail 21831 invoked by uid 500); 24 Aug 2007 05:45:36 -0000 Delivered-To: apmail-logging-general-archive@logging.apache.org Received: (qmail 21779 invoked by uid 500); 24 Aug 2007 05:45:36 -0000 Mailing-List: contact general-help@logging.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Logging General" List-Id: Delivered-To: mailing list general@logging.apache.org Received: (qmail 21759 invoked by uid 99); 24 Aug 2007 05:45:36 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 Aug 2007 22:45:36 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Aug 2007 05:45:37 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 9C8C81A987A; Thu, 23 Aug 2007 22:44:30 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r569257 [18/18] - in /logging/site/trunk/docs/log4j/companions/extras: ./ apidocs/ apidocs/org/apache/log4j/ apidocs/org/apache/log4j/class-use/ apidocs/org/apache/log4j/extras/ apidocs/org/apache/log4j/extras/class-use/ apidocs/org/apache/... Date: Fri, 24 Aug 2007 05:43:56 -0000 To: general@logging.apache.org From: carnold@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070824054430.9C8C81A987A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/XSLTLayout.html URL: http://svn.apache.org/viewvc/logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/XSLTLayout.html?rev=569257&view=auto ============================================================================== --- logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/XSLTLayout.html (added) +++ logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/XSLTLayout.html Thu Aug 23 22:43:39 2007 @@ -0,0 +1,501 @@ + + + +XSLTLayout xref + + + +
+
+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.xml;
+18  import org.apache.log4j.Layout;
+19  import org.apache.log4j.helpers.LogLog;
+20  import org.apache.log4j.helpers.MDCKeySetExtractor;
+21  import org.apache.log4j.spi.LoggingEvent;
+22  import org.apache.log4j.spi.LocationInfo;
+23  import org.w3c.dom.Element;
+24  import org.w3c.dom.NodeList;
+25  
+26  import javax.xml.transform.TransformerFactory;
+27  import javax.xml.transform.TransformerConfigurationException;
+28  import javax.xml.transform.Templates;
+29  import javax.xml.transform.Transformer;
+30  import javax.xml.transform.sax.TransformerHandler;
+31  import javax.xml.transform.sax.SAXTransformerFactory;
+32  import javax.xml.transform.stream.StreamSource;
+33  import javax.xml.transform.stream.StreamResult;
+34  import javax.xml.transform.dom.DOMSource;
+35  import javax.xml.parsers.DocumentBuilderFactory;
+36  import java.io.InputStream;
+37  import java.io.ByteArrayOutputStream;
+38  import java.io.ByteArrayInputStream;
+39  import java.util.Set;
+40  import java.util.Properties;
+41  import java.util.Arrays;
+42  import java.util.TimeZone;
+43  import java.nio.charset.Charset;
+44  import java.nio.ByteBuffer;
+45  import org.apache.log4j.pattern.CachedDateFormat;
+46  import java.text.SimpleDateFormat;
+47  
+48  import org.w3c.dom.Document;
+49  
+50  import org.xml.sax.helpers.AttributesImpl;
+51  
+52  
+53  /***
+54   * XSLTLayout transforms each event as a document using
+55   * a specified or default XSLT transform.  The default
+56   * XSLT transform produces a result similar to XMLLayout.
+57   *
+58   * When used with a FileAppender or similar, the transformation of
+59   * an event will be appended to the results for previous
+60   * transforms.  If each transform results in an XML element, then
+61   * resulting file will only be an XML entity
+62   * since an XML document requires one and only one top-level element.
+63   * To process the entity, reference it in a XML document like so:
+64   *
+65   * <pre>
+66   *  &lt;!DOCTYPE log4j:eventSet [&lt;!ENTITY data SYSTEM &quot;data.xml&quot;&gt;]&gt;
+67   *
+68   *  &lt;log4j:eventSet xmlns:log4j=&quot;http://jakarta.apache.org/log4j/&quot;&gt;
+69   *    &amp;data
+70   *  &lt;/log4j:eventSet&gt;
+71   *
+72   * </pre>
+73   *
+74   * The layout will detect the encoding and media-type specified in
+75   * the transform.  If no encoding is specified in the transform,
+76   * an xsl:output element specifying the US-ASCII encoding will be inserted
+77   * before processing the transform.  If an encoding is specified in the transform,
+78   * the same encoding should be explicitly specified for the appender.
+79   *
+80   * Extracting MDC values can be expensive when used with log4j releases
+81   * prior to 1.2.15.  Output of MDC values is enabled by default
+82   * but be suppressed by setting properties to false.
+83   *
+84   * Extracting location info can be expensive regardless of log4j version.  
+85   * Output of location info is disabled by default but can be enabled
+86   * by setting locationInfo to true.
+87   *
+88   * Embedded transforms in XML configuration should not
+89   * depend on namespace prefixes defined earlier in the document
+90   * as namespace aware parsing in not generally performed when
+91   * using DOMConfigurator.  The transform will serialize
+92   * and reparse to get the namespace aware document needed.
+93   *
+94   */
+95  public final class XSLTLayout extends Layout
+96          implements UnrecognizedElementHandler {
+97      /***
+98       * Namespace for XSLT.
+99       */
+100     private static final String XSLT_NS = "http://www.w3.org/1999/XSL/Transform";
+101     /***
+102      * Namespace for log4j events.
+103      */
+104     private static final String LOG4J_NS = "http://jakarta.apache.org/log4j/";
+105     /***
+106      * Whether location information should be written.
+107      */
+108     private boolean locationInfo = false;
+109     /***
+110      * media-type (mime type) extracted from XSLT transform.
+111      */
+112     private String mediaType = "text/plain";
+113     /***
+114      * Encoding extracted from XSLT transform.
+115      */
+116     private Charset encoding;
+117     /***
+118      * Transformer factory.
+119      */
+120     private SAXTransformerFactory transformerFactory;
+121     /***
+122      * XSLT templates.
+123      */
+124     private Templates templates;
+125     /***
+126      * Output stream.
+127      */
+128     private final ByteArrayOutputStream outputStream;
+129     /***
+130      * Whether throwable information should be ignored.
+131      */
+132     private boolean ignoresThrowable = false;
+133     /***
+134      * Whether properties should be extracted.
+135      */
+136     private boolean properties = true;
+137     /***
+138      * Whether activateOptions has been called.
+139      */
+140     private boolean activated = false;
+141 
+142     /***
+143      * DateFormat for UTC time.
+144      */
+145     private final CachedDateFormat utcDateFormat;
+146 
+147     /***
+148      * Default constructor.
+149      *
+150      */
+151     public XSLTLayout() {
+152         outputStream = new ByteArrayOutputStream();
+153         transformerFactory = (SAXTransformerFactory)
+154                 TransformerFactory.newInstance();
+155 
+156         SimpleDateFormat zdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+157         zdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+158         utcDateFormat = new CachedDateFormat(zdf, 1000);
+159     }
+160 
+161     /***
+162      * {@inheritDoc}
+163      */
+164     public synchronized String getContentType() {
+165         return mediaType;
+166     }
+167 
+168     /***
+169      * The <b>LocationInfo </b> option takes a boolean value. By default, it is
+170      * set to false which means there will be no location information output by
+171      * this layout. If the the option is set to true, then the file name and line
+172      * number of the statement at the origin of the log statement will be output.
+173      *
+174      * <p>
+175      * If you are embedding this layout within an {@link
+176      * org.apache.log4j.net.SMTPAppender} then make sure to set the
+177      * <b>LocationInfo </b> option of that appender as well.
+178      *
+179      * @param flag new value.
+180      */
+181     public synchronized void setLocationInfo(final boolean flag) {
+182       locationInfo = flag;
+183     }
+184 
+185     /***
+186      * Gets whether location info should be output.
+187      * @return if location is output.
+188      */
+189     public synchronized boolean getLocationInfo() {
+190       return locationInfo;
+191     }
+192 
+193     /***
+194      * Sets whether MDC key-value pairs should be output, default false.
+195      * @param flag new value.
+196      */
+197     public synchronized void setProperties(final boolean flag) {
+198       properties = flag;
+199     }
+200 
+201     /***
+202      * Gets whether MDC key-value pairs should be output.
+203      * @return true if MDC key-value pairs are output.
+204      */
+205     public synchronized boolean getProperties() {
+206       return properties;
+207     }
+208 
+209 
+210     /*** {@inheritDoc} */
+211     public synchronized void activateOptions() {
+212         if (templates == null) {
+213             try {
+214                 InputStream is = XSLTLayout.class.getResourceAsStream("default.xslt");
+215                 StreamSource ss = new StreamSource(is);
+216                 templates = transformerFactory.newTemplates(ss);
+217                 encoding = Charset.forName("US-ASCII");
+218                 mediaType = "text/plain";
+219             } catch (Exception ex) {
+220                 LogLog.error("Error loading default.xslt", ex);
+221             }
+222         }
+223         activated = true;
+224     }
+225 
+226     /***
+227      * Gets whether throwables should not be output.
+228      * @return true if throwables should not be output.
+229      */
+230     public synchronized boolean ignoresThrowable() {
+231         return ignoresThrowable;
+232     }
+233 
+234     /***
+235      * Sets whether throwables should not be output.
+236      * @param ignoresThrowable if true, throwables should not be output.
+237     */
+238     public synchronized void setIgnoresThrowable(boolean ignoresThrowable) {
+239       this.ignoresThrowable = ignoresThrowable;
+240     }
+241 
+242 
+243 
+244     /***
+245      * {@inheritDoc}
+246      */
+247     public synchronized String format(final LoggingEvent event) {
+248       if (!activated) {
+249           activateOptions();
+250       }
+251       if (templates != null && encoding != null) {
+252           outputStream.reset();
+253 
+254           try {
+255             TransformerHandler transformer =
+256                       transformerFactory.newTransformerHandler(templates);
+257 
+258             transformer.setResult(new StreamResult(outputStream));
+259             transformer.startDocument();
+260 
+261             //
+262             //   event element
+263             //
+264             AttributesImpl attrs = new AttributesImpl();
+265             attrs.addAttribute(null, "logger", "logger",
+266                     "CDATA", event.getLoggerName());
+267             attrs.addAttribute(null, "timestamp", "timestamp",
+268                     "CDATA", Long.toString(event.timeStamp));
+269             attrs.addAttribute(null, "level", "level",
+270                     "CDATA", event.getLevel().toString());
+271             attrs.addAttribute(null, "thread", "thread",
+272                     "CDATA", event.getThreadName());
+273             StringBuffer buf = new StringBuffer();
+274             utcDateFormat.format(event.timeStamp, buf);
+275             attrs.addAttribute(null, "time", "time", "CDATA", buf.toString());
+276 
+277 
+278             transformer.startElement(LOG4J_NS, "event", "event", attrs);
+279             attrs.clear();
+280 
+281             //
+282             //   message element
+283             //
+284             transformer.startElement(LOG4J_NS, "message", "message", attrs);
+285             String msg = event.getRenderedMessage();
+286             if (msg != null && msg.length() > 0) {
+287                 transformer.characters(msg.toCharArray(), 0, msg.length());
+288             }
+289             transformer.endElement(LOG4J_NS, "message", "message");
+290 
+291             //
+292             //    NDC element
+293             //
+294             String ndc = event.getNDC();
+295             if (ndc != null) {
+296                 transformer.startElement(LOG4J_NS, "NDC", "NDC", attrs);
+297                 char[] ndcChars = ndc.toCharArray();
+298                 transformer.characters(ndcChars, 0, ndcChars.length);
+299                 transformer.endElement(LOG4J_NS, "NDC", "NDC");
+300             }
+301 
+302             //
+303             //    throwable element unless suppressed
+304             //
+305               if (!ignoresThrowable) {
+306                 String[] s = event.getThrowableStrRep();
+307                 if (s != null) {
+308                     transformer.startElement(LOG4J_NS, "throwable",
+309                             "throwable", attrs);
+310                     char[] nl = new char[] { '\n' };
+311                     for (int i = 0; i < s.length; i++) {
+312                         char[] line = s[i].toCharArray();
+313                         transformer.characters(line, 0, line.length);
+314                         transformer.characters(nl, 0, nl.length);
+315                     }
+316                     transformer.endElement(LOG4J_NS, "throwable", "throwable");
+317                 }
+318               }
+319 
+320               //
+321               //     location info unless suppressed
+322               //
+323               //
+324               if (locationInfo) {
+325                 LocationInfo locationInfo = event.getLocationInformation();
+326                 attrs.addAttribute(null, "class", "class", "CDATA",
+327                         locationInfo.getClassName());
+328                 attrs.addAttribute(null, "method", "method", "CDATA",
+329                           locationInfo.getMethodName());
+330                 attrs.addAttribute(null, "file", "file", "CDATA",
+331                             locationInfo.getFileName());
+332                 attrs.addAttribute(null, "line", "line", "CDATA",
+333                             locationInfo.getLineNumber());
+334                 transformer.startElement(LOG4J_NS, "locationInfo",
+335                         "locationInfo", attrs);
+336                 transformer.endElement(LOG4J_NS, "locationInfo",
+337                         "locationInfo");
+338               }
+339 
+340               if (properties) {
+341                 //
+342                 //    write MDC contents out as properties element
+343                 //
+344                 Set mdcKeySet = MDCKeySetExtractor.INSTANCE.getPropertyKeySet(event);
+345 
+346                 if ((mdcKeySet != null) && (mdcKeySet.size() > 0)) {
+347                     attrs.clear();
+348                     transformer.startElement(LOG4J_NS,
+349                             "properties", "properties", attrs);
+350                     Object[] keys = mdcKeySet.toArray();
+351                     Arrays.sort(keys);
+352                     for (int i = 0; i < keys.length; i++) {
+353                         String key = keys[i].toString();
+354                         Object val = event.getMDC(key);
+355                         attrs.clear();
+356                         attrs.addAttribute(null, "name", "name", "CDATA", key);
+357                         attrs.addAttribute(null, "value", "value",
+358                                 "CDATA", val.toString());
+359                         transformer.startElement(LOG4J_NS,
+360                                 "data", "data", attrs);
+361                         transformer.endElement(LOG4J_NS, "data", "data");
+362                     }
+363                 }
+364               }
+365 
+366 
+367             transformer.endElement(LOG4J_NS, "event", "event");
+368             transformer.endDocument();
+369 
+370             String body = encoding.decode(
+371                     ByteBuffer.wrap(outputStream.toByteArray())).toString();
+372             outputStream.reset();
+373             //
+374             //   must remove XML declaration since it may
+375             //      result in erroneous encoding info
+376             //      if written by FileAppender in a different encoding
+377             if (body.startsWith("<?xml ")) {
+378                 int endDecl = body.indexOf("?>");
+379                 if (endDecl != -1) {
+380                     endDecl += 2;
+381                     if (endDecl < body.length() && body.charAt(endDecl) == '\n') {
+382                         endDecl++;
+383                     }
+384                     return body.substring(endDecl);
+385                 }
+386             }
+387             return body;
+388           } catch (Exception ex) {
+389               LogLog.error("Error during transformation", ex);
+390               return ex.toString();
+391           }
+392       }
+393       return "No valid transform or encoding specified.";
+394     }
+395 
+396     /***
+397      * Sets XSLT transform.
+398      * @param xsltdoc DOM document containing XSLT transform source,
+399      * may be modified.
+400      * @throws TransformerConfigurationException if transformer can not be
+401      * created.
+402      */
+403     public void setTransform(final Document xsltdoc)
+404             throws TransformerConfigurationException {
+405         //
+406         //  scan transform source for xsl:output elements
+407         //    and extract encoding, media (mime) type and output method
+408         //
+409         String encodingName = null;
+410         mediaType = null;
+411         String method = null;
+412         NodeList nodes = xsltdoc.getElementsByTagNameNS(
+413                 XSLT_NS,
+414                 "output");
+415         for(int i = 0; i < nodes.getLength(); i++) {
+416             Element outputElement = (Element) nodes.item(i);
+417             if (method == null || method.length() == 0) {
+418                 method = outputElement.getAttributeNS(null, "method");
+419             }
+420             if (encodingName == null || encodingName.length() == 0) {
+421                 encodingName = outputElement.getAttributeNS(null, "encoding");
+422             }
+423             if (mediaType == null || mediaType.length() == 0) {
+424                 mediaType = outputElement.getAttributeNS(null, "media-type");
+425             }
+426         }
+427 
+428         if (mediaType == null || mediaType.length() == 0) {
+429             if ("html".equals(method)) {
+430                 mediaType = "text/html";
+431             } else if ("xml".equals(method)) {
+432                 mediaType = "text/xml";
+433             } else {
+434                 mediaType = "text/plain";
+435             }
+436         }
+437 
+438         //
+439         //  if encoding was not specified,
+440         //     add xsl:output encoding=US-ASCII to XSLT source
+441         //
+442         if (encodingName == null || encodingName.length() == 0) {
+443             Element transformElement = xsltdoc.getDocumentElement();
+444             Element outputElement = xsltdoc.
+445                     createElementNS(XSLT_NS, "output");
+446             outputElement.setAttributeNS(null, "encoding", "US-ASCII");
+447             transformElement.insertBefore(outputElement, transformElement.getFirstChild());
+448             encoding = Charset.forName("US-ASCII");
+449         } else {
+450             encoding = Charset.forName(encodingName);
+451         }
+452 
+453         DOMSource transformSource = new DOMSource(xsltdoc);
+454         
+455         templates = transformerFactory.newTemplates(transformSource);
+456 
+457     }
+458 
+459     /***
+460      * {@inheritDoc}
+461      */
+462     public boolean parseUnrecognizedElement(final Element element,
+463                                             final Properties props)
+464             throws Exception {
+465         if (XSLT_NS.equals(element.getNamespaceURI()) ||
+466                 element.getNodeName().indexOf("transform") != -1 ||
+467                 element.getNodeName().indexOf("stylesheet") != -1) {
+468             //
+469             //   DOMConfigurator typically not namespace aware
+470             //     serialize tree and reparse.
+471             ByteArrayOutputStream os = new ByteArrayOutputStream();
+472             DOMSource source = new DOMSource(element);
+473             TransformerFactory transformerFactory = TransformerFactory.newInstance();
+474             Transformer transformer = transformerFactory.newTransformer();
+475             transformer.transform(source, new StreamResult(os));
+476 
+477             ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+478             DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+479             domFactory.setNamespaceAware(true);
+480             Document xsltdoc = domFactory.newDocumentBuilder().parse(is);
+481             setTransform(xsltdoc);
+482             return true;
+483         }
+484         return false;
+485     }
+486 
+487 
+488 }
+
+
+ + Propchange: logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/XSLTLayout.html ------------------------------------------------------------------------------ svn:mime-type = text/html Modified: logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-frame.html URL: http://svn.apache.org/viewvc/logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-frame.html?rev=569257&r1=569256&r2=569257&view=diff ============================================================================== --- logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-frame.html (original) +++ logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-frame.html Thu Aug 23 22:43:39 2007 @@ -3,7 +3,7 @@ - Apache Extras Companion for log4j 1.2. 1.0-SNAPSHOT Reference Package org.apache.log4j.xml + Apache Extras Companion for log4j 1.2. 1.0 Reference Package org.apache.log4j.xml @@ -17,6 +17,9 @@ Modified: logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-summary.html URL: http://svn.apache.org/viewvc/logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-summary.html?rev=569257&r1=569256&r2=569257&view=diff ============================================================================== --- logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-summary.html (original) +++ logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/xml/package-summary.html Thu Aug 23 22:43:39 2007 @@ -3,7 +3,7 @@ - Apache Extras Companion for log4j 1.2. 1.0-SNAPSHOT Reference Package $name + Apache Extras Companion for log4j 1.2. 1.0 Reference Package $name @@ -38,6 +38,11 @@ UnrecognizedElementHandler + + + + + XSLTLayout