001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model.repl;
038:
039: import java.util.List;
040: import java.io.StringReader;
041: import java.io.Reader;
042: import java.io.File;
043: import java.net.URL;
044: import edu.rice.cs.drjava.model.repl.newjvm.ClassPathManager;
045: import koala.dynamicjava.interpreter.*;
046: import koala.dynamicjava.interpreter.context.*;
047: import koala.dynamicjava.interpreter.error.*;
048: import koala.dynamicjava.interpreter.throwable.*;
049: import koala.dynamicjava.parser.wrapper.*;
050: import koala.dynamicjava.tree.*;
051:
052: import edu.rice.cs.util.classloader.StickyClassLoader;
053: import edu.rice.cs.util.*;
054:
055: // NOTE: Do NOT import/use the config framework in this class!
056: // (This class runs in a different JVM, and will not share the config object)
057:
058: /** An implementation of the interpreter for the repl pane.
059: *
060: * This class is loaded in the Interpreter JVM, not the Main JVM.
061: * (Do not use DrJava's config framework here.)
062: *
063: * @version $Id: DynamicJavaAdapter.java 4260 2007-10-10 20:28:34Z mgricken $
064: */
065: public class DynamicJavaAdapter implements JavaInterpreter {
066: private static Log _log = new Log("MasterSlave.txt", false);
067: private InterpreterExtension _djInterpreter;
068:
069: ClassPathManager cpm;
070:
071: /** Constructor */
072: public DynamicJavaAdapter(ClassPathManager c) {
073: cpm = c;
074: _djInterpreter = new InterpreterExtension(c);
075: }
076:
077: /** Interprets a string as Java source.
078: * @param s the string to interpret
079: * @return the Object generated by the running of s
080: */
081: public Object interpret(String s) throws ExceptionReturnedException {
082: boolean print = false;
083:
084: /* Trims the whitespace from beginning and end of string
085: * Checks the end to see if it is a semicolon
086: * Adds a semicolon if necessary
087: */
088: s = s.trim();
089: if (!s.endsWith(";")) {
090: //s += ";";
091: print = true;
092: }
093:
094: StringReader reader = new StringReader(s);
095: try {
096: Object result = _djInterpreter.interpret(reader, "DrJava");
097: if (print)
098: return result;
099: else
100: return JavaInterpreter.NO_RESULT;
101: } catch (InterpreterException ie) {
102: Throwable cause = ie.getException();
103: if (cause instanceof ThrownException)
104: cause = ((ThrownException) cause).getException();
105: else if (cause instanceof CatchedExceptionError)
106: cause = ((CatchedExceptionError) cause).getException();
107:
108: throw new ExceptionReturnedException(cause);
109: } catch (CatchedExceptionError cee) {
110: throw new ExceptionReturnedException(cee.getException());
111: } catch (InterpreterInterruptedException iie) {
112: return JavaInterpreter.NO_RESULT;
113: }
114: // catch (Throwable ie) {
115: // System.err.print(new Date() + ": ");
116: // System.err.println(ie);
117: // ie.printStackTrace();
118: // System.err.println("\n");
119: // throw new RuntimeException(ie.toString());
120: //
121: //// throw new ExceptionReturnedException(ie);
122: // }
123: }
124:
125: public List<Node> parse(String input) {
126: return _djInterpreter.parse(input);
127: }
128:
129: /** Adds a path to the current classpath.
130: * @param path the path to add
131: */
132: // public void addClassPath(String path) {
133: // //DrJava.consoleErr().println("Added class path: " + path);
134: // _djInterpreter.addClassPath(path);
135: // }
136: public void addProjectClassPath(File path) {
137: cpm.addProjectCP(path);
138: }
139:
140: public void addBuildDirectoryClassPath(File path) {
141: cpm.addBuildDirectoryCP(path);
142: }
143:
144: public void addProjectFilesClassPath(File path) {
145: cpm.addProjectFilesCP(path);
146: }
147:
148: public void addExternalFilesClassPath(File path) {
149: cpm.addExternalFilesCP(path);
150: }
151:
152: public void addExtraClassPath(File path) {
153: cpm.addExtraCP(path);
154: }
155:
156: /** Set the scope for unqualified names to the given package.
157: * @param packageName Package to assume scope of.
158: */
159: public void setPackageScope(String packageName) {
160: StringReader reader = new StringReader("package " + packageName
161: + ";");
162: _djInterpreter.interpret(reader, "DrJava");
163: }
164:
165: /** Returns the value of the variable with the given name in the interpreter.
166: * @param name Name of the variable
167: * @return Value of the variable
168: */
169: public Object getVariable(String name) {
170: return _djInterpreter.getVariable(name);
171: }
172:
173: /** Returns the class of the variable with the given name in the interpreter.
174: * @param name Name of the variable
175: * @return class of the variable
176: */
177: public Class<?> getVariableClass(String name) {
178: return _djInterpreter.getVariableClass(name);
179: }
180:
181: /** Assigns the given value to the given name in the interpreter. If type == null, we assume that the type of
182: * this variable has not been loaded so we set it to Object.
183: * @param name Name of the variable
184: * @param value Value to assign
185: * @param type the type of the variable
186: */
187: public void defineVariable(String name, Object value, Class<?> type) {
188: if (type == null)
189: type = java.lang.Object.class;
190: ((TreeInterpreter) _djInterpreter).defineVariable(name, value,
191: type);
192: }
193:
194: /** Assigns the given value to the given name in the interpreter.
195: * @param name Name of the variable
196: * @param value Value to assign
197: */
198: public void defineVariable(String name, Object value) {
199: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
200: }
201:
202: /** Assigns the given value to the given name in the interpreter.
203: * @param name Name of the variable
204: * @param value boolean to assign
205: */
206: public void defineVariable(String name, boolean value) {
207: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
208: }
209:
210: /** Assigns the given value to the given name in the interpreter.
211: * @param name Name of the variable
212: * @param value byte to assign
213: */
214: public void defineVariable(String name, byte value) {
215: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
216: }
217:
218: /** Assigns the given value to the given name in the interpreter.
219: * @param name Name of the variable
220: * @param value char to assign
221: */
222: public void defineVariable(String name, char value) {
223: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
224: }
225:
226: /** Assigns the given value to the given name in the interpreter.
227: * @param name Name of the variable
228: * @param value double to assign
229: */
230: public void defineVariable(String name, double value) {
231: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
232: }
233:
234: /** Assigns the given value to the given name in the interpreter.
235: * @param name Name of the variable
236: * @param value float to assign
237: */
238: public void defineVariable(String name, float value) {
239: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
240: }
241:
242: /** Assigns the given value to the given name in the interpreter.
243: * @param name Name of the variable
244: * @param value int to assign
245: */
246: public void defineVariable(String name, int value) {
247: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
248: }
249:
250: /** Assigns the given value to the given name in the interpreter.
251: * @param name Name of the variable
252: * @param value long to assign
253: */
254: public void defineVariable(String name, long value) {
255: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
256: }
257:
258: /** Assigns the given value to the given name in the interpreter.
259: * @param name Name of the variable
260: * @param value short to assign
261: */
262: public void defineVariable(String name, short value) {
263: ((TreeInterpreter) _djInterpreter).defineVariable(name, value);
264: }
265:
266: /** Assigns the given value to the given name in the interpreter.
267: * @param name Name of the variable
268: * @param value Value to assign
269: */
270: public void defineConstant(String name, Object value) {
271: _djInterpreter.defineConstant(name, value);
272: }
273:
274: /** Assigns the given value to the given name as a constant in the interpreter.
275: * @param name Name of the variable
276: * @param value boolean to assign
277: */
278: public void defineConstant(String name, boolean value) {
279: _djInterpreter.defineConstant(name, value);
280: }
281:
282: /** Assigns the given value to the given name as a constant in the interpreter.
283: * @param name Name of the variable
284: * @param value byte to assign
285: */
286: public void defineConstant(String name, byte value) {
287: _djInterpreter.defineConstant(name, value);
288: }
289:
290: /** Assigns the given value to the given name as a constant in the interpreter.
291: * @param name Name of the variable
292: * @param value char to assign
293: */
294: public void defineConstant(String name, char value) {
295: _djInterpreter.defineConstant(name, value);
296: }
297:
298: /** Assigns the given value to the given name as a constant in the interpreter.
299: * @param name Name of the variable
300: * @param value double to assign
301: */
302: public void defineConstant(String name, double value) {
303: _djInterpreter.defineConstant(name, value);
304: }
305:
306: /** Assigns the given value to the given name as a constant in the interpreter.
307: * @param name Name of the variable
308: * @param value float to assign
309: */
310: public void defineConstant(String name, float value) {
311: _djInterpreter.defineConstant(name, value);
312: }
313:
314: /** Assigns the given value to the given name as a constant in the interpreter.
315: * @param name Name of the variable
316: * @param value int to assign
317: */
318: public void defineConstant(String name, int value) {
319: _djInterpreter.defineConstant(name, value);
320: }
321:
322: /** Assigns the given value to the given name as a constant in the interpreter.
323: * @param name Name of the variable
324: * @param value long to assign
325: */
326: public void defineConstant(String name, long value) {
327: _djInterpreter.defineConstant(name, value);
328: }
329:
330: /** Assigns the given value to the given name as a constant in the interpreter.
331: * @param name Name of the variable
332: * @param value short to assign
333: */
334: public void defineConstant(String name, short value) {
335: _djInterpreter.defineConstant(name, value);
336: }
337:
338: /** Sets whether protected and private variables should be accessible in the interpreter.
339: * @param accessible Whether protected and private variable are accessible
340: */
341: public void setPrivateAccessible(boolean accessible) {
342: _djInterpreter.setAccessible(accessible);
343: }
344:
345: /** Gets whether protected and private variables should be accessible in the interpreter. */
346: public boolean getPrivateAccessible() {
347: return _djInterpreter.getAccessible();
348: }
349:
350: /** Factory method to make a new NameVisitor.
351: * @param nameContext the context
352: * @return visitor the visitor
353: */
354: public NameVisitor makeNameVisitor(Context nameContext) {
355: return new NameVisitor(nameContext);
356: }
357:
358: /** Factory method to make a new TypeChecker.
359: * @param nameContext Context for the NameVisitor
360: * @param typeContext Context being used for the TypeChecker. This is necessary because we want to perform partial
361: * type checking for the right hand side of a VariableDeclaration.
362: * @return visitor the visitor
363: */
364: // public AbstractTypeChecker makeTypeChecker(Context context) {
365: // // TO DO: move this into its own class if more methods need to be added
366: // return AbstractTypeChecker.makeTypeChecker(context);
367: // }
368: // Removed because AbstractTypeChecker contains a makeTypeChecker method
369: /** Factory method to make a new EvaluationVisitor.
370: * @param context the context
371: * @return visitor the visitor
372: */
373: public EvaluationVisitor makeEvaluationVisitor(Context context) {
374: return new EvaluationVisitorExtension(context);
375: }
376:
377: /** Processes the tree before evaluating it, if necessary.
378: * @param node Tree to process
379: */
380: public Node processTree(Node node) {
381: return node;
382: }
383:
384: public GlobalContext makeGlobalContext(TreeInterpreter i) {
385: return new GlobalContext(i);
386: }
387:
388: /** An extension of DynamicJava's interpreter that makes sure classes are not loaded by the system class loader
389: * (when possible) so that future interpreters will be able to reload the classes. This extension also ensures
390: * that classes on "extra.classpath" will be loaded if referenced by user defined classes. (Without this, classes
391: * on "extra.classpath" can only be referred to directly, and cannot be extended, etc.) <p>
392: * We also override the evaluation visitor to allow the interpreter to be interrupted and to return NO_RESULT if
393: * there was no result.
394: */
395: public class InterpreterExtension extends TreeInterpreter {
396:
397: /** Only constructor. */
398: public InterpreterExtension(ClassPathManager cpm) {
399: super (new JavaCCParserFactory());
400:
401: classLoader = new ClassLoaderExtension(this , cpm);
402: // We have to reinitialize these variables because they automatically
403: // fetch pointers to classLoader in their constructors.
404: nameVisitorContext = makeGlobalContext(this );
405: ClassLoaderContainer clc = new ClassLoaderContainer() {
406: public ClassLoader getClassLoader() {
407: return classLoader;
408: }
409: };
410: nameVisitorContext.setAdditionalClassLoaderContainer(clc);
411: checkVisitorContext = makeGlobalContext(this );
412: checkVisitorContext.setAdditionalClassLoaderContainer(clc);
413: evalVisitorContext = makeGlobalContext(this );
414: evalVisitorContext.setAdditionalClassLoaderContainer(clc);
415: //System.err.println("set loader: " + classLoader);
416:
417: }
418:
419: /** Extends the interpret method to deal with possible interrupted exceptions.
420: * Unfortunately we have to copy all of this method to override it.
421: * @param r the reader from which the statements are read
422: * @param fname the name of the parsed stream
423: * @return the result of the evaluation of the last statement
424: */
425: public Object interpret(Reader r, String fname)
426: throws InterpreterException {
427: List<Node> statements;
428: try {
429: SourceCodeParser p = parserFactory.createParser(r,
430: fname);
431: statements = p.parseStream();
432: // Utilities.showDebug("Interpreting: " + statements);
433: } catch (ParseError e) {
434: //throw new InteractionsException("There was a syntax error in the " +
435: // "previous input.");
436: throw new InterpreterException(e);
437: }
438:
439: Object result = JavaInterpreter.NO_RESULT;
440:
441: nameVisitorContext.setRevertPoint();
442: checkVisitorContext.setRevertPoint();
443: evalVisitorContext.setRevertPoint();
444:
445: try {
446: for (Node n : statements) {
447: n = processTree(n);
448:
449: NameVisitor nv = makeNameVisitor(nameVisitorContext);
450: Node o = n.acceptVisitor(nv);
451: if (o != null)
452: n = o;
453:
454: AbstractTypeChecker tc = AbstractTypeChecker
455: .makeTypeChecker(checkVisitorContext);
456:
457: n.acceptVisitor(tc);
458:
459: evalVisitorContext
460: .defineVariables(checkVisitorContext
461: .getCurrentScopeVariables());
462:
463: EvaluationVisitor ev = makeEvaluationVisitor(evalVisitorContext);
464: _log.log("Ready to interpret " + ev);
465: result = n.acceptVisitor(ev);
466: _log.log("Interpreted result is: " + result);
467: }
468: } catch (ExecutionError e) {
469: // revert the contexts just in case a binding was made in
470: // one context before this error was thrown.
471: nameVisitorContext.revert();
472: checkVisitorContext.revert();
473: evalVisitorContext.revert();
474:
475: //e.printStackTrace(); // For Loop....
476: throw new InterpreterException(e);
477: }
478:
479: if (result instanceof String)
480: return "\"" + result + "\"";
481: if (result instanceof Character)
482: return "'" + result + "'";
483: return result;
484: }
485:
486: /**
487: * Assigns the given value to the given name in the interpreter.
488: * @param name Name of the variable
489: * @param value Value to assign
490: */
491: public void defineConstant(String name, Object value) {
492: Class<?> c = (value == null) ? null : value.getClass();
493: nameVisitorContext.defineConstant(name, c);
494: checkVisitorContext.defineConstant(name, c);
495: evalVisitorContext.defineConstant(name, value);
496: }
497:
498: /** Assigns the given value to the given name as a constant in the interpreter.
499: * @param name Name of the variable
500: * @param value boolean to assign
501: */
502: public void defineConstant(String name, boolean value) {
503: Class<?> c = boolean.class;
504: nameVisitorContext.defineConstant(name, c);
505: checkVisitorContext.defineConstant(name, c);
506: evalVisitorContext.defineConstant(name, Boolean
507: .valueOf(value));
508: }
509:
510: /** Assigns the given value to the given name as a constant in the interpreter.
511: * @param name Name of the variable
512: * @param value byte to assign
513: */
514: public void defineConstant(String name, byte value) {
515: Class<?> c = byte.class;
516: nameVisitorContext.defineConstant(name, c);
517: checkVisitorContext.defineConstant(name, c);
518: evalVisitorContext.defineConstant(name, new Byte(value));
519: }
520:
521: /** Assigns the given value to the given name as a constant in the interpreter.
522: * @param name Name of the variable
523: * @param value char to assign
524: */
525: public void defineConstant(String name, char value) {
526: Class<?> c = char.class;
527: nameVisitorContext.defineConstant(name, c);
528: checkVisitorContext.defineConstant(name, c);
529: evalVisitorContext.defineConstant(name,
530: new Character(value));
531: }
532:
533: /** Assigns the given value to the given name as a constant in the interpreter.
534: * @param name Name of the variable
535: * @param value double to assign
536: */
537: public void defineConstant(String name, double value) {
538: Class<?> c = double.class;
539: nameVisitorContext.defineConstant(name, c);
540: checkVisitorContext.defineConstant(name, c);
541: evalVisitorContext.defineConstant(name, new Double(value));
542: }
543:
544: /** Assigns the given value to the given name as a constant in the interpreter.
545: * @param name Name of the variable
546: * @param value float to assign
547: */
548: public void defineConstant(String name, float value) {
549: Class<?> c = float.class;
550: nameVisitorContext.defineConstant(name, c);
551: checkVisitorContext.defineConstant(name, c);
552: evalVisitorContext.defineConstant(name, new Float(value));
553: }
554:
555: /** Assigns the given value to the given name as a constant in the interpreter.
556: * @param name Name of the variable
557: * @param value int to assign
558: */
559: public void defineConstant(String name, int value) {
560: Class<?> c = int.class;
561: nameVisitorContext.defineConstant(name, c);
562: checkVisitorContext.defineConstant(name, c);
563: evalVisitorContext.defineConstant(name, new Integer(value));
564: }
565:
566: /** Assigns the given value to the given name as a constant in the interpreter.
567: * @param name Name of the variable
568: * @param value long to assign
569: */
570: public void defineConstant(String name, long value) {
571: Class<?> c = long.class;
572: nameVisitorContext.defineConstant(name, c);
573: checkVisitorContext.defineConstant(name, c);
574: evalVisitorContext.defineConstant(name, new Long(value));
575: }
576:
577: /** Assigns the given value to the given name as a constant in the interpreter.
578: * @param name Name of the variable
579: * @param value short to assign
580: */
581: public void defineConstant(String name, short value) {
582: Class<?> c = short.class;
583: nameVisitorContext.defineConstant(name, c);
584: checkVisitorContext.defineConstant(name, c);
585: evalVisitorContext.defineConstant(name, new Short(value));
586: }
587: }
588:
589: /** A class loader for the interpreter. */
590: public static class ClassLoaderExtension extends TreeClassLoader {
591:
592: // the classpath is augmented by calling addURL(URL url) on this class
593: // this will update the classloader variable to contain the new classpath entry
594:
595: private static boolean classLoaderCreated = false;
596:
597: private static StickyClassLoader _stickyLoader;
598:
599: // manages the classpath for the interpreter
600: ClassPathManager cpm;
601:
602: /** Constructor.
603: * @param i the object used to interpret the classes
604: */
605: public ClassLoaderExtension(
606: koala.dynamicjava.interpreter.Interpreter i,
607: ClassPathManager c) {
608: super (i);
609: cpm = c;
610: // The protected variable classLoader contains the class loader to use
611: // to find classes. When a new class path is added to the loader,
612: // it adds on an auxilary classloader and chains the old classLoader
613: // onto the end.
614: // Here we initialize classLoader to be the system class loader, and wrap it to not load edu.rice.cs classes
615: classLoader = new WrapperClassLoader(getClass()
616: .getClassLoader()); // classLoader is only used in getResource()
617: // NOTE that the superclass of ClassLoaderExtension (TreeClassLoader) adds (appends)
618: // URLs to the classpath of this classloader
619:
620: // don't load the dynamic java stuff using the sticky loader!
621: // without this, interpreter-defined classes don't work.
622: String[] excludes = {
623: "edu.rice.cs.drjava.model.repl.DynamicJavaAdapter$InterpreterExtension",
624: "edu.rice.cs.drjava.model.repl.DynamicJavaAdapter$ClassLoaderExtension" };
625:
626: if (!classLoaderCreated) {
627: _stickyLoader = new StickyClassLoader(this , // Sticky's newLoader, indirectly points to the (dynamic) classLoader
628: classLoader, // Sticky's oldLoader
629: excludes);
630: classLoaderCreated = true;
631: }
632:
633: // we will use this to getResource classes
634: }
635:
636: /** Delegates all resource requests to {@link #classLoader} (the system class loader by default).
637: * This method is called by the {@link StickyClassLoader}.
638: */
639: public URL getResource(String name) {
640: // use the cpm to get the resource for the specified name
641: return cpm.getClassLoader().getResource(name);
642: //return classLoader.getResource(name);
643: }
644:
645: protected Class<?> loadClass(String name, boolean resolve)
646: throws ClassNotFoundException {
647: Class<?> clazz;
648:
649: // check the cache
650: if (classes.containsKey(name))
651: clazz = (Class<?>) classes.get(name);
652: else {
653: try {
654: clazz = _stickyLoader.loadClass(name);
655: } catch (ClassNotFoundException e) {
656: // If it exceptions, just fall through to here to try the interpreter.
657: // If all else fails, try loading the class through the interpreter.
658: // That's used for classes defined in the interpreter.
659: clazz = interpreter.loadClass(name);
660: }
661: }
662:
663: if (resolve)
664: resolveClass(clazz);
665:
666: return clazz;
667: }
668:
669: // /** Adds a URL to the class path. DynamicJava's version of this creates a
670: // * new URLClassLoader with the given URL, using the old loader as a parent.
671: // * This seems to cause problems for us in certain cases, such as accessing
672: // * static fields or methods in a class that extends a superclass which is
673: // * loaded by "child" classloader...
674: // *
675: // * Instead, we'll replace the old URLClassLoader with a new one containing
676: // * all the known URLs.
677: // *
678: // * (I don't know if this really works yet, so I'm not including it in
679: // * the current release. CSR, 3-13-2003)
680: // */
681: // public void addURL(URL url) {
682: // if (classLoader == null) {
683: // classLoader = new URLClassLoader(new URL[] { url });
684: // }
685: // else if (classLoader instanceof URLClassLoader) {
686: // URL[] oldURLs = ((URLClassLoader)classLoader).getURLs();
687: // URL[] newURLs = new URL[oldURLs.length + 1];
688: // System.arraycopy(oldURLs, 0, newURLs, 0, oldURLs.length);
689: // newURLs[oldURLs.length] = url;
690: //
691: // // Create a new class loader with all the URLs
692: // classLoader = new URLClassLoader(newURLs);
693: // }
694: // else {
695: // classLoader = new URLClassLoader(new URL[] { url }, classLoader);
696: // }
697: // }
698:
699: // public Class defineClass(String name, byte[] code) {
700: // File file = new File("debug-" + name + ".class");
701: //
702: // try {
703: // FileOutputStream out = new FileOutputStream(file);
704: // out.write(code);
705: // out.close();
706: // DrJava.consoleErr().println("debug class " + name + " to " + file.getAbsolutePath());
707: // }
708: // catch (Throwable t) { }
709: //
710: // Class c = super.defineClass(name, code);
711: // return c;
712: // }
713:
714: }
715: }
|