Clover coverage report - groovy - 1.0-beta-8
Coverage timestamp: Fri Dec 17 2004 14:55:55 GMT
file stats: LOC: 257   Methods: 10
NCLOC: 170   Classes: 2
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
GroovyScriptEngine.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  * $Id: GroovyScriptEngine.java,v 1.4 2004/04/19 07:29:43 cpoirier Exp $version Jan 9, 2004 12:19:58 PM $user Exp $
 3   
  * 
 4   
  * Copyright 2003 (C) Sam Pullara. 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 groovy.util;
 35   
 
 36   
 import groovy.lang.Binding;
 37   
 import groovy.lang.GroovyClassLoader;
 38   
 import groovy.lang.Script;
 39   
 
 40   
 import java.io.BufferedReader;
 41   
 import java.io.File;
 42   
 import java.io.IOException;
 43   
 import java.io.InputStreamReader;
 44   
 import java.net.MalformedURLException;
 45   
 import java.net.URL;
 46   
 import java.net.URLConnection;
 47   
 import java.security.AccessController;
 48   
 import java.security.PrivilegedAction;
 49   
 import java.util.Collections;
 50   
 import java.util.HashMap;
 51   
 import java.util.Iterator;
 52   
 import java.util.Map;
 53   
 
 54   
 import org.codehaus.groovy.control.CompilationFailedException;
 55   
 import org.codehaus.groovy.runtime.InvokerHelper;
 56   
 
 57   
 /**
 58   
  * @author sam
 59   
  * 
 60   
  * To change the template for this generated type comment go to Window -
 61   
  * Preferences - Java - Code Generation - Code and Comments
 62   
  */
 63   
 public class GroovyScriptEngine implements ResourceConnector {
 64   
 
 65   
     /**
 66   
      * Simple testing harness for the GSE. Enter script roots as arguments and
 67   
      * then input script names to run them.
 68   
      * 
 69   
      * @param args
 70   
      * @throws Exception
 71   
      */
 72  0
     public static void main(String[] args) throws Exception {
 73  0
         URL[] roots = new URL[args.length];
 74  0
         for (int i = 0; i < roots.length; i++) {
 75  0
             roots[i] = new File(args[i]).toURL();
 76   
         }
 77  0
         GroovyScriptEngine gse = new GroovyScriptEngine(roots);
 78  0
         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 79  0
         String line;
 80  0
         while (true) {
 81  0
             System.out.print("groovy> ");
 82  0
             if ((line = br.readLine()) == null || line.equals("quit"))
 83  0
                 break;
 84  0
             try {
 85  0
                 System.out.println(gse.run(line, new Binding()));
 86   
             } catch (Exception e) {
 87  0
                 e.printStackTrace();
 88   
             }
 89   
         }
 90   
     }
 91   
 
 92   
     private URL[] roots;
 93   
     private Map scriptCache = Collections.synchronizedMap(new HashMap());
 94   
     private ResourceConnector rc;
 95   
 
 96   
     private static class ScriptCacheEntry {
 97   
         private Class scriptClass;
 98   
         private long lastModified;
 99   
         private Map dependencies = new HashMap();
 100   
     }
 101   
 
 102  0
     public URLConnection getResourceConnection(String resourceName) throws ResourceException {
 103   
         // Get the URLConnection
 104  0
         URLConnection groovyScriptConn = null;
 105   
 
 106  0
         ResourceException se = null;
 107  0
         for (int i = 0; i < roots.length; i++) {
 108  0
             URL scriptURL = null;
 109  0
             try {
 110  0
                 scriptURL = new URL(roots[i], resourceName);
 111  0
                 groovyScriptConn = scriptURL.openConnection();
 112   
             } catch (MalformedURLException e) {
 113  0
                 String message = "Malformed URL: " + roots[i] + ", " + resourceName;
 114  0
                 if (se == null) {
 115  0
                     se = new ResourceException(message);
 116   
                 } else {
 117  0
                     se = new ResourceException(message, se);
 118   
                 }
 119   
             } catch (IOException e1) {
 120  0
                 String message = "Cannot open URL: " + scriptURL;
 121  0
                 if (se == null) {
 122  0
                     se = new ResourceException(message);
 123   
                 } else {
 124  0
                     se = new ResourceException(message, se);
 125   
                 }
 126   
             }
 127   
 
 128   
         }
 129   
 
 130   
         // If we didn't find anything, report on all the exceptions that
 131   
         // occurred.
 132  0
         if (groovyScriptConn == null) {
 133  0
             throw se;
 134   
         }
 135   
 
 136  0
         return groovyScriptConn;
 137   
     }
 138   
 
 139   
     /**
 140   
      * The groovy script engine will run groovy scripts and reload them and
 141   
      * their dependencies when they are modified. This is useful for embedding
 142   
      * groovy in other containers like games and application servers. 
 143   
      */
 144  0
     public GroovyScriptEngine(URL[] roots) {
 145  0
         this.roots = roots;
 146  0
         this.rc = this;
 147   
     }
 148   
 
 149  0
     public GroovyScriptEngine(String[] args) throws IOException {
 150  0
         URL[] roots = new URL[args.length];
 151  0
         for (int i = 0; i < roots.length; i++) {
 152  0
             roots[i] = new File(args[i]).toURL();
 153   
         }
 154  0
         this.rc = this;
 155   
     }
 156   
 
 157  0
     public GroovyScriptEngine(String arg) throws IOException {
 158  0
         this.roots = new URL[1];
 159  0
         roots[0] = new File(arg).toURL();
 160  0
         this.rc = this;
 161   
     }
 162   
 
 163  0
     public GroovyScriptEngine(ResourceConnector rc) {
 164  0
         this.rc = rc;
 165   
     }
 166   
 
 167  0
     public String run(String script, String argument) throws ResourceException, ScriptException {
 168  0
         Binding binding = new Binding();
 169  0
         binding.setVariable("arg", argument);
 170  0
         Object result = run(script, binding);
 171  0
         return result == null ? "" : result.toString();
 172   
     }
 173   
 
 174  0
     public Object run(String script, Binding binding) throws ResourceException, ScriptException {
 175   
 
 176  0
         ScriptCacheEntry entry;
 177   
 
 178  0
         script = script.intern();
 179  0
         synchronized (script) {
 180   
 
 181  0
             URLConnection groovyScriptConn = rc.getResourceConnection(script);
 182   
 
 183   
             // URL last modified
 184  0
             long lastModified = groovyScriptConn.getLastModified();
 185   
             // Check the cache for the script
 186  0
             entry = (ScriptCacheEntry) scriptCache.get(script);
 187   
             // If the entry isn't null check all the dependencies
 188  0
             boolean dependencyOutOfDate = false;
 189  0
             if (entry != null) {
 190  0
                 for (Iterator i = entry.dependencies.keySet().iterator(); i.hasNext();) {
 191  0
                     URLConnection urlc = null;
 192  0
                     URL url = (URL) i.next();
 193  0
                     try {
 194  0
                         urlc = url.openConnection();
 195  0
                         urlc.setDoInput(false);
 196  0
                         urlc.setDoOutput(false);
 197  0
                         long dependentLastModified = urlc.getLastModified();
 198  0
                         if (dependentLastModified > ((Long) entry.dependencies.get(url)).longValue()) {
 199  0
                             dependencyOutOfDate = true;
 200  0
                             break;
 201   
                         }
 202   
                     } catch (IOException ioe) {
 203  0
                         dependencyOutOfDate = true;
 204  0
                         break;
 205   
                     }
 206   
                 }
 207   
             }
 208   
 
 209  0
             if (entry == null || entry.lastModified < lastModified || dependencyOutOfDate) {
 210   
                 // Make a new entry
 211  0
                 entry = new ScriptCacheEntry();
 212   
 
 213   
                 // Closure variable
 214  0
                 final ScriptCacheEntry finalEntry = entry;
 215   
 
 216   
                 // Compile the script into an object
 217  0
                 GroovyClassLoader groovyLoader = 
 218   
                     (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
 219  0
                         public Object run() {
 220  0
                             return new GroovyClassLoader(getClass().getClassLoader()) {
 221  0
                                 protected Class findClass(String className) throws ClassNotFoundException {
 222  0
                                     String filename = className.replace('.', File.separatorChar) + ".groovy";
 223  0
                                     URLConnection dependentScriptConn = null;
 224  0
                                     try {
 225  0
                                         dependentScriptConn = rc.getResourceConnection(filename);
 226  0
                                         finalEntry.dependencies.put(
 227   
                                             dependentScriptConn.getURL(),
 228   
                                             new Long(dependentScriptConn.getLastModified()));
 229   
                                     } catch (ResourceException e1) {
 230  0
                                         throw new ClassNotFoundException("Could not read " + className + ": " + e1);
 231   
                                     }
 232  0
                                     try {
 233  0
                                         return parseClass(dependentScriptConn.getInputStream(), filename);
 234   
                                     } catch (CompilationFailedException e2) {
 235  0
                                         throw new ClassNotFoundException("Syntax error in " + className + ": " + e2);
 236   
                                     } catch (IOException e2) {
 237  0
                                         throw new ClassNotFoundException("Problem reading " + className + ": " + e2);
 238   
                                     }
 239   
                                 }
 240   
                             };
 241   
                         }
 242   
                     });
 243   
 
 244  0
                 try {
 245  0
                     entry.scriptClass = groovyLoader.parseClass(groovyScriptConn.getInputStream(), script);
 246   
                 } catch (Exception e) {
 247  0
                     throw new ScriptException("Could not parse script: " + script, e);
 248   
                 }
 249  0
                 entry.lastModified = lastModified;
 250  0
                 scriptCache.put(script, entry);
 251   
             }
 252   
         }
 253  0
         Script scriptObject = InvokerHelper.createScript(entry.scriptClass, binding);
 254  0
         return scriptObject.run();
 255   
     }
 256   
 }
 257