コード例 #1
0
  public static void patch(CtClass c, IPatcher patcher) throws Exception {
    treatClassToPatch(c);

    if (patcher != null) {
      patcher.initClass(c);
    }

    for (CtMethod m : c.getDeclaredMethods()) {
      boolean wasAbstract = false;
      String newBody = null;
      if (Modifier.isAbstract(m.getModifiers())) {
        m.setModifiers(m.getModifiers() - Modifier.ABSTRACT);
        wasAbstract = true;
      }
      if (patcher != null) {
        newBody = patcher.getNewBody(m);
      }
      if (newBody != null) {
        if (newBody.startsWith(AutomaticPatcher.INSERT_BEFORE)) {
          GwtPatcherUtils.insertBefore(
              m, newBody.substring(AutomaticPatcher.INSERT_BEFORE.length()));
        } else if (newBody.startsWith(AutomaticPatcher.INSERT_AFTER)) {
          GwtPatcherUtils.insertAfter(m, newBody.substring(AutomaticPatcher.INSERT_AFTER.length()));
        } else {
          GwtPatcherUtils.replaceImplementation(m, newBody);
        }
      } else if (wasAbstract) {
        if (patcher != null) {
          m.setBody(
              "{ throw new "
                  + UnsupportedOperationException.class.getName()
                  + "(\"Abstract method '"
                  + c.getSimpleName()
                  + "."
                  + m.getName()
                  + "()' is not patched by "
                  + patcher.getClass().getName()
                  + "\"); }");
        } else {
          m.setBody(
              "{ throw new "
                  + UnsupportedOperationException.class.getName()
                  + "(\"Abstract method '"
                  + c.getSimpleName()
                  + "."
                  + m.getName()
                  + "()' is not patched by any declared "
                  + IPatcher.class.getSimpleName()
                  + " instance\"); }");
        }
      }
    }

    if (patcher != null) {
      patcher.finalizeClass(c);
    }
  }
コード例 #2
0
  private void autoInjectGetSet(CtClass ctClass) throws Exception {

    // hibernate 可能需要 setter/getter 方法,好吧 我们为它添加这些方法

    for (CtField ctField : ctClass.getDeclaredFields()) {
      if (isFinal(ctField) || isStatic(ctField) || ctField.hasAnnotation(Validate.class)) continue;
      // Property name
      String propertyName =
          ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1);
      String getter = "get" + propertyName;
      String setter = "set" + propertyName;

      try {
        CtMethod ctMethod = ctClass.getDeclaredMethod(getter);
        if (ctMethod.getParameterTypes().length > 0 || Modifier.isStatic(ctMethod.getModifiers())) {
          throw new NotFoundException("it's not a getter !");
        }
      } catch (NotFoundException noGetter) {

        String code =
            "public "
                + ctField.getType().getName()
                + " "
                + getter
                + "() { return this."
                + ctField.getName()
                + "; }";
        CtMethod getMethod = CtMethod.make(code, ctClass);
        getMethod.setModifiers(getMethod.getModifiers() | AccessFlag.SYNTHETIC);
        ctClass.addMethod(getMethod);
      }

      try {
        CtMethod ctMethod = ctClass.getDeclaredMethod(setter);
        if (ctMethod.getParameterTypes().length != 1
            || !ctMethod.getParameterTypes()[0].equals(ctField.getType())
            || Modifier.isStatic(ctMethod.getModifiers())) {
          throw new NotFoundException("it's not a setter !");
        }
      } catch (NotFoundException noSetter) {
        CtMethod setMethod =
            CtMethod.make(
                "public void "
                    + setter
                    + "("
                    + ctField.getType().getName()
                    + " value) { this."
                    + ctField.getName()
                    + " = value; }",
                ctClass);
        setMethod.setModifiers(setMethod.getModifiers() | AccessFlag.SYNTHETIC);
        ctClass.addMethod(setMethod);
      }
    }
    ctClass.defrost();
  }
コード例 #3
0
  public String getNewBody(CtMethod m) throws Exception {
    CtMethod patchMethod = findPatchMethod(m);
    if (patchMethod == null) {
      return null;
    }

    processedMethods.add(patchMethod);

    // construction of the redirection code
    StringBuilder buffer = new StringBuilder();
    buffer.append("{");
    buffer.append("return ");
    buffer.append(patchMethod.getDeclaringClass().getName() + "." + patchMethod.getName());
    buffer.append("(");
    boolean append = false;

    if (!Modifier.isStatic(m.getModifiers())) {
      buffer.append("this");
      append = true;
    }
    for (int i = 0; i < m.getParameterTypes().length; i++) {
      if (append) {
        buffer.append(", ");
      }
      int j = i + 1;
      buffer.append("$" + j);
      append = true;
    }
    buffer.append(");");
    buffer.append("}");

    return buffer.toString();
  }
