static {
   List<String> names = new ArrayList<String>();
   for (Method method : GroovyObject.class.getMethods()) {
     names.add(method.getName());
   }
   GROOVYOBJECT_METHOD_NAMESS = new HashSet<String>(names);
 }
  private void replaceObfuscatedMethodNames(AsmagicDiffVisitor dv) {
    for (MethodNode mn : dv.newMethods) {
      if (mn.visibleAnnotations != null) {
        for (Object oan : mn.visibleAnnotations) {
          AnnotationNode an = (AnnotationNode) oan;
          if (an.desc.contains("AsmagicMethodReplace")) {
            List<Object> vals = an.values;

            String alias = null;
            if (vals != null || vals.size() > 1) {
              alias = (String) vals.get(1);
              dv.methodsToReplace.put(alias, 1);
              mn.name = alias;
            }
          }
        }
      }
    }
  }
  /**
   * It is assumed that ALL CLASSES regardless of nesting, have unique names In addition, it is
   * assumed that there is not multi-level nesting A SOURCE STRUCTURE OBJECT CAN ONLY HANDLE ONE
   * LEVEL OF CLASS NESTING
   *
   * @param targetClass
   * @param depth
   * @throws IOException
   */
  private void findNestedInnerClasses(ClassNode2 targetClass, int depth) throws IOException {

    // saves the depth of a particular inner class
    depth++;

    // get the inner classes of a class
    List<InnerClassNode2> innerClassNodes = targetClass.innerClasses;

    // returns if there are no inner classes
    if (innerClassNodes == null) {
      return;
    } else {

      // if there are inner classes, each inner class is converted to a ClassStructure
      // object and stored in an ArrayList
      for (int i = 0; i < innerClassNodes.size(); i++) {
        classStructures.add(new ClassStructure(innerClassNodes.get(i).name, depth));
      }
    }
  }
Example #4
0
  /**
   * constructor allowing this transformer to be provided with access to the JVM's instrumentation
   * implementation
   *
   * @param inst the instrumentation object used to interface to the JVM
   * @param scriptPaths list of file paths for each input script
   * @param scriptTexts the text of each input script
   * @param isRedefine true if class redefinition is allowed false if not
   * @throws Exception if a script is in error
   */
  public Transformer(
      Instrumentation inst, List<String> scriptPaths, List<String> scriptTexts, boolean isRedefine)
      throws Exception {
    this.inst = inst;
    this.isRedefine = isRedefine;
    scriptRepository = new ScriptRepository(skipOverrideRules);
    loadCache = new LoadCache(inst);
    helperManager = new HelperManager(inst);

    Iterator<String> scriptsIter = scriptTexts.iterator();
    Iterator<String> filesIter = scriptPaths.iterator();
    while (scriptsIter.hasNext()) {
      String scriptText = scriptsIter.next();
      String file = filesIter.next();
      List<RuleScript> ruleScripts = scriptRepository.processScripts(scriptText, file);
      for (RuleScript ruleScript : ruleScripts) {
        String name = ruleScript.getName();
        RuleScript previous = scriptRepository.scriptForRuleName(name);
        if (previous == null) {
          scriptRepository.addScript(ruleScript);
        } else {
          StringBuffer buffer = new StringBuffer();
          buffer.append("Transformer : duplicate script name ");
          buffer.append(name);
          buffer.append("in file ");
          buffer.append(ruleScript.getFile());
          buffer.append("  line ");
          buffer.append(ruleScript.getLine());
          buffer.append("\n previously defined in file ");
          buffer.append(previous.getFile());
          buffer.append("  line ");
          buffer.append(previous.getLine());
          Exception ex = new Exception(buffer.toString());
          throw ex;
        }
      }
    }
  }
 private static List<Method> getInheritedMethods(Class baseClass, List<Method> methods) {
   Collections.addAll(methods, baseClass.getMethods());
   Class currentClass = baseClass;
   while (currentClass != null) {
     Method[] protectedMethods = currentClass.getDeclaredMethods();
     for (Method method : protectedMethods) {
       if (method.getName().indexOf('$') != -1) continue;
       if (Modifier.isProtected(method.getModifiers())
           && !containsEquivalentMethod(methods, method)) methods.add(method);
     }
     currentClass = currentClass.getSuperclass();
   }
   return methods;
 }
  /**
   * Construct a proxy generator. This generator is used when we need to create a proxy object for a
   * class or an interface given a map of closures.
   *
   * @param closureMap the delegates implementations
   * @param superClass corresponding to the superclass class visitor
   * @param interfaces extra interfaces the proxy should implement
   * @param proxyLoader the class loader which should be used to load the generated proxy
   * @param delegateClass if not null, generate a delegate field with the corresponding class
   * @param emptyBody if set to true, the unimplemented abstract methods will receive an empty body
   *     instead of throwing an {@link UnsupportedOperationException}.
   */
  public ProxyGeneratorAdapter(
      final Map<Object, Object> closureMap,
      final Class superClass,
      final Class[] interfaces,
      final ClassLoader proxyLoader,
      final boolean emptyBody,
      final Class delegateClass) {
    super(new ClassWriter(0));
    this.visitedMethods = new LinkedHashSet<Object>();
    this.delegatedClosures =
        closureMap.isEmpty() ? EMPTY_DELEGATECLOSURE_MAP : new HashMap<String, Boolean>();
    boolean wildcard = false;
    for (Map.Entry<Object, Object> entry : closureMap.entrySet()) {
      String name = entry.getKey().toString();
      if ("*".equals(name)) {
        wildcard = true;
      }
      this.delegatedClosures.put(name, Boolean.FALSE);
    }
    this.hasWildcard = wildcard;

    // if we have to delegate to another object, generate the appropriate delegate field
    // and collect the name of the methods for which delegation is active
    this.generateDelegateField = delegateClass != null;
    this.objectDelegateMethods =
        generateDelegateField
            ? createDelegateMethodList(delegateClass, interfaces)
            : EMPTY_STRING_SET;
    this.delegateClass = delegateClass;

    // a proxy is supposed to be a concrete class, so it cannot extend an interface.
    // If the provided superclass is an interface, then we replace the superclass with Object
    // and add this interface to the list of implemented interfaces
    boolean isSuperClassAnInterface = superClass.isInterface();
    this.superClass = isSuperClassAnInterface ? Object.class : superClass;

    // create the base list of classes which have possible methods to be overloaded
    this.classList = new LinkedList<Class>();
    this.classList.add(superClass);
    if (generateDelegateField) {
      classList.add(delegateClass);
    }
    if (interfaces != null) {
      Collections.addAll(this.classList, interfaces);
    }
    this.proxyName = proxyName();
    this.loader = proxyLoader != null ? new InnerLoader(proxyLoader) : findClassLoader(superClass);
    this.emptyBody = emptyBody;

    // generate bytecode
    ClassWriter writer = (ClassWriter) cv;
    ClassReader cr = createClassVisitor(Object.class);
    cr.accept(this, 0);
    byte[] b = writer.toByteArray();
    //        CheckClassAdapter.verify(new ClassReader(b), true, new PrintWriter(System.err));
    cachedClass = loader.defineClass(proxyName.replace('/', '.'), b);
    // cache no-arg constructor
    Class[] args =
        generateDelegateField ? new Class[] {Map.class, delegateClass} : new Class[] {Map.class};
    Constructor constructor;
    try {
      constructor = cachedClass.getConstructor(args);
    } catch (NoSuchMethodException e) {
      constructor = null;
    }
    cachedNoArgConstructor = constructor;
  }