KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis.utils;
18
19 import org.apache.axis.attachments.AttachmentPart;
20 import org.apache.axis.attachments.OctetStream;
21 import org.apache.axis.components.image.ImageIO;
22 import org.apache.axis.components.image.ImageIOFactory;
23 import org.apache.axis.components.logger.LogFactory;
24 import org.apache.axis.types.HexBinary;
25 import org.apache.commons.logging.Log;
26
27 import javax.activation.DataHandler JavaDoc;
28 import javax.xml.soap.SOAPException JavaDoc;
29 import javax.xml.transform.Source JavaDoc;
30 import javax.xml.transform.stream.StreamSource JavaDoc;
31 import java.awt.*;
32 import java.beans.Introspector JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.io.InputStream JavaDoc;
35 import java.io.StringReader JavaDoc;
36 import java.io.ByteArrayOutputStream JavaDoc;
37 import java.lang.reflect.Array JavaDoc;
38 import java.lang.reflect.Field JavaDoc;
39 import java.text.Collator JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Arrays JavaDoc;
42 import java.util.Calendar JavaDoc;
43 import java.util.Collection JavaDoc;
44 import java.util.Date JavaDoc;
45 import java.util.HashMap JavaDoc;
46 import java.util.HashSet JavaDoc;
47 import java.util.Hashtable JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50 import java.util.Locale JavaDoc;
51 import java.util.Set JavaDoc;
52
53 /** Utility class to deal with Java language related issues, such
54  * as type conversions.
55  *
56  * @author Glen Daniels (gdaniels@apache.org)
57  */

