KickJava   Java API By Example, From Geeks To Geeks.

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


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 /**
59  *
60  * @author Glen Daniels (gdaniels@allaire.com)
61  */

62
63 import org.jboss.axis.AxisFault;
64 import org.jboss.axis.Constants;
65 import org.jboss.axis.description.OperationDesc;
66 import org.jboss.axis.description.ParameterDesc;
67 import org.jboss.axis.encoding.DeserializationContext;
68 import org.jboss.axis.encoding.Deserializer;
69 import org.jboss.axis.encoding.DeserializerImpl;
70 import org.jboss.axis.encoding.MethodTarget;
71 import org.jboss.axis.soap.SOAPConstants;
72 import org.jboss.axis.utils.JavaUtils;
73 import org.jboss.axis.utils.Messages;
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 java.util.Vector JavaDoc;
81
82 /**
83  * This is the SOAPHandler which is called for each RPC parameter as we're
84  * deserializing the XML for a method call or return. In other words for
85  * this XML:
86  * <p/>
87  * <methodName>
88  * <param1 xsi:type="xsd:string">Hello!</param1>
89  * <param2>3.14159</param2>
90  * </methodName>
91  * <p/>
92  * ...we'll get onStartChild() events for <param1> and <param2>.
93  *
94  * @author Glen Daniels (gdaniels@apache.org)
95  */

