blob: e3d39819eb1254c38e209cf1a408f2ec0db23e16 [file] [log] [blame]
/*
* Copyright 1999-2002,2004 The Apache Software Foundation.
*
* Licensed 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.portal.coplet.adapter.impl;
import java.util.Iterator;
import java.util.Map;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.portal.coplet.CopletData;
import org.apache.cocoon.portal.coplet.CopletInstanceData;
import org.apache.cocoon.portal.coplet.adapter.CopletAdapter;
import org.apache.cocoon.xml.SaxBuffer;
import org.apache.cocoon.xml.XMLUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
/**
* This is the adapter to use pipelines as coplets
*
* @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
* @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
*
* @version CVS $Id: AbstractCopletAdapter.java,v 1.10 2004/03/05 13:02:10 bdelacretaz Exp $
*/
public abstract class AbstractCopletAdapter
extends AbstractLogEnabled
implements CopletAdapter, ThreadSafe, Serviceable {
/** The service manager */
protected ServiceManager manager;
/* (non-Javadoc)
* @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
*/
public void service(ServiceManager manager) throws ServiceException {
this.manager = manager;
}
/**
* Get a configuration value
* First the coplet data is queried and if it doesn't provide an
* attribute with the given name, the coplet base data is used.
*/
protected Object getConfiguration(CopletInstanceData coplet, String key) {
CopletData copletData = coplet.getCopletData();
Object data = copletData.getAttribute( key );
if ( data == null) {
data = copletData.getCopletBaseData().getCopletConfig().get( key );
}
return data;
}
/**
* Implement this and not toSAX()
*/
public abstract void streamContent(CopletInstanceData coplet,
ContentHandler contentHandler)
throws SAXException;
public void toSAX(CopletInstanceData coplet, ContentHandler contentHandler)
throws SAXException {
Boolean bool = (Boolean) this.getConfiguration( coplet, "buffer" );
Integer timeout = (Integer) this.getConfiguration( coplet, "timeout");
if ( timeout != null ) {
// if timeout is set we have to buffer!
bool = Boolean.TRUE;
}
if ( bool != null && bool.booleanValue() ) {
boolean read = false;
SaxBuffer buffer = new SaxBuffer();
Exception error = null;
try {
if ( timeout != null ) {
final int milli = timeout.intValue() * 1000;
LoaderThread loader = new LoaderThread(this, coplet, buffer);
Thread thread = new Thread(loader);
thread.start();
try {
thread.join(milli);
} catch (InterruptedException ignore) {
}
if ( loader.finished ) {
read = true;
}
} else {
this.streamContent( coplet, buffer );
read = true;
}
} catch (Exception exception ) {
error = exception;
this.getLogger().warn("Unable to get content of coplet: " + coplet.getId(), exception);
}
if ( read ) {
buffer.toSAX( contentHandler );
} else {
if ( !this.renderErrorContent(coplet, contentHandler, error)) {
// FIXME - get correct error message
contentHandler.startDocument();
XMLUtils.startElement( contentHandler, "p");
XMLUtils.data( contentHandler, "The coplet " + coplet.getId() + " is currently not available.");
XMLUtils.endElement(contentHandler, "p");
contentHandler.endDocument();
}
}
} else {
this.streamContent( coplet, contentHandler );
}
}
/* (non-Javadoc)
* @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#init(org.apache.cocoon.portal.coplet.CopletInstanceData)
*/
public void init(CopletInstanceData coplet) {
}
/* (non-Javadoc)
* @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#destroy(org.apache.cocoon.portal.coplet.CopletInstanceData)
*/
public void destroy(CopletInstanceData coplet) {
}
/* (non-Javadoc)
* @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#login(org.apache.cocoon.portal.coplet.CopletInstanceData)
*/
public void login(CopletInstanceData coplet) {
// copy temporary attributes from the coplet data
Iterator iter = coplet.getCopletData().getAttributes().entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry entry = (Map.Entry)iter.next();
if ( entry.getKey().toString().startsWith("temporary:") ) {
coplet.setTemporaryAttribute(entry.getKey().toString().substring(10),
entry.getValue());
}
}
}
/* (non-Javadoc)
* @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#logout(org.apache.cocoon.portal.coplet.CopletInstanceData)
*/
public void logout(CopletInstanceData coplet) {
}
/**
* Render the error content for a coplet
* @param coplet The coplet instance data
* @param handler The content handler
* @param error The exception that occured
* @return True if the error content has been rendered, otherwise false
* @throws SAXException
*/
protected boolean renderErrorContent(CopletInstanceData coplet,
ContentHandler handler,
Exception error)
throws SAXException {
return false;
}
}
final class LoaderThread implements Runnable {
private AbstractCopletAdapter adapter;
private ContentHandler handler;
private CopletInstanceData coplet;
boolean finished;
Exception exception;
public LoaderThread(AbstractCopletAdapter adapter,
CopletInstanceData coplet,
ContentHandler handler) {
this.adapter = adapter;
this.coplet = coplet;
this.handler = handler;
}
public void run() {
try {
adapter.streamContent( this.coplet, this.handler );
} catch (Exception local) {
this.exception = local;
} finally {
this.finished = true;
}
}
}