1
/* *******************************************************************
2
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
5
* This program and the accompanying materials are made available
6
* under the terms of the Eclipse Public License v1.0
7
* which accompanies this distribution and is available at
8
* http://www.eclipse.org/legal/epl-v10.html
11
* PARC initial implementation
12
* Adrian Colyer, Andy Clement, overhaul for generics
13
* ******************************************************************/
15
package org.aspectj.weaver;
17
import java.lang.ref.ReferenceQueue;
18
import java.lang.ref.SoftReference;
19
import java.lang.ref.WeakReference;
20
import java.util.ArrayList;
21
import java.util.HashMap;
22
import java.util.Iterator;
23
import java.util.List;
25
import java.util.Properties;
26
import java.util.WeakHashMap;
28
import org.aspectj.asm.IHierarchy;
29
import org.aspectj.bridge.IMessageHandler;
30
import org.aspectj.bridge.ISourceLocation;
31
import org.aspectj.bridge.Message;
32
import org.aspectj.bridge.MessageUtil;
33
import org.aspectj.bridge.IMessage.Kind;
34
import org.aspectj.bridge.context.PinpointingMessageHandler;
35
import org.aspectj.weaver.UnresolvedType.TypeKind;
36
import org.aspectj.weaver.bcel.BcelObjectType;
37
import org.aspectj.weaver.patterns.DeclarePrecedence;
38
import org.aspectj.weaver.patterns.PerClause;
39
import org.aspectj.weaver.patterns.Pointcut;
40
import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegate;
41
import org.aspectj.weaver.tools.Trace;
42
import org.aspectj.weaver.tools.TraceFactory;
45
* A World is a collection of known types and crosscutting members.
47
public abstract class World implements Dump.INode {
48
/** handler for any messages produced during resolution etc. */
49
private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
51
/** handler for cross-reference information produced during the weaving process */
52
private ICrossReferenceHandler xrefHandler = null;
54
/** Currently 'active' scope in which to lookup (resolve) typevariable references */
55
private TypeVariableDeclaringElement typeVariableLookupScope;
57
/** The heart of the world, a map from type signatures to resolved types */
58
protected TypeMap typeMap = new TypeMap(this); // Signature to ResolvedType
61
/** Should we create the hierarchy for binary classes and aspects*/
62
public static boolean createInjarHierarchy = true;
64
/** Calculator for working out aspect precedence */
65
private AspectPrecedenceCalculator precedenceCalculator;
67
/** All of the type and shadow mungers known to us */
68
private CrosscuttingMembersSet crosscuttingMembersSet =
69
new CrosscuttingMembersSet(this);
71
/** Model holds ASM relationships */
72
private IHierarchy model = null;
74
/** for processing Xlint messages */
75
private Lint lint = new Lint(this);
77
/** XnoInline option setting passed down to weaver */
78
private boolean XnoInline;
80
/** XlazyTjp option setting passed down to weaver */
81
private boolean XlazyTjp;
83
/** XhasMember option setting passed down to weaver */
84
private boolean XhasMember = false;
86
/** Xpinpoint controls whether we put out developer info showing the source of messages */
87
private boolean Xpinpoint = false;
89
/** When behaving in a Java 5 way autoboxing is considered */
90
private boolean behaveInJava5Way = false;
92
/** Determines if this world could be used for multiple compiles */
93
private boolean incrementalCompileCouldFollow = false;
95
/** The level of the aspectjrt.jar the code we generate needs to run on */
96
private String targetAspectjRuntimeLevel = Constants.RUNTIME_LEVEL_DEFAULT;
98
/** Flags for the new joinpoints that are 'optional' */
99
private boolean optionalJoinpoint_ArrayConstruction = false; // Command line flag: "-Xjoinpoints:arrayconstruction"
100
private boolean optionalJoinpoint_Synchronization = false; // Command line flag: "-Xjoinpoints:synchronization"
102
private boolean addSerialVerUID = false;
105
private Properties extraConfiguration = null;
106
private boolean checkedAdvancedConfiguration=false;
107
private boolean synchronizationPointcutsInUse = false;
108
// Xset'table options
109
private boolean fastDelegateSupportEnabled = isASMAround;
110
private boolean runMinimalMemory = false;
111
private boolean shouldPipelineCompilation = true;
112
protected boolean bcelRepositoryCaching = xsetBCEL_REPOSITORY_CACHING_DEFAULT.equalsIgnoreCase("true");
113
private boolean completeBinaryTypes = false;
114
public boolean forDEBUG_structuralChangesCode = false;
115
public boolean forDEBUG_bridgingCode = false;
117
private static Trace trace = TraceFactory.getTraceFactory().getTrace(World.class);
119
// Records whether ASM is around ... so we might use it for delegates
120
protected static boolean isASMAround = false;
122
private long errorThreshold;
123
private long warningThreshold;
128
// Class c = Class.forName("org.aspectj.org.objectweb.asm.ClassVisitor");
129
// isASMAround = true;
130
// } catch (ClassNotFoundException cnfe) {
131
// isASMAround = false;
136
* A list of RuntimeExceptions containing full stack information for every
137
* type we couldn't find.
139
private List dumpState_cantFindTypeExceptions = null;
143
* On the first day, God created the primitive types and put them in the type
148
if (trace.isTraceEnabled()) trace.enter("<init>", this);
149
Dump.registerNode(this.getClass(),this);
150
typeMap.put("B", ResolvedType.BYTE);
151
typeMap.put("S", ResolvedType.SHORT);
152
typeMap.put("I", ResolvedType.INT);
153
typeMap.put("J", ResolvedType.LONG);
154
typeMap.put("F", ResolvedType.FLOAT);
155
typeMap.put("D", ResolvedType.DOUBLE);
156
typeMap.put("C", ResolvedType.CHAR);
157
typeMap.put("Z", ResolvedType.BOOLEAN);
158
typeMap.put("V", ResolvedType.VOID);
159
precedenceCalculator = new AspectPrecedenceCalculator(this);
160
if (trace.isTraceEnabled()) trace.exit("<init>");
164
* Dump processing when a fatal error occurs
166
public void accept (Dump.IVisitor visitor) {
167
// visitor.visitObject("Extra configuration:");
168
// visitor.visitList(extraConfiguration.);
169
visitor.visitObject("Shadow mungers:");
170
visitor.visitList(crosscuttingMembersSet.getShadowMungers());
171
visitor.visitObject("Type mungers:");
172
visitor.visitList(crosscuttingMembersSet.getTypeMungers());
173
visitor.visitObject("Late Type mungers:");
174
visitor.visitList(crosscuttingMembersSet.getLateTypeMungers());
175
if (dumpState_cantFindTypeExceptions!=null) {
176
visitor.visitObject("Cant find type problems:");
177
visitor.visitList(dumpState_cantFindTypeExceptions);
178
dumpState_cantFindTypeExceptions = null;
183
// =============================================================================
184
// T Y P E R E S O L U T I O N
185
// =============================================================================
188
* Resolve a type that we require to be present in the world
190
public ResolvedType resolve(UnresolvedType ty) {
191
return resolve(ty, false);
195
* Attempt to resolve a type - the source location gives you some context in which
196
* resolution is taking place. In the case of an error where we can't find the
197
* type - we can then at least report why (source location) we were trying to resolve it.
199
public ResolvedType resolve(UnresolvedType ty,ISourceLocation isl) {
200
ResolvedType ret = resolve(ty,true);
201
if (ResolvedType.isMissing(ty)) {
202
//IMessage msg = null;
203
getLint().cantFindType.signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()),isl);
205
//msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()),isl);
207
//msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
209
//messageHandler.handleMessage(msg);
215
* Convenience method for resolving an array of unresolved types
216
* in one hit. Useful for e.g. resolving type parameters in signatures.
218
public ResolvedType[] resolve(UnresolvedType[] types) {
219
if (types == null) return new ResolvedType[0];
221
ResolvedType[] ret = new ResolvedType[types.length];
222
for (int i=0; i<types.length; i++) {
223
ret[i] = resolve(types[i]);
229
* Resolve a type. This the hub of type resolution. The resolved type is added
230
* to the type map by signature.
232
public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) {
234
// special resolution processing for already resolved types.
235
if (ty instanceof ResolvedType) {
236
ResolvedType rty = (ResolvedType) ty;
241
// dispatch back to the type variable reference to resolve its constituent parts
242
// don't do this for other unresolved types otherwise you'll end up in a loop
243
if (ty.isTypeVariableReference()) {
244
return ty.resolve(this);
247
// if we've already got a resolved type for the signature, just return it
248
// after updating the world
249
String signature = ty.getSignature();
250
ResolvedType ret = typeMap.get(signature);
252
ret.world = this; // Set the world for the RTX
254
} else if ( signature.equals("?") || signature.equals("*")) {
255
// might be a problem here, not sure '?' should make it to here as a signature, the
256
// proper signature for wildcard '?' is '*'
257
// fault in generic wildcard, can't be done earlier because of init issues
258
ResolvedType something = new BoundedReferenceType("?","Ljava/lang/Object",this);
259
typeMap.put("?",something);
263
// no existing resolved type, create one
265
ResolvedType componentType = resolve(ty.getComponentType(),allowMissing);
266
//String brackets = signature.substring(0,signature.lastIndexOf("[")+1);
267
ret = new ResolvedType.Array(signature, "["+componentType.getErasureSignature(),
271
ret = resolveToReferenceType(ty,allowMissing);
272
if (!allowMissing && ret.isMissing()) {
273
ret = handleRequiredMissingTypeDuringResolution(ty);
275
if (completeBinaryTypes) {
276
completeBinaryType(ret);
280
// Pulling in the type may have already put the right entry in the map
281
if (typeMap.get(signature)==null && !ret.isMissing()) {
282
typeMap.put(signature, ret);
288
* Called when a type is resolved - enables its type hierarchy to be finished off before we
291
protected void completeBinaryType(ResolvedType ret) {}
295
* Return true if the classloader relating to this world is definetly the one that will
296
* define the specified class. Return false otherwise or we don't know for certain.
298
public boolean isLocallyDefined(String classname) {
303
* We tried to resolve a type and couldn't find it...
305
private ResolvedType handleRequiredMissingTypeDuringResolution(UnresolvedType ty) {
306
// defer the message until someone asks a question of the type that we can't answer
307
// just from the signature.
308
// MessageUtil.error(messageHandler,
309
// WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
310
if (dumpState_cantFindTypeExceptions==null) {
311
dumpState_cantFindTypeExceptions = new ArrayList();
313
dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName()));
314
return new MissingResolvedTypeWithKnownSignature(ty.getSignature(),this);
318
* Some TypeFactory operations create resolved types directly, but these won't be
319
* in the typeMap - this resolution process puts them there. Resolved types are
320
* also told their world which is needed for the special autoboxing resolved types.
322
public ResolvedType resolve(ResolvedType ty) {
323
if (ty.isTypeVariableReference()) return ty; // until type variables have proper sigs...
324
ResolvedType resolved = typeMap.get(ty.getSignature());
325
if (resolved == null) {
326
typeMap.put(ty.getSignature(), ty);
329
resolved.world = this;
334
* Convenience method for finding a type by name and resolving it in one step.
336
public ResolvedType resolve(String name) {
337
// trace.enter("resolve", this, new Object[] {name});
338
ResolvedType ret = resolve(UnresolvedType.forName(name));
339
// trace.exit("resolve", ret);
343
public ResolvedType resolve(String name,boolean allowMissing) {
344
return resolve(UnresolvedType.forName(name),allowMissing);
347
private ResolvedType currentlyResolvingBaseType;
350
* Resolve to a ReferenceType - simple, raw, parameterized, or generic.
351
* Raw, parameterized, and generic versions of a type share a delegate.
353
private final ResolvedType resolveToReferenceType(UnresolvedType ty,boolean allowMissing) {
354
if (ty.isParameterizedType()) {
355
// ======= parameterized types ================
356
ResolvedType rt = resolveGenericTypeFor(ty,allowMissing);
357
if (rt.isMissing()) return rt;
358
ReferenceType genericType = (ReferenceType)rt;
359
currentlyResolvingBaseType = genericType;
360
ReferenceType parameterizedType =
361
TypeFactory.createParameterizedType(genericType, ty.typeParameters, this);
362
currentlyResolvingBaseType = null;
363
return parameterizedType;
365
} else if (ty.isGenericType()) {
366
// ======= generic types ======================
367
ReferenceType genericType = (ReferenceType)resolveGenericTypeFor(ty,false);
370
} else if (ty.isGenericWildcard()) {
371
// ======= generic wildcard types =============
372
return resolveGenericWildcardFor(ty);
374
// ======= simple and raw types ===============
375
String erasedSignature = ty.getErasureSignature();
376
ReferenceType simpleOrRawType = new ReferenceType(erasedSignature, this);
377
if (ty.needsModifiableDelegate()) simpleOrRawType.setNeedsModifiableDelegate(true);
378
ReferenceTypeDelegate delegate = resolveDelegate(simpleOrRawType);
380
// if (delegate == null) return ResolvedType.MISSING;
381
if (delegate == null) return new MissingResolvedTypeWithKnownSignature(ty.getSignature(),erasedSignature,this);//ResolvedType.MISSING;
383
if (delegate.isGeneric() && behaveInJava5Way) {
384
// ======== raw type ===========
385
simpleOrRawType.typeKind = TypeKind.RAW;
386
ReferenceType genericType = makeGenericTypeFrom(delegate,simpleOrRawType);
387
// name = ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames(ty.getName()),this);
388
simpleOrRawType.setDelegate(delegate);
389
genericType.setDelegate(delegate);
390
simpleOrRawType.setGenericType(genericType);
391
return simpleOrRawType;
394
// ======== simple type =========
395
simpleOrRawType.setDelegate(delegate);
396
return simpleOrRawType;
402
* Attempt to resolve a type that should be a generic type.
404
public ResolvedType resolveGenericTypeFor(UnresolvedType anUnresolvedType, boolean allowMissing) {
405
// Look up the raw type by signature
406
String rawSignature = anUnresolvedType.getRawType().getSignature();
407
ResolvedType rawType = (ResolvedType) typeMap.get(rawSignature);
409
rawType = resolve(UnresolvedType.forSignature(rawSignature),allowMissing);
410
typeMap.put(rawSignature,rawType);
412
if (rawType.isMissing()) return rawType;
414
// Does the raw type know its generic form? (It will if we created the
415
// raw type from a source type, it won't if its been created just through
416
// being referenced, e.g. java.util.List
417
ResolvedType genericType = rawType.getGenericType();
419
// There is a special case to consider here (testGenericsBang_pr95993 highlights it)
420
// You may have an unresolvedType for a parameterized type but it
421
// is backed by a simple type rather than a generic type. This occurs for
422
// inner types of generic types that inherit their enclosing types
424
if (rawType.isSimpleType() && (anUnresolvedType.typeParameters==null || anUnresolvedType.typeParameters.length==0)) {
425
rawType.world = this;
429
if (genericType != null) {
430
genericType.world = this;
433
// Fault in the generic that underpins the raw type ;)
434
ReferenceTypeDelegate delegate = resolveDelegate((ReferenceType)rawType);
435
ReferenceType genericRefType = makeGenericTypeFrom(delegate,((ReferenceType)rawType));
436
((ReferenceType)rawType).setGenericType(genericRefType);
437
genericRefType.setDelegate(delegate);
438
((ReferenceType)rawType).setDelegate(delegate);
439
return genericRefType;
443
private ReferenceType makeGenericTypeFrom(ReferenceTypeDelegate delegate, ReferenceType rawType) {
444
String genericSig = delegate.getDeclaredGenericSignature();
445
if (genericSig != null) {
446
return new ReferenceType(
447
UnresolvedType.forGenericTypeSignature(rawType.getSignature(),delegate.getDeclaredGenericSignature()),this);
449
return new ReferenceType(
450
UnresolvedType.forGenericTypeVariables(rawType.getSignature(), delegate.getTypeVariables()),this);
455
* Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType).
457
private ReferenceType resolveGenericWildcardFor(UnresolvedType aType) {
458
BoundedReferenceType ret = null;
459
// FIXME asc doesnt take account of additional interface bounds (e.g. ? super R & Serializable - can you do that?)
460
if (aType.isExtends()) {
461
ReferenceType upperBound = (ReferenceType)resolve(aType.getUpperBound());
462
ret = new BoundedReferenceType(upperBound,true,this);
463
} else if (aType.isSuper()) {
464
ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound());
465
ret = new BoundedReferenceType(lowerBound,false,this);
467
// must be ? on its own!
473
* Find the ReferenceTypeDelegate behind this reference type so that it can
474
* fulfill its contract.
476
protected abstract ReferenceTypeDelegate resolveDelegate(ReferenceType ty);
479
* Special resolution for "core" types like OBJECT. These are resolved just like
480
* any other type, but if they are not found it is more serious and we issue an
481
* error message immediately.
483
public ResolvedType getCoreType(UnresolvedType tx) {
484
ResolvedType coreTy = resolve(tx,true);
485
if (coreTy.isMissing()) {
486
MessageUtil.error(messageHandler,
487
WeaverMessages.format(WeaverMessages.CANT_FIND_CORE_TYPE,tx.getName()));
493
* Lookup a type by signature, if not found then build one and put it in the
496
public ReferenceType lookupOrCreateName(UnresolvedType ty) {
497
String signature = ty.getSignature();
498
ReferenceType ret = lookupBySignature(signature);
500
ret = ReferenceType.fromTypeX(ty, this);
501
typeMap.put(signature, ret);
507
* Lookup a reference type in the world by its signature. Returns
510
public ReferenceType lookupBySignature(String signature) {
511
return (ReferenceType) typeMap.get(signature);
515
// =============================================================================
516
// T Y P E R E S O L U T I O N -- E N D
517
// =============================================================================
520
* Member resolution is achieved by resolving the declaring type and then
521
* looking up the member in the resolved declaring type.
523
public ResolvedMember resolve(Member member) {
524
ResolvedType declaring = member.getDeclaringType().resolve(this);
525
if (declaring.isRawType()) declaring = declaring.getGenericType();
527
if (member.getKind() == Member.FIELD) {
528
ret = declaring.lookupField(member);
530
ret = declaring.lookupMethod(member);
533
if (ret != null) return ret;
535
return declaring.lookupSyntheticMember(member);
538
// Methods for creating various cross-cutting members...
539
// ===========================================================
542
* Create an advice shadow munger from the given advice attribute
544
public abstract Advice createAdviceMunger(
545
AjAttribute.AdviceAttribute attribute,
550
* Create an advice shadow munger for the given advice kind
552
public final Advice createAdviceMunger(
556
int extraParameterFlags,
557
IHasSourceLocation loc)
559
AjAttribute.AdviceAttribute attribute =
560
new AjAttribute.AdviceAttribute(kind, p, extraParameterFlags, loc.getStart(), loc.getEnd(), loc.getSourceContext());
561
return createAdviceMunger(attribute, p, signature);
564
public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField);
566
public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField);
569
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
570
* @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind)
572
public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind);
574
public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType);
577
* Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo
579
public int compareByPrecedence(ResolvedType aspect1, ResolvedType aspect2) {
580
return precedenceCalculator.compareByPrecedence(aspect1, aspect2);
582
public Integer getPrecedenceIfAny(ResolvedType aspect1, ResolvedType aspect2) {
583
return precedenceCalculator.getPrecedenceIfAny(aspect1, aspect2);
587
* compares by precedence with the additional rule that a super-aspect is
588
* sorted before its sub-aspects
590
public int compareByPrecedenceAndHierarchy(ResolvedType aspect1, ResolvedType aspect2) {
591
return precedenceCalculator.compareByPrecedenceAndHierarchy(aspect1, aspect2);
594
// simple property getter and setters
595
// ===========================================================
598
* Nobody should hold onto a copy of this message handler, or setMessageHandler won't
601
public IMessageHandler getMessageHandler() {
602
return messageHandler;
605
public void setMessageHandler(IMessageHandler messageHandler) {
606
if (this.isInPinpointMode()) {
607
this.messageHandler = new PinpointingMessageHandler(messageHandler);
609
this.messageHandler = messageHandler;
614
* convenenience method for creating and issuing messages via the message handler -
615
* if you supply two locations you will get two messages.
617
public void showMessage(
620
ISourceLocation loc1,
621
ISourceLocation loc2)
624
messageHandler.handleMessage(new Message(message, kind, null, loc1));
626
messageHandler.handleMessage(new Message(message, kind, null, loc2));
629
messageHandler.handleMessage(new Message(message, kind, null, loc2));
633
public boolean debug (String message) {
634
return MessageUtil.debug(messageHandler,message);
637
public void setCrossReferenceHandler(ICrossReferenceHandler xrefHandler) {
638
this.xrefHandler = xrefHandler;
642
* Get the cross-reference handler for the world, may be null.
644
public ICrossReferenceHandler getCrossReferenceHandler() {
645
return this.xrefHandler;
648
public void setTypeVariableLookupScope(TypeVariableDeclaringElement scope) {
649
this.typeVariableLookupScope = scope;
652
public TypeVariableDeclaringElement getTypeVariableLookupScope() {
653
return typeVariableLookupScope;
657
public List getDeclareParents() {
658
return crosscuttingMembersSet.getDeclareParents();
661
public List getDeclareAnnotationOnTypes() {
662
return crosscuttingMembersSet.getDeclareAnnotationOnTypes();
665
public List getDeclareAnnotationOnFields() {
666
return crosscuttingMembersSet.getDeclareAnnotationOnFields();
669
public List getDeclareAnnotationOnMethods() {
670
return crosscuttingMembersSet.getDeclareAnnotationOnMethods();
673
public List getDeclareSoft() {
674
return crosscuttingMembersSet.getDeclareSofts();
677
public CrosscuttingMembersSet getCrosscuttingMembersSet() {
678
return crosscuttingMembersSet;
681
public IHierarchy getModel() {
685
public void setModel(IHierarchy model) {
689
public Lint getLint() {
693
public void setLint(Lint lint) {
697
public boolean isXnoInline() {
701
public void setXnoInline(boolean xnoInline) {
702
XnoInline = xnoInline;
705
public boolean isXlazyTjp() {
709
public void setXlazyTjp(boolean b) {
713
public boolean isHasMemberSupportEnabled() {
717
public void setXHasMemberSupportEnabled(boolean b) {
721
public boolean isInPinpointMode() {
725
public void setPinpointMode(boolean b) {
729
public void setBehaveInJava5Way(boolean b) {
730
behaveInJava5Way = b;
734
* Set the error and warning threashold which can be taken from
735
* CompilerOptions (see bug 129282)
737
* @param errorThreshold
738
* @param warningThreshold
740
public void setErrorAndWarningThreshold(long errorThreshold, long warningThreshold) {
741
this.errorThreshold = errorThreshold;
742
this.warningThreshold = warningThreshold;
746
* @return true if ignoring the UnusedDeclaredThrownException and false if
747
* this compiler option is set to error or warning
749
public boolean isIgnoringUnusedDeclaredThrownException() {
750
// the 0x800000 is CompilerOptions.UnusedDeclaredThrownException
751
// which is ASTNode.bit24
752
if((this.errorThreshold & 0x800000) != 0
753
|| (this.warningThreshold & 0x800000) != 0)
758
public void performExtraConfiguration(String config) {
759
if (config==null) return;
760
// Bunch of name value pairs to split
761
extraConfiguration = new Properties();
763
while ((pos=config.indexOf(","))!=-1) {
764
String nvpair = config.substring(0,pos);
765
int pos2 = nvpair.indexOf("=");
767
String n = nvpair.substring(0,pos2);
768
String v = nvpair.substring(pos2+1);
769
extraConfiguration.setProperty(n,v);
771
config = config.substring(pos+1);
773
if (config.length()>0) {
774
int pos2 = config.indexOf("=");
776
String n = config.substring(0,pos2);
777
String v = config.substring(pos2+1);
778
extraConfiguration.setProperty(n,v);
781
ensureAdvancedConfigurationProcessed();
787
public Properties getExtraConfiguration() {
788
return extraConfiguration;
790
public final static String xsetCAPTURE_ALL_CONTEXT = "captureAllContext"; // default false
791
public final static String xsetACTIVATE_LIGHTWEIGHT_DELEGATES = "activateLightweightDelegates"; // default true
792
public final static String xsetRUN_MINIMAL_MEMORY ="runMinimalMemory"; // default true
793
public final static String xsetDEBUG_STRUCTURAL_CHANGES_CODE = "debugStructuralChangesCode"; // default false
794
public final static String xsetDEBUG_BRIDGING = "debugBridging"; // default false
795
public final static String xsetBCEL_REPOSITORY_CACHING = "bcelRepositoryCaching";
796
public final static String xsetPIPELINE_COMPILATION = "pipelineCompilation";
797
public final static String xsetPIPELINE_COMPILATION_DEFAULT = "true";
798
public final static String xsetCOMPLETE_BINARY_TYPES = "completeBinaryTypes";
799
public final static String xsetCOMPLETE_BINARY_TYPES_DEFAULT = "false";
800
public final static String xsetBCEL_REPOSITORY_CACHING_DEFAULT = "true";
802
public boolean isInJava5Mode() {
803
return behaveInJava5Way;
806
public void setTargetAspectjRuntimeLevel(String s) {
807
targetAspectjRuntimeLevel = s;
810
public void setOptionalJoinpoints(String jps) {
811
if (jps==null) return;
812
if (jps.indexOf("arrayconstruction")!=-1) optionalJoinpoint_ArrayConstruction = true;
813
if (jps.indexOf("synchronization")!=-1) optionalJoinpoint_Synchronization = true;
816
public boolean isJoinpointArrayConstructionEnabled() {
817
return optionalJoinpoint_ArrayConstruction;
819
public boolean isJoinpointSynchronizationEnabled() {
820
return optionalJoinpoint_Synchronization;
823
public String getTargetAspectjRuntimeLevel() {
824
return targetAspectjRuntimeLevel;
827
public boolean isTargettingAspectJRuntime12() {
828
boolean b = false; // pr116679
829
if (!isInJava5Mode()) b=true;
830
else b = getTargetAspectjRuntimeLevel().equals(org.aspectj.weaver.Constants.RUNTIME_LEVEL_12);
831
//System.err.println("Asked if targetting runtime 1.2 , returning: "+b);
836
* Map of types in the world, can have 'references' to expendable ones which
837
* can be garbage collected to recover memory.
838
* An expendable type is a reference type that is not exposed to the weaver (ie
839
* just pulled in for type resolution purposes).
841
protected static class TypeMap {
843
private static boolean debug = false;
845
// Strategy for entries in the expendable map
846
public static int DONT_USE_REFS = 0; // Hang around forever
847
public static int USE_WEAK_REFS = 1; // Collected asap
848
public static int USE_SOFT_REFS = 2; // Collected when short on memory
850
// SECRETAPI - Can switch to a policy of choice ;)
851
public static int policy = USE_SOFT_REFS;
853
// Map of types that never get thrown away
854
private Map /* String -> ResolvedType */ tMap = new HashMap();
856
// Map of types that may be ejected from the cache if we need space
857
private Map expendableMap = new WeakHashMap();
861
// profiling tools...
862
private boolean memoryProfiling = false;
863
private int maxExpendableMapSize = -1;
864
private int collectedTypes = 0;
865
private ReferenceQueue rq = new ReferenceQueue();
867
private static Trace trace = TraceFactory.getTraceFactory().getTrace(World.TypeMap.class);
870
if (trace.isTraceEnabled()) trace.enter("<init>",this,w);
872
memoryProfiling = false;// !w.getMessageHandler().isIgnoring(Message.INFO);
873
if (trace.isTraceEnabled()) trace.exit("<init>");
877
* Add a new type into the map, the key is the type signature.
878
* Some types do *not* go in the map, these are ones involving
879
* *member* type variables. The reason is that when all you have is the
880
* signature which gives you a type variable name, you cannot
881
* guarantee you are using the type variable in the same way
882
* as someone previously working with a similarly
883
* named type variable. So, these do not go into the map:
884
* - TypeVariableReferenceType.
885
* - ParameterizedType where a member type variable is involved.
886
* - BoundedReferenceType when one of the bounds is a type variable.
888
* definition: "member type variables" - a tvar declared on a generic
889
* method/ctor as opposed to those you see declared on a generic type.
891
public ResolvedType put(String key, ResolvedType type) {
892
if (type.isParameterizedType() && type.isParameterizedWithAMemberTypeVariable()) {
894
System.err.println("Not putting a parameterized type that utilises member declared type variables into the typemap: key="+key+" type="+type);
897
if (type.isTypeVariableReference()) {
899
System.err.println("Not putting a type variable reference type into the typemap: key="+key+" type="+type);
902
// this test should be improved - only avoid putting them in if one of the
903
// bounds is a member type variable
904
if (type instanceof BoundedReferenceType) {
906
System.err.println("Not putting a bounded reference type into the typemap: key="+key+" type="+type);
909
if (type instanceof MissingResolvedTypeWithKnownSignature) {
911
System.err.println("Not putting a missing type into the typemap: key="+key+" type="+type);
915
if ((type instanceof ReferenceType) && (((ReferenceType)type).getDelegate()==null) && w.isExpendable(type)) {
917
System.err.println("Not putting expendable ref type with null delegate into typemap: key="+key+" type="+type);
921
if (w.isExpendable(type)) {
922
// Dont use reference queue for tracking if not profiling...
923
if (policy==USE_WEAK_REFS) {
924
if (memoryProfiling) expendableMap.put(key,new WeakReference(type,rq));
925
else expendableMap.put(key,new WeakReference(type));
926
} else if (policy==USE_SOFT_REFS) {
927
if (memoryProfiling) expendableMap.put(key,new SoftReference(type,rq));
928
else expendableMap.put(key,new SoftReference(type));
930
expendableMap.put(key,type);
932
if (memoryProfiling && expendableMap.size()>maxExpendableMapSize) {
933
maxExpendableMapSize = expendableMap.size();
937
return (ResolvedType) tMap.put(key,type);
941
public void report() {
942
if (!memoryProfiling) return;
944
w.getMessageHandler().handleMessage(MessageUtil.info("MEMORY: world expendable type map reached maximum size of #"+maxExpendableMapSize+" entries"));
945
w.getMessageHandler().handleMessage(MessageUtil.info("MEMORY: types collected through garbage collection #"+collectedTypes+" entries"));
948
public void checkq() {
949
if (!memoryProfiling) return;
950
while (rq.poll()!=null) collectedTypes++;
954
* Lookup a type by its signature, always look
955
* in the real map before the expendable map
957
public ResolvedType get(String key) {
959
ResolvedType ret = (ResolvedType) tMap.get(key);
961
if (policy==USE_WEAK_REFS) {
962
WeakReference ref = (WeakReference)expendableMap.get(key);
964
ret = (ResolvedType) ref.get();
966
} else if (policy==USE_SOFT_REFS) {
967
SoftReference ref = (SoftReference)expendableMap.get(key);
969
ret = (ResolvedType) ref.get();
972
return (ResolvedType)expendableMap.get(key);
978
/** Remove a type from the map */
979
public ResolvedType remove(String key) {
980
ResolvedType ret = (ResolvedType) tMap.remove(key);
982
if (policy==USE_WEAK_REFS) {
983
WeakReference wref = (WeakReference)expendableMap.remove(key);
984
if (wref!=null) ret = (ResolvedType)wref.get();
985
} else if (policy==USE_SOFT_REFS) {
986
SoftReference wref = (SoftReference)expendableMap.remove(key);
987
if (wref!=null) ret = (ResolvedType)wref.get();
989
ret = (ResolvedType)expendableMap.remove(key);
995
public String toString() {
996
StringBuffer sb = new StringBuffer();
997
sb.append("types:\n");
998
sb.append(dumpthem(tMap));
999
sb.append("expendables:\n");
1000
sb.append(dumpthem(expendableMap));
1001
return sb.toString();
1004
private String dumpthem(Map m) {
1005
StringBuffer sb = new StringBuffer();
1011
for (Iterator iter = m.entrySet().iterator(); iter.hasNext();) {
1012
Map.Entry entry = (Map.Entry) iter.next();
1013
Object val = entry.getValue();
1014
if (val instanceof WeakReference) {
1015
val = ((WeakReference)val).get();
1017
if (val instanceof SoftReference) {
1018
val = ((SoftReference)val).get();
1020
sb.append(entry.getKey()+"="+val).append("\n");
1021
if (val instanceof ReferenceType) {
1022
ReferenceType refType = (ReferenceType)val;
1023
if (refType.getDelegate() instanceof BcelObjectType) {
1025
} else if (refType.getDelegate() instanceof ReflectionBasedReferenceTypeDelegate) {
1034
sb.append("# BCEL = "+bcelDel+", # REF = "+refDel+", # Other = "+otherTypes);
1036
return sb.toString();
1039
public int totalSize() {
1040
return tMap.size()+expendableMap.size();
1042
public int hardSize() {
1046
public ResolvedType[] getAllTypes() {
1047
List/*ResolvedType*/ results = new ArrayList();
1049
collectTypes(expendableMap, results);
1050
collectTypes(tMap, results);
1051
return (ResolvedType[]) results.toArray(new ResolvedType[results.size()]);
1054
private void collectTypes(Map map, List/*ResolvedType*/ results) {
1055
for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) {
1056
String key = (String) iterator.next();
1057
ResolvedType type = get((String)key);
1058
if (type!=null) results.add(type);
1059
else System.err.println("null!:"+key);
1066
/** Reference types we don't intend to weave may be ejected from
1067
* the cache if we need the space.
1069
protected boolean isExpendable(ResolvedType type) {
1071
!type.equals(UnresolvedType.OBJECT) &&
1073
(!type.isExposedToWeaver()) &&
1074
(!type.isPrimitiveType())
1079
* This class is used to compute and store precedence relationships between
1082
private static class AspectPrecedenceCalculator {
1084
private World world;
1085
private Map cachedResults;
1087
public AspectPrecedenceCalculator(World forSomeWorld) {
1088
this.world = forSomeWorld;
1089
this.cachedResults = new HashMap();
1093
* Ask every declare precedence in the world to order the two aspects.
1094
* If more than one declare precedence gives an ordering, and the orderings
1095
* conflict, then that's an error.
1097
public int compareByPrecedence(ResolvedType firstAspect, ResolvedType secondAspect) {
1098
PrecedenceCacheKey key = new PrecedenceCacheKey(firstAspect,secondAspect);
1099
if (cachedResults.containsKey(key)) {
1100
return ((Integer) cachedResults.get(key)).intValue();
1103
DeclarePrecedence orderer = null; // Records the declare precedence statement that gives the first ordering
1104
for (Iterator i = world.getCrosscuttingMembersSet().getDeclareDominates().iterator(); i.hasNext(); ) {
1105
DeclarePrecedence d = (DeclarePrecedence)i.next();
1106
int thisOrder = d.compare(firstAspect, secondAspect);
1107
if (thisOrder != 0) {
1108
if (orderer==null) orderer = d;
1109
if (order != 0 && order != thisOrder) {
1110
ISourceLocation[] isls = new ISourceLocation[2];
1111
isls[0]=orderer.getSourceLocation();
1112
isls[1]=d.getSourceLocation();
1114
new Message("conflicting declare precedence orderings for aspects: "+
1115
firstAspect.getName()+" and "+secondAspect.getName(),null,true,isls);
1116
world.getMessageHandler().handleMessage(m);
1122
cachedResults.put(key, new Integer(order));
1127
public Integer getPrecedenceIfAny(ResolvedType aspect1,ResolvedType aspect2) {
1128
return (Integer)cachedResults.get(new PrecedenceCacheKey(aspect1,aspect2));
1131
public int compareByPrecedenceAndHierarchy(ResolvedType firstAspect, ResolvedType secondAspect) {
1132
if (firstAspect.equals(secondAspect)) return 0;
1134
int ret = compareByPrecedence(firstAspect, secondAspect);
1135
if (ret != 0) return ret;
1137
if (firstAspect.isAssignableFrom(secondAspect)) return -1;
1138
else if (secondAspect.isAssignableFrom(firstAspect)) return +1;
1144
private static class PrecedenceCacheKey {
1145
public ResolvedType aspect1;
1146
public ResolvedType aspect2;
1148
public PrecedenceCacheKey(ResolvedType a1, ResolvedType a2) {
1153
public boolean equals(Object obj) {
1154
if (!(obj instanceof PrecedenceCacheKey)) return false;
1155
PrecedenceCacheKey other = (PrecedenceCacheKey) obj;
1156
return (aspect1 == other.aspect1 && aspect2 == other.aspect2);
1159
public int hashCode() {
1160
return aspect1.hashCode() + aspect2.hashCode();
1165
public void validateType(UnresolvedType type) { }
1167
// --- with java5 we can get into a recursive mess if we aren't careful when resolving types (*cough* java.lang.Enum) ---
1169
// --- this first map is for java15 delegates which may try and recursively access the same type variables.
1170
// --- I would rather stash this against a reference type - but we don't guarantee referencetypes are unique for
1172
private Map workInProgress1 = new HashMap();
1173
public TypeVariable[] getTypeVariablesCurrentlyBeingProcessed(Class baseClass) {
1174
return (TypeVariable[])workInProgress1.get(baseClass);
1176
public void recordTypeVariablesCurrentlyBeingProcessed(Class baseClass, TypeVariable[] typeVariables) {
1177
workInProgress1.put(baseClass,typeVariables);
1179
public void forgetTypeVariablesCurrentlyBeingProcessed(Class baseClass) {
1180
workInProgress1.remove(baseClass);
1183
public void setAddSerialVerUID(boolean b) { addSerialVerUID=b;}
1184
public boolean isAddSerialVerUID() { return addSerialVerUID;}
1186
/** be careful calling this - pr152257 */
1187
public void flush() {
1188
typeMap.expendableMap.clear();
1191
public void ensureAdvancedConfigurationProcessed() {
1192
// Check *once* whether the user has switched asm support off
1193
if (!checkedAdvancedConfiguration) {
1194
Properties p = getExtraConfiguration();
1197
if (isASMAround) { // dont bother if its not...
1198
String s = p.getProperty(xsetACTIVATE_LIGHTWEIGHT_DELEGATES,"true");
1199
fastDelegateSupportEnabled = s.equalsIgnoreCase("true");
1200
if (!fastDelegateSupportEnabled)
1201
getMessageHandler().handleMessage(MessageUtil.info("[activateLightweightDelegates=false] Disabling optimization to use lightweight delegates for non-woven types"));
1204
String s = p.getProperty(xsetBCEL_REPOSITORY_CACHING,xsetBCEL_REPOSITORY_CACHING_DEFAULT);
1205
bcelRepositoryCaching = s.equalsIgnoreCase("true");
1206
if (!bcelRepositoryCaching) {
1207
getMessageHandler().handleMessage(MessageUtil.info("[bcelRepositoryCaching=false] AspectJ will not use a bcel cache for class information"));
1210
s = p.getProperty(xsetPIPELINE_COMPILATION,xsetPIPELINE_COMPILATION_DEFAULT);
1211
shouldPipelineCompilation = s.equalsIgnoreCase("true");
1213
s = p.getProperty(xsetCOMPLETE_BINARY_TYPES,xsetCOMPLETE_BINARY_TYPES_DEFAULT);
1214
completeBinaryTypes = s.equalsIgnoreCase("true");
1215
if (completeBinaryTypes) {
1216
getMessageHandler().handleMessage(MessageUtil.info("[completeBinaryTypes=true] Completion of binary types activated"));
1219
s = p.getProperty(xsetRUN_MINIMAL_MEMORY,"false");
1220
runMinimalMemory = s.equalsIgnoreCase("true");
1221
// if (runMinimalMemory)
1222
// getMessageHandler().handleMessage(MessageUtil.info("[runMinimalMemory=true] Optimizing bcel processing (and cost of performance) to use less memory"));
1225
s = p.getProperty(xsetDEBUG_STRUCTURAL_CHANGES_CODE,"false");
1226
forDEBUG_structuralChangesCode = s.equalsIgnoreCase("true");
1228
s = p.getProperty(xsetDEBUG_BRIDGING,"false");
1229
forDEBUG_bridgingCode = s.equalsIgnoreCase("true");
1232
checkedAdvancedConfiguration=true;
1236
public boolean isRunMinimalMemory() {
1237
ensureAdvancedConfigurationProcessed();
1238
return runMinimalMemory;
1241
public boolean shouldPipelineCompilation() {
1242
ensureAdvancedConfigurationProcessed();
1243
return shouldPipelineCompilation;
1246
public void setFastDelegateSupport(boolean b) {
1247
if (b && !isASMAround) {
1248
throw new BCException("Unable to activate fast delegate support, ASM classes cannot be found");
1250
fastDelegateSupportEnabled = b;
1253
public boolean isFastDelegateSupportEnabled() {
1254
return false; // ASM not currently being used
1255
// ensureAdvancedConfigurationProcessed();
1256
// return fastDelegateSupportEnabled;
1259
public void setIncrementalCompileCouldFollow(boolean b) {incrementalCompileCouldFollow = b;}
1260
public boolean couldIncrementalCompileFollow() {return incrementalCompileCouldFollow;}
1262
public void setSynchronizationPointcutsInUse() {
1263
if (trace.isTraceEnabled()) trace.enter("setSynchronizationPointcutsInUse", this);
1264
synchronizationPointcutsInUse =true;
1265
if (trace.isTraceEnabled()) trace.exit("setSynchronizationPointcutsInUse");
1267
public boolean areSynchronizationPointcutsInUse() {return synchronizationPointcutsInUse;}
1269
public boolean isASMAround() {
1273
public ResolvedType[] getAllTypes() {
1274
return typeMap.getAllTypes();
b'\\ No newline at end of file'