@Override
 public void afterPropertiesSet() throws Exception {
   Assert.notNull(BindableProxyFactory.this.channelFactory, "Channel Factory cannot be null");
   ReflectionUtils.doWithMethods(
       this.type,
       new ReflectionUtils.MethodCallback() {
         @Override
         public void doWith(Method method) throws IllegalArgumentException {
           Input input = AnnotationUtils.findAnnotation(method, Input.class);
           if (input != null) {
             String name = BindingBeanDefinitionRegistryUtils.getChannelName(input, method);
             validateChannelType(method.getReturnType());
             MessageChannel sharedChannel = locateSharedChannel(name);
             if (sharedChannel == null) {
               BindableProxyFactory.this.inputHolders.put(
                   name,
                   new ChannelHolder(
                       BindableProxyFactory.this.channelFactory.createInputChannel(name), true));
             } else {
               BindableProxyFactory.this.inputHolders.put(
                   name, new ChannelHolder(sharedChannel, false));
             }
           }
         }
       });
   ReflectionUtils.doWithMethods(
       this.type,
       new ReflectionUtils.MethodCallback() {
         @Override
         public void doWith(Method method) throws IllegalArgumentException {
           Output output = AnnotationUtils.findAnnotation(method, Output.class);
           if (output != null) {
             String name = BindingBeanDefinitionRegistryUtils.getChannelName(output, method);
             validateChannelType(method.getReturnType());
             MessageChannel sharedChannel = locateSharedChannel(name);
             if (sharedChannel == null) {
               BindableProxyFactory.this.outputHolders.put(
                   name,
                   new ChannelHolder(
                       BindableProxyFactory.this.channelFactory.createOutputChannel(name), true));
             } else {
               BindableProxyFactory.this.outputHolders.put(
                   name, new ChannelHolder(sharedChannel, false));
             }
           }
         }
       });
 }
  /**
   * Discover a {@link StepExecution} as a field in the test case or create one if none is
   * available.
   *
   * @param testContext the current test context
   * @return a {@link StepExecution}
   */
  protected StepExecution getStepExecution(TestContext testContext) {
    Object target;

    try {
      Method method = TestContext.class.getMethod(GET_TEST_INSTANCE_METHOD);
      target = ReflectionUtils.invokeMethod(method, testContext);
    } catch (NoSuchMethodException e) {
      throw new IllegalStateException(
          "No such method " + GET_TEST_INSTANCE_METHOD + " on provided TestContext", e);
    }

    ExtractorMethodCallback method =
        new ExtractorMethodCallback(StepExecution.class, "getStepExecution");
    ReflectionUtils.doWithMethods(target.getClass(), method);
    if (method.getName() != null) {
      HippyMethodInvoker invoker = new HippyMethodInvoker();
      invoker.setTargetObject(target);
      invoker.setTargetMethod(method.getName());
      try {
        invoker.prepare();
        return (StepExecution) invoker.invoke();
      } catch (Exception e) {
        throw new IllegalArgumentException(
            "Could not create step execution from method: " + method.getName(), e);
      }
    }

    return MetaDataInstanceFactory.createStepExecution();
  }
  @Override
  public Object postProcessAfterInitialization(final Object bean, final String beanName)
      throws BeansException {
    Class<?> targetClass = AopUtils.getTargetClass(bean);
    final RabbitListener classLevelListener =
        AnnotationUtils.findAnnotation(bean.getClass(), RabbitListener.class);
    final List<Method> multiMethods = new ArrayList<Method>();
    ReflectionUtils.doWithMethods(
        targetClass,
        new ReflectionUtils.MethodCallback() {

          @Override
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {
            RabbitListener rabbitListener =
                AnnotationUtils.getAnnotation(method, RabbitListener.class);
            if (rabbitListener != null) {
              processAmqpListener(rabbitListener, method, bean, beanName);
            }
            if (classLevelListener != null) {
              RabbitHandler rabbitHandler =
                  AnnotationUtils.getAnnotation(method, RabbitHandler.class);
              if (rabbitHandler != null) {
                multiMethods.add(method);
              }
            }
          }
        });
    if (classLevelListener != null) {
      processMultiMethodListener(classLevelListener, multiMethods, bean, beanName);
    }
    return bean;
  }
