1 16 package org.apache.cocoon.components.flow.javascript.fom; 17 18 import org.apache.excalibur.source.Source; 19 import org.apache.excalibur.source.SourceResolver; 20 import org.tempuri.javac.JavaClassReader; 21 import org.tempuri.javac.JavaClassReaderFactory; 22 import org.tempuri.javac.JavaClassWriter; 23 import org.tempuri.javac.JavaClassWriterFactory; 24 import org.tempuri.javac.JavaCompiler; 25 import org.tempuri.javac.JavaCompilerErrorHandler; 26 import org.tempuri.javac.JavaSourceReader; 27 import org.tempuri.javac.JavaSourceReaderFactory; 28 import org.tempuri.javacImpl.eclipse.JavaCompilerImpl; 29 30 import java.io.ByteArrayInputStream ; 31 import java.io.ByteArrayOutputStream ; 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.io.InputStreamReader ; 35 import java.io.Reader ; 36 import java.net.MalformedURLException ; 37 import java.util.HashSet ; 38 import java.util.Iterator ; 39 import java.util.LinkedList ; 40 import java.util.List ; 41 42 45 public class CompilingClassLoader extends ClassLoader { 46 47 SourceResolver sourceResolver; 48 JavaCompiler compiler; 49 List sourcePath = new LinkedList (); 50 HashSet sourceListeners = new HashSet (); 51 ClassRepository classRepository; 52 53 public interface SourceListener { 54 public void sourceCompiled(Source src); 55 public void sourceCompilationError(Source src, String error); 56 } 57 58 public interface ClassRepository { 59 public byte[] getCompiledClass(String className); 60 public void addCompiledClass(String className, 61 Source source, 62 byte[] contents); 63 } 64 65 protected Class findClass(String className) 66 throws ClassNotFoundException { 67 final byte[] bytes = compile(className); 68 return defineClass(className, bytes, 0, bytes.length); 69 } 70 71 public CompilingClassLoader(ClassLoader parent, 72 SourceResolver sourceResolver, 73 ClassRepository classRepository) { 74 super(parent); 75 this.sourceResolver = sourceResolver; 76 this.classRepository = classRepository; 77 this.compiler = new JavaCompilerImpl(); 78 this.sourcePath.add(""); 79 } 80 81 static class ClassCompilationException extends ClassNotFoundException { 82 public ClassCompilationException(String msg) { 83 super(msg); 84 } 85 } 86 87 public void addSourceListener(SourceListener listener) { 88 synchronized (sourceListeners) { 89 sourceListeners.add(listener); 90 } 91 } 92 93 public void removeSourceListener(SourceListener listener) { 94 synchronized (sourceListeners) { 95 sourceListeners.remove(listener); 96 } 97 } 98 99 private void notifyListeners(Source src, String err) { 100 SourceListener arr[]; 101 synchronized (sourceListeners) { 102 arr = new SourceListener[sourceListeners.size()]; 103 sourceListeners.toArray(arr); 104 } 105 if (err != null) { 106 for (int i = 0; i < arr.length; i++) { 107 arr[i].sourceCompilationError(src, err); 108 } 109 } else { 110 for (int i = 0; i < arr.length; i++) { 111 arr[i].sourceCompiled(src); 112 } 113 } 114 } 115 116 public void setClassRepository(ClassRepository rep) { 117 classRepository = rep; 118 } 119 120 public ClassRepository getClassRepository() { 121 return classRepository; 122 } 123 124 public void setSourcePath(String [] path) { 125 synchronized (sourcePath) { 126 sourcePath.clear(); 127 for (int i = 0; i < path.length; i++) { 128 sourcePath.add(path[i]); 129 } 130 sourcePath.add(""); 131 } 132 } 133 134 private Source getSource(String className) { 135 int dollar = className.indexOf('$'); 136 if (dollar > 0) { 137 className = className.substring(0, dollar); 139 } 140 141 synchronized (sourcePath) { 142 Iterator i = sourcePath.iterator(); 143 while (i.hasNext()) { 144 String prefix = (String ) i.next(); 145 if (prefix.length() > 0) { 146 if (!prefix.endsWith("/")) { 147 prefix += "/"; 148 } 149 } 150 String uri = prefix + className.replace('.', '/') + ".java"; 151 Source src; 152 try { 153 src = sourceResolver.resolveURI(uri); 154 } catch (MalformedURLException ignored) { 155 continue; 156 } catch (IOException ignored) { 157 continue; 158 } 159 160 if (src.exists()) { 161 return src; 162 } 163 releaseSource(src); 164 } 165 } 166 167 return null; 168 } 169 170 private void releaseSource(Source src) { 171 sourceResolver.release(src); 172 } 173 174 class SourceReaderFactory implements JavaSourceReaderFactory { 175 public JavaSourceReader getSourceReader(final String className) 176 throws IOException { 177 Source src = getSource(className); 178 if (src == null) return null; 179 try { 180 InputStream is = src.getInputStream(); 181 if (is == null) { 182 return null; 183 } 184 185 byte[] buf = new byte[8192]; 186 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 187 int count; 188 while ((count = is.read(buf, 0, buf.length)) > 0) { 189 baos.write(buf, 0, count); 190 } 191 baos.flush(); 192 193 final Reader reader = new InputStreamReader (new ByteArrayInputStream (baos.toByteArray())); 194 return new JavaSourceReader() { 195 public Reader getReader() { 196 return reader; 197 } 198 public String getClassName() { 199 return className; 200 } 201 }; 202 } finally { 203 releaseSource(src); 204 } 205 } 206 } 207 208 private String makeFileName(String className) { 209 Source src = getSource(className); 210 if (src != null) { 211 String result = src.getURI(); 212 releaseSource(src); 213 return result; 214 } 215 return className; 216 } 217 218 class ClassReaderFactory implements JavaClassReaderFactory { 219 public JavaClassReader getClassReader(final String className) 220 throws IOException { 221 final byte[] bytes = classRepository.getCompiledClass(className); 222 if (bytes != null) { 223 return new JavaClassReader() { 224 public String getClassName() { 225 return className; 226 } 227 228 public InputStream getInputStream() { 229 return new ByteArrayInputStream (bytes); 230 } 231 }; 232 } 233 234 String classFile = className.replace('.', '/') + ".class"; 235 final InputStream is = getResourceAsStream(classFile); 236 if (is != null) { 237 return new JavaClassReader() { 238 public String getClassName() { 239 return className; 240 } 241 242 public InputStream getInputStream() { 243 return is; 244 } 245 }; 246 } 247 248 return null; 249 } 250 } 251 252 class ClassWriterFactory implements JavaClassWriterFactory { 253 public JavaClassWriter getClassWriter(final String className) { 254 return new JavaClassWriter() { 255 public String getClassName() { 256 return className; 257 } 258 259 public void writeClass(InputStream contents) 260 throws IOException { 261 byte[] buf = new byte[2048]; 262 ByteArrayOutputStream s = new ByteArrayOutputStream (); 263 264 int count; 265 while ((count = contents.read(buf, 0, buf.length)) > 0) { 266 s.write(buf, 0, count); 267 } 268 s.flush(); 269 270 System.out.println("Compiled: " + className); 271 Source src = getSource(className); 272 classRepository.addCompiledClass(className, 273 src, 274 s.toByteArray()); 275 notifyListeners(src, null); 276 releaseSource(src); 277 } 278 }; 279 } 280 } 281 282 class ErrorHandler implements JavaCompilerErrorHandler { 283 List errList = new LinkedList (); 284 285 public void handleError(String className, 286 int line, 287 int column, 288 Object errorMessage) { 289 String msg = className; 290 try { 291 msg = makeFileName(className); 293 } catch (Exception ignored) { 294 } 296 297 if (line > 0) { 298 msg += ": Line " + line; 299 } 300 if (column >= 0) { 301 msg += "." + column; 302 } 303 msg += ": "; 304 msg += errorMessage; 305 errList.add(msg); 306 } 307 308 public List getErrorList() { 309 return errList; 310 } 311 } 312 313 private byte[] compile(String className) 314 throws ClassNotFoundException { 315 byte[] result = classRepository.getCompiledClass(className); 316 if (result != null) { 317 return result; 318 } 319 320 Source src = getSource(className); 321 if (src == null) { 322 throw new ClassNotFoundException (className); 323 } 324 325 try { 326 ErrorHandler errorHandler = new ErrorHandler(); 328 compiler.compile(new String [] {className}, 329 new SourceReaderFactory(), 330 new ClassReaderFactory(), 331 new ClassWriterFactory(), 332 errorHandler); 333 List errorList = errorHandler.getErrorList(); 334 if (errorList.size() > 0) { 335 StringBuffer msg = new StringBuffer ("Failed to compile Java class "); 336 msg.append(className); 337 msg.append(": "); 338 Iterator iter = errorList.iterator(); 339 while (iter.hasNext()) { 340 msg.append("\n"); 341 msg.append((String )iter.next()); 342 } 343 notifyListeners(src, msg.toString()); 344 throw new ClassCompilationException(msg.toString()); 345 } 346 347 return classRepository.getCompiledClass(className); 348 } finally { 349 releaseSource(src); 350 } 351 } 352 } 353 | Popular Tags |