org.aspectj.asm.internal.JDTLikeHandleProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjweaver Show documentation
Show all versions of aspectjweaver Show documentation
The AspectJ weaver introduces advices to java classes
/********************************************************************
* Copyright (c) 2006 Contributors. All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://eclipse.org/legal/epl-v10.html
*
* Contributors: IBM Corporation - initial API and implementation
* Helen Hawkins - initial version
*******************************************************************/
package org.aspectj.asm.internal;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IElementHandleProvider;
import org.aspectj.asm.IProgramElement;
import org.aspectj.bridge.ISourceLocation;
/**
* Creates JDT-like handles, for example
*
* method with string argument: ; an aspect: top of the tree is either
// or the .lst file
if (ipe == null || (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA) && ipe.getName().equals(""))) {
return "";
} else if (ipe.getHandleIdentifier(false) != null) {
// have already created the handle for this ipe
// therefore just return it
return ipe.getHandleIdentifier();
} else if (ipe.getKind().equals(IProgramElement.Kind.FILE_LST)) {
String configFile = asm.getHierarchy().getConfigFile();
int start = configFile.lastIndexOf(File.separator);
int end = configFile.lastIndexOf(".lst");
if (end != -1) {
configFile = configFile.substring(start + 1, end);
} else {
configFile = new StringBuffer("=").append(configFile.substring(start + 1)).toString();
}
ipe.setHandleIdentifier(configFile);
return configFile;
} else if (ipe.getKind() == IProgramElement.Kind.SOURCE_FOLDER) {
StringBuffer sb = new StringBuffer();
sb.append(createHandleIdentifier(ipe.getParent())).append("/");
// pr249216 - escape any embedded slashes
String folder = ipe.getName();
if (folder.endsWith("/")) {
folder = folder.substring(0, folder.length() - 1);
}
if (folder.indexOf("/") != -1) {
folder = folder.replace("/", "\\/");
}
sb.append(folder);
String handle = sb.toString();
ipe.setHandleIdentifier(handle);
return handle;
}
IProgramElement parent = ipe.getParent();
if (parent != null && parent.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE)) {
// want to miss out '#import declaration' in the handle
parent = ipe.getParent().getParent();
}
StringBuffer handle = new StringBuffer();
// add the handle for the parent
handle.append(createHandleIdentifier(parent));
// add the correct delimiter for this ipe
handle.append(HandleProviderDelimiter.getDelimiter(ipe));
// add the name and any parameters unless we're an initializer
// (initializer's names are '...')
if (!ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
if (ipe.getKind() == IProgramElement.Kind.CLASS && ipe.getName().endsWith("{..}")) {
// format: 'new Runnable() {..}' but its anon-y-mouse
// dont append anything, there may be a count to follow though (!)
} else {
if (ipe.getKind() == IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR) {
handle.append(ipe.getName()).append("_new").append(getParameters(ipe));
} else {
// if (ipe.getKind() == IProgramElement.Kind.PACKAGE && ipe.getName().equals("DEFAULT")) {
// // the delimiter will be in there, but skip the word DEFAULT as it is just a placeholder
// } else {
if (ipe.getKind().isDeclareAnnotation()) {
// escape the @ (pr249216c9)
handle.append("declare \\@").append(ipe.getName().substring(9)).append(getParameters(ipe));
} else {
if (ipe.getFullyQualifiedName() != null) {
handle.append(ipe.getFullyQualifiedName());
} else {
handle.append(ipe.getName());
}
handle.append(getParameters(ipe));
}
}
// }
}
}
// add the count, for example '!2' if its the second ipe of its
// kind in the aspect
handle.append(getCount(ipe));
ipe.setHandleIdentifier(handle.toString());
return handle.toString();
}
private String getParameters(IProgramElement ipe) {
if (ipe.getParameterSignatures() == null || ipe.getParameterSignatures().isEmpty()) {
return "";
}
List sourceRefs = ipe.getParameterSignaturesSourceRefs();
List parameterTypes = ipe.getParameterSignatures();
StringBuffer sb = new StringBuffer();
if (sourceRefs != null) {
for (int i = 0; i < sourceRefs.size(); i++) {
String sourceRef = sourceRefs.get(i);
sb.append(HandleProviderDelimiter.getDelimiter(ipe));
sb.append(sourceRef);
}
} else {
for (char[] element : parameterTypes) {
sb.append(HandleProviderDelimiter.getDelimiter(ipe));
sb.append(NameConvertor.createShortName(element, false, false));
}
}
return sb.toString();
}
/**
* Determine a count to be suffixed to the handle, this is only necessary for identical looking entries at the same level in the
* model (for example two anonymous class declarations). The format is ! where n will be greater than 2.
*
* @param ipe the program element for which the handle is being constructed
* @return a char suffix that will either be empty or of the form "!"
*/
private char[] getCount(IProgramElement ipe) {
// TODO could optimize this code
char[] byteCodeName = ipe.getBytecodeName().toCharArray();
if (ipe.getKind().isInterTypeMember()) {
int count = 1;
List kids = ipe.getParent().getChildren();
for (Iterator iterator = kids.iterator(); iterator.hasNext();) {
IProgramElement object = iterator.next();
if (object.equals(ipe)) {
break;
}
if (object.getKind().isInterTypeMember()) {
if (object.getName().equals(ipe.getName()) && getParameters(object).equals(getParameters(ipe))) {
String existingHandle = object.getHandleIdentifier();
int suffixPosition = existingHandle.indexOf('!');
if (suffixPosition != -1) {
count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
} else {
if (count == 1) {
count = 2;
}
}
}
}
}
if (count > 1) {
return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
}
} else if (ipe.getKind().isDeclare()) {
// // look at peer declares
int count = computeCountBasedOnPeers(ipe);
if (count > 1) {
return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
}
} else if (ipe.getKind().equals(IProgramElement.Kind.ADVICE)) {
// Look at any peer advice
int count = 1;
List kids = ipe.getParent().getChildren();
String ipeSig = ipe.getBytecodeSignature();
// remove return type from the signature - it should not be included in the comparison
int idx = 0;
ipeSig = shortenIpeSig(ipeSig);
for (IProgramElement object : kids) {
if (object.equals(ipe)) {
break;
}
if (object.getKind() == ipe.getKind()) {
if (object.getName().equals(ipe.getName())) {
String sig1 = object.getBytecodeSignature();
if (sig1 != null && (idx = sig1.indexOf(")")) != -1) {
sig1 = sig1.substring(0, idx);
}
// this code needs a speed overhaul... and some proper tests
// Two static parts because one may be enclosing jpsp (269522)
if (sig1 != null) {
if (sig1.indexOf("Lorg/aspectj/lang") != -1) {
if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
}
if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
}
if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
}
}
}
if (sig1 == null && ipeSig == null || (sig1 != null && sig1.equals(ipeSig))) {
String existingHandle = object.getHandleIdentifier();
int suffixPosition = existingHandle.indexOf('!');
if (suffixPosition != -1) {
count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
} else {
if (count == 1) {
count = 2;
}
}
}
}
}
}
if (count > 1) {
return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
}
} else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
// return String.valueOf(++initializerCounter).toCharArray();
// Look at any peer advice
int count = 1;
List kids = ipe.getParent().getChildren();
String ipeSig = ipe.getBytecodeSignature();
// remove return type from the signature - it should not be included in the comparison
int idx = 0;
ipeSig = shortenIpeSig(ipeSig);
for (IProgramElement object : kids) {
if (object.equals(ipe)) {
break;
}
if (object.getKind() == ipe.getKind()) {
if (object.getName().equals(ipe.getName())) {
String sig1 = object.getBytecodeSignature();
if (sig1 != null && (idx = sig1.indexOf(")")) != -1) {
sig1 = sig1.substring(0, idx);
}
// this code needs a speed overhaul... and some proper tests
// Two static parts because one may be enclosing jpsp (269522)
if (sig1 != null) {
if (sig1.indexOf("Lorg/aspectj/lang") != -1) {
if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
}
if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
}
if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
}
}
}
if (sig1 == null && ipeSig == null || (sig1 != null && sig1.equals(ipeSig))) {
String existingHandle = object.getHandleIdentifier();
int suffixPosition = existingHandle.indexOf('!');
if (suffixPosition != -1) {
count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
} else {
if (count == 1) {
count = 2;
}
}
}
}
}
}
// if (count > 1) {
return new Integer(count).toString().toCharArray();
// return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
// }
} else if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
int index = CharOperation.lastIndexOf('!', byteCodeName);
if (index != -1) {
return convertCount(CharOperation.subarray(byteCodeName, index + 1, byteCodeName.length));
}
} else if (ipe.getKind() == IProgramElement.Kind.CLASS) {
// depends on previous children
int count = 1;
List kids = ipe.getParent().getChildren();
if (ipe.getName().endsWith("{..}")) {
// only depends on previous anonymous children, name irrelevant
for (IProgramElement object : kids) {
if (object.equals(ipe)) {
break;
}
if (object.getKind() == ipe.getKind()) {
if (object.getName().endsWith("{..}")) {
String existingHandle = object.getHandleIdentifier();
int suffixPosition = existingHandle.lastIndexOf('!');
int lastSquareBracket = existingHandle.lastIndexOf('['); // type delimiter
if (suffixPosition != -1 && lastSquareBracket < suffixPosition) { // pr260384
count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
} else {
if (count == 1) {
count = 2;
}
}
}
}
}
} else {
for (IProgramElement object : kids) {
if (object.equals(ipe)) {
break;
}
if (object.getKind() == ipe.getKind()) {
if (object.getName().equals(ipe.getName())) {
String existingHandle = object.getHandleIdentifier();
int suffixPosition = existingHandle.lastIndexOf('!');
int lastSquareBracket = existingHandle.lastIndexOf('['); // type delimiter
if (suffixPosition != -1 && lastSquareBracket < suffixPosition) { // pr260384
count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
} else {
if (count == 1) {
count = 2;
}
}
}
}
}
}
if (count > 1) {
return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
}
}
return empty;
}
private String shortenIpeSig(String ipeSig) {
int idx;
if (ipeSig != null && ((idx = ipeSig.indexOf(")")) != -1)) {
ipeSig = ipeSig.substring(0, idx);
}
if (ipeSig != null) {
if (ipeSig.indexOf("Lorg/aspectj/lang") != -1) {
if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
}
if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
}
if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
}
}
}
return ipeSig;
}
private int computeCountBasedOnPeers(IProgramElement ipe) {
int count = 1;
for (IProgramElement object : ipe.getParent().getChildren()) {
if (object.equals(ipe)) {
break;
}
if (object.getKind() == ipe.getKind()) {
if (object.getKind().toString().equals(ipe.getKind().toString())) {
String existingHandle = object.getHandleIdentifier();
int suffixPosition = existingHandle.indexOf('!');
if (suffixPosition != -1) {
count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
} else {
if (count == 1) {
count = 2;
}
}
}
}
}
return count;
}
/**
* Only returns the count if it's not equal to 1
*/
private char[] convertCount(char[] c) {
if ((c.length == 1 && c[0] != ' ' && c[0] != '1') || c.length > 1) {
return CharOperation.concat(countDelim, c);
}
return empty;
}
public String getFileForHandle(String handle) {
IProgramElement node = asm.getHierarchy().getElement(handle);
if (node != null) {
return asm.getCanonicalFilePath(node.getSourceLocation().getSourceFile());
} else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
|| handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
// it's something like *MyAspect.aj or {MyClass.java. In other words
// it's a file node that's been created with no children and no
// parent
return backslash + handle.substring(1);
}
return emptyString;
}
public int getLineNumberForHandle(String handle) {
IProgramElement node = asm.getHierarchy().getElement(handle);
if (node != null) {
return node.getSourceLocation().getLine();
} else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
|| handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
// it's something like *MyAspect.aj or {MyClass.java. In other words
// it's a file node that's been created with no children and no
// parent
return 1;
}
return -1;
}
public int getOffSetForHandle(String handle) {
IProgramElement node = asm.getHierarchy().getElement(handle);
if (node != null) {
return node.getSourceLocation().getOffset();
} else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
|| handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
// it's something like *MyAspect.aj or {MyClass.java. In other words
// it's a file node that's been created with no children and no
// parent
return 0;
}
return -1;
}
public String createHandleIdentifier(ISourceLocation location) {
IProgramElement node = asm.getHierarchy().findElementForSourceLine(location);
if (node != null) {
return createHandleIdentifier(node);
}
return null;
}
public String createHandleIdentifier(File sourceFile, int line, int column, int offset) {
IProgramElement node = asm.getHierarchy().findElementForOffSet(sourceFile.getAbsolutePath(), line, offset);
if (node != null) {
return createHandleIdentifier(node);
}
return null;
}
public boolean dependsOnLocation() {
// handles are independent of soureLocations therefore return false
return false;
}
}