/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.transformation; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.apache.cocoon.components.source.SourceUtil; import org.apache.cocoon.environment.SourceResolver; import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.xml.sax.SAXException; import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.Map; /** * @cocoon.sitemap.component.documentation * The <code>LogTransformer</code> is a class that can be plugged into a pipeline * to print the SAX events which passes thru this transformer in a readable form * to a file. * * @cocoon.sitemap.component.name log * @cocoon.sitemap.component.logger sitemap.transformer.log * * @cocoon.sitemap.component.pooling.max 16 * * * The <code>LogTransformer</code> is a class that can be plugged into a pipeline * to print the SAX events which passes thru this transformer in a readable form * to a file. * <br> * The file will be specified in a parameter tag in the sitemap pipeline to the * transformer as follows: * <p> * <pre> * <map:transform type="log"> *   <map:parameter name="logfile" value="logfile.log"/> *   <map:parameter name="append" value="no"/> * </map:transform> * </pre> * </p> * * Because the log file will be hardcoded into the sitemap this LOGTransformer will * not be thread save!! * <br> * This transformations main purpose is debugging. * * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a> * @author <a href="mailto:giacomo.pati@pwr.ch">Giacomo Pati</a> * (PWR Organisation & Entwicklung) * @version CVS $Id$ * */ public class LogTransformer extends AbstractTransformer { private static String lf = System.getProperty("line.separator", "\n"); /** log file */ private FileWriter logfile; /** * Setup */ public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { final boolean append = parameters.getParameterAsBoolean("append", false); final String logfilename = parameters.getParameter("logfile", null); // Check for null, use System.out if logfile is not specified. this.logfile = null; if ( null != logfilename ) { Source source = null; try { source = resolver.resolveURI( logfilename ); final String systemId = source.getURI(); if ( systemId.startsWith("file:") ) { this.logfile = new FileWriter(systemId.substring(5), append ); } else { throw new ProcessingException("The logfile parameter must point to a file: " + logfilename); } } catch (SourceException se) { throw SourceUtil.handle(se); } finally { resolver.release( source ); } } Date date = new Date(); StringBuffer logEntry = new StringBuffer(); logEntry.append ( "---------------------------- [" ); logEntry.append ( date.toString() ); logEntry.append ( "] ----------------------------" ); this.log("setup", logEntry.toString()); } /** * Recycle */ public void recycle() { super.recycle(); try { if (this.logfile != null) logfile.close(); } catch (Exception e) { this.getLogger().warn("LogTransformer.recycle()", e); } this.logfile = null; } /** * Receive an object for locating the origin of SAX document events. */ public void setDocumentLocator(Locator locator) { this.log("setDocumentLocator", locator != null ? "systemid="+locator.getSystemId()+",publicid="+locator.getPublicId() : "(locator is null)"); if (super.contentHandler!=null) { super.contentHandler.setDocumentLocator(locator); } } /** * Receive notification of the beginning of a document. */ public void startDocument() throws SAXException { this.log("startDocument", ""); if (super.contentHandler!=null) { super.contentHandler.startDocument(); } } /** * Receive notification of the end of a document. */ public void endDocument() throws SAXException { this.log ("endDocument", ""); if (super.contentHandler!=null) { super.contentHandler.endDocument(); } } /** * Begin the scope of a prefix-URI Namespace mapping. */ public void startPrefixMapping(String prefix, String uri) throws SAXException { this.log ("startPrefixMapping", "prefix="+prefix+",uri="+uri); if (super.contentHandler!=null) { super.contentHandler.startPrefixMapping(prefix,uri); } } /** * End the scope of a prefix-URI mapping. */ public void endPrefixMapping(String prefix) throws SAXException { this.log ("endPrefixMapping", "prefix="+prefix); if (super.contentHandler!=null) { super.contentHandler.endPrefixMapping(prefix); } } /** * Receive notification of the beginning of an element. */ public void startElement(String uri, String loc, String raw, Attributes a) throws SAXException { this.log ("startElement", "uri="+uri+",local="+loc+",raw="+raw); for (int i = 0; i < a.getLength(); i++) { this.log (" ", Integer.toString(i+1) +". uri="+a.getURI(i) +",local="+a.getLocalName(i) +",qname="+a.getQName(i) +",type="+a.getType(i) +",value="+a.getValue(i)); } if (super.contentHandler!=null) { super.contentHandler.startElement(uri,loc,raw,a); } } /** * Receive notification of the end of an element. */ public void endElement(String uri, String loc, String raw) throws SAXException { this.log ("endElement", "uri="+uri+",local="+loc+",raw="+raw); if (super.contentHandler!=null) { super.contentHandler.endElement(uri,loc,raw); } } /** * Receive notification of character data. */ public void characters(char ch[], int start, int len) throws SAXException { this.log ("characters", new String(ch,start,len)); if (super.contentHandler!=null) { super.contentHandler.characters(ch,start,len); } } /** * Receive notification of ignorable whitespace in element content. */ public void ignorableWhitespace(char ch[], int start, int len) throws SAXException { this.log ("ignorableWhitespace", new String(ch,start,len)); if (super.contentHandler!=null) { super.contentHandler.ignorableWhitespace(ch,start,len); } } /** * Receive notification of a processing instruction. */ public void processingInstruction(String target, String data) throws SAXException { log ("processingInstruction", "target="+target+",data="+data); if (super.contentHandler!=null) { super.contentHandler.processingInstruction(target,data); } } /** * Receive notification of a skipped entity. */ public void skippedEntity(String name) throws SAXException { this.log ("skippedEntity", "name="+name); if (super.contentHandler!=null) { super.contentHandler.skippedEntity(name); } } /** * Report the start of DTD declarations, if any. */ public void startDTD(String name, String publicId, String systemId) throws SAXException { this.log ("startDTD", "name="+name+",publicId="+publicId+",systemId="+systemId); if (super.lexicalHandler!=null) { super.lexicalHandler.startDTD(name,publicId,systemId); } } /** * Report the end of DTD declarations. */ public void endDTD() throws SAXException { this.log ("endDTD", ""); if (super.lexicalHandler!=null) { super.lexicalHandler.endDTD(); } } /** * Report the beginning of an entity. */ public void startEntity(String name) throws SAXException { this.log ("startEntity", "name="+name); if (super.lexicalHandler!=null) { super.lexicalHandler.startEntity(name); } } /** * Report the end of an entity. */ public void endEntity(String name) throws SAXException { this.log ("endEntity", "name="+name); if (super.lexicalHandler!=null) { super.lexicalHandler.endEntity(name); } } /** * Report the start of a CDATA section. */ public void startCDATA() throws SAXException { this.log ("startCDATA", ""); if (super.lexicalHandler!=null) { super.lexicalHandler.startCDATA(); } } /** * Report the end of a CDATA section. */ public void endCDATA() throws SAXException { this.log ("endCDATA", ""); if (super.lexicalHandler!=null) { super.lexicalHandler.endCDATA(); } } /** * Report an XML comment anywhere in the document. */ public void comment(char ch[], int start, int len) throws SAXException { this.log ("comment", new String(ch,start,len)); if (super.lexicalHandler!=null) { super.lexicalHandler.comment(ch,start,len); } } /** * Report to logfile. */ private void log (String location, String description) { final StringBuffer logEntry = new StringBuffer(); logEntry.append ( "[" ); logEntry.append ( location ); logEntry.append ( "] " ); logEntry.append ( description ); logEntry.append ( lf ); final String text = logEntry.toString(); if ( this.getLogger().isInfoEnabled() ) { this.getLogger().info( text ); } try { if ( null != this.logfile ) { this.logfile.write( text, 0, text.length()); this.logfile.flush(); } else { System.out.println( text ); } } catch(IOException ioe) { this.getLogger().debug("LogTransformer.log", ioe); } } /** * Attempt to close the log file when the class is GC'd */ public void destroy() { try { if (this.logfile != null) logfile.close(); } catch (Exception e) {getLogger().debug("LogTransformer.destroy()", e);} } }