Пример #4
0
 /**
  * Initialize a new HandlerMethodResolver for the specified handler type.
  *
  * @param handlerType the handler class to introspect
  */
 public void init(Class<?> handlerType) {
   Class<?>[] handlerTypes =
       Proxy.isProxyClass(handlerType)
           ? handlerType.getInterfaces()
           : new Class<?>[] {handlerType};
   for (final Class<?> currentHandlerType : handlerTypes) {
     ReflectionUtils.doWithMethods(
         currentHandlerType,
         new ReflectionUtils.MethodCallback() {
           public void doWith(Method method) {
             Method specificMethod = ClassUtils.getMostSpecificMethod(method, currentHandlerType);
             if (isHandlerMethod(method)) {
               handlerMethods.add(specificMethod);
             } else if (method.isAnnotationPresent(InitBinder.class)) {
               initBinderMethods.add(specificMethod);
             } else if (method.isAnnotationPresent(ModelAttribute.class)) {
               modelAttributeMethods.add(specificMethod);
             }
           }
         },
         ReflectionUtils.NON_BRIDGED_METHODS);
   }
   this.typeLevelMapping = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
   SessionAttributes sessionAttributes = handlerType.getAnnotation(SessionAttributes.class);
   this.sessionAttributesFound = (sessionAttributes != null);
   if (this.sessionAttributesFound) {
     this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.value()));
     this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types()));
   }
 }
 @Override
 public Object postProcessAfterInitialization(final Object bean, String beanName) {
   if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
     final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
     Class<?> targetClass = AopUtils.getTargetClass(bean);
     ReflectionUtils.doWithMethods(
         targetClass,
         new MethodCallback() {
           @Override
           public void doWith(Method method)
               throws IllegalArgumentException, IllegalAccessException {
             for (Scheduled scheduled :
                 AnnotationUtils.getRepeatableAnnotation(
                     method, Schedules.class, Scheduled.class)) {
               processScheduled(scheduled, method, bean);
               annotatedMethods.add(method);
             }
           }
         });
     if (annotatedMethods.isEmpty()) {
       this.nonAnnotatedClasses.add(bean.getClass());
     }
   }
   return bean;
 }
