1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276 |
- /* *******************************************************************
- * Copyright (c) 2002 Contributors
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * Andy Clement 6Jul05 generics - signature attribute
- * ******************************************************************/
-
-
- 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.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 org.aspectj.apache.bcel.Constants;
- import org.aspectj.apache.bcel.classfile.Attribute;
- import org.aspectj.apache.bcel.classfile.ConstantUtf8;
- 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.Unknown;
- import org.aspectj.apache.bcel.classfile.annotation.Annotation;
- import org.aspectj.apache.bcel.generic.ClassGen;
- import org.aspectj.apache.bcel.generic.ConstantPoolGen;
- 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.PUSH;
- import org.aspectj.apache.bcel.generic.RETURN;
- import org.aspectj.apache.bcel.generic.Type;
- import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
- import org.aspectj.bridge.IMessage;
- import org.aspectj.bridge.ISourceLocation;
- import org.aspectj.bridge.SourceLocation;
- import org.aspectj.util.CollectionUtil;
- import org.aspectj.weaver.AjAttribute;
- import org.aspectj.weaver.BCException;
- import org.aspectj.weaver.Member;
- import org.aspectj.weaver.NameMangler;
- import org.aspectj.weaver.ResolvedMember;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.Shadow;
- import org.aspectj.weaver.TypeVariable;
- import org.aspectj.weaver.UnresolvedType;
- import org.aspectj.weaver.WeaverMessages;
- import org.aspectj.weaver.WeaverStateInfo;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-
- /**
- * 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 {
-
- int highestLineNumber = 0; // ---- JSR 45 info
-
- private 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 ConstantPoolGen constantPoolGen;
- private World world;
- private String packageName = null;
-
- private List /*LazyMethodGen*/ methodGens = new ArrayList();
- private List /*LazyClassGen*/ classGens = new ArrayList();
- private List /*AnnotationGen*/ annotations = new ArrayList();
- private int childCounter = 0;
-
- private InstructionFactory fact;
-
- private boolean isSerializable = false;
- private boolean hasSerialVersionUIDField = false;
- private boolean hasClinit = false;
-
- // ---
-
- static class InlinedSourceFileInfo {
- int highestLineNumber;
- int offset; // calculated
-
- InlinedSourceFileInfo(int highestLineNumber) {
- this.highestLineNumber = highestLineNumber;
- }
- }
-
- void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
- Object o = inlinedFiles.get(fullpath);
- if (o != null) {
- InlinedSourceFileInfo info = (InlinedSourceFileInfo) o;
- if (info.highestLineNumber < highestLineNumber) {
- info.highestLineNumber = highestLineNumber;
- }
- } else {
- inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
- }
- }
-
- void calculateSourceDebugExtensionOffsets() {
- int i = roundUpToHundreds(highestLineNumber);
- for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
- InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
- element.offset = i;
- i = roundUpToHundreds(i + element.highestLineNumber);
- }
- }
-
- private static int roundUpToHundreds(int i) {
- return ((i / 100) + 1) * 100;
- }
-
- int getSourceDebugExtensionOffset(String fullpath) {
- return ((InlinedSourceFileInfo) inlinedFiles.get(fullpath)).offset;
- }
-
- private Unknown getSourceDebugExtensionAttribute() {
- int nameIndex = constantPoolGen.addUtf8("SourceDebugExtension");
- String data = getSourceDebugExtensionString();
- //System.err.println(data);
- byte[] bytes = Utility.stringToUTF(data);
- int length = bytes.length;
-
- return new Unknown(nameIndex, length, bytes, constantPoolGen.getConstantPool());
- }
-
- // 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);
-
- LazyClassGen clazz = new LazyClassGen(BcelWorld.getBcelObjectType(world.resolve(name)));
- clazz.print(out);
- out.println();
- }
-
-
- public int getNewGeneratedNameTag() {
- return 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);
- constantPoolGen = myGen.getConstantPool();
- fact = new InstructionFactory(myGen, constantPoolGen);
- regenerateGenericSignatureAttribute = true;
- this.world = world;
- }
-
- //Non child type, so it comes from a real type in the world.
- public LazyClassGen(BcelObjectType myType) {
- myGen = new ClassGen(myType.getJavaClass());
- constantPoolGen = myGen.getConstantPool();
- fact = new InstructionFactory(myGen, constantPoolGen);
- this.myType = myType;
- this.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(ResolvedType.LONG)) {
- // hasSerialVersionUIDField = true;
- // }
- // }
- hasSerialVersionUIDField = hasSerialVersionUIDField(getType());
-
- ResolvedMember[] methods = getType().getDeclaredMethods();
- for (int i = 0; i < methods.length; i++) {
- ResolvedMember method = methods[i];
- if (method.getName().equals("<clinit>")) {
- hasClinit = true;
- }
- }
- }
-
- Method[] methods = myGen.getMethods();
- for (int i = 0; i < methods.length; i++) {
- addMethodGen(new LazyMethodGen(methods[i], this));
- }
- }
-
- public static boolean hasSerialVersionUIDField (ResolvedType type) {
-
- ResolvedMember[] fields = type.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- ResolvedMember field = fields[i];
- if (field.getName().equals("serialVersionUID")
- && field.isStatic() && field.getType().equals(ResolvedType.LONG)) {
- return true;
- }
- }
-
- return false;
- }
-
- // public void addAttribute(Attribute i) {
- // myGen.addAttribute(i);
- // }
-
- // ----
-
- public String getInternalClassName() {
- return getConstantPoolGen().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();
- }
- }
-
-
- public File getPackagePath(File root) {
- String str = getInternalClassName();
- int index = str.lastIndexOf('/');
- if (index == -1)
- return root;
- return new File(root, str.substring(0, index));
- }
-
- /** 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 String getClassId() {
- String str = getInternalClassName();
- int index = str.lastIndexOf('/');
- if (index == -1)
- return str;
- return str.substring(index + 1);
- }
-
-
- public void addMethodGen(LazyMethodGen gen) {
- //assert gen.getClassName() == super.getClassName();
- methodGens.add(gen);
- if (highestLineNumber < gen.highestLineNumber) highestLineNumber = gen.highestLineNumber;
- }
-
- public void addMethodGen(LazyMethodGen gen, ISourceLocation sourceLocation) {
- addMethodGen(gen);
- if (!gen.getMethod().isPrivate()) {
- warnOnAddedMethod(gen.getMethod(),sourceLocation);
- }
- }
-
-
- public void errorOnAddedField (Field field, ISourceLocation sourceLocation) {
- if (isSerializable && !hasSerialVersionUIDField) {
- getWorld().getLint().serialVersionUIDBroken.signal(
- new String[] {
- myType.getResolvedTypeX().getName().toString(),
- 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 getMethodGens() {
- return methodGens; //???Collections.unmodifiableList(methodGens);
- }
-
- // FIXME asc Should be collection returned here
- public Field[] getFieldGens() {
- return myGen.getFields();
- }
-
- public Field getField(String name) {
- Field[] allFields = myGen.getFields();
- if (allFields==null) return null;
- for (int i = 0; i < allFields.length; i++) {
- Field field = allFields[i];
- if (field.getName().equals(name)) return field;
- }
- return null;
- }
-
- // FIXME asc How do the ones on the underlying class surface if this just returns new ones added?
- // FIXME asc ...although no one calls this right now !
- public List getAnnotations() {
- return annotations;
- }
-
- private void writeBack(BcelWorld world) {
- if (getConstantPoolGen().getSize() > Short.MAX_VALUE) {
- reportClassTooBigProblem();
- return;
- }
-
- if (annotations.size()>0) {
- for (Iterator iter = annotations.iterator(); iter.hasNext();) {
- AnnotationGen element = (AnnotationGen) iter.next();
- myGen.addAnnotation(element);
- }
- // Attribute[] annAttributes = org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(getConstantPoolGen(),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...)
- boolean hasVersionAttribute = false;
- Attribute[] attrs = myGen.getAttributes();
- for (int i = 0; i < attrs.length && !hasVersionAttribute; i++) {
- Attribute attribute = attrs[i];
- if (attribute.getName().equals("org.aspectj.weaver.WeaverVersion")) hasVersionAttribute=true;
- }
- if (!hasVersionAttribute)
- myGen.addAttribute(BcelAttributes.bcelAttribute(new AjAttribute.WeaverVersionInfo(),getConstantPoolGen()));
-
- if (myType != null && myType.getWeaverState() != null) {
- myGen.addAttribute(BcelAttributes.bcelAttribute(
- new AjAttribute.WeaverState(myType.getWeaverState()),
- getConstantPoolGen()));
- }
-
- //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();
-
- int len = methodGens.size();
- myGen.setMethods(new Method[0]);
-
- calculateSourceDebugExtensionOffsets();
- for (int i = 0; i < len; i++) {
- LazyMethodGen gen = (LazyMethodGen) methodGens.get(i);
- // we skip empty clinits
- if (isEmptyClinit(gen)) continue;
- myGen.addMethod(gen.getMethod());
- }
- if (inlinedFiles.size() != 0) {
- if (hasSourceDebugExtensionAttribute(myGen)) {
- world.showMessage(
- IMessage.WARNING,
- WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45,getFileName()),
- null,
- null);
- }
- // 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.
- // myGen.addAttribute(getSourceDebugExtensionAttribute());
- }
-
- fixupGenericSignatureAttribute();
- }
-
- /**
- * When working with 1.5 generics, a signature attribute is attached to the type which indicates
- * how it was declared. This routine ensures the signature attribute for what we are about
- * to write out is correct. Basically its responsibilities are:
- * 1. Checking whether the attribute needs changing (i.e. did weaving change the type hierarchy)
- * 2. If it did, removing the old attribute
- * 3. Check if we need an attribute at all, are we generic? are our supertypes parameterized/generic?
- * 4. Build the new attribute which includes all typevariable, supertype and superinterface information
- */
- 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
- Attribute[] as = myGen.getAttributes();
- for (int i = 0; i < as.length; i++) {
- Attribute attribute = as[i];
- if (attribute.getName().equals("Signature")) sigAttr = (Signature)attribute;
- }
- }
-
- // 3. Do we need an attribute?
- boolean needAttribute = false;
- if (sigAttr!=null) needAttribute = true; // If we had one before, we definetly still need one as types can't be 'removed' from the hierarchy
-
- // check the interfaces
- if (!needAttribute) {
- if (myType==null) {
- boolean stop = true;
- }
- ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
- for (int i = 0; i < interfaceRTXs.length; i++) {
- ResolvedType typeX = interfaceRTXs[i];
- if (typeX.isGenericType() || typeX.isParameterizedType()) needAttribute = true;
- }
-
- // check the supertype
- ResolvedType superclassRTX = myType.getSuperclass();
- if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) needAttribute = true;
- }
-
- if (needAttribute) {
- StringBuffer signature = new StringBuffer();
- // first, the type variables...
- TypeVariable[] tVars = myType.getTypeVariables();
- if (tVars.length>0) {
- signature.append("<");
- for (int i = 0; i < tVars.length; i++) {
- TypeVariable variable = tVars[i];
- if (i!=0) signature.append(",");
- signature.append(variable.getSignature());
- }
- signature.append(">");
- }
- // now the supertype
- String supersig = myType.getSuperclass().getSignatureForAttribute();
- signature.append(supersig);
- ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
- for (int i = 0; i < interfaceRTXs.length; i++) {
- String s = interfaceRTXs[i].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 = constantPoolGen.addUtf8("Signature");
- int sigIndex = constantPoolGen.addUtf8(signature);
- return new Signature(nameIndex,2,sigIndex,constantPoolGen.getConstantPool());
- }
-
- /**
- *
- */
- 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.getAccessFlags(), 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) {
- ConstantPoolGen pool = gen.getConstantPool();
- Attribute[] attrs = gen.getAttributes();
- for (int i = 0; i < attrs.length; i++) {
- if ("SourceDebugExtension"
- .equals(((ConstantUtf8) pool.getConstant(attrs[i].getNameIndex())).getBytes())) {
- return true;
- }
- }
- return false;
- }
-
- public JavaClass getJavaClass(BcelWorld world) {
- 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);
- }
-
- public void addInterface(UnresolvedType typeX, ISourceLocation sourceLocation) {
- regenerateGenericSignatureAttribute = true;
- myGen.addInterface(typeX.getRawName());
- if (!typeX.equals(UnresolvedType.SERIALIZABLE))
- warnOnAddedInterface(typeX.getName(),sourceLocation);
- }
-
- public void setSuperClass(ResolvedType typeX) {
- regenerateGenericSignatureAttribute = true;
- myType.addParent(typeX); // used for the attribute
- if (typeX.getGenericType()!=null) typeX = typeX.getGenericType();
- myGen.setSuperclassName(typeX.getName()); // used in the real class data
- }
-
- public String getSuperClassname() {
- return myGen.getSuperclassName();
- }
-
- // FIXME asc not great that some of these ask the gen and some ask the type ! (see the related setters too)
- public ResolvedType getSuperClass() {
- return myType.getSuperclass();
- }
-
- public String[] getInterfaceNames() {
- return myGen.getInterfaceNames();
- }
-
-
- // non-recursive, may be a bug, ha ha.
- private List getClassGens() {
- List ret = new ArrayList();
- ret.add(this);
- ret.addAll(classGens);
-
- return ret;
- }
-
-
- public List getChildClasses(BcelWorld world) {
- if (classGens.isEmpty()) return Collections.EMPTY_LIST;
- List ret = new ArrayList();
- for (Iterator i = classGens.iterator(); i.hasNext();) {
- LazyClassGen clazz = (LazyClassGen) i.next();
- 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;
- }
-
- public String toString() {
- return toShortString();
- }
-
- public String toShortString() {
- String s =
- org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getAccessFlags(), true);
- if (s != "")
- s += " ";
- s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getAccessFlags());
- 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 classGens = getClassGens();
- for (Iterator iter = classGens.iterator(); iter.hasNext();) {
- LazyClassGen element = (LazyClassGen) 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 (int i = 0, len = fields.length; i < len; i++) {
- out.print(" ");
- out.println(fields[i]);
- }
- List methodGens = getMethodGens();
- for (Iterator iter = methodGens.iterator(); iter.hasNext();) {
- LazyMethodGen gen = (LazyMethodGen) 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() instanceof RETURN)) {
- start = start.getNext();
- } else {
- return false;
- }
- }
-
- return true;
- }
-
- public ConstantPoolGen getConstantPoolGen() {
- return constantPoolGen;
- }
-
- 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 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 (Iterator i = methodGens.iterator(); i.hasNext();) {
- LazyMethodGen gen = (LazyMethodGen) i.next();
- if (gen.getName().equals("<clinit>")) return gen;
- }
- LazyMethodGen clinit = new LazyMethodGen(
- Modifier.STATIC,
- Type.VOID,
- "<clinit>",
- new Type[0],
- CollectionUtil.NO_STRINGS,
- this);
- clinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(clinit);
- return clinit;
- }
-
- public LazyMethodGen getAjcPreClinit() {
- for (Iterator i = methodGens.iterator(); i.hasNext();) {
- LazyMethodGen gen = (LazyMethodGen) i.next();
- if (gen.getName().equals(NameMangler.AJC_PRE_CLINIT_NAME)) return gen;
- }
- LazyMethodGen ajcClinit = new LazyMethodGen(
- Modifier.STATIC,
- Type.VOID,
- NameMangler.AJC_PRE_CLINIT_NAME,
- new Type[0],
- CollectionUtil.NO_STRINGS,
- this);
- ajcClinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(ajcClinit);
-
- getStaticInitializer().getBody().insert(Utility.createInvoke(getFactory(), ajcClinit));
- return ajcClinit;
- }
-
-
-
- // reflective thisJoinPoint support
- Map/*BcelShadow, Field*/ tjpFields = new HashMap();
- 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 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 ret = (Field)tjpFields.get(shadow);
- if (ret != null) return ret;
-
- int modifiers = Modifier.STATIC | 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;
- if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have different staticjp types in 1.2
- jpType = staticTjpType;
- } else {
- jpType = isEnclosingJp?enclosingStaticTjpType:staticTjpType;
- }
- ret = new FieldGen(modifiers,jpType,"ajc$tjp_" + tjpFields.size(),getConstantPoolGen()).getField();
- addField(ret);
- tjpFields.put(shadow, ret);
- return ret;
- }
-
-
- //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",
- // getConstantPoolGen()).getField();
- // addField(ajClassField);
- //
- // InstructionList il = new InstructionList();
- // il.append(new PUSH(getConstantPoolGen(), 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) return;
-
- InstructionList il = initializeAllTjps();
-
- getStaticInitializer().getBody().insert(il);
- }
-
-
- private InstructionList initializeAllTjps() {
- InstructionList list = new InstructionList();
- InstructionFactory fact = getFactory();
-
- // make a new factory
- list.append(fact.createNew(factoryType));
- list.append(InstructionFactory.createDup(1));
-
- list.append(new PUSH(getConstantPoolGen(), getFileName()));
-
- // load the current Class object
- //XXX check that this works correctly for inners/anonymous
- list.append(new PUSH(getConstantPoolGen(), getClassName()));
- //XXX do we need to worry about the fact the theorectically this could throw
- //a ClassNotFoundException
- list.append(fact.createInvoke("java.lang.Class", "forName", classType,
- new Type[] {Type.STRING}, Constants.INVOKESTATIC));
-
- list.append(fact.createInvoke(factoryType.getClassName(), "<init>",
- Type.VOID, new Type[] {Type.STRING, classType},
- Constants.INVOKESPECIAL));
-
- list.append(InstructionFactory.createStore(factoryType, 0));
-
- List entries = new ArrayList(tjpFields.entrySet());
- Collections.sort(entries, new Comparator() {
- public int compare(Object a, Object b) {
- Map.Entry ae = (Map.Entry) a;
- Map.Entry be = (Map.Entry) b;
- return ((Field) ae.getValue())
- .getName()
- .compareTo(((Field)be.getValue()).getName());
- }
- });
-
- for (Iterator i = entries.iterator(); i.hasNext(); ) {
- Map.Entry entry = (Map.Entry)i.next();
- initializeTjp(fact, list, (Field)entry.getValue(), (BcelShadow)entry.getKey());
- }
-
- return list;
- }
-
-
- private void initializeTjp(InstructionFactory fact, InstructionList list,
- Field field, BcelShadow shadow)
- {
- Member sig = shadow.getSignature();
- //ResolvedMember mem = shadow.getSignature().resolve(shadow.getWorld());
-
- // load the factory
- list.append(InstructionFactory.createLoad(factoryType, 0));
-
- // load the kind
- list.append(new PUSH(getConstantPoolGen(), shadow.getKind().getName()));
-
- // create the signature
- list.append(InstructionFactory.createLoad(factoryType, 0));
-
- if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2
- list.append(new PUSH(getConstantPoolGen(), sig.getSignatureString(shadow.getWorld())));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING },
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.METHOD)) {
- BcelWorld w = shadow.getWorld();
- // For methods, push the parts of the signature on.
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
- list.append(new PUSH(getConstantPoolGen(),sig.getName()));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getExceptions(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getReturnType())));
- // And generate a call to the variant of makeMethodSig() that takes 7 strings
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING,Type.STRING,Type.STRING,Type.STRING,Type.STRING,Type.STRING,Type.STRING },
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.HANDLER)) {
- BcelWorld w = shadow.getWorld();
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING, Type.STRING, Type.STRING },
- Constants.INVOKEVIRTUAL));
- } else if(sig.getKind().equals(Member.CONSTRUCTOR)) {
- BcelWorld w = shadow.getWorld();
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getExceptions(w))));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING },
- Constants.INVOKEVIRTUAL));
- } else if(sig.getKind().equals(Member.FIELD)) {
- BcelWorld w = shadow.getWorld();
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
- list.append(new PUSH(getConstantPoolGen(),sig.getName()));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getReturnType())));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING },
- Constants.INVOKEVIRTUAL));
- } else if(sig.getKind().equals(Member.ADVICE)) {
- BcelWorld w = shadow.getWorld();
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
- list.append(new PUSH(getConstantPoolGen(),sig.getName()));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getExceptions(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString((sig.getReturnType()))));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- 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(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
- list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING, Type.STRING },
- Constants.INVOKEVIRTUAL));
- } else {
- list.append(new PUSH(getConstantPoolGen(), sig.getSignatureString(shadow.getWorld())));
- list.append(fact.createInvoke(factoryType.getClassName(),
- sig.getSignatureMakerName(),
- new ObjectType(sig.getSignatureType()),
- new Type[] { Type.STRING },
- Constants.INVOKEVIRTUAL));
- }
-
- //XXX should load source location from shadow
- list.append(Utility.createConstant(fact, shadow.getSourceLine()));
-
- final String factoryMethod;
-
- if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have makeESJP() in 1.2
- 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");
- }
- 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));
- }
- }
-
-
- 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 {
- return t.getName();
- }
- }
-
- protected String makeString(UnresolvedType[] types) {
- if (types == null) return "";
- StringBuffer buf = new StringBuffer();
- for (int i = 0, len=types.length; i < len; i++) {
- buf.append(makeString(types[i]));
- buf.append(':');
- }
- return buf.toString();
- }
-
- protected String makeString(String[] names) {
- if (names == null) return "";
- StringBuffer buf = new StringBuffer();
- for (int i = 0, len=names.length; i < len; i++) {
- buf.append(names[i]);
- buf.append(':');
- }
- 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();
- }
-
- private void addField(Field field) {
- myGen.addField(field);
- }
-
- public void replaceField(Field oldF, Field newF){
- myGen.removeField(oldF);
- myGen.addField(newF);
- }
-
- public void addField(Field 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 (Iterator i = methodGens.iterator(); i.hasNext();) {
- LazyMethodGen gen = (LazyMethodGen) i.next();
- 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.setAccessFlags(Utility.makePublic(myGen.getAccessFlags()));
- }
-
-
- public boolean hasAnnotation(UnresolvedType t) {
-
- // annotations on the real thing
- AnnotationGen agens[] = myGen.getAnnotations();
- if (agens==null) return false;
- for (int i = 0; i < agens.length; i++) {
- AnnotationGen gen = agens[i];
- if (t.equals(UnresolvedType.forSignature(gen.getTypeSignature()))) return true;
- }
-
- // annotations added during this weave
-
- return false;
- }
-
- public void addAnnotation(Annotation a) {
- if (!hasAnnotation(UnresolvedType.forSignature(a.getTypeSignature()))) {
- annotations.add(new AnnotationGen(a,getConstantPoolGen(),true));
- }
- }
-
- // 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) {
- ResolvedType[] interfaces = aType.getDeclaredInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- if (interfaces[i].getSignature().equals(UnresolvedType.SERIALIZABLE.getSignature())) {
- return true;
- } else {
- if (interfaces[i].isMissing()) continue;
- ResolvedType superInterface = interfaces[i].getSuperclass();
- if (superInterface != null && !superInterface.isMissing()) {
- if (implementsSerializable(superInterface)) return true;
- }
- }
- }
- ResolvedType superType = aType.getSuperclass();
- if (superType != null && !superType.isMissing()) {
- return implementsSerializable(superType);
- }
- return false;
- }
-
-
- }
|