View Javadoc

    1   /*
    2    * $Id: CachingGroovyEngine.java,v 1.6 2005/08/20 19:02:15 blackdrag Exp $
    3    *
    4    * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
    5    *
    6    * Redistribution and use of this software and associated documentation
    7    * ("Software"), with or without modification, are permitted provided that the
    8    * following conditions are met: 1. Redistributions of source code must retain
    9    * copyright statements and notices. Redistributions must also contain a copy
    10   * of this document. 2. Redistributions in binary form must reproduce the above
    11   * copyright notice, this list of conditions and the following disclaimer in
    12   * the documentation and/or other materials provided with the distribution. 3.
    13   * The name "groovy" must not be used to endorse or promote products derived
    14   * from this Software without prior written permission of The Codehaus. For
    15   * written permission, please contact info@codehaus.org. 4. Products derived
    16   * from this Software may not be called "groovy" nor may "groovy" appear in
    17   * their names without prior written permission of The Codehaus. "groovy" is a
    18   * registered trademark of The Codehaus. 5. Due credit should be given to The
    19   * Codehaus - http://groovy.codehaus.org/
    20   *
    21   * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
    22   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    23   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    24   * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
    25   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    27   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    28   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
    31   * DAMAGE.
    32   *
    33   */
    34  package org.codehaus.groovy.bsf;
    35
    36  import groovy.lang.Binding;
    37  import groovy.lang.GroovyClassLoader;
    38  import groovy.lang.GroovyShell;
    39  import groovy.lang.Script;
    40  import org.apache.bsf.BSFDeclaredBean;
    41  import org.apache.bsf.BSFException;
    42  import org.apache.bsf.BSFManager;
    43  import org.apache.bsf.util.BSFFunctions;
    44  import org.codehaus.groovy.control.CompilerConfiguration;
    45  import org.codehaus.groovy.runtime.InvokerHelper;
    46
    47  import java.io.ByteArrayInputStream;
    48  import java.security.AccessController;
    49  import java.security.PrivilegedAction;
    50  import java.util.HashMap;
    51  import java.util.Map;
    52  import java.util.Vector;
    53
    54  /***
    55   * A Caching implementation of the GroovyEngine
    56   *
    57   * @author James Birchfield
    58   */
    59  public class CachingGroovyEngine extends GroovyEngine {
    60      private static final Object[] EMPTY_ARGS = new Object[]{new String[]{}};
    61
    62      private Map evalScripts;
    63      private Map execScripts;
    64      private Binding context;
    65      private ClassLoader parent;
    66      private GroovyClassLoader loader;
    67
    68
    69      /***
    70       * Evaluate an expression.
    71       */
    72      public Object eval(String source, int lineNo, int columnNo, Object script) throws BSFException {
    73          try {
    74              //          Object result = shell.evaluate(script.toString(), source);
    75              Class scriptClass = (Class) evalScripts.get(script);
    76              if (scriptClass == null) {
    77                  scriptClass = loader.parseClass(new ByteArrayInputStream(script.toString().getBytes()), source);
    78                  evalScripts.put(script, scriptClass);
    79              } else {
    80                  System.out.println("eval() - Using cached script...");
    81              }
    82              //can't cache the script because the context may be different.
    83              //but don't bother loading parsing the class again
    84              Script s = InvokerHelper.createScript(scriptClass, context);
    85              return s.run();
    86          } catch (Exception e) {
    87              throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "exception from Groovy: " + e, e);
    88          }
    89      }
    90
    91      /***
    92       * Execute a script.
    93       */
    94      public void exec(String source, int lineNo, int columnNo, Object script) throws BSFException {
    95          try {
    96              //          shell.run(script.toString(), source, EMPTY_ARGS);
    97
    98              Class scriptClass = (Class) execScripts.get(script);
    99              if (scriptClass == null) {
    100                 scriptClass = loader.parseClass(new ByteArrayInputStream(script.toString().getBytes()), source);
    101                 execScripts.put(script, scriptClass);
    102             } else {
    103                 System.out.println("exec() - Using cached version of class...");
    104             }
    105             InvokerHelper.invokeMethod(scriptClass, "main", EMPTY_ARGS);
    106         } catch (Exception e) {
    107             System.err.println("BSF trace");
    108             e.printStackTrace(System.err);
    109             throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "exception from Groovy: " + e, e);
    110         }
    111     }
    112
    113     /***
    114      * Initialize the engine.
    115      */
    116     public void initialize(final BSFManager mgr, String lang, Vector declaredBeans) throws BSFException {
    117         super.initialize(mgr, lang, declaredBeans);
    118         parent = mgr.getClassLoader();
    119         if (parent == null)
    120             parent = GroovyShell.class.getClassLoader();
    121         final ClassLoader finalParent = parent;
    122         this.loader =
    123                 (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
    124                     public Object run() {
    125                         CompilerConfiguration configuration = new CompilerConfiguration();
    126                         configuration.setClasspath(mgr.getClassPath());
    127                         return new GroovyClassLoader(finalParent, configuration);
    128                     }
    129                 });
    130         execScripts = new HashMap();
    131         evalScripts = new HashMap();
    132         context = shell.getContext();
    133         // create a shell
    134
    135         // register the mgr with object name "bsf"
    136         context.setVariable("bsf", new BSFFunctions(mgr, this));
    137
    138         int size = declaredBeans.size();
    139         for (int i = 0; i < size; i++) {
    140             declareBean((BSFDeclaredBean) declaredBeans.elementAt(i));
    141         }
    142     }
    143 }