@@ -176,6 +176,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { | |||
notifyRequestor(); | |||
} else { | |||
weave(); // notification happens as weave progresses... | |||
weaver.getWorld().flush(); | |||
} | |||
} catch (IOException ex) { | |||
AbortCompilation ac = new AbortCompilation(null,ex); | |||
@@ -306,6 +307,7 @@ public class AjCompilerAdapter implements ICompilerAdapter { | |||
} finally { | |||
// ???: is this the right point for this? After weaving has finished clear the caches. | |||
CflowPointcut.clearCaches(); | |||
weaver.tidyUp(); | |||
} | |||
} | |||
@@ -81,6 +81,7 @@ public class EclipseFactory { | |||
private LookupEnvironment lookupEnvironment; | |||
private boolean xSerializableAspects; | |||
private World world; | |||
public Collection finishedTypeMungers = null; | |||
// We can get clashes if we don't treat raw types differently - we end up looking | |||
// up a raw and getting the generic type (pr115788) | |||
@@ -397,7 +398,6 @@ public class EclipseFactory { | |||
return getWorld().getDeclareAnnotationOnMethods(); | |||
} | |||
public Collection finishedTypeMungers = null; | |||
public boolean areTypeMungersFinished() { | |||
return finishedTypeMungers != null; | |||
@@ -987,7 +987,6 @@ public class EclipseFactory { | |||
} | |||
name.setGenericType(complexName); | |||
complexName.setDelegate(t); | |||
complexName.setSourceContext(t.getResolvedTypeX().getSourceContext()); | |||
} | |||
name.setDelegate(t); | |||
@@ -1024,5 +1023,6 @@ public class EclipseFactory { | |||
public void cleanup() { | |||
this.typexToBinding.clear(); | |||
this.rawTypeXToBinding.clear(); | |||
this.finishedTypeMungers = null; | |||
} | |||
} |
@@ -97,7 +97,7 @@ public class EclipseSourceType extends AbstractReferenceTypeDelegate { | |||
this.declaration = declaration; | |||
this.unit = unit; | |||
resolvedTypeX.setSourceContext(new EclipseSourceContext(declaration.compilationResult)); | |||
setSourceContext(new EclipseSourceContext(declaration.compilationResult)); | |||
resolvedTypeX.setStartPos(declaration.sourceStart); | |||
resolvedTypeX.setEndPos(declaration.sourceEnd); | |||
} |
@@ -108,7 +108,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc | |||
* that there is only one builder present, so if two extendsion reset it, only | |||
* the latter will get used. | |||
*/ | |||
private static AsmHierarchyBuilder asmHierarchyBuilder = new AsmHierarchyBuilder(); | |||
public static AsmHierarchyBuilder asmHierarchyBuilder = new AsmHierarchyBuilder(); | |||
static { | |||
CompilationAndWeavingContext.registerFormatter( |
@@ -12,9 +12,24 @@ | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.patterns.Declare; | |||
public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDelegate { | |||
public final static String UNKNOWN_SOURCE_FILE = "<Unknown>"; // Just randomly picked, happens to match BCEL javaclass default | |||
private String sourcefilename = UNKNOWN_SOURCE_FILE; // Sourcefilename is stored only here | |||
protected boolean exposedToWeaver; | |||
protected ReferenceType resolvedTypeX; | |||
private ISourceContext sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT; | |||
public AbstractReferenceTypeDelegate(ReferenceType resolvedTypeX, boolean exposedToWeaver) { | |||
this.resolvedTypeX = resolvedTypeX; | |||
@@ -24,6 +39,8 @@ public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDele | |||
public final boolean isClass() { | |||
return !isAspect() && !isInterface(); | |||
} | |||
/** | |||
* Designed to be overriden by EclipseType to disable collection of shadow mungers | |||
@@ -40,5 +57,216 @@ public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDele | |||
public ReferenceType getResolvedTypeX() { | |||
return resolvedTypeX; | |||
} | |||
/** | |||
* Create the string representation for a delegate, allowing us to | |||
* more easily compare delegate implementations. | |||
*/ | |||
public String stringifyDelegate() { | |||
StringBuffer result = new StringBuffer(); | |||
result.append("=== Delegate for "+getResolvedTypeX().getName()+"\n"); | |||
result.append("isAspect?"+isAspect()+"\n"); | |||
result.append("isAnnotationStyleAspect?"+isAnnotationStyleAspect()+"\n"); | |||
result.append("isInterface?"+isInterface()+"\n"); | |||
result.append("isEnum?"+isEnum()+"\n"); | |||
result.append("isClass?"+isClass()+"\n"); | |||
result.append("-\n"); | |||
result.append("isAnnotation?"+isAnnotation()+"\n"); | |||
result.append("retentionPolicy="+getRetentionPolicy()+"\n"); | |||
result.append("canAnnotationTargetType?"+canAnnotationTargetType()+"\n"); | |||
AnnotationTargetKind[] kinds = getAnnotationTargetKinds(); | |||
if (kinds!=null && kinds.length>0) { | |||
result.append("annotationTargetKinds:["); | |||
for (int i = 0; i < kinds.length; i++) { | |||
AnnotationTargetKind kind = kinds[i]; | |||
result.append(kind); | |||
if ((i+1)<kinds.length) result.append(" "); | |||
} | |||
result.append("]\n"); | |||
} | |||
result.append("isAnnotationWithRuntimeRetention?"+isAnnotationWithRuntimeRetention()+"\n"); | |||
result.append("-\n"); | |||
result.append("isAnonymous?"+isAnonymous()+"\n"); | |||
result.append("isNested?"+isNested()+"\n"); | |||
result.append("-\n"); | |||
result.append("isGeneric?"+isGeneric()+"\n"); | |||
result.append("declaredGenericSignature="+getDeclaredGenericSignature()+"\n"); | |||
result.append("-\n"); | |||
AnnotationX[] axs = getAnnotations(); | |||
if (axs!=null && axs.length>0) { | |||
result.append("getAnnotations() returns: "+axs.length+" annotations\n"); | |||
for (int i = 0; i < axs.length; i++) { | |||
AnnotationX annotationX = axs[i]; | |||
result.append(" #"+i+") "+annotationX+"\n"); | |||
} | |||
} else { | |||
result.append("getAnnotations() returns nothing\n"); | |||
} | |||
ResolvedType[] axtypes = getAnnotationTypes(); | |||
if (axtypes!=null && axtypes.length>0) { | |||
result.append("getAnnotationTypes() returns: "+axtypes.length+" annotations\n"); | |||
for (int i = 0; i < axtypes.length; i++) { | |||
ResolvedType annotation = axtypes[i]; | |||
result.append(" #"+i+") "+annotation+":"+annotation.getClass()+"\n"); | |||
} | |||
} else { | |||
result.append("getAnnotationTypes() returns nothing\n"); | |||
} | |||
result.append("isExposedToWeaver?"+isExposedToWeaver()+"\n"); | |||
result.append("getSuperclass?"+getSuperclass()+"\n"); | |||
result.append("getResolvedTypeX?"+getResolvedTypeX()+"\n"); | |||
result.append("--\n"); | |||
ResolvedMember[] fields = getDeclaredFields(); | |||
if (fields!=null && fields.length>0) { | |||
result.append("The fields: "+fields.length+"\n"); | |||
for (int i = 0; i < fields.length; i++) { | |||
ResolvedMember member = fields[i]; | |||
result.append("f"+i+") "+member.toDebugString()+"\n"); | |||
} | |||
} | |||
ResolvedMember[] methods = getDeclaredMethods(); | |||
if (methods!=null && methods.length>0) { | |||
result.append("The methods: "+methods.length+"\n"); | |||
for (int i = 0; i < methods.length; i++) { | |||
ResolvedMember member = methods[i]; | |||
result.append("m"+i+") "+member.toDebugString()+"\n"); | |||
} | |||
} | |||
ResolvedType[] interfaces = getDeclaredInterfaces(); | |||
if (interfaces!=null && interfaces.length>0) { | |||
result.append("The interfaces: "+interfaces.length+"\n"); | |||
for (int i = 0; i < interfaces.length; i++) { | |||
ResolvedType member = interfaces[i]; | |||
result.append("i"+i+") "+member+"\n"); | |||
} | |||
} | |||
result.append("getModifiers?"+getModifiers()+"\n"); | |||
result.append("perclause="+getPerClause()+"\n"); | |||
result.append("aj:weaverstate="+getWeaverState()+"\n"); | |||
ResolvedMember[] pointcuts = getDeclaredPointcuts(); | |||
if (pointcuts!=null && pointcuts.length>0) { | |||
result.append("The pointcuts: "+pointcuts.length+"\n"); | |||
// Sort the damn things | |||
List sortedSetOfPointcuts = new ArrayList(); | |||
for (int i = 0; i < pointcuts.length; i++) {sortedSetOfPointcuts.add(pointcuts[i]);} | |||
Collections.sort(sortedSetOfPointcuts); | |||
int i =0; | |||
for (Iterator iter = sortedSetOfPointcuts.iterator(); iter.hasNext();) { | |||
ResolvedMember member = (ResolvedMember) iter.next(); | |||
result.append("p"+i+") "+member.toDebugString()+"\n"); | |||
i++; | |||
} | |||
} | |||
Collection declares = getDeclares(); | |||
if (declares.size()>0) { | |||
result.append("The declares: "+declares.size()+"\n"); | |||
// // Sort the damn things | |||
// List sortedSetOfPointcuts = new ArrayList(); | |||
// for (int i = 0; i < pointcuts.length; i++) {sortedSetOfPointcuts.add(pointcuts[i]);} | |||
// Collections.sort(sortedSetOfPointcuts); | |||
int i=0; | |||
for (Iterator iter = declares.iterator(); iter.hasNext();) { | |||
Declare dec = (Declare) iter.next(); | |||
result.append("d"+i+") "+dec.toString()+"\n"); | |||
i++; | |||
} | |||
} | |||
TypeVariable[] tv = getTypeVariables(); | |||
if (tv!=null && tv.length>0) { | |||
result.append("The type variables: "+tv.length+"\n"); | |||
for (int i = 0; i < tv.length; i++) { | |||
result.append("tv"+i+") "+tv[i]+"\n"); | |||
} | |||
} | |||
Collection tmungers = getTypeMungers(); | |||
if (tmungers.size()>0) { | |||
List sorted = new ArrayList(); | |||
sorted.addAll(tmungers); | |||
Collections.sort(sorted,new Comparator() { | |||
public int compare(Object arg0, Object arg1) { | |||
return arg0.toString().compareTo(arg1.toString()); | |||
} | |||
}); | |||
result.append("The type mungers: "+tmungers.size()+"\n"); | |||
int i=0; | |||
for (Iterator iter = sorted.iterator(); iter.hasNext();) { | |||
ConcreteTypeMunger mun = (ConcreteTypeMunger) iter.next(); | |||
result.append("tm"+i+") "+mun.toString()+"\n"); | |||
i++; | |||
} | |||
} | |||
result.append("doesNotExposeShadowMungers?"+doesNotExposeShadowMungers()+"\n"); | |||
Collection pas = getPrivilegedAccesses(); | |||
if (pas!=null && pas.size()>0) { | |||
// List sorted = new ArrayList(); | |||
// sorted.addAll(tmungers); | |||
// Collections.sort(sorted,new Comparator() { | |||
// public int compare(Object arg0, Object arg1) { | |||
// return arg0.toString().compareTo(arg1.toString()); | |||
// } | |||
// }); | |||
result.append("The privileged accesses: "+pas.size()+"\n"); | |||
int i=0; | |||
for (Iterator iter = pas.iterator(); iter.hasNext();) { | |||
ResolvedMember mun = (ResolvedMember) iter.next(); | |||
result.append("tm"+i+") "+mun.toDebugString()+"\n"); | |||
i++; | |||
} | |||
} | |||
// public Collection getPrivilegedAccesses(); | |||
// public boolean hasAnnotation(UnresolvedType ofType); | |||
result.append("==="); | |||
return result.toString(); | |||
} | |||
public final String getSourcefilename() { | |||
return sourcefilename; | |||
} | |||
public final void setSourcefilename(String sourceFileName) { | |||
this.sourcefilename = sourceFileName; | |||
if (sourceFileName!=null && sourceFileName.equals(AbstractReferenceTypeDelegate.UNKNOWN_SOURCE_FILE)) { | |||
this.sourcefilename = "Type '"+ getResolvedTypeX().getName()+"' (no debug info available)"; | |||
} else { | |||
String pname = getResolvedTypeX().getPackageName(); | |||
if (pname != null) { | |||
this.sourcefilename = pname.replace('.', '/') + '/' + sourceFileName; | |||
} | |||
} | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
return getSourceContext().makeSourceLocation(0, 0); | |||
} | |||
public ISourceContext getSourceContext() { | |||
return sourceContext; | |||
} | |||
public void setSourceContext(ISourceContext isc) { | |||
this.sourceContext = isc; | |||
} | |||
} |
@@ -122,6 +122,10 @@ public class JoinPointSignature implements ResolvedMember { | |||
public String[] getParameterNames() { | |||
return realMember.getParameterNames(); | |||
} | |||
public void setParameterNames(String[] names) { | |||
realMember.setParameterNames(names); | |||
} | |||
public String[] getParameterNames(World world) { | |||
return realMember.getParameterNames(world); |
@@ -13,6 +13,7 @@ package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
@@ -32,11 +33,11 @@ public class JoinPointSignatureIterator implements Iterator { | |||
ResolvedType firstDefiningType; | |||
private World world; | |||
private List /*JoinPointSignature*/ discoveredSignatures = new ArrayList(); | |||
private List additionalSignatures = new ArrayList(); | |||
private List additionalSignatures = Collections.EMPTY_LIST; | |||
private Iterator discoveredSignaturesIterator = null; | |||
private Iterator superTypeIterator = null; | |||
private Set visitedSuperTypes = new HashSet(); | |||
private List /*SearchPair*/ yetToBeProcessedSuperMembers = new ArrayList(); | |||
private List /*SearchPair*/ yetToBeProcessedSuperMembers = null;//new ArrayList(); | |||
private boolean iteratingOverDiscoveredSignatures = true; | |||
private boolean couldBeFurtherAsYetUndiscoveredSignatures = true; | |||
@@ -184,14 +185,17 @@ public class JoinPointSignatureIterator implements Iterator { | |||
ResolvedType declaringType = (ResolvedType) iter.next(); | |||
ResolvedMember member = foundMember.withSubstituteDeclaringType(declaringType); | |||
discoveredSignatures.add(member); // for next time we are reset | |||
if (additionalSignatures==Collections.EMPTY_LIST) additionalSignatures=new ArrayList(); | |||
additionalSignatures.add(member); // for this time | |||
} | |||
// if this was a parameterized type, look in the generic type that backs it too | |||
if (superType.isParameterizedType() && (foundMember.backingGenericMember != null)) { | |||
ResolvedMember member =new JoinPointSignature(foundMember.backingGenericMember,foundMember.declaringType.resolve(world)); | |||
discoveredSignatures.add(member); // for next time we are reset | |||
if (additionalSignatures==Collections.EMPTY_LIST) additionalSignatures=new ArrayList(); | |||
additionalSignatures.add(member); // for this time | |||
} | |||
if (yetToBeProcessedSuperMembers==null) yetToBeProcessedSuperMembers=new ArrayList(); | |||
yetToBeProcessedSuperMembers.add(new SearchPair(foundMember,superType)); | |||
return true; | |||
} else { | |||
@@ -199,7 +203,7 @@ public class JoinPointSignatureIterator implements Iterator { | |||
} | |||
} | |||
} | |||
if (!yetToBeProcessedSuperMembers.isEmpty()) { | |||
if (yetToBeProcessedSuperMembers!=null && !yetToBeProcessedSuperMembers.isEmpty()) { | |||
SearchPair nextUp = (SearchPair) yetToBeProcessedSuperMembers.remove(0); | |||
firstDefiningType = nextUp.type; | |||
firstDefiningMember = nextUp.member; |
@@ -48,7 +48,6 @@ public class ReferenceType extends ResolvedType { | |||
ReferenceType genericType = null; | |||
ReferenceTypeDelegate delegate = null; | |||
ISourceContext sourceContext = null; | |||
int startPos = 0; | |||
int endPos = 0; | |||
@@ -347,12 +346,12 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
public ISourceContext getSourceContext() { | |||
return sourceContext; | |||
return delegate.getSourceContext(); | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
if (sourceContext == null) return null; | |||
return sourceContext.makeSourceLocation(new Position(startPos, endPos)); | |||
ISourceContext isc = delegate.getSourceContext(); | |||
return isc.makeSourceLocation(new Position(startPos, endPos)); | |||
} | |||
public boolean isExposedToWeaver() { | |||
@@ -601,8 +600,9 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
public void setDelegate(ReferenceTypeDelegate delegate) { | |||
if (this.delegate!=null && this.delegate.getSourceContext()!=SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) | |||
((AbstractReferenceTypeDelegate)delegate).setSourceContext(this.delegate.getSourceContext()); | |||
this.delegate = delegate; | |||
for(Iterator it = this.derivativeTypes.iterator(); it.hasNext(); ) { | |||
ReferenceType dependent = (ReferenceType) it.next(); | |||
dependent.setDelegate(delegate); | |||
@@ -638,10 +638,6 @@ public class ReferenceType extends ResolvedType { | |||
this.endPos = endPos; | |||
} | |||
public void setSourceContext(ISourceContext sourceContext) { | |||
this.sourceContext = sourceContext; | |||
} | |||
public void setStartPos(int startPos) { | |||
this.startPos = startPos; | |||
} |
@@ -61,6 +61,10 @@ public interface ReferenceTypeDelegate { | |||
public ReferenceType getResolvedTypeX(); | |||
public boolean doesNotExposeShadowMungers(); | |||
public ISourceContext getSourceContext(); | |||
public String getSourcefilename(); | |||
public String getDeclaredGenericSignature(); | |||
} |
@@ -57,6 +57,7 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe | |||
public ISourceContext getSourceContext(World world); | |||
public String[] getParameterNames(); | |||
public void setParameterNames(String[] names); | |||
public String[] getParameterNames(World world); | |||
@@ -47,10 +47,10 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// the case. It is up to the caller to work out where that is! | |||
// Once determined the caller may choose to stash the annotations in this member... | |||
private boolean isAnnotatedElsewhere = false; // this field is not serialized. | |||
private boolean isAjSynthetic = true; | |||
private boolean isAjSynthetic = false; | |||
// generic methods have type variables | |||
private TypeVariable[] typeVariables; | |||
protected TypeVariable[] typeVariables; | |||
// these three fields hold the source location of this member | |||
protected int start, end; | |||
@@ -276,6 +276,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
public boolean isAjSynthetic() { | |||
return isAjSynthetic; | |||
} | |||
protected void setAjSynthetic(boolean b) {isAjSynthetic= b;} | |||
public boolean hasAnnotations() { | |||
return (annotationTypes!=null); | |||
@@ -491,7 +493,6 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
public String[] getParameterNames() { | |||
return parameterNames; | |||
} | |||
public final void setParameterNames(String[] pnames) { | |||
@@ -507,11 +508,11 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
public ISourceLocation getSourceLocation() { | |||
//System.out.println("get context: " + this + " is " + sourceContext); | |||
if (sourceContext == null) { | |||
if (getSourceContext() == null) { | |||
//System.err.println("no context: " + this); | |||
return null; | |||
} | |||
return sourceContext.makeSourceLocation(this); | |||
return getSourceContext().makeSourceLocation(this); | |||
} | |||
public int getEnd() { | |||
@@ -530,6 +531,10 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
this.start = sourceStart; | |||
this.end = sourceEnd; | |||
} | |||
public void setDeclaringType(ReferenceType rt) { | |||
declaringType = rt; | |||
} | |||
public void setSourceContext(ISourceContext sourceContext) { | |||
this.sourceContext = sourceContext; | |||
@@ -838,8 +843,12 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
StringBuffer r = new StringBuffer(); | |||
// modifiers | |||
String mods = Modifier.toString(modifiers); | |||
if (mods.length()!=0) r.append(mods).append(" "); | |||
int mods = modifiers; | |||
if ((mods & 4096)>0) mods = mods -4096; // remove synthetic (added in the ASM case but not in the BCEL case...) | |||
if ((mods & 512)>0) mods = mods -512; // remove interface (added in the BCEL case but not in the ASM case...) | |||
if ((mods & 131072)>0) mods = mods -131072; // remove deprecated (added in the ASM case but not in the BCEL case...) | |||
String modsStr = Modifier.toString(mods); | |||
if (modsStr.length()!=0) r.append(modsStr).append("("+mods+")").append(" "); | |||
// type variables | |||
if (typeVariables!=null && typeVariables.length>0) { | |||
@@ -853,7 +862,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
// 'declaring' type | |||
r.append(returnType.toDebugString()); | |||
r.append(getGenericReturnType().toDebugString()); | |||
r.append(' '); | |||
// name | |||
@@ -864,8 +873,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// parameter signature if a method | |||
if (kind != FIELD) { | |||
r.append("("); | |||
UnresolvedType[] params = parameterTypes; | |||
boolean parameterNamesExist = parameterNames!=null && parameterNames.length==params.length; | |||
UnresolvedType[] params = getGenericParameterTypes(); | |||
boolean parameterNamesExist = showParameterNames && parameterNames!=null && parameterNames.length==params.length; | |||
if (params.length != 0) { | |||
for (int i=0, len = params.length; i < len; i++) { | |||
if (i>0) r.append(", "); | |||
@@ -877,6 +886,9 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
return r.toString(); | |||
} | |||
// SECRETAPI - controlling whether parameter names come out in the debug string (for testing purposes) | |||
public static boolean showParameterNames = true; | |||
public String toGenericString() { | |||
StringBuffer buf = new StringBuffer(); |
@@ -0,0 +1,98 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* 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 | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.SourceLocation; | |||
public class SourceContextImpl implements ISourceContext { | |||
private AbstractReferenceTypeDelegate delegate; | |||
private int[] lineBreaks; | |||
public SourceContextImpl(AbstractReferenceTypeDelegate delegate) { | |||
this.delegate = delegate; | |||
} | |||
public void configureFromAttribute(String name,int []linebreaks) { | |||
this.delegate.setSourcefilename(name); | |||
this.lineBreaks = linebreaks; | |||
} | |||
private File getSourceFile() { | |||
return new File(delegate.getSourcefilename()); | |||
} | |||
public int getOffset() { return 0; } | |||
/* | |||
// AMC - a temporary "fudge" to give as much information as possible about the identity of the | |||
// source file this source location points to. | |||
String internalClassName = getEnclosingClass().getInternalClassName(); | |||
String fileName = getEnclosingClass().getFileName(); | |||
String extension = fileName.substring( fileName.lastIndexOf("."), fileName.length()); | |||
String filePrefix = fileName.substring( 0, fileName.lastIndexOf(".")); | |||
// internal class name is e.g. figures/Point, we don't know whether the file was | |||
// .aj or .java so we put it together with the file extension of the enclosing class | |||
// BUT... sometimes internalClassName is a different class (an aspect), so we only use it if it | |||
// matches the file name. | |||
String mostAccurateFileNameGuess; | |||
if ( internalClassName.endsWith(filePrefix)) { | |||
mostAccurateFileNameGuess = internalClassName + extension; | |||
} else { | |||
mostAccurateFileNameGuess = fileName; | |||
} | |||
return new SourceLocation(new File(mostAccurateFileNameGuess), getSourceLine()); | |||
*/ | |||
public ISourceLocation makeSourceLocation(IHasPosition position) { | |||
if (lineBreaks != null) { | |||
int line = Arrays.binarySearch(lineBreaks, position.getStart()); | |||
if (line < 0) line = -line; | |||
return new SourceLocation(getSourceFile(), line); //??? have more info | |||
} else { | |||
return new SourceLocation(getSourceFile(), 0); | |||
} | |||
} | |||
public ISourceLocation makeSourceLocation(int line, int offset) { | |||
if (line < 0) line = 0; | |||
SourceLocation sl = new SourceLocation(getSourceFile(), line); | |||
if (offset > 0) { | |||
sl.setOffset(offset); | |||
} else { | |||
if (lineBreaks != null) { | |||
int likelyOffset = 0; | |||
if (line > 0 && line < lineBreaks.length) { | |||
//1st char of given line is next char after previous end of line | |||
likelyOffset = lineBreaks[line-1] + 1; | |||
} | |||
sl.setOffset(likelyOffset); | |||
} | |||
} | |||
return sl; | |||
} | |||
public final static ISourceContext UNKNOWN_SOURCE_CONTEXT = new ISourceContext() { | |||
public ISourceLocation makeSourceLocation(IHasPosition position) {return null;} | |||
public ISourceLocation makeSourceLocation(int line, int offset) {return null;} | |||
public int getOffset() {return 0;} | |||
}; | |||
} |
@@ -46,7 +46,7 @@ public class TypeFactory { | |||
} | |||
ResolvedType[] resolvedParameters = inAWorld.resolve(someTypeParameters); | |||
ReferenceType pType = new ReferenceType(baseType,resolvedParameters,inAWorld); | |||
pType.setSourceContext(aBaseType.getSourceContext()); | |||
// pType.setSourceContext(aBaseType.getSourceContext()); | |||
return (ReferenceType) pType.resolve(inAWorld); | |||
} | |||
@@ -66,7 +66,7 @@ public class TypeFactory { | |||
if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting generic type"); | |||
} | |||
ReferenceType rType = new ReferenceType(aBaseType,inAWorld); | |||
rType.setSourceContext(aBaseType.getSourceContext()); | |||
//rType.setSourceContext(aBaseType.getSourceContext()); | |||
return (ReferenceType) rType.resolve(inAWorld); | |||
} | |||
@@ -21,6 +21,7 @@ import java.util.Set; | |||
*/ | |||
public class TypeVariable { | |||
public static final TypeVariable[] NONE = new TypeVariable[0]; | |||
/** | |||
* whether or not the bounds of this type variable have been | |||
* resolved |
@@ -92,6 +92,18 @@ public abstract class World implements Dump.INode { | |||
private Properties extraConfiguration = null; | |||
// Records whether ASM is around ... so we might use it for delegates | |||
protected static boolean isASMAround; | |||
static { | |||
try { | |||
Class c = Class.forName("org.aspectj.org.objectweb.asm.ClassVisitor"); | |||
isASMAround = true; | |||
} catch (ClassNotFoundException cnfe) { | |||
isASMAround = false; | |||
} | |||
} | |||
/** | |||
* A list of RuntimeExceptions containing full stack information for every | |||
* type we couldn't find. | |||
@@ -307,6 +319,7 @@ public abstract class World implements Dump.INode { | |||
// ======= simple and raw types =============== | |||
String erasedSignature = ty.getErasureSignature(); | |||
ReferenceType simpleOrRawType = new ReferenceType(erasedSignature, this); | |||
if (ty.needsModifiableDelegate()) simpleOrRawType.setNeedsModifiableDelegate(true); | |||
ReferenceTypeDelegate delegate = resolveDelegate(simpleOrRawType); | |||
// 117854 | |||
// if (delegate == null) return ResolvedType.MISSING; | |||
@@ -683,6 +696,9 @@ public abstract class World implements Dump.INode { | |||
} | |||
} | |||
/** | |||
* may return null | |||
*/ | |||
public Properties getExtraConfiguration() { | |||
return extraConfiguration; | |||
} | |||
@@ -1043,6 +1059,16 @@ public abstract class World implements Dump.INode { | |||
workInProgress1.remove(baseClass); | |||
} | |||
public void flush() { | |||
// System.err.println("BEFORE FLUSHING"); | |||
// System.err.println(typeMap.toString()); | |||
typeMap.expendableMap.clear(); | |||
// System.err.println("AFTER FLUSHING"); | |||
// System.err.println(typeMap.toString()); | |||
// System.gc(); | |||
System.gc(); | |||
} | |||
// --- | |||
} |
@@ -113,6 +113,11 @@ final class BcelField extends ResolvedMemberImpl { | |||
annotationTypes.toArray(ret); | |||
return ret; | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
ensureAnnotationTypesRetrieved(); | |||
return annotations; | |||
} | |||
private void ensureAnnotationTypesRetrieved() { | |||
if (annotationTypes == null) { |
@@ -14,10 +14,12 @@ | |||
package org.aspectj.weaver.bcel; | |||
import java.lang.reflect.Modifier; | |||
import java.util.ArrayList; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.aspectj.apache.bcel.classfile.Attribute; | |||
import org.aspectj.apache.bcel.classfile.ExceptionTable; | |||
import org.aspectj.apache.bcel.classfile.GenericSignatureParser; | |||
import org.aspectj.apache.bcel.classfile.LocalVariable; | |||
@@ -36,6 +38,7 @@ import org.aspectj.weaver.ResolvedMemberImpl; | |||
import org.aspectj.weaver.ResolvedPointcutDefinition; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.ShadowMunger; | |||
import org.aspectj.weaver.TypeVariable; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException; | |||
@@ -143,6 +146,32 @@ final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
} | |||
} | |||
// for testing - if we have this attribute, return it - will return null if it doesnt know anything | |||
public AjAttribute[] getAttributes(String name) { | |||
List results = new ArrayList(); | |||
List l = BcelAttributes.readAjAttributes(getDeclaringType().getClassName(),method.getAttributes(), getSourceContext(world),world.getMessageHandler(),bcelObjectType.getWeaverVersionAttribute()); | |||
for (Iterator iter = l.iterator(); iter.hasNext();) { | |||
AjAttribute element = (AjAttribute) iter.next(); | |||
if (element.getNameString().equals(name)) results.add(element); | |||
} | |||
if (results.size()>0) { | |||
return (AjAttribute[])results.toArray(new AjAttribute[]{}); | |||
} | |||
return null; | |||
} | |||
// for testing - use with the method above | |||
public String[] getAttributeNames(boolean onlyIncludeAjOnes) { | |||
Attribute[] as = method.getAttributes(); | |||
List names = new ArrayList(); | |||
String[] strs = new String[as.length]; | |||
for (int j = 0; j < as.length; j++) { | |||
if (!onlyIncludeAjOnes || as[j].getName().startsWith(AjAttribute.AttributePrefix)) | |||
names.add(as[j].getName()); | |||
} | |||
return (String[])names.toArray(new String[]{}); | |||
} | |||
public boolean isAjSynthetic() { | |||
return isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX); | |||
@@ -294,6 +323,24 @@ final class BcelMethod extends ResolvedMemberImpl { | |||
// generic method declaration | |||
canBeParameterized = true; | |||
} | |||
typeVariables = new TypeVariable[mSig.formalTypeParameters.length]; | |||
for (int i = 0; i < typeVariables.length; i++) { | |||
Signature.FormalTypeParameter methodFtp = mSig.formalTypeParameters[i]; | |||
try { | |||
typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable( | |||
methodFtp, | |||
mSig.formalTypeParameters, | |||
world); | |||
} catch (GenericSignatureFormatException e) { | |||
// this is a development bug, so fail fast with good info | |||
throw new IllegalStateException( | |||
"While getting the type variables for method " + this.toString() | |||
+ " with generic signature " + mSig + | |||
" the following error condition was detected: " + e.getMessage()); | |||
} | |||
} | |||
Signature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals(); | |||
Signature.FormalTypeParameter[] formals = new | |||
Signature.FormalTypeParameter[parentFormals.length + mSig.formalTypeParameters.length]; |
@@ -27,9 +27,9 @@ 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.annotation.Annotation; | |||
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementValue; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.AbstractReferenceTypeDelegate; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AjcMemberMaker; | |||
@@ -41,6 +41,7 @@ import org.aspectj.weaver.ReferenceTypeDelegate; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedPointcutDefinition; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.SourceContextImpl; | |||
import org.aspectj.weaver.TypeVariable; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.WeaverStateInfo; | |||
@@ -120,18 +121,21 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
super(resolvedTypeX, exposedToWeaver); | |||
this.javaClass = javaClass; | |||
//ATAJ: set the delegate right now for @AJ poincut, else it is done too late to lookup | |||
//ATAJ: set the delegate right now for @AJ pointcut, else it is done too late to lookup | |||
// @AJ pc refs annotation in class hierarchy | |||
resolvedTypeX.setDelegate(this); | |||
if (resolvedTypeX.getSourceContext() == null) { | |||
resolvedTypeX.setSourceContext(new BcelSourceContext(this)); | |||
// if (resolvedTypeX.getSourceContext() == null) { | |||
// resolvedTypeX. | |||
if (resolvedTypeX.getSourceContext()==SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) { | |||
setSourceContext(new SourceContextImpl(this)); | |||
} | |||
// this should only ever be java.lang.Object which is | |||
// the only class in Java-1.4 with no superclasses | |||
isObject = (javaClass.getSuperclassNameIndex() == 0); | |||
unpackAspectAttributes(); | |||
setSourcefilename(javaClass.getSourceFileName()); | |||
} | |||
@@ -265,7 +269,6 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
private void unpackAspectAttributes() { | |||
isUnpacked = true; | |||
List pointcuts = new ArrayList(); | |||
typeMungers = new ArrayList(); | |||
declares = new ArrayList(); | |||
@@ -309,8 +312,9 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
} else if (a instanceof AjAttribute.PrivilegedAttribute) { | |||
privilegedAccess = ((AjAttribute.PrivilegedAttribute)a).getAccessedMembers(); | |||
} else if (a instanceof AjAttribute.SourceContextAttribute) { | |||
if (getResolvedTypeX().getSourceContext() instanceof BcelSourceContext) { | |||
((BcelSourceContext)getResolvedTypeX().getSourceContext()).addAttributeInfo((AjAttribute.SourceContextAttribute)a); | |||
if (getResolvedTypeX().getSourceContext() instanceof SourceContextImpl) { | |||
AjAttribute.SourceContextAttribute sca = (AjAttribute.SourceContextAttribute)a; | |||
((SourceContextImpl)getResolvedTypeX().getSourceContext()).configureFromAttribute(sca.getSourceFileName(),sca.getLineBreaks()); | |||
} | |||
} else if (a instanceof AjAttribute.WeaverVersionInfo) { | |||
wvInfo = (AjAttribute.WeaverVersionInfo)a; // Set the weaver version used to build this type | |||
@@ -443,26 +447,7 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
} | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
return getRetentionPolicy().equals("RUNTIME"); | |||
// if (!isAnnotation()) { | |||
// return false; | |||
// } else { | |||
// Annotation[] annotationsOnThisType = javaClass.getAnnotations(); | |||
// for (int i = 0; i < annotationsOnThisType.length; i++) { | |||
// Annotation a = annotationsOnThisType[i]; | |||
// if (a.getTypeName().equals(UnresolvedType.AT_RETENTION.getName())) { | |||
// List values = a.getValues(); | |||
// boolean isRuntime = false; | |||
// for (Iterator it = values.iterator(); it.hasNext();) { | |||
// ElementNameValuePair element = (ElementNameValuePair) it.next(); | |||
// ElementValue v = element.getValue(); | |||
// isRuntime = v.stringifyValue().equals("RUNTIME"); | |||
// } | |||
// return isRuntime; | |||
// } | |||
// } | |||
// } | |||
// return false; | |||
return (getRetentionPolicy()==null?false:getRetentionPolicy().equals("RUNTIME")); | |||
} | |||
@@ -510,29 +495,32 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
for (int i = 0; i < annotationsOnThisType.length; i++) { | |||
Annotation a = annotationsOnThisType[i]; | |||
if (a.getTypeName().equals(UnresolvedType.AT_TARGET.getName())) { | |||
List values = a.getValues(); | |||
for (Iterator it = values.iterator(); it.hasNext();) { | |||
ElementNameValuePair element = (ElementNameValuePair) it.next(); | |||
ElementValue v = element.getValue(); | |||
String targetKind = v.stringifyValue(); | |||
if (targetKind.equals("ANNOTATION_TYPE")) { | |||
targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE); | |||
} else if (targetKind.equals("CONSTRUCTOR")) { | |||
targetKinds.add(AnnotationTargetKind.CONSTRUCTOR); | |||
} else if (targetKind.equals("FIELD")) { | |||
targetKinds.add(AnnotationTargetKind.FIELD); | |||
} else if (targetKind.equals("LOCAL_VARIABLE")) { | |||
targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE); | |||
} else if (targetKind.equals("METHOD")) { | |||
targetKinds.add(AnnotationTargetKind.METHOD); | |||
} else if (targetKind.equals("PACKAGE")) { | |||
targetKinds.add(AnnotationTargetKind.PACKAGE); | |||
} else if (targetKind.equals("PARAMETER")) { | |||
targetKinds.add(AnnotationTargetKind.PARAMETER); | |||
} else if (targetKind.equals("TYPE")) { | |||
targetKinds.add(AnnotationTargetKind.TYPE); | |||
} | |||
} | |||
ArrayElementValue arrayValue = (ArrayElementValue)((ElementNameValuePair)a.getValues().get(0)).getValue(); | |||
ElementValue[] evs = arrayValue.getElementValuesArray(); | |||
if (evs!=null) { | |||
for (int j = 0; j < evs.length; j++) { | |||
ElementValue v = evs[j]; | |||
String targetKind = v.stringifyValue(); | |||
if (targetKind.equals("ANNOTATION_TYPE")) { | |||
targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE); | |||
} else if (targetKind.equals("CONSTRUCTOR")) { | |||
targetKinds.add(AnnotationTargetKind.CONSTRUCTOR); | |||
} else if (targetKind.equals("FIELD")) { | |||
targetKinds.add(AnnotationTargetKind.FIELD); | |||
} else if (targetKind.equals("LOCAL_VARIABLE")) { | |||
targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE); | |||
} else if (targetKind.equals("METHOD")) { | |||
targetKinds.add(AnnotationTargetKind.METHOD); | |||
} else if (targetKind.equals("PACKAGE")) { | |||
targetKinds.add(AnnotationTargetKind.PACKAGE); | |||
} else if (targetKind.equals("PARAMETER")) { | |||
targetKinds.add(AnnotationTargetKind.PARAMETER); | |||
} else if (targetKind.equals("TYPE")) { | |||
targetKinds.add(AnnotationTargetKind.TYPE); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
if (!targetKinds.isEmpty()) { | |||
@@ -547,10 +535,6 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
return getResolvedTypeX().isSynthetic(); | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
return getResolvedTypeX().getSourceContext().makeSourceLocation(0, 0); //FIXME ??? we can do better than this | |||
} | |||
public AjAttribute.WeaverVersionInfo getWeaverVersionAttribute() { | |||
return wvInfo; | |||
} | |||
@@ -687,7 +671,7 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
if (isGeneric()) { | |||
// update resolved typex to point at generic type not raw type. | |||
ReferenceType genericType = (ReferenceType) this.resolvedTypeX.getGenericType(); | |||
genericType.setSourceContext(this.resolvedTypeX.getSourceContext()); | |||
//genericType.setSourceContext(this.resolvedTypeX.getSourceContext()); | |||
genericType.setStartPos(this.resolvedTypeX.getStartPos()); | |||
this.resolvedTypeX = genericType; | |||
} | |||
@@ -751,6 +735,31 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
return (javaClass==null?"BcelObjectType":"BcelObjectTypeFor:"+javaClass.getClassName()); | |||
} | |||
// for testing - if we have this attribute, return it - will return null if it doesnt know anything | |||
public AjAttribute[] getAttributes(String name) { | |||
List results = new ArrayList(); | |||
List l = BcelAttributes.readAjAttributes(javaClass.getClassName(),javaClass.getAttributes(), getResolvedTypeX().getSourceContext(),getResolvedTypeX().getWorld().getMessageHandler(),AjAttribute.WeaverVersionInfo.UNKNOWN); | |||
for (Iterator iter = l.iterator(); iter.hasNext();) { | |||
AjAttribute element = (AjAttribute) iter.next(); | |||
if (element.getNameString().equals(name)) results.add(element); | |||
} | |||
if (results.size()>0) { | |||
return (AjAttribute[])results.toArray(new AjAttribute[]{}); | |||
} | |||
return null; | |||
} | |||
// for testing - use with the method above - this returns *all* including those that are not Aj attributes | |||
public String[] getAttributeNames() { | |||
Attribute[] as = javaClass.getAttributes(); | |||
String[] strs = new String[as.length]; | |||
for (int j = 0; j < as.length; j++) { | |||
strs[j] = as[j].getName(); | |||
} | |||
return strs; | |||
} | |||
} | |||
@@ -148,7 +148,9 @@ public class BcelWeaver implements IWeaver { | |||
*/ | |||
public ResolvedType addLibraryAspect(String aspectName) { | |||
// 1 - resolve as is | |||
ResolvedType type = world.resolve(UnresolvedType.forName(aspectName), true); | |||
UnresolvedType unresolvedT = UnresolvedType.forName(aspectName); | |||
unresolvedT.setNeedsModifiableDelegate(true); | |||
ResolvedType type = world.resolve(unresolvedT, true); | |||
if (type.isMissing()) { | |||
// fallback on inner class lookup mechanism | |||
String fixedName = aspectName; | |||
@@ -159,7 +161,9 @@ public class BcelWeaver implements IWeaver { | |||
fixedNameChars[hasDot] = '$'; | |||
fixedName = new String(fixedNameChars); | |||
hasDot = fixedName.lastIndexOf('.'); | |||
type = world.resolve(UnresolvedType.forName(fixedName), true); | |||
UnresolvedType ut = UnresolvedType.forName(fixedName); | |||
ut.setNeedsModifiableDelegate(true); | |||
type = world.resolve(ut, true); | |||
if (!type.isMissing()) { | |||
break; | |||
} | |||
@@ -1276,8 +1280,8 @@ public class BcelWeaver implements IWeaver { | |||
//classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData())); | |||
// new: reweavable default with clever diff | |||
classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes()))); | |||
} else { | |||
classType.resetState(); | |||
// } else { | |||
// classType.resetState(); | |||
} | |||
} | |||
@@ -1672,4 +1676,11 @@ public class BcelWeaver implements IWeaver { | |||
public World getWorld() { | |||
return world; | |||
} | |||
public void tidyUp() { | |||
shadowMungerList = null; // setup by prepareForWeave | |||
typeMungerList = null; // setup by prepareForWeave | |||
lateTypeMungerList = null; // setup by prepareForWeave | |||
declareParentsList = null; // setup by prepareForWeave | |||
} | |||
} |
@@ -20,10 +20,12 @@ import java.util.Collections; | |||
import org.aspectj.weaver.AnnotationTargetKind; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ReferenceType; | |||
import org.aspectj.weaver.ReferenceTypeDelegate; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.SourceContextImpl; | |||
import org.aspectj.weaver.TypeVariable; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.WeaverStateInfo; | |||
@@ -351,5 +353,14 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
public ReflectionBasedResolvedMemberImpl createResolvedMemberFor(Member aMember) { | |||
return null; | |||
} | |||
public String getSourcefilename() { | |||
// crappy guess.. | |||
return resolvedType.getName() + ".class"; | |||
} | |||
public ISourceContext getSourceContext() { | |||
return SourceContextImpl.UNKNOWN_SOURCE_CONTEXT; | |||
} | |||
} |