コード例 #4
0
  // this GwtCreateHandler has been introduced to make possible the
  // instanciation of abstract classes
  // that gwt-test-utils doesn't patch right now
  public Object create(Class<?> classLiteral) throws Exception {
    if (classLiteral.isAnnotation()
        || classLiteral.isArray()
        || classLiteral.isEnum()
        || classLiteral.isInterface()
        || !Modifier.isAbstract(classLiteral.getModifiers())) {
      return null;
    }

    Class<?> newClass = cache.get(classLiteral);

    if (newClass != null) {
      return newClass.newInstance();
    }

    CtClass ctClass = GwtClassPool.getCtClass(classLiteral);
    CtClass subClass = GwtClassPool.get().makeClass(classLiteral.getCanonicalName() + "SubClass");

    subClass.setSuperclass(ctClass);

    for (CtMethod m : ctClass.getDeclaredMethods()) {
      if (javassist.Modifier.isAbstract(m.getModifiers())) {
        CtMethod copy = new CtMethod(m, subClass, null);
        subClass.addMethod(copy);
      }
    }

    GwtPatcherUtils.patch(subClass, null);

    newClass = subClass.toClass(GwtClassLoader.get(), null);
    cache.put(classLiteral, newClass);

    return newClass.newInstance();
  }
コード例 #5
0
ファイル: Dispatcher.java プロジェクト: dtubest/Razor
  private Object[] extractParams(Mapping mapping, HttpServletRequest request) {
    Object[] params;

    ClassPool pool = ClassPool.getDefault();

    pool.insertClassPath(new ClassClassPath(mapping.clazz));

    CtMethod cm = null;
    CtClass[] parameterTypes = new CtClass[0];
    try {
      cm = pool.get(mapping.clazz.getName()).getDeclaredMethod(mapping.method.getName());
      parameterTypes = cm.getParameterTypes();
    } catch (NotFoundException e) {
      e.printStackTrace();
    }

    if (0 == parameterTypes.length) return new Object[0];

    params = new Object[parameterTypes.length];

    LocalVariableAttribute attr =
        (LocalVariableAttribute)
            cm.getMethodInfo().getCodeAttribute().getAttribute(LocalVariableAttribute.tag);
    int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
    for (int i = 0; i < params.length; i++) {
      String name = attr.variableName(i + pos);
      String typeName = parameterTypes[i].getName();

      Binder binder = Binder.valueOf(typeName);
      Object param = binder.get(name, request, mapping);
      params[i] = param;
    }

    return params;
  }
コード例 #6
0
ファイル: TransformCall.java プロジェクト: enenuki/phd
 /*  31:    */
 /*  32:    */ public TransformCall(Transformer next, String oldMethodName, CtMethod substMethod)
       /*  33:    */ {
   /*  34: 44 */ super(next);
   /*  35: 45 */ this.methodname = oldMethodName;
   /*  36: 46 */ this.methodDescriptor = substMethod.getMethodInfo2().getDescriptor();
   /*  37: 47 */ this.classname = (this.newClassname = substMethod.getDeclaringClass().getName());
   /*  38: 48 */ this.newMethodname = substMethod.getName();
   /*  39: 49 */ this.constPool = null;
   /*  40: 50 */ this.newMethodIsPrivate = Modifier.isPrivate(substMethod.getModifiers());
   /*  41:    */ }
コード例 #7
0
ファイル: PerstTranslator.java プロジェクト: kowalot/volante
 private void preprocessMethods(CtClass cc, boolean insertLoad, boolean wrapFieldAccess)
     throws CannotCompileException {
   CtMethod[] methods = cc.getDeclaredMethods();
   for (int i = 0; i < methods.length; i++) {
     CtMethod m = methods[i];
     if (wrapFieldAccess) {
       m.instrument(
           new ExprEditor() {
             public void edit(FieldAccess fa) throws CannotCompileException {
               try {
                 if ((fa.getField().getModifiers() & (Modifier.TRANSIENT | Modifier.STATIC)) == 0
                     && fa.getField().getDeclaringClass().subtypeOf(persistentInterface)) {
                   if (fa.isWriter()) {
                     fa.replace("{ $0.loadAndModify(); $proceed($$); }");
                   }
                   // isSelfReader is my extension of JAssist, if you
                   // use original version of JAssist comment the
                   // branch below or replace "else if" with "else".
                   // In first case Perst will not be able to handle
                   // access to foreign (non-this) fields. You should use
                   // getter/setter methods instead.
                   // In second case access to foreign fields still will be possible,
                   // but with significant degradation of performance and
                   // increased code size, because in this case before ALL access
                   // to fields of persistent capable object call of load() method
                   // will be inserted.
                   else if (!fa.isSelfReader()) {
                     fa.replace("{ $0.load(); $_ = $proceed($$); }");
                   }
                 }
               } catch (NotFoundException x) {
               }
             }
           });
     }
     if (insertLoad
         && !"recursiveLoading".equals(m.getName())
         && (m.getModifiers() & (Modifier.STATIC | Modifier.ABSTRACT)) == 0) {
       m.insertBefore("load();");
     }
   }
 }
