View Javadoc

1   package org.apache.maven.continuum.xmlrpc.server;
2   
3   import java.lang.reflect.InvocationTargetException;
4   import java.lang.reflect.Method;
5   
6   import org.apache.xmlrpc.XmlRpcException;
7   import org.apache.xmlrpc.XmlRpcHandler;
8   import org.apache.xmlrpc.XmlRpcRequest;
9   import org.apache.xmlrpc.common.TypeConverter;
10  import org.apache.xmlrpc.common.TypeConverterFactory;
11  import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException;
12  import org.apache.xmlrpc.metadata.Util;
13  import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping;
14  import org.apache.xmlrpc.server.RequestProcessorFactoryFactory;
15  import org.codehaus.plexus.PlexusContainer;
16  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
17  
18  /**
19   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
20   * @version $Id: ContinuumXmlRpcMetaDataHandler.java 765340 2009-04-15 20:22:00Z evenisse $
21   */
22  public class ContinuumXmlRpcMetaDataHandler
23      implements XmlRpcHandler
24  {
25      private static class MethodData
26      {
27          final Method method;
28  
29          final TypeConverter[] typeConverters;
30  
31          MethodData( Method pMethod, TypeConverterFactory pTypeConverterFactory )
32          {
33              method = pMethod;
34              Class[] paramClasses = method.getParameterTypes();
35              typeConverters = new TypeConverter[paramClasses.length];
36              for ( int i = 0; i < paramClasses.length; i++ )
37              {
38                  typeConverters[i] = pTypeConverterFactory.getTypeConverter( paramClasses[i] );
39              }
40          }
41      }
42  
43      private final AbstractReflectiveHandlerMapping mapping;
44  
45      private final MethodData[] methods;
46  
47      private final Class clazz;
48  
49      private final RequestProcessorFactoryFactory.RequestProcessorFactory requestProcessorFactory;
50  
51      private final String[][] signatures;
52  
53      private final String methodHelp;
54  
55      private final PlexusContainer container;
56  
57      /**
58       * Creates a new instance.
59       *
60       * @param pMapping   The mapping, which creates this handler.
61       * @param pClass     The class, which has been inspected to create
62       *                   this handler. Typically, this will be the same as
63       *                   <pre>pInstance.getClass()</pre>. It is used for diagnostic
64       *                   messages only.
65       * @param pMethods   The method, which will be invoked for
66       *                   executing the handler.
67       * @param signatures The signature, which will be returned by
68       *                   {@link #getSignatures()}.
69       * @param methodHelp The help string, which will be returned
70       *                   by {@link #getMethodHelp()}.
71       * @param container  The container that loaded the component
72       */
73      public ContinuumXmlRpcMetaDataHandler( AbstractReflectiveHandlerMapping pMapping,
74                                             TypeConverterFactory pTypeConverterFactory, Class pClass,
75                                             RequestProcessorFactoryFactory.RequestProcessorFactory pFactory,
76                                             Method[] pMethods, String[][] signatures, String methodHelp,
77                                             PlexusContainer container )
78      {
79          mapping = pMapping;
80          clazz = pClass;
81          methods = new MethodData[pMethods.length];
82          requestProcessorFactory = pFactory;
83          for ( int i = 0; i < methods.length; i++ )
84          {
85              methods[i] = new MethodData( pMethods[i], pTypeConverterFactory );
86          }
87          this.signatures = signatures;
88          this.methodHelp = methodHelp;
89          this.container = container;
90      }
91  
92      private Object getInstance( XmlRpcRequest pRequest )
93          throws XmlRpcException
94      {
95          return requestProcessorFactory.getRequestProcessor( pRequest );
96      }
97  
98      public Object execute( XmlRpcRequest pRequest )
99          throws XmlRpcException
100     {
101         AbstractReflectiveHandlerMapping.AuthenticationHandler authHandler = mapping.getAuthenticationHandler();
102         if ( authHandler != null && !authHandler.isAuthorized( pRequest ) )
103         {
104             throw new XmlRpcNotAuthorizedException( "Not authorized" );
105         }
106         Object[] args = new Object[pRequest.getParameterCount()];
107         for ( int j = 0; j < args.length; j++ )
108         {
109             args[j] = pRequest.getParameter( j );
110         }
111         Object instance = getInstance( pRequest );
112         for ( MethodData methodData : methods )
113         {
114             TypeConverter[] converters = methodData.typeConverters;
115             if ( args.length == converters.length )
116             {
117                 boolean matching = true;
118                 for ( int j = 0; j < args.length; j++ )
119                 {
120                     if ( !converters[j].isConvertable( args[j] ) )
121                     {
122                         matching = false;
123                         break;
124                     }
125                 }
126                 if ( matching )
127                 {
128                     for ( int j = 0; j < args.length; j++ )
129                     {
130                         args[j] = converters[j].convert( args[j] );
131                     }
132                     return invoke( instance, methodData.method, args );
133                 }
134             }
135         }
136         throw new XmlRpcException( "No method matching arguments: " + Util.getSignature( args ) );
137     }
138 
139     private Object invoke( Object pInstance, Method pMethod, Object[] pArgs )
140         throws XmlRpcException
141     {
142         try
143         {
144             return pMethod.invoke( pInstance, pArgs );
145         }
146         catch ( IllegalAccessException e )
147         {
148             throw new XmlRpcException( "Illegal access to method " + pMethod.getName() + " in class " + clazz.getName(),
149                                        e );
150         }
151         catch ( IllegalArgumentException e )
152         {
153             throw new XmlRpcException(
154                 "Illegal argument for method " + pMethod.getName() + " in class " + clazz.getName(), e );
155         }
156         catch ( InvocationTargetException e )
157         {
158             Throwable t = e.getTargetException();
159             if ( t instanceof XmlRpcException )
160             {
161                 throw (XmlRpcException) t;
162             }
163             throw new XmlRpcException(
164                 "Failed to invoke method " + pMethod.getName() + " in class " + clazz.getName() + ": " + t.getMessage(),
165                 t );
166         }
167         finally
168         {
169             try
170             {
171                 container.release( pInstance );
172             }
173             catch ( ComponentLifecycleException e )
174             {
175                 //Do nothing
176             }
177         }
178     }
179 
180     public String[][] getSignatures()
181         throws XmlRpcException
182     {
183         return signatures;
184     }
185 
186     public String getMethodHelp()
187         throws XmlRpcException
188     {
189         return methodHelp;
190     }
191 
192 }