예제 #1
0
  /**
   * Introspects the given class
   *
   * @param clazz the class
   */
  private void introspect(Class<?> clazz) {
    // get the target clazz as it could potentially have been enhanced by CGLIB etc.
    clazz = getTargetClass(clazz);
    ObjectHelper.notNull(clazz, "clazz", this);

    LOG.trace("Introspecting class: {}", clazz);

    // if the class is not public then fallback and use interface methods if possible
    // this allow Camel to invoke private beans which implements interfaces
    List<Method> methods = Arrays.asList(clazz.getDeclaredMethods());
    if (!Modifier.isPublic(clazz.getModifiers())) {
      LOG.trace("Preferring interface methods as class: {} is not public accessible", clazz);
      List<Method> interfaceMethods = getInterfaceMethods(clazz);

      // still keep non-accessible class methods to provide more specific Exception if method is
      // non-accessible
      interfaceMethods.addAll(methods);
      methods = interfaceMethods;
    }

    for (Method method : methods) {
      boolean valid = isValidMethod(clazz, method);
      LOG.trace("Method: {} is valid: {}", method, valid);
      if (valid) {
        introspect(clazz, method);
      }
    }

    Class<?> superclass = clazz.getSuperclass();
    if (superclass != null && !superclass.equals(Object.class)) {
      introspect(superclass);
    }
  }
예제 #2
0
파일: BeanInfo.java 프로젝트: tivv/camel
  /**
   * Introspects the given class
   *
   * @param clazz the class
   */
  private void introspect(Class<?> clazz) {
    // get the target clazz as it could potentially have been enhanced by CGLIB etc.
    clazz = getTargetClass(clazz);
    ObjectHelper.notNull(clazz, "clazz", this);

    LOG.trace("Introspecting class: {}", clazz);

    // does the class have any public constructors?
    publicConstructors = clazz.getConstructors().length > 0;

    // favor declared methods, and then filter out duplicate interface methods
    List<Method> methods;
    if (Modifier.isPublic(clazz.getModifiers())) {
      LOG.trace("Preferring class methods as class: {} is public accessible", clazz);
      methods = new ArrayList<Method>(Arrays.asList(clazz.getDeclaredMethods()));
    } else {
      LOG.trace("Preferring interface methods as class: {} is not public accessible", clazz);
      methods = getInterfaceMethods(clazz);
      // and then we must add its declared methods as well
      List<Method> extraMethods = Arrays.asList(clazz.getDeclaredMethods());
      methods.addAll(extraMethods);
    }

    Set<Method> overrides = new HashSet<Method>();
    Set<Method> bridges = new HashSet<Method>();

    // do not remove duplicates form class from the Java itself as they have some "duplicates" we
    // need
    boolean javaClass = clazz.getName().startsWith("java.") || clazz.getName().startsWith("javax.");
    if (!javaClass) {
      // it may have duplicate methods already, even from declared or from interfaces + declared
      for (Method source : methods) {
        for (Method target : methods) {
          // skip ourselves
          if (ObjectHelper.isOverridingMethod(source, target, true)) {
            continue;
          }
          // skip duplicates which may be assign compatible (favor keep first added method when
          // duplicate)
          if (ObjectHelper.isOverridingMethod(source, target, false)) {
            overrides.add(target);
          }
        }
      }
      methods.removeAll(overrides);
      overrides.clear();
    }

    // if we are a public class, then add non duplicate interface classes also
    if (Modifier.isPublic(clazz.getModifiers())) {
      // add additional interface methods
      List<Method> extraMethods = getInterfaceMethods(clazz);
      for (Method target : extraMethods) {
        for (Method source : methods) {
          if (ObjectHelper.isOverridingMethod(source, target, false)) {
            overrides.add(target);
          }
        }
      }
      // remove all the overrides methods
      extraMethods.removeAll(overrides);
      methods.addAll(extraMethods);
    }

    // now introspect the methods and filter non valid methods
    for (Method method : methods) {
      boolean valid = isValidMethod(clazz, method);
      LOG.trace("Method: {} is valid: {}", method, valid);
      if (valid) {
        introspect(clazz, method);
      }
    }

    Class<?> superclass = clazz.getSuperclass();
    if (superclass != null && !superclass.equals(Object.class)) {
      introspect(superclass);
    }
  }
예제 #3
0
파일: BeanInfo.java 프로젝트: tivv/camel
  public BeanInfo(
      CamelContext camelContext,
      Class<?> type,
      Method explicitMethod,
      ParameterMappingStrategy strategy) {
    this.camelContext = camelContext;
    this.type = type;
    this.strategy = strategy;
    this.component = camelContext.getComponent("bean", BeanComponent.class);

    final BeanInfoCacheKey key = new BeanInfoCacheKey(type, explicitMethod);

    // lookup if we have a bean info cache
    BeanInfo beanInfo = component.getBeanInfoFromCache(key);
    if (beanInfo != null) {
      // copy the values from the cache we need
      defaultMethod = beanInfo.defaultMethod;
      operations = beanInfo.operations;
      operationsWithBody = beanInfo.operationsWithBody;
      operationsWithNoBody = beanInfo.operationsWithNoBody;
      operationsWithCustomAnnotation = beanInfo.operationsWithCustomAnnotation;
      operationsWithHandlerAnnotation = beanInfo.operationsWithHandlerAnnotation;
      methodMap = beanInfo.methodMap;
      publicConstructors = beanInfo.publicConstructors;
      return;
    }

    if (explicitMethod != null) {
      // must be a valid method
      if (!isValidMethod(type, explicitMethod)) {
        throw new IllegalArgumentException(
            "The method "
                + explicitMethod
                + " is not valid (for example the method must be public)");
      }
      introspect(getType(), explicitMethod);
    } else {
      introspect(getType());
    }

    // if there are only 1 method with 1 operation then select it as a default/fallback method
    MethodInfo method = null;
    if (operations.size() == 1) {
      List<MethodInfo> methods = operations.values().iterator().next();
      if (methods.size() == 1) {
        method = methods.get(0);
      }
    }
    defaultMethod = method;

    // mark the operations lists as unmodifiable, as they should not change during runtime
    // to keep this code thread safe
    operations = Collections.unmodifiableMap(operations);
    operationsWithBody = Collections.unmodifiableList(operationsWithBody);
    operationsWithNoBody = Collections.unmodifiableList(operationsWithNoBody);
    operationsWithCustomAnnotation = Collections.unmodifiableList(operationsWithCustomAnnotation);
    operationsWithHandlerAnnotation = Collections.unmodifiableList(operationsWithHandlerAnnotation);
    methodMap = Collections.unmodifiableMap(methodMap);

    // add new bean info to cache
    component.addBeanInfoToCache(key, this);
  }