コード例 #8
0
  private Set<CtMethod> getPatchMethods(Set<CtClass> patchClasses) {
    Set<CtMethod> result = new HashSet<CtMethod>();

    // add all @PatchMethod found in a temporary map
    Map<String, List<CtMethod>> temp = new HashMap<String, List<CtMethod>>();
    for (CtClass patchClass : patchClasses) {
      for (CtMethod ctMethod : patchClass.getDeclaredMethods()) {
        if (ctMethod.hasAnnotation(PatchMethod.class)) {
          if (!Modifier.isStatic(ctMethod.getModifiers())) {
            throw new GwtTestPatchException(
                "@"
                    + PatchMethod.class.getName()
                    + " has to be static : '"
                    + ctMethod.getLongName()
                    + "'");
          }
          String nameAndSignature =
              ctMethod.getName() + Descriptor.toString(ctMethod.getSignature());
          List<CtMethod> correspondingMethods = temp.get(nameAndSignature);

          if (correspondingMethods == null) {
            correspondingMethods = new ArrayList<CtMethod>();
            temp.put(nameAndSignature, correspondingMethods);
          }

          correspondingMethods.add(ctMethod);
        }
      }
    }

    // for each @PatchMethod with the same signature, filter to get one with
    // override=true
    for (Map.Entry<String, List<CtMethod>> entry : temp.entrySet()) {
      CtMethod methodToUse = getMethodToUse(entry.getValue(), PatchMethod.class);
      methodToUse.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
      result.add(methodToUse);
    }

    return result;
  }
コード例 #9
0
  private CtMethod getInitMethod(Set<CtClass> patchClasses) {
    List<CtMethod> initMethods = new ArrayList<CtMethod>();

    for (CtClass patchClass : patchClasses) {
      for (CtMethod ctMethod : patchClass.getDeclaredMethods()) {
        if (ctMethod.hasAnnotation(InitMethod.class)) {
          if (!Modifier.isStatic(ctMethod.getModifiers())) {
            throw new GwtTestPatchException(
                "@"
                    + InitMethod.class.getName()
                    + " has to be static : '"
                    + ctMethod.getLongName()
                    + "'");
          }
          try {
            if (ctMethod.getParameterTypes().length != 1
                || ctMethod.getParameterTypes()[0] != GwtClassPool.getCtClass(CtClass.class)) {
              throw new GwtTestPatchException(
                  "@"
                      + InitMethod.class.getName()
                      + " method must have one and only one parameter of type '"
                      + CtClass.class.getName()
                      + "'");
            }
          } catch (NotFoundException e) {
            // should never happen
            throw new GwtTestPatchException(e);
          }
          initMethods.add(ctMethod);
        }
      }
    }

    CtMethod initMethod = getMethodToUse(initMethods, InitMethod.class);
    if (initMethod != null) {
      initMethod.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
    }
    return initMethod;
  }
コード例 #10
0
 private static void removeNativeModifier(CtMethod m) throws Exception {
   if (Modifier.isNative(m.getModifiers())) {
     m.setModifiers(m.getModifiers() - Modifier.NATIVE);
   }
 }
