1 4 package com.tc.aspectwerkz.compiler; 5 6 7 import com.tc.aspectwerkz.aspect.AdviceInfo; 8 import com.tc.aspectwerkz.cflow.CflowBinding; 9 import com.tc.aspectwerkz.cflow.CflowCompiler; 10 import com.tc.aspectwerkz.definition.SystemDefinitionContainer; 11 import com.tc.aspectwerkz.joinpoint.management.AdviceInfoContainer; 12 import com.tc.aspectwerkz.joinpoint.management.JoinPointManager; 13 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint; 14 import com.tc.aspectwerkz.util.ContextClassLoader; 15 16 import java.io.ByteArrayOutputStream ; 17 import java.io.File ; 18 import java.io.FileInputStream ; 19 import java.io.FileOutputStream ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.net.URL ; 23 import java.net.URLClassLoader ; 24 import java.text.SimpleDateFormat ; 25 import java.util.ArrayList ; 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.Map ; 30 31 70 public class AspectWerkzC { 71 private static final String COMMAND_LINE_OPTION_DASH = "-"; 73 private static final String COMMAND_LINE_OPTION_VERBOSE = "-verbose"; 74 private static final String COMMAND_LINE_OPTION_DETAILS = "-details"; 75 private static final String COMMAND_LINE_OPTION_GENJP = "-genjp"; 76 private static final String COMMAND_LINE_OPTION_HALT = "-haltOnError"; 77 private static final String COMMAND_LINE_OPTION_VERIFY = "-verify"; 78 private static final String COMMAND_LINE_OPTION_CLASSPATH = "-cp"; 79 private static final String COMMAND_LINE_OPTION_TARGETS = "compile.targets"; 80 81 84 private static final String PRE_PROCESSOR_CLASSNAME_PROPERTY = "aspectwerkz.classloader.preprocessor"; 85 86 private final static String AW_TRANSFORM_DETAILS = "aspectwerkz.transform.details"; 87 88 91 private static final String PRE_PROCESSOR_CLASSNAME_DEFAULT = "com.tc.aspectwerkz.transform.AspectWerkzPreProcessor"; 92 93 private final static String MF_CUSTOM_DATE = "X-AspectWerkzC-created"; 94 95 private final static String MF_CUSTOM_PP = "X-AspectWerkzC-preprocessor"; 96 97 private final static String MF_CUSTOM_COMMENT = "X-AspectWerkzC-comment"; 98 99 private final static String MF_CUSTOM_COMMENT_VALUE = "AspectWerkzC - AspectWerkz compiler, aspectwerkz.codehaus.org"; 100 101 private final static SimpleDateFormat DF = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); 102 103 private final static String BACKUP_DIR = "_aspectwerkzc"; 104 105 private boolean verify = false; 106 107 private boolean genJp = false; 108 109 private boolean haltOnError = false; 110 111 private String backupDir = BACKUP_DIR; 112 113 116 private URLClassLoader compilationLoader = null; 117 118 121 private boolean isAspectWerkzPreProcessor = false; 123 124 127 private int sourceIndex; 128 129 132 private Map backupMap = new HashMap (); 133 134 137 private Map successMap = new HashMap (); 138 139 private long timer; 140 141 144 private Utility utility; 145 146 149 public AspectWerkzC() { 150 sourceIndex = 0; 152 utility = new Utility(); 153 timer = System.currentTimeMillis(); 154 } 155 156 160 public void setVerbose(boolean verbose) { 161 utility.setVerbose(verbose); 162 } 163 164 public void setGenJp(boolean genpJp) { 165 this.genJp = genpJp; 166 } 167 168 public void setHaltOnError(boolean haltOnError) { 169 this.haltOnError = haltOnError; 170 } 171 172 public void setVerify(boolean verify) { 173 this.verify = verify; 174 } 175 176 public void setDetails(boolean details) { 177 if (details) { 178 System.setProperty(AW_TRANSFORM_DETAILS, "true"); 179 } 180 } 181 182 public void setBackupDir(String backup) { 183 this.backupDir = backup; 184 } 185 186 public Utility getUtility() { 187 return utility; 188 } 189 190 194 public void setPreprocessor(String preprocessor) throws CompileException { 195 } 207 208 211 public void backup(File source, int index) { 212 File dest = new File (this.backupDir + File.separator + index + File.separator + source.getName()); 214 utility.backupFile(source, dest); 215 216 backupMap.put(source, dest); 218 } 219 220 223 public void restoreBackup() { 224 for (Iterator i = backupMap.keySet().iterator(); i.hasNext();) { 225 File source = (File ) i.next(); 226 if (!successMap.containsKey(source)) { 227 File dest = (File ) backupMap.get(source); 228 utility.backupFile(dest, source); 229 } 230 } 231 } 232 233 236 public void postCompile(String message) { 237 restoreBackup(); 238 utility.log(" [backup] removing backup"); 239 utility.deleteDir(new File (this.backupDir)); 240 long ms = Math.max(System.currentTimeMillis() - timer, 1 * 1000); 241 System.out.println("( " + (int) (ms / 1000) + " s ) " + message); 242 if (!haltOnError) { 243 for (Iterator i = backupMap.keySet().iterator(); i.hasNext();) { 244 File source = (File ) i.next(); 245 if (successMap.containsKey(source)) { 246 System.out.println("SUCCESS: " + source); 247 } else { 248 System.out.println("FAILED : " + source); 249 } 250 } 251 } 252 } 253 254 261 public void doCompile(File sourceFile, String prefixPackage) throws CompileException { 262 if (sourceFile.isDirectory()) { 263 File [] classes = sourceFile.listFiles(); 264 for (int i = 0; i < classes.length; i++) { 265 if (classes[i].isDirectory() && !(this.backupDir.equals(classes[i].getName()))) { 266 String packaging = (prefixPackage != null) ? (prefixPackage + "." + classes[i] 267 .getName()) : classes[i].getName(); 268 doCompile(classes[i], packaging); 269 } else if (classes[i].getName().toLowerCase().endsWith(".class")) { 270 compileClass(classes[i], prefixPackage); 271 } else if (isJarFile(classes[i])) { 272 compileJar(classes[i]); 274 } 275 } 276 } else if (sourceFile.getName().toLowerCase().endsWith(".class")) { 277 compileClass(sourceFile, null); 278 } else if (isJarFile(sourceFile)) { 279 compileJar(sourceFile); 280 } 281 } 282 283 286 public void compileClass(File file, String packaging) throws CompileException { 287 InputStream in = null; 288 FileOutputStream fos = null; 289 try { 290 utility.log(" [compile] " + file.getCanonicalPath()); 291 292 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 294 in = new FileInputStream (file); 295 byte[] buffer = new byte[1024]; 296 while (in.available() > 0) { 297 int length = in.read(buffer); 298 if (length == -1) { 299 break; 300 } 301 bos.write(buffer, 0, length); 302 } 303 304 String className = file.getName().substring(0, file.getName().length() - 6); 306 if (packaging != null) { 307 className = packaging + '.' + className; 308 } 309 310 318 356 if (verify) { 358 URLClassLoader verifier = new VerifierClassLoader( 359 compilationLoader.getURLs(), 360 ClassLoader.getSystemClassLoader() 361 ); 362 try { 363 utility.log(" [verify] " + className); 364 Class.forName(className, false, verifier); 365 } catch (Throwable t) { 366 utility.log(" [verify] corrupted class: " + className); 367 throw new CompileException("corrupted class: " + className, t); 368 } 369 } 370 } catch (IOException e) { 371 throw new CompileException("compile " + file.getAbsolutePath() + " failed", e); 372 } finally { 373 try { 374 in.close(); 375 } catch (Throwable e) { 376 ; 377 } 378 try { 379 fos.close(); 380 } catch (Throwable e) { 381 ; 382 } 383 } 384 } 385 386 390 public void compileJar(File file) throws CompileException { 391 utility.log(" [compilejar] " + file.getAbsolutePath()); 392 393 436 } 528 529 534 public boolean compile(File source) { 535 sourceIndex++; 536 backup(source, sourceIndex); 537 try { 538 doCompile(source, null); 539 } catch (CompileException e) { 540 utility.log(" [aspectwerkzc] compilation encountered an error"); 541 e.printStackTrace(); 542 return (!haltOnError); 543 } 544 545 successMap.put(source, Boolean.TRUE); 547 return true; 548 } 549 550 556 public void setCompilationPath(File [] targets, ClassLoader parentLoader) { 557 URL [] urls = new URL [targets.length]; 558 int j = 0; 559 for (int i = 0; i < targets.length; i++) { 560 try { 561 urls[j] = targets[i].getCanonicalFile().toURL(); 562 j++; 563 } catch (IOException e) { 564 System.err.println("bad target " + targets[i]); 565 } 566 } 567 568 compilationLoader = new URLClassLoader (urls, parentLoader); 569 } 570 571 574 public static boolean isJarFile(File source) { 575 return (source.isFile() && (source.getName().toLowerCase().endsWith(".jar") || source 576 .getName().toLowerCase().endsWith(".zip"))); 577 } 578 579 582 public static void doHelp() { 583 System.out.println("--- AspectWerkzC compiler ---"); 584 System.out.println("Usage:"); 585 System.out 586 .println( 587 "java -cp ... com.tc.aspectwerkz.compiler.AspectWerkzC [-verbose] [-haltOnError] [-verify] <target 1> .. <target n>" 588 ); 589 System.out.println(" <target i> : exploded dir, jar, zip files to compile"); 590 } 591 592 598 private static AspectWerkzC createCompiler(Map params) { 599 AspectWerkzC compiler = new AspectWerkzC(); 600 601 for (Iterator it = params.entrySet().iterator(); it.hasNext();) { 602 Map.Entry param = (Map.Entry ) it.next(); 603 604 if (COMMAND_LINE_OPTION_VERBOSE.equals(param.getKey())) { 605 compiler.setVerbose(Boolean.TRUE.equals(param.getValue())); 606 } else if (COMMAND_LINE_OPTION_HALT.equals(param.getKey())) { 607 compiler.setHaltOnError(Boolean.TRUE.equals(param.getValue())); 608 } else if (COMMAND_LINE_OPTION_VERIFY.equals(param.getKey())) { 609 compiler.setVerify(Boolean.TRUE.equals(param.getValue())); 610 } else if (COMMAND_LINE_OPTION_GENJP.equals(param.getKey())) { 611 compiler.setGenJp(Boolean.TRUE.equals(param.getValue())); 612 } else if (COMMAND_LINE_OPTION_DETAILS.equals(param.getKey())) { 613 compiler.setDetails(Boolean.TRUE.equals(param.getValue())); 614 } 615 } 616 617 return compiler; 618 } 619 620 631 public static void compile(AspectWerkzC compiler, 632 ClassLoader classLoader, 633 String preProcessor, 634 List classpath, 635 List targets) { 636 List fullPath = new ArrayList (); 637 if (classpath != null) { 638 fullPath.addAll(classpath); 639 } 640 641 fullPath.addAll(targets); 642 643 compiler.setCompilationPath((File []) fullPath.toArray(new File [fullPath.size()]), classLoader); 644 645 Thread.currentThread().setContextClassLoader(compiler.compilationLoader); 646 647 SystemDefinitionContainer.disableSystemWideDefinition(); 651 SystemDefinitionContainer.deployDefinitions( 652 compiler.compilationLoader, 653 SystemDefinitionContainer.getDefaultDefinition(compiler.compilationLoader) 654 ); 655 656 String preprocessorFqn = preProcessor == null ? PRE_PROCESSOR_CLASSNAME_DEFAULT 657 : preProcessor; 658 659 try { 660 compiler.setPreprocessor(preprocessorFqn); 661 } catch (CompileException e) { 662 System.err.println("Cannot instantiate ClassPreProcessor: " + preprocessorFqn); 663 e.printStackTrace(); 664 System.exit(-1); 665 } 666 667 cleanBackupDir(compiler); 668 669 for (Iterator i = targets.iterator(); i.hasNext();) { 670 if (!compiler.compile((File ) i.next())) { 671 compiler.postCompile("*** An error occured ***"); 672 System.exit(-1); 673 } 674 } 675 compiler.postCompile(""); 676 } 677 678 private static void cleanBackupDir(AspectWerkzC compiler) { 679 try { 681 File temp = new File (compiler.backupDir); 682 if (temp.exists()) { 683 compiler.getUtility().deleteDir(temp); 684 } 685 temp.mkdir(); 686 (new File (temp, "" + System.currentTimeMillis() + ".timestamp")).createNewFile(); 687 } catch (Exception e) { 688 System.err.println("failed to prepare backup dir: " + compiler.backupDir); 689 e.printStackTrace(); 690 System.exit(-1); 691 } 692 } 693 694 public static void main(String [] args) { 695 if (args.length <= 0) { 696 doHelp(); 697 return; } 699 700 Map options = parseOptions(args); 701 AspectWerkzC compiler = createCompiler(options); 702 703 compiler.setBackupDir(BACKUP_DIR); 704 705 compile( 706 compiler, 707 ClassLoader.getSystemClassLoader(), 708 System.getProperty( 709 PRE_PROCESSOR_CLASSNAME_PROPERTY, 710 PRE_PROCESSOR_CLASSNAME_DEFAULT 711 ), 712 (List ) options.get(COMMAND_LINE_OPTION_CLASSPATH), 713 (List ) options.get(COMMAND_LINE_OPTION_TARGETS) 714 ); 715 } 716 717 private static Map parseOptions(String [] args) { 718 Map options = new HashMap (); 719 List targets = new ArrayList (); 720 721 for (int i = 0; i < args.length; i++) { 722 if (COMMAND_LINE_OPTION_VERBOSE.equals(args[i])) { 723 options.put(COMMAND_LINE_OPTION_VERBOSE, Boolean.TRUE); 724 } else if (COMMAND_LINE_OPTION_GENJP.equals(args[i])) { 725 options.put(COMMAND_LINE_OPTION_GENJP, Boolean.TRUE); 726 } else if (COMMAND_LINE_OPTION_DETAILS.equals(args[i])) { 727 options.put(COMMAND_LINE_OPTION_DETAILS, Boolean.TRUE); 728 } else if (COMMAND_LINE_OPTION_HALT.equals(args[i])) { 729 options.put(COMMAND_LINE_OPTION_HALT, Boolean.TRUE); 730 } else if (COMMAND_LINE_OPTION_VERIFY.equals(args[i])) { 731 options.put(COMMAND_LINE_OPTION_VERIFY, Boolean.TRUE); 732 } else if (COMMAND_LINE_OPTION_CLASSPATH.equals(args[i])) { 733 if (i == (args.length - 1)) { 734 continue; 735 } else { 736 options.put( 737 COMMAND_LINE_OPTION_CLASSPATH, 738 toFileArray(args[++i], File.pathSeparator) 739 ); 740 } 741 } else if (args[i].startsWith(COMMAND_LINE_OPTION_DASH)) { 742 ; } else { 744 File file = toFile(args[i]); 745 if (file == null) { 746 System.err.println("Ignoring inexistant target: " + args[i]); 747 } else { 748 targets.add(file); 749 } 750 } 751 } 752 753 options.put(COMMAND_LINE_OPTION_TARGETS, targets); 754 755 return options; 756 } 757 758 private static List toFileArray(String str, String sep) { 759 if (str == null || str.length() == 0) { 760 return new ArrayList (); 761 } 762 763 List files = new ArrayList (); 764 int start = 0; 765 int idx = str.indexOf(sep, start); 766 int len = sep.length(); 767 768 while (idx != -1) { 769 files.add(new File (str.substring(start, idx))); 770 start = idx + len; 771 idx = str.indexOf(sep, start); 772 } 773 774 files.add(new File (str.substring(start))); 775 776 return files; 777 } 778 779 private static File toFile(String path) { 780 File file = new File (path); 781 782 return file.exists() ? file : null; 783 } 784 785 793 804 812 private JoinPointManager.CompiledJoinPoint compileJoinPoint(EmittedJoinPoint emittedJoinPoint, ClassLoader loader) throws IOException { 813 try { 814 Class callerClass = ContextClassLoader.forName(emittedJoinPoint.getCallerClassName().replace('/', '.')); 815 Class calleeClass = ContextClassLoader.forName(emittedJoinPoint.getCalleeClassName().replace('/', '.')); 816 JoinPointManager.CompiledJoinPoint jp = JoinPointManager.compileJoinPoint( 817 emittedJoinPoint.getJoinPointType(), 818 callerClass, 819 emittedJoinPoint.getCallerMethodName(), 820 emittedJoinPoint.getCallerMethodDesc(), 821 emittedJoinPoint.getCallerMethodModifiers(), 822 emittedJoinPoint.getCalleeClassName(), 823 emittedJoinPoint.getCalleeMemberName(), 824 emittedJoinPoint.getCalleeMemberDesc(), 825 emittedJoinPoint.getCalleeMemberModifiers(), 826 emittedJoinPoint.getJoinPointHash(), 827 emittedJoinPoint.getJoinPointClassName(), 828 calleeClass, 829 loader, 830 null 831 ); 832 return jp; 833 } catch (ClassNotFoundException e) { 834 throw new IOException ("Could not compile joinpoint : " + e.toString()); 835 } 836 } 837 838 845 private CflowCompiler.CompiledCflowAspect[] compileCflows(JoinPointManager.CompiledJoinPoint jp) { 846 List allCflowBindings = new ArrayList (); 847 AdviceInfoContainer adviceInfoContainer = jp.compilationInfo.getInitialModel().getAdviceInfoContainer(); 848 849 AdviceInfo[] advices = adviceInfoContainer.getAllAdviceInfos(); 850 for (int i = 0; i < advices.length; i++) { 851 AdviceInfo adviceInfo = advices[i]; 852 List cflowBindings = CflowBinding.getCflowBindingsForCflowOf(adviceInfo.getExpressionInfo()); 853 allCflowBindings.addAll(cflowBindings); 854 } 855 856 List compiledCflows = new ArrayList (); 857 for (Iterator iterator = allCflowBindings.iterator(); iterator.hasNext();) { 858 CflowBinding cflowBinding = (CflowBinding) iterator.next(); 859 compiledCflows.add(CflowCompiler.compileCflowAspect(cflowBinding.getCflowID())); 860 } 861 862 return (CflowCompiler.CompiledCflowAspect[]) compiledCflows.toArray(new CflowCompiler.CompiledCflowAspect[0]); 863 } 864 865 872 private static String getBaseDir(String weavedClassFileFullPath, String weavedClassName) { 873 String baseDirAbsolutePath = weavedClassFileFullPath; 874 int parentEndIndex = baseDirAbsolutePath.lastIndexOf(File.separatorChar); 875 for (int j = weavedClassName.toCharArray().length - 1; j >= 0; j--) { 876 char c = weavedClassName.toCharArray()[j]; 877 if (c == '.') { 878 if (parentEndIndex > 0) { 879 baseDirAbsolutePath = baseDirAbsolutePath.substring(0, parentEndIndex); 880 parentEndIndex = baseDirAbsolutePath.lastIndexOf(File.separatorChar); 881 } 882 } 883 } 884 if (parentEndIndex > 0) { 885 baseDirAbsolutePath = baseDirAbsolutePath.substring(0, parentEndIndex); 886 } 887 return baseDirAbsolutePath; 888 } 889 } | Popular Tags |