Package org.huihoo.workflow.rules.config

Source Code of org.huihoo.workflow.rules.config.ScriptCompilationContext

//----------------------------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.config;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.URLClassLoader;

import org.huihoo.workflow.rules.Constants;
import org.huihoo.workflow.rules.ScriptContext;
import org.huihoo.workflow.rules.ScriptException;
import org.huihoo.workflow.rules.compiler.Compiler;
import org.huihoo.workflow.rules.compiler.JavaCompiler;
import org.huihoo.workflow.rules.compiler.ScriptCompiler;
import org.huihoo.workflow.rules.compiler.ScriptReader;
import org.huihoo.workflow.rules.compiler.ScriptRuntimeContext;
import org.huihoo.workflow.rules.compiler.ScriptWriter;
import org.huihoo.workflow.rules.compiler.SunJavaCompiler;
import org.huihoo.workflow.rules.interpretor.ScriptWrapper;
import org.huihoo.workflow.rules.loader.ScriptClassLoader;
import org.huihoo.workflow.rules.util.StringManager;
import org.huihoo.workflow.xpdl.WorkflowCondition;
import org.huihoo.workflow.xpdl.WorkflowPackage;
import org.huihoo.workflow.xpdl.WorkflowProcess;
import org.huihoo.workflow.xpdl.WorkflowTransition;


