Logo Search packages:      
Sourcecode: aspectj version File versions

JDTLikeHandleProvider.java

/********************************************************************
 * 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: <tjp{Demo.java[Demo~main~\[QString; method with generic argument:
 * <pkg{MyClass.java[MyClass~myMethod~QList<QString;>; an aspect: <pkg*A1.aj}A1 advice with Integer arg:
 * <pkg*A8.aj}A8&afterReturning&QInteger; method call: <pkg*A10.aj[C~m1?method-call(void pkg.C.m2())
 * 
 */
00030 public class JDTLikeHandleProvider implements IElementHandleProvider {

      private final AsmManager asm;

      // Need to keep our own count of the number of initializers
      // because this information cannot be gained from the ipe.
      private int initializerCounter = 0;

      private static final char[] empty = new char[] {};
      private static final char[] countDelim = new char[] { HandleProviderDelimiter.COUNT.getDelimiter() };

      private static final String backslash = "\\";
      private static final String emptyString = "";

      public JDTLikeHandleProvider(AsmManager asm) {
            this.asm = asm;
      }

00048       public String createHandleIdentifier(IProgramElement ipe) {

            // AjBuildManager.setupModel --> top of the tree is either
            // <root> or the .lst file
            if (ipe == null || (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA) && ipe.getName().equals("<root>"))) {
                  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 (!<n>)
                  } 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 {
                                    handle.append(ipe.getName()).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 = (String) sourceRefs.get(i);
                        sb.append(HandleProviderDelimiter.getDelimiter(ipe));
                        sb.append(sourceRef);
                  }
            } else {
                  for (Iterator iter = parameterTypes.iterator(); iter.hasNext();) {
                        char[] element = (char[]) iter.next();
                        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 !<n> 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 "!<n>"
       */
00157       private char[] getCount(IProgramElement ipe) {
            // TODO could optimize this code
            char[] byteCodeName = ipe.getBytecodeName().toCharArray();

            if (ipe.getKind().isDeclareAnnotation()) {
                  // look at peer declares
                  int count = 1;
                  List kids = ipe.getParent().getChildren();
                  int idx = 0;
                  for (Iterator iterator = kids.iterator(); iterator.hasNext();) {
                        IProgramElement object = (IProgramElement) iterator.next();
                        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;
                                          }
                                    }
                              }
                        }
                  }
                  if (count > 1) {
                        return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
                  }
            } else if (ipe.getKind().isDeclare()) {
                  int index = CharOperation.lastIndexOf('_', byteCodeName);
                  if (index != -1) {
                        return convertCount(CharOperation.subarray(byteCodeName, index + 1, byteCodeName.length));
                  }
            } 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;
                  if (ipeSig != null && ((idx = ipeSig.indexOf(")")) != -1)) {
                        ipeSig = ipeSig.substring(0, idx);
                  }
                  for (Iterator iterator = kids.iterator(); iterator.hasNext();) {
                        IProgramElement object = (IProgramElement) iterator.next();
                        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();
            } 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 (Iterator iterator = kids.iterator(); iterator.hasNext();) {
                              IProgramElement object = (IProgramElement) iterator.next();
                              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 (Iterator iterator = kids.iterator(); iterator.hasNext();) {
                              IProgramElement object = (IProgramElement) iterator.next();
                              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;
      }

      /**
       * Only returns the count if it's not equal to 1
       */
00312       private char[] convertCount(char[] c) {
            if ((c.length == 1 && c[0] != ' ' && c[0] != '1') || c.length > 1) {
                  return CharOperation.concat(countDelim, c);
            }
            return empty;
      }

00319       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;
      }

00333       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;
      }

00361       public String createHandleIdentifier(ISourceLocation location) {
            IProgramElement node = asm.getHierarchy().findElementForSourceLine(location);
            if (node != null) {
                  return createHandleIdentifier(node);
            }
            return null;
      }

00369       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;
      }

00382       public void initialize() {
            // reset the initializer count. This ensures we return the
            // same handle as JDT for initializers.
            initializerCounter = 0;
      }
}

Generated by  Doxygen 1.6.0   Back to index