View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.statemachine.transition;
21  
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import java.util.Arrays;
25  
26  import org.apache.mina.statemachine.context.StateContext;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  import org.apache.mina.statemachine.State;
30  
31  /**
32   * {@link SelfTransition} which invokes a {@link Method}. The {@link Method} can
33   * have zero or any number of StateContext and State regarding order
34   * <p>
35   * Normally you wouldn't create instances of this class directly but rather use the
36   * {@link SelfTransition} annotation to define the methods which should be used as
37   * transitions in your state machine and then let {@link StateMachineFactory} create a
38   * {@link StateMachine} for you.
39   * </p>
40   *
41   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
42   */
43  public class MethodSelfTransition extends AbstractSelfTransition {
44      private static final Logger LOGGER = LoggerFactory.getLogger(MethodTransition.class);
45  
46      private Method method;
47  
48      private final Object target;
49  
50      private static final Object[] EMPTY_ARGUMENTS = new Object[0];
51  
52      public MethodSelfTransition(Method method, Object target) {
53          super();
54          this.method = method;
55          this.target = target;
56      }
57  
58      /**
59       * Creates a new instance
60       * 
61       * @param method the target method.
62       * @param target the target object.
63       */
64      public MethodSelfTransition(String methodName, Object target) {
65  
66          this.target = target;
67  
68          Method[] candidates = target.getClass().getMethods();
69          Method result = null;
70          for (int i = 0; i < candidates.length; i++) {
71              if (candidates[i].getName().equals(methodName)) {
72                  if (result != null) {
73                      throw new AmbiguousMethodException(methodName);
74                  }
75                  result = candidates[i];
76              }
77          }
78  
79          if (result == null) {
80              throw new NoSuchMethodException(methodName);
81          }
82  
83          this.method = result;
84  
85      }
86  
87      /**
88       * Returns the target {@link Method}.
89       * 
90       * @return the method.
91       */
92      public Method getMethod() {
93          return method;
94      }
95  
96      public boolean doExecute(StateContext stateContext, State state) {
97          Class<?>[] types = method.getParameterTypes();
98  
99          if (types.length == 0) {
100             invokeMethod(EMPTY_ARGUMENTS);
101             return true;
102         }
103 
104         if (types.length > 2) {
105             return false;
106         }
107 
108         Object[] args = new Object[types.length];
109 
110         int i = 0;
111         if (types[i].isAssignableFrom(StateContext.class)) {
112             args[i++] = stateContext;
113         }
114         if (i < types.length && types[i].isAssignableFrom(State.class)) {
115             args[i++] = state;
116         }
117 
118         invokeMethod(args);
119 
120         return true;
121     }
122 
123     private void invokeMethod(Object[] arguments) {
124         try {
125             if (LOGGER.isDebugEnabled()) {
126                 LOGGER.debug("Executing method " + method + " with arguments " + Arrays.asList(arguments));
127             }
128             method.invoke(target, arguments);
129         } catch (InvocationTargetException ite) {
130             if (ite.getCause() instanceof RuntimeException) {
131                 throw (RuntimeException) ite.getCause();
132             }
133             throw new MethodInvocationException(method, ite);
134         } catch (IllegalAccessException iae) {
135             throw new MethodInvocationException(method, iae);
136         }
137     }
138 
139 }