Пример #6
0
 /**
  * Check that {@link #blogService} is advised for caching and that all methods relating to
  * published posts have the {@link Cacheable} annotation. Note that while more extensive mocking
  * and testing through {@code MockMvc} etc is possible, this approach is less fragile and much
  * more concise while still being likely to catch configuration errors.
  */
 @Test
 public void blogServiceIsAdvisedForCaching() {
   assertThat("BlogService is not advised as expected", blogService, instanceOf(Advised.class));
   boolean hasCachingAdvisor = false;
   for (Advisor advisor : ((Advised) blogService).getAdvisors()) {
     if (advisor instanceof BeanFactoryCacheOperationSourceAdvisor) {
       hasCachingAdvisor = true;
       break;
     }
   }
   assertTrue("BlogService is advised, but does not have caching advisor", hasCachingAdvisor);
   // @formatter:off
   ReflectionUtils.doWithMethods(
       BlogService.class,
       new ReflectionUtils.MethodCallback() { // TODO: lambda
         @Override
         public void doWith(Method method)
             throws IllegalArgumentException, IllegalAccessException {
           Cacheable cacheable = AnnotationUtils.findAnnotation(method, Cacheable.class);
           String methodName = method.getName();
           if (methodName.matches("^get.*Published.*$")) {
             assertNotNull(
                 "Method " + methodName + " was expected to have Cacheable annotation.",
                 cacheable);
             String[] cacheName = cacheable.value();
             assertThat(cacheName[0], equalTo(DatabaseConfig.CACHE_NAME));
           } else {
             assertNull(
                 "Method " + methodName + " was not expected to have Cacheable annotation.",
                 cacheable);
           }
         }
       });
   // @formatter:on
 }
  @Test
  public void testGateway2() throws Exception {
    FtpOutboundGateway gateway =
        TestUtils.getPropertyValue(gateway2, "handler", FtpOutboundGateway.class);
    assertEquals(
        "X", TestUtils.getPropertyValue(gateway, "remoteFileTemplate.remoteFileSeparator"));
    assertNotNull(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory"));
    assertTrue(
        TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory")
            instanceof CachingSessionFactory);
    assertNotNull(TestUtils.getPropertyValue(gateway, "outputChannel"));
    assertEquals(
        "local-test-dir",
        TestUtils.getPropertyValue(gateway, "localDirectoryExpression.literalValue"));
    assertFalse((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory"));
    assertEquals(Command.GET, TestUtils.getPropertyValue(gateway, "command"));
    @SuppressWarnings("unchecked")
    Set<String> options = TestUtils.getPropertyValue(gateway, "options", Set.class);
    assertTrue(options.contains(Option.PRESERVE_TIMESTAMP));
    gateway.handleMessage(new GenericMessage<String>("foo"));
    assertFalse(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
    assertEquals(1, adviceCalled);

    // INT-3129
    assertNotNull(TestUtils.getPropertyValue(gateway, "localFilenameGeneratorExpression"));
    final AtomicReference<Method> genMethod = new AtomicReference<Method>();
    ReflectionUtils.doWithMethods(
        FtpOutboundGateway.class,
        new ReflectionUtils.MethodCallback() {

          @Override
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {
            if ("generateLocalFileName".equals(method.getName())) {
              method.setAccessible(true);
              genMethod.set(method);
            }
          }
        });
    assertEquals(
        "FOO.afoo", genMethod.get().invoke(gateway, new GenericMessage<String>(""), "foo"));
    assertThat(
        TestUtils.getPropertyValue(gateway, "mputFilter"),
        Matchers.instanceOf(SimplePatternFileListFilter.class));
  }
  /**
   * Searches for {@link org.springframework.security.access.prepost.PreAuthorize} and {@link
   * org.springframework.security.access.prepost.PostAuthorize} annotations representing permissions
   * and parses them. Parsed annotations are used to find permissions. After that those permissions
   * are added to {@link org.motechproject.security.service.MotechPermissionService}
   *
   * @param bean to be processed
   * @param beanName name of the bean
   * @return processed bean
   */
  @Override
  public Object postProcessAfterInitialization(final Object bean, final String beanName) {
    LOGGER.debug("Searching for security annotations in: {}", beanName);

    doWithMethods(
        bean.getClass(),
        new MethodCallback() {
          @Override
          public void doWith(Method method) throws IllegalAccessException {
            Method methodOfOriginalClassIfProxied =
                findMethod(getTargetClass(bean), method.getName(), method.getParameterTypes());

            if (methodOfOriginalClassIfProxied != null) {
              PreAuthorize preAuthorize =
                  findAnnotation(methodOfOriginalClassIfProxied, PreAuthorize.class);
              PostAuthorize postAuthorize =
                  findAnnotation(methodOfOriginalClassIfProxied, PostAuthorize.class);

              List<String> annotations = new ArrayList<>(2);
              List<String> permissions = new ArrayList<>();

              if (preAuthorize != null) {
                annotations.add(preAuthorize.value());
              }

              if (postAuthorize != null) {
                annotations.add(postAuthorize.value());
              }

              for (String annotation : annotations) {
                SpelExpression expression =
                    (SpelExpression) annotationParser.parseExpression(annotation);
                permissions.addAll(findPermissions(expression.getAST()));
              }

              addRoleAndPermissions(permissions);
            }
          }
        });

    LOGGER.debug("Searched for security annotations in: {}", beanName);

    return bean;
  }
Пример #9
0
  /**
   * 检查上下文中的BOP服务方法
   *
   * @throws org.springframework.beans.BeansException
   */
  private void registerFromContext(final ApplicationContext context) throws BeansException {
    if (logger.isDebugEnabled()) {
      logger.debug("对Spring上下文中的Bean进行扫描,查找ROP服务方法: " + context);
    }
    String[] beanNames = context.getBeanNamesForType(Object.class);
    for (final String beanName : beanNames) {
      Class<?> handlerType = context.getType(beanName);
      ReflectionUtils.doWithMethods(
          handlerType,
          new ReflectionUtils.MethodCallback() {
            public void doWith(Method method)
                throws IllegalArgumentException, IllegalAccessException {
              ReflectionUtils.makeAccessible(method);

              ServiceMethod serviceMethod = method.getAnnotation(ServiceMethod.class);
              ServiceMethodGroup serviceMethodGroup =
                  method.getDeclaringClass().getAnnotation(ServiceMethodGroup.class);

              ServiceMethodDefinition definition = null;
              if (serviceMethodGroup != null) {
                definition = buildServiceMethodDefinition(serviceMethodGroup, serviceMethod);
              } else {
                definition = buildServiceMethodDefinition(serviceMethod);
              }
              ServiceMethodHandler serviceMethodHandler = new ServiceMethodHandler();
              serviceMethodHandler.setServiceMethodDefinition(definition);

              // 1.set handler
              serviceMethodHandler.setHandler(context.getBean(beanName)); // handler
              serviceMethodHandler.setHandlerMethod(method); // handler'method
              if (method.getParameterTypes().length > 0) { // handler method's parameter
                Class<?> aClass = method.getParameterTypes()[0];
                Assert.isAssignable(RopRequest.class, aClass, "@ServiceMethod方法入参必须是RopRequest");
                serviceMethodHandler.setRequestType((Class<? extends RopRequest>) aClass);
              }

              // 2.set sign fieldNames
              serviceMethodHandler.setIgnoreSignFieldNames(
                  getIgnoreSignFieldNames(serviceMethodHandler.getRequestType()));

              addServiceMethod(
                  serviceMethod.value(), serviceMethod.version(), serviceMethodHandler);

              if (logger.isDebugEnabled()) {
                logger.debug(
                    "注册服务方法:"
                        + method.getDeclaringClass().getCanonicalName()
                        + "#"
                        + method.getName()
                        + "(..)");
              }
            }
          },
          new ReflectionUtils.MethodFilter() {
            public boolean matches(Method method) {
              return AnnotationUtils.findAnnotation(method, ServiceMethod.class) != null;
            }
          });
    }
    if (context.getParent() != null) {
      registerFromContext(context.getParent());
    }
    if (logger.isInfoEnabled()) {
      logger.info("共注册了" + serviceHandlerMap.size() + "个服务方法");
    }
  }
  @Override
  public Object postProcessAfterInitialization(final Object bean, final String beanName)
      throws BeansException {
    Assert.notNull(this.beanFactory, "BeanFactory must not be null");
    final Class<?> beanClass = this.getBeanClass(bean);
    if (this.requireComponentAnnotation
        && AnnotationUtils.findAnnotation(beanClass, Component.class) == null) {
      // we only post-process stereotype components
      return bean;
    }

    ReflectionUtils.doWithMethods(
        beanClass,
        new ReflectionUtils.MethodCallback() {

          @Override
          @SuppressWarnings({"unchecked", "rawtypes"})
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {
            Map<Class<? extends Annotation>, List<Annotation>> annotationChains =
                new HashMap<Class<? extends Annotation>, List<Annotation>>();
            for (Class<? extends Annotation> annotationType :
                MessagingAnnotationPostProcessor.this.postProcessors.keySet()) {
              if (AnnotatedElementUtils.isAnnotated(method, annotationType.getName())) {
                List<Annotation> annotationChain = getAnnotationChain(method, annotationType);
                if (annotationChain.size() > 0) {
                  annotationChains.put(annotationType, annotationChain);
                }
              }
            }

            for (Map.Entry<Class<? extends Annotation>, List<Annotation>> entry :
                annotationChains.entrySet()) {
              Class<? extends Annotation> annotationType = entry.getKey();
              List<Annotation> annotations = entry.getValue();
              MethodAnnotationPostProcessor postProcessor =
                  MessagingAnnotationPostProcessor.this.postProcessors.get(annotationType);
              if (postProcessor != null
                  && postProcessor.shouldCreateEndpoint(method, annotations)) {
                Method targetMethod = method;
                if (AopUtils.isJdkDynamicProxy(bean)) {
                  try {
                    targetMethod =
                        bean.getClass().getMethod(method.getName(), method.getParameterTypes());
                  } catch (NoSuchMethodException e) {
                    throw new IllegalArgumentException(
                        "Service methods must be extracted to the service "
                            + "interface for JdkDynamicProxy. The affected bean is: '"
                            + beanName
                            + "' "
                            + "and its method: '"
                            + method
                            + "'",
                        e);
                  }
                }
                Object result =
                    postProcessor.postProcess(bean, beanName, targetMethod, annotations);
                if (result != null && result instanceof AbstractEndpoint) {
                  AbstractEndpoint endpoint = (AbstractEndpoint) result;
                  String autoStartup =
                      MessagingAnnotationUtils.resolveAttribute(
                          annotations, "autoStartup", String.class);
                  if (StringUtils.hasText(autoStartup)) {
                    autoStartup = getBeanFactory().resolveEmbeddedValue(autoStartup);
                    if (StringUtils.hasText(autoStartup)) {
                      endpoint.setAutoStartup(Boolean.parseBoolean(autoStartup));
                    }
                  }

                  String phase =
                      MessagingAnnotationUtils.resolveAttribute(annotations, "phase", String.class);
                  if (StringUtils.hasText(phase)) {
                    phase = getBeanFactory().resolveEmbeddedValue(phase);
                    if (StringUtils.hasText(phase)) {
                      endpoint.setPhase(Integer.parseInt(phase));
                    }
                  }

                  String endpointBeanName = generateBeanName(beanName, method, annotationType);
                  endpoint.setBeanName(endpointBeanName);
                  getBeanFactory().registerSingleton(endpointBeanName, endpoint);
                  getBeanFactory().initializeBean(endpoint, endpointBeanName);

                  Role role = AnnotationUtils.findAnnotation(method, Role.class);
                  if (role != null) {
                    MessagingAnnotationPostProcessor.this.lazyLifecycleRoles.add(
                        role.value(), endpointBeanName);
                  }
                }
              }
            }
          }
        },
        ReflectionUtils.USER_DECLARED_METHODS);

    return bean;
  }
  @Test
  public void testKafkaMessageDrivenChannelAdapterParser() throws Exception {
    assertFalse(this.kafkaListener.isAutoStartup());
    assertFalse(this.kafkaListener.isRunning());
    assertEquals(100, this.kafkaListener.getPhase());
    assertSame(this.nullChannel, TestUtils.getPropertyValue(this.kafkaListener, "outputChannel"));
    assertSame(this.errorChannel, TestUtils.getPropertyValue(this.kafkaListener, "errorChannel"));
    assertSame(this.keyDecoder, TestUtils.getPropertyValue(this.kafkaListener, "keyDecoder"));
    assertSame(
        this.payloadDecoder, TestUtils.getPropertyValue(this.kafkaListener, "payloadDecoder"));
    KafkaMessageListenerContainer container =
        TestUtils.getPropertyValue(
            this.kafkaListener, "messageListenerContainer", KafkaMessageListenerContainer.class);
    assertSame(
        this.connectionFactory,
        TestUtils.getPropertyValue(container, "kafkaTemplate.connectionFactory"));
    assertSame(this.offsetManager, container.getOffsetManager());
    assertSame(this.errorHandler, container.getErrorHandler());
    assertSame(this.executor, container.getFetchTaskExecutor());
    assertEquals(10, container.getConcurrency());
    assertEquals(1000, container.getMaxFetch());
    assertEquals(1024, container.getQueueSize());
    assertEquals(5000, container.getStopTimeout());
    assertArrayEquals(
        new String[] {"foo", "bar"},
        TestUtils.getPropertyValue(container, "topics", String[].class));
    assertOverrides(this.kafkaListener, false, false, false, true);
    assertOverrides(this.withMBFactoryOverrideAndId, true, true, false, false);
    assertOverrides(this.withMBFactoryOverrideAndTS, true, false, true, true);
    assertOverrides(this.withOverrideIdTS, false, true, true, true);

    final AtomicReference<Method> toMessage = new AtomicReference<Method>();
    ReflectionUtils.doWithMethods(
        KafkaMessageDrivenChannelAdapter.class,
        new MethodCallback() {

          @Override
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {
            method.setAccessible(true);
            toMessage.set(method);
          }
        },
        new MethodFilter() {

          @Override
          public boolean matches(Method method) {
            return method.getName().equals("toMessage");
          }
        });

    Message<?> m = getAMessageFrom(this.kafkaListener, toMessage.get());
    assertNull(m.getHeaders().getId());
    assertNull(m.getHeaders().getTimestamp());
    assertNull(m.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT));
    assertRest(m);

    m = getAMessageFrom(this.withMBFactoryOverrideAndId, toMessage.get());
    assertThat(m, Matchers.instanceOf(GenericMessage.class));
    assertNotNull(m.getHeaders().getId());
    assertNotNull(m.getHeaders().getTimestamp());
    assertNotNull(m.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT));
    assertRest(m);

    m = getAMessageFrom(this.withMBFactoryOverrideAndTS, toMessage.get());
    assertThat(m, Matchers.instanceOf(GenericMessage.class));
    assertNotNull(m.getHeaders().getId());
    assertNotNull(m.getHeaders().getTimestamp());
    assertNull(m.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT));
    assertRest(m);

    m = getAMessageFrom(this.withOverrideIdTS, toMessage.get());
    assertNotNull(m.getHeaders().getId());
    assertNotNull(m.getHeaders().getTimestamp());
    assertNull(m.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT));
    assertRest(m);
  }
  private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(
      final Object targetObject,
      final Class<? extends Annotation> annotationType,
      final String methodName,
      final boolean requiresReply) {

    Map<String, Map<Class<?>, HandlerMethod>> handlerMethods =
        new HashMap<String, Map<Class<?>, HandlerMethod>>();

    final Map<Class<?>, HandlerMethod> candidateMethods = new HashMap<Class<?>, HandlerMethod>();
    final Map<Class<?>, HandlerMethod> candidateMessageMethods =
        new HashMap<Class<?>, HandlerMethod>();
    final Map<Class<?>, HandlerMethod> fallbackMethods = new HashMap<Class<?>, HandlerMethod>();
    final Map<Class<?>, HandlerMethod> fallbackMessageMethods =
        new HashMap<Class<?>, HandlerMethod>();
    final AtomicReference<Class<?>> ambiguousFallbackType = new AtomicReference<Class<?>>();
    final AtomicReference<Class<?>> ambiguousFallbackMessageGenericType =
        new AtomicReference<Class<?>>();
    final Class<?> targetClass = this.getTargetClass(targetObject);
    MethodFilter methodFilter = new UniqueMethodFilter(targetClass);
    ReflectionUtils.doWithMethods(
        targetClass,
        new MethodCallback() {
          @Override
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {
            boolean matchesAnnotation = false;
            if (method.isBridge()) {
              return;
            }
            if (isMethodDefinedOnObjectClass(method)) {
              return;
            }
            if (method.getDeclaringClass().equals(Proxy.class)) {
              return;
            }
            if (!Modifier.isPublic(method.getModifiers())) {
              return;
            }
            if (requiresReply && void.class.equals(method.getReturnType())) {
              return;
            }
            if (methodName != null && !methodName.equals(method.getName())) {
              return;
            }
            if (annotationType != null
                && AnnotationUtils.findAnnotation(method, annotationType) != null) {
              matchesAnnotation = true;
            }
            HandlerMethod handlerMethod = null;
            try {
              handlerMethod = new HandlerMethod(method, canProcessMessageList);
            } catch (IneligibleMethodException e) {
              if (logger.isDebugEnabled()) {
                logger.debug(
                    "Method ["
                        + method
                        + "] is not eligible for Message handling "
                        + e.getMessage()
                        + ".");
              }
              return;
            } catch (Exception e) {
              if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method + "] is not eligible for Message handling.", e);
              }
              return;
            }
            Class<?> targetParameterType = handlerMethod.getTargetParameterType();
            if (matchesAnnotation || annotationType == null) {
              if (handlerMethod.isMessageMethod()) {
                if (candidateMessageMethods.containsKey(targetParameterType)) {
                  throw new IllegalArgumentException(
                      "Found more than one method match for type "
                          + "[Message<"
                          + targetParameterType
                          + ">]");
                }
                candidateMessageMethods.put(targetParameterType, handlerMethod);
              } else {
                if (candidateMethods.containsKey(targetParameterType)) {
                  String exceptionMessage = "Found more than one method match for ";
                  if (Void.class.equals(targetParameterType)) {
                    exceptionMessage += "empty parameter for 'payload'";
                  } else {
                    exceptionMessage += "type [" + targetParameterType + "]";
                  }
                  throw new IllegalArgumentException(exceptionMessage);
                }
                candidateMethods.put(targetParameterType, handlerMethod);
              }
            } else {
              if (handlerMethod.isMessageMethod()) {
                if (fallbackMessageMethods.containsKey(targetParameterType)) {
                  // we need to check for duplicate type matches,
                  // but only if we end up falling back
                  // and we'll only keep track of the first one
                  ambiguousFallbackMessageGenericType.compareAndSet(null, targetParameterType);
                }
                fallbackMessageMethods.put(targetParameterType, handlerMethod);
              } else {
                if (fallbackMethods.containsKey(targetParameterType)) {
                  // we need to check for duplicate type matches,
                  // but only if we end up falling back
                  // and we'll only keep track of the first one
                  ambiguousFallbackType.compareAndSet(null, targetParameterType);
                }
                fallbackMethods.put(targetParameterType, handlerMethod);
              }
            }
          }
        },
        methodFilter);

    if (!candidateMethods.isEmpty() || !candidateMessageMethods.isEmpty()) {
      handlerMethods.put(CANDIDATE_METHODS, candidateMethods);
      handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
      return handlerMethods;
    }
    if ((ambiguousFallbackType.get() != null || ambiguousFallbackMessageGenericType.get() != null)
        && ServiceActivator.class.equals(annotationType)) {
      /*
       * When there are ambiguous fallback methods,
       * a Service Activator can finally fallback to RequestReplyExchanger.exchange(m).
       * Ambiguous means > 1 method that takes the same payload type, or > 1 method
       * that takes a Message with the same generic type.
       */
      List<Method> frameworkMethods = new ArrayList<Method>();
      Class<?>[] allInterfaces =
          org.springframework.util.ClassUtils.getAllInterfacesForClass(targetClass);
      for (Class<?> iface : allInterfaces) {
        try {
          if ("org.springframework.integration.gateway.RequestReplyExchanger"
              .equals(iface.getName())) {
            frameworkMethods.add(targetClass.getMethod("exchange", Message.class));
            if (logger.isDebugEnabled()) {
              logger.debug(
                  targetObject.getClass()
                      + ": Ambiguous fallback methods; using RequestReplyExchanger.exchange()");
            }
          }
        } catch (Exception e) {
          // should never happen (but would fall through to errors below)
        }
      }
      if (frameworkMethods.size() == 1) {
        HandlerMethod handlerMethod =
            new HandlerMethod(frameworkMethods.get(0), canProcessMessageList);
        handlerMethods.put(
            CANDIDATE_METHODS,
            Collections.<Class<?>, HandlerMethod>singletonMap(Object.class, handlerMethod));
        handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
        return handlerMethods;
      }
    }

    try {
      Assert.state(
          !fallbackMethods.isEmpty() || !fallbackMessageMethods.isEmpty(),
          "Target object of type ["
              + this.targetObject.getClass()
              + "] has no eligible methods for handling Messages.");
    } catch (Exception e) {
      // TODO backward compatibility
      throw new IllegalArgumentException(e.getMessage());
    }

    Assert.isNull(
        ambiguousFallbackType.get(),
        "Found ambiguous parameter type ["
            + ambiguousFallbackType
            + "] for method match: "
            + fallbackMethods.values());
    Assert.isNull(
        ambiguousFallbackMessageGenericType.get(),
        "Found ambiguous parameter type ["
            + ambiguousFallbackMessageGenericType
            + "] for method match: "
            + fallbackMethods.values());

    handlerMethods.put(CANDIDATE_METHODS, fallbackMethods);
    handlerMethods.put(CANDIDATE_MESSAGE_METHODS, fallbackMessageMethods);
    return handlerMethods;
  }
  public Object postProcessAfterInitialization(final Object bean, final String beanName)
      throws BeansException {
    // first sift through and get all the methods
    // then get all the annotations
    // then build the metadata and register the metadata
    final Class<?> targetClass = AopUtils.getTargetClass(bean);
    final org.activiti.spring.annotations.ActivitiComponent component =
        targetClass.getAnnotation(org.activiti.spring.annotations.ActivitiComponent.class);

    ReflectionUtils.doWithMethods(
        targetClass,
        new ReflectionUtils.MethodCallback() {
          @SuppressWarnings("unchecked")
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {

            State state = AnnotationUtils.getAnnotation(method, State.class);

            String processName = component.processKey();

            if (StringUtils.hasText(state.process())) {
              processName = state.process();
            }

            String stateName = state.state();

            if (!StringUtils.hasText(stateName)) {
              stateName = state.value();
            }

            Assert.notNull(stateName, "You must provide a stateName!");

            Map<Integer, String> vars = new HashMap<Integer, String>();
            Annotation[][] paramAnnotationsArray = method.getParameterAnnotations();

            int ctr = 0;
            int pvMapIndex = -1;
            int procIdIndex = -1;

            for (Annotation[] paramAnnotations : paramAnnotationsArray) {
              ctr += 1;

              for (Annotation pa : paramAnnotations) {
                if (pa instanceof ProcessVariable) {
                  ProcessVariable pv = (ProcessVariable) pa;
                  String pvName = pv.value();
                  vars.put(ctr, pvName);
                } else if (pa instanceof ProcessVariables) {
                  pvMapIndex = ctr;
                } else if (pa instanceof ProcessId) {
                  procIdIndex = ctr;
                }
              }
            }

            ActivitiStateHandlerRegistration registration =
                new ActivitiStateHandlerRegistration(
                    vars, method, bean, stateName, beanName, pvMapIndex, procIdIndex, processName);
            registry.registerActivitiStateHandler(registration);
          }
        },
        new ReflectionUtils.MethodFilter() {
          public boolean matches(Method method) {
            return null != AnnotationUtils.getAnnotation(method, State.class);
          }
        });

    return bean;
  }
  private void createChannels(Class<?> type) throws Exception {
    ReflectionUtils.doWithMethods(
        type,
        new ReflectionUtils.MethodCallback() {
          @Override
          public void doWith(Method method)
              throws IllegalArgumentException, IllegalAccessException {

            Input input = AnnotationUtils.findAnnotation(method, Input.class);
            if (input != null) {
              String name = BindingBeanDefinitionRegistryUtils.getChannelName(input, method);
              Class<?> inputChannelType = method.getReturnType();
              MessageChannel sharedChannel = locateSharedChannel(name);
              if (sharedChannel == null) {
                MessageChannel inputChannel = createMessageChannel(inputChannelType);
                inputs.put(name, new ChannelHolder(inputChannel, true));
              } else {
                if (inputChannelType.isAssignableFrom(sharedChannel.getClass())) {
                  inputs.put(name, new ChannelHolder(sharedChannel, false));
                } else {
                  // handle the special case where the shared channel is of a different nature
                  // (i.e. pollable vs subscribable) than the target channel
                  final MessageChannel inputChannel = createMessageChannel(inputChannelType);
                  if (isPollable(sharedChannel.getClass())) {
                    bridgePollableToSubscribableChannel(sharedChannel, inputChannel);
                  } else {
                    bridgeSubscribableToPollableChannel(
                        (SubscribableChannel) sharedChannel, inputChannel);
                  }
                  inputs.put(name, new ChannelHolder(inputChannel, false));
                }
              }
            }

            Output output = AnnotationUtils.findAnnotation(method, Output.class);
            if (output != null) {
              String name = BindingBeanDefinitionRegistryUtils.getChannelName(output, method);
              Class<?> messageChannelType = method.getReturnType();
              MessageChannel sharedChannel = locateSharedChannel(name);
              if (sharedChannel == null) {
                MessageChannel outputChannel = createMessageChannel(messageChannelType);
                outputs.put(name, new ChannelHolder(outputChannel, true));
              } else {
                if (messageChannelType.isAssignableFrom(sharedChannel.getClass())) {
                  outputs.put(name, new ChannelHolder(sharedChannel, false));
                } else {
                  // handle the special case where the shared channel is of a different nature
                  // (i.e. pollable vs subscribable) than the target channel
                  final MessageChannel outputChannel = createMessageChannel(messageChannelType);
                  if (isPollable(messageChannelType)) {
                    bridgePollableToSubscribableChannel(outputChannel, sharedChannel);
                  } else {
                    bridgeSubscribableToPollableChannel(
                        (SubscribableChannel) outputChannel, sharedChannel);
                  }
                  outputs.put(name, new ChannelHolder(outputChannel, false));
                }
              }
            }
          }
        });
  }