コード例 #11
0
  @Override
  public void enhanceThisClass(ApplicationClass applicationClass) throws Exception {

    final CtClass ctClass = makeClass(applicationClass);
    if (ctClass.isInterface()) {
      return;
    }
    if (ctClass.getName().endsWith(".package")) {
      return;
    }

    // Add a default constructor if needed
    try {
      boolean hasDefaultConstructor = false;
      for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
        if (constructor.getParameterTypes().length == 0) {
          hasDefaultConstructor = true;
          break;
        }
      }
      if (!hasDefaultConstructor && !ctClass.isInterface()) {
        CtConstructor defaultConstructor =
            CtNewConstructor.make("public " + ctClass.getSimpleName() + "() {}", ctClass);
        ctClass.addConstructor(defaultConstructor);
      }
    } catch (Exception e) {
      Logger.error(e, "Error in PropertiesEnhancer");
      throw new UnexpectedException("Error in PropertiesEnhancer", e);
    }

    if (isScala(applicationClass)) {
      // Temporary hack for Scala. Done.
      applicationClass.enhancedByteCode = ctClass.toBytecode();
      ctClass.defrost();
      return;
    }

    for (CtField ctField : ctClass.getDeclaredFields()) {
      try {

        if (isProperty(ctField)) {

          // Property name
          String propertyName =
              ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1);
          String getter = "get" + propertyName;
          String setter = "set" + propertyName;

          try {
            CtMethod ctMethod = ctClass.getDeclaredMethod(getter);
            if (ctMethod.getParameterTypes().length > 0
                || Modifier.isStatic(ctMethod.getModifiers())) {
              throw new NotFoundException("it's not a getter !");
            }
          } catch (NotFoundException noGetter) {

            // Créé le getter
            String code =
                "public "
                    + ctField.getType().getName()
                    + " "
                    + getter
                    + "() { return this."
                    + ctField.getName()
                    + "; }";
            CtMethod getMethod = CtMethod.make(code, ctClass);
            getMethod.setModifiers(getMethod.getModifiers() | AccessFlag.SYNTHETIC);
            ctClass.addMethod(getMethod);
          }

          if (!isFinal(ctField)) {
            try {
              CtMethod ctMethod = ctClass.getDeclaredMethod(setter);
              if (ctMethod.getParameterTypes().length != 1
                  || !ctMethod.getParameterTypes()[0].equals(ctField.getType())
                  || Modifier.isStatic(ctMethod.getModifiers())) {
                throw new NotFoundException("it's not a setter !");
              }
            } catch (NotFoundException noSetter) {
              // Créé le setter
              CtMethod setMethod =
                  CtMethod.make(
                      "public void "
                          + setter
                          + "("
                          + ctField.getType().getName()
                          + " value) { this."
                          + ctField.getName()
                          + " = value; }",
                      ctClass);
              setMethod.setModifiers(setMethod.getModifiers() | AccessFlag.SYNTHETIC);
              ctClass.addMethod(setMethod);
              createAnnotation(getAnnotations(setMethod), PlayPropertyAccessor.class);
            }
          }
        }

      } catch (Exception e) {
        Logger.error(e, "Error in PropertiesEnhancer");
        throw new UnexpectedException("Error in PropertiesEnhancer", e);
      }
    }

    // Add a default constructor if needed
    try {
      boolean hasDefaultConstructor = false;
      for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
        if (constructor.getParameterTypes().length == 0) {
          hasDefaultConstructor = true;
          break;
        }
      }
      if (!hasDefaultConstructor) {
        CtConstructor defaultConstructor = CtNewConstructor.defaultConstructor(ctClass);
        ctClass.addConstructor(defaultConstructor);
      }
    } catch (Exception e) {
      Logger.error(e, "Error in PropertiesEnhancer");
      throw new UnexpectedException("Error in PropertiesEnhancer", e);
    }

    // Intercept all fields access
    for (final CtBehavior ctMethod : ctClass.getDeclaredBehaviors()) {
      ctMethod.instrument(
          new ExprEditor() {

            @Override
            public void edit(FieldAccess fieldAccess) throws CannotCompileException {
              try {

                // Acces à une property ?
                if (isProperty(fieldAccess.getField())) {

                  // TODO : vérifier que c'est bien un champ d'une classe de l'application
                  // (fieldAccess.getClassName())

                  // Si c'est un getter ou un setter
                  String propertyName = null;
                  if (fieldAccess
                          .getField()
                          .getDeclaringClass()
                          .equals(ctMethod.getDeclaringClass())
                      || ctMethod
                          .getDeclaringClass()
                          .subclassOf(fieldAccess.getField().getDeclaringClass())) {
                    if ((ctMethod.getName().startsWith("get")
                            || (!isFinal(fieldAccess.getField())
                                && ctMethod.getName().startsWith("set")))
                        && ctMethod.getName().length() > 3) {
                      propertyName = ctMethod.getName().substring(3);
                      propertyName =
                          propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
                    }
                  }

                  // On n'intercepte pas le getter de sa propre property
                  if (propertyName == null || !propertyName.equals(fieldAccess.getFieldName())) {

                    String invocationPoint =
                        ctClass.getName()
                            + "."
                            + ctMethod.getName()
                            + ", line "
                            + fieldAccess.getLineNumber();

                    if (fieldAccess.isReader()) {

                      // Réécris l'accés en lecture à la property
                      fieldAccess.replace(
                          "$_ = ($r)play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeReadProperty($0, \""
                              + fieldAccess.getFieldName()
                              + "\", \""
                              + fieldAccess.getClassName()
                              + "\", \""
                              + invocationPoint
                              + "\");");

                    } else if (!isFinal(fieldAccess.getField()) && fieldAccess.isWriter()) {

                      // Réécris l'accés en ecriture à la property
                      fieldAccess.replace(
                          "play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeWriteProperty($0, \""
                              + fieldAccess.getFieldName()
                              + "\", "
                              + fieldAccess.getField().getType().getName()
                              + ".class, $1, \""
                              + fieldAccess.getClassName()
                              + "\", \""
                              + invocationPoint
                              + "\");");
                    }
                  }
                }

              } catch (Exception e) {
                throw new UnexpectedException("Error in PropertiesEnhancer", e);
              }
            }
          });
    }

    // Done.
    applicationClass.enhancedByteCode = ctClass.toBytecode();
    ctClass.defrost();
  }
