1 46 package groovy.lang; 47 48 import groovy.ui.GroovyMain; 49 50 import org.codehaus.groovy.ast.ClassNode; 51 import org.codehaus.groovy.control.CompilationFailedException; 52 import org.codehaus.groovy.control.CompilerConfiguration; 53 import org.codehaus.groovy.runtime.InvokerHelper; 54 55 import java.io.ByteArrayInputStream ; 56 import java.io.File ; 57 import java.io.IOException ; 58 import java.io.InputStream ; 59 import java.lang.reflect.Constructor ; 60 import java.security.AccessController ; 61 import java.security.PrivilegedAction ; 62 import java.security.PrivilegedActionException ; 63 import java.security.PrivilegedExceptionAction ; 64 import java.util.HashMap ; 65 import java.util.List ; 66 import java.util.Map ; 67 68 75 public class GroovyShell extends GroovyObjectSupport { 76 77 private class ShellLoader extends GroovyClassLoader { 78 public ShellLoader() { 79 super(loader, config); 80 } 81 public Class defineClass(ClassNode classNode, String file, String newCodeBase) { 82 Class c = super.defineClass(classNode,file,newCodeBase); 83 classMap.put(c.getName(),this); 84 return c; 85 } 86 } 87 88 private static ClassLoader getLoader(ClassLoader cl) { 89 if (cl!=null) return cl; 90 cl = Thread.currentThread().getContextClassLoader(); 91 if (cl!=null) return cl; 92 cl = GroovyShell.class.getClassLoader(); 93 if (cl!=null) return cl; 94 return null; 95 } 96 97 private class MainClassLoader extends ClassLoader { 98 public MainClassLoader(ClassLoader parent) { 99 super(getLoader(parent)); 100 } 101 protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { 102 Object cached = classMap.get(name); 103 if (cached!=null) return (Class ) cached; 104 ClassLoader parent = getParent(); 105 if (parent!=null) return parent.loadClass(name); 106 return super.loadClass(name,resolve); 107 } 108 } 109 110 111 public static final String [] EMPTY_ARGS = {}; 112 113 114 private HashMap classMap = new HashMap (); 115 private MainClassLoader loader; 116 private Binding context; 117 private int counter; 118 private CompilerConfiguration config; 119 120 public static void main(String [] args) { 121 GroovyMain.main(args); 122 } 123 124 public GroovyShell() { 125 this(null, new Binding()); 126 } 127 128 public GroovyShell(Binding binding) { 129 this(null, binding); 130 } 131 132 public GroovyShell(CompilerConfiguration config) { 133 this(new Binding(), config); 134 } 135 136 public GroovyShell(Binding binding, CompilerConfiguration config) { 137 this(null, binding, config); 138 } 139 140 public GroovyShell(ClassLoader parent, Binding binding) { 141 this(parent, binding, null); 142 } 143 144 public GroovyShell(ClassLoader parent) { 145 this(parent, new Binding(), null); 146 } 147 148 public GroovyShell(final ClassLoader parent, Binding binding, final CompilerConfiguration config) { 149 this.config = config; 150 this.loader = new MainClassLoader(parent); 151 this.context = binding; 152 } 153 154 public void initialiseBinding() { 155 Map map = context.getVariables(); 156 if (map.get("shell")==null) map.put("shell",this); 157 } 158 159 public void resetLoadedClasses() { 160 classMap.clear(); 161 } 162 163 169 public GroovyShell(GroovyShell shell) { 170 this(shell.loader, shell.context); 171 } 172 173 public Binding getContext() { 174 return context; 175 } 176 177 public Object getProperty(String property) { 178 Object answer = getVariable(property); 179 if (answer == null) { 180 answer = super.getProperty(property); 181 } 182 return answer; 183 } 184 185 public void setProperty(String property, Object newValue) { 186 setVariable(property, newValue); 187 try { 188 super.setProperty(property, newValue); 189 } catch (GroovyRuntimeException e) { 190 } 192 } 193 194 200 public void run(File scriptFile, List list) throws CompilationFailedException, IOException { 201 String [] args = new String [list.size()]; 202 run(scriptFile, (String []) list.toArray(args)); 203 } 204 205 212 public void run(String scriptText, String fileName, List list) throws CompilationFailedException { 213 String [] args = new String [list.size()]; 214 list.toArray(args); 215 run(scriptText, fileName, args); 216 } 217 218 224 public void run(final File scriptFile, String [] args) throws CompilationFailedException, IOException { 225 String scriptName = scriptFile.getName(); 226 int p = scriptName.lastIndexOf("."); 227 if (p++ >= 0) { 228 if (scriptName.substring(p).equals("java")) { 229 System.err.println("error: cannot compile file with .java extension: " + scriptName); 230 throw new CompilationFailedException(0, null); 231 } 232 } 233 234 final Thread thread = Thread.currentThread(); 236 238 class DoSetContext implements PrivilegedAction { 239 ClassLoader classLoader; 240 241 public DoSetContext(ClassLoader loader) { 242 classLoader = loader; 243 } 244 245 public Object run() { 246 thread.setContextClassLoader(classLoader); 247 return null; 248 } 249 } 250 251 AccessController.doPrivileged(new DoSetContext(loader)); 252 253 Class scriptClass; 256 final ShellLoader loader = new ShellLoader(); 257 try { 258 scriptClass = (Class ) AccessController.doPrivileged(new PrivilegedExceptionAction () { 259 public Object run() throws CompilationFailedException, IOException { 260 return loader.parseClass(scriptFile); 261 } 262 }); 263 } catch (PrivilegedActionException pae) { 264 Exception e = pae.getException(); 265 if (e instanceof CompilationFailedException) { 266 throw (CompilationFailedException) e; 267 } else if (e instanceof IOException ) { 268 throw (IOException ) e; 269 } else { 270 throw (RuntimeException ) pae.getException(); 271 } 272 } 273 274 runMainOrTestOrRunnable(scriptClass, args); 275 276 } 279 280 292 private void runMainOrTestOrRunnable(Class scriptClass, String [] args) { 293 if (scriptClass == null) { 294 return; 295 } 296 try { 297 scriptClass.getMethod("main", new Class []{String [].class}); 299 } catch (NoSuchMethodException e) { 300 if (isUnitTestCase(scriptClass)) { 303 runTest(scriptClass); 304 } 305 else if (Runnable .class.isAssignableFrom(scriptClass)) { 308 Constructor constructor = null; 309 Runnable runnable = null; 310 Throwable reason = null; 311 try { 312 constructor = scriptClass.getConstructor(new Class []{(new String []{}).getClass()}); 314 try { 315 runnable = (Runnable ) constructor.newInstance(new Object []{args}); 317 } catch (Throwable t) { 318 reason = t; 319 } 320 } catch (NoSuchMethodException e1) { 321 try { 322 constructor = scriptClass.getConstructor(new Class []{}); 324 try { 325 runnable = (Runnable ) constructor.newInstance(new Object []{}); 327 } catch (Throwable t) { 328 reason = t; 329 } 330 } catch (NoSuchMethodException nsme) { 331 reason = nsme; 332 } 333 } 334 if (constructor != null && runnable != null) { 335 runnable.run(); 336 } else { 337 throw new GroovyRuntimeException("This script or class could not be run. ", reason); 338 } 339 } else { 340 throw new GroovyRuntimeException("This script or class could not be run. \n" + 341 "It should either: \n" + 342 "- have a main method, \n" + 343 "- be a class extending GroovyTestCase, \n" + 344 "- or implement the Runnable interface."); 345 } 346 return; 347 } 348 InvokerHelper.invokeMethod(scriptClass, "main", new Object []{args}); 350 } 351 352 360 private void runTest(Class scriptClass) { 361 try { 362 InvokerHelper.invokeStaticMethod("junit.textui.TestRunner", "run", new Object []{scriptClass}); 363 } catch (Exception e) { 364 throw new GroovyRuntimeException("Failed to run the unit test. JUnit is not on the Classpath."); 365 } 366 } 367 368 374 private boolean isUnitTestCase(Class scriptClass) { 375 final ShellLoader loader = new ShellLoader(); 378 boolean isUnitTestCase = false; 379 try { 380 try { 381 Class testCaseClass = this.loader.loadClass("groovy.util.GroovyTestCase"); 382 if (testCaseClass.isAssignableFrom(scriptClass)) { 384 isUnitTestCase = true; 385 } 386 } catch (ClassNotFoundException e) { 387 } 389 } catch (Throwable e) { 390 } 392 return isUnitTestCase; 393 } 394 395 402 public void run(String scriptText, String fileName, String [] args) throws CompilationFailedException { 403 run(new ByteArrayInputStream (scriptText.getBytes()), fileName, args); 404 } 405 406 413 public Object run(final InputStream in, final String fileName, String [] args) throws CompilationFailedException { 414 GroovyCodeSource gcs = (GroovyCodeSource) AccessController.doPrivileged(new PrivilegedAction () { 415 public Object run() { 416 return new GroovyCodeSource(in, fileName, "/groovy/shell"); 417 } 418 }); 419 Class scriptClass = parseClass(gcs); 420 runMainOrTestOrRunnable(scriptClass, args); 421 return null; 422 } 423 424 public Object getVariable(String name) { 425 return context.getVariables().get(name); 426 } 427 428 public void setVariable(String name, Object value) { 429 context.setVariable(name, value); 430 } 431 432 440 public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException { 441 Script script = parse(codeSource); 442 return script.run(); 443 } 444 445 451 public Object evaluate(String scriptText, String fileName) throws CompilationFailedException { 452 return evaluate(new ByteArrayInputStream (scriptText.getBytes()), fileName); 453 } 454 455 459 public Object evaluate(String scriptText, String fileName, String codeBase) throws CompilationFailedException { 460 return evaluate(new GroovyCodeSource(new ByteArrayInputStream (scriptText.getBytes()), fileName, codeBase)); 461 } 462 463 468 public Object evaluate(File file) throws CompilationFailedException, IOException { 469 return evaluate(new GroovyCodeSource(file)); 470 } 471 472 477 public Object evaluate(String scriptText) throws CompilationFailedException { 478 return evaluate(new ByteArrayInputStream (scriptText.getBytes()), generateScriptName()); 479 } 480 481 486 public Object evaluate(InputStream in) throws CompilationFailedException { 487 return evaluate(in, generateScriptName()); 488 } 489 490 496 public Object evaluate(InputStream in, String fileName) throws CompilationFailedException { 497 Script script = null; 498 try { 499 script = parse(in, fileName); 500 return script.run(); 501 } finally { 502 if (script != null) { 503 InvokerHelper.removeClass(script.getClass()); 504 } 505 } 506 } 507 508 515 public Script parse(final InputStream in, final String fileName) throws CompilationFailedException { 516 GroovyCodeSource gcs = (GroovyCodeSource) AccessController.doPrivileged(new PrivilegedAction () { 517 public Object run() { 518 return new GroovyCodeSource(in, fileName, "/groovy/shell"); 519 } 520 }); 521 return parse(gcs); 522 } 523 524 527 private Class parseClass(final GroovyCodeSource codeSource) throws CompilationFailedException { 528 ShellLoader loader = new ShellLoader(); 530 return loader.parseClass(codeSource, false); 531 } 532 533 541 public Script parse(final GroovyCodeSource codeSource) throws CompilationFailedException { 542 return InvokerHelper.createScript(parseClass(codeSource), context); 543 } 544 545 550 public Script parse(File file) throws CompilationFailedException, IOException { 551 return parse(new GroovyCodeSource(file)); 552 } 553 554 559 public Script parse(String scriptText) throws CompilationFailedException { 560 return parse(new ByteArrayInputStream (scriptText.getBytes()), generateScriptName()); 561 } 562 563 public Script parse(String scriptText, String fileName) throws CompilationFailedException { 564 return parse(new ByteArrayInputStream (scriptText.getBytes()), fileName); 565 } 566 567 572 public Script parse(InputStream in) throws CompilationFailedException { 573 return parse(in, generateScriptName()); 574 } 575 576 protected synchronized String generateScriptName() { 577 return "Script" + (++counter) + ".groovy"; 578 } 579 } 580 | Popular Tags |