package com.renderx.cocoon; import java.io.Serializable; import com.renderx.xep.FormatterImpl; import com.renderx.xep.FOTarget; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.serialization.AbstractSerializer; import org.apache.excalibur.source.SourceValidity; import org.apache.excalibur.source.impl.validity.NOPValidity; /** * This XEP Serializer is compatible with XEP Version 4.0.x. It will not work with Version 3.6.3 and before. */ public class XEPSerializer extends AbstractSerializer implements Configurable, CacheableProcessingComponent { //*************************************************************************** //* //* Attributes //* //***************************************************************************/ // Cocoon Logger protected org.apache.avalon.framework.logger.Logger cocoonLogger; /** * The FormatterImpl XEP Formatter Implementation. */ private FormatterImpl formatter; /** * The current mime-type. */ protected String mimetype; /** * Should we set the content length ? */ protected boolean setContentLength = true; /** * SystemId. */ private String systemID; //*************************************************************************** //* //* Cocoon Lifecycle Methods //* //***************************************************************************/ /** * Set the configurations for this serializer. */ public void configure( Configuration conf ) throws ConfigurationException { String loc; if( cocoonLogger == null ) { cocoonLogger = getLogger().getChildLogger( "XEPSerializer" ); } if( conf != null ) { this.setContentLength = conf.getChild( "set-content-length" ).getValueAsBoolean( true ); } // Get the mime type. if (conf != null) this.mimetype = conf.getAttribute( "mime-type" ); if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "mime-type: " + mimetype ); } // best effort, sitemap is in the same directory, or in a upper-level one loc = conf.getLocation(); systemID = loc.substring( 0, loc.lastIndexOf( '/' ) + 1 ) + "xep.fo.input"; if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "systemID: " + systemID ); } // Iterate through the parameters, looking for a renderer reference java.util.Properties properties = new java.util.Properties(); Configuration[] parameters = conf.getChildren( "parameter" ); for( int i = 0; i < parameters.length; i++ ) { String key = parameters[i].getAttribute( "name" ); String value = parameters[i].getAttribute( "value" ); if( key.startsWith( "com.renderx.xep." ) ) { properties.put( key.substring( "com.renderx.xep.".length() ), value ); if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Property set, key: " + key.substring( "com.renderx.xep.".length() ) + ", value: " + value ); } } } try { formatter = new com.renderx.xep.FormatterImpl( properties, new CustomXEPLogger() ); if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "XEP Formatter created" ); } } catch( com.renderx.xep.lib.ConfigurationException e ) { cocoonLogger.error( "XEP Configuration exception creating formatter: " + e ); throw( new ConfigurationException( e.getMessage() ) ); } } /** * Return the MIME type. */ public String getMimeType() { return( mimetype ); } /** * Generate the unique key. * This key must be unique inside the space of this component. * This method must be invoked before the generateValidity() method. * * @return The generated key or 0 if the component * is currently not cacheable. */ public Serializable getKey() // AJT - Replaces above for latest version of Cocoon { return( "1" ); } /** * Generate the validity object. * Before this method can be invoked the generateKey() method * must be invoked. * * @return The generated validity object or null if the * component is currently not cacheable. */ public SourceValidity getValidity() // AJT - Replaces above for latest version of Cocoon { return( NOPValidity.SHARED_INSTANCE ); } /** * Recycle serializer by removing references */ public void recycle() { super.recycle(); if( formatter != null ) { if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Formatter cleanup start..." ); } formatter.cleanup(); if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Formatter cleanup completed." ); } } } /** * Test if the component wants to set the content length */ public boolean shouldSetContentLength() { return( this.setContentLength ); } //*************************************************************************** //* //* SAX ContentHandler Methods //* //***************************************************************************/ /** * Create the XEP formatter which handles the output stream * Set the java.io.OutputStream where the XML should be serialized. */ public void setOutputStream( java.io.OutputStream out ) { String targetFormat = null; if( mimetype.equalsIgnoreCase( "application/postscript" ) ) { targetFormat = "PostScript"; } else if( mimetype.equalsIgnoreCase( "application/pdf" ) ) { targetFormat = "PDF"; } else { cocoonLogger.error( "Invalid mimetype: " + mimetype ); throw( new RuntimeException( "Invalid mimetype: " + mimetype ) ); } if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Target format: " + targetFormat ); } try { setContentHandler( formatter.createContentHandler( systemID, new FOTarget( out, targetFormat ) ) ); } catch( com.renderx.xep.lib.ConfigurationException e ) { cocoonLogger.error( "XEP Configuration exception setting content handler: " + e ); throw( new RuntimeException( e.getMessage() ) ); } } //*************************************************************************** //* //* Custom XEP Logger Class //* //***************************************************************************/ /** * This custom logger class intercepts XEP Logging Events and routes them to the Cocoon Logger (logkit) instead */ private class CustomXEPLogger implements com.renderx.xep.lib.Logger { private boolean processMessage = false; private boolean error = false; private StringBuffer message = null; public CustomXEPLogger() { } public void openDocument() { if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Document opened" ); } } public void closeDocument() { if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Document closed" ); } } public void openState (String state ) { if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "State opened: " + state ); } } public void closeState (String state ) { if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "State closed: " + state ); } } public void event( String type, String message ) { if( cocoonLogger.isDebugEnabled() ) { cocoonLogger.debug( "Event type: " + type + ", message: " + message ); } } public void info( String message ) { if( cocoonLogger.isInfoEnabled() ) { cocoonLogger.info( message ); } } public void warning( String message ) { if( cocoonLogger.isWarnEnabled() ) { cocoonLogger.warn( message ); } } public void error( String message ) { if( cocoonLogger.isErrorEnabled() ) { cocoonLogger.error( message ); } } public void exception( String message, Exception ex ) { if( cocoonLogger.isFatalErrorEnabled() ) { cocoonLogger.fatalError( message, ex ); } } } }