コード例 #12
0
  /**
   * Creates a map of concrete json request handler invokers keyed by <b><code>
   * &lt;service-name&gt;/&lt;op-name&gt;</code></b>.
   *
   * @param handlerInstance The request handler instance to generate invokers for
   * @return the map of generated invokers
   */
  public static Map<String, Map<String, AbstractJSONRequestHandlerInvoker>> createInvokers(
      Object handlerInstance) {
    if (handlerInstance == null)
      throw new IllegalArgumentException("The passed handlerInstance was null");
    Map<String, AbstractJSONRequestHandlerInvoker> subInvokerMap =
        new HashMap<String, AbstractJSONRequestHandlerInvoker>();
    Map<String, Map<String, AbstractJSONRequestHandlerInvoker>> invokerMap =
        invokerCache.get(handlerInstance.getClass());
    if (invokerMap != null) {
      LOG.info("Found Cached Invokers for [{}]", handlerInstance.getClass().getName());
      return invokerMap;
    }
    invokerMap = new HashMap<String, Map<String, AbstractJSONRequestHandlerInvoker>>(1);

    LOG.info("Generating Invokers for [{}]", handlerInstance.getClass().getName());
    JSONRequestService svc = handlerInstance.getClass().getAnnotation(JSONRequestService.class);
    final String invokerServiceKey = svc.name();
    final String invokerServiceDescription = svc.description();

    invokerMap.put(invokerServiceKey, subInvokerMap);

    ClassPool cp = new ClassPool();
    cp.appendClassPath(new ClassClassPath(handlerInstance.getClass()));
    cp.appendClassPath(new ClassClassPath(AbstractJSONRequestHandlerInvoker.class));
    cp.importPackage(handlerInstance.getClass().getPackage().getName());
    Set<ClassLoader> classPathsAdded = new HashSet<ClassLoader>();
    Set<String> packagesImported = new HashSet<String>();
    try {
      final CtClass jsonRequestCtClass = cp.get(JSONRequest.class.getName());
      final CtClass parent = cp.get(AbstractJSONRequestHandlerInvoker.class.getName());
      CtClass targetClass = cp.get(handlerInstance.getClass().getName());
      Collection<Method> methods = getTargetMethods(handlerInstance.getClass());
      for (Method m : methods) {
        final JSONRequestHandler jsonHandler = m.getAnnotation(JSONRequestHandler.class);
        final String opName = jsonHandler.name();
        final String opDescription = jsonHandler.description();
        final RequestType opType = jsonHandler.type();

        int targetMethodHashCode = m.toGenericString().hashCode();
        final String className =
            String.format(
                "%s-%s%s-%s-%s",
                handlerInstance.getClass().getName(),
                invokerServiceKey,
                opName,
                "ServiceInvoker",
                targetMethodHashCode);

        final CtClass invokerClass = cp.makeClass(className, parent);
        CtField ctf = new CtField(targetClass, "typedTarget", invokerClass);
        ctf.setModifiers(ctf.getModifiers() | Modifier.FINAL);
        invokerClass.addField(ctf);
        for (CtConstructor parentCtor : parent.getConstructors()) {
          CtConstructor invokerCtor = CtNewConstructor.copy(parentCtor, invokerClass, null);
          invokerCtor.setBody(
              "{ super($$); typedTarget = (" + handlerInstance.getClass().getName() + ")$1; }");
          invokerClass.addConstructor(invokerCtor);
        }
        CtMethod invokerMethod =
            CtNewMethod.copy(
                parent.getDeclaredMethod("doInvoke", new CtClass[] {jsonRequestCtClass}),
                invokerClass,
                null);
        StringBuilder b = new StringBuilder("{this.typedTarget.").append(m.getName()).append("($1");
        final Class<?>[] ptypes = m.getParameterTypes();
        final int remainingParamCount = ptypes.length - 1;
        //				Set<Class<?>> classPathsAdded = new HashSet<Class<?>>();
        //				Set<String> packagesImported = new HashSet<String>();
        if (remainingParamCount > 0) {
          for (int i = 0; i < remainingParamCount; i++) {
            final Class<?> type = ptypes[i + 1];
            if (type.getName().contains("UniqueIdType")) {
              System.err.println("Comin Up....");
            }
            if (type.isPrimitive()) {
              b.append(", (").append(type.getName()).append(") null");
            } else {
              if (classPathsAdded.add(type.getClassLoader())) {
                cp.appendClassPath(new LoaderClassPath(type.getClassLoader()));
              }
              try {
                Package p = type.getPackage();
                if (p == null) {
                  if (type.isArray()) {
                    if (!type.getComponentType().isPrimitive()) {
                      p = type.getComponentType().getPackage();
                    }
                  }
                }
                if (type.isEnum()) {
                  final String f = type.getEnclosingClass().getName() + "." + type.getSimpleName();
                  b.append(", (").append(f).append(") null");
                  String pack = type.getEnclosingClass().getPackage().getName();
                  if (packagesImported.add(pack)) {
                    cp.importPackage(pack);
                  }
                  continue;
                }

                if (p != null) {
                  if (packagesImported.add(p.getName())) {
                    cp.importPackage(p.getName());
                  }
                }
              } catch (Exception ex) {
                ex.printStackTrace(System.err);
              }
              b.append(", (").append(type.getSimpleName()).append(") null");
            }
          }
        }

        b.append(");}");
        System.out.println("[" + m.getName() + "]: [" + b.toString() + "]");
        // invokerMethod.setBody("{this.typedTarget." + m.getName() + "($1);}");
        invokerMethod.setBody(b.toString());
        invokerMethod.setModifiers(invokerMethod.getModifiers() & ~Modifier.ABSTRACT);
        invokerClass.addMethod(invokerMethod);
        // invokerClass.writeFile(System.getProperty("java.io.tmpdir") + File.separator +
        // "jsoninvokers");
        Class<?> clazz =
            invokerClass.toClass(
                handlerInstance.getClass().getClassLoader(),
                handlerInstance.getClass().getProtectionDomain());
        Constructor<?> ctor =
            clazz.getDeclaredConstructor(
                Object.class,
                String.class,
                String.class,
                String.class,
                String.class,
                RequestType.class);
        AbstractJSONRequestHandlerInvoker invokerInstance =
            (AbstractJSONRequestHandlerInvoker)
                ctor.newInstance(
                    handlerInstance,
                    invokerServiceKey,
                    invokerServiceDescription,
                    opName,
                    opDescription,
                    opType);
        subInvokerMap.put(opName, invokerInstance);
      }
      invokerCache.put(handlerInstance.getClass(), invokerMap);
      return invokerMap;
    } catch (Exception ex) {
      LOG.error(
          "Failed to create RequestHandlerInvoker for [{}]",
          handlerInstance.getClass().getName(),
          ex);
      throw new RuntimeException(
          "Failed to create RequestHandlerInvoker [" + handlerInstance.getClass().getName() + "]",
          ex);
    }
  }
