Package org.apache.cocoon.portal.coplet.adapter.impl

Source Code of org.apache.cocoon.portal.coplet.adapter.impl.LoaderThread

/*
* Copyright 1999-2002,2004-2005 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.ProcessingException;
import org.apache.cocoon.components.thread.RunnableManager;
import org.apache.cocoon.environment.CocoonRunnable;
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;
import EDU.oswego.cs.dl.util.concurrent.CountDown;

/**
* This is the abstract base adapter to use pipelines as coplets
*
* <h2>Configuration</h2>
* <table><tbody>
* <tr>
*   <th>buffer</th>
*   <td>Shall the content of the coplet be buffered? If a coplet is
*       buffered, errors local to the coplet are caught and a not
*       availability notice is delivered instead. Buffering does not
*       cache responses for subsequent requests.</td>
*   <td></td>
*   <td>boolean</td>
*   <td><code>false</code></td>
</tr>
* <tr>
*   <th>timeout</th>
*   <td>Max time in seconds content delivery may take. After a timeout,
*       a not availability notice is delivered. Setting a timeout automatically
*       turns on buffering.</td>
*   <td></td>
*   <td>int</td>
*   <td><code>null</code></td>
</tr>
* </tbody></table>
*
* @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 387799 2006-03-22 08:42:57Z cziegeler $
*/
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;
    }
   
    /**
     * 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.
     * If no value is found the default value is returned.
     */
    protected Object getConfiguration(CopletInstanceData coplet,
                                      String key,
                                      Object defaultValue) {
        Object data = this.getConfiguration(coplet, key);
        if ( data == null ) {
            data = defaultValue;
        }
        return data;
    }

    /**
     * Implement this and not toSAX()
     */
    public abstract void streamContent(CopletInstanceData coplet,
                                         ContentHandler contentHandler)
    throws SAXException;
   
    /**
     * This method streams the content of a coplet instance data.
     * It handles buffering and timeout setting and calls
     * {@link #streamContent(CopletInstanceData, ContentHandler)}
     * for creating the content.
     *
     * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#toSAX(org.apache.cocoon.portal.coplet.CopletInstanceData, org.xml.sax.ContentHandler)
     */
    public void toSAX(CopletInstanceData coplet, ContentHandler contentHandler)
    throws SAXException {
        final long startTime = System.currentTimeMillis();
        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);
                    final RunnableManager runnableManager = (RunnableManager)this.manager.lookup( RunnableManager.ROLE );
                    try {
                        runnableManager.execute( new CocoonRunnable(loader) );
                    } finally {
                        this.manager.release( runnableManager );
                    }
                    try {
                        read = loader.join( milli );
                    } catch (InterruptedException ignore) {
                        // ignored
                    }
                    error = loader.exception;
                    if ( error != null && this.getLogger().isWarnEnabled() ) {
                        this.getLogger().warn("Unable to get content of coplet: " + coplet.getId(), error);                       
                    }
                } else {
                    this.streamContent( coplet, buffer );
                    read = true;
                }
            } catch (Exception exception ) {
                error = exception;
                this.getLogger().warn("Unable to get content of coplet: " + coplet.getId(), exception);
            } catch (Throwable t ) {
                error = new ProcessingException("Unable to get content of coplet: " + coplet.getId(), t);
                this.getLogger().warn("Unable to get content of coplet: " + coplet.getId(), t);               
            }
           
            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 );
        }
        if ( this.getLogger().isInfoEnabled() ) {
            final long msecs = System.currentTimeMillis() - startTime;
            this.getLogger().info("Streamed coplet " + coplet.getCopletData().getId() +
                                  " (instance " + coplet.getId() + ") in " + msecs + "ms.");
        }
    }
   
    /* (non-Javadoc)
     * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#init(org.apache.cocoon.portal.coplet.CopletInstanceData)
     */
    public void init(CopletInstanceData coplet) {
        // nothing to do here, can be overwritten in subclasses
    }
   
    /* (non-Javadoc)
     * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#destroy(org.apache.cocoon.portal.coplet.CopletInstanceData)
     */
    public void destroy(CopletInstanceData coplet) {
        // nothing to do here, can be overwritten in subclasses
    }

    /* (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) {
        // nothing to do here, can be overwritten in subclasses
    }
   
    /**
     * 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 final AbstractCopletAdapter adapter;
    private final ContentHandler        handler;
    private final CopletInstanceData    coplet;
    private final CountDown             finished;
    Exception exception;

    public LoaderThread(AbstractCopletAdapter adapter,
                         CopletInstanceData coplet,
                         ContentHandler handler) {
        this.adapter = adapter;
        this.coplet  = coplet;
        this.handler = handler;
        this.finished = new CountDown( 1 );
    }
   
    public void run() {
        try {
            adapter.streamContent( this.coplet, this.handler );
        } catch (Exception local) {
            this.exception = local;
        } finally {
            this.finished.release();
        }
    }
   
    boolean join( final long milis )
    throws InterruptedException {
        return this.finished.attempt( milis );
    }
   
}
TOP

Related Classes of org.apache.cocoon.portal.coplet.adapter.impl.LoaderThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.