/**
* @author reic
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class ScriptCompilationContext
{
  protected static StringManager sm = StringManager.getManager(Constants.RESOURCE_BUNDLE_BASE);

  private String className;

  private String basePackageName;
  private String derivedPackageName;

  private String scriptJavaFileName;
  private String classFileName;
  private ScriptWriter writer;
  private ScriptReader reader;
 
  private Options options;
  private ScriptWrapper ssw;
  private Compiler scriptCompiler;
  private String classPath;
 
  private String outputDir;
  private ScriptContext scriptContext;
  private URLClassLoader loader;

  private ScriptRuntimeContext rctxt;

  private int removed = 0;

  private URLClassLoader scriptClassLoader;
  private URL baseUrl;
  private Class scriptClass;

  private WorkflowTransition workflowTransition;

  public ScriptCompilationContext(
    WorkflowTransition workflowTransition,
    Options options,
    ScriptContext scriptContext,
    ScriptWrapper ssw,
    ScriptRuntimeContext rctxt)
  {

    this.workflowTransition = workflowTransition;
    this.options = options;
    this.scriptContext = scriptContext;
   
    this.ssw=ssw;
    this.rctxt = rctxt;
    this.basePackageName = Constants.SCRIPT_PACKAGE_NAME;
  }

  /**
   * The classpath that is passed off to the Java compiler.
   */
  public String getClassPath()
  {
    if (classPath != null)
    {
      return classPath;
    }
    return rctxt.getClassPath();
  }

  /**
   * The classpath that is passed off to the Java compiler.
   */
  public void setClassPath(String classPath)
  {
    this.classPath = classPath;
  }

  /**
   * What class loader to use for loading classes while compiling
   * this script?
   */
  public ClassLoader getClassLoader()
  {
    if (loader != null)
    {
      return loader;
    }
    return rctxt.getParentClassLoader();
  }

  public void setClassLoader(URLClassLoader loader)
  {
    this.loader = loader;
  }

  /** ---------- Input/Output  ---------- */

  /**
   * The output directory to generate code into.  The output directory
   * is make up of the scratch directory, which is provide in Options,
   * plus the directory derived from the package name.
   */
  public String getOutputDir()
  {
    if (outputDir == null)
    {
      createOutputDir();
    }

    return outputDir;
  }

  /**
   * Create a "Compiler" object based on some init param data. This
   * is not done yet. Right now we're just hardcoding the actual
   * compilers that are created.
   */
  public Compiler createCompiler() throws ScriptException
  {
    if (scriptCompiler != null)
    {
      return scriptCompiler;
    }

    JavaCompiler javac=new SunJavaCompiler();
    scriptCompiler = new ScriptCompiler(this);
    scriptCompiler.setJavaCompiler(javac);
    return scriptCompiler;
  }

  public Compiler getCompiler()
  {
    return scriptCompiler;
  }

  /** ---------- Access resources in the workflowapp ---------- */

  /**
   * Gets a resource as a stream, relative to the meanings of this
   * scriptContext's implementation.
   * @return a null if the resource cannot be found or represented
   *         as an InputStream.
   */
  public java.io.InputStream getResourceAsStream(String res)
  {
    return scriptContext.getResourceAsStream(canonicalURI(res));
  }

  /**
   * Gets the actual path of a URI relative to the scriptContext of
   * the compilation.
   */
  public String getRealPath(String path)
  {
    if (scriptContext != null)
    {
      return scriptContext.getRealPath(path);
    }
    return path;
  }

  /* ==================== Common implementation ==================== */

  /**
   * Just the class name (does not include package name) of the
   * generated class.
   */
  public String getScriptClassName()
  {

    if (className != null)
    {
      return className;
    }

    className = formatJavaID("_script_" + workflowTransition.getUUID());

    return className;
  }

  public void setScriptClassName(String className)
  {
    this.className = formatJavaID(className);
  }
 
  public WorkflowCondition getCondition()
  {
    return workflowTransition.getCondition();
  }
  /**
   * Package name for the generated class is make up of the base package
   * name, which is user settable, and the derived package name.  The
   * derived package name directly mirrors the file heirachy of the script page.
   */
  public String getScriptPackageName()
  {
    String dPackageName = getDerivedPackageName();
    if (dPackageName.length() == 0)
    {
      return basePackageName;
    }
    return basePackageName + '.' + getDerivedPackageName();
  }

  private String getDerivedPackageName()
  {
    if (derivedPackageName != null)
    {
      return derivedPackageName;
    }

    WorkflowProcess workflowProcess = workflowTransition.getWorkflowProcess();
    WorkflowPackage workflowPackage = workflowProcess.getWorkflowPackage();
    derivedPackageName = formatJavaID("_" + workflowPackage.getUUID() + "._" + workflowProcess.getUUID());

    return derivedPackageName;
  }

  /**
   * The package name into which the script class is generated.
   */
  public void setScriptPackageName(String scriptPackageName)
  {
    this.basePackageName = formatJavaID(scriptPackageName);
  }

  /**
   * Full path name of the Java file into which the script is being
   * generated.
   */
  public String getScriptJavaFileName()
  {

    if (scriptJavaFileName == null)
    {
      scriptJavaFileName = getOutputDir()  + File.separator+ getScriptClassName() + ".java";
    }
    else
    {
      // Make sure output dir exists
      makeOutputDir();
    }
    return scriptJavaFileName;
  }

  public void setScriptJavaFileName(String scriptJavaFileName)
  {
    this.scriptJavaFileName = formatJavaID(scriptJavaFileName);
  }

  /**
   * Get hold of the Options object for this scriptContext.
   */
  public Options getOptions()
  {
    return options;
  }

  public ScriptContext getScriptContext()
  {
    return scriptContext;
  }

  public ScriptRuntimeContext getRuntimeContext()
  {
    return rctxt;
  }

  public String getScriptClassFileName()
  {

    if (classFileName == null)
    {
      classFileName = getOutputDir() + File.separator+getScriptClassName() + ".class";
    }
    else
    {
      // Make sure output dir exists
      makeOutputDir();
    }
    return classFileName;
  }

  /**
   * Where is the script being generated?
   */
  public ScriptWriter getWriter()
  {
    return writer;
  }

  public void setWriter(ScriptWriter writer)
  {
    this.writer = writer;
  }

  /**
   * Get the input reader for the SCRIPT text.
   */
  public ScriptReader getReader()
  {
    return this.reader;
  }

  public void setReader(ScriptReader reader)
  {
    this.reader=reader;
  }
   
  /**
   * Are we keeping generated code around?
   */
  public boolean keepGenerated()
  {
    return getOptions().getKeepGenerated();
  }
  // ==================== Removal ====================

  public void incrementRemoved()
  {
    if (removed > 1)
    {
      scriptCompiler.removeGeneratedFiles();
      if (rctxt != null)
      {
        rctxt.removeScriptWrapper(workflowTransition);
      }
    }
    removed++;
  }

  public boolean isRemoved()
  {
    if (removed > 1)
    {
      return true;
    }
    return false;
  }
  // ==================== Compile and reload ====================

  public void compile() throws FileNotFoundException, ScriptException
  {
    createCompiler();
   
    if (scriptCompiler.isOutDated())
    {
      try
      {
        scriptCompiler.compile();
        ssw.setReload(true);
      }
      catch (ScriptException ex)
      {
        throw ex;
      }
      catch (Exception ex)
      {
        throw new ScriptException(sm.getString("script.error.unable.compile"), ex);
      }
    }
  }
  // ==================== Manipulating the class ====================

  public Class load() throws ScriptException,FileNotFoundException
  {
    try
    {
      URL baseUrl = options.getScratchDir().toURL();
      scriptClassLoader = new ScriptClassLoader(new URL[] { baseUrl }, rctxt.getParentClassLoader());

      String name = getScriptPackageName() + "." + getScriptClassName();
      scriptClass = scriptClassLoader.loadClass(name);
    }
    catch (Exception ex)
    {
      if(ex instanceof ScriptException)
      {
        throw (ScriptException)ex;
      }
      throw new ScriptException(sm.getString("script.error.unable.load"), ex);
    }
    removed = 0;
    return scriptClass;
  }

  // ==================== Private methods ====================

  static Object outputDirLock = new Object();

  private void makeOutputDir()
  {
    synchronized (outputDirLock)
    {
      File outDirFile = new File(outputDir);
      outDirFile.mkdirs();
    }
  }

  private void createOutputDir()
  {
    String path = getScriptPackageName().replace('.', '/');

    try
    {
      // Append script or tag handler path to scratch dir
      baseUrl = options.getScratchDir().toURL();

      String outUrlString = baseUrl.toString() + '/' + path;
      URL outUrl = new URL(outUrlString);
      outputDir = outUrl.getFile() + File.separator;
      makeOutputDir();
    }
    catch (Exception e)
    {
      throw new IllegalStateException("No output directory: " + e.getMessage());
    }
  }

  private static final boolean isPathSeparator(char c)
  {
    return (c == '/' || c == '\\');
  }
 
  private static final String formatJavaID(String s)
  {
    if (s == null)
    {
      return null;
    }
   
    return s.replace('-','_');
  }
 
  private static final String canonicalURI(String s)
  {
    if (s == null)
      return null;
    StringBuffer result = new StringBuffer();
    final int len = s.length();
    int pos = 0;
    while (pos < len)
    {
      char c = s.charAt(pos);
      if (isPathSeparator(c))
      {
        /*
          * multiple path separators.
          * 'foo///bar' -> 'foo/bar'
          */
        while (pos + 1 < len && isPathSeparator(s.charAt(pos + 1)))
        {
          ++pos;
        }

        if (pos + 1 < len && s.charAt(pos + 1) == '.')
        {
          /*
            * a single dot at the end of the path - we are done.
            */
          if (pos + 2 >= len)
            break;

          switch (s.charAt(pos + 2))
          {
            /*
              * self directory in path
              * foo/./bar -> foo/bar
              */
            case '/' :
            case '\\' :
              pos += 2;
              continue;

              /*
                * two dots in a path: go back one hierarchy.
                * foo/bar/../baz -> foo/baz
                */
            case '.' :
              // only if we have exactly _two_ dots.
              if (pos + 3 < len && isPathSeparator(s.charAt(pos + 3)))
              {
                pos += 3;
                int separatorPos = result.length() - 1;
                while (separatorPos >= 0 && !isPathSeparator(result.charAt(separatorPos)))
                {
                  --separatorPos;
                }
                if (separatorPos >= 0)
                  result.setLength(separatorPos);
                continue;
              }
          }
        }
      }
      result.append(c);
      ++pos;
    }
    return result.toString();
  }
}
TOP

Related Classes of org.huihoo.workflow.rules.config.ScriptCompilationContext

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.