View Javadoc

1   package org.apache.maven.continuum.xmlrpc.server;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.xmlrpc.XmlRpcException;
23  import org.apache.xmlrpc.XmlRpcHandler;
24  import org.apache.xmlrpc.XmlRpcRequest;
25  import org.apache.xmlrpc.common.TypeConverter;
26  import org.apache.xmlrpc.common.TypeConverterFactory;
27  import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException;
28  import org.apache.xmlrpc.metadata.Util;
29  import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping;
30  import org.apache.xmlrpc.server.RequestProcessorFactoryFactory;
31  import org.codehaus.plexus.PlexusContainer;
32  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
33  
34  import java.lang.reflect.InvocationTargetException;
35  import java.lang.reflect.Method;
36  
37  /**
38   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
39   * @version $Id: ContinuumXmlRpcMetaDataHandler.java 1372267 2012-08-13 05:47:30Z brett $
40   */
41  public class ContinuumXmlRpcMetaDataHandler
42      implements XmlRpcHandler
43  {
44      private static class MethodData
45      {
46          final Method method;
47  
48          final TypeConverter[] typeConverters;
49  
50          MethodData( Method pMethod, TypeConverterFactory pTypeConverterFactory )
51          {
52              method = pMethod;
53              Class[] paramClasses = method.getParameterTypes();
54              typeConverters = new TypeConverter[paramClasses.length];
55              for ( int i = 0; i < paramClasses.length; i++ )
56              {
57                  typeConverters[i] = pTypeConverterFactory.getTypeConverter( paramClasses[i] );
58              }
59          }
60      }
61  
62      private final AbstractReflectiveHandlerMapping mapping;
63  
64      private final MethodData[] methods;
65  
66      private final Class clazz;
67  
68      private final RequestProcessorFactoryFactory.RequestProcessorFactory requestProcessorFactory;
69  
70      private final String[][] signatures;
71  
72      private final String methodHelp;
73  
74      private final PlexusContainer container;
75  
76      /**
77       * Creates a new instance.
78       *
79       * @param pMapping   The mapping, which creates this handler.
80       * @param pClass     The class, which has been inspected to create
81       *                   this handler. Typically, this will be the same as
82       *                   <pre>pInstance.getClass()</pre>. It is used for diagnostic
83       *                   messages only.
84       * @param pMethods   The method, which will be invoked for
85       *                   executing the handler.
86       * @param signatures The signature, which will be returned by
87       *                   {@link #getSignatures()}.
88       * @param methodHelp The help string, which will be returned
89       *                   by {@link #getMethodHelp()}.
90       * @param container  The container that loaded the component
91       */
92      public ContinuumXmlRpcMetaDataHandler( AbstractReflectiveHandlerMapping pMapping,
93                                             TypeConverterFactory pTypeConverterFactory, Class pClass,
94                                             RequestProcessorFactoryFactory.RequestProcessorFactory pFactory,
95                                             Method[] pMethods, String[][] signatures, String methodHelp,
96                                             PlexusContainer container )
97      {
98          mapping = pMapping;
99          clazz = pClass;
100         methods = new MethodData[pMethods.length];
101         requestProcessorFactory = pFactory;
102         for ( int i = 0; i < methods.length; i++ )
103         {
104             methods[i] = new MethodData( pMethods[i], pTypeConverterFactory );
105         }
106         this.signatures = signatures;
107         this.methodHelp = methodHelp;
108         this.container = container;
109     }
110 
111     private Object getInstance( XmlRpcRequest pRequest )
112         throws XmlRpcException
113     {
114         return requestProcessorFactory.getRequestProcessor( pRequest );
115     }
116 
117     public Object execute( XmlRpcRequest pRequest )
118         throws XmlRpcException
119     {
120         AbstractReflectiveHandlerMapping.AuthenticationHandler authHandler = mapping.getAuthenticationHandler();
121         if ( authHandler != null && !authHandler.isAuthorized( pRequest ) )
122         {
123             throw new XmlRpcNotAuthorizedException( "Not authorized" );
124         }
125         Object[] args = new Object[pRequest.getParameterCount()];
126         for ( int j = 0; j < args.length; j++ )
127         {
128             args[j] = pRequest.getParameter( j );
129         }
130         Object instance = getInstance( pRequest );
131         for ( MethodData methodData : methods )
132         {
133             TypeConverter[] converters = methodData.typeConverters;
134             if ( args.length == converters.length )
135             {
136                 boolean matching = true;
137                 for ( int j = 0; j < args.length; j++ )
138                 {
139                     if ( !converters[j].isConvertable( args[j] ) )
140                     {
141                         matching = false;
142                         break;
143                     }
144                 }
145                 if ( matching )
146                 {
147                     for ( int j = 0; j < args.length; j++ )
148                     {
149                         args[j] = converters[j].convert( args[j] );
150                     }
151                     return invoke( instance, methodData.method, args );
152                 }
153             }
154         }
155         throw new XmlRpcException( "No method matching arguments: " + Util.getSignature( args ) );
156     }
157 
158     private Object invoke( Object pInstance, Method pMethod, Object[] pArgs )
159         throws XmlRpcException
160     {
161         try
162         {
163             return pMethod.invoke( pInstance, pArgs );
164         }
165         catch ( IllegalAccessException e )
166         {
167             throw new XmlRpcException( "Illegal access to method " + pMethod.getName() + " in class " + clazz.getName(),
168                                        e );
169         }
170         catch ( IllegalArgumentException e )
171         {
172             throw new XmlRpcException(
173                 "Illegal argument for method " + pMethod.getName() + " in class " + clazz.getName(), e );
174         }
175         catch ( InvocationTargetException e )
176         {
177             Throwable t = e.getTargetException();
178             if ( t instanceof XmlRpcException )
179             {
180                 throw (XmlRpcException) t;
181             }
182             throw new XmlRpcException(
183                 "Failed to invoke method " + pMethod.getName() + " in class " + clazz.getName() + ": " + t.getMessage(),
184                 t );
185         }
186         finally
187         {
188             try
189             {
190                 container.release( pInstance );
191             }
192             catch ( ComponentLifecycleException e )
193             {
194                 //Do nothing
195             }
196         }
197     }
198 
199     public String[][] getSignatures()
200         throws XmlRpcException
201     {
202         return signatures;
203     }
204 
205     public String getMethodHelp()
206         throws XmlRpcException
207     {
208         return methodHelp;
209     }
210 
211 }