protected void replaceMethodCallInMethod(MethodDetail md)
        throws NotFoundException, CannotCompileException {
      String callingObject = ", null";
      if (!Modifier.isStatic(md.where.getModifiers())) {
        callingObject = ", this";
      }

      String invocationClassName = callerInfos.get(md.callerInfoField);
      String typedTargetObject =
          javassist.Modifier.isStatic(md.calledMethod.getModifiers())
              ? ""
              : "invocation.typedTargetObject=$0;";

      String replaced =
          methodByMethodInfoFromWeakReference("info", md.callerInfoField)
              + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { "
              + invocationClassName
              + " invocation = new "
              + invocationClassName
              + "    (info"
              + callingObject
              + ", $0, $args, info.getInterceptors());"
              + OptimizedBehaviourInvocations.setArguments(
                  md.calledMethod.getParameterTypes().length)
              + typedTargetObject
              + "invocation.setTargetObject($0);"
              + "$_ = ($r)invocation.invokeNext();"
              + "} else { "
              + "$_ = $proceed($$); "
              + "}";

      md.call.replace(replaced);
    }
예제 #2
0
  /**
   * Determine the name of parameter with index i in the given method. Use the locals attributes
   * about local variables from the classfile. Note: This is still work in progress.
   *
   * @param method
   * @param locals
   * @param i
   * @return the name of the parameter if available or a number if not.
   */
  static String parameterNameFor(CtBehavior method, LocalVariableAttribute locals, int i) {

    if (locals == null) {
      return Integer.toString(i + 1);
    }

    int modifiers = method.getModifiers();

    int j = i;

    if (Modifier.isSynchronized(modifiers)) {
      // skip object to synchronize upon.
      j++;
      // System.err.println("Synchronized");
    }
    if (Modifier.isStatic(modifiers) == false) {
      // skip "this"
      j++;
      // System.err.println("Instance");
    }
    String variableName = locals.variableName(j);
    // if (variableName.equals("this")) {
    // System.err.println("'this' returned as a parameter name for "
    // + method.getName() + " index " + j
    // +
    // ", names are probably shifted. Please submit source for class in slf4j bugreport");
    // }
    return variableName;
  }
 /**
  * Filters the caller methods.
  *
  * @param method the method to filter
  * @return boolean true if the method should be filtered away
  */
 private boolean methodFilterCaller(final CtBehavior method) {
   if (Modifier.isNative(method.getModifiers())
       || Modifier.isInterface(method.getModifiers())
       || method.getName().equals(TransformationUtil.GET_META_DATA_METHOD)
       || method.getName().equals(TransformationUtil.SET_META_DATA_METHOD)
       || method.getName().equals(TransformationUtil.CLASS_LOOKUP_METHOD)
       || method.getName().equals(TransformationUtil.GET_UUID_METHOD)) {
     return true;
   } else {
     return false;
   }
 }
예제 #4
0
파일: CtNewMethod.java 프로젝트: bily/fsxp
  private static CtMethod delegator0(CtMethod delegate, CtClass declaring)
      throws CannotCompileException, NotFoundException {
    MethodInfo deleInfo = delegate.getMethodInfo2();
    String methodName = deleInfo.getName();
    String desc = deleInfo.getDescriptor();
    ConstPool cp = declaring.getClassFile2().getConstPool();
    MethodInfo minfo = new MethodInfo(cp, methodName, desc);
    minfo.setAccessFlags(deleInfo.getAccessFlags());

    ExceptionsAttribute eattr = deleInfo.getExceptionsAttribute();
    if (eattr != null) minfo.setExceptionsAttribute((ExceptionsAttribute) eattr.copy(cp, null));

    Bytecode code = new Bytecode(cp, 0, 0);
    boolean isStatic = Modifier.isStatic(delegate.getModifiers());
    CtClass deleClass = delegate.getDeclaringClass();
    CtClass[] params = delegate.getParameterTypes();
    int s;
    if (isStatic) {
      s = code.addLoadParameters(params, 0);
      code.addInvokestatic(deleClass, methodName, desc);
    } else {
      code.addLoad(0, deleClass);
      s = code.addLoadParameters(params, 1);
      code.addInvokespecial(deleClass, methodName, desc);
    }

    code.addReturn(delegate.getReturnType());
    code.setMaxLocals(++s);
    code.setMaxStack(s < 2 ? 2 : s); // for a 2-word return value
    minfo.setCodeAttribute(code.toCodeAttribute());
    return new CtMethod(minfo, declaring);
  }
    protected void replaceMethodCallInCon(ConstructorDetail cd)
        throws CannotCompileException, NotFoundException {
      String invocationClassName = callerInfos.get(cd.callerInfoField);
      String typedTargetObject =
          javassist.Modifier.isStatic(cd.calledMethod.getModifiers())
              ? ""
              : "invocation.typedTargetObject=$0;";

      String replaced =
          methodByConInfoFromWeakReference("info", cd.callerInfoField)
              + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { "
              + invocationClassName
              + " invocation = new "
              + invocationClassName
              + "    (info, this, $0, $args, info.getInterceptors());"
              + typedTargetObject
              + OptimizedBehaviourInvocations.setArguments(
                  cd.calledMethod.getParameterTypes().length)
              + "invocation.setTargetObject($0);"
              + "$_ = ($r)invocation.invokeNext();"
              + "} else { "
              + "$_ = $proceed($$); "
              + "}";

      cd.call.replace(replaced);
    }
  // 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();
  }
    protected void replaceConCallInMethod(ConByMethodDetail cd)
        throws NotFoundException, CannotCompileException {
      // If target constructor is advisable we do not want to create an optimized invocation class
      // since the interceptor chain for its execution pointcut does not get invoked.
      if (cd.isTgtConAdvised) {
        super.replaceConCallInMethod(cd);
        return;
      }
      String callingObject = "null";
      if (!Modifier.isStatic(cd.where.getModifiers())) {
        callingObject = "this";
      }

      String invocationClassName = callerInfos.get(cd.callerInfoField);
      String replaced =
          conByMethodInfoFromWeakReference("info", cd.callerInfoField)
              + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { "
              + "java.lang.Object callingObject = "
              + callingObject
              + "; "
              + invocationClassName
              + " invocation = new "
              + invocationClassName
              + "    (info,"
              + callingObject
              + ", $args, info.getInterceptors());"
              + OptimizedBehaviourInvocations.setArguments(
                  cd.calledConstructor.getParameterTypes().length)
              + "$_ = ($r)invocation.invokeNext();"
              + "} else { "
              + "$_ = $proceed($$); "
              + "}";

      cd.call.replace(replaced);
    }
예제 #8
0
  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;
  }
 private FieldInjectionTarget(TargetMember targetMember, CtClass ctClass, CtField ctField) {
   super(targetMember, ctClass);
   this.ctField = ctField;
   if (!Modifier.isStatic(ctField.getModifiers())) {
     throw new InjectionException(
         "Field is not static [" + targetMember.getQualifiedName() + "]");
   }
 }
예제 #10
0
  @Test(groups = "unit", timeOut = 1000)
  public void test() throws ClassNotFoundException {
    final Collection<Class<?>> descriptionClasses = Lists.newArrayList();
    final URL url =
        AnnotationTests.class.getClassLoader().getResource("META-INF/jobs/persistence.xml");
    final String jpaConfigContents = InputContexts.toString(InputContexts.forUrl(url));
    final List<Class<? extends ActivityDescription>> activityDescriptionsMapped =
        Lists.newArrayList();
    for (final Class<? extends ActivityFactory<?>> factoryClass : FACTORIES) {
      // Make sure the class is make as a ManageBean to DI context picks it up.
      assert factoryClass.getAnnotation(ManagedBean.class) != null
          : "Factory class " + factoryClass + " is not annotated with @ManagedBean";

      // assert factoryClass.getDeclaredConstructors().length == 1;
      boolean foundInjectedConstructor = false;
      for (Constructor<?> constructor : factoryClass.getDeclaredConstructors()) {
        if (constructor.getParameterTypes().length == 0
            || constructor.getAnnotation(Inject.class) != null) {
          foundInjectedConstructor = true;
        }
      }
      assert foundInjectedConstructor;

      final ActivityFactoryFor factoryAnnotation =
          factoryClass.getAnnotation(ActivityFactoryFor.class);
      // Make sure this class specifies which ActivityDescription it acts an ActivityFactory for.
      assert factoryAnnotation != null;
      final Class<? extends ActivityDescription> descriptionClass = factoryAnnotation.value();
      activityDescriptionsMapped.add(descriptionClass);
      assert ActivityDescription.class.isAssignableFrom(descriptionClass);
      // Make sure there are not multiple descriptions per factory
      assert !descriptionClasses.contains(descriptionClass);

      // Make sure the description can be persisted
      assert descriptionClass.getAnnotation(Entity.class) != null
          : descriptionClass + " is not annotated with entity.";
      assert jpaConfigContents.contains(descriptionClass.getCanonicalName())
          : "Class " + descriptionClass.getCanonicalName() + " not found in JPA configuration.";
    }

    final Pattern pattern = Pattern.compile("\\<class\\>.*\\<");
    final Matcher matcher = pattern.matcher(jpaConfigContents);
    int start = 0;
    while (matcher.find(start)) {
      final int startIdx = matcher.start() + "<class>".length();
      final int endIdx = jpaConfigContents.indexOf("<", startIdx);
      final String classStr = jpaConfigContents.substring(startIdx, endIdx);
      final Class<?> clazz = Class.forName(classStr);
      if (ActivityDescription.class.isAssignableFrom(clazz)) {
        if (!Modifier.isAbstract(clazz.getModifiers())) {
          assert activityDescriptionsMapped.contains(clazz)
              : "No activity factory found for description class " + clazz;
        }
      }
      start = endIdx;
    }
  }
예제 #11
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);
    }
  }
