KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > encoding > ser > SimpleDeserializer


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.encoding.ser;
57
58 import org.jboss.axis.description.TypeDesc;
59 import org.jboss.axis.encoding.DeserializationContext;
60 import org.jboss.axis.encoding.Deserializer;
61 import org.jboss.axis.encoding.DeserializerImpl;
62 import org.jboss.axis.encoding.SimpleType;
63 import org.jboss.axis.encoding.TypeMapping;
64 import org.jboss.axis.message.SOAPHandler;
65 import org.jboss.axis.utils.BeanPropertyDescriptor;
66 import org.jboss.axis.utils.BeanUtils;
67 import org.jboss.axis.utils.Messages;
68 import org.jboss.logging.Logger;
69 import org.xml.sax.Attributes JavaDoc;
70 import org.xml.sax.SAXException JavaDoc;
71
72 import javax.xml.namespace.QName JavaDoc;
73 import java.io.CharArrayWriter JavaDoc;
74 import java.lang.reflect.Constructor JavaDoc;
75 import java.lang.reflect.InvocationTargetException JavaDoc;
76 import java.util.HashMap JavaDoc;
77 import java.util.Iterator JavaDoc;
78 import java.util.Map JavaDoc;
79 import java.util.Set JavaDoc;
80
81 /**
82  * A deserializer for any simple type with a (String) constructor. Note:
83  * this class is designed so that subclasses need only override the makeValue
84  * method in order to construct objects of their own type.
85  *
86  * @author Glen Daniels (gdaniels@macromedia.com)
87  * @author Sam Ruby (rubys@us.ibm.com)
88  * Modified for JAX-RPC @author Rich Scheuerle (scheu@us.ibm.com)
89  */

