View Javadoc

    1   /*
    2    * $Id: CachingGroovyEngine.java 4166 2006-10-25 07:07:33Z paulk $
    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  import java.util.logging.Logger;
    54  import java.util.logging.Level;
    55
    56  /***
    57   * A Caching implementation of the GroovyEngine
    58   *
    59   * @author James Birchfield
    60   */
    61  public class CachingGroovyEngine extends GroovyEngine {
    62      private static final Logger LOG = Logger.getLogger(CachingGroovyEngine.class.getName());
    63      private static final Object[] EMPTY_ARGS = new Object[]{new String[]{}};
    64
    65      private Map evalScripts;
    66      private Map execScripts;
    67      private Binding context;
    68      private GroovyClassLoader loader;
    69
    70      /***
    71       * Evaluate an expression.
    72       */
    73      public Object eval(String source, int lineNo, int columnNo, Object script) throws BSFException {
    74          try {
    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                  LOG.fine("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                 LOG.fine("exec() - Using cached version of class...");
    104             }
    105             InvokerHelper.invokeMethod(scriptClass, "main", EMPTY_ARGS);
    106         } catch (Exception e) {
    107             LOG.log(Level.WARNING, "BSF trace", 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         ClassLoader 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         // register the mgr with object name "bsf"
    134         context.setVariable("bsf", new BSFFunctions(mgr, this));
    135         int size = declaredBeans.size();
    136         for (int i = 0; i < size; i++) {
    137             declareBean((BSFDeclaredBean) declaredBeans.elementAt(i));
    138         }
    139     }
    140 }