예제 #12
0
 /*  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:    */ }
예제 #13
0
  private static void treatClassToPatch(CtClass c) throws CannotCompileException {
    if (c == null) {
      throw new IllegalArgumentException("the class to patch cannot be null");
    }

    int modifiers = c.getModifiers();

    if (Modifier.isAnnotation(modifiers)) {
      throw new IllegalArgumentException("the class to patch cannot be an annotation");
    }
    if (Modifier.isInterface(modifiers)) {
      throw new IllegalArgumentException("the class to patch cannot be an interface");
    }
    if (Modifier.isEnum(modifiers)) {
      throw new IllegalArgumentException("the class to patch cannot be an enum");
    }

    c.setModifiers(Modifier.PUBLIC);

    addDefaultConstructor(c);
  }
  public ObjBase makeValue(ObjectId id, DBObject rawData, Class<? extends ObjBase> c) {

    if (Modifier.isAbstract(c.getModifiers()) || Modifier.isInterface(c.getModifiers())) {
      // extract declared schema from result, use that class
      Object schemaId = rawData.get(ReservedFieldNames.SCHEMA);
      try {
        c = (Class<ObjBase>) ClassUtil.findClass(schemaId.toString());
      } catch (ClassNotFoundException ex) {
        log.warn("Could not find fallback schema {}", schemaId);
        return null;
      }
    }

    ObjBase value = makeStub(id, c, rawData);
    // update stub with the rest of the data,
    if (value != null && !(value instanceof Swappable))
      try {
        unmarshaller.unmarshall(Bson.createDocument(rawData), value, this);
      } catch (MarshallingException me) {
        log.warn(me.getMessage(), me);
      }

    return value;
  }
 private Map<String, CtField> collectReactiveFields(CtClass managedCtClass) {
   final Map<String, CtField> persistentFieldMap = new HashMap<String, CtField>();
   for (CtField ctField : managedCtClass.getDeclaredFields()) {
     // skip static fields, skip final fields, and skip fields added by enhancement
     if (Modifier.isStatic(ctField.getModifiers())
         || ctField.getName().startsWith(DROOLS_PREFIX)) {
       continue;
     }
     // skip outer reference in inner classes
     if ("this$0".equals(ctField.getName())) {
       continue;
     }
     // optimization: skip final field, unless it is a Reactive Collection/List/... in which case
     // we need to consider anyway:
     if (Modifier.isFinal(ctField.getModifiers())) {
       if (!isCtFieldACollection(ctField)) {
         continue;
       }
     }
     persistentFieldMap.put(ctField.getName(), ctField);
   }
   // CtClass.getFields() does not return private fields, while CtClass.getDeclaredFields() does
   // not return inherit
   for (CtField ctField : managedCtClass.getFields()) {
     if (ctField.getDeclaringClass().equals(managedCtClass)) {
       // Already processed above
       continue;
     }
     if (Modifier.isStatic(ctField.getModifiers())
         || ctField.getName().startsWith(DROOLS_PREFIX)) {
       continue;
     }
     persistentFieldMap.put(ctField.getName(), ctField);
   }
   return persistentFieldMap;
 }