90 public class SimpleDeserializer extends DeserializerImpl
91 {
92    private static Logger log = Logger.getLogger(SimpleDeserializer.class.getName());
93
94    //StringBuffer val = new StringBuffer(); -- FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11945
95
private final CharArrayWriter JavaDoc val = new CharArrayWriter JavaDoc();
96    private Constructor JavaDoc constructor = null;
97    private Map JavaDoc propertyMap = null;
98    private HashMap JavaDoc attributeMap = null;
99
100    public QName JavaDoc xmlType;
101    public Class JavaDoc javaType;
102
103    private TypeDesc typeDesc = null;
104
105    protected SimpleDeserializer cacheStringDSer = null;
106    protected QName JavaDoc cacheXMLType = null;
107
108    /**
109     * The Deserializer is constructed with the xmlType and
110     * javaType (which could be a java primitive like int.class)
111     */

112    public SimpleDeserializer(Class JavaDoc javaType, QName JavaDoc xmlType)
113    {
114       this.xmlType = xmlType;
115       this.javaType = javaType;
116
117       init();
118    }
119
120    public SimpleDeserializer(Class JavaDoc javaType, QName JavaDoc xmlType, TypeDesc typeDesc)
121    {
122       this.xmlType = xmlType;
123       this.javaType = javaType;
124       this.typeDesc = typeDesc;
125
126       init();
127    }
128
129    /**
130     * Initialize the typeDesc, property descriptors and propertyMap.
131     */

132    private void init()
133    {
134       // The typeDesc and map array are only necessary
135
// if this class extends SimpleType.
136
if (SimpleType.class.isAssignableFrom(javaType))
137       {
138          // Set the typeDesc if not already set
139
if (typeDesc == null)
140          {
141             typeDesc = TypeDesc.getTypeDescForClass(javaType);
142          }
143          // Get the cached propertyDescriptor from the type or
144
// generate a fresh one.
145
if (typeDesc != null)
146          {
147             propertyMap = typeDesc.getPropertyDescriptorMap();
148          }
149          else
150          {
151             BeanPropertyDescriptor[] pd = BeanUtils.getPd(javaType, null);
152             propertyMap = new HashMap JavaDoc();
153             for (int i = 0; i < pd.length; i++)
154             {
155                BeanPropertyDescriptor descriptor = pd[i];
156                propertyMap.put(descriptor.getName(), descriptor);
157             }
158          }
159       }
160    }
161
162    /**
163     * Reset deserializer for re-use
164     */

165    public void reset()
166    {
167       //val.setLength(0); // Reset string buffer back to zero -- FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11945
168
val.reset();
169       attributeMap = null; // Remove attribute map
170
isNil = false; // Don't know if nil
171
isEnded = false; // Indicate the end of element not yet called
172
}
173
174    /**
175     * Remove the Value Targets of the Deserializer.
176     * Simple deserializers may be re-used, so don't
177     * nullify the vector.
178     */

179    public void removeValueTargets()
180    {
181       if (targets != null)
182       {
183          targets.clear();
184          // targets = null;
185
}
186    }
187
188    /**
189     * The Factory calls setConstructor.
190     */

191    public void setConstructor(Constructor JavaDoc c)
192    {
193       constructor = c;
194    }
195
196    /**
197     * There should not be nested elements, so thow and exception if this occurs.
198     */

199    public SOAPHandler onStartChild(String JavaDoc namespace,
200                                    String JavaDoc localName,
201                                    String JavaDoc prefix,
202                                    Attributes JavaDoc attributes,
203                                    DeserializationContext context)
204            throws SAXException JavaDoc
205    {
206       throw new SAXException JavaDoc(Messages.getMessage("cantHandle00", "SimpleDeserializer"));
207    }
208
209    /**
210     * Append any characters received to the value. This method is defined
211     * by Deserializer.
212     */

213    public void characters(char[] chars, int start, int end)
214            throws SAXException JavaDoc
215    {
216       //val.append(chars, start, end); -- FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11945
217
val.write(chars, start, end);
218    }
219
220    /**
221     * Append any characters to the value. This method is defined by
222     * Deserializer.
223     */

224    public void onEndElement(String JavaDoc namespace, String JavaDoc localName,
225                             DeserializationContext context)
226            throws SAXException JavaDoc
227    {
228       //if (isNil || val == null) { -- FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11945
229
if (isNil)
230       {
231          value = null;
232          return;
233       }
234       try
235       {
236          value = makeValue(val.toString());
237       }
238       catch (InvocationTargetException JavaDoc ite)
239       {
240          Throwable JavaDoc realException = ite.getTargetException();
241          if (realException instanceof Exception JavaDoc)
242             throw new SAXException JavaDoc((Exception JavaDoc)realException);
243          else
244             throw new SAXException JavaDoc(ite.getMessage());
245       }
246       catch (Exception JavaDoc e)
247       {
248          throw new SAXException JavaDoc(e);
249       }
250
251       // If this is a SimpleType, set attributes we have stashed away
252
setSimpleTypeAttributes();
253    }
254
255    /**
256     * Convert the string that has been accumulated into an Object. Subclasses
257     * may override this. Note that if the javaType is a primitive, the returned
258     * object is a wrapper class.
259     *
260     * @param source the serialized value to be deserialized
261     * @throws Exception any exception thrown by this method will be wrapped
262     */

263    public Object JavaDoc makeValue(String JavaDoc source) throws Exception JavaDoc
264    {
265
266       log.debug("Making value [" + source + "] for javaType: " + javaType);
267
268       // If the javaType is a boolean, except a number of different sources
269
if (javaType == boolean.class || javaType == Boolean JavaDoc.class)
270       {
271          // This is a pretty lame test, but it is what the previous code did.
272
switch (source.charAt(0))
273          {
274             case '0':
275             case 'f':
276             case 'F':
277                return Boolean.FALSE;
278
279             case '1':
280             case 't':
281             case 'T':
282                return Boolean.TRUE;
283
284             default:
285                throw new NumberFormatException JavaDoc(Messages.getMessage("badBool00"));
286          }
287
288       }
289
290       // If expecting a Float or a Double, need to accept some special cases.
291
if (javaType == float.class ||
292               javaType == java.lang.Float JavaDoc.class)
293       {
294          if (source.equals("NaN"))
295          {
296             return new Float JavaDoc(Float.NaN);
297          }
298          else if (source.equals("INF"))
299          {
300             return new Float JavaDoc(Float.POSITIVE_INFINITY);
301          }
302          else if (source.equals("-INF"))
303          {
304             return new Float JavaDoc(Float.NEGATIVE_INFINITY);
305          }
306       }
307
308       if (javaType == double.class ||
309               javaType == java.lang.Double JavaDoc.class)
310       {
311          if (source.equals("NaN"))
312          {
313             return new Double JavaDoc(Double.NaN);
314          }
315          else if (source.equals("INF"))
316          {
317             return new Double JavaDoc(Double.POSITIVE_INFINITY);
318          }
319          else if (source.equals("-INF"))
320          {
321             return new Double JavaDoc(Double.NEGATIVE_INFINITY);
322          }
323       }
324
325       return constructor.newInstance(new Object JavaDoc[]{source});
326    }
327
328    /**
329     * Set the bean properties that correspond to element attributes.
330     * <p/>
331     * This method is invoked after startElement when the element requires
332     * deserialization (i.e. the element is not an href and the value is not nil.)
333     *
334     * @param namespace is the namespace of the element
335     * @param localName is the name of the element
336     * @param prefix is the prefix of the element
337     * @param attributes are the attributes on the element...used to get the type
338     * @param context is the DeserializationContext
339     */

340    public void onStartElement(String JavaDoc namespace, String JavaDoc localName,
341                               String JavaDoc prefix, Attributes JavaDoc attributes,
342                               DeserializationContext context)
343            throws SAXException JavaDoc
344    {
345
346       // If we have no metadata, we have no attributes. Q.E.D.
347
if (typeDesc == null)
348          return;
349
350       // loop through the attributes and set bean properties that
351
// correspond to attributes
352
for (int i = 0; i < attributes.getLength(); i++)
353       {
354          QName JavaDoc attrQName = new QName JavaDoc(attributes.getURI(i),
355                  attributes.getLocalName(i));
356          String JavaDoc fieldName = typeDesc.getFieldNameForAttribute(attrQName);
357          if (fieldName != null)
358          {
359             // look for the attribute property
360
BeanPropertyDescriptor bpd = (BeanPropertyDescriptor)propertyMap.get(fieldName);
361             if (bpd != null)
362             {
363                if (!bpd.isWriteable() || bpd.isIndexed())
364                   continue;
365
366                // determine the QName for this child element
367
TypeMapping tm = context.getTypeMapping();
368                Class JavaDoc type = bpd.getType();
369                QName JavaDoc qn = tm.getTypeQName(type);
370                if (qn == null)
371                   throw new SAXException JavaDoc(Messages.getMessage("unregistered00", type.toString()));
372
373                // get the deserializer
374
Deserializer dSer = context.getDeserializerForType(qn);
375                if (dSer == null)
376                   throw new SAXException JavaDoc(Messages.getMessage("noDeser00", type.toString()));
377                if (!(dSer instanceof SimpleDeserializer))
378                   throw new SAXException JavaDoc(Messages.getMessage("AttrNotSimpleType00", bpd.getName(), type.toString()));
379
380                // Success! Create an object from the string and save
381
// it in our attribute map for later.
382
if (attributeMap == null)
383                {
384                   attributeMap = new HashMap JavaDoc();
385                }
386                try
387                {
388                   Object JavaDoc val = ((SimpleDeserializer)dSer).makeValue(attributes.getValue(i));
389                   attributeMap.put(fieldName, val);
390                }
391                catch (Exception JavaDoc e)
392                {
393                   throw new SAXException JavaDoc(e);
394                }
395             }
396          }
397       } // attribute loop
398
} // onStartElement
399

400    /**
401     * Process any attributes we may have encountered (in onStartElement)
402     */

403    private void setSimpleTypeAttributes() throws SAXException JavaDoc
404    {
405       // if this isn't a simpleType bean, wont have attributes
406
if (!SimpleType.class.isAssignableFrom(javaType) ||
407               attributeMap == null)
408          return;
409
410       // loop through map
411
Set JavaDoc entries = attributeMap.entrySet();
412       for (Iterator JavaDoc iterator = entries.iterator(); iterator.hasNext();)
413       {
414          Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iterator.next();
415          String JavaDoc name = (String JavaDoc)entry.getKey();
416          Object JavaDoc val = entry.getValue();
417
418          BeanPropertyDescriptor bpd =
419                  (BeanPropertyDescriptor)propertyMap.get(name);
420          if (!bpd.isWriteable() || bpd.isIndexed()) continue;
421          try
422          {
423             bpd.set(value, val);
424          }
425          catch (Exception JavaDoc e)
426          {
427             throw new SAXException JavaDoc(e);
428          }
429       }
430    }
431
432 }
433
Popular Tags