KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > message > RPCElement


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55
56 package org.jboss.axis.message;
57
58 import org.jboss.axis.AxisFault;
59 import org.jboss.axis.Constants;
60 import org.jboss.axis.Message;
61 import org.jboss.axis.MessageContext;
62 import org.jboss.axis.description.OperationDesc;
63 import org.jboss.axis.description.ParameterDesc;
64 import org.jboss.axis.description.ServiceDesc;
65 import org.jboss.axis.encoding.DeserializationContext;
66 import org.jboss.axis.encoding.SerializationContext;
67 import org.jboss.axis.enums.Style;
68 import org.jboss.axis.enums.Use;
69 import org.jboss.axis.handlers.soap.SOAPService;
70 import org.jboss.axis.soap.SOAPConstants;
71 import org.jboss.axis.utils.JavaUtils;
72 import org.jboss.axis.utils.Messages;
73 import org.jboss.axis.wsdl.toJava.Utils;
74 import org.jboss.logging.Logger;
75 import org.xml.sax.Attributes JavaDoc;
76 import org.xml.sax.SAXException JavaDoc;
77
78 import javax.xml.namespace.QName JavaDoc;
79 import javax.xml.soap.SOAPElement JavaDoc;
80 import javax.xml.soap.SOAPException JavaDoc;
81 import java.util.ArrayList JavaDoc;
82 import java.util.Enumeration JavaDoc;
83 import java.util.Vector JavaDoc;
84
85 public class RPCElement extends SOAPBodyElementAxisImpl
86 {
87    private static Logger log = Logger.getLogger(RPCElement.class.getName());
88
89    protected Vector JavaDoc params = new Vector JavaDoc();
90    protected boolean needDeser = false;
91    OperationDesc[] operations = null;
92
93    public RPCElement(String JavaDoc namespace, String JavaDoc localName, String JavaDoc prefix, Attributes JavaDoc attributes, DeserializationContext context, OperationDesc[] operations) throws AxisFault
94    {
95       super(namespace, localName, prefix, attributes, context);
96
97       // This came from parsing XML, so we need to deserialize it sometime
98
needDeser = true;
99
100       MessageContext msgContext = context.getMessageContext();
101
102       // Obtain our possible operations
103
if (operations == null && msgContext != null)
104       {
105          SOAPService service = msgContext.getService();
106          if (service != null)
107          {
108             ServiceDesc serviceDesc =
109                     service.getInitializedServiceDesc(msgContext);
110
111             String JavaDoc lc = Utils.xmlNameToJava(name);
112             if (serviceDesc == null)
113             {
114                AxisFault.makeFault(new ClassNotFoundException JavaDoc(Messages.getMessage("noClassForService00",
115                        lc)));
116             }
117
118             operations = serviceDesc.getOperationsByName(lc);
119          }
120       }
121       this.operations = operations;
122    }
123
124    public RPCElement(String JavaDoc namespace, String JavaDoc methodName, Object JavaDoc[] args)
125    {
126       super(namespace, methodName);
127       this.setNamespaceURI(namespace);
128       this.name = methodName;
129
130       for (int i = 0; args != null && i < args.length; i++)
131       {
132          RPCParam rpcParam = null;
133          if (args[i] instanceof RPCParam)
134          {
135             rpcParam = (RPCParam)args[i];
136
137          }
138          else
139          {
140             String JavaDoc name = null;
141             if (name == null) name = "arg" + i;
142             rpcParam = new RPCParam(namespace, name, args[i]);
143          }
144
145          addParam(rpcParam);
146
147          // Added to build the soap tree such that it contains SOAPElements for the parameters
148
// Revisit to do this properly for the different encoding styles, arrays, value types, etc.
149
// TDI 06-June-2006
150

151          try
152          {
153             addChildElement(new RPCParamElementImpl(rpcParam));
154          }
155          catch (SOAPException JavaDoc e)
156          {
157             log.error("Cannot ass rpc param child element", e);
158          }
159       }
160    }
161
162    public RPCElement(String JavaDoc methodName)
163    {
164       super(methodName);
165       this.name = methodName;
166    }
167
168    public String JavaDoc getMethodName()
169    {
170       return name;
171    }
172
173    public void setNeedDeser(boolean needDeser)
174    {
175       this.needDeser = needDeser;
176    }
177
178    public void deserialize() throws SAXException JavaDoc
179    {
180       needDeser = false;
181
182       MessageContext msgContext = context.getMessageContext();
183
184       // Figure out if we should be looking for out params or in params
185
// (i.e. is this message a response?)
186
Message msg = msgContext.getCurrentMessage();
187       SOAPConstants soapConstants = msgContext.getSOAPConstants();
188
189       boolean isResponse = ((msg != null) &&
190               Message.RESPONSE.equals(msg.getMessageType()));
191
192       // We're going to need this below, so create one.
193
RPCHandler rpcHandler = new RPCHandler(this, isResponse);
194
195       if (operations != null)
196       {
197          int numParams = getChildren().size();
198
199          SAXException JavaDoc savedException = null;
200
201          // By default, accept missing parameters as nulls, and
202
// allow the message context to override.
203
boolean acceptMissingParams = msgContext.isPropertyTrue(MessageContext.ACCEPTMISSINGPARAMS,
204                  true);
205
206          // We now have an array of all operations by this name. Try to
207
// find the right one. For each matching operation which has an
208
// equal number of "in" parameters, try deserializing. If we
209
// don't succeed for any of the candidates, punt.
210

211          for (int i = 0; i < operations.length; i++)
212          {
213             OperationDesc operation = operations[i];
214
215             // See if any information is coming from a header
216
boolean needHeaderProcessing =
217                     needHeaderProcessing(operation, isResponse);
218
219             // Make a quick check to determine if the operation
220
// could be a match.
221
// 1) The element is the first param, DOCUMENT, (i.e.
222
// don't know the operation name or the number
223
// of params, so try all operations).
224
// or (2) Style is literal
225
// If the Style is LITERAL, the numParams may be inflated
226
// as in the following case:
227
// <getAttractions xmlns="urn:CityBBB">
228
// <attname>Christmas</attname>
229
// <attname>Xmas</attname>
230
// </getAttractions>
231
// for getAttractions(String[] attName)
232
// numParams will be 2 and and operation.getNumInParams=1
233
// or (3) Number of expected params is
234
// >= num params in message
235
if (operation.getStyle() == Style.DOCUMENT ||
236                     operation.getStyle() == Style.WRAPPED ||
237                     operation.getUse() == Use.LITERAL ||
238                     (acceptMissingParams ?
239                     (operation.getNumInParams() >= numParams) :
240                     (operation.getNumInParams() == numParams)))
241             {
242
243                boolean isEncoded = operation.getUse() == Use.ENCODED;
244                rpcHandler.setOperation(operation);
245                try
246                {
247                   // If no operation name and more than one
248
// parameter is expected, don't
249
// wrap the rpcHandler in an EnvelopeHandler.
250
if ((operation.getStyle() == Style.DOCUMENT) &&
251                           operation.getNumInParams() > 0)
252                   {
253                      context.pushElementHandler(rpcHandler);
254                      context.setCurElement(null);
255                   }
256                   else
257                   {
258                      context.pushElementHandler(new EnvelopeHandler(rpcHandler));
259                      context.setCurElement(this);
260                   }
261
262                   publishToHandler((org.xml.sax.ContentHandler JavaDoc)context);
263
264                   // If parameter values are located in headers,
265
// get the information and publish the header
266
// elements to the rpc handler.
267
if (needHeaderProcessing)
268                   {
269                      processHeaders(operation, isResponse,
270                              context, rpcHandler);
271                   }
272
273                   // Check if the RPCParam's value match the signature of the
274
// param in the operation.
275
boolean match = true;
276                   for (int j = 0; j < params.size() && match; j++)
277                   {
278                      RPCParam rpcParam = (RPCParam)params.get(j);
279                      Object JavaDoc value = rpcParam.getValue();
280
281                      // first check the type on the paramter
282
ParameterDesc paramDesc = rpcParam.getParamDesc();
283
284                      // if we found some type info try to make sure the value type is
285
// correct. For instance, if we deserialized a xsd:dateTime in
286
// to a Calendar and the service takes a Date, we need to convert
287
if (paramDesc != null && paramDesc.getJavaType() != null)
288                      {
289
290                         // Get the type in the signature (java type or its holder)
291
Class JavaDoc sigType = paramDesc.getJavaType();
292                         if (!JavaUtils.isConvertable(value, sigType, isEncoded))
293                            match = false;
294                      }
295                   }
296                   // This is not the right operation, try the next one.
297
if (!match)
298                   {
299                      params = new Vector JavaDoc();
300                      continue;
301                   }
302
303                   // Success!! This is the right one...
304
msgContext.setOperation(operation);
305                   return;
306                }
307                catch (SAXException JavaDoc e)
308                {
309                   // If there was a problem, try the next one.
310
savedException = e;
311                   params = new Vector JavaDoc();
312                   continue;
313                }
314                catch (AxisFault e)
315                {
316                   // Thrown by getHeadersByName...
317
// If there was a problem, try the next one.
318
savedException = new SAXException JavaDoc(e);
319                   params = new Vector JavaDoc();
320                   continue;
321                }
322             }
323          }
324
325          // If we're SOAP 1.2, getting to this point means bad arguments.
326
if (!msgContext.isClient() && soapConstants == SOAPConstants.SOAP12_CONSTANTS)
327          {
328             AxisFault fault = new AxisFault(Constants.FAULT_SOAP12_SENDER, "string", null, null);
329             fault.addFaultSubCode(Constants.FAULT_SUBCODE_BADARGS);
330             throw new SAXException JavaDoc(fault);
331          }
332
333          if (savedException != null)
334          {
335             throw savedException;
336          }
337          else if (!msgContext.isClient())
338          {
339             QName JavaDoc faultCode = new QName JavaDoc(Constants.FAULT_SERVER_USER);
340             if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
341                faultCode = Constants.FAULT_SOAP12_SENDER;
342             AxisFault fault = new AxisFault(faultCode,
343                     null, Messages.getMessage("noSuchOperation", name), null, null, null);
344
345             throw new SAXException JavaDoc(fault);
346          }
347       }
348
349       if (operations != null)
350       {
351          rpcHandler.setOperation(operations[0]);
352       }
353
354       // Same logic as above. Don't wrap rpcHandler
355
// if there is no operation wrapper in the message
356
if (operations != null && operations.length > 0 &&
357               (operations[0].getStyle() == Style.DOCUMENT))
358       {
359          context.pushElementHandler(rpcHandler);
360          context.setCurElement(null);
361       }
362       else
363       {
364          context.pushElementHandler(new EnvelopeHandler(rpcHandler));
365          context.setCurElement(this);
366       }
367
368       publishToHandler((org.xml.sax.ContentHandler JavaDoc)context);
369    }
370
371    /**
372     * This gets the FIRST param whose name matches.
373     * !!! Should it return more in the case of duplicates?
374     */

375    public RPCParam getParam(String JavaDoc name) throws SAXException JavaDoc
376    {
377       if (needDeser)
378       {
379          deserialize();
380       }
381
382       for (int i = 0; i < params.size(); i++)
383       {
384          RPCParam param = (RPCParam)params.elementAt(i);
385          if (param.getName().equals(name))
386             return param;
387       }
388
389       return null;
390    }
391
392    public Vector JavaDoc getParams() throws SAXException JavaDoc
393    {
394       if (needDeser)
395       {
396          deserialize();
397       }
398
399       return params;
400    }
401
402    public void addParam(RPCParam param)
403    {
404       param.setRPCCall(this);
405       params.addElement(param);
406    }
407
408    protected void outputImpl(SerializationContext context) throws Exception JavaDoc
409    {
410       boolean hasOperationElement = true;
411
412       MessageContext msgContext = context.getMessageContext();
413       if (msgContext != null)
414          hasOperationElement = msgContext.getOperationStyle() == Style.RPC || msgContext.getOperationStyle() == Style.WRAPPED;
415
416       // When I have MIME and a no-param document WSDL, if I don't check
417
// for no params here, the server chokes with "can't find Body".
418
// because it will be looking for the enclosing element always
419
// found in an RPC-style (and wrapped) request
420
boolean noParams = params.size() == 0;
421       // If this has not been deserialized and there is a msg, recheck size
422
if (this.needDeser && context.getCurrentMessage() != null)
423          noParams = getParams().size() == 0;
424
425       if (hasOperationElement || noParams)
426       {
427          // Set default namespace if appropriate (to avoid prefix mappings
428
// in literal style). Do this only if there is no encodingStyle.
429
if (encodingStyle != null && encodingStyle.equals(""))
430          {
431             context.registerPrefixForURI("", getNamespaceURI());
432          }
433          context.startElement(new QName JavaDoc(getNamespaceURI(), name), attributes);
434       }
435
436       for (int i = 0; i < params.size(); i++)
437       {
438          RPCParam param = (RPCParam)params.elementAt(i);
439          if (!hasOperationElement && encodingStyle != null && encodingStyle.equals(""))
440          {
441             String JavaDoc uri = param.getQName().getNamespaceURI();
442             String JavaDoc prefix = context.getPrefixForURI(uri);
443             context.registerPrefixForURI(prefix, uri);
444          }
445          param.serialize(context);
446       }
447
448       if (hasOperationElement || noParams)
449       {
450          context.endElement();
451       }
452    }
453
454    /**
455     * needHeaderProcessing
456     *
457     * @param operation OperationDesc
458     * @param isResponse boolean indicates if request or response message
459     * @return true if the operation description indicates parameters/results
460     * are located in the soap header.
461     */

462    private boolean needHeaderProcessing(OperationDesc operation,
463                                         boolean isResponse)
464    {
465
466       // Search parameters/return to see if any indicate
467
// that instance data is contained in the header.
468
ArrayList JavaDoc paramDescs = operation.getParameters();
469       if (paramDescs != null)
470       {
471          for (int j = 0; j < paramDescs.size(); j++)
472          {
473             ParameterDesc paramDesc =
474                     (ParameterDesc)paramDescs.get(j);
475             if ((!isResponse && paramDesc.isInHeader()) ||
476                     (isResponse && paramDesc.isOutHeader()))
477             {
478                return true;
479             }
480          }
481       }
482       if (isResponse &&
483               operation.getReturnParamDesc() != null &&
484               operation.getReturnParamDesc().isOutHeader())
485       {
486          return true;
487       }
488       return false;
489    }
490
491    /**
492     * needHeaderProcessing
493     *
494     * @param operation OperationDesc
495     * @param isResponse boolean indicates if request or response message
496     * @param context DeserializationContext
497     * @param handler RPCHandler used to deserialize parameters
498     * are located in the soap header.
499     */

500    private void processHeaders(OperationDesc operation,
501                                boolean isResponse,
502                                DeserializationContext context,
503                                RPCHandler handler)
504            throws AxisFault, SAXException JavaDoc
505    {
506       // Inform handler that subsequent elements come from
507
// the header
508
try
509       {
510          handler.setHeaderElement(true);
511          // Get the soap envelope
512
SOAPElement JavaDoc envelope = getParentElement();
513          while (envelope != null &&
514                  !(envelope instanceof SOAPEnvelopeAxisImpl))
515          {
516             envelope = envelope.getParentElement();
517          }
518          if (envelope == null)
519             return;
520
521          // Find parameters that have instance
522
// data in the header.
523
ArrayList JavaDoc paramDescs = operation.getParameters();
524          if (paramDescs != null)
525          {
526             for (int j = 0; j < paramDescs.size(); j++)
527             {
528                ParameterDesc paramDesc =
529                        (ParameterDesc)paramDescs.get(j);
530                if ((!isResponse && paramDesc.isInHeader()) ||
531                        (isResponse && paramDesc.isOutHeader()))
532                {
533                   // Get the headers that match the parameter's
534
// QName
535
Enumeration JavaDoc headers = ((SOAPEnvelopeAxisImpl)envelope).
536                           getHeadersByName(paramDesc.getQName().getNamespaceURI(),
537                                   paramDesc.getQName().getLocalPart(),
538                                   true);
539                   // Publish each of the found elements to the
540
// handler. The pushElementHandler and
541
// setCurElement calls are necessary to
542
// have the message element recognized as a
543
// child of the RPCElement.
544
while (headers != null &&
545                           headers.hasMoreElements())
546                   {
547                      context.pushElementHandler(handler);
548                      context.setCurElement(null);
549                      ((SOAPElementAxisImpl)headers.nextElement()).
550                              publishToHandler((org.xml.sax.ContentHandler JavaDoc)context);
551                   }
552                }
553             }
554          }
555
556          // Now do the same processing for the return parameter.
557
if (isResponse &&
558                  operation.getReturnParamDesc() != null &&
559                  operation.getReturnParamDesc().isOutHeader())
560          {
561             ParameterDesc paramDesc = operation.getReturnParamDesc();
562             Enumeration JavaDoc headers =
563                     ((SOAPEnvelopeAxisImpl)envelope).
564                     getHeadersByName(paramDesc.getQName().getNamespaceURI(),
565                             paramDesc.getQName().getLocalPart(),
566                             true);
567             while (headers != null &&
568                     headers.hasMoreElements())
569             {
570                context.pushElementHandler(handler);
571                context.setCurElement(null);
572
573                ((SOAPElementAxisImpl)headers.nextElement()).
574                        publishToHandler((org.xml.sax.ContentHandler JavaDoc)context);
575             }
576          }
577       }
578       finally
579       {
580          handler.setHeaderElement(false);
581       }
582    }
583 }
584
Popular Tags