예제 #16
0
 /**
  * Return whether or not the class has a method with the given name
  *
  * @param theClass the class to inspect
  * @param theName the name of the method to look for
  * @return true if the class contains the method, false otherwise
  */
 private static boolean hasMethod(CtClass theClass, String theName) {
   try {
     return theClass.getDeclaredMethod(theName) != null
         && !Modifier.isAbstract(theClass.getDeclaredMethod(theName).getModifiers());
   } catch (NotFoundException e) {
     try {
       if (theClass.getSuperclass() != null) {
         return hasMethod(theClass.getSuperclass(), theName);
       } else {
         return false;
       }
     } catch (NotFoundException e1) {
       return false;
     }
   }
 }
예제 #17
0
    AccessType(Method method) {
      int modifier = method.getModifiers();
      if (Modifier.isPrivate(modifier)) {
        throw new UnsupportedOperationException("method = private");
      }
      if (Modifier.isFinal(modifier)) {
        throw new UnsupportedOperationException("method = final");
      }

      this.method = method;

      accesssType = "";
      staticType = "";
      syncType = "";
      methodName = "";

      methodName = method.getName();

      if (Modifier.isProtected(modifier)) {
        accesssType = "protected";
      }
      if (Modifier.isPackage(modifier)) {
        accesssType = "";
      }
      if (Modifier.isPublic(modifier)) {
        accesssType = "public";
      }
      if (Modifier.isStatic(modifier)) {
        staticType = "static";
      }
      if (Modifier.isSynchronized(modifier)) {
        syncType = "synchronized";
      }

      returnType = createParameterName(method.getReturnType());

      Set<String> throwSet = new HashSet<String>();
      for (Class<?> ex : method.getExceptionTypes()) {
        throwSet.add(ex.getSimpleName());
      }
      this.throwSet = throwSet;

      List<Parameter> paramList = new ArrayList<Parameter>();
      for (Class<?> p : method.getParameterTypes()) {
        paramList.add(createParameterName(p));
      }
      this.paramList = paramList;
    }
 private CtField[] collectPersistentFields(CtClass managedCtClass) {
   final List<CtField> persistentFieldList = new LinkedList<CtField>();
   for (CtField ctField : managedCtClass.getDeclaredFields()) {
     // skip static fields and skip fields added by enhancement
     if (Modifier.isStatic(ctField.getModifiers())
         || ctField.getName().startsWith("$$_hibernate_")) {
       continue;
     }
     // skip outer reference in inner classes
     if ("this$0".equals(ctField.getName())) {
       continue;
     }
     if (enhancementContext.isPersistentField(ctField)) {
       persistentFieldList.add(ctField);
     }
   }
   return enhancementContext.order(
       persistentFieldList.toArray(new CtField[persistentFieldList.size()]));
 }
예제 #19
0
  /**
   * Get the bean proeprties from the given class
   *
   * @param thePool the class pool to use when creating new fields
   * @param theClass the class the new fields will belong to
   * @param theInterface the original bean class
   * @return a Map of the bean property names with the new field for the property as the value
   * @throws javassist.CannotCompileException thrown if there is an error generating the methods
   * @throws javassist.NotFoundException thrown if there is an error generating the methods
   */
  private static <T> Map<String, CtField> properties(
      final ClassPool thePool, final CtClass theClass, final Class<T> theInterface)
      throws NotFoundException, CannotCompileException {
    Map<String, CtField> aMap = new HashMap<String, CtField>();

    for (Method aMethod : theInterface.getDeclaredMethods()) {

      // see if we've already processed this method.  Normal .equals for a method will not work
      // because the classes have to be the same,
      // what we want is the semantics of isAssignableFrom, not .equals between the classes
      // declaring the methods.  Thus, the FINDER
      // predicate implementation does exactly that.  It's a copy of the Method.equals function, but
      // with the .equals for the declaring
      // class changed to isAssignableFrom so we get the expected behavior.
      FINDER.method = aMethod;

      if (Iterables2.find(processedMethods, FINDER)) {
        continue;
      }

      // we want to ignore methods with implementations, we should not override them.
      if (!Modifier.isAbstract(aMethod.getModifiers())) {

        // mark the method as one we've already handled in case we get this method again on a
        // superclass/interface
        processedMethods.add(aMethod);
        continue;
      }

      if (!aMethod.getName().startsWith("get")
          && !aMethod.getName().startsWith("is")
          && !aMethod.getName().startsWith("has")
          && !aMethod.getName().startsWith("set")) {

        if (EmpireOptions.STRICT_MODE) {
          throw new IllegalArgumentException(
              "Non-bean style methods found, implementations for them cannot not be generated");
        } else {
          LOGGER.warn(
              "Non-bean style methods found, implementations for them cannot not be generated : "
                  + aMethod.getName());
        }
      }

      String aProp = aMethod.getName().substring(aMethod.getName().startsWith("is") ? 2 : 3);

      aProp = String.valueOf(aProp.charAt(0)).toLowerCase() + aProp.substring(1);

      Class aType = null;
      Type generics = null;

      if (aMethod.getName().startsWith("get")
          || aMethod.getName().startsWith("is")
          || aMethod.getName().startsWith("has")) {
        aType = aMethod.getReturnType();
        generics = aMethod.getGenericReturnType();
      } else if (aMethod.getName().startsWith("set") && aMethod.getParameterTypes().length > 0) {
        aType = aMethod.getParameterTypes()[0];

        if (aMethod.getGenericParameterTypes() != null
            && aMethod.getGenericParameterTypes().length > 0) {
          generics = aMethod.getGenericParameterTypes()[0];
        }
      }

      if (aType != null) {
        CtField aNewField = new CtField(thePool.get(aType.getName()), aProp, theClass);

        if (generics != null && generics instanceof ParameterizedTypeImpl) {
          for (Type t : ((ParameterizedTypeImpl) generics).getActualTypeArguments()) {
            String aFlag = "";
            String aName;

            if (t instanceof WildcardTypeImpl) {
              WildcardTypeImpl aWildcard = (WildcardTypeImpl) t;
              // trying to suss out super v extends w/o resorting to string munging.
              if (aWildcard.getLowerBounds().length == 0 && aWildcard.getUpperBounds().length > 0) {
                // no lower bounds afaik indicates ? extends Foo
                aFlag = "+";
                aName = ((Class) aWildcard.getUpperBounds()[0]).getName();
              } else if (aWildcard.getLowerBounds().length > 0) {
                // lower & upper bounds I believe indicates something of the form Foo super Bar
                aFlag = "-";
                aName = ((Class) aWildcard.getLowerBounds()[0]).getName();
              } else {
                throw new CannotCompileException(
                    "Unknown or unsupported type signature found: " + t);
              }
            } else {
              aName = ((Class) t).getName();
            }

            aNewField
                .getFieldInfo()
                .addAttribute(
                    new SignatureAttribute(
                        aNewField.getFieldInfo().getConstPool(),
                        "L"
                            + aType.getName().replace('.', '/')
                            + "<"
                            + aFlag
                            + "L"
                            + aName.replace('.', '/')
                            + ";>;"));
          }
        }

        aMap.put(aProp, aNewField);
      }

      // mark the method as one we've already handled in case we get this method again on a
      // superclass/interface
      processedMethods.add(aMethod);
    }

    return aMap;
  }
