1 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 63 public class GroovyScriptEngine implements ResourceConnector { 64 65 72 public static void main(String [] args) throws Exception { 73 URL [] roots = new URL [args.length]; 74 for (int i = 0; i < roots.length; i++) { 75 roots[i] = new File (args[i]).toURL(); 76 } 77 GroovyScriptEngine gse = new GroovyScriptEngine(roots); 78 BufferedReader br = new BufferedReader (new InputStreamReader (System.in)); 79 String line; 80 while (true) { 81 System.out.print("groovy> "); 82 if ((line = br.readLine()) == null || line.equals("quit")) 83 break; 84 try { 85 System.out.println(gse.run(line, new Binding())); 86 } catch (Exception e) { 87 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 public URLConnection getResourceConnection(String resourceName) throws ResourceException { 103 URLConnection groovyScriptConn = null; 105 106 ResourceException se = null; 107 for (int i = 0; i < roots.length; i++) { 108 URL scriptURL = null; 109 try { 110 scriptURL = new URL (roots[i], resourceName); 111 groovyScriptConn = scriptURL.openConnection(); 112 } catch (MalformedURLException e) { 113 String message = "Malformed URL: " + roots[i] + ", " + resourceName; 114 if (se == null) { 115 se = new ResourceException(message); 116 } else { 117 se = new ResourceException(message, se); 118 } 119 } catch (IOException e1) { 120 String message = "Cannot open URL: " + scriptURL; 121 if (se == null) { 122 se = new ResourceException(message); 123 } else { 124 se = new ResourceException(message, se); 125 } 126 } 127 128 } 129 130 if (groovyScriptConn == null) { 133 throw se; 134 } 135 136 return groovyScriptConn; 137 } 138 139 147 public GroovyScriptEngine(URL [] roots) { 148 this.roots = roots; 149 this.rc = this; 150 } 151 152 public GroovyScriptEngine(String [] args) throws IOException { 153 roots = new URL [args.length]; 154 for (int i = 0; i < roots.length; i++) { 155 roots[i] = new File (args[i]).toURL(); 156 } 157 this.rc = this; 158 } 159 160 public GroovyScriptEngine(String arg) throws IOException { 161 roots = new URL [1]; 162 roots[0] = new File (arg).toURL(); 163 this.rc = this; 164 } 165 166 public GroovyScriptEngine(ResourceConnector rc) { 167 this.rc = rc; 168 } 169 170 public String run(String script, String argument) throws ResourceException, ScriptException { 171 Binding binding = new Binding(); 172 binding.setVariable("arg", argument); 173 Object result = run(script, binding); 174 return result == null ? "" : result.toString(); 175 } 176 177 public Object run(String script, Binding binding) throws ResourceException, ScriptException { 178 179 ScriptCacheEntry entry; 180 181 script = script.intern(); 182 synchronized (script) { 183 184 URLConnection groovyScriptConn = rc.getResourceConnection(script); 185 186 long lastModified = groovyScriptConn.getLastModified(); 188 entry = (ScriptCacheEntry) scriptCache.get(script); 190 boolean dependencyOutOfDate = false; 192 if (entry != null) { 193 for (Iterator i = entry.dependencies.keySet().iterator(); i.hasNext();) { 194 URLConnection urlc = null; 195 URL url = (URL ) i.next(); 196 try { 197 urlc = url.openConnection(); 198 urlc.setDoInput(false); 199 urlc.setDoOutput(false); 200 long dependentLastModified = urlc.getLastModified(); 201 if (dependentLastModified > ((Long ) entry.dependencies.get(url)).longValue()) { 202 dependencyOutOfDate = true; 203 break; 204 } 205 } catch (IOException ioe) { 206 dependencyOutOfDate = true; 207 break; 208 } 209 } 210 } 211 212 if (entry == null || entry.lastModified < lastModified || dependencyOutOfDate) { 213 entry = new ScriptCacheEntry(); 215 216 final ScriptCacheEntry finalEntry = entry; 218 219 GroovyClassLoader groovyLoader = 221 (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction () { 222 public Object run() { 223 return new GroovyClassLoader(getClass().getClassLoader()) { 224 protected Class findClass(String className) throws ClassNotFoundException { 225 String filename = className.replace('.', File.separatorChar) + ".groovy"; 226 URLConnection dependentScriptConn = null; 227 try { 228 dependentScriptConn = rc.getResourceConnection(filename); 229 finalEntry.dependencies.put( 230 dependentScriptConn.getURL(), 231 new Long (dependentScriptConn.getLastModified())); 232 } catch (ResourceException e1) { 233 throw new ClassNotFoundException ("Could not read " + className + ": " + e1); 234 } 235 try { 236 return parseClass(dependentScriptConn.getInputStream(), filename); 237 } catch (CompilationFailedException e2) { 238 throw new ClassNotFoundException ("Syntax error in " + className + ": " + e2); 239 } catch (IOException e2) { 240 throw new ClassNotFoundException ("Problem reading " + className + ": " + e2); 241 } 242 } 243 }; 244 } 245 }); 246 247 try { 248 entry.scriptClass = groovyLoader.parseClass(groovyScriptConn.getInputStream(), script); 249 } catch (Exception e) { 250 throw new ScriptException("Could not parse script: " + script, e); 251 } 252 entry.lastModified = lastModified; 253 scriptCache.put(script, entry); 254 } 255 } 256 Script scriptObject = InvokerHelper.createScript(entry.scriptClass, binding); 257 return scriptObject.run(); 258 } 259 } 260 | Popular Tags |