KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > utils > JavaUtils


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.utils;
57
58 import org.jboss.axis.attachments.AttachmentPartImpl;
59 import org.jboss.axis.attachments.OctetStream;
60 import org.jboss.axis.components.image.ImageIO;
61 import org.jboss.axis.components.image.ImageIOFactory;
62 import org.jboss.axis.types.HexBinary;
63 import org.jboss.logging.Logger;
64
65 import javax.activation.DataHandler JavaDoc;
66 import javax.xml.namespace.QName JavaDoc;
67 import javax.xml.rpc.holders.*;
68 import javax.xml.soap.SOAPException JavaDoc;
69 import javax.xml.transform.Source JavaDoc;
70 import javax.xml.transform.stream.StreamSource JavaDoc;
71 import java.awt.*;
72 import java.beans.Introspector JavaDoc;
73 import java.io.ByteArrayOutputStream JavaDoc;
74 import java.io.IOException JavaDoc;
75 import java.io.InputStream JavaDoc;
76 import java.io.StringReader JavaDoc;
77 import java.lang.reflect.Array JavaDoc;
78 import java.lang.reflect.Constructor JavaDoc;
79 import java.lang.reflect.Field JavaDoc;
80 import java.lang.reflect.Method JavaDoc;
81 import java.math.BigDecimal JavaDoc;
82 import java.math.BigInteger JavaDoc;
83 import java.text.Collator JavaDoc;
84 import java.util.ArrayList JavaDoc;
85 import java.util.Arrays JavaDoc;
86 import java.util.Calendar JavaDoc;
87 import java.util.Collection JavaDoc;
88 import java.util.GregorianCalendar JavaDoc;
89 import java.util.HashMap JavaDoc;
90 import java.util.HashSet JavaDoc;
91 import java.util.Hashtable JavaDoc;
92 import java.util.Iterator JavaDoc;
93 import java.util.List JavaDoc;
94 import java.util.Locale JavaDoc;
95 import java.util.Set JavaDoc;
96
97 /**
98  * Utility class to deal with Java language related issues, such
99  * as type conversions.
100  *
101  * @author Glen Daniels (gdaniels@macromedia.com)
102  */