예제 #20
0
 private static void removeNativeModifier(CtMethod m) throws Exception {
   if (Modifier.isNative(m.getModifiers())) {
     m.setModifiers(m.getModifiers() - Modifier.NATIVE);
   }
 }
예제 #21
0
  private static CtClass makeExpressionClass(
      Source.Staged staged, String superClassName, String memberClassName) {
    // Here we make the language class accessible!
    if (!Modifier.isPublic(staged.getLanguage().getModifiers())) {
      staged.getLanguage().setModifiers(Modifier.setPublic(staged.getLanguage().getModifiers()));
    }

    CtClass clazz;
    try {
      ClassPool cp = ClassPool.getDefault();

      CtClass superClass = cp.getCtClass(superClassName);
      clazz =
          cp.makeClass(
              superClass.getName()
                  + "$Generated"
                  + id
                  + "$"
                  + staged.getMember().getDeclaringClass().getName().replace(".", "_")
                  + "$"
                  + staged.getMember().getName().replace(".", "_"),
              superClass);
      id++;

      // Make accepted language static fields
      HashMap<CtClass, String> acceptedLanguageMap = new HashMap<>();
      for (Use.Argument a : staged.getArguments()) {
        for (CtClass l : a.getAcceptedLanguages()) {
          if (!acceptedLanguageMap.containsKey(l) && !l.equals(Util.LANGUAGE_CLASS)) {
            String lName = "acceptedLanguage" + acceptedLanguageMap.size();
            int lPersistentId = Dispatcher.addPersistent(l);
            CtField lField =
                CtField.make(
                    "private static final "
                        + CtClass.class.getName()
                        + " "
                        + lName
                        + " = ("
                        + CtClass.class.getName()
                        + ") "
                        + Util.DISPATCHER_CLASS.getName()
                        + ".removePersistent("
                        + lPersistentId
                        + ");",
                    clazz);
            clazz.addField(lField);

            acceptedLanguageMap.put(l, lName);
          }
        }
      }

      // Make language field
      String languageName = "language";
      int languagePersistentId = Dispatcher.addPersistent(staged.getLanguage());
      CtField languageField =
          CtField.make(
              "private static final "
                  + CtClass.class.getName()
                  + " "
                  + languageName
                  + " = ("
                  + CtClass.class.getName()
                  + ") "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".removePersistent("
                  + languagePersistentId
                  + ");",
              clazz);
      clazz.addField(languageField);

      // Make member field
      String memberName = "member";
      int memberPersistentId = Dispatcher.addPersistent(staged.getMember());
      CtField memberField =
          CtField.make(
              "private static final "
                  + memberClassName
                  + " "
                  + memberName
                  + " = ("
                  + memberClassName
                  + ")"
                  + Util.DISPATCHER_CLASS.getName()
                  + ".removePersistent("
                  + memberPersistentId
                  + ");",
              clazz);
      clazz.addField(memberField);

      // Make constructor
      String constructorSource =
          "private constructor("
              + Util.EXPRESSION_CLASS.getName()
              + "[] arguments, "
              + Util.STATIC_INFO_CLASS.getName()
              + " staticInfo, "
              + Util.CLOSURE_HOLDER_CLASS.getName()
              + " closureHolder) {\n"
              + "    super(arguments, staticInfo, closureHolder);\n"
              + "}";
      CtConstructor constructor = CtNewConstructor.make(constructorSource, clazz);
      clazz.addConstructor(constructor);

      // Make factory-like invoke methods
      ImmutableList<Use.Argument> args = staged.getArguments();
      StringBuilder invokeSource = new StringBuilder();
      if (staged.isStrict() || Util.isCarrier(staged.getType())) {
        invokeSource.append(
            "public static " + staged.getType().getCtClass().getName() + " invoke(");
      } else if (staged.getType().isReference()) {
        invokeSource.append("public static " + Util.LOCAL_CARRIER_CLASS.getName() + " invoke(");
      } else {
        invokeSource.append("public static " + clazz.getName() + " invoke(");
      }

      if (staged.getArguments().size() > 253) {
        invokeSource.append("Object[] objectArguments, ");
        if (!staged.getStaticInfoElements().isEmpty()) {
          invokeSource.append(Util.STATIC_INFO_CLASS.getName() + " staticInfo, ");
        }
        invokeSource.append(Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n");
        for (int i = 0; i < args.size(); i++) {
          if (Util.isGlobalCarrier(args.get(i).getType())) {
            invokeSource
                .append("    ")
                .append(Util.GLOBAL_CARRIER_CLASS.getName())
                .append(" argument")
                .append(i)
                .append(" = (")
                .append(Util.GLOBAL_CARRIER_CLASS.getName())
                .append(") objectArguments[")
                .append(i)
                .append("];\n");
          } else if (Util.isLocalCarrier(args.get(i).getType())
              || (args.get(i).getType().isReference()
                  && !Util.couldBeGlobalCarrier(args.get(i).getType()))) {
            invokeSource
                .append("    ")
                .append(Util.LOCAL_CARRIER_CLASS.getName())
                .append(" argument")
                .append(i)
                .append(" = (")
                .append(Util.LOCAL_CARRIER_CLASS.getName())
                .append(") objectArguments[")
                .append(i)
                .append("];\n");
          } else if (args.get(i).getType().isReference()) {
            invokeSource
                .append("    ")
                .append(Type.OBJECT.getCtClass().getName())
                .append(" argument")
                .append(i)
                .append(" = objectArguments[")
                .append(i)
                .append("];\n");
          } else {
            invokeSource
                .append("    ")
                .append(Util.EXPRESSION_CLASS.getName())
                .append(" argument")
                .append(i)
                .append(" = (")
                .append(Util.EXPRESSION_CLASS.getName())
                .append(") objectArguments[")
                .append(i)
                .append("];\n");
          }
        }
      } else {
        for (int i = 0; i < args.size(); i++) {
          if (Util.isGlobalCarrier(args.get(i).getType())) {
            invokeSource.append(Util.GLOBAL_CARRIER_CLASS.getName()).append(" argument").append(i);
          } else if (Util.isLocalCarrier(args.get(i).getType())
              || (args.get(i).getType().isReference()
                  && !Util.couldBeGlobalCarrier(args.get(i).getType()))) {
            invokeSource.append(Util.LOCAL_CARRIER_CLASS.getName()).append(" argument").append(i);
          } else if (args.get(i).getType().isReference()) {
            invokeSource.append(Type.OBJECT.getCtClass().getName()).append(" argument").append(i);
          } else {
            invokeSource.append(Util.EXPRESSION_CLASS.getName()).append(" argument").append(i);
          }
          invokeSource.append(", ");
        }

        if (!staged.getStaticInfoElements().isEmpty()) {
          invokeSource.append(Util.STATIC_INFO_CLASS.getName() + " staticInfo, ");
        }
        invokeSource.append(Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n");
      }

      invokeSource.append(
          "    "
              + Util.EXPRESSION_CLASS.getName()
              + " payload;\n"
              + "    "
              + Util.EXPRESSION_CLASS.getName()
              + "[] arguments = new "
              + Util.EXPRESSION_CLASS.getName()
              + "["
              + args.size()
              + "];\n");
      for (int i = 0; i < args.size(); i++) {
        if (Util.isGlobalCarrier(args.get(i).getType())) {
          invokeSource.append(
              "    payload = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".unloadGlobalCarrierChecked(argument"
                  + i
                  + ");\n"
                  + "    if (!("
                  + generateLanguageAcceptCheck(
                      "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ")) {\n"
                  + "        arguments["
                  + i
                  + "] = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".selfLiftGlobalCarrier(argument"
                  + i
                  + ");\n"
                  + "    } else {\n"
                  + "        arguments["
                  + i
                  + "] = payload;\n"
                  + "    }\n");
        } else if (Util.isLocalCarrier(args.get(i).getType())
            || (args.get(i).getType().isReference()
                && !Util.couldBeGlobalCarrier(args.get(i).getType()))) {
          invokeSource.append(
              "    payload = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".unloadLocalCarrierChecked(argument"
                  + i
                  + ");\n"
                  + "    if ("
                  + generateLanguageAcceptCheck(
                      "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ") {\n"
                  + "        arguments["
                  + i
                  + "] = payload.getRaw();\n"
                  + "    } else {\n"
                  + "        payload.evaluate();\n"

                  // This handles the weird case when the materialized argument could be globally
                  // carried and might need unloading and checking
                  // We know that it is an ObjectValue instance
                  + "        "
                  + Util.EXPRESSION_CLASS.getName()
                  + " value = payload.asValueIfEvaluated();\n"
                  + "        Object obj = value.materializeAsObject(); \n"
                  + "        if (obj instanceof "
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") {\n"
                  + "            payload = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".unloadGlobalCarrier(("
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") obj);\n"
                  + "            if (payload == null || !("
                  + generateLanguageAcceptCheck(
                      "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ")) {\n"
                  + "                arguments["
                  + i
                  + "] = value;\n"
                  + "            } else {\n"
                  + "                arguments["
                  + i
                  + "] = payload;\n"
                  + "            }\n"
                  + "        } else {\n"
                  + "            arguments["
                  + i
                  + "] = value;\n"
                  + "        }\n"
                  + "    }\n");
        } else if (args.get(i).getType().isReference()) {
          invokeSource.append(
              "    if (argument"
                  + i
                  + " instanceof "
                  + Util.LOCAL_CARRIER_CLASS.getName()
                  + ") {\n"
                  + "        payload = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".unloadLocalCarrierChecked(("
                  + Util.LOCAL_CARRIER_CLASS.getName()
                  + ") argument"
                  + i
                  + ");\n"
                  + "        if ("
                  + generateLanguageAcceptCheck(
                      "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ") {\n"
                  + "            arguments["
                  + i
                  + "] = payload.getRaw();\n"
                  + "        } else {\n"
                  + "            payload.evaluate();\n"

                  // This handles the weird case when the materialized argument could be globally
                  // carried and might need unloading and checking
                  // We know that it is an ObjectValue instance
                  + "            "
                  + Util.EXPRESSION_CLASS.getName()
                  + " value = payload.asValueIfEvaluated();\n"
                  + "            Object obj = value.materializeAsObject(); \n"
                  + "            if (obj instanceof "
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") {\n"
                  + "                payload = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".unloadGlobalCarrier(("
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") obj);\n"
                  + "                if (payload == null || !("
                  + generateLanguageAcceptCheck(
                      "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ")) {\n"
                  + "                    arguments["
                  + i
                  + "] = value;\n"
                  + "                } else {\n"
                  + "                    arguments["
                  + i
                  + "] = payload;\n"
                  + "                }\n"
                  + "            } else {\n"
                  + "                arguments["
                  + i
                  + "] = value;\n"
                  + "            }\n"
                  + "        }\n"
                  + "    } else if (argument"
                  + i
                  + " instanceof "
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") {\n"
                  + "        payload = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".unloadGlobalCarrierChecked(("
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") argument"
                  + i
                  + ");\n"
                  + "        if (!("
                  + generateLanguageAcceptCheck(
                      "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ")) {\n"
                  + "            arguments["
                  + i
                  + "] = "
                  + Util.DISPATCHER_CLASS.getName()
                  + ".selfLiftGlobalCarrier(("
                  + Util.GLOBAL_CARRIER_CLASS.getName()
                  + ") argument"
                  + i
                  + ");\n"
                  + "        } else {\n"
                  + "            arguments["
                  + i
                  + "] = payload;\n"
                  + "        }\n"
                  + "    } else {\n"
                  + "        arguments["
                  + i
                  + "] = "
                  + Util.DISPATCHER_CLASS.getName()
                  + "."
                  + Util.getLiftMethodName(Type.OBJECT)
                  + "(argument"
                  + i
                  + ");\n"
                  + "    }\n");
        } else {
          invokeSource.append(
              "    if ("
                  + generateLanguageAcceptCheck(
                      "argument" + i, args.get(i).getAcceptedLanguages(), acceptedLanguageMap)
                  + ") {\n"
                  + "        arguments["
                  + i
                  + "] = argument"
                  + i
                  + generateConversionSuffix(args.get(i).getType())
                  + ".getRaw();\n"
                  + "    } else {\n"
                  + "        argument"
                  + i
                  + ".evaluate();\n"
                  + "        arguments["
                  + i
                  + "] = argument"
                  + i
                  + ".asValueIfEvaluated();\n"
                  + "    }\n");
        }
      }
      String construction;
      if (!staged.getStaticInfoElements().isEmpty()) {
        construction = "new " + clazz.getName() + "(arguments, staticInfo, closureHolder)";
      } else {
        construction = "new " + clazz.getName() + "(arguments, null, closureHolder)";
      }
      if (staged.isStrict()) {
        Type type = staged.getType();
        if (type.isReference()) {
          invokeSource.append(
              "    return ("
                  + type.getCtClass().getName()
                  + ") ("
                  + construction
                  + ").materializeAsObject();\n");
        } else if (type.equals(Type.BOOLEAN)) {
          invokeSource.append("    return (" + construction + ").materializeAsBoolean();\n");
        } else if (type.equals(Type.INT)) {
          invokeSource.append("    return (" + construction + ").materializeAsInteger();\n");
        } else if (type.equals(Type.LONG)) {
          invokeSource.append("    return (" + construction + ").materializeAsLong();\n");
        } else if (type.equals(Type.FLOAT)) {
          invokeSource.append("    return (" + construction + ").materializeAsFloat();\n");
        } else if (type.equals(Type.DOUBLE)) {
          invokeSource.append("    return (" + construction + ").materializeAsDouble();\n");
        } else if (type.equals(Type.BYTE)) {
          invokeSource.append("    return (" + construction + ").materializeAsByte();\n");
        } else if (type.equals(Type.CHAR)) {
          invokeSource.append("    return (" + construction + ").materializeAsCharacter();\n");
        } else if (type.equals(Type.SHORT)) {
          invokeSource.append("    return (" + construction + ").materializeAsShort();\n");
        } else if (type.equals(Type.VOID)) {
          invokeSource.append("    return (" + construction + ").evaluate();\n");
        }
      } else {
        if (Util.isGlobalCarrier(staged.getType())) {
          if (staged.getType().getCtClass().equals(Util.GLOBAL_CARRIER_CLASS)) {
            invokeSource.append(
                "    return new "
                    + Util.GLOBAL_CARRIER_CLASS.getName()
                    + "("
                    + construction
                    + ");\n");
          } else {
            CarrierTransformer.transformCarrierChecked(staged.getType().getCtClass());
            invokeSource.append(
                "    return new "
                    + staged.getType().getCtClass().getName()
                    + "(("
                    + Util.DISAMBIGUATION_PARAMETER_CLASS.getName()
                    + ") null, "
                    + construction
                    + ");\n");
          }
        } else if (Util.isLocalCarrier(staged.getType())) {
          if (staged.getType().getCtClass().equals(Util.LOCAL_CARRIER_CLASS)) {
            invokeSource.append(
                "    return new "
                    + Util.LOCAL_CARRIER_CLASS.getName()
                    + "("
                    + construction
                    + ");\n");
          } else {
            CarrierTransformer.transformCarrierChecked(staged.getType().getCtClass());
            invokeSource.append(
                "    return new "
                    + staged.getType().getCtClass().getName()
                    + "(("
                    + Util.DISAMBIGUATION_PARAMETER_CLASS.getName()
                    + ") null, "
                    + construction
                    + ");\n");
          }
        } else if (staged.getType().isReference()) {
          invokeSource.append(
              "    return new " + Util.LOCAL_CARRIER_CLASS.getName() + "(" + construction + ");\n");
        } else {
          invokeSource.append("    return " + construction + ";\n");
        }
      }
      invokeSource.append("}");
      CtMethod invoke = CtMethod.make(invokeSource.toString(), clazz);
      clazz.addMethod(invoke);

      // Make isomorphic hash code method
      String isomorphicHashCodeSource =
          "int isomorphicHashCode() {\n"
              + "    if (!$0.isomorphicHashCodeHasBeenCalculated) {\n"
              + "        super.isomorphicHashCode("
              + staged.getMember().hashCode()
              + ");\n"
              + "    }"
              + "    return $0.isomorphicHashCode;"
              + "}";
      CtMethod isomorphicHashCode = CtMethod.make(isomorphicHashCodeSource, clazz);
      clazz.addMethod(isomorphicHashCode);

      // Make isomorphism check method
      String isIsomorphicToSource =
          "boolean isIsomorphicTo(java.util.IdentityHashMap identityMap, "
              + Util.EXPRESSION_CLASS.getName()
              + " expression) {\n"
              + "    if (!(expression instanceof "
              + clazz.getName()
              + ")) { return false; }\n"
              + "    return super.isIsomorphicTo(identityMap, expression);\n"
              + "}";
      CtMethod isIsomorphicTo = CtMethod.make(isIsomorphicToSource, clazz);
      clazz.addMethod(isIsomorphicTo);

      // Make cache clone (with empty leaves to save memory) creation method
      String cacheCloneSource =
          Util.EXPRESSION_CLASS.getName()
              + " cacheClone(java.util.IdentityHashMap identityMap) {\n"
              + "    "
              + Util.EXPRESSION_CLASS.getName()
              + " e = ("
              + Util.EXPRESSION_CLASS.getName()
              + ") identityMap.get(this);\n"
              + "    if (e != null) {\n"
              + "        return e;\n"
              + "    } else {\n"
              + "        "
              + Util.EXPRESSION_CLASS.getName()
              + "[] clonedArguments = super.cacheCloneArguments(identityMap);\n"
              + "        if (clonedArguments != null) {\n"
              + "            "
              + clazz.getName()
              + " s = new "
              + clazz.getName()
              + "(clonedArguments, $0.staticInfo, null);\n"
              + "            s.isomorphicHashCode = $0.isomorphicHashCode();\n"
              + "            s.isomorphicHashCodeHasBeenCalculated = true;\n"
              + "            identityMap.put(this, s);\n"
              + "            return s;\n"
              + "        } else {\n"
              + "            identityMap.put(this, this);\n"
              + "            return this;\n"
              + "        }\n"
              + "    }\n"
              + "}";
      CtMethod cacheClone = CtMethod.make(cacheCloneSource, clazz);
      clazz.addMethod(cacheClone);

      // Make language acceptance check method
      String isAcceptedBySource =
          "boolean isAcceptedBy("
              + CtClass.class.getName()
              + " language) { return $0.language.equals(language); }";
      CtMethod isAcceptedBy = CtMethod.make(isAcceptedBySource, clazz);
      clazz.addMethod(isAcceptedBy);

      // Make polymorphic member retrieval method
      String getMemberSource =
          "public " + memberClassName + " getMember() { return $0." + memberName + "; }";
      CtMethod getMember = CtMethod.make(getMemberSource, clazz);
      clazz.addMethod(getMember);

      // Make evaluation method
      Class<?> closureInterface = getClosureInterface(staged.getType());
      String evaluateSource;
      if (Util.isGlobalCarrier(staged.getType()) && !staged.isStrict()) {
        evaluateSource = "public void evaluate() { throw new UnsupportedOperationException(); }";
      } else {
        evaluateSource =
            "public void evaluate() {\n"
                + "    if ($0.value != null) { return; }\n"
                + "    "
                + closureInterface.getName()
                + " closure;\n"
                + "    "
                + Util.ENVIRONMENT_CLASS.getName()
                + " environment;\n"
                + "    if ($0.closureHolder == null) {\n"
                + "        "
                + Util.CLOSURE_HOLDER_CLASS.getName()
                + " cachedClosureHolder = "
                + GlobalCache.class.getName()
                + ".getCachedClosureHolder($0);\n"
                + "        if (cachedClosureHolder == null) {\n"
                + "            "
                + Util.BINDER_CLASS.getName()
                + " binder = new "
                + Util.BINDER_CLASS.getName()
                + "($0);\n"
                + "            closure = "
                + staged.getLanguage().getName()
                + ".make"
                + closureInterface.getSimpleName()
                + "($0, binder, false);\n"
                + "            environment = new "
                + Util.ENVIRONMENT_CLASS.getName()
                + "($0, binder.getBoundCount());\n"
                + "            if (!binder.inspectionOccurred()) {\n"
                + "                "
                + GlobalCache.class.getName()
                + ".cache($0, closure, binder.getBoundCount());\n"
                + "            }\n"
                + "        } else {\n"
                + "            closure = ("
                + closureInterface.getName()
                + ") cachedClosureHolder.getClosure();\n"
                + "            environment = new "
                + Util.ENVIRONMENT_CLASS.getName()
                + "($0, cachedClosureHolder.getEnvironmentSize());\n"
                + "        }\n"
                + "    } else {\n"
                + "        closure = ("
                + closureInterface.getName()
                + ") $0.closureHolder.getClosure();\n"
                + "        if (closure == null) {\n"
                + "            "
                + Util.CLOSURE_HOLDER_CLASS.getName()
                + " cachedClosureHolder = "
                + GlobalCache.class.getName()
                + ".getCachedClosureHolder($0);\n"
                + "            if (cachedClosureHolder == null) {\n"
                + "                "
                + Util.BINDER_CLASS.getName()
                + " binder = new "
                + Util.BINDER_CLASS.getName()
                + "($0);\n"
                + "                closure = "
                + staged.getLanguage().getName()
                + ".make"
                + closureInterface.getSimpleName()
                + "($0, binder, $0.closureHolder.isPermanent());\n"
                + "                environment = new "
                + Util.ENVIRONMENT_CLASS.getName()
                + "($0, binder.getBoundCount());\n"
                + "                if (!binder.inspectionOccurred()) {\n"
                + "                    $0.closureHolder.set(closure, binder.getBoundCount());\n"
                + "                    "
                + GlobalCache.class.getName()
                + ".cache($0, closure, binder.getBoundCount());\n"
                + "                }\n"
                + "            } else {\n"
                + "                closure = ("
                + closureInterface.getName()
                + ") cachedClosureHolder.getClosure();\n"
                + "                environment = new "
                + Util.ENVIRONMENT_CLASS.getName()
                + "($0, cachedClosureHolder.getEnvironmentSize());\n"
                + "                $0.closureHolder.set(closure, cachedClosureHolder.getEnvironmentSize());\n"
                + "            }\n"
                + "        } else {\n"
                + "            environment = new "
                + Util.ENVIRONMENT_CLASS.getName()
                + "($0, $0.closureHolder.getEnvironmentSize());\n"
                + "        }\n"
                + "    }\n"
                + (staged.getType().equals(Type.VOID)
                    ? "    closure.evaluate(environment);\n"
                    : "    $0.value = "
                        + Util.DISPATCHER_CLASS.getName()
                        + "."
                        + Util.getLiftMethodName(staged.getType())
                        + "(closure.evaluate(environment));\n")
                + "}";
      }
      CtMethod evaluate = CtMethod.make(evaluateSource, clazz);
      clazz.addMethod(evaluate);

      clazz.toClass();
    } catch (CannotCompileException | NotFoundException e) {
      throw new RuntimeException(e);
    }

    return clazz;
  }
 private boolean isJAXRSEntity(Class<?> javaClass, Class<? extends Annotation> annotation) {
   if (!hasAnnotation(javaClass, annotation)) return false;
   if (javaClass.isInterface() || Modifier.isAbstract(javaClass.getModifiers())) return false;
   return true;
 }
예제 #23
0
  private void enhance_(ApplicationClass applicationClass, boolean buildAuthorityRegistryOnly)
      throws Exception {
    Plugin.trace("about to enhance applicationClass: %s", applicationClass);
    CtClass ctClass = makeClass(applicationClass);
    Set<CtBehavior> s = new HashSet<CtBehavior>();
    s.addAll(Arrays.asList(ctClass.getDeclaredMethods()));
    s.addAll(Arrays.asList(ctClass.getMethods()));
    s.addAll(Arrays.asList(ctClass.getConstructors()));
    s.addAll(Arrays.asList(ctClass.getDeclaredConstructors()));
    for (final CtBehavior ctBehavior : s) {
      if (!Modifier.isPublic(ctBehavior.getModifiers())
          || javassist.Modifier.isAbstract(ctBehavior.getModifiers())) {
        continue;
      }

      boolean needsEnhance = false;
      RequireRight rr = null;
      RequirePrivilege rp = null;
      RequireAccounting ra = null;
      boolean allowSystem = false;
      Object[] aa = ctBehavior.getAnnotations();
      for (Object o : aa) {
        if (o instanceof RequirePrivilege) {
          needsEnhance = true;
          rp = (RequirePrivilege) o;
          continue;
        }
        if (o instanceof RequireRight) {
          needsEnhance = true;
          rr = (RequireRight) o;
          continue;
        }
        if (o instanceof AllowSystemAccount) {
          allowSystem = true;
          continue;
        }
        if (o instanceof RequireAccounting) {
          needsEnhance = true;
          ra = (RequireAccounting) o;
        }
      }
      if (!needsEnhance) continue;

      String key = ctBehavior.getLongName();
      String errMsg = String.format("Error enhancing class %s.%s: ", ctClass, ctBehavior);
      // process rr & rp
      if (null != rr || null != rp) {
        // check before/after enhancement
        Authority.registAuthoriable_(key, rr, rp);
        if (!buildAuthorityRegistryOnly) {
          // verify if before attribute of rr and rp is consistent
          if (null != rr && null != rp && (rr.before() != rp.before())) {
            String reason = "The before setting of RequireRight and RequirePrivilege doesn't match";
            throw new RuntimeException(errMsg + reason);
          }
          boolean before = true;
          if (null != rr) before = rr.before();
          if (null != rp) before = rp.before();
          // try best to guess the target object
          String curObj = "";
          if (null != rr) {
            // target object only impact dynamic access checking, hence rr shall not be null
            boolean isConstructor = ctBehavior instanceof CtConstructor;
            boolean isStatic = false;
            if (!isConstructor) isStatic = Modifier.isStatic(ctBehavior.getModifiers());
            int paraCnt = ctBehavior.getParameterTypes().length;
            int id = rr.target();
            // calibrate target id
            if (0 == id) {
              if (isConstructor) {
                id = -1;
              } else if (isStatic) {
                if (paraCnt > 0) id = 1;
                else id = -1;
              }
            } else if (id > paraCnt) {
              id = paraCnt;
            }
            // speculate cur target statement
            String sid = null;
            if (id == -1) sid = "_";
            if (id > -1) sid = String.valueOf(id);
            if (null != sid) {
              curObj =
                  "play.modules.aaa.PlayDynamicRightChecker.setObjectIfNoCurrent($" + sid + ");";
            }

            if (-1 == id) before = false;
          }
          // check permission enhancement
          if (before) {
            ctBehavior.insertBefore(
                curObj
                    + " play.modules.aaa.enhancer.Enhancer.Authority.checkPermission(\""
                    + key
                    + "\", "
                    + Boolean.toString(allowSystem)
                    + ");");
          } else {
            ctBehavior.insertAfter(
                curObj
                    + " play.modules.aaa.enhancer.Enhancer.Authority.checkPermission(\""
                    + key
                    + "\", "
                    + Boolean.toString(allowSystem)
                    + ");");
          }
        }
      }

      if (buildAuthorityRegistryOnly) continue;

      // process ra
      if (null != ra) {
        CtClass[] paraTypes = ctBehavior.getParameterTypes();
        String sParam = null;
        if (0 < paraTypes.length) {
          sParam = "new Object[0]";
        } else {
          sParam = "{$$}";
        }
        String msg = ra.value();
        if (null == msg || "".equals(msg)) msg = key;
        if (ra.before()) {
          ctBehavior.insertBefore(
              "play.modules.aaa.utils.Accounting.info(\""
                  + msg
                  + "\", "
                  + Boolean.toString(allowSystem)
                  + ", "
                  + sParam
                  + ");");
        } else {
          ctBehavior.insertAfter(
              "play.modules.aaa.utils.Accounting.info(\""
                  + msg
                  + "\", "
                  + Boolean.toString(allowSystem)
                  + ", "
                  + sParam
                  + ");");
        }
        CtClass etype = ClassPool.getDefault().get("java.lang.Exception");
        ctBehavior.addCatch(
            "{play.modules.aaa.utils.Accounting.error($e, \""
                + msg
                + "\", "
                + Boolean.toString(allowSystem)
                + ", "
                + sParam
                + "); throw $e;}",
            etype);
      }
    }

    if (buildAuthorityRegistryOnly) return;

    applicationClass.enhancedByteCode = ctClass.toBytecode();
    ctClass.detach();
  }