12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925 |
- /* *******************************************************************
- * Copyright (c) 2002-2010 Contributors
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * PARC initial implementation
- * Andy Clement 6Jul05 generics - signature attribute
- * Abraham Nevado
- * ******************************************************************/
-
- package org.aspectj.weaver.bcel;
-
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.lang.reflect.Modifier;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.SortedMap;
- import java.util.TreeMap;
- import java.util.Vector;
-
- import org.aspectj.apache.bcel.Constants;
- import org.aspectj.apache.bcel.classfile.Attribute;
- import org.aspectj.apache.bcel.classfile.ConstantPool;
- import org.aspectj.apache.bcel.classfile.Field;
- import org.aspectj.apache.bcel.classfile.JavaClass;
- import org.aspectj.apache.bcel.classfile.Method;
- import org.aspectj.apache.bcel.classfile.Signature;
- import org.aspectj.apache.bcel.classfile.Synthetic;
- import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
- import org.aspectj.apache.bcel.generic.BasicType;
- import org.aspectj.apache.bcel.generic.ClassGen;
- import org.aspectj.apache.bcel.generic.FieldGen;
- import org.aspectj.apache.bcel.generic.InstructionConstants;
- import org.aspectj.apache.bcel.generic.InstructionFactory;
- import org.aspectj.apache.bcel.generic.InstructionHandle;
- import org.aspectj.apache.bcel.generic.InstructionList;
- import org.aspectj.apache.bcel.generic.ObjectType;
- import org.aspectj.apache.bcel.generic.Type;
- import org.aspectj.bridge.IMessage;
- import org.aspectj.bridge.ISourceLocation;
- import org.aspectj.bridge.SourceLocation;
- import org.aspectj.weaver.AjAttribute;
- import org.aspectj.weaver.AjAttribute.WeaverState;
- import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
- import org.aspectj.weaver.BCException;
- import org.aspectj.weaver.Member;
- import org.aspectj.weaver.MemberKind;
- import org.aspectj.weaver.NameMangler;
- import org.aspectj.weaver.ResolvedMember;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.RuntimeVersion;
- import org.aspectj.weaver.Shadow;
- import org.aspectj.weaver.SignatureUtils;
- import org.aspectj.weaver.TypeVariable;
- import org.aspectj.weaver.UnresolvedType;
- import org.aspectj.weaver.UnresolvedType.TypeKind;
- import org.aspectj.weaver.WeaverMessages;
- import org.aspectj.weaver.WeaverStateInfo;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.bcel.asm.AsmDetector;
- import org.aspectj.weaver.bcel.asm.StackMapAdder;
-
- /**
- * Lazy lazy lazy. We don't unpack the underlying class unless necessary. Things like new methods and annotations accumulate in here
- * until they must be written out, don't add them to the underlying MethodGen! Things are slightly different if this represents an
- * Aspect.
- */
- public final class LazyClassGen {
-
- private static final Type[] ARRAY_7STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
- Type.STRING, Type.STRING, Type.INT };
-
- private static final Type[] ARRAY_8STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
- Type.STRING, Type.STRING, Type.STRING, Type.INT };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_METHOD = new Type[] {
- Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_CONSTRUCTOR = new Type[] {
- Type.STRING, Type.INT, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_CATCHCLAUSE = new Type[] {
- Type.STRING, Type.CLASS, Type.CLASS, Type.STRING, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_FIELD = new Type[] {
- Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_INITIALIZER = new Type[] {
- Type.STRING, Type.INT, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_MONITOR = new Type[] {
- Type.STRING, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_ADVICE = new Type[] {
- Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY,
- Type.CLASS_ARRAY, Type.CLASS, Type.INT
- };
-
-
-
-
-
- private static final int ACC_SYNTHETIC = 0x1000;
-
- private static final String[] NO_STRINGS = new String[0];
-
- int highestLineNumber = 0; // ---- JSR 45 info
-
- private final SortedMap<String, InlinedSourceFileInfo> inlinedFiles = new TreeMap<>();
-
- private boolean regenerateGenericSignatureAttribute = false;
-
- private BcelObjectType myType; // XXX is not set for types we create
- private ClassGen myGen;
- private final ConstantPool cp;
- private final World world;
- private final String packageName = null;
-
- private final List<BcelField> fields = new ArrayList<>();
- private final List<LazyMethodGen> methodGens = new ArrayList<>();
- private final List<LazyClassGen> classGens = new ArrayList<>();
- private final List<AnnotationGen> annotations = new ArrayList<>();
- private int childCounter = 0;
-
- private final InstructionFactory fact;
-
- private boolean isSerializable = false;
- private boolean hasSerialVersionUIDField = false;
- private boolean serialVersionUIDRequiresInitialization = false;
- private long calculatedSerialVersionUID;
- private boolean hasClinit = false;
-
- private ResolvedType[] extraSuperInterfaces = null;
- private ResolvedType superclass = null;
-
- // ---
-
- static class InlinedSourceFileInfo {
- int highestLineNumber;
- int offset; // calculated
-
- InlinedSourceFileInfo(int highestLineNumber) {
- this.highestLineNumber = highestLineNumber;
- }
- }
-
- void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
- InlinedSourceFileInfo info = inlinedFiles.get(fullpath);
- if (info != null) {
- if (info.highestLineNumber < highestLineNumber) {
- info.highestLineNumber = highestLineNumber;
- }
- } else {
- inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
- }
- }
-
- void calculateSourceDebugExtensionOffsets() {
- int i = roundUpToHundreds(highestLineNumber);
- for (InlinedSourceFileInfo element : inlinedFiles.values()) {
- element.offset = i;
- i = roundUpToHundreds(i + element.highestLineNumber);
- }
- }
-
- private static int roundUpToHundreds(int i) {
- return ((i / 100) + 1) * 100;
- }
-
- int getSourceDebugExtensionOffset(String fullpath) {
- return inlinedFiles.get(fullpath).offset;
- }
-
- // private Unknown getSourceDebugExtensionAttribute() {
- // int nameIndex = cp.addUtf8("SourceDebugExtension");
- // String data = getSourceDebugExtensionString();
- // //System.err.println(data);
- // byte[] bytes = Utility.stringToUTF(data);
- // int length = bytes.length;
- //
- // return new Unknown(nameIndex, length, bytes, cp);
- // }
-
- // private LazyClassGen() {}
- // public static void main(String[] args) {
- // LazyClassGen m = new LazyClassGen();
- // m.highestLineNumber = 37;
- // m.inlinedFiles.put("boo/baz/foo.java", new InlinedSourceFileInfo( 83));
- // m.inlinedFiles.put("boo/barz/foo.java", new InlinedSourceFileInfo(292));
- // m.inlinedFiles.put("boo/baz/moo.java", new InlinedSourceFileInfo(128));
- // m.calculateSourceDebugExtensionOffsets();
- // System.err.println(m.getSourceDebugExtensionString());
- // }
-
- // For the entire pathname, we're using package names. This is probably
- // wrong.
- // private String getSourceDebugExtensionString() {
- // StringBuffer out = new StringBuffer();
- // String myFileName = getFileName();
- // // header section
- // out.append("SMAP\n");
- // out.append(myFileName);
- // out.append("\nAspectJ\n");
- // // stratum section
- // out.append("*S AspectJ\n");
- // // file section
- // out.append("*F\n");
- // out.append("1 ");
- // out.append(myFileName);
- // out.append("\n");
- // int i = 2;
- // for (Iterator iter = inlinedFiles.keySet().iterator(); iter.hasNext();) {
- // String element = (String) iter.next();
- // int ii = element.lastIndexOf('/');
- // if (ii == -1) {
- // out.append(i++); out.append(' ');
- // out.append(element); out.append('\n');
- // } else {
- // out.append("+ "); out.append(i++); out.append(' ');
- // out.append(element.substring(ii+1)); out.append('\n');
- // out.append(element); out.append('\n');
- // }
- // }
- // // emit line section
- // out.append("*L\n");
- // out.append("1#1,");
- // out.append(highestLineNumber);
- // out.append(":1,1\n");
- // i = 2;
- // for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
- // InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
- // out.append("1#");
- // out.append(i++); out.append(',');
- // out.append(element.highestLineNumber); out.append(":");
- // out.append(element.offset + 1); out.append(",1\n");
- // }
- // // end section
- // out.append("*E\n");
- // // and finish up...
- // return out.toString();
- // }
-
- // ---- end JSR45-related stuff
-
- /** Emit disassembled class and newline to out */
- public static void disassemble(String path, String name, PrintStream out) throws IOException {
- if (null == out) {
- return;
- }
- // out.println("classPath: " + classPath);
-
- BcelWorld world = new BcelWorld(path);
-
- UnresolvedType ut = UnresolvedType.forName(name);
- ut.setNeedsModifiableDelegate(true);
- LazyClassGen clazz = new LazyClassGen(BcelWorld.getBcelObjectType(world.resolve(ut)));
- clazz.print(out);
- out.println();
- }
-
- public String getNewGeneratedNameTag() {
- return Integer.toString(childCounter++);
- }
-
- // ----
-
- public LazyClassGen(String class_name, String super_class_name, String file_name, int access_flags, String[] interfaces,
- World world) {
- myGen = new ClassGen(class_name, super_class_name, file_name, access_flags, interfaces);
- cp = myGen.getConstantPool();
- fact = new InstructionFactory(myGen, cp);
- regenerateGenericSignatureAttribute = true;
- this.world = world;
- }
-
- public void setMajorMinor(int major, int minor) {
- myGen.setMajor(major);
- myGen.setMinor(minor);
- }
-
- public int getMajor() {
- return myGen.getMajor();
- }
-
- public int getMinor() {
- return myGen.getMinor();
- }
-
- // Non child type, so it comes from a real type in the world.
- public LazyClassGen(BcelObjectType myType) {
- myGen = new ClassGen(myType.getJavaClass());
- cp = myGen.getConstantPool();
- fact = new InstructionFactory(myGen, cp);
- this.myType = myType;
- world = myType.getResolvedTypeX().getWorld();
-
- /* Does this class support serialization */
- if (implementsSerializable(getType())) {
- isSerializable = true;
-
- // ResolvedMember[] fields = getType().getDeclaredFields();
- // for (int i = 0; i < fields.length; i++) {
- // ResolvedMember field = fields[i];
- // if (field.getName().equals("serialVersionUID")
- // && field.isStatic() && field.getType().equals(UnresolvedType.LONG))
- // {
- // hasSerialVersionUIDField = true;
- // }
- // }
- hasSerialVersionUIDField = hasSerialVersionUIDField(getType());
-
- ResolvedMember[] methods = getType().getDeclaredMethods();
- for (ResolvedMember method : methods) {
- if (method.getName().equals("<clinit>")) {
- if (method.getKind() != Member.STATIC_INITIALIZATION) {
- throw new RuntimeException("qui?");
- }
- hasClinit = true;
- }
- }
-
- // Do we need to calculate an SUID and add it?
- if (!getType().isInterface() && !hasSerialVersionUIDField && world.isAddSerialVerUID()) {
- calculatedSerialVersionUID = myGen.getSUID();
- FieldGen fg = new FieldGen(Constants.ACC_PRIVATE | Constants.ACC_FINAL | Constants.ACC_STATIC, BasicType.LONG,
- "serialVersionUID", getConstantPool());
- addField(fg);
- hasSerialVersionUIDField = true;
- serialVersionUIDRequiresInitialization = true;
- // warn about what we've done?
- if (world.getLint().calculatingSerialVersionUID.isEnabled()) {
- world.getLint().calculatingSerialVersionUID.signal(
- new String[] { getClassName(), Long.toString(calculatedSerialVersionUID) + "L" }, null, null);
- }
- }
- }
-
- ResolvedMember[] methods = myType.getDeclaredMethods();
- for (ResolvedMember method : methods) {
- addMethodGen(new LazyMethodGen((BcelMethod) method, this));
- }
-
- // Method[] methods = myGen.getMethods();
- // for (int i = 0; i < methods.length; i++) {
- // addMethodGen(new LazyMethodGen(methods[i], this));
- // }
-
- ResolvedMember[] fields = myType.getDeclaredFields();
- for (ResolvedMember field : fields) {
- this.fields.add((BcelField) field);
- }
- }
-
- public static boolean hasSerialVersionUIDField(ResolvedType type) {
-
- ResolvedMember[] fields = type.getDeclaredFields();
- for (ResolvedMember field : fields) {
- if (field.getName().equals("serialVersionUID") && Modifier.isStatic(field.getModifiers())
- && field.getType().equals(UnresolvedType.LONG)) {
- return true;
- }
- }
-
- return false;
- }
-
- // public void addAttribute(Attribute i) {
- // myGen.addAttribute(i);
- // }
-
- // ----
-
- public String getInternalClassName() {
- return getConstantPool().getConstantString_CONSTANTClass(myGen.getClassNameIndex());
- // getConstantPool().getConstantString(
- // myGen.getClassNameIndex(),
- // Constants.CONSTANT_Class);
-
- }
-
- public String getInternalFileName() {
- String str = getInternalClassName();
- int index = str.lastIndexOf('/');
- if (index == -1) {
- return getFileName();
- } else {
- return str.substring(0, index + 1) + getFileName();
- }
- }
-
- /**
- * Returns the packagename - if its the default package we return an empty string
- */
- public String getPackageName() {
- if (packageName != null) {
- return packageName;
- }
- String str = getInternalClassName();
- int index = str.indexOf("<");
- if (index != -1) {
- str = str.substring(0, index); // strip off the generics guff
- }
- index = str.lastIndexOf("/");
- if (index == -1) {
- return "";
- }
- return str.substring(0, index).replace('/', '.');
- }
-
- public void addMethodGen(LazyMethodGen gen) {
- // assert gen.getClassName() == super.getClassName();
- methodGens.add(gen);
- if (highestLineNumber < gen.highestLineNumber) {
- highestLineNumber = gen.highestLineNumber;
- }
- }
-
- public boolean removeMethodGen(LazyMethodGen gen) {
- return methodGens.remove(gen);
- }
-
- public void addMethodGen(LazyMethodGen gen, ISourceLocation sourceLocation) {
- addMethodGen(gen);
- if (!gen.getMethod().isPrivate()) {
- warnOnAddedMethod(gen.getMethod(), sourceLocation);
- }
- }
-
- public void errorOnAddedField(FieldGen field, ISourceLocation sourceLocation) {
- if (isSerializable && !hasSerialVersionUIDField) {
- getWorld().getLint().serialVersionUIDBroken.signal(
- new String[] { myType.getResolvedTypeX().getName(), field.getName() }, sourceLocation, null);
- }
- }
-
- public void warnOnAddedInterface(String name, ISourceLocation sourceLocation) {
- warnOnModifiedSerialVersionUID(sourceLocation, "added interface " + name);
- }
-
- public void warnOnAddedMethod(Method method, ISourceLocation sourceLocation) {
- warnOnModifiedSerialVersionUID(sourceLocation, "added non-private method " + method.getName());
- }
-
- public void warnOnAddedStaticInitializer(Shadow shadow, ISourceLocation sourceLocation) {
- if (!hasClinit) {
- warnOnModifiedSerialVersionUID(sourceLocation, "added static initializer");
- }
- }
-
- public void warnOnModifiedSerialVersionUID(ISourceLocation sourceLocation, String reason) {
- if (isSerializable && !hasSerialVersionUIDField) {
- getWorld().getLint().needsSerialVersionUIDField.signal(new String[] { myType.getResolvedTypeX().getName().toString(),
- reason }, sourceLocation, null);
- }
- }
-
- public World getWorld() {
- return world;
- }
-
- public List<LazyMethodGen> getMethodGens() {
- return methodGens; // ???Collections.unmodifiableList(methodGens);
- }
-
- public List<BcelField> getFieldGens() {
- return fields;
- }
-
- public boolean fieldExists(String name) {
- // Field[] allFields = myGen.getFields();
- // if (allFields!=null) {
- // for (int i=0;i<allFields.length;i++) {
- // Field f = allFields[i];
- // if (f.getName().equals(name)) {
- // return f;
- // }
- // }
- // }
- for (BcelField f: fields) {
- if (f.getName().equals(name)) {
- return true;
- }
- }
- return false;
- }
-
- private void writeBack(BcelWorld world) {
- if (getConstantPool().getSize() > Short.MAX_VALUE) {
- reportClassTooBigProblem();
- return;
- }
-
- if (annotations.size() > 0) {
- for (AnnotationGen element : annotations) {
- myGen.addAnnotation(element);
- }
- // Attribute[] annAttributes =
- // org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(
- // getConstantPool(),annotations);
- // for (int i = 0; i < annAttributes.length; i++) {
- // Attribute attribute = annAttributes[i];
- // System.err.println("Adding attribute for "+attribute);
- // myGen.addAttribute(attribute);
- // }
- }
-
- // Add a weaver version attribute to the file being produced (if
- // necessary...)
- if (!myGen.hasAttribute("org.aspectj.weaver.WeaverVersion")) {
- myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverVersionInfo(), getConstantPool()));
- }
-
- // see 389678: TODO more finessing possible here?
- if (world.isOverWeaving()) {
- if (myGen.hasAttribute(WeaverState.AttributeName) && myType!=null && myType.getWeaverState() != null) {
- myGen.removeAttribute(myGen.getAttribute(WeaverState.AttributeName));
- myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
- }
- } else {
- if (!myGen.hasAttribute(WeaverState.AttributeName) && myType != null && myType.getWeaverState() != null) {
- myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
- }
- }
-
- // FIXME ATAJ needed only for slow Aspects.aspectOf() - keep or remove
- // make a lot of test fail since the test compare weaved class file
- // based on some test data as text files...
- // if (!myGen.isInterface()) {
- // addAjClassField();
- // }
-
- addAjcInitializers();
-
- // 17Feb05 - ASC - Skip this for now - it crashes IBM 1.4.2 jvms
- // (pr80430). Will be revisited when contents
- // of attribute are confirmed to be correct.
- boolean sourceDebugExtensionSupportSwitchedOn = false;
-
- if (sourceDebugExtensionSupportSwitchedOn) {
- calculateSourceDebugExtensionOffsets();
- }
-
- int len = methodGens.size();
- myGen.setMethods(Method.NoMethods);
-
- for (LazyMethodGen gen : methodGens) {
- // we skip empty clinits
- if (isEmptyClinit(gen)) {
- continue;
- }
- myGen.addMethod(gen.getMethod());
- }
-
- len = fields.size();
- myGen.setFields(Field.NoFields);
- for (int i = 0; i < len; i++) {
- BcelField gen = fields.get(i);
- myGen.addField(gen.getField(cp));
- }
-
- if (sourceDebugExtensionSupportSwitchedOn) {
- if (inlinedFiles.size() != 0) {
- if (hasSourceDebugExtensionAttribute(myGen)) {
- world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45, getFileName()), null,
- null);
- }
- // myGen.addAttribute(getSourceDebugExtensionAttribute());
- }
- }
-
- fixupGenericSignatureAttribute();
- }
-
- /**
- * When working with Java generics, a signature attribute is attached to the type which indicates how it was declared. This
- * routine ensures the signature attribute for the class we are about to write out is correct. Basically its responsibilities
- * are:
- * <ol>
- * <li>
- * Checking whether the attribute needs changing (ie. did weaving change the type hierarchy) - if it did, remove the old
- * attribute
- * <li>
- * Check if we need an attribute at all, are we generic? are our supertypes parameterized/generic?
- * <li>
- * Build the new attribute which includes all typevariable, supertype and superinterface information
- * </ol>
- */
- private void fixupGenericSignatureAttribute() {
-
- if (getWorld() != null && !getWorld().isInJava5Mode()) {
- return;
- }
-
- // TODO asc generics Temporarily assume that types we generate dont need
- // a signature attribute (closure/etc).. will need
- // revisiting no doubt...
- // if (myType == null) {
- // return;
- // }
-
- // 1. Has anything changed that would require us to modify this
- // attribute?
- if (!regenerateGenericSignatureAttribute) {
- return;
- }
-
- // 2. Find the old attribute
- Signature sigAttr = null;
- if (myType != null) { // if null, this is a type built from scratch, it
- // won't already have a sig attribute
- sigAttr = (Signature) myGen.getAttribute("Signature");
- }
-
- // 3. Do we need an attribute?
- boolean needAttribute = false;
- // If we had one before, we definetly still need one as types can't be
- // 'removed' from the hierarchy
- if (sigAttr != null) {
- needAttribute = true;
- }
-
- // check the interfaces
- if (!needAttribute) {
- if (myType != null) {
- ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
- for (ResolvedType typeX : interfaceRTXs) {
- if (typeX.isGenericType() || typeX.isParameterizedType()) {
- needAttribute = true;
- }
- }
- if (extraSuperInterfaces != null) {
- for (ResolvedType interfaceType : extraSuperInterfaces) {
- if (interfaceType.isGenericType() || interfaceType.isParameterizedType()) {
- needAttribute = true;
- }
- }
- }
- }
-
- if (myType == null) {
- ResolvedType superclassRTX = superclass;
- if (superclassRTX != null) {
- if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
- needAttribute = true;
- }
- }
- } else {
- // check the supertype
- ResolvedType superclassRTX = getSuperClass();
- if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
- needAttribute = true;
- }
- }
- }
-
- if (needAttribute) {
- StringBuilder signature = new StringBuilder();
- // first, the type variables...
- if (myType != null) {
- TypeVariable[] tVars = myType.getTypeVariables();
- if (tVars.length > 0) {
- signature.append("<");
- for (TypeVariable variable : tVars) {
- signature.append(variable.getSignatureForAttribute());
- }
- signature.append(">");
- }
- }
- // now the supertype
- String supersig = getSuperClass().getSignatureForAttribute();
- signature.append(supersig);
- if (myType != null) {
- ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
- for (ResolvedType interfaceRTX : interfaceRTXs) {
- String s = interfaceRTX.getSignatureForAttribute();
- signature.append(s);
- }
- if (extraSuperInterfaces != null) {
- for (ResolvedType extraSuperInterface : extraSuperInterfaces) {
- String s = extraSuperInterface.getSignatureForAttribute();
- signature.append(s);
- }
- }
- }
- if (sigAttr != null) {
- myGen.removeAttribute(sigAttr);
- }
- myGen.addAttribute(createSignatureAttribute(signature.toString()));
- }
- }
-
- /**
- * Helper method to create a signature attribute based on a string signature: e.g. "Ljava/lang/Object;LI<Ljava/lang/Double;>;"
- */
- private Signature createSignatureAttribute(String signature) {
- int nameIndex = cp.addUtf8("Signature");
- int sigIndex = cp.addUtf8(signature);
- return new Signature(nameIndex, 2, sigIndex, cp);
- }
-
- /**
- *
- */
- private void reportClassTooBigProblem() {
- // PR 59208
- // we've generated a class that is just toooooooooo big (you've been
- // generating programs
- // again haven't you? come on, admit it, no-one writes classes this big
- // by hand).
- // create an empty myGen so that we can give back a return value that
- // doesn't upset the
- // rest of the process.
- myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(), myGen.getFileName(), myGen.getModifiers(),
- myGen.getInterfaceNames());
- // raise an error against this compilation unit.
- getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG, this.getClassName()),
- new SourceLocation(new File(myGen.getFileName()), 0), null);
- }
-
- private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
- return gen.hasAttribute("SourceDebugExtension");
- }
-
- public JavaClass getJavaClass(BcelWorld world) {
- writeBack(world);
- return myGen.getJavaClass();
- }
-
- public byte[] getJavaClassBytesIncludingReweavable(BcelWorld world) {
- writeBack(world);
- byte[] wovenClassFileData = myGen.getJavaClass().getBytes();
- // At 1.6 stackmaps are optional, whilst at 1.7 and later they
- // are required (unless turning off the verifier)
- if ((myGen.getMajor() == Constants.MAJOR_1_6 && world.shouldGenerateStackMaps()) || myGen.getMajor() > Constants.MAJOR_1_6) {
- if (!AsmDetector.isAsmAround) {
- throw new BCException(
- "Unable to find ASM classes (" + AsmDetector.CLASS_READER + ", " + AsmDetector.CLASS_VISITOR + ") " +
- "for stackmap generation. Stackmap generation for woven code is required to avoid verify errors " +
- "on a Java 1.7 or higher runtime.", AsmDetector.reasonAsmIsMissing
- );
- }
- wovenClassFileData = StackMapAdder.addStackMaps(world, myGen.getClassName(), wovenClassFileData);
- }
-
- WeaverStateInfo wsi = myType.getWeaverState();// getOrCreateWeaverStateInfo();
- if (wsi != null && wsi.isReweavable() && !world.isOverWeaving()) { // && !reweavableDataInserted
- // reweavableDataInserted = true;
- return wsi.replaceKeyWithDiff(wovenClassFileData);
- } else {
- return wovenClassFileData;
- }
- }
-
- public void addGeneratedInner(LazyClassGen newClass) {
- classGens.add(newClass);
- }
-
- public void addInterface(ResolvedType newInterface, ISourceLocation sourceLocation) {
- regenerateGenericSignatureAttribute = true;
-
- if (extraSuperInterfaces == null) {
- extraSuperInterfaces = new ResolvedType[1];
- extraSuperInterfaces[0] = newInterface;
- } else {
- ResolvedType[] x = new ResolvedType[extraSuperInterfaces.length + 1];
- System.arraycopy(extraSuperInterfaces, 0, x, 1, extraSuperInterfaces.length);
- x[0] = newInterface;
- extraSuperInterfaces = x;
- }
- myGen.addInterface(newInterface.getRawName());
- if (!newInterface.equals(UnresolvedType.SERIALIZABLE)) {
- warnOnAddedInterface(newInterface.getName(), sourceLocation);
- }
- }
-
- public void setSuperClass(ResolvedType newSuperclass) {
- regenerateGenericSignatureAttribute = true;
- superclass = newSuperclass;
- // myType.addParent(typeX); // used for the attribute
- if (newSuperclass.getGenericType() != null) {
- newSuperclass = newSuperclass.getGenericType();
- }
- myGen.setSuperclassName(newSuperclass.getName()); // used in the real
- // class data
- }
-
- // public String getSuperClassname() {
- // return myGen.getSuperclassName();
- // }
-
- public ResolvedType getSuperClass() {
- if (superclass != null) {
- return superclass;
- }
- return myType.getSuperclass();
- }
-
- public String[] getInterfaceNames() {
- return myGen.getInterfaceNames();
- }
-
- // non-recursive, may be a bug, ha ha.
- private List<LazyClassGen> getClassGens() {
- List<LazyClassGen> ret = new ArrayList<>();
- ret.add(this);
- ret.addAll(classGens);
- return ret;
- }
-
- public List<UnwovenClassFile.ChildClass> getChildClasses(BcelWorld world) {
- if (classGens.isEmpty()) {
- return Collections.emptyList();
- }
- List<UnwovenClassFile.ChildClass> ret = new ArrayList<>();
- for (LazyClassGen clazz : classGens) {
- byte[] bytes = clazz.getJavaClass(world).getBytes();
- String name = clazz.getName();
- int index = name.lastIndexOf('$');
- // XXX this could be bad, check use of dollar signs.
- name = name.substring(index + 1);
- ret.add(new UnwovenClassFile.ChildClass(name, bytes));
- }
- return ret;
- }
-
- @Override
- public String toString() {
- return toShortString();
- }
-
- public String toShortString() {
- String s = org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getModifiers(), true);
- if (!s.equals("")) {
- s += " ";
- }
- s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getModifiers());
- s += " ";
- s += myGen.getClassName();
- return s;
- }
-
- public String toLongString() {
- ByteArrayOutputStream s = new ByteArrayOutputStream();
- print(new PrintStream(s));
- return new String(s.toByteArray());
- }
-
- public void print() {
- print(System.out);
- }
-
- public void print(PrintStream out) {
- List<LazyClassGen> classGens = getClassGens();
- for (Iterator<LazyClassGen> iter = classGens.iterator(); iter.hasNext();) {
- LazyClassGen element = iter.next();
- element.printOne(out);
- if (iter.hasNext()) {
- out.println();
- }
- }
- }
-
- private void printOne(PrintStream out) {
- out.print(toShortString());
- out.print(" extends ");
- out.print(org.aspectj.apache.bcel.classfile.Utility.compactClassName(myGen.getSuperclassName(), false));
-
- int size = myGen.getInterfaces().length;
-
- if (size > 0) {
- out.print(" implements ");
- for (int i = 0; i < size; i++) {
- out.print(myGen.getInterfaceNames()[i]);
- if (i < size - 1) {
- out.print(", ");
- }
- }
- }
- out.print(":");
- out.println();
- // XXX make sure to pass types correctly around, so this doesn't happen.
- if (myType != null) {
- myType.printWackyStuff(out);
- }
- Field[] fields = myGen.getFields();
- for (Field field : fields) {
- out.print(" ");
- out.println(field);
- }
- List<LazyMethodGen> methodGens = getMethodGens();
- for (Iterator<LazyMethodGen> iter = methodGens.iterator(); iter.hasNext();) {
- LazyMethodGen gen = iter.next();
- // we skip empty clinits
- if (isEmptyClinit(gen)) {
- continue;
- }
- gen.print(out, (myType != null ? myType.getWeaverVersionAttribute() : WeaverVersionInfo.UNKNOWN));
- if (iter.hasNext()) {
- out.println();
- }
- }
- // out.println(" ATTRIBS: " + Arrays.asList(myGen.getAttributes()));
-
- out.println("end " + toShortString());
- }
-
- private boolean isEmptyClinit(LazyMethodGen gen) {
-
- if (!gen.getName().equals("<clinit>")) {
- return false;
- }
- // System.err.println("checking clinig: " + gen);
- InstructionHandle start = gen.getBody().getStart();
- while (start != null) {
- if (Range.isRangeHandle(start) || (start.getInstruction().opcode == Constants.RETURN)) {
- start = start.getNext();
- } else {
- return false;
- }
- }
-
- return true;
- }
-
- public ConstantPool getConstantPool() {
- return cp;
- }
-
- public String getName() {
- return myGen.getClassName();
- }
-
- public boolean isWoven() {
- return myType.getWeaverState() != null;
- }
-
- public boolean isReweavable() {
- if (myType.getWeaverState() == null) {
- return true;
- }
- return myType.getWeaverState().isReweavable();
- }
-
- public Set<String> getAspectsAffectingType() {
- if (myType.getWeaverState() == null) {
- return null;
- }
- return myType.getWeaverState().getAspectsAffectingType();
- }
-
- public WeaverStateInfo getOrCreateWeaverStateInfo(boolean inReweavableMode) {
- WeaverStateInfo ret = myType.getWeaverState();
- if (ret != null) {
- return ret;
- }
- ret = new WeaverStateInfo(inReweavableMode);
- myType.setWeaverState(ret);
- return ret;
- }
-
- public InstructionFactory getFactory() {
- return fact;
- }
-
- public LazyMethodGen getStaticInitializer() {
- for (LazyMethodGen gen : methodGens) {
- // OPTIMIZE persist kind of member into the gen object? for clinit
- if (gen.getName().equals("<clinit>")) {
- return gen;
- }
- }
- LazyMethodGen clinit = new LazyMethodGen(Modifier.STATIC, Type.VOID, "<clinit>", Type.NO_ARGS, NO_STRINGS, this);
- clinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(clinit);
- return clinit;
- }
-
- /**
- * Retrieve the ajc$preClinit method - this method captures any initialization AspectJ wants to ensure happens in a class. It is
- * called from the static initializer. Maintaining this separation enables overweaving to ignore join points added due to
- * earlier weaves. If the ajc$preClinit method cannot be found, it is created and a call to it is placed in the real static
- * initializer (the call is placed at the start of the static initializer).
- *
- * @return the LazyMethodGen representing the ajc$ clinit
- */
- public LazyMethodGen getAjcPreClinit() {
- if (this.isInterface()) {
- throw new IllegalStateException();
- }
- for (LazyMethodGen methodGen : methodGens) {
- if (methodGen.getName().equals(NameMangler.AJC_PRE_CLINIT_NAME)) {
- return methodGen;
- }
- }
- LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
- NameMangler.AJC_PRE_CLINIT_NAME, Type.NO_ARGS, NO_STRINGS, this);
- ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(ajcPreClinit);
- InstructionList clinitBody = getStaticInitializer().getBody();
- clinitBody.insert(Utility.createInvoke(fact, ajcPreClinit));
- if (serialVersionUIDRequiresInitialization) {
- InstructionList il = new InstructionList();
- il.append(InstructionFactory.PUSH(getConstantPool(), calculatedSerialVersionUID));
- il.append(getFactory().createFieldAccess(getClassName(), "serialVersionUID", BasicType.LONG,
- Constants.PUTSTATIC));
- clinitBody.insert(il);
- }
- return ajcPreClinit;
- }
-
- /**
- * factory method for building multiple extended clinit methods. Constructs a new clinit method that invokes the previous one
- * and then returns it. The index is used as a name suffix.
- *
- * @param previousPreClinit
- * @param i
- */
- public LazyMethodGen createExtendedAjcPreClinit(LazyMethodGen previousPreClinit, int i) {
- LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
- NameMangler.AJC_PRE_CLINIT_NAME + i, Type.NO_ARGS, NO_STRINGS, this);
- ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(ajcPreClinit);
- previousPreClinit.getBody().insert(Utility.createInvoke(fact, ajcPreClinit));
- return ajcPreClinit;
- }
-
- //
-
- // reflective thisJoinPoint support
- private Map<BcelShadow, Field> tjpFields = new HashMap<>();
- Map<CacheKey, Field> annotationCachingFieldCache = new HashMap<>();
- private int tjpFieldsCounter = -1; // -1 means not yet initialized
- private int annoFieldsCounter = 0;
- public static final ObjectType proceedingTjpType = new ObjectType("org.aspectj.lang.ProceedingJoinPoint");
- public static final ObjectType tjpType = new ObjectType("org.aspectj.lang.JoinPoint");
- public static final ObjectType staticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
- public static final ObjectType typeForAnnotation = new ObjectType("java.lang.annotation.Annotation");
- public static final ObjectType enclosingStaticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$EnclosingStaticPart");
- private static final ObjectType sigType = new ObjectType("org.aspectj.lang.Signature");
- // private static final ObjectType slType =
- // new ObjectType("org.aspectj.lang.reflect.SourceLocation");
- private static final ObjectType factoryType = new ObjectType("org.aspectj.runtime.reflect.Factory");
- private static final ObjectType classType = new ObjectType("java.lang.Class");
-
- public Field getTjpField(BcelShadow shadow, final boolean isEnclosingJp) {
- Field tjpField = tjpFields.get(shadow);
- if (tjpField != null) {
- return tjpField;
- }
-
- int modifiers = Modifier.STATIC;
-
- // J9: Can't always be final on Java 9 because it is set outside of clinit
- // But must be final in interface
- if (shadow.getEnclosingClass().isInterface()) {
- modifiers |= Modifier.FINAL;
- }
-
- // XXX - Do we ever inline before or after advice? If we do, then we
- // better include them in the check below. (or just change it to
- // shadow.getEnclosingMethod().getCanInline())
-
- // If the enclosing method is around advice, we could inline the join
- // point that has led to this shadow. If we do that then the TJP we are
- // creating here must be PUBLIC so it is visible to the type in which the
- // advice is inlined. (PR71377)
- LazyMethodGen encMethod = shadow.getEnclosingMethod();
- boolean shadowIsInAroundAdvice = false;
- if (encMethod != null && encMethod.getName().startsWith(NameMangler.PREFIX + "around")) {
- shadowIsInAroundAdvice = true;
- }
-
- if (getType().isInterface() || shadowIsInAroundAdvice) {
- modifiers |= Modifier.PUBLIC;
- } else {
- modifiers |= Modifier.PRIVATE;
- }
- ObjectType jpType = null;
- // Did not have different static joinpoint types in 1.2
- if (world.isTargettingAspectJRuntime12()) {
- jpType = staticTjpType;
- } else {
- jpType = isEnclosingJp ? enclosingStaticTjpType : staticTjpType;
- }
- if (tjpFieldsCounter == -1) {
- // not yet initialized, do it now
- if (!world.isOverWeaving()) {
- tjpFieldsCounter = 0;
- } else {
- List<BcelField> existingFields = getFieldGens();
- if (existingFields == null) {
- tjpFieldsCounter = 0;
- } else {
- BcelField lastField = null;
- // OPTIMIZE: go from last to first?
- for (BcelField field : existingFields) {
- if (field.getName().startsWith("ajc$tjp_")) {
- lastField = field;
- }
- }
- if (lastField == null) {
- tjpFieldsCounter = 0;
- } else {
- tjpFieldsCounter = Integer.parseInt(lastField.getName().substring(8)) + 1;
- // System.out.println("tjp counter starting at " + tjpFieldsCounter);
- }
- }
- }
- }
- if (!isInterface() && world.isTransientTjpFields()) {
- modifiers|=Modifier.TRANSIENT;
- }
- FieldGen fGen = new FieldGen(modifiers, jpType, "ajc$tjp_" + tjpFieldsCounter++, getConstantPool());
- addField(fGen);
- tjpField = fGen.getField();
- tjpFields.put(shadow, tjpField);
- return tjpField;
- }
-
- /**
- * Create a field in the type containing the shadow where the annotation retrieved during binding can be stored - for later fast
- * access.
- *
- * @param shadow the shadow at which the @annotation result is being cached
- * @return a field
- */
- public Field getAnnotationCachingField(BcelShadow shadow, ResolvedType toType, boolean isWithin) {
- // Multiple annotation types at a shadow. A different field would be required for each
- CacheKey cacheKey = new CacheKey(shadow, toType, isWithin);
- Field field = annotationCachingFieldCache.get(cacheKey);
- // System.out.println(field + " for shadow " + shadow);
- if (field == null) {
- // private static Annotation ajc$anno$<nnn>
- StringBuilder sb = new StringBuilder();
- sb.append(NameMangler.ANNOTATION_CACHE_FIELD_NAME);
- sb.append(annoFieldsCounter++);
- FieldGen annotationCacheField = new FieldGen(Modifier.PRIVATE | Modifier.STATIC, typeForAnnotation, sb.toString(), cp);
- addField(annotationCacheField);
- field = annotationCacheField.getField();
- annotationCachingFieldCache.put(cacheKey, field);
- }
- return field;
- }
-
- static class CacheKey {
- private Object key;
- private ResolvedType annotationType;
-
- // If the annotation is being accessed via @annotation on a shadow then we can use the shadows toString() (so two shadows
- // the same share a variable), but if it is @withincode() or @within() we can't share them (as the shadows may look the same
- // but be occurring 'within' different things). In the within cases we continue to use the shadow itself as the key.
- CacheKey(BcelShadow shadow, ResolvedType annotationType, boolean isWithin) {
- this.key = isWithin ? shadow : shadow.toString();
- this.annotationType = annotationType;
- }
-
- @Override
- public int hashCode() {
- return key.hashCode() * 37 + annotationType.hashCode();
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof CacheKey)) {
- return false;
- }
- CacheKey oCacheKey = (CacheKey) other;
- return key.equals(oCacheKey.key) && annotationType.equals(oCacheKey.annotationType);
- }
- }
-
- // FIXME ATAJ needed only for slow Aspects.aspectOf - keep or remove
- // private void addAjClassField() {
- // // Andy: Why build it again??
- // Field ajClassField = new FieldGen(
- // Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
- // classType,
- // "aj$class",
- // getConstantPool()).getField();
- // addField(ajClassField);
- //
- // InstructionList il = new InstructionList();
- // il.append(new PUSH(getConstantPool(), getClassName()));
- // il.append(fact.createInvoke("java.lang.Class", "forName", classType,
- // new Type[] {Type.STRING}, Constants.INVOKESTATIC));
- // il.append(fact.createFieldAccess(getClassName(), ajClassField.getName(),
- // classType, Constants.PUTSTATIC));
- //
- // getStaticInitializer().getBody().insert(il);
- // }
-
- private void addAjcInitializers() {
- if (tjpFields.size() == 0 && !serialVersionUIDRequiresInitialization) {
- return;
- }
-
- InstructionList[] il = initializeAllTjps();
-
- LazyMethodGen prevMethod;
- LazyMethodGen nextMethod = null;
- if (this.isInterface()) { // Cannot sneak stuff into another static method in an interface
- prevMethod = getStaticInitializer();
- } else {
- prevMethod = getAjcPreClinit();
- }
- for (int counter = 1; counter <= il.length; counter++) {
- if (il.length > counter) {
- nextMethod = createExtendedAjcPreClinit(prevMethod, counter);
- }
- prevMethod.getBody().insert(il[counter - 1]);
- prevMethod = nextMethod;
- }
- }
-
- private InstructionList initInstructionList() {
- InstructionList list = new InstructionList();
- InstructionFactory fact = getFactory();
-
- // make a new factory
- list.append(fact.createNew(factoryType));
- list.append(InstructionFactory.createDup(1));
-
- list.append(InstructionFactory.PUSH(getConstantPool(), getFileName()));
-
- // load the current Class object
- // XXX check that this works correctly for inners/anonymous
- list.append(fact.PUSHCLASS(cp, myGen.getClassName()));
- // XXX do we need to worry about the fact the theorectically this could
- // throw
- // a ClassNotFoundException
-
- list.append(fact.createInvoke(factoryType.getClassName(), "<init>", Type.VOID, new Type[] { Type.STRING, classType },
- Constants.INVOKESPECIAL));
-
- list.append(InstructionFactory.createStore(factoryType, 0));
- return list;
- }
-
- private InstructionList[] initializeAllTjps() {
- Vector<InstructionList> lists = new Vector<>();
-
- InstructionList list = initInstructionList();
- lists.add(list);
-
- List<Map.Entry<BcelShadow, Field>> entries = new ArrayList<>(tjpFields.entrySet());
- entries.sort(new Comparator<Map.Entry<BcelShadow, Field>>() {
- @Override
- public int compare(Map.Entry<BcelShadow, Field> a, Map.Entry<BcelShadow, Field> b) {
- return (a.getValue()).getName().compareTo((b.getValue()).getName());
- }
- });
-
- long estimatedSize = 0;
- for (Map.Entry<BcelShadow, Field> entry : entries) {
- if (estimatedSize > Constants.MAX_CODE_SIZE) {
- estimatedSize = 0;
- list = initInstructionList();
- lists.add(list);
- }
- estimatedSize += entry.getValue().getSignature().getBytes().length;
- initializeTjp(fact, list, entry.getValue(), entry.getKey());
- }
- InstructionList listArrayModel[] = new InstructionList[1];
- return lists.toArray(listArrayModel);
- }
-
- private void initializeTjp(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
- if (world.getTargetAspectjRuntimeLevel() == RuntimeVersion.V1_9) {
- initializeTjpOptimal(fact, list, field, shadow);
- return;
- }
- boolean fastSJP = false;
- // avoid fast SJP if it is for an enclosing joinpoint
- boolean isFastSJPAvailable = shadow.getWorld().isTargettingRuntime1_6_10()
- && !enclosingStaticTjpType.equals(field.getType());
-
- Member sig = shadow.getSignature();
-
- // load the factory
- list.append(InstructionFactory.createLoad(factoryType, 0));
-
- // load the kind
- list.append(InstructionFactory.PUSH(getConstantPool(), shadow.getKind().getName()));
-
- // create the signature
- if (world.isTargettingAspectJRuntime12() || !isFastSJPAvailable || !sig.getKind().equals(Member.METHOD)) {
- list.append(InstructionFactory.createLoad(factoryType, 0));
- }
-
- String signatureMakerName = SignatureUtils.getSignatureMakerName(sig);
- ObjectType signatureType = new ObjectType(SignatureUtils.getSignatureType(sig));
- UnresolvedType[] exceptionTypes = null;
- if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2
- list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.METHOD)) {
- BcelWorld w = shadow.getWorld();
-
- // For methods, push the parts of the signature on.
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, sig.getName()));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- exceptionTypes = sig.getExceptions(w);
- if (isFastSJPAvailable && exceptionTypes.length == 0) {
- fastSJP = true;
- } else {
- list.append(InstructionFactory.PUSH(cp, makeString(exceptionTypes)));
- }
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
- // And generate a call to the variant of makeMethodSig() that takes the strings
- if (isFastSJPAvailable) {
- fastSJP = true;
- } else {
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY7,
- Constants.INVOKEVIRTUAL));
- }
-
- } else if (sig.getKind().equals(Member.MONITORENTER)) {
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.MONITOREXIT)) {
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.HANDLER)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY3,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
- BcelWorld w = shadow.getWorld();
- if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
- // its the magical new jp
- list.append(InstructionFactory.PUSH(cp, makeString(Modifier.PUBLIC)));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, "")); // sig.getParameterNames?
- list.append(InstructionFactory.PUSH(cp, ""));// sig.getExceptions?
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
- Constants.INVOKEVIRTUAL));
- } else {
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
- Constants.INVOKEVIRTUAL));
- }
- } else if (sig.getKind().equals(Member.FIELD)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, sig.getName()));
- // see pr227401
- UnresolvedType dType = sig.getDeclaringType();
- if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
- dType = sig.getDeclaringType().resolve(world).getGenericType();
- }
- list.append(InstructionFactory.PUSH(cp, makeString(dType)));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY4,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.ADVICE)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, sig.getName()));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
- list.append(InstructionFactory.PUSH(cp, makeString((sig.getReturnType()))));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, new Type[] { Type.STRING,
- Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING }, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY2,
- Constants.INVOKEVIRTUAL));
- } else {
- // TODO looks like this block is unused code
- list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- }
-
- // XXX should load source location from shadow
- list.append(Utility.createConstant(fact, shadow.getSourceLine()));
-
- final String factoryMethod;
-
- // TAG:SUPPORTING12: We didn't have makeESJP() in 1.2
- if (world.isTargettingAspectJRuntime12()) {
- list.append(fact.createInvoke(factoryType.getClassName(), "makeSJP", staticTjpType, new Type[] { Type.STRING, sigType,
- Type.INT }, Constants.INVOKEVIRTUAL));
-
- // put it in the field
- list.append(fact.createFieldAccess(getClassName(), field.getName(), staticTjpType, Constants.PUTSTATIC));
-
- } else {
- if (staticTjpType.equals(field.getType())) {
- factoryMethod = "makeSJP";
- } else if (enclosingStaticTjpType.equals(field.getType())) {
- factoryMethod = "makeESJP";
- } else {
- throw new Error("should not happen");
- }
-
- if (fastSJP) {
- if (exceptionTypes != null && exceptionTypes.length != 0) {
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_8STRING_INT,
- Constants.INVOKEVIRTUAL));
- } else {
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_7STRING_INT,
- Constants.INVOKEVIRTUAL));
- }
- } else {
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), new Type[] { Type.STRING,
- sigType, Type.INT }, Constants.INVOKEVIRTUAL));
- }
-
- // put it in the field
- list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
- }
- }
-
- public String getFactoryMethod(Field field, BcelShadow shadow) {
- StringBuilder b = new StringBuilder();
- b.append("make");
- MemberKind kind = shadow.getSignature().getKind();
- if (kind.equals(Member.METHOD)) {
- b.append("Method");
- } else if (kind.equals(Member.CONSTRUCTOR)) {
- b.append("Constructor");
- } else if (kind.equals(Member.HANDLER)) {
- b.append("CatchClause");
- } else if (kind.equals(Member.FIELD)) {
- b.append("Field");
- } else if (kind.equals(Member.STATIC_INITIALIZATION)) {
- b.append("Initializer");
- } else if (kind.equals(Member.MONITORENTER)) {
- b.append("Lock");
- } else if (kind.equals(Member.MONITOREXIT)) {
- b.append("Unlock");
- } else if (kind.equals(Member.ADVICE)) {
- b.append("Advice");
- } else {
- throw new IllegalStateException(kind.toString());
- }
- if (staticTjpType.equals(field.getType())) {
- b.append("SJP");
- } else if (enclosingStaticTjpType.equals(field.getType())) {
- b.append("ESJP");
- }
- return b.toString();
- }
-
- /**
- * Generate optimal joinpoint initialization code.
- *
- * As of version 1.9.1 the runtime includes new factory methods for joinpoints that take classes, not strings
- * and using them requires different code generation. Using these instead of the old ones means we can avoid
- * deferred classloading for these types. By using the LDC instruction that loads classes, it also means
- * anything modifying woven code and changing type names will also pick up on these references.
- */
- private void initializeTjpOptimal(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
- list.append(InstructionFactory.createLoad(factoryType, 0));
- pushString(list, shadow.getKind().getName());
- String factoryMethod = getFactoryMethod(field, shadow);
- Member sig = shadow.getSignature();
- BcelWorld w = shadow.getWorld();
-
- if (sig.getKind().equals(Member.METHOD)) {
- pushInt(list, sig.getModifiers(w));
- pushString(list, sig.getName());
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, sig.getParameterNames(w));
- pushClasses(list, sig.getExceptions(w));
- pushClass(list, sig.getReturnType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_METHOD, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
- if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
- pushInt(list, Modifier.PUBLIC);
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, null);
- pushClasses(list, null);
- } else {
- pushInt(list, sig.getModifiers(w));
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, sig.getParameterNames(w));
- pushClasses(list, sig.getExceptions(w));
- }
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_CONSTRUCTOR, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.HANDLER)) {
- pushClass(list, sig.getDeclaringType());
- pushClass(list, sig.getParameterTypes()[0]);
- String pname = null;
- String[] pnames = sig.getParameterNames(w);
- if (pnames != null && pnames.length>0) {
- pname = pnames[0];
- }
- pushString(list, pname);
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_CATCHCLAUSE, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.FIELD)) {
- pushInt(list, sig.getModifiers(w));
- pushString(list, sig.getName());
- // see pr227401
- UnresolvedType dType = sig.getDeclaringType();
- if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
- dType = sig.getDeclaringType().resolve(world).getGenericType();
- }
- pushClass(list, dType);
- pushClass(list, sig.getReturnType());
- pushInt(list,shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_FIELD, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
- pushInt(list, sig.getModifiers(w));
- pushClass(list, sig.getDeclaringType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_INITIALIZER, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.MONITORENTER)) {
- pushClass(list, sig.getDeclaringType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.MONITOREXIT)) {
- pushClass(list, sig.getDeclaringType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.ADVICE)) {
- pushInt(list, sig.getModifiers(w));
- pushString(list, sig.getName());
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, sig.getParameterNames(w));
- pushClasses(list, sig.getExceptions(w));
- pushClass(list, sig.getReturnType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_ADVICE, Constants.INVOKEVIRTUAL));
- } else {
- throw new IllegalStateException("not sure what to do: "+shadow);
- }
- list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
- }
-
- private void pushStrings(InstructionList list, String[] strings) {
- // Build an array loaded with the strings
- if (strings == null || strings.length == 0) {
- list.append(InstructionFactory.ACONST_NULL);
- } else {
- list.append(InstructionFactory.PUSH(cp, strings.length));
- list.append(fact.createNewArray(Type.STRING, (short)1));
- for (int s=0;s<strings.length;s++) {
- list.append(InstructionFactory.DUP);
- list.append(InstructionFactory.PUSH(cp, s));
- list.append(InstructionFactory.PUSH(cp, strings[s]));
- list.append(InstructionFactory.AASTORE);
- }
- }
- }
-
- private void pushClass(InstructionList list, UnresolvedType type) {
- if (type.isPrimitiveType()) {
- if (type.getSignature().equals("I")) {
- list.append(fact.createGetStatic("java/lang/Integer","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("D")) {
- list.append(fact.createGetStatic("java/lang/Double","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("S")) {
- list.append(fact.createGetStatic("java/lang/Short","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("J")) {
- list.append(fact.createGetStatic("java/lang/Long","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("F")) {
- list.append(fact.createGetStatic("java/lang/Float","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("C")) {
- list.append(fact.createGetStatic("java/lang/Character","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("B")) {
- list.append(fact.createGetStatic("java/lang/Byte","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("Z")) {
- list.append(fact.createGetStatic("java/lang/Boolean","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("V")) {
- list.append(InstructionFactory.ACONST_NULL);
- }
- return;
- }
- String classString = makeLdcClassString(type);
- if (classString == null) {
- list.append(InstructionFactory.ACONST_NULL);
- } else {
- list.append(fact.PUSHCLASS(cp, classString));
- }
- }
-
- private void pushClasses(InstructionList list, UnresolvedType[] types) {
- // Build an array loaded with the class objects
- if (types == null || types.length == 0) {
- list.append(InstructionFactory.ACONST_NULL);
- } else {
- list.append(InstructionFactory.PUSH(cp, types.length));
- list.append(fact.createNewArray(Type.CLASS, (short)1));
- for (int t=0;t<types.length;t++) {
- list.append(InstructionFactory.DUP);
- list.append(InstructionFactory.PUSH(cp, t));
- pushClass(list, types[t]);
- list.append(InstructionFactory.AASTORE);
- }
- }
- }
-
- private final void pushString(InstructionList list, String string) {
- list.append(InstructionFactory.PUSH(cp, string));
- }
-
- private final void pushInt(InstructionList list, int value) {
- list.append(InstructionFactory.PUSH(cp, value));
- }
-
- protected String makeString(int i) {
- return Integer.toString(i, 16); // ??? expensive
- }
-
- protected String makeString(UnresolvedType t) {
- // this is the inverse of the odd behavior for Class.forName w/ arrays
- if (t.isArray()) {
- // this behavior matches the string used by the eclipse compiler for
- // Foo.class literals
- return t.getSignature().replace('/', '.');
- } else {
- if (t.isParameterizedType()) {
- return t.getRawType().getName();
- } else {
- return t.getName();
- }
- }
- }
-
- protected String makeLdcClassString(UnresolvedType type) {
- if (type.isVoid() || type.isPrimitiveType()) {
- return null;
- }
- if (type.isArray()) {
- return type.getSignature();
- } else {
- if (type.isParameterizedType()) {
- type = type.getRawType();
- }
- String signature = type.getSignature();
- if (signature.length() ==1 ) {
- return signature;
- }
- return signature.substring(1,signature.length()-1);
- }
- }
-
- protected String makeString(UnresolvedType[] types) {
- if (types == null) {
- return "";
- }
- StringBuilder buf = new StringBuilder();
- for (int i = 0, len = types.length; i < len; i++) {
- if (i > 0) {
- buf.append(':');
- }
- buf.append(makeString(types[i]));
- }
- return buf.toString();
- }
-
- protected String makeString(String[] names) {
- if (names == null) {
- return "";
- }
- StringBuilder buf = new StringBuilder();
- for (int i = 0, len = names.length; i < len; i++) {
- if (i > 0) {
- buf.append(':');
- }
- buf.append(names[i]);
- }
- return buf.toString();
- }
-
- public ResolvedType getType() {
- if (myType == null) {
- return null;
- }
- return myType.getResolvedTypeX();
- }
-
- public BcelObjectType getBcelObjectType() {
- return myType;
- }
-
- public String getFileName() {
- return myGen.getFileName();
- }
-
- // for *new* fields
- private void addField(FieldGen field) {
- makeSyntheticAndTransientIfNeeded(field);
- BcelField bcelField = null;
- if (getBcelObjectType() != null) {
- bcelField = new BcelField(getBcelObjectType(), field.getField());
- } else {
- bcelField = new BcelField(getName(), field.getField(), world);
- }
- fields.add(bcelField);
- // myGen.addField(field.getField());
- }
-
- private void makeSyntheticAndTransientIfNeeded(FieldGen field) {
- if (field.getName().startsWith(NameMangler.PREFIX) && !field.getName().startsWith("ajc$interField$")
- && !field.getName().startsWith("ajc$instance$")) {
- // it's an aj added field
- // first do transient
- if (!field.isStatic()) {
- field.setModifiers(field.getModifiers() | Constants.ACC_TRANSIENT);
- }
- // then do synthetic
- if (getWorld().isInJava5Mode()) {
- // add the synthetic modifier flag
- field.setModifiers(field.getModifiers() | ACC_SYNTHETIC);
- }
- if (!hasSyntheticAttribute(field.getAttributes())) {
- // belt and braces, do the attribute even on Java 5 in addition
- // to the modifier flag
- // Attribute[] oldAttrs = field.getAttributes();
- // Attribute[] newAttrs = new Attribute[oldAttrs.length + 1];
- // System.arraycopy(oldAttrs, 0, newAttrs, 0, oldAttrs.length);
- ConstantPool cpg = myGen.getConstantPool();
- int index = cpg.addUtf8("Synthetic");
- Attribute synthetic = new Synthetic(index, 0, new byte[0], cpg);
- field.addAttribute(synthetic);
- // newAttrs[newAttrs.length - 1] = synthetic;
- // field.setAttributes(newAttrs);
- }
- }
- }
-
- private boolean hasSyntheticAttribute(List<Attribute> attributes) {
- for (Attribute attribute : attributes) {
- if (attribute.getName().equals("Synthetic")) {
- return true;
- }
- }
- return false;
- }
-
- public void addField(FieldGen field, ISourceLocation sourceLocation) {
- addField(field);
- if (!(field.isPrivate() && (field.isStatic() || field.isTransient()))) {
- errorOnAddedField(field, sourceLocation);
- }
- }
-
- public String getClassName() {
- return myGen.getClassName();
- }
-
- public boolean isInterface() {
- return myGen.isInterface();
- }
-
- public boolean isAbstract() {
- return myGen.isAbstract();
- }
-
- public LazyMethodGen getLazyMethodGen(Member m) {
- return getLazyMethodGen(m.getName(), m.getSignature(), false);
- }
-
- public LazyMethodGen getLazyMethodGen(String name, String signature) {
- return getLazyMethodGen(name, signature, false);
- }
-
- public LazyMethodGen getLazyMethodGen(String name, String signature, boolean allowMissing) {
- for (LazyMethodGen gen : methodGens) {
- if (gen.getName().equals(name) && gen.getSignature().equals(signature)) {
- return gen;
- }
- }
-
- if (!allowMissing) {
- throw new BCException("Class " + this.getName() + " does not have a method " + name + " with signature " + signature);
- }
-
- return null;
- }
-
- public void forcePublic() {
- myGen.setModifiers(Utility.makePublic(myGen.getModifiers()));
- }
-
- public boolean hasAnnotation(UnresolvedType t) {
-
- // annotations on the real thing
- AnnotationGen agens[] = myGen.getAnnotations();
- if (agens == null) {
- return false;
- }
- for (AnnotationGen gen : agens) {
- if (t.equals(UnresolvedType.forSignature(gen.getTypeSignature()))) {
- return true;
- }
- }
-
- // annotations added during this weave
-
- return false;
- }
-
- public void addAnnotation(AnnotationGen a) {
- if (!hasAnnotation(UnresolvedType.forSignature(a.getTypeSignature()))) {
- annotations.add(new AnnotationGen(a, getConstantPool(), true));
- }
- }
-
- public void addAttribute(AjAttribute attribute) {
- myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool()));
- }
-
- public void addAttribute(Attribute attribute) {
- myGen.addAttribute(attribute);
- }
-
- public Collection<Attribute> getAttributes() {
- return myGen.getAttributes();
- }
-
- // this test is like asking:
- // if
- // (UnresolvedType.SERIALIZABLE.resolve(getType().getWorld()).isAssignableFrom
- // (getType())) {
- // only we don't do that because this forces us to find all the supertypes
- // of the type,
- // and if one of them is missing we fail, and it's not worth failing just to
- // put out
- // a warning message!
- private boolean implementsSerializable(ResolvedType aType) {
- if (aType.getSignature().equals(UnresolvedType.SERIALIZABLE.getSignature())) {
- return true;
- }
-
- ResolvedType[] interfaces = aType.getDeclaredInterfaces();
- for (ResolvedType anInterface : interfaces) {
- if (anInterface.isMissing()) {
- continue;
- }
- if (implementsSerializable(anInterface)) {
- return true;
- }
- }
- ResolvedType superType = aType.getSuperclass();
- if (superType != null && !superType.isMissing()) {
- return implementsSerializable(superType);
- }
- return false;
- }
-
- public boolean isAtLeastJava5() {
- return (myGen.getMajor() >= Constants.MAJOR_1_5);
- }
-
- /**
- * Return the next available field name with the specified 'prefix', e.g. for prefix 'class$' where class$0, class$1 exist then
- * return class$2
- */
- public String allocateField(String prefix) {
- int highestAllocated = -1;
- List<BcelField> fs = getFieldGens();
- for (BcelField field : fs) {
- if (field.getName().startsWith(prefix)) {
- try {
- int num = Integer.parseInt(field.getName().substring(prefix.length()));
- if (num > highestAllocated) {
- highestAllocated = num;
- }
- } catch (NumberFormatException nfe) {
- // something wrong with the number on the end of that
- // field...
- }
- }
- }
- return prefix + Integer.toString(highestAllocated + 1);
- }
-
- }
|