103 public class JavaUtils
104 {
105    private static Logger log = Logger.getLogger(JavaUtils.class.getName());
106
107    public static final char NL = '\n';
108
109    public static final char CR = '\r';
110
111    /**
112     * The prefered line separator
113     */

114    public static final String JavaDoc LS = System.getProperty("line.separator",
115            (new Character JavaDoc(NL)).toString());
116
117
118    public static Class JavaDoc getWrapperClass(Class JavaDoc primitive)
119    {
120       if (primitive == int.class)
121          return java.lang.Integer JavaDoc.class;
122       else if (primitive == short.class)
123          return java.lang.Short JavaDoc.class;
124       else if (primitive == boolean.class)
125          return java.lang.Boolean JavaDoc.class;
126       else if (primitive == byte.class)
127          return java.lang.Byte JavaDoc.class;
128       else if (primitive == long.class)
129          return java.lang.Long JavaDoc.class;
130       else if (primitive == double.class)
131          return java.lang.Double JavaDoc.class;
132       else if (primitive == float.class)
133          return java.lang.Float JavaDoc.class;
134       else if (primitive == char.class)
135          return java.lang.Character JavaDoc.class;
136
137       return null;
138    }
139
140    public static String JavaDoc getWrapper(String JavaDoc primitive)
141    {
142       if (primitive.equals("int"))
143          return "Integer";
144       else if (primitive.equals("short"))
145          return "Short";
146       else if (primitive.equals("boolean"))
147          return "Boolean";
148       else if (primitive.equals("byte"))
149          return "Byte";
150       else if (primitive.equals("long"))
151          return "Long";
152       else if (primitive.equals("double"))
153          return "Double";
154       else if (primitive.equals("float"))
155          return "Float";
156       else if (primitive.equals("char"))
157          return "Character";
158
159       return null;
160    }
161
162    public static Class JavaDoc getPrimitiveClass(Class JavaDoc wrapper)
163    {
164       if (wrapper == java.lang.Integer JavaDoc.class)
165          return int.class;
166       else if (wrapper == java.lang.Short JavaDoc.class)
167          return short.class;
168       else if (wrapper == java.lang.Boolean JavaDoc.class)
169          return boolean.class;
170       else if (wrapper == java.lang.Byte JavaDoc.class)
171          return byte.class;
172       else if (wrapper == java.lang.Long JavaDoc.class)
173          return long.class;
174       else if (wrapper == java.lang.Double JavaDoc.class)
175          return double.class;
176       else if (wrapper == java.lang.Float JavaDoc.class)
177          return float.class;
178       else if (wrapper == java.lang.Character JavaDoc.class)
179          return char.class;
180
181       return null;
182    }
183
184    public static Class JavaDoc getPrimitiveClass(String JavaDoc javaType)
185    {
186       if ("int".equals(javaType))
187          return int.class;
188       else if ("short".equals(javaType))
189          return short.class;
190       else if ("boolean".equals(javaType))
191          return boolean.class;
192       else if ("byte".equals(javaType))
193          return byte.class;
194       else if ("long".equals(javaType))
195          return long.class;
196       else if ("double".equals(javaType))
197          return double.class;
198       else if ("float".equals(javaType))
199          return float.class;
200       else if ("char".equals(javaType))
201          return char.class;
202
203       return null;
204    }
205
206    /**
207     * It the argument to the convert(...) method implements
208     * the ConvertCache interface, the convert(...) method
209     * will use the set/get methods to store and retrieve
210     * converted values.
211     */

212    public interface ConvertCache
213    {
214       /**
215        * Set/Get converted values of the convert method.
216        */

217       public void setConvertedValue(Class JavaDoc cls, Object JavaDoc value);
218
219       public Object JavaDoc getConvertedValue(Class JavaDoc cls);
220
221       /**
222        * Get the destination array class described by the xml
223        */

224       public Class JavaDoc getDestClass();
225    }
226
227    /**
228     * Utility function to convert an Object to some desired Class.
229     * <p/>
230     * Right now this works for:
231     * arrays <-> Lists,
232     * Holders <-> held values
233     *
234     * @param arg the array to convert
235     * @param destClass the actual class we want
236     */

237    public static Object JavaDoc convert(Object JavaDoc arg, Class JavaDoc destClass)
238    {
239       if (destClass == null)
240       {
241          return arg;
242       }
243
244       Class JavaDoc argHeldType = null;
245       if (arg != null)
246       {
247          argHeldType = getHolderValueType(arg.getClass());
248       }
249
250       if (arg != null && argHeldType == null && destClass.isAssignableFrom(arg.getClass()))
251       {
252          return arg;
253       }
254
255       if (arg != null && destClass != null)
256          assertClassLoaders(arg.getClass(), destClass);
257
258       if (log.isDebugEnabled())
259       {
260          String JavaDoc clsName = "null";
261          if (arg != null) clsName = arg.getClass().getName();
262          log.debug(Messages.getMessage("convert00", clsName, destClass.getName()));
263       }
264
265       // See if a previously converted value is stored in the argument.
266
Object JavaDoc destValue = null;
267       if (arg instanceof ConvertCache)
268       {
269          destValue = ((ConvertCache)arg).getConvertedValue(destClass);
270          if (destValue != null)
271             return destValue;
272       }
273
274       // Get the destination held type or the argument held type if they exist
275
Class JavaDoc destHeldType = getHolderValueType(destClass);
276
277       // Convert between Axis special purpose HexBinary and byte[]
278
if (arg instanceof HexBinary && destClass == byte[].class)
279          return ((HexBinary)arg).getBytes();
280       if (arg instanceof byte[] && destClass == HexBinary.class)
281          return new HexBinary((byte[])arg);
282       if (arg instanceof HexBinary && destClass == Byte JavaDoc[].class)
283          return convert(((HexBinary)arg).getBytes(), Byte JavaDoc[].class);
284       if (arg instanceof Byte JavaDoc[] && destClass == HexBinary.class)
285          return new HexBinary((Byte JavaDoc[])arg);
286
287       // Convert between Calendar and Date
288
if (arg instanceof Calendar JavaDoc && destClass.isAssignableFrom(java.util.Date JavaDoc.class))
289       {
290          return ((Calendar JavaDoc)arg).getTime();
291       }
292       if (arg instanceof java.util.Date JavaDoc && destClass.isAssignableFrom(Calendar JavaDoc.class))
293       {
294          GregorianCalendar JavaDoc gregorianCalendar = new GregorianCalendar JavaDoc();
295          gregorianCalendar.setTime((java.util.Date JavaDoc)arg);
296          return gregorianCalendar;
297       }
298
299       // Convert between Calendar and org.jboss.axis.types.Time
300
if (arg instanceof Calendar JavaDoc && destClass.isAssignableFrom(org.jboss.axis.types.Time.class))
301          return new org.jboss.axis.types.Time((Calendar JavaDoc)arg);
302       if (arg instanceof org.jboss.axis.types.Time && destClass.isAssignableFrom(Calendar JavaDoc.class))
303          return ((org.jboss.axis.types.Time)arg).getAsCalendar();
304
305       // Convert between HashMap and Hashtable
306
if (arg instanceof HashMap JavaDoc && destClass == Hashtable JavaDoc.class)
307       {
308          return new Hashtable JavaDoc((HashMap JavaDoc)arg);
309       }
310
311       // Allow mapping of String to org.jboss.axis.types.Language
312
if (arg instanceof org.jboss.axis.types.Language && destClass == String JavaDoc.class)
313          return arg.toString();
314       if (arg instanceof String JavaDoc && destClass == org.jboss.axis.types.Language.class)
315          return new org.jboss.axis.types.Language((String JavaDoc)arg);
316
317       // Allow mapping of String to org.jboss.axis.types.Token
318
if (arg instanceof org.jboss.axis.types.Token && destClass == String JavaDoc.class)
319          return arg.toString();
320       if (arg instanceof String JavaDoc && destClass == org.jboss.axis.types.Token.class)
321          return new org.jboss.axis.types.Token((String JavaDoc)arg);
322
323       // Do fuzzy bean conversion arg -> wrapperBean(dest)
324
if (arg != null && isBeanCompatible(destClass))
325       {
326          try
327          {
328             Constructor JavaDoc ctor = getConstructorForClass(destClass, arg.getClass());
329             Object JavaDoc ctorArg = convert(arg, ctor.getParameterTypes()[0]);
330             return ctor.newInstance(new Object JavaDoc[]{ctorArg});
331          }
332          catch (Exception JavaDoc ignore)
333          {
334             // ignore
335
}
336       }
337       // Do fuzzy bean conversion wrapperBean -> dest
338
if (arg != null && isBeanCompatible(arg.getClass()))
339       {
340          try
341          {
342             Method JavaDoc getter = getAccessorForClass(arg.getClass(), destClass);
343             return getter.invoke(arg, null);
344          }
345          catch (Exception JavaDoc ignore)
346          {
347             // ignore
348
}
349       }
350
351       // Convert an AttachmentPart to the given destination class.
352
if (isAttachmentSupported() &&
353               (arg instanceof InputStream JavaDoc || arg instanceof AttachmentPartImpl || arg instanceof DataHandler JavaDoc))
354       {
355          try
356          {
357             String JavaDoc destName = destClass.getName();
358             if (destClass == String JavaDoc.class
359                     || destClass == OctetStream.class
360                     || destClass == byte[].class
361                     || destClass == Image.class
362                     || destClass == Source JavaDoc.class
363                     || destClass == DataHandler JavaDoc.class
364                     || destName.equals("javax.mail.internet.MimeMultipart"))
365             {
366                DataHandler JavaDoc handler = null;
367                if (arg instanceof AttachmentPartImpl)
368                {
369                   handler = ((AttachmentPartImpl)arg).getDataHandler();
370                }
371                else if (arg instanceof DataHandler JavaDoc)
372                {
373                   handler = (DataHandler JavaDoc)arg;
374                }
375                if (destClass == Image.class)
376                {
377                   // Note: An ImageIO component is required to process an Image
378
// attachment, but if the image would be null
379
// (is.available == 0) then ImageIO component isn't needed
380
// and we can return null.
381
InputStream JavaDoc is = (InputStream JavaDoc)handler.getContent();
382                   if (is.available() == 0)
383                   {
384                      return null;
385                   }
386                   else
387                   {
388                      ImageIO imageIO = ImageIOFactory.getImageIO();
389                      if (imageIO != null)
390                      {
391                         return getImageFromStream(is);
392                      }
393                      else
394                      {
395                         log.info(Messages.getMessage("needImageIO"));
396                         return arg;
397                      }
398                   }
399                }
400                else if (destClass == Source JavaDoc.class)
401                {
402                   // For a reason unknown to me, the handler's
403
// content is a String. Convert it to a
404
// StreamSource.
405
return new StreamSource JavaDoc(new StringReader JavaDoc((String JavaDoc)handler.getContent()));
406                }
407                else if ((arg instanceof InputStream JavaDoc) && (destClass == OctetStream.class || destClass == byte[].class))
408                {
409                   InputStream JavaDoc in = (InputStream JavaDoc)arg;
410                   ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
411                   int byte1 = -1;
412                   while ((byte1 = in.read()) != -1)
413                      baos.write(byte1);
414                   return new OctetStream(baos.toByteArray());
415                }
416                else if (destClass == DataHandler JavaDoc.class)
417                {
418                   return handler;
419                }
420                else
421                {
422                   return handler.getContent();
423                }
424             }
425          }
426          catch (IOException JavaDoc ioe)
427          {
428          }
429          catch (SOAPException JavaDoc se)
430          {
431          }
432       }
433
434       // If the destination is an array and the source
435
// is a suitable component, return an array with
436
// the single item.
437
if (arg != null &&
438               destClass.isArray() &&
439               !destClass.getComponentType().equals(Object JavaDoc.class) &&
440               !destClass.getComponentType().isArray() &&
441               destClass.getComponentType().isAssignableFrom(arg.getClass()))
442       {
443          Object JavaDoc array =
444                  Array.newInstance(destClass.getComponentType(), 1);
445          Array.set(array, 0, arg);
446          return array;
447       }
448
449       // Return if no conversion is available
450
if (!(arg instanceof Collection JavaDoc ||
451               (arg != null && arg.getClass().isArray())) &&
452               ((destHeldType == null && argHeldType == null) ||
453               (destHeldType != null && argHeldType != null)))
454       {
455          return arg;
456       }
457
458       // Take care of Holder conversion
459
if (destHeldType != null)
460       {
461          // Convert arg into Holder holding arg.
462
Object JavaDoc newArg = convert(arg, destHeldType);
463          Object JavaDoc argHolder = null;
464          try
465          {
466             argHolder = destClass.newInstance();
467             setHolderValue(argHolder, newArg);
468             return argHolder;
469          }
470          catch (Exception JavaDoc e)
471          {
472             return arg;
473          }
474       }
475       else if (argHeldType != null)
476       {
477          // Convert arg into the held type
478
try
479          {
480             Object JavaDoc newArg = getHolderValue(arg);
481             return convert(newArg, destClass);
482          }
483          catch (HolderException e)
484          {
485             return arg;
486          }
487       }
488
489       // Flow to here indicates that neither arg or destClass is a Holder
490

491       // Check to see if the argument has a prefered destination class.
492
if (arg instanceof ConvertCache &&
493               ((ConvertCache)arg).getDestClass() != destClass)
494       {
495          Class JavaDoc hintClass = ((ConvertCache)arg).getDestClass();
496          if (hintClass != null &&
497                  hintClass.isArray() &&
498                  destClass.isArray() &&
499                  destClass.isAssignableFrom(hintClass))
500          {
501             destClass = hintClass;
502             destValue = ((ConvertCache)arg).getConvertedValue(destClass);
503             if (destValue != null)
504                return destValue;
505          }
506       }
507
508       if (arg == null)
509       {
510          return arg;
511       }
512
513       // The arg may be an array or List
514
int length = 0;
515       if (arg.getClass().isArray())
516       {
517          length = Array.getLength(arg);
518       }
519       else
520       {
521          length = ((Collection JavaDoc)arg).size();
522       }
523       if (destClass.isArray())
524       {
525          Class JavaDoc componentType = destClass.getComponentType();
526          if (componentType.isPrimitive())
527          {
528
529             Object JavaDoc array = Array.newInstance(componentType, length);
530             // Assign array elements
531
if (arg.getClass().isArray())
532             {
533                for (int i = 0; i < length; i++)
534                {
535                   Object JavaDoc srcObj = Array.get(arg, i);
536                   Object JavaDoc valObj = convert(srcObj, componentType);
537                   Array.set(array, i, valObj);
538                }
539             }
540             else
541             {
542                int idx = 0;
543                for (Iterator JavaDoc i = ((Collection JavaDoc)arg).iterator();
544                     i.hasNext();)
545                {
546                   Array.set(array, idx++, i.next());
547                }
548             }
549             destValue = array;
550
551          }
552          else
553          {
554             Object JavaDoc[] array;
555             try
556             {
557                array = (Object JavaDoc[])Array.newInstance(destClass.getComponentType(),
558                        length);
559             }
560             catch (Exception JavaDoc e)
561             {
562                return arg;
563             }
564
565             // Use convert to assign array elements.
566
if (arg.getClass().isArray())
567             {
568                for (int i = 0; i < length; i++)
569                {
570                   array[i] = convert(Array.get(arg, i),
571                           destClass.getComponentType());
572                }
573             }
574             else
575             {
576                int idx = 0;
577                for (Iterator JavaDoc i = ((Collection JavaDoc)arg).iterator();
578                     i.hasNext();)
579                {
580                   array[idx++] = convert(i.next(),
581                           destClass.getComponentType());
582                }
583             }
584             destValue = array;
585          }
586       }
587       else if (Collection JavaDoc.class.isAssignableFrom(destClass))
588       {
589          Collection JavaDoc newList = null;
590          try
591          {
592             // if we are trying to create an interface, build something
593
// that implements the interface
594
if (destClass == Collection JavaDoc.class || destClass == List JavaDoc.class)
595             {
596                newList = new ArrayList JavaDoc();
597             }
598             else if (destClass == Set JavaDoc.class)
599             {
600                newList = new HashSet JavaDoc();
601             }
602             else
603             {
604                newList = (Collection JavaDoc)destClass.newInstance();
605             }
606          }
607          catch (Exception JavaDoc e)
608          {
609             // Couldn't build one for some reason... so forget it.
610
return arg;
611          }
612
613          if (arg.getClass().isArray())
614          {
615             for (int j = 0; j < length; j++)
616             {
617                newList.add(Array.get(arg, j));
618             }
619          }
620          else
621          {
622             for (Iterator JavaDoc j = ((Collection JavaDoc)arg).iterator();
623                  j.hasNext();)
624             {
625                newList.add(j.next());
626             }
627          }
628          destValue = newList;
629       }
630       else
631       {
632          destValue = arg;
633       }
634
635       // Store the converted value in the argument if possible.
636
if (arg instanceof ConvertCache)
637       {
638          ((ConvertCache)arg).setConvertedValue(destClass, destValue);
639       }
640       return destValue;
641    }
642
643    public static boolean isConvertable(Object JavaDoc obj, Class JavaDoc dest)
644    {
645       return isConvertable(obj, dest, false);
646    }
647
648    public static boolean isConvertable(Object JavaDoc obj, Class JavaDoc dest, boolean isEncoded)
649    {
650       Class JavaDoc src = null;
651
652       if (obj != null)
653       {
654          if (obj instanceof Class JavaDoc)
655          {
656             src = (Class JavaDoc)obj;
657          }
658          else
659          {
660             src = obj.getClass();
661          }
662       }
663       else
664       {
665          if (!dest.isPrimitive())
666             return true;
667       }
668
669       if (dest == null)
670          return false;
671
672       if (src != null)
673       {
674          // If we're directly assignable, we're good.
675
if (dest.isAssignableFrom(src))
676             return true;
677
678          assertClassLoaders(src, dest);
679
680          if (src.getName().equals(dest.getName()))
681          {
682             log.error("Conflicting classloaders detected: [src=" + src.getClassLoader() + ",dest=" + dest.getClassLoader() + "]");
683             return false;
684          }
685
686          //Allow mapping of Map's to Map's
687
if (java.util.Map JavaDoc.class.isAssignableFrom(dest) &&
688                  java.util.Map JavaDoc.class.isAssignableFrom(src))
689          {
690             return true;
691          }
692
693          // If it's a wrapping conversion, we're good.
694
if (getWrapperClass(src) == dest)
695             return true;
696          if (getWrapperClass(dest) == src)
697             return true;
698
699          // If it's List -> Array or vice versa, we're good.
700
if ((Collection JavaDoc.class.isAssignableFrom(src) || src.isArray()) &&
701                  (Collection JavaDoc.class.isAssignableFrom(dest) || dest.isArray()) &&
702                  (src.getComponentType() == Object JavaDoc.class ||
703                  src.getComponentType() == null ||
704                  dest.getComponentType() == Object JavaDoc.class ||
705                  dest.getComponentType() == null ||
706                  isConvertable(src.getComponentType(), dest.getComponentType())))
707             return true;
708
709          // If destination is an array, and src is a component, we're good
710
// if we're not encoded!
711
if (!isEncoded && dest.isArray() &&
712                  !dest.getComponentType().equals(Object JavaDoc.class) &&
713                  dest.getComponentType().isAssignableFrom(src))
714             return true;
715
716          if (src == HexBinary.class && dest == byte[].class)
717             return true;
718          if (src == byte[].class && dest == HexBinary.class)
719             return true;
720          if (src == HexBinary.class && dest == Byte JavaDoc[].class)
721             return true;
722