1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jci.compilers;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.net.URLClassLoader;
28 import java.util.HashMap;
29 import java.util.Locale;
30 import java.util.Map;
31
32 import org.objectweb.asm.ClassReader;
33 import org.objectweb.asm.ClassWriter;
34 import org.objectweb.asm.util.CheckClassAdapter;
35 import org.vafer.dependency.asm.RenamingVisitor;
36 import org.vafer.dependency.resources.ResourceRenamer;
37
38
39
40
41
42
43
44
45
46
47 public final class JavacClassLoader extends URLClassLoader {
48
49 private final Map loaded = new HashMap();
50
51 public JavacClassLoader( final ClassLoader pParent ) {
52 super(getToolsJar(), pParent);
53 }
54
55 private static URL[] getToolsJar() {
56 try {
57 Class.forName("com.sun.tools.javac.Main");
58
59
60 return new URL[0];
61
62 } catch (Exception e) {
63 }
64
65
66
67 String javaHome = System.getProperty("java.home");
68 if (javaHome.toLowerCase(Locale.US).endsWith(File.separator + "jre")) {
69 javaHome = javaHome.substring(0, javaHome.length()-4);
70 }
71
72 final File toolsJar = new File(javaHome + "/lib/tools.jar");
73
74 if (toolsJar.exists()) {
75 try {
76 return new URL[] { toolsJar.toURL() };
77 } catch (MalformedURLException e) {
78 }
79 }
80
81 final StringBuffer sb = new StringBuffer();
82 sb.append("Could not find javac compiler class (should be in the tools.jar/classes.jar in your JRE/JDK). ");
83 sb.append("os.name").append('=').append(System.getProperty("os.name")).append(", ");
84 sb.append("os.version").append('=').append(System.getProperty("os.version")).append(", ");
85 sb.append("java.class.path").append('=').append(System.getProperty("java.class.path"));
86
87 throw new RuntimeException(sb.toString());
88 }
89
90 protected Class findClass( final String name ) throws ClassNotFoundException {
91
92 if (name.startsWith("java.")) {
93 return super.findClass(name);
94 }
95
96 try {
97
98 final Class clazz = (Class) loaded.get(name);
99 if (clazz != null) {
100 return clazz;
101 }
102
103 final byte[] classBytes;
104
105 if (name.startsWith("com.sun.tools.javac.")) {
106 final InputStream classStream = getResourceAsStream(name.replace('.', '/') + ".class");
107
108 final ClassWriter renamedCw = new ClassWriter(true, false);
109 new ClassReader(classStream).accept(new RenamingVisitor(new CheckClassAdapter(renamedCw), new ResourceRenamer() {
110 public String getNewNameFor(final String pOldName) {
111 if (pOldName.startsWith(FileOutputStream.class.getName())) {
112 return FileOutputStreamProxy.class.getName();
113 }
114 if (pOldName.startsWith(FileInputStream.class.getName())) {
115 return FileInputStreamProxy.class.getName();
116 }
117 return pOldName;
118 }
119 }), false);
120
121 classBytes = renamedCw.toByteArray();
122
123 } else {
124 return super.findClass(name);
125 }
126
127 final Class newClazz = defineClass(name, classBytes, 0, classBytes.length);
128 loaded.put(name, newClazz);
129 return newClazz;
130 } catch (IOException e) {
131 throw new ClassNotFoundException("", e);
132 }
133 }
134
135 protected synchronized Class loadClass( final String classname, final boolean resolve ) throws ClassNotFoundException {
136
137 Class theClass = findLoadedClass(classname);
138 if (theClass != null) {
139 return theClass;
140 }
141
142 try {
143 theClass = findClass(classname);
144 } catch (ClassNotFoundException cnfe) {
145 theClass = getParent().loadClass(classname);
146 }
147
148 if (resolve) {
149 resolveClass(theClass);
150 }
151
152 return theClass;
153 }
154 }