コード例 #13
0
  @Override
  public void enhanceThisClass(ApplicationClass applicationClass) throws Exception {
    CtClass ctClass = makeClass(applicationClass);
    String entityName = ctClass.getName();
    Logger.debug("Enhance class " + entityName);

    // Only enhance Neo4jModel classes.
    if (!ctClass.subtypeOf(classPool.get("play.modules.neo4j.model.Neo4jModel"))) {
      return;
    }

    // Add a default constructor if needed
    try {
      for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
        if (constructor.getParameterTypes().length == 0) {
          ctClass.removeConstructor(constructor);
        }
        if (constructor.getParameterTypes().length == 1
            && constructor.getParameterTypes()[0].getClass().isInstance(Node.class)) {
          ctClass.removeConstructor(constructor);
        }
      }
      if (!ctClass.isInterface()) {
        Logger.debug("Adding default constructor");
        CtConstructor defaultConstructor =
            CtNewConstructor.make("public " + ctClass.getSimpleName() + "() { super();}", ctClass);
        ctClass.addConstructor(defaultConstructor);
      }
    } catch (Exception e) {
      Logger.error(e, "Error in PropertiesEnhancer");
      throw new UnexpectedException("Error in PropertiesEnhancer", e);
    }

    // for all field, we add getter / setter
    for (CtField ctField : ctClass.getDeclaredFields()) {
      try {
        // Property name
        String propertyName =
            ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1);
        String getter = "get" + propertyName;
        String setter = "set" + propertyName;

        Logger.debug("Field " + ctField.getName() + " is a property ?");
        if (isProperty(ctField)) {
          Logger.debug("true");

          // ~~~~~~~~~
          // GETTER
          // ~~~~~~~
          try {
            CtMethod ctMethod = ctClass.getDeclaredMethod(getter);
            if (!ctMethod.getName().equalsIgnoreCase("getShouldBeSave")) {
              ctClass.removeMethod(ctMethod);
              throw new NotFoundException("it's not a true getter !");
            }
          } catch (NotFoundException noGetter) {
            // create getter
            Logger.debug("Adding getter " + getter + " for class " + entityName);
            // @formatter:off
            String code =
                "public "
                    + ctField.getType().getName()
                    + " "
                    + getter
                    + "() {"
                    + "if(this.shouldBeSave == Boolean.FALSE && this.node != null){"
                    + "return (("
                    + ctField.getType().getName()
                    + ") play.modules.neo4j.util.Binder.bindFromNeo4jFormat(this.node.getProperty(\""
                    + ctField.getName()
                    + "\", null),"
                    + ctField.getType().getName()
                    + ".class ));"
                    + "}else{"
                    + "return "
                    + ctField.getName()
                    + ";"
                    + "}"
                    + "}";
            // @formatter:on
            Logger.debug(code);
            CtMethod getMethod = CtMethod.make(code, ctClass);
            ctClass.addMethod(getMethod);
          }

          // ~~~~~~~~~
          // SETTER
          // ~~~~~~~
          try {
            CtMethod ctMethod = ctClass.getDeclaredMethod(setter);
            if (ctMethod.getParameterTypes().length != 1
                || !ctMethod.getParameterTypes()[0].equals(ctField.getType())
                || Modifier.isStatic(ctMethod.getModifiers())
                || hasPlayPropertiesAccessorAnnotation(ctMethod)) {
              if (hasPlayPropertiesAccessorAnnotation(ctMethod)) {
                ctClass.removeMethod(ctMethod);
              }
              throw new NotFoundException("it's not a true setter !");
            }
          } catch (NotFoundException noSetter) {
            // create setter
            Logger.debug("Adding setter " + setter + " for class " + entityName);
            // @formatter:off
            String code =
                "public void "
                    + setter
                    + "("
                    + ctField.getType().getName()
                    + " value) { "
                    + "this."
                    + ctField.getName()
                    + " = value;"
                    + "this.shouldBeSave = Boolean.TRUE;"
                    + "}";
            // formatter:on
            CtMethod setMethod = CtMethod.make(code, ctClass);
            Logger.debug(code);
            ctClass.addMethod(setMethod);
          }
        } else {
          // ~~~~~~~~~
          // GETTER for neo4j relation property
          // ~~~~~~~
          if (hasNeo4jRelationAnnotation(ctField)) {
            // test for related annotation
            Neo4jRelatedTo relatedTo = getRelatedAnnotation(ctField);
            if (relatedTo != null) {
              CtMethod ctMethod = ctClass.getDeclaredMethod(getter);
              ctClass.removeMethod(ctMethod);
              String code;
              if (relatedTo.lazy()) {
                // @formatter:off
                code =
                    "public "
                        + ctField.getType().getName()
                        + " "
                        + getter
                        + "() {"
                        + "if(this."
                        + ctField.getName()
                        + " == null){"
                        + "java.lang.reflect.Field field = this.getClass().getField(\""
                        + ctField.getName()
                        + "\");"
                        + "this."
                        + ctField.getName()
                        + "=play.modules.neo4j.relationship.Neo4jRelationFactory.getModelsFromRelation(\""
                        + relatedTo.value()
                        + "\", \""
                        + relatedTo.direction()
                        + "\", field, this.node);"
                        + "}"
                        + "return "
                        + ctField.getName()
                        + ";"
                        + "}";
                // @formatter:on
              } else {
                // @formatter:off
                code =
                    "public "
                        + ctField.getType().getName()
                        + " "
                        + getter
                        + "() {"
                        + "return "
                        + ctField.getName()
                        + ";"
                        + "}";
                // @formatter:on
              }
              Logger.debug(code);
              CtMethod method = CtMethod.make(code, ctClass);
              ctClass.addMethod(method);
            }
            // test for unique relation annotation
            Neo4jUniqueRelation uniqueRelation = getUniqueRelationAnnotation(ctField);
            if (uniqueRelation != null) {
              CtMethod ctMethod = ctClass.getDeclaredMethod(getter);
              ctClass.removeMethod(ctMethod);
              String code;
              // @formatter:off
              code =
                  "public "
                      + ctField.getType().getName()
                      + " "
                      + getter
                      + "() {"
                      + "return ("
                      + ctField.getType().getName()
                      + ")"
                      + ctField.getName()
                      + ";"
                      + "}";
              // @formatter:on
              Logger.debug(code);
              CtMethod method = CtMethod.make(code, ctClass);
              ctClass.addMethod(method);
            }
          }
        }
      } catch (Exception e) {
        Logger.error(e, "Error in PropertiesEnhancer");
        throw new UnexpectedException("Error in PropertiesEnhancer", e);
      }
    }

    // Adding getByKey() method
    Logger.debug("Adding getByKey() method for class " + entityName);
    // @formatter:off
    String codeGetByKey =
        "public static play.modules.neo4j.model.Neo4jModel getByKey(Long key) throws play.modules.neo4j.exception.Neo4jException {"
            + "return ("
            + entityName
            + ")_getByKey(key, \""
            + entityName
            + "\");"
            + "}";
    // @formatter:on
    Logger.debug(codeGetByKey);
    CtMethod getByKeyMethod = CtMethod.make(codeGetByKey, ctClass);
    ctClass.addMethod(getByKeyMethod);

    // ~~~~~~~~~~~~~~~
    // Adding findAll() method
    // @formatter:off
    String codeFindAll =
        "public static java.util.List findAll() {"
            + "return "
            + entityName
            + "._findAll(\""
            + entityName
            + "\");"
            + "}";
    // @formatter:on
    Logger.debug(codeFindAll);
    CtMethod findAllMethod = CtMethod.make(codeFindAll, ctClass);
    ctClass.addMethod(findAllMethod);

    // ~~~~~~~~~~~~~~~
    // Adding queryIndex() method
    // @formatter:off
    String queryIndex =
        "public static java.util.List queryIndex(String indexname, String query) {"
            + "return "
            + entityName
            + "._queryIndex(indexname, query);"
            + "}";
    // @formatter:on
    Logger.debug(queryIndex);
    CtMethod queryIndexMethod = CtMethod.make(queryIndex, ctClass);
    ctClass.addMethod(queryIndexMethod);

    // Done.
    applicationClass.enhancedByteCode = ctClass.toBytecode();
    ctClass.defrost();
  }
