/*
 * Created on 2004-3-14
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package workflow.script.interpretor;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import workflow.script.Constants;
import workflow.script.EmbeddedScriptOptions;
import workflow.script.Options;
import workflow.script.ParameterContext;
import workflow.script.ScriptException;
import workflow.script.compiler.ScriptRuntimeContext;
import workflow.script.loader.ScriptClassLoader;
import workflow.script.core.ScriptContext;
import workflow.script.util.StringManager;
import workflow.wfmc.rtm.WorkflowWork;
import workflow.wfmc.xpdl.WorkflowTransition;


/**
 * @author zosatapo
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class JavaInterpretor implements ScriptInterpretor
{
	private static Log log = LogFactory.getLog(JavaInterpretor.class);
	protected static StringManager sm = StringManager.getManager(Constants.RESOURCE_BUNDLE_BASE);
	
	private ScriptContext scriptContext;
	private Options options;
	private ScriptRuntimeContext rctxt;

	private ScriptClassLoader wfsClassLoader;
	
	public void initialize(ScriptContext scriptContext)
	{
		this.scriptContext = scriptContext;
	}

	public ScriptContext getScriptContext()
	{
		return this.scriptContext;
	}

	public boolean evalute(
		WorkflowWork workflowWork,
		WorkflowTransition workflowTransition,
		ParameterContext paramContext)
		throws ScriptException
	{
		return evaluteScriptFile(workflowWork, workflowTransition, paramContext);
	}

	public void start() throws ScriptException
	{		
		this.options = new EmbeddedScriptOptions(this.scriptContext);		
		this.rctxt = new ScriptRuntimeContext(this.scriptContext, this.options);
					
		try
		{	
			URL baseUrl = options.getScratchDir().toURL();
			this.wfsClassLoader = new ScriptClassLoader(new URL[] { baseUrl }, rctxt.getParentClassLoader());
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
			wfsClassLoader = null;
		}
		
		log.debug(
			sm.getString("script.message.scratch.dir.is", options.getScratchDir().toString()));
		log.debug(sm.getString("script.message.dont.modify.servlets"));
	} 
	
	public void stop() throws ScriptException
	{
		log.debug("JavaInterpretor.stop()");
		rctxt.destroy();
	}
	
	// -------------------------------------------------------- Private Methods 
	private boolean evaluteScriptFile(
		WorkflowWork workflowWork,
		WorkflowTransition workflowTransition,
		ParameterContext paramContext)
		throws ScriptException
	{
		String wfsUri = workflowTransition.getScriptFileName();		
		
		if (wfsUri == null || wfsUri.length() == 0)
		{
			//transition unconditionally
			return true;
		}

		ScriptWrapper wrapper = (ScriptWrapper) rctxt.getScriptWrapper(workflowTransition);
		if (wrapper == null)
		{
			// First check if the requested WSP page exists, to avoid
			// creating unnecessary directories and files.
			InputStream resourceStream = scriptContext.getResourceAsStream(options.getScriptDir()+wfsUri);
			
			if (resourceStream == null)
			{
				throw new ScriptException("script not found : "+wfsUri);
			}
			else
			{
				try
				{
					resourceStream.close();
				}
				catch (IOException e)
				{ 
					/* ignore */
				}
			}

			synchronized (this)
			{
				wrapper = (ScriptWrapper) rctxt.getScriptWrapper(workflowTransition);
				if (wrapper == null)
				{
					wrapper = new ScriptWrapper(scriptContext,workflowTransition, options,  rctxt);
					rctxt.addScriptWrapper(workflowTransition, wrapper);
				}
			}
		}

		return wrapper.evalute(workflowWork,workflowTransition, paramContext);
	}
}
