KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > soap > server > RPCRouter


1 package org.apache.soap.server;
2
3 import java.io.*;
4 import java.util.*;
5 import java.lang.reflect.*;
6 import org.w3c.dom.*;
7 import org.apache.soap.util.Bean;
8 import org.apache.soap.util.MethodUtils;
9 import org.apache.soap.util.IOUtils;
10 import org.apache.soap.*;
11 import org.apache.soap.rpc.*;
12 import org.apache.soap.util.StringUtils;
13
14 /**
15  * This class is a transport independent SOAP RPC router. However you
16  * do it, if you get a SOAP envelope to me, I will build a Call object
17  * out of it, check whether its valid and finally do it for you (on
18  * an object you give me).
19  *
20  * @author Sanjiva Weerawarana <sanjiva@watson.ibm.com>
21  */

22 public class RPCRouter {
23   public static Call extractCallFromEnvelope (ServiceManager serviceManager,
24                                               Envelope callEnv,
25                                               SOAPContext ctx)
26                                                 throws SOAPException {
27     // determine target object URI by looking in the envelope
28
Vector bodyEntries = callEnv.getBody ().getBodyEntries ();
29     Element mainEntry = (Element) bodyEntries.elementAt (0);
30     String JavaDoc targetObjectURI = StringUtils.parseFullTargetObjectURI(mainEntry.getNamespaceURI ());
31     
32     // call on known entity?
33
DeploymentDescriptor dd = serviceManager.query (targetObjectURI);
34     if (dd == null) {
35       throw new SOAPException (
36         Constants.FAULT_CODE_SERVER_BAD_TARGET_OBJECT_URI,
37         "Unable to determine object id from call: is the method element " +
38         "namespaced?");
39     }
40
41     // If I'm supposed to check mustUnderstands, do it now.
42
if (dd.getCheckMustUnderstands()) {
43       Header header = callEnv.getHeader();
44
45       if (header != null) {
46         Utils.checkMustUnderstands(header);
47       }
48     }
49
50     // now extract the call from the call envelope with the given
51
// deployment information about the object. Note that I still
52
// pass in the service manager because I don't want to mess
53
// with that code right now. I should actually be passing in
54
// the soap mapping registry for this service.
55
return Call.extractFromEnvelope (callEnv, serviceManager, ctx);
56   }
57
58   /**
59    * Check whether the call is valid w.r.t. being on a method that's
60    * published by the service. The call is assumed to have been built
61    * by the above method; hence the call is on a known service.
62    */

63   public static boolean validCall (DeploymentDescriptor dd, Call call) {
64     String JavaDoc callMethodName = call.getMethodName ();
65     String JavaDoc[] pubMethods = dd.getMethods ();
66     for (int i = 0; i < pubMethods.length; i++) {
67       if (callMethodName.equals (pubMethods[i])) {
68         return true;
69       }
70     }
71     return false;
72   }
73
74   /**
75    * Do the call on the given target object.
76    */

77   public static Response invoke (DeploymentDescriptor dd,
78                                  Call call, Object JavaDoc targetObject,
79                                  SOAPContext reqCtx, SOAPContext resCtx )
80        throws SOAPException {
81     byte providerType = dd.getProviderType ();
82
83     // build the args and determine response encoding style
84
Vector params = call.getParams ();
85     String JavaDoc respEncStyle = call.getEncodingStyleURI ();
86     Object JavaDoc[] args = null;
87     Class JavaDoc[] argTypes = null;
88     if (params != null) {
89       int paramsCount = params.size ();
90       args = new Object JavaDoc[paramsCount];
91       argTypes = new Class JavaDoc[paramsCount];
92       for (int i = 0; i < paramsCount; i++) {
93         Parameter param = (Parameter) params.elementAt (i);
94         args[i] = param.getValue ();
95         argTypes[i] = param.getType ();
96         if (respEncStyle == null) {
97           respEncStyle = param.getEncodingStyleURI ();
98         }
99       }
100     }
101     if (respEncStyle == null) {
102       // need to set a default encoding to be used for the response
103
respEncStyle = Constants.NS_URI_SOAP_ENC;
104     }
105     
106     // invoke the method (directly for Java and via InvokeBSF for script
107
// methods)
108
Bean result = null;
109     try {
110       if (providerType == DeploymentDescriptor.PROVIDER_JAVA ||
111           providerType == DeploymentDescriptor.PROVIDER_USER_DEFINED) {
112         Method m = null ;
113         try {
114           m = MethodUtils.getMethod (targetObject,
115                                      call.getMethodName(),
116                                      argTypes);
117         } catch (NoSuchMethodException JavaDoc e) {
118           try {
119             int paramsCount = 0 ;
120             if ( params != null ) paramsCount = params.size();
121             Class JavaDoc[] tmpArgTypes = new Class JavaDoc[paramsCount+1];
122             Object JavaDoc[] tmpArgs = new Object JavaDoc[paramsCount+1];
123             for ( int i = 0 ; i < paramsCount ; i++ )
124               tmpArgTypes[i+1] = argTypes[i] ;
125             argTypes = tmpArgTypes ;
126             argTypes[0] = SOAPContext.class ;
127             m = MethodUtils.getMethod (targetObject,call.getMethodName(),
128                                        argTypes);
129             for ( int i = 0 ; i < paramsCount ; i++ )
130               tmpArgs[i+1] = args[i] ;
131             tmpArgs[0] = reqCtx ;
132             args = tmpArgs ;
133           } catch (NoSuchMethodException JavaDoc e2) {
134             /*
135               Don't want the "No Signature Match" error message to include
136               the SOAPContext argument.
137             */

138             throw e;
139           } catch (Exception JavaDoc e2) {
140             throw e2;
141           }
142         } catch (Exception JavaDoc e) {
143           throw e;
144         }
145
146         result = new Bean (m.getReturnType (), m.invoke (targetObject, args));
147       } else {
148         // find the class that provides the BSF services (done
149
// this way via reflection to avoid a compile-time dependency on BSF)
150
Class JavaDoc bc = Class.forName ("org.apache.soap.server.InvokeBSF");
151
152         // now invoke the service
153
Class JavaDoc[] sig = {DeploymentDescriptor.class,
154                        Object JavaDoc.class,
155                        String JavaDoc.class,
156                        Object JavaDoc[].class};
157         Method m = MethodUtils.getMethod (bc, "service", sig, true);
158         result = (Bean) m.invoke (null, new Object JavaDoc[] {dd, targetObject,
159                                                       call.getMethodName (),
160                                                       args});
161       }
162     } catch (InvocationTargetException e) {
163       Throwable JavaDoc t = e.getTargetException();
164
165       if (t instanceof SOAPException) {
166         throw (SOAPException)t;
167       } else {
168         throw new SOAPException(Constants.FAULT_CODE_SERVER,
169                                 "Exception from service object: " +
170                                 t.getMessage(), t);
171       }
172     } catch (ClassNotFoundException JavaDoc e) {
173       throw new SOAPException (Constants.FAULT_CODE_SERVER,
174                                "Unable to load BSF: script services " +
175                                "unsupported without BSF", e);
176     } catch (Throwable JavaDoc t) {
177       throw new SOAPException (Constants.FAULT_CODE_SERVER,
178                                "Exception while handling service request: " +
179                                t.getMessage(), t);
180     }
181    
182     // build the response object
183
Parameter ret = null;
184     if (result.type != void.class) {
185       ret = new Parameter (RPCConstants.ELEM_RETURN, result.type,
186                            result.value, null);
187     }
188     return new Response (call.getTargetObjectURI (), call.getMethodName (),
189                          ret, null, null, respEncStyle, resCtx);
190   }
191 }
192
Popular Tags