コード例 #14
0
  public ClazzInfo classProcessing(String clazzName)
      throws NotFoundException, CannotCompileException {
    ClassPool classPool = ClassPool.getDefault();
    CtClass cz = classPool.get(clazzName);
    classPool.importPackage(clazzName); // 继承
    classPool.importPackage("java.lang.reflect.Method"); // 添加反射引用

    CtClass newClass = classPool.makeClass(clazzName + "$MC_IMPL"); // 新建代理类
    newClass.setSuperclass(cz); // 继承

    // 构造块
    CtConstructor tempC;
    CtConstructor[] ctConstructors = cz.getDeclaredConstructors();
    newClass.addConstructor(CtNewConstructor.defaultConstructor(newClass));
    for (CtConstructor c : ctConstructors) {
      try {
        tempC = CtNewConstructor.copy(c, newClass, null);
        tempC.setBody("{super($$);}");
        newClass.addConstructor(tempC);
      } catch (Exception e) {
        // e.printStackTrace();
      }
    }

    // 字段块
    //		CtField[] ctFields = cz.getDeclaredFields();
    //		for (CtField f : ctFields)
    //			System.out.println(f.getFieldInfo().getConstantValue());

    // 方法块
    CtMethod[] ctMethods = cz.getDeclaredMethods();
    CtMethod tempM; // 复制方法名
    Map<String, Method> tempMethod = new HashMap<String, Method>();
    for (CtMethod m : ctMethods) {
      tempMethod.put(
          String.format(
              "%s %s %s(%s);",
              Modifier.toString(m.getModifiers()),
              m.getReturnType().getName(),
              m.getName(),
              Util.getParameterTypes(m.getParameterTypes())),
          null);
      // System.err.println(String.format("%s %s %s(%s);", Modifier.toString(m.getModifiers()),
      // m.getReturnType().getName(), m.getName(), Util.getParameterTypes(m.getParameterTypes())));
      tempM = CtNewMethod.copy(m, newClass, null);
      if ("void".equals(tempM.getReturnType().getName()))
        tempM.setBody("{super." + tempM.getName() + "($$);}");
      else tempM.setBody("{ return super." + tempM.getName() + "($$);}");
      //				CtNewMethod.make(src, declaring, delegateObj, delegateMethod)
      // 方法修改
      //			if (m.getName().equals("x")) {
      //				//tempM.setBody("{$proceed($$);}", "this", "mba");
      //				//tempM.setBody("{n nn = new n();" + "Method a = n.class.getDeclaredMethod(\"a\", new
      // Class[] { Integer.TYPE });" + "a.invoke(nn, new Object[] { Integer.valueOf(1) });}");
      //				tempM.setBody("{Method a = n.class.getDeclaredMethod(\"axx\", new Class[] { Integer.TYPE
      // });}");
      //			}
      newClass.addMethod(tempM);
    }

    // 测试输出
    try {
      newClass.writeFile("D:/Desktop");
    } catch (IOException e) {
      e.printStackTrace();
    }

    //		Class clazz = newClass.toClass();
    //		System.out.println(clazz.getCanonicalName());
    //		DefaultCachePoolFactory.newInstance().addNFloop4Map(new ClazzInfo(clazz, tempMethod),
    // DefaultPool.NORNAL_BEAN, clazz.getCanonicalName());
    //		return clazz;
    return new ClazzInfo(newClass.toClass(), tempMethod);
  }
