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 );
}
}
}
}