1 16 package org.apache.cocoon.components.language.programming.java; 17 18 import org.apache.avalon.excalibur.pool.Recyclable; 19 import org.apache.cocoon.components.language.programming.CompilerError; 20 import org.apache.cocoon.components.language.programming.LanguageCompiler; 21 import org.apache.cocoon.util.ClassUtils; 22 import org.apache.commons.lang.StringUtils; 23 import org.apache.commons.lang.SystemUtils; 24 25 import org.eclipse.jdt.core.compiler.IProblem; 26 import org.eclipse.jdt.internal.compiler.ClassFile; 27 import org.eclipse.jdt.internal.compiler.CompilationResult; 28 import org.eclipse.jdt.internal.compiler.Compiler; 29 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; 30 import org.eclipse.jdt.internal.compiler.ICompilerRequestor; 31 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; 32 import org.eclipse.jdt.internal.compiler.IProblemFactory; 33 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; 34 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; 35 import org.eclipse.jdt.internal.compiler.env.INameEnvironment; 36 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; 37 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 38 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 39 40 import java.io.BufferedOutputStream ; 41 import java.io.BufferedReader ; 42 import java.io.ByteArrayOutputStream ; 43 import java.io.File ; 44 import java.io.FileOutputStream ; 45 import java.io.FileReader ; 46 import java.io.IOException ; 47 import java.io.InputStream ; 48 import java.io.Reader ; 49 import java.util.HashMap ; 50 import java.util.LinkedList ; 51 import java.util.List ; 52 import java.util.Locale ; 53 import java.util.Map ; 54 import java.util.StringTokenizer ; 55 56 61 public class EclipseJavaCompiler implements LanguageCompiler, Recyclable { 62 63 boolean debug; 64 65 String sourceDir; 66 String sourceFile; 67 String destDir; 68 String sourceEncoding; 69 int compilerComplianceLevel; 70 71 List errors = new LinkedList (); 72 73 public EclipseJavaCompiler() { 74 this.debug = true; 75 } 76 77 public void recycle() { 78 sourceFile = null; 79 sourceDir = null; 80 destDir = null; 81 sourceEncoding = null; 82 errors.clear(); 83 } 84 85 public void setFile(String file) { 86 this.sourceFile = file; 88 } 89 90 public void setSource(String srcDir) { 91 this.sourceDir = srcDir; 93 } 94 95 public void setDestination(String destDir) { 96 this.destDir = destDir; 98 } 99 100 public void setEncoding(String encoding) { 101 this.sourceEncoding = encoding; 102 } 103 104 112 public void setCompilerComplianceLevel(int compilerComplianceLevel) { 113 this.compilerComplianceLevel = compilerComplianceLevel; 114 } 115 116 121 public void setClasspath(String cp) { 122 } 124 125 private String makeClassName(String fileName) throws IOException { 126 File origFile = new File(fileName); 127 String canonical = null; 128 if (origFile.exists()) { 129 canonical = origFile.getCanonicalPath().replace('\\', '/'); 130 } 131 String str = fileName; 132 str = str.replace('\\', '/'); 133 if (sourceDir != null) { 134 String prefix = 135 new File(sourceDir).getCanonicalPath().replace('\\', '/'); 136 if (canonical != null) { 137 if (canonical.startsWith(prefix)) { 138 String result = canonical.substring(prefix.length() + 1, 139 canonical.length() -5); 140 result = result.replace('/', '.'); 141 return result; 142 } 143 } else { 144 File t = new File(sourceDir, fileName); 145 if (t.exists()) { 146 str = t.getCanonicalPath().replace('\\', '/'); 147 String result = str.substring(prefix.length()+1, 148 str.length() - 5).replace('/', '.'); 149 return result; 150 } 151 } 152 } 153 if (fileName.endsWith(".java")) { 154 fileName = fileName.substring(0, fileName.length() - 5); 155 } 156 return StringUtils.replaceChars(fileName, "\\/", ".."); 157 } 158 159 public boolean compile() throws IOException { 160 final String targetClassName = makeClassName(sourceFile); 161 final ClassLoader classLoader = ClassUtils.getClassLoader(); 162 String [] fileNames = new String [] {sourceFile}; 163 String [] classNames = new String [] {targetClassName}; 164 class CompilationUnit implements ICompilationUnit { 165 166 String className; 167 String sourceFile; 168 169 CompilationUnit(String sourceFile, String className) { 170 this.className = className; 171 this.sourceFile = sourceFile; 172 } 173 174 public char[] getFileName() { 175 return className.toCharArray(); 176 } 177 178 public char[] getContents() { 179 char[] result = null; 180 FileReader fr = null; 181 try { 182 fr = new FileReader(sourceFile); 183 Reader reader = new BufferedReader (fr); 184 if (reader != null) { 185 char[] chars = new char[8192]; 186 StringBuffer buf = new StringBuffer (); 187 int count; 188 while ((count = reader.read(chars, 0, chars.length)) > 0) { 189 buf.append(chars, 0, count); 190 } 191 result = new char[buf.length()]; 192 buf.getChars(0, result.length, result, 0); 193 } 194 } catch (IOException e) { 195 handleError(className, -1, -1, e.getMessage()); 196 } 197 return result; 198 } 199 200 public char[] getMainTypeName() { 201 int dot = className.lastIndexOf('.'); 202 if (dot > 0) { 203 return className.substring(dot + 1).toCharArray(); 204 } 205 return className.toCharArray(); 206 } 207 208 public char[][] getPackageName() { 209 StringTokenizer izer = new StringTokenizer (className, "."); 210 char[][] result = new char[izer.countTokens()-1][]; 211 for (int i = 0; i < result.length; i++) { 212 String tok = izer.nextToken(); 213 result[i] = tok.toCharArray(); 214 } 215 return result; 216 } 217 } 218 219 220 final INameEnvironment env = new INameEnvironment() { 221 222 public NameEnvironmentAnswer findType(char[][] compoundTypeName) { 223 StringBuffer result = new StringBuffer (); 224 for (int i = 0; i < compoundTypeName.length; i++) { 225 if (i > 0) { 226 result.append("."); 227 } 228 result.append(compoundTypeName[i]); 229 } 230 return findType(result.toString()); 231 } 232 233 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { 234 StringBuffer result = new StringBuffer (); 235 for (int i = 0; i < packageName.length; i++) { 236 if (i > 0) { 237 result.append("."); 238 } 239 result.append(packageName[i]); 240 } 241 result.append("."); 242 result.append(typeName); 243 return findType(result.toString()); 244 } 245 246 private NameEnvironmentAnswer findType(String className) { 247 248 try { 249 if (className.equals(targetClassName)) { 250 ICompilationUnit compilationUnit = 251 new CompilationUnit(sourceFile, className); 252 return 253 new NameEnvironmentAnswer(compilationUnit); 254 } 255 String resourceName = 256 className.replace('.', '/') + ".class"; 257 InputStream is = 258 classLoader.getResourceAsStream(resourceName); 259 if (is != null) { 260 byte[] classBytes; 261 byte[] buf = new byte[8192]; 262 ByteArrayOutputStream baos = 263 new ByteArrayOutputStream (buf.length); 264 int count; 265 while ((count = is.read(buf, 0, buf.length)) > 0) { 266 baos.write(buf, 0, count); 267 } 268 baos.flush(); 269 classBytes = baos.toByteArray(); 270 char[] fileName = className.toCharArray(); 271 ClassFileReader classFileReader = 272 new ClassFileReader(classBytes, fileName, 273 true); 274 return 275 new NameEnvironmentAnswer(classFileReader); 276 } 277 } catch (IOException exc) { 278 handleError(className, -1, -1, 279 exc.getMessage()); 280 } catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException exc) { 281 handleError(className, -1, -1, 282 exc.getMessage()); 283 } 284 return null; 285 } 286 287 private boolean isPackage(String result) { 288 if (result.equals(targetClassName)) { 289 return false; 290 } 291 String resourceName = result.replace('.', '/') + ".class"; 292 InputStream is = 293 classLoader.getResourceAsStream(resourceName); 294 return is == null; 295 } 296 297 public boolean isPackage(char[][] parentPackageName, char[] packageName) { 298 StringBuffer result = new StringBuffer (); 299 if (parentPackageName != null) { 300 for (int i = 0; i < parentPackageName.length; i++) { 301 if (i > 0) { 302 result.append("."); 303 } 304 result.append(parentPackageName[i]); 305 } 306 } 307 String str = new String (packageName); 308 if (Character.isUpperCase(str.charAt(0)) && !isPackage(result.toString())) { 309 return false; 310 } 311 result.append("."); 312 result.append(str); 313 return isPackage(result.toString()); 314 } 315 316 public void cleanup() { 317 } 319 }; 320 final IErrorHandlingPolicy policy = 321 DefaultErrorHandlingPolicies.proceedWithAllProblems(); 322 final Map settings = new HashMap (9); 323 settings.put(CompilerOptions.OPTION_LineNumberAttribute, 324 CompilerOptions.GENERATE); 325 settings.put(CompilerOptions.OPTION_SourceFileAttribute, 326 CompilerOptions.GENERATE); 327 settings.put(CompilerOptions.OPTION_ReportDeprecation, 328 CompilerOptions.IGNORE); 329 settings.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.IGNORE); 330 if (sourceEncoding != null) { 331 settings.put(CompilerOptions.OPTION_Encoding, sourceEncoding); 332 } 333 if (debug) { 334 settings.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE); 335 } 336 switch (this.compilerComplianceLevel) { 338 case 150: 339 settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5); 340 settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5); 341 break; 342 case 140: 343 settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4); 344 break; 345 default: 346 settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3); 347 } 348 switch (SystemUtils.JAVA_VERSION_INT) { 350 case 150: 351 settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5); 352 break; 353 case 140: 354 settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4); 355 break; 356 default: 357 settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3); 358 } 359 final IProblemFactory problemFactory = 360 new DefaultProblemFactory(Locale.getDefault()); 361 362 final ICompilerRequestor requestor = new ICompilerRequestor() { 363 public void acceptResult(CompilationResult result) { 364 try { 365 if (result.hasErrors()) { 366 IProblem[] errors = result.getErrors(); 367 for (int i = 0; i < errors.length; i++) { 368 IProblem error = errors[i]; 369 String name = new String (errors[i].getOriginatingFileName()); 370 handleError(name, error.getSourceLineNumber(), -1, error.getMessage()); 371 } 372 } else { 373 ClassFile[] classFiles = result.getClassFiles(); 374 for (int i = 0; i < classFiles.length; i++) { 375 ClassFile classFile = classFiles[i]; 376 char[][] compoundName = classFile.getCompoundName(); 377 StringBuffer className = new StringBuffer (); 378 for (int j = 0; j < compoundName.length; j++) { 379 if (j > 0) { 380 className.append("."); 381 } 382 className.append(compoundName[j]); 383 } 384 byte[] bytes = classFile.getBytes(); 385 String outFile = destDir + "/" + 386 className.toString().replace('.', '/') + ".class"; 387 FileOutputStream fout = new FileOutputStream (outFile); 388 BufferedOutputStream bos = new BufferedOutputStream (fout); 389 bos.write(bytes); 390 bos.close(); 391 } 392 } 393 } catch (IOException exc) { 394 exc.printStackTrace(); 395 } 396 } 397 }; 398 ICompilationUnit[] compilationUnits = 399 new ICompilationUnit[classNames.length]; 400 for (int i = 0; i < compilationUnits.length; i++) { 401 String className = classNames[i]; 402 compilationUnits[i] = new CompilationUnit(fileNames[i], className); 403 } 404 Compiler compiler = new Compiler (env, 405 policy, 406 settings, 407 requestor, 408 problemFactory); 409 compiler.compile(compilationUnits); 410 return errors.size() == 0; 411 } 412 413 void handleError(String className, int line, int column, Object errorMessage) { 414 String fileName = 415 className.replace('.', File.separatorChar) + ".java"; 416 if (column < 0) column = 0; 417 errors.add(new CompilerError(fileName, 418 true, 419 line, 420 column, 421 line, 422 column, 423 errorMessage.toString())); 424 } 425 426 public List getErrors() throws IOException { 427 return errors; 428 } 429 } 430 | Popular Tags |