From 183fc23883289ae42854ce9afcf2d3b0d29b7599 Mon Sep 17 00:00:00 2001 From: aclement Date: Thu, 18 Mar 2004 13:00:01 +0000 Subject: [PATCH] Fix for Bugzilla Bug 40192 build cancel during weaving --- .../ajde/internal/BuildNotifierAdapter.java | 9 +- ajde/testdata/BuildCancelling/A1.aj | 9 + ajde/testdata/BuildCancelling/A2.aj | 9 + ajde/testdata/BuildCancelling/A3.aj | 9 + ajde/testdata/BuildCancelling/A4.aj | 9 + ajde/testdata/BuildCancelling/Cl1.java | 4 + ajde/testdata/BuildCancelling/Cl2.java | 4 + ajde/testdata/BuildCancelling/Cl3.java | 4 + .../testdata/BuildCancelling/EvenMoreCode.lst | 10 + ajde/testdata/BuildCancelling/HW.java | 13 + ajde/testdata/BuildCancelling/LoadsaCode.lst | 7 + ajde/testsrc/org/aspectj/ajde/AjdeTests.java | 1 + .../org/aspectj/ajde/BuildCancellingTest.java | 410 ++++++++++++++++++ .../org/aspectj/bridge/IProgressListener.java | 11 + .../internal/compiler/AjCompilerAdapter.java | 7 +- .../ajdt/internal/compiler/WeaverAdapter.java | 88 +++- .../internal/core/builder/AjBuildManager.java | 20 +- 17 files changed, 610 insertions(+), 14 deletions(-) create mode 100644 ajde/testdata/BuildCancelling/A1.aj create mode 100644 ajde/testdata/BuildCancelling/A2.aj create mode 100644 ajde/testdata/BuildCancelling/A3.aj create mode 100644 ajde/testdata/BuildCancelling/A4.aj create mode 100644 ajde/testdata/BuildCancelling/Cl1.java create mode 100644 ajde/testdata/BuildCancelling/Cl2.java create mode 100644 ajde/testdata/BuildCancelling/Cl3.java create mode 100644 ajde/testdata/BuildCancelling/EvenMoreCode.lst create mode 100644 ajde/testdata/BuildCancelling/HW.java create mode 100644 ajde/testdata/BuildCancelling/LoadsaCode.lst create mode 100644 ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java diff --git a/ajde/src/org/aspectj/ajde/internal/BuildNotifierAdapter.java b/ajde/src/org/aspectj/ajde/internal/BuildNotifierAdapter.java index e1288e293..37a25f404 100644 --- a/ajde/src/org/aspectj/ajde/internal/BuildNotifierAdapter.java +++ b/ajde/src/org/aspectj/ajde/internal/BuildNotifierAdapter.java @@ -16,7 +16,6 @@ package org.aspectj.ajde.internal; import org.aspectj.ajde.Ajde; import org.aspectj.ajde.BuildProgressMonitor; import org.aspectj.ajdt.internal.core.builder.AjBuildManager; -import org.aspectj.bridge.AbortException; import org.aspectj.bridge.IProgressListener; public class BuildNotifierAdapter implements IProgressListener { @@ -50,4 +49,12 @@ public class BuildNotifierAdapter implements IProgressListener { progressMonitor.setProgressText(text); } + public void setCancelledRequested(boolean cancelRequested) { + this.cancelRequested = cancelRequested; + } + + public boolean isCancelledRequested() { + return cancelRequested; + } + } diff --git a/ajde/testdata/BuildCancelling/A1.aj b/ajde/testdata/BuildCancelling/A1.aj new file mode 100644 index 000000000..1245cfff1 --- /dev/null +++ b/ajde/testdata/BuildCancelling/A1.aj @@ -0,0 +1,9 @@ + +public aspect A1 { + + pointcut m1(): execution(* main(..)); + + before(): m1() { + System.err.println("Before main runs"); + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/A2.aj b/ajde/testdata/BuildCancelling/A2.aj new file mode 100644 index 000000000..4a2ee8189 --- /dev/null +++ b/ajde/testdata/BuildCancelling/A2.aj @@ -0,0 +1,9 @@ + +public aspect A2 { + + pointcut m1(): execution(* main(..)); + + after(): m1() { + System.err.println("After main runs"); + } +} diff --git a/ajde/testdata/BuildCancelling/A3.aj b/ajde/testdata/BuildCancelling/A3.aj new file mode 100644 index 000000000..d9f7a6888 --- /dev/null +++ b/ajde/testdata/BuildCancelling/A3.aj @@ -0,0 +1,9 @@ + +public aspect A3 { + + pointcut m1(): call(* *print*(..)); + + before(): m1() { + System.err.println("Calling print"); + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/A4.aj b/ajde/testdata/BuildCancelling/A4.aj new file mode 100644 index 000000000..5c475d4f2 --- /dev/null +++ b/ajde/testdata/BuildCancelling/A4.aj @@ -0,0 +1,9 @@ + +public aspect A4 { + + pointcut m1(): call(* *print*(..)); + + after(): m1() { + System.err.println("After call to print"); + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/Cl1.java b/ajde/testdata/BuildCancelling/Cl1.java new file mode 100644 index 000000000..7652142c6 --- /dev/null +++ b/ajde/testdata/BuildCancelling/Cl1.java @@ -0,0 +1,4 @@ +public class Cl1 { + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/Cl2.java b/ajde/testdata/BuildCancelling/Cl2.java new file mode 100644 index 000000000..8ba3e49ed --- /dev/null +++ b/ajde/testdata/BuildCancelling/Cl2.java @@ -0,0 +1,4 @@ +public class Cl2 { + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/Cl3.java b/ajde/testdata/BuildCancelling/Cl3.java new file mode 100644 index 000000000..0b3b301df --- /dev/null +++ b/ajde/testdata/BuildCancelling/Cl3.java @@ -0,0 +1,4 @@ +public class Cl3 { + public static void callPrint(String s) { + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/EvenMoreCode.lst b/ajde/testdata/BuildCancelling/EvenMoreCode.lst new file mode 100644 index 000000000..cfd1cee3e --- /dev/null +++ b/ajde/testdata/BuildCancelling/EvenMoreCode.lst @@ -0,0 +1,10 @@ +A1.aj +Cl1.java +A2.aj +Cl2.java +HW.java +A3.aj +Cl3.java +A4.aj +-verbose +-noExit diff --git a/ajde/testdata/BuildCancelling/HW.java b/ajde/testdata/BuildCancelling/HW.java new file mode 100644 index 000000000..3f8aaf831 --- /dev/null +++ b/ajde/testdata/BuildCancelling/HW.java @@ -0,0 +1,13 @@ + +public class HW { + public static void main(String[] args) { + callPrint("Hello"); + callPrint(" "); + callPrint("World"); + callPrint("\n"); + } + + public static void callPrint(String s) { + System.out.print(s); + } +} \ No newline at end of file diff --git a/ajde/testdata/BuildCancelling/LoadsaCode.lst b/ajde/testdata/BuildCancelling/LoadsaCode.lst new file mode 100644 index 000000000..e313f343d --- /dev/null +++ b/ajde/testdata/BuildCancelling/LoadsaCode.lst @@ -0,0 +1,7 @@ +A1.aj +A2.aj +HW.java +A3.aj +A4.aj +-verbose +-noExit diff --git a/ajde/testsrc/org/aspectj/ajde/AjdeTests.java b/ajde/testsrc/org/aspectj/ajde/AjdeTests.java index ecd8471ce..b66c019ed 100644 --- a/ajde/testsrc/org/aspectj/ajde/AjdeTests.java +++ b/ajde/testsrc/org/aspectj/ajde/AjdeTests.java @@ -35,6 +35,7 @@ public class AjdeTests extends TestCase { suite.addTestSuite(ResourceCopyTestCase.class); suite.addTestSuite(ModelPerformanceTest.class); suite.addTestSuite(SavedModelConsistencyTest. class); + suite.addTestSuite(BuildCancellingTest.class); suite.addTestSuite(JarManifestTest.class); //$JUnit-END$ diff --git a/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java b/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java new file mode 100644 index 000000000..5d07718e1 --- /dev/null +++ b/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java @@ -0,0 +1,410 @@ +/* ******************************************************************* + * Copyright (c) 2004 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Andy Clement Initial version + * ******************************************************************/ + +package org.aspectj.ajde; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.ajde.internal.CompilerAdapter; +import org.aspectj.util.FileUtil; + +/** + * It is now possible to cancel the compiler during either the + * compilation or weaving phases - this testcase verifies a few + * cases, making sure the process stops when expected. It can + * check the disk contents, but it doesn't right now. + * + * Two different .lst files are used during these tests: LoadsaCode.lst and + * EvenMoreCode.lst which contain mixes of aspects and classes + * + * Here are some things to think about that will help you understand what is + * on the disk when we cancel the compiler. + * + * There are 3 important phases worth remembering : + * - Compile all the types + * - Weave all the aspects + * - Weave all the classes + * + * Each of those steps goes through all the types. This + * means during the 'weave all the aspects' step we are + * jumping over classes and during the 'weave all the + * classes ' step we are jumping over aspects. Why is this important? + * + * + * We only write bytes out during the 'weave all the classes ' phase and it is even + * during that phase that we write out the bytes for aspects. This means if you cancel + * during compilation or during the weaving of aspects - there will be nothing on the + * disk. If you cancel whilst in the 'weave all the classes ' phase then the disk + * will contain anything finished with by the cancellation point. + */ +public class BuildCancellingTest extends AjdeTestCase { + + private CompilerAdapter compilerAdapter; + public static final String PROJECT_DIR = "BuildCancelling"; + public static final String binDir = "bin"; + + public BuildCancellingTest(String arg0) { + super(arg0); + } + + // Ensure the output directory is clean + protected void setUp() throws Exception { + super.setUp(PROJECT_DIR); + FileUtil.deleteContents(openFile(binDir)); + } + + + + /** + * After first compilation message, get it to cancel, there should be one more warning + * message about cancelling the compile and their should be nothing on the disk. + */ + public void testCancelFirstCompile() { + System.out.println("\n\n\ntestCancelFirstCompile: Building with LoadsaCode.lst"); + compilerAdapter = new CompilerAdapter(); + compilerAdapter.showInfoMessages(false); + BuildProgMon programmableBPM = new BuildProgMon(); + + programmableBPM.cancelOn("compiled:",1); // Force a cancel after the first compile occurs + + compilerAdapter.compile( + (String) openFile("LoadsaCode.lst").getAbsolutePath(), + programmableBPM, + false); + + assertTrue("Should have cancelled after first compile?:"+programmableBPM.numCompiledMessages, + programmableBPM.numCompiledMessages==1); + +// Comment out to check the disk contents +// assertTrue("As weaving was cancelled, no files should have been written out, but I found:"+wovenClassesFound(), +// wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Compilation cancelled as requested"); + if (!expectedCancelMessageFound) dumpTaskData(); // Useful for debugging + assertTrue("Failed to get warning message about compilation being cancelled!", expectedCancelMessageFound); + } + + + + /** + * After third compilation message, get it to cancel, there should be one more warning + * message about cancelling the compile and their should be nothing on the disk. + */ + public void testCancelThirdCompile() { + System.out.println("\n\n\ntestCancelThirdCompile: Building with LoadsaCode.lst"); + compilerAdapter = new CompilerAdapter(); + compilerAdapter.showInfoMessages(false); + BuildProgMon programmableBPM = new BuildProgMon(); + + programmableBPM.cancelOn("compiled:",3); // Force a cancel after the third compile occurs + + compilerAdapter.compile( + (String) openFile("LoadsaCode.lst").getAbsolutePath(), + programmableBPM, + false); + + assertTrue("Should have cancelled after third compile?:"+programmableBPM.numCompiledMessages, + programmableBPM.numCompiledMessages==3); + +// Comment out to check the disk contents +// assertTrue("As weaving was cancelled, no files should have been written out, but I found:"+wovenClassesFound(), +// wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Compilation cancelled as requested"); + if (!expectedCancelMessageFound) dumpTaskData(); // Useful for debugging + assertTrue("Failed to get warning message about compilation being cancelled!", expectedCancelMessageFound); + } + + + /** + * After first weave aspect message, get it to cancel, there should be one more warning + * message about cancelling the weave and their should be nothing on the disk. + */ + public void testCancelFirstAspectWeave() { + System.out.println("\n\n\ntestCancelFirstAspectWeave: Building with LoadsaCode.lst"); + compilerAdapter = new CompilerAdapter(); + compilerAdapter.showInfoMessages(false); + BuildProgMon programmableBPM = new BuildProgMon(); + + programmableBPM.cancelOn("woven aspect ",1); // Force a cancel after the first weave aspect occurs + + compilerAdapter.compile((String) openFile("LoadsaCode.lst").getAbsolutePath(),programmableBPM,false); + + assertTrue("Should have cancelled after first aspect weave?:"+programmableBPM.numWovenAspectMessages, + programmableBPM.numWovenAspectMessages==1); + +// Comment out to check the disk contents +// assertTrue("As weaving was cancelled, no files should have been written out?:"+wovenClassesFound(), +// wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) dumpTaskData(); // Useful for debugging + assertTrue("Failed to get warning message about weaving being cancelled!", expectedCancelMessageFound); + } + + + + /** + * After third weave aspect message, get it to cancel, there should be one more warning + * message about cancelling the weave and their should be nothing on the disk. + */ + public void testCancelThirdAspectWeave() { + System.out.println("\n\n\ntestCancelThirdAspectWeave: Building with LoadsaCode.lst"); + compilerAdapter = new CompilerAdapter(); + compilerAdapter.showInfoMessages(false); + + BuildProgMon programmableBPM = new BuildProgMon(); + // Force a cancel after the third weave occurs. + // This should leave two class files on disk - I think? + programmableBPM.cancelOn("woven aspect ",3); + + compilerAdapter.compile( + (String) openFile("LoadsaCode.lst").getAbsolutePath(), + programmableBPM, + false); + + assertTrue("Should have cancelled after third weave?:"+programmableBPM.numWovenAspectMessages, + programmableBPM.numWovenAspectMessages==3); + +// Comment out to check disk contents +// assertTrue("As weaving was cancelled, no files should have been written out?:"+wovenClassesFound(), +// wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) dumpTaskData(); // Useful for debugging + assertTrue("Failed to get warning message about weaving being cancelled!", expectedCancelMessageFound); + + } + + /** + * After first weave class message, get it to cancel, there should be one more + * warning message about cancelling the weave and their should be nothing on the + * disk. + * + * EvenMoreCode.lst contains: + * A1.aj + * Cl1.java + * A2.aj + * Cl2.java + * HW.java + * A3.aj + * Cl3.java + * A4.aj + * + */ + public void testCancelFirstClassWeave() { + System.out.println("testCancelFirstClassWeave: Building with EvenMoreCode.lst"); + compilerAdapter = new CompilerAdapter(); + compilerAdapter.showInfoMessages(false); + BuildProgMon programmableBPM = new BuildProgMon(); + + programmableBPM.cancelOn("woven class",1); + + compilerAdapter.compile( + (String) openFile("EvenMoreCode.lst").getAbsolutePath(), + programmableBPM, + false); + +// Should just be A1 on the disk - uncomment this line to verify that! +// assertTrue("Incorrect disk contents found",diskContents("A1")); + + assertTrue("Should have cancelled after first class weave?:"+programmableBPM.numWovenClassMessages, + programmableBPM.numWovenClassMessages==1); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) dumpTaskData(); // Useful for debugging + assertTrue("Failed to get warning message about weaving being cancelled!", expectedCancelMessageFound); + } + + + /** + * After first weave aspect message, get it to cancel, there should be one more + * warning message about cancelling the weave and their should be nothing on the + * disk. + * + * EvenMoreCode.lst contains: + * A1.aj + * Cl1.java + * A2.aj + * Cl2.java + * HW.java + * A3.aj + * Cl3.java + * A4.aj + * + */ + public void testCancelSecondClassWeave() { + System.out.println("testCancelSecondClassWeave: Building with EvenMoreCode.lst"); + compilerAdapter = new CompilerAdapter(); + compilerAdapter.showInfoMessages(false); + BuildProgMon programmableBPM = new BuildProgMon(); + + programmableBPM.cancelOn("woven class",2); + + compilerAdapter.compile( + (String) openFile("EvenMoreCode.lst").getAbsolutePath(), + programmableBPM, + false); + +// Uncomment this line to verify disk contents +// assertTrue("Incorrect disk contents found",diskContents("A1 Cl1 A2")); + + assertTrue("Should have cancelled after first class weave?:"+programmableBPM.numWovenClassMessages, + programmableBPM.numWovenClassMessages==2); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) dumpTaskData(); // Useful for debugging + assertTrue("Failed to get warning message about weaving being cancelled!", expectedCancelMessageFound); + + } + + + // ---- + // Helper classes and methods + + + private class BuildProgMon implements BuildProgressMonitor { + + public int numWovenClassMessages = 0; + public int numWovenAspectMessages = 0; + public int numCompiledMessages = 0; + + private String programmableString; + private int count; + private List messagesReceived = new ArrayList(); + private int currentVal; + + public void start(String configFile) { + currentVal = 0; + } + + public void cancelOn(String string,int count) { + programmableString = string; + this.count = count; + } + + public void setProgressText(String text) { + String newText = text+" [Percentage="+currentVal+"%]"; + messagesReceived.add(newText); + if (text.startsWith("woven aspect ")) numWovenAspectMessages++; + if (text.startsWith("woven class ")) numWovenClassMessages++; + if (text.startsWith("compiled:")) numCompiledMessages++; + if (programmableString != null + && text.indexOf(programmableString) != -1) { + count--; + if (count==0) { + System.out.println("Just got message '"+newText+"' - asking build to cancel"); + compilerAdapter.requestCompileExit(); + programmableString = null; + } + } + } + + public boolean containsMessage(String prefix,String distinguishingMarks) { + for (Iterator iter = messagesReceived.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + if (element.startsWith(prefix) && + element.indexOf(distinguishingMarks)!=-1) return true; + } + return false; + } + + public void dumpMessages() { + System.out.println("ProgressMonitorMessages"); + for (Iterator iter = messagesReceived.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + System.out.println(element); + } + } + + public void setProgressBarVal(int newVal) { + this.currentVal = newVal; + } + + public void incrementProgressBarVal() { + System.err.println("ipbv"); + } + + public void setProgressBarMax(int maxVal) { + System.err.println("spbm"+maxVal); + } + + public int getProgressBarMax() { + return 100; // Causes setProgressBarVal() to be fed what are effectively percentages + } + + public void finish() { + } + + } + + private boolean diskContents(String shouldExist) { + String[] fullList = new String[] { "A1","A2","A3","A4","Cl1","Cl2","Cl3","HW"}; + boolean isOK = true; + for (int i = 0; i < fullList.length; i++) { + String file = fullList[i]; + if (shouldExist.indexOf(file)!=-1) { + // There should be a class file called this + if (!openFile("bin/"+file+".class").exists()) { + isOK=false; + System.out.println("Couldn't find this expected file: "+file+".class"); + } + } else { + // There should NOT be a class file called this + if (openFile("bin/"+file+".class").exists()) { + isOK=false; + System.out.println("Found this file when not expected: "+file+".class"); + } + } + } + return isOK; + } + + private int wovenClassesFound() { + int found = 0; + File fA1 = openFile("bin/A1.class"); + File fA2 = openFile("bin/A2.class"); + File fA3 = openFile("bin/A3.class"); + File fA4 = openFile("bin/A4.class"); + File fHW = openFile("bin/HW.class"); + + found+=(fA1.exists()?1:0); + found+=(fA2.exists()?1:0); + found+=(fA3.exists()?1:0); + found+=(fA4.exists()?1:0); + found+=(fHW.exists()?1:0); + return found; + } + + + private boolean checkFor(String what) { + List ll = ideManager.getCompilationSourceLineTasks(); + for (Iterator iter = ll.iterator(); iter.hasNext();) { + Object element = (Object) iter.next(); + if (element.toString().indexOf(what) != -1) + return true; + } + return false; + } + + private void dumpTaskData() { + List ll = ideManager.getCompilationSourceLineTasks(); + for (Iterator iter = ll.iterator(); iter.hasNext();) { + Object element = (Object) iter.next(); + System.out.println("RecordedMessage>"+element); + } + } + +} diff --git a/bridge/src/org/aspectj/bridge/IProgressListener.java b/bridge/src/org/aspectj/bridge/IProgressListener.java index 1686c64b0..59d5f3366 100644 --- a/bridge/src/org/aspectj/bridge/IProgressListener.java +++ b/bridge/src/org/aspectj/bridge/IProgressListener.java @@ -26,4 +26,15 @@ public interface IProgressListener { * @param percentDone how much work is completed so far */ public void setProgress(double percentDone); + + /** + * @param cancelRequested true if the caller wants the current compilation to stop asap + */ + public void setCancelledRequested(boolean cancelRequested); + + /** + * @return true if the consumer of the progress info would like the compileation to stop + */ + public boolean isCancelledRequested(); + } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java index d679d12b9..a6eacc40a 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java @@ -21,6 +21,7 @@ import java.util.Map; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHandler; +import org.aspectj.bridge.IProgressListener; import org.aspectj.weaver.bcel.BcelWeaver; import org.aspectj.weaver.bcel.BcelWorld; import org.eclipse.jdt.internal.compiler.CompilationResult; @@ -44,6 +45,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { private boolean reportedErrors; private boolean isXNoWeave; private IIntermediateResultsRequestor intermediateResultsRequestor; + private IProgressListener progressListener; private IOutputClassFileNameProvider outputFileNameProvider; private WeaverMessageHandler weaverMessageHandler; private List /* InterimCompilationResult */ binarySources = new ArrayList(); @@ -73,6 +75,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { BcelWeaver weaver, EclipseFactory eFactory, IIntermediateResultsRequestor intRequestor, + IProgressListener progressListener, IOutputClassFileNameProvider outputFileNameProvider, Map binarySourceEntries, /* fileName |-> List */ Collection /* InterimCompilationResult */ resultSetForFullWeave, @@ -81,6 +84,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { this.isBatchCompile = isBatchCompile; this.weaver = weaver; this.intermediateResultsRequestor = intRequestor; + this.progressListener = progressListener; this.outputFileNameProvider = outputFileNameProvider; this.isXNoWeave = isXNoWeave; this.resultSetForFullWeave = resultSetForFullWeave; @@ -130,6 +134,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { } else { resultsPendingWeave.add(intRes); } + } public void beforeResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) { @@ -212,7 +217,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { addAllKnownClassesToWeaveList(); } - weaver.weave(new WeaverAdapter(this,weaverMessageHandler)); + weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener)); } private void addAllKnownClassesToWeaveList() { diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java index 6eead0082..345b928ad 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java @@ -14,9 +14,12 @@ import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; +import org.aspectj.bridge.IProgressListener; import org.aspectj.weaver.IClassFileProvider; import org.aspectj.weaver.IWeaveRequestor; import org.aspectj.weaver.bcel.UnwovenClassFile; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; /** * @author colyer @@ -32,13 +35,24 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera private InterimCompilationResult nowProcessing; private InterimCompilationResult lastReturnedResult; private WeaverMessageHandler weaverMessageHandler; + private IProgressListener progressListener; private boolean finalPhase = false; + private int localIteratorCounter; + // Fields related to progress monitoring + private int progressMaxTypes; + private String progressPhasePrefix; + private double fromPercent; + private double toPercent = 100.0; + private int progressCompletionCount; + public WeaverAdapter(AjCompilerAdapter forCompiler, - WeaverMessageHandler weaverMessageHandler) { - this.compilerAdapter = forCompiler; + WeaverMessageHandler weaverMessageHandler, + IProgressListener progressListener) { + this.compilerAdapter = forCompiler; this.weaverMessageHandler = weaverMessageHandler; + this.progressListener = progressListener; } /* (non-Javadoc) @@ -46,6 +60,7 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera */ public Iterator getClassFileIterator() { classFileIndex = 0; + localIteratorCounter = 0; nowProcessing = null; lastReturnedResult = null; resultIterator = compilerAdapter.resultsPendingWeave.iterator(); @@ -98,8 +113,10 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera finishedWith(lastReturnedResult); } } + localIteratorCounter++; lastReturnedResult = nowProcessing; weaverMessageHandler.setCurrentResult(nowProcessing.result()); + // weaverMessageHandler.handleMessage(new Message("weaving " + nowProcessing.fileName(),IMessage.INFO, null, null)); return nowProcessing.unwovenClassFiles()[classFileIndex++]; } /* (non-Javadoc) @@ -108,22 +125,50 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera public void remove() { throw new UnsupportedOperationException(); } - + // IWeaveRequestor // ===================================================================================== - + // weave phases as indicated by bcelWeaver... - public void processingReweavableState() {} - public void addingTypeMungers() {} - public void weavingAspects() {} - public void weavingClasses() {finalPhase = true;} + public void processingReweavableState() { + + // progress reporting logic + fromPercent = 50.0; // Assume weaving takes 50% of the progress bar... + recordProgress("processing reweavable state"); + } + + public void addingTypeMungers() { + + // progress reporting logic + // At this point we have completed one iteration through all the classes/aspects + // we'll be dealing with, so let us remember this max value for localIteratorCounter + // (for accurate progress reporting) + recordProgress("adding type mungers"); + progressMaxTypes = localIteratorCounter; + } + + public void weavingAspects() { + + // progress reporting logic + progressPhasePrefix="woven aspect "; + progressCompletionCount=0; // Start counting from *now* + } + + public void weavingClasses() { + finalPhase = true; + + // progress reporting logic + progressPhasePrefix="woven class "; + } public void weaveCompleted() { if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) { finishedWith(lastReturnedResult); } } + + /* (non-Javadoc) * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile) @@ -135,6 +180,20 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera AjClassFile ajcf = new AjClassFile(className.toCharArray(), result.getBytes()); lastReturnedResult.result().record(ajcf.fileName(),ajcf); + + if (progressListener != null) { + progressCompletionCount++; + + // Smoothly take progress from 'fromPercent' to 'toPercent' + recordProgress( + fromPercent + +((progressCompletionCount/(double)progressMaxTypes)*(toPercent-fromPercent)), + progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")"); + + if (progressListener.isCancelledRequested()) { + throw new AbortCompilation(true,new OperationCanceledException("Weaving cancelled as requested")); + } + } } // helpers... @@ -160,4 +219,17 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera table.remove(victim); } } + + private void recordProgress(String message) { + if (progressListener!=null) { + progressListener.setText(message); + } + } + + private void recordProgress(double percentage,String message) { + if (progressListener!=null) { + progressListener.setProgress(percentage/100); + progressListener.setText(message); + } + } } \ No newline at end of file diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java index f49ea9e3c..dc1eef8f5 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java @@ -31,6 +31,7 @@ import org.aspectj.bridge.*; import org.aspectj.util.FileUtil; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.*; +import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.*; import org.eclipse.jdt.internal.compiler.batch.*; @@ -38,6 +39,7 @@ import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.env.*; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.parser.Parser; +import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; //import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; @@ -158,7 +160,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,ICompilerAda for (int i = 0; (i < 5) && !files.isEmpty(); i++) { // System.err.println("XXXX inc: " + files); performCompilation(files); - if (handler.hasErrors()) { + if (handler.hasErrors() || (progressListener!=null && progressListener.isCancelledRequested())) { return false; } files = state.getFilesToCompile(false); @@ -572,8 +574,11 @@ public class AjBuildManager implements IOutputClassFileNameProvider,ICompilerAda options.produceReferenceInfo(true); //TODO turn off when not needed - compiler.compile(getCompilationUnits(filenames, encodings)); - + try { + compiler.compile(getCompilationUnits(filenames, encodings)); + } catch (OperationCanceledException oce) { + handler.handleMessage(new Message("build cancelled:"+oce.getMessage(),IMessage.WARNING,null,null)); + } // cleanup environment.cleanup(); environment = null; @@ -592,6 +597,11 @@ public class AjBuildManager implements IOutputClassFileNameProvider,ICompilerAda progressListener.setText("compiled: " + result.fileName()); } state.noteResult(result); + + if (progressListener!=null && progressListener.isCancelledRequested()) { + throw new AbortCompilation(true, + new OperationCanceledException("Compilation cancelled as requested")); + } } }; } @@ -853,7 +863,9 @@ public class AjBuildManager implements IOutputClassFileNameProvider,ICompilerAda return new AjCompilerAdapter(forCompiler,batchCompile,bcelWorld,bcelWeaver, factory, - getInterimResultRequestor(),this, + getInterimResultRequestor(), + progressListener, + this, state.binarySourceFiles, state.resultsFromFile.values(), buildConfig.isNoWeave()); -- 2.39.5