コード例 #15
0
  /** Generate Javassist Proxy Classes */
  private static <T> void generateProxyClass(
      Class<T> primaryInterface, String superClassName, String methodBody) throws Exception {
    String newClassName = superClassName.replaceAll("(.+)\\.(\\w+)", "$1.Hikari$2");

    CtClass superCt = classPool.getCtClass(superClassName);
    CtClass targetCt = classPool.makeClass(newClassName, superCt);
    targetCt.setModifiers(Modifier.FINAL);

    System.out.println("Generating " + newClassName);

    targetCt.setModifiers(Modifier.PUBLIC);

    // Make a set of method signatures we inherit implementation for, so we don't generate delegates
    // for these
    Set<String> superSigs = new HashSet<>();
    for (CtMethod method : superCt.getMethods()) {
      if ((method.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
        superSigs.add(method.getName() + method.getSignature());
      }
    }

    Set<String> methods = new HashSet<>();
    Set<Class<?>> interfaces = getAllInterfaces(primaryInterface);
    for (Class<?> intf : interfaces) {
      CtClass intfCt = classPool.getCtClass(intf.getName());
      targetCt.addInterface(intfCt);
      for (CtMethod intfMethod : intfCt.getDeclaredMethods()) {
        final String signature = intfMethod.getName() + intfMethod.getSignature();

        // don't generate delegates for methods we override
        if (superSigs.contains(signature)) {
          continue;
        }

        // Ignore already added methods that come from other interfaces
        if (methods.contains(signature)) {
          continue;
        }

        // Ignore default methods (only for Jre8 or later)
        if (isDefaultMethod(intf, intfCt, intfMethod)) {
          continue;
        }

        // Track what methods we've added
        methods.add(signature);

        // Clone the method we want to inject into
        CtMethod method = CtNewMethod.copy(intfMethod, targetCt, null);

        String modifiedBody = methodBody;

        // If the super-Proxy has concrete methods (non-abstract), transform the call into a simple
        // super.method() call
        CtMethod superMethod = superCt.getMethod(intfMethod.getName(), intfMethod.getSignature());
        if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) {
          modifiedBody = modifiedBody.replace("((cast) ", "");
          modifiedBody = modifiedBody.replace("delegate", "super");
          modifiedBody = modifiedBody.replace("super)", "super");
        }

        modifiedBody = modifiedBody.replace("cast", primaryInterface.getName());

        // Generate a method that simply invokes the same method on the delegate
        if (isThrowsSqlException(intfMethod)) {
          modifiedBody = modifiedBody.replace("method", method.getName());
        } else {
          modifiedBody =
              "{ return ((cast) delegate).method($$); }"
                  .replace("method", method.getName())
                  .replace("cast", primaryInterface.getName());
        }

        if (method.getReturnType() == CtClass.voidType) {
          modifiedBody = modifiedBody.replace("return", "");
        }

        method.setBody(modifiedBody);
        targetCt.addMethod(method);
      }
    }

    targetCt.writeFile("target/classes");
  }