Package org.huihoo.workflow.rules.compiler

Source Code of org.huihoo.workflow.rules.compiler.ScriptRuntimeContext

//----------------------------BEGIN LICENSE----------------------------
/*
* Willow : the Open Source WorkFlow Project
* Distributable under GNU LGPL license by gun.org
*
* Copyright (C) 2004-2010 huihoo.org
* Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com>
*
* ====================================================================
* Project Homepage : http://www.huihoo.org/willow
* Source Forge     : http://sourceforge.net/projects/huihoo
* Mailing list     : willow@lists.sourceforge.net
*/
//----------------------------END  LICENSE-----------------------------
package org.huihoo.workflow.rules.compiler;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.huihoo.workflow.rules.Constants;
import org.huihoo.workflow.rules.ScriptContext;
import org.huihoo.workflow.rules.config.Options;
import org.huihoo.workflow.rules.config.ScriptCompilationContext;
import org.huihoo.workflow.rules.interpretor.ScriptWrapper;
import org.huihoo.workflow.rules.util.StringManager;
import org.huihoo.workflow.xpdl.WorkflowCondition;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.condition.ScriptCondition;

import com.zosatapo.commons.util.log.SystemLogHandler;

/**
* @author reic
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class ScriptRuntimeContext implements Runnable
{
  // Logger
  private static Log log = LogFactory.getLog(ScriptRuntimeContext.class);
 
  protected static StringManager sm = StringManager.getManager(Constants.RESOURCE_BUNDLE_BASE);
 
  // ----------------------------------------------------------- Constructors

  /**
   * Create a ScriptRuntimeContext for a org.huihoo.workflow application servletContext.
   *
   * Loads in any previously generated dependencies from file.
   *
   * @param ScriptContext for org.huihoo.workflow application
   */
  public ScriptRuntimeContext(ScriptContext servletContext, Options options)
  {

    System.setErr(new SystemLogHandler(System.err));
    System.setOut(new SystemLogHandler(System.out));
   
    this.servletContext = servletContext;
    this.options = options;

    // Get the parent class loader
    parentClassLoader = (URLClassLoader) servletContext.getAttribute(Constants.SCRIPT_CLASS_LOADER);
   
    if (parentClassLoader == null)
    {
      parentClassLoader = (URLClassLoader) this.getClass().getClassLoader();
    }

   
    if (parentClassLoader != null)
    {
      log.debug(sm.getString("script.message.parent_class_loader_is", parentClassLoader.toString()));
    }
    else
    {
      log.debug(sm.getString("script.message.parent_class_loader_is", "<none>"));
    }
   
    initClassPath();
   
    // If workflow application servletContext is running from a
    // directory, start the background compilation thread
    String appBase = servletContext.getRealPath("/");
    if (appBase != null && options.getReloading())
    {
      if (appBase.endsWith(File.separator))
      {
        appBase = appBase.substring(0, appBase.length() - 1);
      }
      String directory = appBase.substring(appBase.lastIndexOf(File.separator));
      threadName = threadName + "[" + directory + "]";
      threadStart();
    }
  }

  // ----------------------------------------------------- Instance Variables

  /**
   * This org.huihoo.workflow applications ScriptContext
   */
  private ScriptContext servletContext;
  private Options options;
  private URLClassLoader parentClassLoader;
  private String classpath;

  /**
   * Maps WFS pages to their ScriptBase's
   */
  private Map wfses = Collections.synchronizedMap(new HashMap());

  /**
    * The background thread.
    */
  private Thread thread = null;

  /**
    * The background thread completion semaphore.
    */
  private boolean threadDone = false;

  /**
    * Name to register for the background thread.
    */
  private String threadName = "ScriptRuntimeContext";
  // ------------------------------------------------------ Protected Methods

  /**
   * Add a new ScriptWrapper.
   *
   * @param String uri of WFS
   * @param Script className for WFS
   */
  public void addScriptWrapper(
    WorkflowTransition transition,
    ScriptWrapper scriptWrapper)
  {
    wfses.remove(genScriptUUID(transition));
    wfses.put(genScriptUUID(transition), scriptWrapper);
  }

  /**
   * Get an already existing ScriptWrapper.
   *
   */
  public ScriptWrapper getScriptWrapper(WorkflowTransition transition)
  {
    return (ScriptWrapper) wfses.get(genScriptUUID(transition));
  }

  /**
   * Remove a  ScriptWrapper.
   *
   */
  public void removeScriptWrapper(WorkflowTransition transition)
  {
    wfses.remove(genScriptUUID(transition));
  }
  /**
   * Get the parent URLClassLoader.
   *
   * @return URLClassLoader parent
   */
  public URLClassLoader getParentClassLoader()
  {
    return parentClassLoader;
  }

  /**
   * Process a "destory" event for this org.huihoo.workflow application servletContext.
   */
  public void destroy()
  {
    threadStop();
   
    if (System.err instanceof SystemLogHandler)
    {
      System.setErr(((SystemLogHandler) System.err).getWrapped());
    }
   
    Iterator servlets = wfses.values().iterator();
    while (servlets.hasNext())
    {
      ((ScriptWrapper) servlets.next()).destroy();
    }
   
  }

  /**
   * The classpath that is passed off to the Java compiler.
   */
  public String getClassPath()
  {
    return classpath;
  }

  /**
   * Method used to initialize classpath for compiles.
   */
  private void initClassPath()
  {

    URL[] urls = parentClassLoader.getURLs();
    StringBuffer cpath = new StringBuffer();
    String sep = System.getProperty("path.separator");

    for (int i = 0; i < urls.length; i++)
    {
      // Willow can use URL's other than file URL's,
      // a protocol other than file: will generate a
      // bad file system path, so only add file:
      // protocol URL's to the classpath.

      if (urls[i].getProtocol().equals("file"))
      {
        cpath.append((String) urls[i].getFile() + sep);
      }
    }

    cpath.append(options.getScratchDir() + sep);
    classpath = cpath.toString();
   
    String cp = (String) servletContext.getAttribute(Constants.SCRIPT_CLASS_PATH);
   
    if (cp == null || cp.equals(""))
    {
      cp = options.getClassPath();
    }
   
    if(cp!=null)
    {
      classpath +=cp;
    }
  }

  private String genScriptUUID(WorkflowTransition workflowTransition)
  {
    WorkflowCondition condition=workflowTransition.getCondition();
    if(condition!=null && condition instanceof ScriptCondition)
    {
      return workflowTransition.getUUID()+"."+condition.getContent();
    }
   
    return workflowTransition.getUUID();
  }
 
  // -------------------------------------------------------- Thread Support

  /**
   * Start the background thread that will periodically check for
   * changes to compile time script files in a WFS.
   *
   * @exception IllegalStateException if we should not be starting
   *  a background thread now
   */
  protected void threadStart()
  {

    // Has the background thread already been started?
    if (thread != null)
    {
      return;
    }

    // Start the background thread
    threadDone = false;
    thread = new Thread(this, threadName);
    thread.setDaemon(true);
    thread.start();

  }

  /**
   * Stop the background thread that is periodically checking for
   * changes to compile time included files in a RULE.
   */
  protected void threadStop()
  {

    if (thread == null)
    {
      return;
    }

    threadDone = true;
    thread.interrupt();
    thread = null;

  }

  /**
   * Sleep for the duration specified by the <code>checkInterval</code>
   * property.
   */
  protected void threadSleep()
  {

    try
    {
      Thread.sleep(options.getCheckInterval() * 1000L);
    }
    catch (InterruptedException e)
    {
      ;
    }

  }

  // ------------------------------------------------------ Background Thread

  /**
   * Method used by background thread to check the RULE dependencies
   * registered with this class for RULE's.
   */
  private void checkCompile()
  {
    Object[] scriptWrappers = wfses.values().toArray();
    for (int i = 0; i < scriptWrappers.length; i++)
    {
      ScriptWrapper scriptWrapper = (ScriptWrapper) scriptWrappers[i];
      ScriptCompilationContext ctxt = scriptWrapper.getServletEngineContext();
     
      // scriptWrapper also synchronizes on this when
      // it detects it has to do a reload
      synchronized (scriptWrapper)
      {
        try
        {
          ctxt.compile();
        }
        catch (FileNotFoundException ex)
        {
          ctxt.incrementRemoved();
        }
        catch (Throwable t)
        {
          scriptWrapper.getServletContext().log("Background compile failed", t);
        }
      }
    }
  }

  /**
   * The background thread that checks for changes to files
   * included by a RULE and flags that a recompile is required.
   */
  public void run()
  {

    // Loop until the termination semaphore is set
    while (!threadDone)
    {

      // Wait for our check interval
      threadSleep();

      // Check for script files which are newer than the
      // WFS which uses them.
      try
      {
        checkCompile();
      }
      catch (Throwable t)
      {
        t.printStackTrace();
      }
    }
  }
}
TOP

Related Classes of org.huihoo.workflow.rules.compiler.ScriptRuntimeContext

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.