96 public class RPCHandler extends SOAPHandler
97 {
98    private static Logger log = Logger.getLogger(RPCHandler.class.getName());
99
100    private RPCElement rpcElem;
101    private RPCParam currentParam = null;
102    private boolean isResponse;
103    private OperationDesc operation;
104    private boolean isHeaderElement;
105
106    public RPCHandler(RPCElement rpcElem, boolean isResponse)
107    {
108       this.rpcElem = rpcElem;
109       this.isResponse = isResponse;
110    }
111
112    public void setOperation(OperationDesc myOperation)
113    {
114       this.operation = myOperation;
115    }
116
117    /**
118     * Indicate RPCHandler is processing header elements
119     *
120     * @param value boolean indicating whether
121     * header elements are being processed.
122     */

123    public void setHeaderElement(boolean value)
124    {
125       isHeaderElement = true;
126    }
127
128    /**
129     * This method is invoked when an element start tag is encountered.
130     * The purpose of this method in RPCHandler is to reset variables
131     * (this allows re-use of RPCHandlers)
132     *
133     * @param namespace is the namespace of the element
134     * @param localName is the name of the element
135     * @param prefix is the prefix of the element
136     * @param attributes are the attributes on the element...used to get the type
137     * @param context is the DeserializationContext
138     */

139    public void startElement(String JavaDoc namespace, String JavaDoc localName,
140                             String JavaDoc prefix, Attributes JavaDoc attributes,
141                             DeserializationContext context)
142            throws SAXException JavaDoc
143    {
144       super.startElement(namespace, localName, prefix, attributes, context);
145       currentParam = null;
146    }
147
148    /**
149     * Register the start of a parameter (child element of the method call
150     * element).
151     * <p/>
152     * Our job here is to figure out a) which parameter this is (based on
153     * the QName of the element or its position), and b) what type it is
154     * (based on the xsi:type attribute or operation metadata) so we can
155     * successfully deserialize it.
156     */

157    public SOAPHandler onStartChild(String JavaDoc namespace,
158                                    String JavaDoc localName,
159                                    String JavaDoc prefix,
160                                    Attributes JavaDoc attributes,
161                                    DeserializationContext context)
162            throws SAXException JavaDoc
163    {
164       if (log.isDebugEnabled())
165       {
166          log.debug("Enter: RPCHandler.onStartChild()");
167       }
168
169       if (!context.isDoneParsing())
170       {
171          try
172          {
173             context.pushNewElement(new SOAPElementAxisImpl(namespace, localName,
174                     prefix, attributes,
175                     context));
176          }
177          catch (AxisFault axisFault)
178          {
179             throw new SAXException JavaDoc(axisFault);
180          }
181       }
182
183       SOAPElementAxisImpl curEl = context.getCurElement();
184       QName JavaDoc type = null;
185       QName JavaDoc qname = new QName JavaDoc(namespace, localName);
186       ParameterDesc paramDesc = null;
187
188       SOAPConstants soapConstants = context.getMessageContext().getSOAPConstants();
189       if (soapConstants == SOAPConstants.SOAP12_CONSTANTS &&
190               Constants.QNAME_RPC_RESULT.equals(qname))
191       {
192          // TODO: fix it ... now we just skip it
193
return new DeserializerImpl();
194       }
195
196       Vector JavaDoc params = rpcElem.getParams();
197
198       // Create a new param if not the same element
199
if (currentParam == null ||
200               !currentParam.getQName().getNamespaceURI().equals(namespace) ||
201               !currentParam.getQName().getLocalPart().equals(localName))
202       {
203          currentParam = new RPCParam(namespace, localName, null);
204          rpcElem.addParam(currentParam);
205       }
206
207       // Grab xsi:type attribute if present, on either this element or
208
// the referent (if it's an href). MessageElement.getType() will
209
// automatically dig through to the referent if necessary.
210
type = curEl.getType();
211       if (type == null)
212       {
213          type = context.getTypeFromAttributes(namespace, localName, attributes);
214       }
215
216       if (log.isDebugEnabled())
217       {
218          log.debug(Messages.getMessage("typeFromAttr00", "" + type));
219       }
220
221
222       Class JavaDoc destClass = null;
223
224       // If we have an operation descriptor, try to associate this parameter
225
// with the appropriate ParameterDesc
226
if (operation != null)
227       {
228
229          // Try by name first
230
if (isResponse)
231          {
232             paramDesc = operation.getOutputParamByQName(qname);
233          }
234          else
235          {
236             paramDesc = operation.getInputParamByQName(qname);
237          }
238
239
240          // If that didn't work, try position
241
// FIXME : Do we need to be in EITHER named OR positional
242
// mode? I.e. will it screw us up to find something
243
// by position if we've already looked something up
244
// by name? I think so...
245
if (paramDesc == null)
246          {
247             if (isResponse)
248             {
249                paramDesc = operation.getReturnParamDesc();
250             }
251             else
252             {
253                paramDesc = operation.getParameter(params.size() - 1);
254             }
255          }
256
257          if (paramDesc == null)
258          {
259             throw new SAXException JavaDoc(Messages.getMessage("noParmDesc"));
260          }
261          // Make sure that we don't find body parameters that should
262
// be in the header
263
if (!isHeaderElement &&
264                  ((isResponse && paramDesc.isOutHeader()) ||
265                  (!isResponse && paramDesc.isInHeader())))
266          {
267             throw new SAXException JavaDoc(Messages.getMessage("expectedHeaderParam",
268                     paramDesc.getQName().toString()));
269          }
270
271          destClass = paramDesc.getJavaType();
272
273          // Keep the association so we can use it later
274
// (see RPCProvider.processMessage())
275
currentParam.setParamDesc(paramDesc);
276
277          if (type == null)
278          {
279             type = paramDesc.getTypeQName();
280          }
281       }
282
283       // If the nil attribute is set, just
284
// return the base DeserializerImpl.
285
// Register the value target to set the value
286
// on the RPCParam. This is necessary for cases like
287
// <method>
288
// <foo>123</foo>
289
// <foo>456</foo>
290
// <foo xsi:nil="true" />
291
// </method>
292
// so that a list of 3 items is created.
293
// Failure to register the target would result in the last
294
// item not being added to the list
295
if (context.isNil(attributes))
296       {
297          Deserializer nilDSer = new DeserializerImpl();
298          nilDSer.registerValueTarget(new MethodTarget(currentParam, RPCParam.getValueSetMethod()));
299          return (SOAPHandler)nilDSer;
300       }
301
302       Deserializer dser = null;
303       if ((type == null) && (namespace != null) && (!namespace.equals("")))
304       {
305          dser = context.getDeserializerForType(qname);
306       }
307       else
308       {
309          dser = context.getDeserializer(destClass, type);
310       }
311
312       if (dser == null)
313       {
314          if (type != null)
315          {
316             dser = context.getDeserializerForType(type);
317             if (null != destClass && dser == null && destClass.isAssignableFrom(SOAPElement JavaDoc.class))
318             {
319                //If a DOM element is expected, as last resort always allow direct mapping
320
// of parameter's SOAP xml to a DOM element. Support of literal parms by default.
321
dser = context.getDeserializerForType(Constants.SOAP_ELEMENT);
322
323             }
324             if (dser == null)
325             {
326                throw new SAXException JavaDoc(Messages.getMessage("noDeser01", localName, "" + type));
327             }
328             if (paramDesc != null && paramDesc.getJavaType() != null && !Constants.XSD_ANYTYPE.equals(type))
329             {
330                // If we have an xsi:type, make sure it makes sense with the current paramDesc type
331
Class JavaDoc xsiClass = context.getTypeMapping().getClassForQName(type);
332                if (xsiClass != null && !JavaUtils.isConvertable(xsiClass, destClass))
333                {
334                   throw new SAXException JavaDoc("Bad types (" + xsiClass + " -> " + destClass + ")");
335                }
336             }
337          }
338          else
339          {
340             dser = new DeserializerImpl();
341             if (dser == null)
342             {
343                throw new SAXException JavaDoc(Messages.getMessage("noDeser01", localName, "" + type));
344             }
345          }
346       }
347
348       dser.setDefaultType(type);
349
350       dser.registerValueTarget(new MethodTarget(currentParam, RPCParam.getValueSetMethod()));
351
352       if (log.isDebugEnabled())
353       {
354          log.debug("Exit: RPCHandler.onStartChild()");
355       }
356       return (SOAPHandler)dser;
357    }
358
359    public void endElement(String JavaDoc namespace, String JavaDoc localName, DeserializationContext context)
360            throws SAXException JavaDoc
361    {
362       // endElement may not be called in all circumstances.
363
// In addition, onStartChild may be called after endElement
364
// (for header parameter/response processing).
365
// So please don't add important logic to this method.
366
if (log.isDebugEnabled())
367       {
368          log.debug(Messages.getMessage("setProp00",
369                  "MessageContext", "RPCHandler.endElement()."));
370       }
371       context.getMessageContext().setProperty("RPC", rpcElem);
372    }
373 }
374
Popular Tags