1 28 package net.sf.jasperreports.engine.design; 29 30 import java.io.ByteArrayOutputStream ; 31 import java.io.File ; 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.lang.reflect.Constructor ; 35 import java.lang.reflect.InvocationTargetException ; 36 import java.util.Enumeration ; 37 import java.util.HashMap ; 38 import java.util.Iterator ; 39 import java.util.List ; 40 import java.util.Locale ; 41 import java.util.Map ; 42 import java.util.Properties ; 43 44 import net.sf.jasperreports.engine.JRException; 45 import net.sf.jasperreports.engine.JRReport; 46 import net.sf.jasperreports.engine.JRRuntimeException; 47 import net.sf.jasperreports.engine.util.JRClassLoader; 48 import net.sf.jasperreports.engine.util.JRProperties; 49 50 import org.apache.commons.logging.Log; 51 import org.apache.commons.logging.LogFactory; 52 import org.eclipse.jdt.core.compiler.IProblem; 53 import org.eclipse.jdt.internal.compiler.ClassFile; 54 import org.eclipse.jdt.internal.compiler.CompilationResult; 55 import org.eclipse.jdt.internal.compiler.Compiler; 56 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; 57 import org.eclipse.jdt.internal.compiler.ICompilerRequestor; 58 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; 59 import org.eclipse.jdt.internal.compiler.IProblemFactory; 60 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; 61 import org.eclipse.jdt.internal.compiler.env.IBinaryType; 62 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; 63 import org.eclipse.jdt.internal.compiler.env.INameEnvironment; 64 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; 65 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 66 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 67 68 72 public class JRJdtCompiler extends JRAbstractJavaCompiler 73 { 74 private static final String JDT_PROPERTIES_PREFIX = "org.eclipse.jdt.core."; 75 76 79 static final Log log = LogFactory.getLog(JRJdtCompiler.class); 80 81 private final ClassLoader classLoader; 82 83 Constructor constrNameEnvAnsBin; 84 Constructor constrNameEnvAnsCompUnit; 85 86 boolean is2ArgsConstr; 87 Constructor constrNameEnvAnsBin2Args; 88 Constructor constrNameEnvAnsCompUnit2Args; 89 90 public JRJdtCompiler () 91 { 92 super(false); 93 94 classLoader = getClassLoader(); 95 96 boolean success; 97 try { 99 Class classAccessRestriction = loadClass("org.eclipse.jdt.internal.compiler.env.AccessRestriction"); 100 constrNameEnvAnsBin2Args = NameEnvironmentAnswer.class.getConstructor(new Class []{IBinaryType.class, classAccessRestriction}); 101 constrNameEnvAnsCompUnit2Args = NameEnvironmentAnswer.class.getConstructor(new Class []{ICompilationUnit.class, classAccessRestriction}); 102 is2ArgsConstr = true; 103 success = true; 104 } 105 catch (NoSuchMethodException e) 106 { 107 success = false; 108 } 109 catch (ClassNotFoundException ex) 110 { 111 success = false; 112 } 113 114 if (!success) 115 { 116 try 117 { 118 constrNameEnvAnsBin = NameEnvironmentAnswer.class.getConstructor(new Class []{IBinaryType.class}); 119 constrNameEnvAnsCompUnit = NameEnvironmentAnswer.class.getConstructor(new Class []{ICompilationUnit.class}); 120 is2ArgsConstr = false; 121 } 122 catch (NoSuchMethodException ex) 123 { 124 throw new JRRuntimeException("Not able to load JDT classes", ex); 125 } 126 } 127 } 128 129 130 133 protected String compileUnits(final JRCompilationUnit[] units, String classpath, File tempDirFile) 134 { 135 final StringBuffer problemBuffer = new StringBuffer (); 136 137 138 class CompilationUnit implements ICompilationUnit 139 { 140 protected String srcCode; 141 protected String className; 142 143 public CompilationUnit(String srcCode, String className) 144 { 145 this.srcCode = srcCode; 146 this.className = className; 147 } 148 149 public char[] getFileName() 150 { 151 return className.toCharArray(); 152 } 153 154 public char[] getContents() 155 { 156 return srcCode.toCharArray(); 157 } 158 159 public char[] getMainTypeName() 160 { 161 return className.toCharArray(); 162 } 163 164 public char[][] getPackageName() 165 { 166 return new char[0][0]; 167 } 168 } 169 170 171 final INameEnvironment env = new INameEnvironment() 172 { 173 public NameEnvironmentAnswer findType(char[][] compoundTypeName) 174 { 175 StringBuffer result = new StringBuffer (); 176 String sep = ""; 177 for (int i = 0; i < compoundTypeName.length; i++) { 178 result.append(sep); 179 result.append(compoundTypeName[i]); 180 sep = "."; 181 } 182 return findType(result.toString()); 183 } 184 185 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) 186 { 187 StringBuffer result = new StringBuffer (); 188 String sep = ""; 189 for (int i = 0; i < packageName.length; i++) { 190 result.append(sep); 191 result.append(packageName[i]); 192 sep = "."; 193 } 194 result.append(sep); 195 result.append(typeName); 196 return findType(result.toString()); 197 } 198 199 private int getClassIndex(String className) 200 { 201 int classIdx; 202 for (classIdx = 0; classIdx < units.length; ++classIdx) 203 { 204 if (className.equals(units[classIdx].getName())) 205 { 206 break; 207 } 208 } 209 210 if (classIdx >= units.length) 211 { 212 classIdx = -1; 213 } 214 215 return classIdx; 216 } 217 218 private NameEnvironmentAnswer findType(String className) 219 { 220 try 221 { 222 int classIdx = getClassIndex(className); 223 224 if (classIdx >= 0) 225 { 226 ICompilationUnit compilationUnit = 227 new CompilationUnit( 228 units[classIdx].getSourceCode(), className); 229 if (is2ArgsConstr) 230 { 231 return (NameEnvironmentAnswer) constrNameEnvAnsCompUnit2Args.newInstance(new Object [] { compilationUnit, null }); 232 } 233 234 return (NameEnvironmentAnswer) constrNameEnvAnsCompUnit.newInstance(new Object [] { compilationUnit }); 235 } 236 237 String resourceName = className.replace('.', '/') + ".class"; 238 InputStream is = getResource(resourceName); 239 if (is != null) 240 { 241 byte[] classBytes; 242 byte[] buf = new byte[8192]; 243 ByteArrayOutputStream baos = new ByteArrayOutputStream (buf.length); 244 int count; 245 while ((count = is.read(buf, 0, buf.length)) > 0) 246 { 247 baos.write(buf, 0, count); 248 } 249 baos.flush(); 250 classBytes = baos.toByteArray(); 251 char[] fileName = className.toCharArray(); 252 ClassFileReader classFileReader = 253 new ClassFileReader(classBytes, fileName, true); 254 255 if (is2ArgsConstr) 256 { 257 return (NameEnvironmentAnswer) constrNameEnvAnsBin2Args.newInstance(new Object [] { classFileReader, null }); 258 } 259 260 return (NameEnvironmentAnswer) constrNameEnvAnsBin.newInstance(new Object [] { classFileReader }); 261 } 262 } 263 catch (IOException exc) 264 { 265 log.error("Compilation error", exc); 266 } 267 catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException exc) 268 { 269 log.error("Compilation error", exc); 270 } 271 catch (InvocationTargetException e) 272 { 273 throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e); 274 } 275 catch (IllegalArgumentException e) 276 { 277 throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e); 278 } 279 catch (InstantiationException e) 280 { 281 throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e); 282 } 283 catch (IllegalAccessException e) 284 { 285 throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e); 286 } 287 return null; 288 } 289 290 private boolean isPackage(String result) 291 { 292 int classIdx = getClassIndex(result); 293 if (classIdx >= 0) 294 { 295 return false; 296 } 297 298 String resourceName = result.replace('.', '/') + ".class"; 299 300 boolean isPackage = true; 301 302 InputStream is = getResource(resourceName); 303 304 if (is != null) { try { 308 isPackage = (is.read() > 0); 309 } 310 catch(IOException e) 311 { 312 } 314 finally 315 { 316 try 317 { 318 is.close(); 319 } 320 catch(IOException e) 321 { 322 } 324 } 325 } 326 327 return isPackage; 328 } 329 330 public boolean isPackage(char[][] parentPackageName, char[] packageName) 331 { 332 StringBuffer result = new StringBuffer (); 333 String sep = ""; 334 if (parentPackageName != null) 335 { 336 for (int i = 0; i < parentPackageName.length; i++) 337 { 338 result.append(sep); 339 result.append(parentPackageName[i]); 340 sep = "."; 341 } 342 } 343 if (Character.isUpperCase(packageName[0])) 344 { 345 if (!isPackage(result.toString())) 346 { 347 return false; 348 } 349 } 350 result.append(sep); 351 result.append(packageName); 352 return isPackage(result.toString()); 353 } 354 355 public void cleanup() 356 { 357 } 358 359 }; 360 361 final IErrorHandlingPolicy policy = 362 DefaultErrorHandlingPolicies.proceedWithAllProblems(); 363 364 final Map settings = getJdtSettings(); 365 366 final IProblemFactory problemFactory = 367 new DefaultProblemFactory(Locale.getDefault()); 368 369 final ICompilerRequestor requestor = 370 new ICompilerRequestor() 371 { 372 public void acceptResult(CompilationResult result) 373 { 374 String className = ((CompilationUnit) result.getCompilationUnit()).className; 375 376 int classIdx; 377 for (classIdx = 0; classIdx < units.length; ++classIdx) 378 { 379 if (className.equals(units[classIdx].getName())) 380 { 381 break; 382 } 383 } 384 385 if (result.hasErrors()) 386 { 387 String sourceCode = units[classIdx].getSourceCode(); 388 389 IProblem[] problems = result.getErrors(); 390 for (int i = 0; i < problems.length; i++) 391 { 392 IProblem problem = problems[i]; 393 { 395 problemBuffer.append(i + 1); 396 problemBuffer.append(". "); 397 problemBuffer.append(problem.getMessage()); 398 399 if ( 400 problem.getSourceStart() >= 0 401 && problem.getSourceEnd() >= 0 402 ) 403 { 404 int problemStartIndex = sourceCode.lastIndexOf("\n", problem.getSourceStart()) + 1; 405 int problemEndIndex = sourceCode.indexOf("\n", problem.getSourceEnd()); 406 if (problemEndIndex < 0) 407 { 408 problemEndIndex = sourceCode.length(); 409 } 410 411 problemBuffer.append("\n"); 412 problemBuffer.append( 413 sourceCode.substring( 414 problemStartIndex, 415 problemEndIndex 416 ) 417 ); 418 problemBuffer.append("\n"); 419 for(int j = problemStartIndex; j < problem.getSourceStart(); j++) 420 { 421 problemBuffer.append(" "); 422 } 423 if (problem.getSourceStart() == problem.getSourceEnd()) 424 { 425 problemBuffer.append("^"); 426 } 427 else 428 { 429 problemBuffer.append("<"); 430 for(int j = problem.getSourceStart() + 1; j < problem.getSourceEnd(); j++) 431 { 432 problemBuffer.append("-"); 433 } 434 problemBuffer.append(">"); 435 } 436 } 437 438 problemBuffer.append("\n"); 439 } 440 } 441 problemBuffer.append(problems.length); 442 problemBuffer.append(" errors\n"); 443 } 444 if (problemBuffer.length() == 0) 445 { 446 ClassFile[] resultClassFiles = result.getClassFiles(); 447 for (int i = 0; i < resultClassFiles.length; i++) 448 { 449 units[classIdx].setCompileData(resultClassFiles[i].getBytes()); 450 } 451 } 452 } 453 }; 454 455 ICompilationUnit[] compilationUnits = new ICompilationUnit[units.length]; 456 for (int i = 0; i < compilationUnits.length; i++) 457 { 458 compilationUnits[i] = new CompilationUnit(units[i].getSourceCode(), units[i].getName()); 459 } 460 461 Compiler compiler = 462 new Compiler (env, policy, settings, requestor, problemFactory); 463 compiler.compile(compilationUnits); 464 465 if (problemBuffer.length() > 0) 466 { 467 return problemBuffer.toString(); 468 } 469 470 return null; 471 } 472 473 474 protected Map getJdtSettings() 475 { 476 final Map settings = new HashMap (); 477 settings.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE); 478 settings.put(CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.GENERATE); 479 settings.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE); 480 489 List properties = JRProperties.getProperties(JDT_PROPERTIES_PREFIX); 490 for (Iterator it = properties.iterator(); it.hasNext();) 491 { 492 JRProperties.PropertySuffix property = (JRProperties.PropertySuffix) it.next(); 493 String propVal = property.getValue(); 494 if (propVal != null && propVal.length() > 0) 495 { 496 settings.put(property.getKey(), propVal); 497 } 498 } 499 500 Properties systemProps = System.getProperties(); 501 for (Enumeration it = systemProps.propertyNames(); it.hasMoreElements();) 502 { 503 String propName = (String ) it.nextElement(); 504 if (propName.startsWith(JDT_PROPERTIES_PREFIX)) 505 { 506 String propVal = systemProps.getProperty(propName); 507 if (propVal != null && propVal.length() > 0) 508 { 509 settings.put(propName, propVal); 510 } 511 } 512 } 513 514 return settings; 515 } 516 517 518 521 private ClassLoader getClassLoader() 522 { 523 ClassLoader clsLoader = Thread.currentThread().getContextClassLoader(); 524 525 if (clsLoader != null) 526 { 527 try 528 { 529 Class.forName(JRJdtCompiler.class.getName(), true, clsLoader); 530 } 531 catch (ClassNotFoundException e) 532 { 533 clsLoader = null; 534 } 537 } 538 539 if (clsLoader == null) 540 { 541 clsLoader = JRClassLoader.class.getClassLoader(); 542 } 543 544 return clsLoader; 545 } 546 547 protected InputStream getResource (String resourceName) 548 { 549 if (classLoader == null) 550 { 551 return JRJdtCompiler.class.getResourceAsStream("/" + resourceName); 552 } 553 return classLoader.getResourceAsStream(resourceName); 554 } 555 556 557 protected Class loadClass (String className) throws ClassNotFoundException 558 { 559 if (classLoader == null) 560 { 561 return Class.forName(className); 562 } 563 return classLoader.loadClass(className); 564 } 565 566 567 protected void checkLanguage(String language) throws JRException 568 { 569 if (!JRReport.LANGUAGE_JAVA.equals(language)) 570 { 571 throw 572 new JRException( 573 "Language \"" + language 574 + "\" not supported by this report compiler.\n" 575 + "Expecting \"java\" instead." 576 ); 577 } 578 } 579 580 581 protected String generateSourceCode(JRSourceCompileTask sourceTask) throws JRException 582 { 583 return JRClassGenerator.generateClass(sourceTask); 584 } 585 586 protected String getSourceFileName(String unitName) 587 { 588 return unitName + ".java"; 589 } 590 591 592 protected String getCompilerClass() 593 { 594 return JRJavacCompiler.class.getName(); 595 } 596 } 597 | Popular Tags |