58 public class JavaUtils
59 {
60     private JavaUtils() {
61     }
62
63     protected static Log log =
64         LogFactory.getLog(JavaUtils.class.getName());
65     
66     public static final char NL = '\n';
67
68     public static final char CR = '\r';
69
70     /**
71      * The prefered line separator
72      */

73     public static final String JavaDoc LS = System.getProperty("line.separator",
74                                                        (new Character JavaDoc(NL)).toString());
75
76
77     public static Class JavaDoc getWrapperClass(Class JavaDoc primitive)
78     {
79         if (primitive == int.class)
80             return java.lang.Integer JavaDoc.class;
81         else if (primitive == short.class)
82             return java.lang.Short JavaDoc.class;
83         else if (primitive == boolean.class)
84             return java.lang.Boolean JavaDoc.class;
85         else if (primitive == byte.class)
86             return java.lang.Byte JavaDoc.class;
87         else if (primitive == long.class)
88             return java.lang.Long JavaDoc.class;
89         else if (primitive == double.class)
90             return java.lang.Double JavaDoc.class;
91         else if (primitive == float.class)
92             return java.lang.Float JavaDoc.class;
93         else if (primitive == char.class)
94             return java.lang.Character JavaDoc.class;
95         
96         return null;
97     }
98     
99     public static String JavaDoc getWrapper(String JavaDoc primitive)
100     {
101         if (primitive.equals("int"))
102             return "Integer";
103         else if (primitive.equals("short"))
104             return "Short";
105         else if (primitive.equals("boolean"))
106             return "Boolean";
107         else if (primitive.equals("byte"))
108             return "Byte";
109         else if (primitive.equals("long"))
110             return "Long";
111         else if (primitive.equals("double"))
112             return "Double";
113         else if (primitive.equals("float"))
114             return "Float";
115         else if (primitive.equals("char"))
116             return "Character";
117         
118         return null;
119     }
120
121     public static Class JavaDoc getPrimitiveClass(Class JavaDoc wrapper)
122     {
123         if (wrapper == java.lang.Integer JavaDoc.class)
124             return int.class;
125         else if (wrapper == java.lang.Short JavaDoc.class)
126             return short.class;
127         else if (wrapper == java.lang.Boolean JavaDoc.class)
128             return boolean.class;
129         else if (wrapper == java.lang.Byte JavaDoc.class)
130             return byte.class;
131         else if (wrapper == java.lang.Long JavaDoc.class)
132             return long.class;
133         else if (wrapper == java.lang.Double JavaDoc.class)
134             return double.class;
135         else if (wrapper == java.lang.Float JavaDoc.class)
136             return float.class;
137         else if (wrapper == java.lang.Character JavaDoc.class)
138             return char.class;
139         
140         return null;
141     }
142
143     /*
144          * Any builtin type that has a constructor that takes a String is a basic
145          * type.
146          * This is for optimization purposes, so that we don't introspect
147          * primitive java types or some basic Axis types.
148          */

149     public static boolean isBasic(Class JavaDoc javaType) {
150         return (javaType.isPrimitive() ||
151                 javaType == String JavaDoc.class ||
152                 javaType == Boolean JavaDoc.class ||
153                 javaType == Float JavaDoc.class ||
154                 javaType == Double JavaDoc.class ||
155                 Number JavaDoc.class.isAssignableFrom(javaType) ||
156                 javaType == org.apache.axis.types.Day.class ||
157                 javaType == org.apache.axis.types.Duration.class ||
158                 javaType == org.apache.axis.types.Entities.class ||
159                 javaType == org.apache.axis.types.Entity.class ||
160                 javaType == HexBinary.class ||
161                 javaType == org.apache.axis.types.Id.class ||
162                 javaType == org.apache.axis.types.IDRef.class ||
163                 javaType == org.apache.axis.types.IDRefs.class ||
164                 javaType == org.apache.axis.types.Language.class ||
165                 javaType == org.apache.axis.types.Month.class ||
166                 javaType == org.apache.axis.types.MonthDay.class ||
167                 javaType == org.apache.axis.types.Name.class ||
168                 javaType == org.apache.axis.types.NCName.class ||
169                 javaType == org.apache.axis.types.NegativeInteger.class ||
170                 javaType == org.apache.axis.types.NMToken.class ||
171                 javaType == org.apache.axis.types.NMTokens.class ||
172                 javaType == org.apache.axis.types.NonNegativeInteger.class ||
173                 javaType == org.apache.axis.types.NonPositiveInteger.class ||
174                 javaType == org.apache.axis.types.NormalizedString.class ||
175                 javaType == org.apache.axis.types.PositiveInteger.class ||
176                 javaType == org.apache.axis.types.Time.class ||
177                 javaType == org.apache.axis.types.Token.class ||
178                 javaType == org.apache.axis.types.UnsignedByte.class ||
179                 javaType == org.apache.axis.types.UnsignedInt.class ||
180                 javaType == org.apache.axis.types.UnsignedLong.class ||
181                 javaType == org.apache.axis.types.UnsignedShort.class ||
182                 javaType == org.apache.axis.types.URI.class ||
183                 javaType == org.apache.axis.types.Year.class ||
184                 javaType == org.apache.axis.types.YearMonth.class);
185     }
186
187     /**
188      * It the argument to the convert(...) method implements
189      * the ConvertCache interface, the convert(...) method
190      * will use the set/get methods to store and retrieve
191      * converted values.
192      **/

193     public interface ConvertCache {
194         /**
195          * Set/Get converted values of the convert method.
196          **/

197         public void setConvertedValue(Class JavaDoc cls, Object JavaDoc value);
198         public Object JavaDoc getConvertedValue(Class JavaDoc cls);
199         /**
200          * Get the destination array class described by the xml
201          **/

202         public Class JavaDoc getDestClass();
203     }
204
205     /** Utility function to convert an Object to some desired Class.
206      *
207      * Right now this works for:
208      * arrays <-> Lists,
209      * Holders <-> held values
210      * @param arg the array to convert
211      * @param destClass the actual class we want
212      */

213     public static Object JavaDoc convert(Object JavaDoc arg, Class JavaDoc destClass)
214     {
215         if (destClass == null) {
216             return arg;
217         }
218
219         Class JavaDoc argHeldType = null;
220         if (arg != null) {
221             argHeldType = getHolderValueType(arg.getClass());
222         }
223
224         if (arg != null && argHeldType == null && destClass.isAssignableFrom(arg.getClass())) {
225             return arg;
226         }
227
228         if (log.isDebugEnabled()) {
229             String JavaDoc clsName = "null";
230             if (arg != null) clsName = arg.getClass().getName();
231             log.debug( Messages.getMessage("convert00", clsName, destClass.getName()));
232         }
233
234         // See if a previously converted value is stored in the argument.
235
Object JavaDoc destValue = null;
236         if (arg instanceof ConvertCache) {
237             destValue = (( ConvertCache) arg).getConvertedValue(destClass);
238             if (destValue != null)
239                 return destValue;
240         }
241
242         // Get the destination held type or the argument held type if they exist
243
Class JavaDoc destHeldType = getHolderValueType(destClass);
244
245         // Convert between Axis special purpose HexBinary and byte[]
246
if (arg instanceof HexBinary &&
247             destClass == byte[].class) {
248             return ((HexBinary) arg).getBytes();
249         } else if (arg instanceof byte[] &&
250                    destClass == HexBinary.class) {
251             return new HexBinary((byte[]) arg);
252         }
253
254         // Convert between Calendar and Date
255
if (arg instanceof Calendar JavaDoc && destClass == Date JavaDoc.class) {
256             return ((Calendar JavaDoc) arg).getTime();
257         }
258         if (arg instanceof Date JavaDoc && destClass == Calendar JavaDoc.class) {
259             Calendar JavaDoc calendar = Calendar.getInstance();
260             calendar.setTime((Date JavaDoc) arg);
261             return calendar;
262         }
263
264         // Convert between Calendar and java.sql.Date
265
if (arg instanceof Calendar JavaDoc && destClass == java.sql.Date JavaDoc.class) {
266             return new java.sql.Date JavaDoc(((Calendar JavaDoc) arg).getTime().getTime());
267         }
268
269         // Convert between HashMap and Hashtable
270
if (arg instanceof HashMap JavaDoc && destClass == Hashtable JavaDoc.class) {
271             return new Hashtable JavaDoc((HashMap JavaDoc)arg);
272         }
273
274         // Convert an AttachmentPart to the given destination class.
275
if (isAttachmentSupported() &&
276                 (arg instanceof InputStream JavaDoc || arg instanceof AttachmentPart || arg instanceof DataHandler JavaDoc)) {
277             try {
278                 String JavaDoc destName = destClass.getName();
279                 if (destClass == String JavaDoc.class
280                         || destClass == OctetStream.class
281                         || destClass == byte[].class
282                         || destClass == Image.class
283                         || destClass == Source JavaDoc.class
284                         || destClass == DataHandler JavaDoc.class
285                         || destName.equals("javax.mail.internet.MimeMultipart")) {
286                     DataHandler JavaDoc handler = null;
287                     if (arg instanceof AttachmentPart) {
288                         handler = ((AttachmentPart) arg).getDataHandler();
289                     }
290                     else if (arg instanceof DataHandler JavaDoc) {
291                         handler = (DataHandler JavaDoc) arg;
292                     }
293                     if (destClass == Image.class) {
294                         // Note: An ImageIO component is required to process an Image
295
// attachment, but if the image would be null
296
// (is.available == 0) then ImageIO component isn't needed
297
// and we can return null.
298
InputStream JavaDoc is = (InputStream JavaDoc) handler.getContent();
299                         if (is.available() == 0) {
300                             return null;
301                         }
302                         else {
303                             ImageIO imageIO = ImageIOFactory.getImageIO();
304                             if (imageIO != null) {
305                                 return getImageFromStream(is);
306                             }
307                             else {
308                                 log.info(Messages.getMessage("needImageIO"));
309                                 return arg;
310                             }
311                         }
312                     }
313                     else if (destClass == javax.xml.transform.Source JavaDoc.class) {
314                         // For a reason unknown to me, the handler's
315
// content is a String. Convert it to a
316
// StreamSource.
317
return new StreamSource JavaDoc(new StringReader JavaDoc(
318                                 (String JavaDoc) handler.getContent()));
319                     }
320                     else if (destClass == OctetStream.class || destClass == byte[].class) {
321                         InputStream JavaDoc in = null;
322                         if (arg instanceof InputStream JavaDoc) {
323                             in = (InputStream JavaDoc) arg;
324                         } else {
325                             in = (InputStream JavaDoc)handler.getContent();
326                         }
327                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
328                         int byte1 = -1;
329                         while((byte1 = in.read())!=-1)
330                             baos.write(byte1);
331                         return new OctetStream(baos.toByteArray());
332                     }
333                     else if (destClass == DataHandler JavaDoc.class) {
334                         return handler;
335                     }
336                     else {
337                         return handler.getContent();
338                     }
339                 }
340             }
341             catch (IOException JavaDoc ioe) {
342             }
343             catch (SOAPException JavaDoc se) {
344             }
345         }
346
347         // If the destination is an array and the source
348
// is a suitable component, return an array with
349
// the single item.
350
if (arg != null &&
351             destClass.isArray() &&
352             !destClass.getComponentType().equals(Object JavaDoc.class) &&
353             destClass.getComponentType().isAssignableFrom(arg.getClass())) {
354             Object JavaDoc array =
355                 Array.newInstance(destClass.getComponentType(), 1);
356             Array.set(array, 0, arg);
357             return array;
358         }
359
360         // in case destClass is array and arg is ArrayOfT class. (ArrayOfT -> T[])
361
if (arg != null && destClass.isArray()) {
362             Object JavaDoc newArg = ArrayUtil.convertObjectToArray(arg, destClass);
363             if (newArg == null
364                     || (newArg != ArrayUtil.NON_CONVERTABLE && newArg != arg)) {
365                 return newArg;
366             }
367         }
368                
369         // in case arg is ArrayOfT and destClass is an array. (T[] -> ArrayOfT)
370
if (arg != null && arg.getClass().isArray()) {
371             Object JavaDoc newArg = ArrayUtil.convertArrayToObject(arg, destClass);
372             if (newArg != null)
373                 return newArg;
374         }
375
376         // Return if no conversion is available
377
if (!(arg instanceof Collection JavaDoc ||
378               (arg != null && arg.getClass().isArray())) &&
379             ((destHeldType == null && argHeldType == null) ||
380              (destHeldType != null && argHeldType != null))) {
381             return arg;
382         }
383
384         // Take care of Holder conversion
385
if (destHeldType != null) {
386             // Convert arg into Holder holding arg.
387
Object JavaDoc newArg = convert(arg, destHeldType);
388             Object JavaDoc argHolder = null;
389             try {
390                 argHolder = destClass.newInstance();
391                 setHolderValue(argHolder, newArg);
392                 return argHolder;
393             } catch (Exception JavaDoc e) {
394                 return arg;
395             }
396         } else if (argHeldType != null) {
397             // Convert arg into the held type
398
try {
399                 Object JavaDoc newArg = getHolderValue(arg);
400                 return convert(newArg, destClass);
401             } catch (HolderException e) {
402                 return arg;
403             }
404         }
405
406         // Flow to here indicates that neither arg or destClass is a Holder
407

408         // Check to see if the argument has a prefered destination class.
409
if (arg instanceof ConvertCache &&
410             (( ConvertCache) arg).getDestClass() != destClass) {
411             Class JavaDoc hintClass = ((ConvertCache) arg).getDestClass();
412             if (hintClass != null &&
413                 hintClass.isArray() &&
414                 destClass.isArray() &&
415                 destClass.isAssignableFrom(hintClass)) {
416                 destClass = hintClass;
417                 destValue = ((ConvertCache) arg).getConvertedValue(destClass);
418                 if (destValue != null)
419                     return destValue;
420             }
421         }
422         
423         if (arg == null) {
424             return arg;
425         }
426
427         // The arg may be an array or List
428
int length = 0;
429         if (arg.getClass().isArray()) {
430             length = Array.getLength(arg);
431         } else {
432             length = ((Collection JavaDoc) arg).size();
433         }
434         if (destClass.isArray()) {
435             if (destClass.getComponentType().isPrimitive()) {
436
437                 Object JavaDoc array = Array.newInstance(destClass.getComponentType(),
438                                                  length);
439                 // Assign array elements
440
if (arg.getClass().isArray()) {
441                     for (int i = 0; i < length; i++) {
442                         Array.set(array, i, Array.get(arg, i));
443                     }
444                 } else {
445                     int idx = 0;
446                     for (Iterator JavaDoc i = ((Collection JavaDoc)arg).iterator();
447                             i.hasNext();) {
448                         Array.set(array, idx++, i.next());
449                     }
450                 }
451                 destValue = array;
452
453             } else {
454                 Object JavaDoc [] array;
455                 try {
456                     array = (Object JavaDoc [])Array.newInstance(destClass.getComponentType(),
457                                                          length);
458                 } catch (Exception JavaDoc e) {
459                     return arg;
460                 }
461
462                 // Use convert to assign array elements.
463
if (arg.getClass().isArray()) {
464                     for (int i = 0; i < length; i++) {
465                         array[i] = convert(Array.get(arg, i),
466                                            destClass.getComponentType());
467                     }
468                 } else {
469                     int idx = 0;
470                     for (Iterator JavaDoc i = ((Collection JavaDoc)arg).iterator();
471                             i.hasNext();) {
472                         array[idx++] = convert(i.next(),
473                                            destClass.getComponentType());
474                     }
475                 }
476                 destValue = array;
477             }
478         }
479         else if (Collection JavaDoc.class.isAssignableFrom(destClass)) {
480             Collection JavaDoc newList = null;
481             try {
482                 // if we are trying to create an interface, build something
483
// that implements the interface
484
if (destClass == Collection JavaDoc.class || destClass == List JavaDoc.class) {
485                     newList = new ArrayList JavaDoc();
486                 } else if (destClass == Set JavaDoc.class) {
487                     newList = new HashSet JavaDoc();
488                 } else {
489                     newList = (Collection JavaDoc)destClass.newInstance();
490                 }
491             } catch (Exception JavaDoc e) {
492                 // Couldn't build one for some reason... so forget it.
493
return arg;
494             }
495
496             if (arg.getClass().isArray()) {
497                 for (int j = 0; j < length; j++) {
498                     newList.add(Array.get(arg, j));
499                 }
500             } else {
501                 for (Iterator JavaDoc j = ((Collection JavaDoc)arg).iterator();
502                             j.hasNext();) {
503                     newList.add(j.next());
504                 }
505             }
506             destValue = newList;
507         }
508         else {
509             destValue = arg;
510         }
511
512         // Store the converted value in the argument if possible.
513
if (arg instanceof ConvertCache) {
514             (( ConvertCache) arg).setConvertedValue(destClass, destValue);
515         }
516         return destValue;
517     }
518
519     public static boolean isConvertable(Object JavaDoc obj, Class JavaDoc dest)
520     {
521         return isConvertable(obj, dest, false);
522     }
523
524     public static boolean isConvertable(Object JavaDoc obj, Class JavaDoc dest, boolean isEncoded)
525     {
526         Class JavaDoc src = null;
527         
528         if (obj != null) {
529             if (obj instanceof Class JavaDoc) {
530                 src = (Class JavaDoc)obj;
531             } else {
532                 src = obj.getClass();
533             }
534         } else {
535             if(!dest.isPrimitive())
536                 return true;
537         }
538         
539         if (dest == null)
540             return false;
541         
542         if (src != null) {
543             // If we're directly assignable, we're good.
544
if (dest.isAssignableFrom(src))
545                 return true;
546
547             //Allow mapping of Map's to Map's
548
if (java.util.Map JavaDoc.class.isAssignableFrom(dest) &&
549                 java.util.Map JavaDoc.class.isAssignableFrom(src)) {
550                   return true;
551             }
552
553             // If it's a wrapping conversion, we're good.
554
if (getWrapperClass(src) == dest)
555                 return true;
556             if (getWrapperClass(dest) == src)
557                 return true;
558             
559             // If it's List -> Array or vice versa, we're good.
560
if ((Collection JavaDoc.class.isAssignableFrom(src) || src.isArray()) &&
561                 (Collection JavaDoc.class.isAssignableFrom(dest) || dest.isArray()) &&
562                 (src.getComponentType() == Object JavaDoc.class ||
563                  src.getComponentType() == null ||
564                  dest.getComponentType() == Object JavaDoc.class ||
565                  dest.getComponentType() == null ||
566                  isConvertable(src.getComponentType(), dest.getComponentType())))
567                     return true;
568             
569             // If destination is an array, and src is a component, we're good
570
// if we're not encoded!
571
if (!isEncoded && dest.isArray() &&
572 // !dest.getComponentType().equals(Object.class) &&
573
dest.getComponentType().isAssignableFrom(src))
574                 return true;
575
576             if ((src == HexBinary.class && dest == byte[].class) ||
577                 (src == byte[].class && dest == HexBinary.class))
578                 return true;
579             
580             // Allow mapping of Calendar to Date
581
if (Calendar JavaDoc.class.isAssignableFrom(src) && dest == Date JavaDoc.class)
582                 return true;
583
584             // Allow mapping of Date to Calendar
585
if (Date JavaDoc.class.isAssignableFrom(src) && dest == Calendar JavaDoc.class)
586                 return true;
587
588             // Allow mapping of Calendar to java.sql.Date
589
if (Calendar JavaDoc.class.isAssignableFrom(src) && dest == java.sql.Date JavaDoc.class)
590                 return true;
591         }
592         
593         Class JavaDoc destHeld = JavaUtils.getHolderValueType(dest);
594         // Can always convert a null to an empty holder
595
if (src == null)
596             return (destHeld != null);
597         
598         if (destHeld != null) {
599             if (destHeld.isAssignableFrom(src) || isConvertable(src, destHeld))
600                 return true;
601         }
602
603         // If it's holder -> held or held -> holder, we're good
604
Class JavaDoc srcHeld = JavaUtils.getHolderValueType(src);
605         if (srcHeld != null) {
606             if (dest.isAssignableFrom(srcHeld) || isConvertable(srcHeld, dest))
607                 return true;
608         }
609
610         // If it's a MIME type mapping and we want a DataHandler,
611
// then we're good.
612
if (dest.getName().equals("javax.activation.DataHandler")) {
613             String JavaDoc name = src.getName();
614             if (src == String JavaDoc.class
615                     || src == java.awt.Image JavaDoc.class
616                     || src == OctetStream.class
617