All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.outbrain.ob1k.server.MethodParamNamesExtractor Maven / Gradle / Ivy

The newest version!
package com.outbrain.ob1k.server;


import org.objectweb.asm.*;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * Created by aronen on 2/12/14.
 * extract an ordered list of param names from all given methods
 * assumes that each method is non-static and is not a constructor
 */
public class MethodParamNamesExtractor {

  public static Map> extract(final Class type, final Collection methods) throws IOException {

    final InputStream classBytes = MethodParamNamesExtractor.class.getClassLoader().getResourceAsStream(toResourceName(type));
    final ClassReader cr = new ClassReader(classBytes);

    final Map methodsSignature = new HashMap<>();
    for (final Method method: methods) {
      methodsSignature.put(method.getName(), method);
    }

    if (methodsSignature.size() != new HashSet<>(methods).size()) {
      throw new IllegalArgumentException("method names must be unique in service: " + type.getName());
    }

    final Map> paramsMap = new HashMap<>();
    cr.accept(new ClassVisitor(Opcodes.ASM4) {
      public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
        final Method method = methodsSignature.get(name);
        if(method != null) {
          final SortedMap names = new TreeMap<>();
          paramsMap.put(method, names);

          return new MethodVisitor(Opcodes.ASM4) {
            @Override
            public void visitLocalVariable(final String name, final String description, final String signature, final Label start, final Label end, final int index) {
//              System.out.println("visiting: " + name + " ,desc: " + description + " ,signature: " + signature + " ,index: " + index);
              // zero index is always this in non-static, non constructor methods.
              // we collect all method params including local params and only at the end sort by index and take the first N actual request params.
              if (Modifier.isStatic(method.getModifiers()) || index > 0) {
                names.put(index, name);
              }
            }
          };
        } else {
          return super.visitMethod(access, name, desc, signature, exceptions);
        }
      }
    }, 0);

    final Map> result = new HashMap<>();
    for (final Method method : paramsMap.keySet()) {
      final SortedMap params = paramsMap.get(method);
      final List names = new ArrayList<>();
      final int length = method.getParameterTypes().length;
      int index = 0;
      for (final String name: params.values()) {
        if (index < length) {
          names.add(name);
        }
        index++;
      }
      result.put(method, names);
    }

    return result;
  }

  private static String toResourceName(final Class type) {
    return type.getName().replace('.', '/') + ".class";
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy