@@ -1,4 +1,5 @@ | |||
CalculatePI.java | |||
Logger.aj | |||
-verbose | |||
-noExit | |||
-noExit | |||
-XnotReweavable |
@@ -1,5 +1,4 @@ | |||
CalculatePI.java | |||
Logger.aj | |||
-Xreweavable | |||
-verbose | |||
-noExit |
@@ -1,4 +1,3 @@ | |||
SecondAspect.aj | |||
-Xreweavable | |||
-verbose | |||
-noExit |
@@ -1,3 +1,2 @@ | |||
Logger.aj | |||
-Xreweavable | |||
-verbose |
@@ -1,5 +1,4 @@ | |||
tjp/Demo.java | |||
tjp/GetInfo.java | |||
-Xreweavable | |||
-verbose | |||
-noExit |
@@ -1,3 +1,2 @@ | |||
-Xreweavable | |||
-verbose | |||
-noExit |
@@ -183,7 +183,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { | |||
world.setXlazyTjp(weaverOption.lazyTjp); | |||
world.setXHasMemberSupportEnabled(weaverOption.hasMember); | |||
world.setPinpointMode(weaverOption.pinpoint); | |||
weaver.setReweavableMode(weaverOption.reWeavable, false); | |||
weaver.setReweavableMode(weaverOption.notReWeavable); | |||
world.setXnoInline(weaverOption.noInline); | |||
world.setBehaveInJava5Way(weaverOption.java5);//TODO should be autodetected ? | |||
//-Xlintfile: first so that lint wins |
@@ -35,7 +35,7 @@ public class Options { | |||
private final static String OPTION_noWarnNone = "-warn:none"; | |||
private final static String OPTION_proceedOnError = "-proceedOnError"; | |||
private final static String OPTION_verbose = "-verbose"; | |||
private final static String OPTION_reweavable = "-Xreweavable"; | |||
private final static String OPTION_notReweavable = "-XNotReweavable"; | |||
private final static String OPTION_noinline = "-Xnoinline"; | |||
private final static String OPTION_hasMember = "-XhasMember"; | |||
private final static String OPTION_pinpoint = "-Xdev:pinpoint"; | |||
@@ -91,8 +91,8 @@ public class Options { | |||
weaverOption.noWarn = true; | |||
} else if (arg.equalsIgnoreCase(OPTION_proceedOnError)) { | |||
weaverOption.proceedOnError = true; | |||
} else if (arg.equalsIgnoreCase(OPTION_reweavable)) { | |||
weaverOption.reWeavable = true; | |||
} else if (arg.equalsIgnoreCase(OPTION_notReweavable)) { | |||
weaverOption.notReWeavable = true; | |||
} else if (arg.equalsIgnoreCase(OPTION_showWeaveInfo)) { | |||
weaverOption.showWeaveInfo = true; | |||
} else if (arg.equalsIgnoreCase(OPTION_hasMember)) { | |||
@@ -144,7 +144,7 @@ public class Options { | |||
boolean noWarn; | |||
boolean proceedOnError; | |||
boolean verbose; | |||
boolean reWeavable; | |||
boolean notReWeavable; | |||
boolean noInline; | |||
boolean showWeaveInfo; | |||
boolean pinpoint; |
@@ -525,10 +525,12 @@ public class BuildArgParser extends Main { | |||
} else if (arg.equals("-XlazyTjp")) { | |||
buildConfig.setXlazyTjp(true); | |||
} else if (arg.startsWith("-Xreweavable")) { | |||
buildConfig.setXreweavable(true); | |||
showWarning("-Xreweavable is on by default"); | |||
if (arg.endsWith(":compress")) { | |||
buildConfig.setXreweavableCompressClasses(true); | |||
showWarning("-Xreweavable:compress is no longer available - reweavable is now default"); | |||
} | |||
} else if (arg.startsWith("-XnotReweavable")) { | |||
buildConfig.setXnotReweavable(true); | |||
} else if (arg.equals("-XnoInline")) { | |||
buildConfig.setXnoInline(true); | |||
} else if (arg.equals("-XhasMember")) { |
@@ -123,8 +123,10 @@ xoption.usage = {0} non-standard options:\n\ | |||
\t-XnoInline don't inline advice\n\ | |||
\t-XlazyTjp create thisJoinPoint objects lazily\n\ | |||
\t-Xreweavable create class files that can be subsequently rewoven\n\ | |||
\t by AspectJ\n\ | |||
\t-Xreweavable:compress as above, but also compress the reweaving information\n\ | |||
\t by AspectJ. Deprecated, this is now on by default.\n\ | |||
\t-Xreweavable:compress deprecated, reweavable is now default.\n\ | |||
\t-XnotReweavable create class files that can't be subsequently rewoven\n\ | |||
\t by AspectJ.\n\ | |||
\t-XserializableAspects allows aspects to implement serializable\n\ | |||
\t-XnoWeave compile classes but do not weave. Deprecated, use\n\ | |||
\t reweavable instead.\n\ |
@@ -34,8 +34,7 @@ public class AspectJCore extends JavaCore { | |||
public static final String COMPILER_SERIALIZABLE_ASPECTS = AjCompilerOptions.OPTION_XSerializableAspects; | |||
public static final String COMPILER_LAZY_TJP = AjCompilerOptions.OPTION_XLazyThisJoinPoint; | |||
public static final String COMPILER_NO_ADVICE_INLINE = AjCompilerOptions.OPTION_XNoInline; | |||
public static final String COMPILER_REWEAVABLE = AjCompilerOptions.OPTION_XReweavable; | |||
public static final String COMPILER_REWEAVABLE_COMPRESS = AjCompilerOptions.OPTION_XReweavableCompress; | |||
public static final String COMPILER_NOT_REWEAVABLE = AjCompilerOptions.OPTION_XNotReweavable; | |||
public AspectJCore() { | |||
super(); |
@@ -366,11 +366,8 @@ public class AjBuildConfig { | |||
if (!isXlazyTjp() && global.isXlazyTjp()) { | |||
setXlazyTjp(true); | |||
} | |||
if (!isXreweavable() && global.isXreweavable()) { | |||
setXreweavable(true); | |||
} | |||
if (!getXreweavableCompressClasses() && global.getXreweavableCompressClasses()) { | |||
setXreweavableCompressClasses(true); | |||
if (!isXNotReweavable() && global.isXNotReweavable()) { | |||
setXnotReweavable(true); | |||
} | |||
} | |||
@@ -473,8 +470,8 @@ public class AjBuildConfig { | |||
options.xLazyThisJoinPoint = b; | |||
} | |||
public void setXreweavable(boolean b) { | |||
options.xReweavable = b; | |||
public void setXnotReweavable(boolean b) { | |||
options.xNotReweavable = b; | |||
} | |||
public void setXHasMemberSupport(boolean enabled) { | |||
@@ -492,17 +489,10 @@ public class AjBuildConfig { | |||
public boolean isXdevPinpoint() { | |||
return options.xdevPinpoint; | |||
} | |||
public boolean isXreweavable() { | |||
return options.xReweavable; | |||
} | |||
public void setXreweavableCompressClasses(boolean b) { | |||
options.xReweavableCompress = b; | |||
} | |||
public boolean getXreweavableCompressClasses() { | |||
return options.xReweavableCompress; | |||
public boolean isXNotReweavable() { | |||
return options.xNotReweavable; | |||
} | |||
public boolean isGenerateJavadocsInModelMode() { |
@@ -612,8 +612,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc | |||
} | |||
} | |||
bcelWeaver.setReweavableMode(buildConfig.isXreweavable(),buildConfig.getXreweavableCompressClasses()); | |||
bcelWeaver.setReweavableMode(buildConfig.isXNotReweavable()); | |||
//check for org.aspectj.runtime.JoinPoint | |||
ResolvedType joinPoint = bcelWorld.resolve("org.aspectj.lang.JoinPoint"); |
@@ -40,8 +40,7 @@ public class AjCompilerOptions extends CompilerOptions { | |||
public static final String OPTION_XSerializableAspects = "org.aspectj.ajdt.core.compiler.weaver.XSerializableAspects"; | |||
public static final String OPTION_XLazyThisJoinPoint = "org.aspectj.ajdt.core.compiler.weaver.XLazyThisJoinPoint"; | |||
public static final String OPTION_XNoInline = "org.aspectj.ajdt.core.compiler.weaver.XNoInline"; | |||
public static final String OPTION_XReweavable = "org.aspectj.ajdt.core.compiler.weaver.XReweavable"; | |||
public static final String OPTION_XReweavableCompress = "org.aspectj.ajdt.core.compiler.weaver.XReweavableCompress"; | |||
public static final String OPTION_XNotReweavable = "org.aspectj.ajdt.core.compiler.weaver.XNotReweavable"; | |||
public static final String OPTION_XHasMember = "org.aspectj.ajdt.core.compiler.weaver.XHasMember"; | |||
public static final String OPTION_XdevPinpoint = "org.aspectj.ajdt.core.compiler.weaver.XdevPinpoint"; | |||
@@ -66,8 +65,7 @@ public class AjCompilerOptions extends CompilerOptions { | |||
public boolean xSerializableAspects = false; | |||
public boolean xLazyThisJoinPoint = false; | |||
public boolean xNoInline = false; | |||
public boolean xReweavable = false; | |||
public boolean xReweavableCompress = false; | |||
public boolean xNotReweavable = false; | |||
public boolean xHasMember = false; | |||
public boolean xdevPinpoint = false; | |||
public boolean showWeavingInformation = false; | |||
@@ -121,8 +119,7 @@ public class AjCompilerOptions extends CompilerOptions { | |||
map.put(OPTION_XSerializableAspects,this.xSerializableAspects ? ENABLED : DISABLED); | |||
map.put(OPTION_XLazyThisJoinPoint,this.xLazyThisJoinPoint ? ENABLED : DISABLED); | |||
map.put(OPTION_XNoInline,this.xNoInline ? ENABLED : DISABLED); | |||
map.put(OPTION_XReweavable,this.xReweavable ? ENABLED : DISABLED); | |||
map.put(OPTION_XReweavableCompress,this.xReweavableCompress ? ENABLED : DISABLED); | |||
map.put(OPTION_XNotReweavable,this.xNotReweavable ? ENABLED : DISABLED); | |||
map.put(OPTION_XHasMember, this.xHasMember ? ENABLED : DISABLED); | |||
map.put(OPTION_XdevPinpoint, this.xdevPinpoint ? ENABLED : DISABLED); | |||
@@ -178,13 +175,14 @@ public class AjCompilerOptions extends CompilerOptions { | |||
this.xNoInline = false; | |||
} | |||
} | |||
if ((optionValue = optionsMap.get(OPTION_XReweavable)) != null) { | |||
if ((optionValue = optionsMap.get(OPTION_XNotReweavable)) != null) { | |||
if (ENABLED.equals(optionValue)) { | |||
this.xReweavable = true; | |||
this.xNotReweavable = true; | |||
} else if (DISABLED.equals(optionValue)) { | |||
this.xReweavable = false; | |||
this.xNotReweavable = false; | |||
} | |||
} | |||
/* | |||
if ((optionValue = optionsMap.get(OPTION_XReweavableCompress)) != null) { | |||
if (ENABLED.equals(optionValue)) { | |||
this.xReweavableCompress = true; | |||
@@ -192,6 +190,10 @@ public class AjCompilerOptions extends CompilerOptions { | |||
this.xReweavableCompress = false; | |||
} | |||
} | |||
*/ | |||
if ((optionValue = optionsMap.get(OPTION_XHasMember)) != null) { | |||
if (ENABLED.equals(optionValue)) { | |||
this.xHasMember = true; | |||
@@ -263,8 +265,7 @@ public class AjCompilerOptions extends CompilerOptions { | |||
buf.append("\n\t- no inline (X option): ").append(this.xNoInline ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- generate serializable aspects (X option): ").append(this.xSerializableAspects ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- lazy thisJoinPoint (X option): ").append(this.xLazyThisJoinPoint ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- generate reweavable class files (X option): ").append(this.xReweavable ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- compress reweavable class files (X option): ").append(this.xReweavableCompress ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- generate non-reweavable class files (X option): ").append(this.xNotReweavable ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- has member support (X option): ").append(this.xHasMember ? ENABLED : DISABLED); //$NON-NLS-1$ | |||
buf.append("\n\t- generate AJDE model: ").append(this.generateModel ? ENABLED : DISABLED); //$NON-NLS-1$ |
@@ -162,7 +162,7 @@ public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFacto | |||
myBcelWorld.setPinpointMode(options.xdevPinpoint); | |||
setLintProperties(myBcelWorld,options); | |||
myWeaver = new BcelWeaver(myBcelWorld); | |||
myWeaver.setReweavableMode(options.xReweavable,options.xReweavableCompress); | |||
myWeaver.setReweavableMode(options.xNotReweavable); | |||
// TODO deal with injars, inpath, and aspectpath here... | |||
} | |||
@@ -39,6 +39,7 @@ public class BinaryFormsTestCase extends CommandTestCase { | |||
args.add("-d"); | |||
args.add("out"); | |||
args.add("-XnotReweavable"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/lib/ConcreteA.aj"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/lib/AbstractA.aj"); | |||
@@ -54,6 +55,7 @@ public class BinaryFormsTestCase extends CommandTestCase { | |||
args.add("-d"); | |||
args.add("out"); | |||
args.add("-XnotReweavable"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/client/Client.java"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/client/Client1.java"); | |||
@@ -69,6 +71,7 @@ public class BinaryFormsTestCase extends CommandTestCase { | |||
args.add("-classpath"); | |||
args.add(AjcTests.aspectjrtClasspath()); | |||
args.add("-XnotReweavable"); | |||
args.add("-d"); | |||
args.add("out"); | |||
@@ -89,6 +92,7 @@ public class BinaryFormsTestCase extends CommandTestCase { | |||
args.add("-d"); | |||
args.add("out"); | |||
args.add("-XnotReweavable"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/client/MyAspect1.aj"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/client/Client1.java"); | |||
@@ -101,6 +105,7 @@ public class BinaryFormsTestCase extends CommandTestCase { | |||
args.add("-d"); | |||
args.add("out"); | |||
args.add("-XnotReweavable"); | |||
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/binary/client/Client1.java"); | |||
@@ -40,8 +40,7 @@ public class AjCompilerOptionsTest extends TestCase { | |||
assertFalse(options.xSerializableAspects); | |||
assertFalse(options.xLazyThisJoinPoint); | |||
assertFalse(options.xNoInline); | |||
assertFalse(options.xReweavable); | |||
assertFalse(options.xReweavableCompress); | |||
assertFalse(options.xNotReweavable); | |||
assertFalse(options.generateModel); | |||
assertFalse(options.generateJavaDocsInModel); | |||
assertFalse(options.generateEmacsSymFiles); | |||
@@ -64,8 +63,7 @@ public class AjCompilerOptionsTest extends TestCase { | |||
options.xSerializableAspects = true; | |||
options.xLazyThisJoinPoint = true; | |||
options.xNoInline = true; | |||
options.xReweavable = true; | |||
options.xReweavableCompress = true; | |||
options.xNotReweavable = true; | |||
options.generateModel = true; | |||
options.generateJavaDocsInModel = true; | |||
options.generateEmacsSymFiles = true; | |||
@@ -76,8 +74,7 @@ public class AjCompilerOptionsTest extends TestCase { | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XSerializableAspects)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XLazyThisJoinPoint)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XNoInline)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XReweavable)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XReweavableCompress)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XNotReweavable)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_GenerateModel)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_GenerateJavaDocsInModel)); | |||
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_Emacssym)); | |||
@@ -101,8 +98,7 @@ public class AjCompilerOptionsTest extends TestCase { | |||
map.put(AjCompilerOptions.OPTION_XSerializableAspects,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_XLazyThisJoinPoint,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_XNoInline,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_XReweavable,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_XReweavableCompress,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_XNotReweavable,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_GenerateModel,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_GenerateJavaDocsInModel,CompilerOptions.ENABLED); | |||
map.put(AjCompilerOptions.OPTION_Emacssym,CompilerOptions.ENABLED); | |||
@@ -114,8 +110,7 @@ public class AjCompilerOptionsTest extends TestCase { | |||
assertTrue(options.xSerializableAspects); | |||
assertTrue(options.xLazyThisJoinPoint); | |||
assertTrue(options.xNoInline); | |||
assertTrue(options.xReweavable); | |||
assertTrue(options.xReweavableCompress); | |||
assertTrue(options.xNotReweavable); | |||
assertTrue(options.generateModel); | |||
assertTrue(options.generateJavaDocsInModel); | |||
assertTrue(options.generateEmacsSymFiles); |
@@ -256,7 +256,7 @@ public class AjcTask extends MatchingTask { | |||
static { | |||
String[] xs = new String[] | |||
{ "serializableAspects", "incrementalFile", "lazyTjp", | |||
"reweavable", "reweavable:compress", "noInline" | |||
"reweavable", "reweavable:compress", "notReweavable", "noInline" | |||
//, "targetNearSource", "OcodeSize", | |||
}; | |||
VALID_XOPTIONS = Collections.unmodifiableList(Arrays.asList(xs)); | |||
@@ -467,6 +467,10 @@ public class AjcTask extends MatchingTask { | |||
cmd.addFlag("-Xreweavable",reweavable); | |||
} | |||
public void setXNotReweavable(boolean notReweavable) { | |||
cmd.addFlag("-XnotReweavable",notReweavable); | |||
} | |||
public void setXNoInline(boolean noInline) { | |||
cmd.addFlag("-XnoInline",noInline); | |||
} | |||
@@ -1820,6 +1824,8 @@ public class AjcTask extends MatchingTask { | |||
setXNoweave(true); | |||
} else if ("-Xreweavable".equals(flag)) { | |||
setXReweavable(true); | |||
} else if ("-XnotReweavable".equals(flag)) { | |||
setXNotReweavable(true); | |||
} else if (flag.startsWith("@")) { | |||
File file = new File(flag.substring(1)); | |||
if (file.canRead()) { |
@@ -58,9 +58,7 @@ public class WeaveSpec extends CompileSpec { | |||
setFiles(aspectsFiles); | |||
String options = getOptions(); | |||
if (options == null) { | |||
setOptions("-Xreweavable"); | |||
} else if (options.indexOf("-Xreweavable") == -1) { | |||
setOptions(options + ",-Xreweavable"); | |||
setOptions(""); | |||
} | |||
setClasspath("classes.jar"); | |||
args = buildArgs(); |
@@ -1661,6 +1661,7 @@ public class CompilerRun implements IAjcRun { | |||
factory.create("XnoInline"), | |||
factory.create("XnoWeave"), | |||
factory.create("Xreweavable"), | |||
factory.create("XnotReweavable"), | |||
factory.create("XserializableAspects") | |||
}; | |||
@@ -180,7 +180,6 @@ | |||
keywords="purejava"> | |||
<compile classpath="classesDir,jars/required.jar" | |||
files="Main.java" | |||
options="-Xreweavable" | |||
outjar="main.zip"/> | |||
<compile classpath="classesDir,jars/required.jar" | |||
aspectpath="jars/requiredAspects.jar,jars/AspectMain.jar" | |||
@@ -639,7 +638,7 @@ Also forked/unforked throw different exceptions | |||
keywords="purejava"> | |||
<compile classpath="classesDir,jars/required.jar" | |||
files="Main.java" | |||
options="-Xreweavable" | |||
options="" | |||
outjar="main.zip"/> | |||
<run class="Main" fork="true" exception="NoClassDefFoundError"/> | |||
<run class="Main" fork="false" exception="java.lang.ClassNotFoundException"/> |
@@ -23,10 +23,13 @@ public class MainVerboseAndShow { | |||
public static void main(String args[]) throws Throwable { | |||
new MainVerboseAndShow().target(); | |||
if (!MessageHolder.startsAs(Arrays.asList(new String[]{ | |||
"info weaving 'ataspectj/ltwlog/MainVerboseAndShow'", | |||
"info weaver operating in reweavable mode. Need to verify any required types exist.", | |||
"weaveinfo Join point 'method-execution(void ataspectj.ltwlog.MainVerboseAndShow.target())' in Type 'ataspectj.ltwlog.MainVerboseAndShow' (MainVerboseAndShow.java:22) advised by before advice from 'ataspectj.ltwlog.Aspect1' (Aspect1.java)", | |||
"info weaving 'ataspectj/ltwlog/Aspect1'"}))) { | |||
"info weaving 'ataspectj/ltwlog/Aspect1'", | |||
"info weaver operating in reweavable mode. Need to verify any required types exist."}))) { | |||
MessageHolder.dump(); | |||
throw new RuntimeException("failed"); | |||
} |
@@ -1,5 +1,5 @@ | |||
<aspectj> | |||
<weaver options="-XmessageHandlerClass:ataspectj.ltwlog.MessageHolder -verbose"/> | |||
<weaver options="-XmessageHandlerClass:ataspectj.ltwlog.MessageHolder -verbose -xNotReweavable"/> | |||
<aspects> | |||
<aspect name="ataspectj.ltwlog.Aspect1"/> | |||
</aspects> |
@@ -163,7 +163,7 @@ | |||
<compile | |||
files="pack/DefineInterface.java, | |||
pack/InterfaceDefinition.java, | |||
pack/MyInterface.java"/> | |||
pack/MyInterface.java" options="-XnotReweavable"/> | |||
<run class="pack.InterfaceDefinition"/> | |||
<compile | |||
includeClassesDir="true" |
@@ -3697,20 +3697,20 @@ | |||
<!-- generics/itds and binary weaving --> | |||
<ajc-test dir="java5/generics/itds/binaryweaving" vm="1.5" title="binary weaving ITDs - A"> | |||
<compile files="TestA_generictype.java" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="TestA_aspect.aj,TestA_class.java" inpath="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="TestA_generictype.java" outjar="code.jar" options="-1.5"/> | |||
<compile files="TestA_aspect.aj,TestA_class.java" inpath="code.jar" options="-1.5"/> | |||
<run class="TestA_class"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/binaryweaving" vm="1.5" title="binary weaving ITDs - B"> | |||
<compile files="TestB_generictype.java" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="TestB_aspect1.aj,TestB_aspect2.aj,TestB_class.java" inpath="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="TestB_generictype.java" outjar="code.jar" options="-1.5"/> | |||
<compile files="TestB_aspect1.aj,TestB_aspect2.aj,TestB_class.java" inpath="code.jar" options="-1.5"/> | |||
<run class="TestB_class"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/binaryweaving" vm="1.5" title="binary weaving ITDs - 1"> | |||
<compile files="BaseClass.java" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="A1.aj" inpath="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="BaseClass.java" outjar="code.jar" options="-1.5"/> | |||
<compile files="A1.aj" inpath="code.jar" options="-1.5"/> | |||
<run class="BaseClass"> | |||
<stderr> | |||
<line text="Advice count=1"/> | |||
@@ -3719,11 +3719,11 @@ | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/binaryweaving" vm="1.5" title="binary weaving ITDs - 2"> | |||
<compile files="BaseClass.java,A1.aj" outjar="code.jar" options="-1.5,-Xreweavable,-showWeaveInfo"> | |||
<compile files="BaseClass.java,A1.aj" outjar="code.jar" options="-1.5,-showWeaveInfo"> | |||
<message kind="weave" text="Type 'BaseClass' (BaseClass.java) has intertyped field from 'A1' (A1.aj:'java.util.List BaseClass.list1')"/> | |||
<message kind="weave" text="Type 'BaseClass' (BaseClass.java:12) advised by after advice from 'A1' (A1.aj:7)"/> | |||
</compile> | |||
<compile files="A2.aj" inpath="code.jar" options="-1.5,-Xreweavable,-showWeaveInfo"> | |||
<compile files="A2.aj" inpath="code.jar" options="-1.5,-showWeaveInfo"> | |||
<message kind="weave" text="Type 'BaseClass' (BaseClass.java) has intertyped field from 'A1' (A1.aj:'java.util.List BaseClass.list1')"/> | |||
<message kind="weave" text="Type 'BaseClass' (BaseClass.java:12) advised by after advice from 'A1' (A1.aj:7)"/> | |||
<message kind="weave" text="Type 'BaseClass' (BaseClass.java) has intertyped field from 'A2' (A2.aj:'java.util.List BaseClass.list2')"/> | |||
@@ -3737,8 +3737,8 @@ | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/binaryweaving" vm="1.5" title="binary weaving ITDs - 3"> | |||
<compile files="BaseClass.java,A1.aj,A2.aj" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="A3.aj" inpath="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="BaseClass.java,A1.aj,A2.aj" outjar="code.jar" options="-1.5"/> | |||
<compile files="A3.aj" inpath="code.jar" options="-1.5"/> | |||
<run class="BaseClass"> | |||
<stderr> | |||
<line text="Advice count=3"/> | |||
@@ -3755,8 +3755,8 @@ | |||
<run class="X1"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods -1binary"> | |||
<compile files="Sub1.java,Super1.java" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="X1.aj,Util.java" inpath="code.jar" options ="-1.5,-Xreweavable"/> | |||
<compile files="Sub1.java,Super1.java" outjar="code.jar" options="-1.5"/> | |||
<compile files="X1.aj,Util.java" inpath="code.jar" options ="-1.5"/> | |||
<run class="X1"/> | |||
</ajc-test> | |||
@@ -3765,8 +3765,8 @@ | |||
<run class="X2"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods -2binary"> | |||
<compile files="Sub2.java,Super2.java" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="X2.aj,Util.java" inpath="code.jar" options ="-1.5,-Xreweavable"/> | |||
<compile files="Sub2.java,Super2.java" outjar="code.jar" options="-1.5"/> | |||
<compile files="X2.aj,Util.java" inpath="code.jar" options ="-1.5"/> | |||
<run class="X2"/> | |||
</ajc-test> | |||
@@ -3775,8 +3775,8 @@ | |||
<run class="X3"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods -3binary"> | |||
<compile files="Sub3.java,Super3.java" outjar="code.jar" options="-1.5,-Xreweavable"/> | |||
<compile files="X3.aj,Util.java" inpath="code.jar" options ="-1.5,-Xreweavable"/> | |||
<compile files="Sub3.java,Super3.java" outjar="code.jar" options="-1.5"/> | |||
<compile files="X3.aj,Util.java" inpath="code.jar" options ="-1.5"/> | |||
<run class="X3"/> | |||
</ajc-test> | |||
@@ -50,7 +50,7 @@ public class AtAjLTWTests extends XMLBasedAjcTestCase { | |||
} | |||
public void testAjcLTWAroundInlineMungerTest_Xreweavable() { | |||
runTest("AjcLTW AroundInlineMungerTest -Xreweavable"); | |||
runTest("AjcLTW AroundInlineMungerTest"); | |||
} | |||
public void testAjcLTWAroundInlineMungerTest() { |
@@ -15,7 +15,7 @@ | |||
<ajc-test dir="java5/ataspectj" title="AjcLTW PerClauseTest -Xreweavable"> | |||
<compile | |||
files="ataspectj/PerClauseTest.java,ataspectj/PerClauseTestAspects.java,ataspectj/TestHelper.java" | |||
options="-1.5 -Xreweavable"/> | |||
options="-1.5"/> | |||
<ant file="ajc-ant.xml" target="ltw.PerClauseTest" verbose="true"/> | |||
</ajc-test> | |||
@@ -45,7 +45,7 @@ | |||
<ajc-test dir="java5/ataspectj" title="AjcLTW AroundInlineMungerTest -Xreweavable"> | |||
<compile | |||
files="ataspectj/AroundInlineMungerTest.java,ataspectj/AroundInlineMungerTestAspects.java,ataspectj/TestHelper.java" | |||
options="-1.5 -Xreweavable"/> | |||
options="-1.5"/> | |||
<ant file="ajc-ant.xml" target="ltw.AroundInlineMungerTest" verbose="true"/> | |||
</ajc-test> | |||
@@ -55,17 +55,17 @@ | |||
options="-1.5 -Xlint:ignore"/> | |||
<compile | |||
files="ataspectj/AroundInlineMungerTest.java,ataspectj/TestHelper.java" | |||
options="-1.5 -Xreweavable"/> | |||
options="-1.5"/> | |||
<ant file="ajc-ant.xml" target="ltw.AroundInlineMungerTest" verbose="true"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="AjcLTW AroundInlineMungerTest -XnoInline -Xreweavable"> | |||
<compile | |||
files="ataspectj/AroundInlineMungerTestAspects.java" | |||
options="-1.5 -Xlint:ignore -XnoInline -Xreweavable"/> | |||
options="-1.5 -Xlint:ignore -XnoInline"/> | |||
<compile | |||
files="ataspectj/AroundInlineMungerTest.java,ataspectj/TestHelper.java" | |||
options="-1.5 -Xreweavable -XnoInline"/> | |||
options="-1.5 -XnoInline"/> | |||
<ant file="ajc-ant.xml" target="ltw.AroundInlineMungerTest" verbose="true"/> | |||
</ajc-test> | |||
@@ -75,7 +75,7 @@ | |||
options="-1.5 -Xlint:ignore"/> | |||
<compile | |||
files="ataspectj/AroundInlineMungerTest2.aj,ataspectj/TestHelper.java" | |||
options="-1.5 -Xreweavable"/> | |||
options="-1.5"/> | |||
<ant file="ajc-ant.xml" target="ltw.AroundInlineMungerTest2" verbose="true"/> | |||
</ajc-test> | |||
@@ -89,7 +89,7 @@ | |||
<ajc-test dir="java5/ataspectj" title="Ajc Aspect1 LTW Aspect2 -Xreweavable"> | |||
<compile | |||
files="ataspectj/ltwreweavable/Main.java,ataspectj/ltwreweavable/Aspect1.java,ataspectj/ltwreweavable/Advisable.java" | |||
options="-1.5 -Xreweavable" | |||
options="-1.5" | |||
outjar="main1.jar"/> | |||
<ant file="ajc-ant.xml" target="ltw.Aspect2MainTest" verbose="true"/> | |||
</ajc-test> |
@@ -56,7 +56,7 @@ | |||
<ajc-test dir="incremental/model/weaving2" | |||
title="Testing incremental structure model: Weaving handlers" | |||
keywords="incremental-test,model-test" > | |||
<compile staging="true" options="-incremental,-emacssym" sourceroots="src"/> | |||
<compile staging="true" options="-incremental,-emacssym, -XnotReweavable" sourceroots="src"/> | |||
<inc-compile tag="20" checkModel="code=1,advice=1,RelationshipMapSize=2"/> <!-- BetaA has a new piece of handler advice added --> | |||
<inc-compile tag="30" checkModel="code=1,advice=2,RelationshipMapSize=3"/> <!-- secondary.GammaA added, also advises the same handler --> | |||
<inc-compile tag="40" checkModel="code=1,advice=1,RelationshipMapSize=2"/> <!-- primary.BetaA deleted --> | |||
@@ -87,7 +87,7 @@ | |||
<ajc-test dir="incremental/model/sourcefiles_addremove" | |||
title="Testing incremental structure model: Adding and removing files" | |||
keywords="incremental-test,model-test" > | |||
<compile staging="true" options="-incremental,-emacssym" sourceroots="src"/> | |||
<compile staging="true" options="-incremental,-emacssym, -XnotReweavable" sourceroots="src"/> | |||
<!-- On first compile, two source files in model, 'root' and 'Alpha' --> | |||
<inc-compile tag="20" checkModel="java source file=3,FileMapSize=2"/> <!-- Adds primary.Beta class --> | |||
<inc-compile tag="30" checkModel="java source file=4"/> <!-- Adds secondary.Gamma aspect --> |
@@ -13,6 +13,8 @@ | |||
package org.aspectj.weaver; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
@@ -25,12 +27,10 @@ import java.util.List; | |||
import java.util.Set; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipInputStream; | |||
import java.util.zip.ZipOutputStream; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.weaver.bcel.BcelTypeMunger; | |||
/** | |||
* WeaverStateInfo represents how a type was processed. It is used by the weaver to determine how a type | |||
* was previously treated and whether reweaving is allowed. | |||
@@ -51,31 +51,48 @@ public class WeaverStateInfo { | |||
private List/*Entry*/ typeMungers; | |||
private boolean oldStyle; | |||
private boolean reweavable; | |||
private boolean reweavableCompressedMode; // If true, unwovenClassFile is compressed on write and uncompressed on read | |||
private boolean reweavableCompressedMode; // If true, unwovenClassFile is uncompressed on read | |||
private boolean reweavableDiffMode; // if true, unwovenClassFile is written and read as a diff | |||
private Set /*String*/ aspectsAffectingType; // These must exist in the world for reweaving to be valid | |||
private byte[] unwovenClassFile; // Original 'untouched' class file | |||
private static boolean reweavableDefault = false; | |||
private static boolean reweavableDefault = true; // ajh02: changed from false; | |||
private static boolean reweavableCompressedModeDefault = false; | |||
private static boolean reweavableDiffModeDefault = true; | |||
// when serializing the WeaverStateInfo we come to adding the reweavable data, | |||
// we'd like to add a diff of the unwovenClassFile and the wovenClassFile, | |||
// but we don't have the wovenClassFile yet as we're still in the process of making it. | |||
// so we put this key there instead as a stub. | |||
// Then when the wovenClassFile has been made, replaceKeyWithDiff is called. | |||
private static byte [] key = { | |||
-51, 34, 105, 56, -34, 65, 45, 78, -26, 125, 114, 97, 98, 1, -1, -42 | |||
}; | |||
private boolean unwovenClassFileIsADiff = false; | |||
public WeaverStateInfo() { | |||
this(new ArrayList(), false,reweavableDefault,reweavableCompressedModeDefault); | |||
this(new ArrayList(), false,reweavableDefault,reweavableCompressedModeDefault,reweavableDiffModeDefault); | |||
} | |||
private WeaverStateInfo(List typeMungers, boolean oldStyle,boolean reweavableMode,boolean reweavableCompressedMode) { | |||
public WeaverStateInfo(boolean reweavable) { | |||
this(new ArrayList(), false,reweavable,reweavableCompressedModeDefault,reweavableDiffModeDefault); | |||
} | |||
private WeaverStateInfo(List typeMungers, boolean oldStyle,boolean reweavableMode,boolean reweavableCompressedMode,boolean reweavableDiffMode) { | |||
this.typeMungers = typeMungers; | |||
this.oldStyle = oldStyle; | |||
this.reweavable = reweavableMode; | |||
this.reweavableCompressedMode = reweavableCompressedMode; | |||
this.reweavableDiffMode = reweavableMode?reweavableDiffMode:false; | |||
this.aspectsAffectingType= new HashSet(); | |||
this.unwovenClassFile = null; | |||
} | |||
public static void setReweavableModeDefaults(boolean mode, boolean compress) { | |||
public static void setReweavableModeDefaults(boolean mode, boolean compress, boolean diff) { | |||
reweavableDefault = mode; | |||
reweavableCompressedModeDefault = compress; | |||
reweavableDiffModeDefault = diff; | |||
} | |||
private static final int UNTOUCHED=0, WOVEN=2, EXTENDED=3; | |||
@@ -83,21 +100,32 @@ public class WeaverStateInfo { | |||
// Use 'bits' for these capabilities - only valid in EXTENDED mode | |||
private static final byte REWEAVABLE_BIT = 1<<4; | |||
private static final byte REWEAVABLE_COMPRESSION_BIT = 1<<5; | |||
private static final byte REWEAVABLE_DIFF_BIT = 1<<6; | |||
/** See comments on write() */ | |||
public static final WeaverStateInfo read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
byte b = s.readByte(); | |||
boolean isReweavable = ((b&REWEAVABLE_BIT)!=0); | |||
if (isReweavable) b=(byte) (b-REWEAVABLE_BIT); | |||
if (isReweavable){ | |||
b=(byte) (b-REWEAVABLE_BIT); | |||
} | |||
boolean isReweavableCompressed = ((b&REWEAVABLE_COMPRESSION_BIT)!=0); | |||
if (isReweavableCompressed) b=(byte) (b-REWEAVABLE_COMPRESSION_BIT); | |||
if (isReweavableCompressed){ | |||
b=(byte) (b-REWEAVABLE_COMPRESSION_BIT); | |||
} | |||
boolean isReweavableDiff = ((b&REWEAVABLE_DIFF_BIT)!=0); | |||
if (isReweavableDiff){ | |||
b=(byte) (b-REWEAVABLE_DIFF_BIT); | |||
} | |||
switch(b) { | |||
case UNTOUCHED: | |||
throw new RuntimeException("unexpected UNWOVEN"); | |||
case WOVEN: | |||
return new WeaverStateInfo(Collections.EMPTY_LIST, true,isReweavable,isReweavableCompressed); | |||
return new WeaverStateInfo(Collections.EMPTY_LIST, true,isReweavable,isReweavableCompressed,isReweavableDiff); | |||
case EXTENDED: | |||
int n = s.readShort(); | |||
List l = new ArrayList(); | |||
@@ -107,7 +135,7 @@ public class WeaverStateInfo { | |||
ResolvedTypeMunger.read(s, context); | |||
l.add(new Entry(aspectType, typeMunger)); | |||
} | |||
WeaverStateInfo wsi = new WeaverStateInfo(l,false,isReweavable,isReweavableCompressed); | |||
WeaverStateInfo wsi = new WeaverStateInfo(l,false,isReweavable,isReweavableCompressed,isReweavableDiff); | |||
readAnyReweavableData(wsi,s); | |||
return wsi; | |||
} | |||
@@ -129,13 +157,28 @@ public class WeaverStateInfo { | |||
} | |||
} | |||
/** | |||
* Serialize the WeaverStateInfo. Various bits are set within the 'kind' flag to indicate the structure of | |||
* the attribute. In reweavable diff mode a 'marker' is inserted at the start of the attribute to indicate | |||
* where the final calculated diff should be inserted. When the key is replaced with the diff, the 'kind' | |||
* byte moves to the front of the attribute - thats why in the read logic you'll see it expecting the | |||
* kind as the first byte. | |||
*/ | |||
public void write(DataOutputStream s) throws IOException { | |||
if (oldStyle) throw new RuntimeException("shouldn't be writing this"); | |||
if (oldStyle || reweavableCompressedMode) { | |||
throw new RuntimeException("shouldn't be writing this"); | |||
} | |||
byte weaverStateInfoKind = EXTENDED; | |||
if (reweavable) weaverStateInfoKind |= REWEAVABLE_BIT; | |||
if (reweavableCompressedMode) weaverStateInfoKind |= REWEAVABLE_COMPRESSION_BIT; | |||
if (reweavableDiffMode){ | |||
s.write(key); // put key in so we can replace it with the diff later | |||
weaverStateInfoKind |= REWEAVABLE_DIFF_BIT; | |||
} | |||
s.writeByte(weaverStateInfoKind); | |||
int n = typeMungers.size(); | |||
s.writeShort(n); | |||
for (int i=0; i < n; i++) { | |||
@@ -176,10 +219,14 @@ public class WeaverStateInfo { | |||
public boolean isOldStyle() { | |||
return oldStyle; | |||
} | |||
public byte[] getUnwovenClassFileData() { | |||
public byte[] getUnwovenClassFileData(byte wovenClassFile[]) { | |||
if (unwovenClassFileIsADiff){ | |||
unwovenClassFile = applyDiff(wovenClassFile, unwovenClassFile); | |||
unwovenClassFileIsADiff = false; | |||
} | |||
return unwovenClassFile; | |||
} | |||
} | |||
public void setUnwovenClassFileData(byte[] data) { | |||
unwovenClassFile = data; | |||
@@ -189,9 +236,8 @@ public class WeaverStateInfo { | |||
return reweavable; | |||
} | |||
public void setReweavable(boolean rw,boolean compressData) { | |||
public void setReweavable(boolean rw) { | |||
reweavable = rw; | |||
reweavableCompressedMode = compressData; | |||
} | |||
public void addAspectsAffectingType(Collection /*String*/ aspects) { | |||
@@ -204,11 +250,8 @@ public class WeaverStateInfo { | |||
return this.aspectsAffectingType; | |||
} | |||
//// | |||
private static void readAnyReweavableData(WeaverStateInfo wsi,DataInputStream s) throws IOException { | |||
if (wsi.isReweavable()) { | |||
// Load list of aspects that need to exist in the world for reweaving to be 'legal' | |||
int numberAspectsAffectingType = s.readShort(); | |||
@@ -216,18 +259,9 @@ public class WeaverStateInfo { | |||
int unwovenClassFileSize = s.readInt(); | |||
byte[] classData = null; | |||
// The data might or might not be compressed: | |||
if (!wsi.reweavableCompressedMode) { | |||
// Read it straight in | |||
classData = new byte[unwovenClassFileSize]; | |||
int bytesread = s.read(classData); | |||
if (bytesread!=unwovenClassFileSize) | |||
throw new IOException("ERROR whilst reading reweavable data, expected "+ | |||
unwovenClassFileSize+" bytes, only found "+bytesread); | |||
} else { | |||
// Decompress it | |||
classData = new byte[unwovenClassFileSize]; | |||
// the unwovenClassFile may have been compressed: | |||
if (wsi.reweavableCompressedMode) { | |||
classData = new byte[unwovenClassFileSize]; | |||
ZipInputStream zis = new ZipInputStream(s); | |||
ZipEntry zen = zis.getNextEntry(); | |||
int current = 0; | |||
@@ -239,13 +273,191 @@ public class WeaverStateInfo { | |||
} | |||
zis.closeEntry(); | |||
if (bytesToGo!=0) | |||
throw new IOException("ERROR whilst reading compressed reweavable data, expected "+ | |||
unwovenClassFileSize+" bytes, only found "+current); | |||
throw new IOException("ERROR whilst reading compressed reweavable data, expected "+ | |||
unwovenClassFileSize+" bytes, only found "+current); | |||
} else { | |||
classData = new byte[unwovenClassFileSize]; | |||
int bytesread = s.read(classData); | |||
if (bytesread!=unwovenClassFileSize) | |||
throw new IOException("ERROR whilst reading reweavable data, expected "+ | |||
unwovenClassFileSize+" bytes, only found "+bytesread); | |||
} | |||
// if it was diffMode we'll have to remember to apply the diff if someone | |||
// asks for the unwovenClassFile | |||
wsi.unwovenClassFileIsADiff = wsi.reweavableDiffMode; | |||
wsi.setUnwovenClassFileData(classData); | |||
} | |||
} | |||
/** | |||
* Here is the cleverness for reweavable diff mode. The class file on disk contains, inside the weaverstateinfo attribute, a diff | |||
* that can be applied to 'itself' to recover the original class - which can then be rewoven. | |||
*/ | |||
public byte[] replaceKeyWithDiff(byte wovenClassFile[]) { | |||
// we couldn't have made the diff earlier | |||
// as we didn't have the wovenClassFile | |||
// so we left a key there as a marker to come back to | |||
if (reweavableDiffMode){ | |||
ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(); | |||
DataOutputStream s = new DataOutputStream(arrayStream); | |||
int endOfKey = findEndOfKey(wovenClassFile); | |||
int startOfKey = endOfKey - key.length; | |||
// the length of the wsi attribute is written infront of it in the classFile, | |||
// swapping the diff for the key will probably change the length of the wsi, | |||
// so we'll have to fiddle with the four 'int length' bytes | |||
int oldLengthLocation = startOfKey -4; | |||
int oldLength = readInt(wovenClassFile, oldLengthLocation); | |||
wovenClassFile = deleteInArray(wovenClassFile,startOfKey,endOfKey); // delete the key | |||
byte [] wovenClassFileUpToWSI = new byte [oldLengthLocation]; | |||
System.arraycopy(wovenClassFile,0,wovenClassFileUpToWSI,0,oldLengthLocation); | |||
byte [] diff = generateDiff(wovenClassFileUpToWSI, unwovenClassFile); | |||
try { // put the length of the diff infront of the diff | |||
s.writeInt(diff.length); | |||
s.write(diff); | |||
} catch(IOException e){} | |||
diff = arrayStream.toByteArray(); | |||
// we have to swap the oldLength for the new one, | |||
// and add the diff, using the oldLength to work out where it should go :) | |||
int newLength = oldLength - key.length + diff.length; | |||
byte newLengthBytes[] = serializeInt(newLength); | |||
// swap in the serialized newLength for the oldOne: | |||
wovenClassFile[oldLengthLocation] = newLengthBytes[0]; | |||
wovenClassFile[oldLengthLocation + 1] = newLengthBytes[1]; | |||
wovenClassFile[oldLengthLocation + 2] = newLengthBytes[2]; | |||
wovenClassFile[oldLengthLocation + 3] = newLengthBytes[3]; | |||
// add the diff | |||
wovenClassFile = insertArray(diff, wovenClassFile, oldLengthLocation + 4 + oldLength - key.length); | |||
} | |||
return wovenClassFile; | |||
} | |||
private static final int findEndOfKey(byte [] wovenClassFile){ | |||
// looks through the classfile backwards (as the attributes are all near the end) | |||
for(int i = wovenClassFile.length - 1; i > 0; i--) | |||
if(endOfKeyHere(wovenClassFile, i)){ | |||
return i + 1; | |||
} | |||
throw new RuntimeException("key not found in wovenClassFile"); // should never happen | |||
} | |||
private static final boolean endOfKeyHere(byte lookIn[], int i){ | |||
for(int j = 0; j < key.length; j++) | |||
if(key[key.length - 1 - j] != lookIn[i - j]){ | |||
return false; | |||
} | |||
return true; | |||
} | |||
private static final byte[] insertArray(byte toInsert[], byte original[], int offset){ | |||
byte result[] = new byte[original.length + toInsert.length]; | |||
System.arraycopy(original, 0, result, 0, offset); | |||
System.arraycopy(toInsert, 0, result, offset, toInsert.length); | |||
System.arraycopy(original, offset, result, offset + toInsert.length, original.length - offset); | |||
return result; | |||
} | |||
private static final int readInt(byte [] a, int offset){ | |||
ByteArrayInputStream b = new ByteArrayInputStream(a, offset, 4); | |||
DataInputStream d = new DataInputStream(b); | |||
int length = -1; | |||
try{ | |||
length = d.readInt(); | |||
} | |||
catch(IOException e) { | |||
throw(new RuntimeException("readInt called with a bad array or offset")); // should never happen | |||
} | |||
return length; | |||
} | |||
private static final byte[] deleteInArray(byte a[], int start, int end){ | |||
int lengthToDelete = end - start; | |||
byte result[] = new byte[a.length - lengthToDelete]; // make a new array | |||
System.arraycopy(a, 0, result, 0, start); // copy in the bit before the deleted bit | |||
System.arraycopy(a, end, result, start, a.length - end); // copy in the bit after the deleted bit | |||
return result; | |||
} | |||
// ajh02: a quick note about the diff format... | |||
// | |||
// classfiles consist of: | |||
// 8 bytes: magic number and minor and major versions, | |||
// 2 bytes: its constant pool count | |||
// n bytes: the rest of the class file | |||
// | |||
// weaving a classfile never changes the classfile's first 8 bytes, | |||
// and after the constant pool count there's usually a run of bytes that weaving didn't change | |||
// hereafter referred to as the run | |||
// | |||
// so the diff consists of: | |||
// 2 bytes: its constant pool count | |||
// 4 bytes: length of the run | |||
// n bytes: the rest of the unwovenClassFile | |||
byte [] generateDiff(byte [] wovenClassFile, byte [] unWovenClassFile){ | |||
// find how long the run is | |||
int lookingAt = 10; | |||
int shorterLength | |||
=(wovenClassFile.length < unWovenClassFile.length)? wovenClassFile.length:unWovenClassFile.length; | |||
while (lookingAt < shorterLength && (wovenClassFile[lookingAt] == unWovenClassFile[lookingAt])){ | |||
lookingAt++; | |||
} | |||
int lengthInCommon = lookingAt - 10; | |||
byte [] diff = new byte [unWovenClassFile.length - 4 - lengthInCommon]; | |||
// first 2 bytes of the diff are the constant pool count | |||
diff[0] = unWovenClassFile[8]; | |||
diff[1] = unWovenClassFile[9]; | |||
// then 4 bytes saying how long the run is | |||
byte [] lengthInCommonBytes = serializeInt(lengthInCommon); | |||
diff[2] = lengthInCommonBytes[0]; | |||
diff[3] = lengthInCommonBytes[1]; | |||
diff[4] = lengthInCommonBytes[2]; | |||
diff[5] = lengthInCommonBytes[3]; | |||
// then we just dump the rest of the unWovenClassFile verbatim | |||
System.arraycopy(unWovenClassFile,10+lengthInCommon,diff,6,diff.length-6); | |||
return diff; | |||
} | |||
byte [] applyDiff(byte [] wovenClassFile, byte [] diff){ | |||
int lengthInCommon = readInt(diff,2); | |||
byte [] unWovenClassFile = new byte [4 + diff.length + lengthInCommon]; | |||
// copy the first 8 bytes from the wovenClassFile | |||
System.arraycopy(wovenClassFile,0,unWovenClassFile,0,8); | |||
// copy the constant pool count from the diff | |||
unWovenClassFile[8] = diff[0]; | |||
unWovenClassFile[9] = diff[1]; | |||
// copy the run from the wovenClassFile | |||
System.arraycopy(wovenClassFile,10,unWovenClassFile,10,lengthInCommon); | |||
// copy the stuff after the run from the diff | |||
System.arraycopy(diff,6,unWovenClassFile,10+lengthInCommon,diff.length-6); | |||
return unWovenClassFile; | |||
} | |||
private byte [] serializeInt(int i){ | |||
ByteArrayOutputStream bos = new ByteArrayOutputStream(4); | |||
DataOutputStream dos = new DataOutputStream(bos); | |||
try { | |||
dos.writeInt(i); | |||
} catch(IOException e) {} | |||
return bos.toByteArray(); | |||
} | |||
private static void writeAnyReweavableData(WeaverStateInfo wsi,DataOutputStream s) throws IOException { | |||
@@ -259,16 +471,12 @@ public class WeaverStateInfo { | |||
} | |||
} | |||
byte[] data = wsi.unwovenClassFile; | |||
s.writeInt(data.length); | |||
// Do we need to compress the data? | |||
if (!wsi.reweavableCompressedMode) { | |||
// if we're not in diffMode, write the unwovenClassFile now, | |||
// otherwise we'll insert it as a diff later | |||
if (!wsi.reweavableDiffMode) { | |||
s.writeInt(data.length); | |||
s.write(wsi.unwovenClassFile); | |||
} else { | |||
ZipOutputStream zos = new ZipOutputStream(s); | |||
ZipEntry ze = new ZipEntry("data"); | |||
zos.putNextEntry(ze); | |||
zos.write(wsi.unwovenClassFile,0,wsi.unwovenClassFile.length); | |||
zos.closeEntry(); | |||
} | |||
} | |||
} |
@@ -120,7 +120,6 @@ class BcelClassWeaver implements IClassWeaver { | |||
// Static setting across BcelClassWeavers | |||
private static boolean inReweavableMode = false; | |||
private static boolean compressReweavableAttributes = false; | |||
private List addedSuperInitializersAsList = null; // List<IfaceInitList> | |||
@@ -425,17 +424,17 @@ class BcelClassWeaver implements IClassWeaver { | |||
// finally, if we changed, we add in the introduced methods. | |||
if (isChanged) { | |||
clazz.getOrCreateWeaverStateInfo(); | |||
clazz.getOrCreateWeaverStateInfo(inReweavableMode); | |||
weaveInAddedMethods(); // FIXME asc are these potentially affected by declare annotation? | |||
} | |||
if (inReweavableMode || clazz.getType().isAspect()) { | |||
WeaverStateInfo wsi = clazz.getOrCreateWeaverStateInfo(); | |||
if (inReweavableMode) { | |||
WeaverStateInfo wsi = clazz.getOrCreateWeaverStateInfo(true); | |||
wsi.addAspectsAffectingType(aspectsAffectingType); | |||
wsi.setUnwovenClassFileData(ty.getJavaClass().getBytes()); | |||
wsi.setReweavable(true,compressReweavableAttributes); | |||
wsi.setReweavable(true); | |||
} else { | |||
clazz.getOrCreateWeaverStateInfo().setReweavable(false,false); | |||
clazz.getOrCreateWeaverStateInfo(false).setReweavable(false); | |||
} | |||
return isChanged; | |||
@@ -926,7 +925,9 @@ class BcelClassWeaver implements IClassWeaver { | |||
ShadowMunger aMunger = (ShadowMunger) iter2.next(); | |||
if (aMunger instanceof BcelAdvice) { | |||
BcelAdvice bAdvice = (BcelAdvice)aMunger; | |||
aspectsAffectingType.add(bAdvice.getConcreteAspect().getName()); | |||
if(bAdvice.getConcreteAspect() != null){ | |||
aspectsAffectingType.add(bAdvice.getConcreteAspect().getName()); | |||
} | |||
} else { | |||
// It is a 'Checker' - we don't need to remember aspects that only contributed Checkers... | |||
} | |||
@@ -1769,7 +1770,8 @@ class BcelClassWeaver implements IClassWeaver { | |||
shadow.implement(); | |||
CompilationAndWeavingContext.leavingPhase(tok); | |||
} | |||
mg.matchedShadows = null; | |||
int ii = mg.getMaxLocals(); | |||
mg.matchedShadows = null; | |||
} | |||
// ---- | |||
@@ -1787,9 +1789,12 @@ class BcelClassWeaver implements IClassWeaver { | |||
} | |||
// Called by the BcelWeaver to let us know all BcelClassWeavers need to collect reweavable info | |||
public static void setReweavableMode(boolean mode,boolean compress) { | |||
public static void setReweavableMode(boolean mode) { | |||
inReweavableMode = mode; | |||
compressReweavableAttributes = compress; | |||
} | |||
public static boolean getReweavableMode() { | |||
return inReweavableMode; | |||
} | |||
} |
@@ -103,7 +103,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
if (changed && munger.changesPublicSignature()) { | |||
WeaverStateInfo info = | |||
weaver.getLazyClassGen().getOrCreateWeaverStateInfo(); | |||
weaver.getLazyClassGen().getOrCreateWeaverStateInfo(weaver.getReweavableMode()); | |||
info.addConcreteMunger(this); | |||
} | |||
// Whilst type mungers aren't persisting their source locations, we add this relationship during |
@@ -1179,7 +1179,10 @@ public class BcelWeaver implements IWeaver { | |||
} | |||
} | |||
} | |||
classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData())); | |||
// old: | |||
//classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData())); | |||
// new: reweavable default with clever diff | |||
classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes()))); | |||
} else { | |||
classType.resetState(); | |||
} | |||
@@ -1219,7 +1222,7 @@ public class BcelWeaver implements IWeaver { | |||
public UnwovenClassFile[] getClassFilesFor(LazyClassGen clazz) { | |||
List childClasses = clazz.getChildClasses(world); | |||
UnwovenClassFile[] ret = new UnwovenClassFile[1 + childClasses.size()]; | |||
ret[0] = new UnwovenClassFile(clazz.getFileName(),clazz.getJavaClass(world).getBytes()); | |||
ret[0] = new UnwovenClassFile(clazz.getFileName(),clazz.getJavaClassBytesIncludingReweavable(world)); | |||
int index = 1; | |||
for (Iterator iter = childClasses.iterator(); iter.hasNext();) { | |||
UnwovenClassFile.ChildClass element = (UnwovenClassFile.ChildClass) iter.next(); | |||
@@ -1552,10 +1555,10 @@ public class BcelWeaver implements IWeaver { | |||
this.progressPerClassFile = progressPerClassFile; | |||
} | |||
public void setReweavableMode(boolean mode,boolean compress) { | |||
inReweavableMode = mode; | |||
WeaverStateInfo.setReweavableModeDefaults(mode,compress); | |||
BcelClassWeaver.setReweavableMode(mode,compress); | |||
public void setReweavableMode(boolean xNotReweavable) { | |||
inReweavableMode = !xNotReweavable; | |||
WeaverStateInfo.setReweavableModeDefaults(!xNotReweavable,false,true); | |||
BcelClassWeaver.setReweavableMode(!xNotReweavable); | |||
} | |||
public boolean isReweavable() { |
@@ -600,6 +600,18 @@ public final class LazyClassGen { | |||
writeBack(world); | |||
return myGen.getJavaClass(); | |||
} | |||
public byte [] getJavaClassBytesIncludingReweavable(BcelWorld world){ | |||
writeBack(world); | |||
byte [] wovenClassFileData = myGen.getJavaClass().getBytes(); | |||
WeaverStateInfo wsi = myType.getWeaverState();//getOrCreateWeaverStateInfo(); | |||
if(wsi != null && wsi.isReweavable()){ // && !reweavableDataInserted | |||
//reweavableDataInserted = true; | |||
return wsi.replaceKeyWithDiff(wovenClassFileData); | |||
} else{ | |||
return wovenClassFileData; | |||
} | |||
} | |||
public void addGeneratedInner(LazyClassGen newClass) { | |||
classGens.add(newClass); | |||
@@ -749,7 +761,7 @@ public final class LazyClassGen { | |||
} | |||
public boolean isReweavable() { | |||
if (myType.getWeaverState()==null) return false; | |||
if (myType.getWeaverState()==null) return true; | |||
return myType.getWeaverState().isReweavable(); | |||
} | |||
@@ -757,12 +769,11 @@ public final class LazyClassGen { | |||
if (myType.getWeaverState()==null) return null; | |||
return myType.getWeaverState().getAspectsAffectingType(); | |||
} | |||
public WeaverStateInfo getOrCreateWeaverStateInfo() { | |||
public WeaverStateInfo getOrCreateWeaverStateInfo(boolean inReweavableMode) { | |||
WeaverStateInfo ret = myType.getWeaverState(); | |||
if (ret != null) return ret; | |||
ret = new WeaverStateInfo(); | |||
ret = new WeaverStateInfo(inReweavableMode); | |||
myType.setWeaverState(ret); | |||
return ret; | |||
} |
@@ -67,7 +67,7 @@ missingPerClause=expected per clause on super aspect not found on {0} | |||
wrongPerClause=wrong kind of per clause on super, expected {0} but found {1} | |||
# Reweavable messages... | |||
alreadyWoven=class ''{0}'' is already woven and has not been built with -Xreweavable | |||
alreadyWoven=class ''{0}'' is already woven and has not been built in reweavable mode | |||
reweavableMode=weaver operating in reweavable mode. Need to verify any required types exist. | |||
processingReweavable=processing reweavable type {0}: {1} | |||
missingReweavableType=type {0} is needed by reweavable type {1} |