/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */

package com.sun.enterprise.web.connector.grizzly.async;

import com.sun.enterprise.web.connector.grizzly.AsyncExecutor;
import com.sun.enterprise.web.connector.grizzly.AsyncHandler;
import com.sun.enterprise.web.connector.grizzly.Pipeline;
import com.sun.enterprise.web.connector.grizzly.ProcessorTask;
import com.sun.enterprise.web.connector.grizzly.TaskBase;
import com.sun.enterprise.web.connector.grizzly.TaskEvent;

/**
 * A <code>Task</code> that wraps the execution of an asynchronous execution
 * of a <code>ProcessorTask</code>. Internaly, this class invoke the associated
 * <code>AsyncExecutor</code> method to execute the <code>ProcessorTask</code>
 * lifecycle operations.
 *
 * @author Jeanfrancois Arcand
 */
public class AsyncProcessorTask extends TaskBase {
    
    public final static int PRE_EXECUTE = 0;
    public final static int INTERRUPTED = 1;
    public final static int POST_EXECUTE = 2;
    public final static int COMPLETED = 3;      
    /**
     * The <code>AsyncExecutor</code> which drive the execution of the 
     * <code>ProcesssorTask</code>
     */
    private AsyncExecutor asyncExecutor;

    
    /**
     * The <code>ProcessorTask</code>
     */
    private ProcessorTask processorTask;
    
    
    /**
     * The current execution stage.
     */
    private int stage = PRE_EXECUTE;
    
    
    /**
     * Execute the <code>AsyncExecutor</code> based on the <code>stage</code>
     * of the <code>ProcessorTask</code> execution.
     */
    public void doTask() throws java.io.IOException {
        boolean contineExecution = true;
        while ( contineExecution ) {
            try{
                switch(stage){
                    case PRE_EXECUTE:
                       stage = INTERRUPTED;                       
                       contineExecution = asyncExecutor.preExecute();
                       break;                
                    case INTERRUPTED:
                       stage = POST_EXECUTE;                        
                       contineExecution = asyncExecutor.interrupt();
                       break;                
                    case POST_EXECUTE:    
                       contineExecution = asyncExecutor.postExecute();
                       stage = COMPLETED;
                       break;                
                }
            } catch (Throwable t){
                if ( stage <= INTERRUPTED) {
                    // We must close the connection.
                    stage = POST_EXECUTE;
                } else {
                    stage = COMPLETED;
                    throw new RuntimeException(t);
                }
            } finally {
                // If the execution is completed, return this task to the pool.
                if ( stage == COMPLETED){
                    stage = PRE_EXECUTE;
                    ((DefaultAsyncHandler)processorTask.getAsyncHandler())
                        .returnTask(this);
                }
            }
        } 
    }

    /**
     * Not used.
     */
    public void taskEvent(TaskEvent event) {
    }
    
    /**
     * Return the <code>stage</code> of the current execution.
     */
    public int getStage(){
        return stage;
    }
    
    
    /**
     * Reset the object.
     */
    public void recycle(){
        stage = PRE_EXECUTE;
        processorTask = null;
    }

    
    /**
     * Set the <code>AsyncExecutor</code> used by this <code>Task</code>
     * to delegate the execution of a <code>ProcessorTask</code>.
     */
    public void setAsyncExecutor(AsyncExecutor asyncExecutor){
        this.asyncExecutor = asyncExecutor;
    }
    
    
    /**
     * Get the <code>AsyncExecutor</code>.
     */
    public AsyncExecutor getAsyncExecutor(){
        return asyncExecutor;
    }
    
    
    /**
     * Set the <code>ProcessorTask</code> that needs to be executed
     * asynchronously.
     */
    public void setProcessorTask(ProcessorTask processorTask){
        this.processorTask = processorTask;
        if ( pipeline == null && processorTask != null) {
            setPipeline(processorTask.getPipeline());
        }        
    }
    
    
    /**
     * Return the <code>ProcessorTask</code>.
     */
    public ProcessorTask getProcessorTask(){
        return processorTask;
    }

}
