View Javadoc

    1   /*
    2    * $Id: CachingGroovyEngine.java,v 1.5 2004/12/14 00:08:26 spullara 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 String[] EMPTY_ARGS = {
    61      };
    62
    63      private Map evalScripts;
    64      private Map execScripts;
    65      private Binding context;
    66      private ClassLoader parent;
    67      private GroovyClassLoader loader;
    68
    69
    70      /***
    71       * Evaluate an expression.
    72       */
    73      public Object eval(String source, int lineNo, int columnNo, Object script) throws BSFException {
    74          try {
    75              //          Object result = shell.evaluate(script.toString(), source);
    76              Class scriptClass = (Class) evalScripts.get(script);
    77              if (scriptClass == null) {
    78                  scriptClass = loader.parseClass(new ByteArrayInputStream(script.toString().getBytes()), source);
    79                  evalScripts.put(script, scriptClass);
    80              } else {
    81                  System.out.println("eval() - Using cached script...");
    82              }
    83              //can't cache the script because the context may be different.
    84              //but don't bother loading parsing the class again
    85              Script s = InvokerHelper.createScript(scriptClass, context);
    86              return s.run();
    87          } catch (Exception e) {
    88              throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "exception from Groovy: " + e, e);
    89          }
    90      }
    91
    92      /***
    93       * Execute a script.
    94       */
    95      public void exec(String source, int lineNo, int columnNo, Object script) throws BSFException {
    96          try {
    97              //          shell.run(script.toString(), source, EMPTY_ARGS);
    98
    99              Class scriptClass = (Class) execScripts.get(script);
    100             if (scriptClass == null) {
    101                 scriptClass = loader.parseClass(new ByteArrayInputStream(script.toString().getBytes()), source);
    102                 execScripts.put(script, scriptClass);
    103             } else {
    104                 System.out.println("exec() - Using cached version of class...");
    105             }
    106             InvokerHelper.invokeMethod(scriptClass, "main", EMPTY_ARGS);
    107         } catch (Exception e) {
    108             throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "exception from Groovy: " + e, e);
    109         }
    110     }
    111
    112     /***
    113      * Initialize the engine.
    114      */
    115     public void initialize(final BSFManager mgr, String lang, Vector declaredBeans) throws BSFException {
    116         super.initialize(mgr, lang, declaredBeans);
    117         parent = mgr.getClassLoader();
    118         if (parent == null)
    119             parent = GroovyShell.class.getClassLoader();
    120         final ClassLoader finalParent = parent;
    121         this.loader =
    122                 (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
    123                     public Object run() {
    124                         CompilerConfiguration configuration = new CompilerConfiguration();
    125                         configuration.setClasspath(mgr.getClassPath());
    126                         return new GroovyClassLoader(finalParent, configuration);
    127                     }
    128                 });
    129         execScripts = new HashMap();
    130         evalScripts = new HashMap();
    131         context = shell.getContext();
    132         // create a shell
    133
    134         // register the mgr with object name "bsf"
    135         context.setVariable("bsf", new BSFFunctions(mgr, this));
    136
    137         int size = declaredBeans.size();
    138         for (int i = 0; i < size; i++) {
    139             declareBean((BSFDeclaredBean) declaredBeans.elementAt(i));
    140         }
    141     }
    142 }