| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.axis.utils; |
| |
| import org.apache.axis.attachments.AttachmentPart; |
| import org.apache.axis.attachments.OctetStream; |
| import org.apache.axis.components.logger.LogFactory; |
| import org.apache.axis.types.HexBinary; |
| import org.apache.commons.logging.Log; |
| |
| import javax.activation.DataHandler; |
| import javax.imageio.ImageIO; |
| import javax.xml.soap.SOAPException; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.stream.StreamSource; |
| import java.awt.*; |
| import java.beans.Introspector; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.lang.reflect.Array; |
| import java.lang.reflect.Field; |
| import java.text.Collator; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Calendar; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.WeakHashMap; |
| import java.util.HashSet; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Set; |
| |
| /** Utility class to deal with Java language related issues, such |
| * as type conversions. |
| * |
| * @author Glen Daniels (gdaniels@apache.org) |
| */ |
| public class JavaUtils |
| { |
| private JavaUtils() { |
| } |
| |
| protected static Log log = |
| LogFactory.getLog(JavaUtils.class.getName()); |
| |
| public static final char NL = '\n'; |
| |
| public static final char CR = '\r'; |
| |
| /** |
| * The prefered line separator |
| */ |
| public static final String LS = System.getProperty("line.separator", |
| (new Character(NL)).toString()); |
| |
| |
| public static Class getWrapperClass(Class primitive) |
| { |
| if (primitive == int.class) |
| return java.lang.Integer.class; |
| else if (primitive == short.class) |
| return java.lang.Short.class; |
| else if (primitive == boolean.class) |
| return java.lang.Boolean.class; |
| else if (primitive == byte.class) |
| return java.lang.Byte.class; |
| else if (primitive == long.class) |
| return java.lang.Long.class; |
| else if (primitive == double.class) |
| return java.lang.Double.class; |
| else if (primitive == float.class) |
| return java.lang.Float.class; |
| else if (primitive == char.class) |
| return java.lang.Character.class; |
| |
| return null; |
| } |
| |
| public static String getWrapper(String primitive) |
| { |
| if (primitive.equals("int")) |
| return "Integer"; |
| else if (primitive.equals("short")) |
| return "Short"; |
| else if (primitive.equals("boolean")) |
| return "Boolean"; |
| else if (primitive.equals("byte")) |
| return "Byte"; |
| else if (primitive.equals("long")) |
| return "Long"; |
| else if (primitive.equals("double")) |
| return "Double"; |
| else if (primitive.equals("float")) |
| return "Float"; |
| else if (primitive.equals("char")) |
| return "Character"; |
| |
| return null; |
| } |
| |
| public static Class getPrimitiveClass(Class wrapper) |
| { |
| if (wrapper == java.lang.Integer.class) |
| return int.class; |
| else if (wrapper == java.lang.Short.class) |
| return short.class; |
| else if (wrapper == java.lang.Boolean.class) |
| return boolean.class; |
| else if (wrapper == java.lang.Byte.class) |
| return byte.class; |
| else if (wrapper == java.lang.Long.class) |
| return long.class; |
| else if (wrapper == java.lang.Double.class) |
| return double.class; |
| else if (wrapper == java.lang.Float.class) |
| return float.class; |
| else if (wrapper == java.lang.Character.class) |
| return char.class; |
| |
| return null; |
| } |
| |
| public static Class getPrimitiveClassFromName(String primitive) { |
| if (primitive.equals("int")) |
| return int.class; |
| else if (primitive.equals("short")) |
| return short.class; |
| else if (primitive.equals("boolean")) |
| return boolean.class; |
| else if (primitive.equals("byte")) |
| return byte.class; |
| else if (primitive.equals("long")) |
| return long.class; |
| else if (primitive.equals("double")) |
| return double.class; |
| else if (primitive.equals("float")) |
| return float.class; |
| else if (primitive.equals("char")) |
| return char.class; |
| |
| return null; |
| } |
| |
| /* |
| * Any builtin type that has a constructor that takes a String is a basic |
| * type. |
| * This is for optimization purposes, so that we don't introspect |
| * primitive java types or some basic Axis types. |
| */ |
| public static boolean isBasic(Class javaType) { |
| return (javaType.isPrimitive() || |
| javaType == String.class || |
| javaType == Boolean.class || |
| javaType == Float.class || |
| javaType == Double.class || |
| Number.class.isAssignableFrom(javaType) || |
| javaType == org.apache.axis.types.Day.class || |
| javaType == org.apache.axis.types.Duration.class || |
| javaType == org.apache.axis.types.Entities.class || |
| javaType == org.apache.axis.types.Entity.class || |
| javaType == HexBinary.class || |
| javaType == org.apache.axis.types.Id.class || |
| javaType == org.apache.axis.types.IDRef.class || |
| javaType == org.apache.axis.types.IDRefs.class || |
| javaType == org.apache.axis.types.Language.class || |
| javaType == org.apache.axis.types.Month.class || |
| javaType == org.apache.axis.types.MonthDay.class || |
| javaType == org.apache.axis.types.Name.class || |
| javaType == org.apache.axis.types.NCName.class || |
| javaType == org.apache.axis.types.NegativeInteger.class || |
| javaType == org.apache.axis.types.NMToken.class || |
| javaType == org.apache.axis.types.NMTokens.class || |
| javaType == org.apache.axis.types.NonNegativeInteger.class || |
| javaType == org.apache.axis.types.NonPositiveInteger.class || |
| javaType == org.apache.axis.types.NormalizedString.class || |
| javaType == org.apache.axis.types.PositiveInteger.class || |
| javaType == org.apache.axis.types.Time.class || |
| javaType == org.apache.axis.types.Token.class || |
| javaType == org.apache.axis.types.UnsignedByte.class || |
| javaType == org.apache.axis.types.UnsignedInt.class || |
| javaType == org.apache.axis.types.UnsignedLong.class || |
| javaType == org.apache.axis.types.UnsignedShort.class || |
| javaType == org.apache.axis.types.URI.class || |
| javaType == org.apache.axis.types.Year.class || |
| javaType == org.apache.axis.types.YearMonth.class); |
| } |
| |
| /** |
| * It the argument to the convert(...) method implements |
| * the ConvertCache interface, the convert(...) method |
| * will use the set/get methods to store and retrieve |
| * converted values. |
| **/ |
| public interface ConvertCache { |
| /** |
| * Set/Get converted values of the convert method. |
| **/ |
| public void setConvertedValue(Class cls, Object value); |
| public Object getConvertedValue(Class cls); |
| /** |
| * Get the destination array class described by the xml |
| **/ |
| public Class getDestClass(); |
| } |
| |
| /** Utility function to convert an Object to some desired Class. |
| * |
| * Right now this works for: |
| * arrays <-> Lists, |
| * Holders <-> held values |
| * @param arg the array to convert |
| * @param destClass the actual class we want |
| */ |
| public static Object convert(Object arg, Class destClass) |
| { |
| if (destClass == null) { |
| return arg; |
| } |
| |
| Class argHeldType = null; |
| if (arg != null) { |
| argHeldType = getHolderValueType(arg.getClass()); |
| } |
| |
| if (arg != null && argHeldType == null && destClass.isAssignableFrom(arg.getClass())) { |
| return arg; |
| } |
| |
| if (log.isDebugEnabled()) { |
| String clsName = "null"; |
| if (arg != null) clsName = arg.getClass().getName(); |
| log.debug( Messages.getMessage("convert00", clsName, destClass.getName())); |
| } |
| |
| // See if a previously converted value is stored in the argument. |
| Object destValue = null; |
| if (arg instanceof ConvertCache) { |
| destValue = (( ConvertCache) arg).getConvertedValue(destClass); |
| if (destValue != null) |
| return destValue; |
| } |
| |
| // Get the destination held type or the argument held type if they exist |
| Class destHeldType = getHolderValueType(destClass); |
| |
| // Convert between Axis special purpose HexBinary and byte[] |
| if (arg instanceof HexBinary && |
| destClass == byte[].class) { |
| return ((HexBinary) arg).getBytes(); |
| } else if (arg instanceof byte[] && |
| destClass == HexBinary.class) { |
| return new HexBinary((byte[]) arg); |
| } |
| |
| // Convert between Calendar and Date |
| if (arg instanceof Calendar && destClass == Date.class) { |
| return ((Calendar) arg).getTime(); |
| } |
| if (arg instanceof Date && destClass == Calendar.class) { |
| Calendar calendar = Calendar.getInstance(); |
| calendar.setTime((Date) arg); |
| return calendar; |
| } |
| |
| // Convert between Calendar and java.sql.Date |
| if (arg instanceof Calendar && destClass == java.sql.Date.class) { |
| return new java.sql.Date(((Calendar) arg).getTime().getTime()); |
| } |
| |
| // Convert between HashMap and Hashtable |
| if (arg instanceof HashMap && destClass == Hashtable.class) { |
| return new Hashtable((HashMap)arg); |
| } |
| |
| // Convert an AttachmentPart to the given destination class. |
| if (isAttachmentSupported() && |
| (arg instanceof InputStream || arg instanceof AttachmentPart || arg instanceof DataHandler)) { |
| try { |
| String destName = destClass.getName(); |
| if (destClass == String.class |
| || destClass == OctetStream.class |
| || destClass == byte[].class |
| || destClass == Image.class |
| || destClass == Source.class |
| || destClass == DataHandler.class |
| || destName.equals("javax.mail.internet.MimeMultipart")) { |
| DataHandler handler = null; |
| if (arg instanceof AttachmentPart) { |
| handler = ((AttachmentPart) arg).getDataHandler(); |
| } |
| else if (arg instanceof DataHandler) { |
| handler = (DataHandler) arg; |
| } |
| if (destClass == Image.class) { |
| // Note: An ImageIO component is required to process an Image |
| // attachment, but if the image would be null |
| // (is.available == 0) then ImageIO component isn't needed |
| // and we can return null. |
| InputStream is = handler.getInputStream(); |
| if (is.available() == 0) { |
| return null; |
| } |
| else { |
| return ImageIO.read(is); |
| } |
| } |
| else if (destClass == javax.xml.transform.Source.class) { |
| // For a reason unknown to me, the handler's |
| // content is a String. Convert it to a |
| // StreamSource. |
| return new StreamSource(handler.getInputStream()); |
| } |
| else if (destClass == OctetStream.class || destClass == byte[].class) { |
| InputStream in = null; |
| if (arg instanceof InputStream) { |
| in = (InputStream) arg; |
| } else { |
| in = handler.getInputStream(); |
| } |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| int byte1 = -1; |
| while((byte1 = in.read())!=-1) |
| baos.write(byte1); |
| return new OctetStream(baos.toByteArray()); |
| } |
| else if (destClass == DataHandler.class) { |
| return handler; |
| } |
| else { |
| return handler.getContent(); |
| } |
| } |
| } |
| catch (IOException ioe) { |
| } |
| catch (SOAPException se) { |
| } |
| } |
| |
| // If the destination is an array and the source |
| // is a suitable component, return an array with |
| // the single item. |
| if (arg != null && |
| destClass.isArray() && |
| !destClass.getComponentType().equals(Object.class) && |
| destClass.getComponentType().isAssignableFrom(arg.getClass())) { |
| Object array = |
| Array.newInstance(destClass.getComponentType(), 1); |
| Array.set(array, 0, arg); |
| return array; |
| } |
| |
| // in case destClass is array and arg is ArrayOfT class. (ArrayOfT -> T[]) |
| if (arg != null && destClass.isArray()) { |
| Object newArg = ArrayUtil.convertObjectToArray(arg, destClass); |
| if (newArg == null |
| || (newArg != ArrayUtil.NON_CONVERTABLE && newArg != arg)) { |
| return newArg; |
| } |
| } |
| |
| // in case arg is ArrayOfT and destClass is an array. (T[] -> ArrayOfT) |
| if (arg != null && arg.getClass().isArray()) { |
| Object newArg = ArrayUtil.convertArrayToObject(arg, destClass); |
| if (newArg != null) |
| return newArg; |
| } |
| |
| // Return if no conversion is available |
| if (!(arg instanceof Collection || |
| (arg != null && arg.getClass().isArray())) && |
| ((destHeldType == null && argHeldType == null) || |
| (destHeldType != null && argHeldType != null))) { |
| return arg; |
| } |
| |
| // Take care of Holder conversion |
| if (destHeldType != null) { |
| // Convert arg into Holder holding arg. |
| Object newArg = convert(arg, destHeldType); |
| Object argHolder = null; |
| try { |
| argHolder = destClass.newInstance(); |
| setHolderValue(argHolder, newArg); |
| return argHolder; |
| } catch (Exception e) { |
| return arg; |
| } |
| } else if (argHeldType != null) { |
| // Convert arg into the held type |
| try { |
| Object newArg = getHolderValue(arg); |
| return convert(newArg, destClass); |
| } catch (HolderException e) { |
| return arg; |
| } |
| } |
| |
| // Flow to here indicates that neither arg or destClass is a Holder |
| |
| // Check to see if the argument has a prefered destination class. |
| if (arg instanceof ConvertCache && |
| (( ConvertCache) arg).getDestClass() != destClass) { |
| Class hintClass = ((ConvertCache) arg).getDestClass(); |
| if (hintClass != null && |
| hintClass.isArray() && |
| destClass.isArray() && |
| destClass.isAssignableFrom(hintClass)) { |
| destClass = hintClass; |
| destValue = ((ConvertCache) arg).getConvertedValue(destClass); |
| if (destValue != null) |
| return destValue; |
| } |
| } |
| |
| if (arg == null) { |
| return arg; |
| } |
| |
| // The arg may be an array or List |
| int length = 0; |
| if (arg.getClass().isArray()) { |
| length = Array.getLength(arg); |
| } else { |
| length = ((Collection) arg).size(); |
| } |
| if (destClass.isArray()) { |
| if (destClass.getComponentType().isPrimitive()) { |
| |
| Object array = Array.newInstance(destClass.getComponentType(), |
| length); |
| // Assign array elements |
| if (arg.getClass().isArray()) { |
| for (int i = 0; i < length; i++) { |
| Array.set(array, i, Array.get(arg, i)); |
| } |
| } else { |
| int idx = 0; |
| for (Iterator i = ((Collection)arg).iterator(); |
| i.hasNext();) { |
| Array.set(array, idx++, i.next()); |
| } |
| } |
| destValue = array; |
| |
| } else { |
| Object [] array; |
| try { |
| array = (Object [])Array.newInstance(destClass.getComponentType(), |
| length); |
| } catch (Exception e) { |
| return arg; |
| } |
| |
| // Use convert to assign array elements. |
| if (arg.getClass().isArray()) { |
| for (int i = 0; i < length; i++) { |
| array[i] = convert(Array.get(arg, i), |
| destClass.getComponentType()); |
| } |
| } else { |
| int idx = 0; |
| for (Iterator i = ((Collection)arg).iterator(); |
| i.hasNext();) { |
| array[idx++] = convert(i.next(), |
| destClass.getComponentType()); |
| } |
| } |
| destValue = array; |
| } |
| } |
| else if (Collection.class.isAssignableFrom(destClass)) { |
| Collection newList = null; |
| try { |
| // if we are trying to create an interface, build something |
| // that implements the interface |
| if (destClass == Collection.class || destClass == List.class) { |
| newList = new ArrayList(); |
| } else if (destClass == Set.class) { |
| newList = new HashSet(); |
| } else { |
| newList = (Collection)destClass.newInstance(); |
| } |
| } catch (Exception e) { |
| // Couldn't build one for some reason... so forget it. |
| return arg; |
| } |
| |
| if (arg.getClass().isArray()) { |
| for (int j = 0; j < length; j++) { |
| newList.add(Array.get(arg, j)); |
| } |
| } else { |
| for (Iterator j = ((Collection)arg).iterator(); |
| j.hasNext();) { |
| newList.add(j.next()); |
| } |
| } |
| destValue = newList; |
| } |
| else { |
| destValue = arg; |
| } |
| |
| // Store the converted value in the argument if possible. |
| if (arg instanceof ConvertCache) { |
| (( ConvertCache) arg).setConvertedValue(destClass, destValue); |
| } |
| return destValue; |
| } |
| |
| public static boolean isConvertable(Object obj, Class dest) |
| { |
| return isConvertable(obj, dest, false); |
| } |
| |
| public static boolean isConvertable(Object obj, Class dest, boolean isEncoded) |
| { |
| Class src = null; |
| |
| if (obj != null) { |
| if (obj instanceof Class) { |
| src = (Class)obj; |
| } else { |
| src = obj.getClass(); |
| } |
| } else { |
| if(!dest.isPrimitive()) |
| return true; |
| } |
| |
| if (dest == null) |
| return false; |
| |
| if (src != null) { |
| // If we're directly assignable, we're good. |
| if (dest.isAssignableFrom(src)) |
| return true; |
| |
| //Allow mapping of Map's to Map's |
| if (java.util.Map.class.isAssignableFrom(dest) && |
| java.util.Map.class.isAssignableFrom(src)) { |
| return true; |
| } |
| |
| // If it's a wrapping conversion, we're good. |
| if (getWrapperClass(src) == dest) |
| return true; |
| if (getWrapperClass(dest) == src) |
| return true; |
| |
| // If it's List -> Array or vice versa, we're good. |
| if ((Collection.class.isAssignableFrom(src) || src.isArray()) && |
| (Collection.class.isAssignableFrom(dest) || dest.isArray()) && |
| (src.getComponentType() == Object.class || |
| src.getComponentType() == null || |
| dest.getComponentType() == Object.class || |
| dest.getComponentType() == null || |
| isConvertable(src.getComponentType(), dest.getComponentType()))) |
| return true; |
| |
| // If destination is an array, and src is a component, we're good |
| // if we're not encoded! |
| if (!isEncoded && dest.isArray() && |
| // !dest.getComponentType().equals(Object.class) && |
| dest.getComponentType().isAssignableFrom(src)) |
| return true; |
| |
| if ((src == HexBinary.class && dest == byte[].class) || |
| (src == byte[].class && dest == HexBinary.class)) |
| return true; |
| |
| // Allow mapping of Calendar to Date |
| if (Calendar.class.isAssignableFrom(src) && dest == Date.class) |
| return true; |
| |
| // Allow mapping of Date to Calendar |
| if (Date.class.isAssignableFrom(src) && dest == Calendar.class) |
| return true; |
| |
| // Allow mapping of Calendar to java.sql.Date |
| if (Calendar.class.isAssignableFrom(src) && dest == java.sql.Date.class) |
| return true; |
| } |
| |
| Class destHeld = JavaUtils.getHolderValueType(dest); |
| // Can always convert a null to an empty holder |
| if (src == null) |
| return (destHeld != null); |
| |
| if (destHeld != null) { |
| if (destHeld.isAssignableFrom(src) || isConvertable(src, destHeld)) |
| return true; |
| } |
| |
| // If it's holder -> held or held -> holder, we're good |
| Class srcHeld = JavaUtils.getHolderValueType(src); |
| if (srcHeld != null) { |
| if (dest.isAssignableFrom(srcHeld) || isConvertable(srcHeld, dest)) |
| return true; |
| } |
| |
| // If it's a MIME type mapping and we want a DataHandler, |
| // then we're good. |
| if (dest.getName().equals("javax.activation.DataHandler")) { |
| String name = src.getName(); |
| if (src == String.class |
| || src == java.awt.Image.class |
| || src == OctetStream.class |
| || name.equals("javax.mail.internet.MimeMultipart") |
| || name.equals("javax.xml.transform.Source")) |
| return true; |
| } |
| |
| if (src.getName().equals("javax.activation.DataHandler")) { |
| if (dest == byte[].class) |
| return true; |
| if (dest.isArray() && dest.getComponentType() == byte[].class) |
| return true; |
| } |
| |
| if (dest.getName().equals("javax.activation.DataHandler")) { |
| if (src == Object[].class) |
| return true; |
| if (src.isArray() && src.getComponentType() == Object[].class) |
| return true; |
| } |
| |
| if (obj instanceof java.io.InputStream) { |
| if (dest == OctetStream.class) |
| return true; |
| } |
| |
| if (src.isPrimitive()) { |
| return isConvertable(getWrapperClass(src),dest); |
| } |
| |
| // ArrayOfT -> T[] ? |
| if (dest.isArray()) { |
| if (ArrayUtil.isConvertable(src, dest) == true) |
| return true; |
| } |
| |
| // T[] -> ArrayOfT ? |
| if (src.isArray()) { |
| if (ArrayUtil.isConvertable(src, dest) == true) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * @deprecated Use {@link ImageIO#read(InputStream)} instead. |
| */ |
| public static Image getImageFromStream(InputStream is) { |
| try { |
| return ImageIO.read(is); |
| } |
| catch (Throwable t) { |
| return null; |
| } |
| } // getImageFromStream |
| |
| /** |
| * These are java keywords as specified at the following URL (sorted alphabetically). |
| * http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308 |
| * Note that false, true, and null are not strictly keywords; they are literal values, |
| * but for the purposes of this array, they can be treated as literals. |
| * ****** PLEASE KEEP THIS LIST SORTED IN ASCENDING ORDER ****** |
| */ |
| static final String keywords[] = |
| { |
| "abstract", "assert", "boolean", "break", "byte", "case", |
| "catch", "char", "class", "const", "continue", |
| "default", "do", "double", "else", "extends", |
| "false", "final", "finally", "float", "for", |
| "goto", "if", "implements", "import", "instanceof", |
| "int", "interface", "long", "native", "new", |
| "null", "package", "private", "protected", "public", |
| "return", "short", "static", "strictfp", "super", |
| "switch", "synchronized", "this", "throw", "throws", |
| "transient", "true", "try", "void", "volatile", |
| "while" |
| }; |
| |
| /** Collator for comparing the strings */ |
| static final Collator englishCollator = Collator.getInstance(Locale.ENGLISH); |
| |
| /** Use this character as suffix */ |
| static final char keywordPrefix = '_'; |
| |
| /** |
| * isJavaId |
| * Returns true if the name is a valid java identifier. |
| * @param id to check |
| * @return boolean true/false |
| **/ |
| public static boolean isJavaId(String id) { |
| if (id == null || id.equals("") || isJavaKeyword(id)) |
| return false; |
| if (!Character.isJavaIdentifierStart(id.charAt(0))) |
| return false; |
| for (int i=1; i<id.length(); i++) |
| if (!Character.isJavaIdentifierPart(id.charAt(i))) |
| return false; |
| return true; |
| } |
| |
| /** |
| * checks if the input string is a valid java keyword. |
| * @return boolean true/false |
| */ |
| public static boolean isJavaKeyword(String keyword) { |
| return (Arrays.binarySearch(keywords, keyword, englishCollator) >= 0); |
| } |
| |
| /** |
| * Turn a java keyword string into a non-Java keyword string. (Right now |
| * this simply means appending an underscore.) |
| */ |
| public static String makeNonJavaKeyword(String keyword){ |
| return keywordPrefix + keyword; |
| } |
| |
| /** |
| * Converts text of the form |
| * Foo[] to the proper class name for loading [LFoo |
| */ |
| public static String getLoadableClassName(String text) { |
| if (text == null || |
| text.indexOf("[") < 0 || |
| text.charAt(0) == '[') |
| return text; |
| String className = text.substring(0,text.indexOf("[")); |
| if (className.equals("byte")) |
| className = "B"; |
| else if (className.equals("char")) |
| className = "C"; |
| else if (className.equals("double")) |
| className = "D"; |
| else if (className.equals("float")) |
| className = "F"; |
| else if (className.equals("int")) |
| className = "I"; |
| else if (className.equals("long")) |
| className = "J"; |
| else if (className.equals("short")) |
| className = "S"; |
| else if (className.equals("boolean")) |
| className = "Z"; |
| else |
| className = "L" + className + ";"; |
| int i = text.indexOf("]"); |
| while (i > 0) { |
| className = "[" + className; |
| i = text.indexOf("]", i+1); |
| } |
| return className; |
| } |
| |
| /** |
| * Converts text of the form |
| * [LFoo to the Foo[] |
| */ |
| public static String getTextClassName(String text) { |
| if (text == null || |
| text.indexOf("[") != 0) |
| return text; |
| String className = ""; |
| int index = 0; |
| while(index < text.length() && |
| text.charAt(index) == '[') { |
| index ++; |
| className += "[]"; |
| } |
| if (index < text.length()) { |
| if (text.charAt(index)== 'B') |
| className = "byte" + className; |
| else if (text.charAt(index) == 'C') |
| className = "char" + className; |
| else if (text.charAt(index) == 'D') |
| className = "double" + className; |
| else if (text.charAt(index) == 'F') |
| className = "float" + className; |
| else if (text.charAt(index) == 'I') |
| className = "int" + className; |
| else if (text.charAt(index) == 'J') |
| className = "long" + className; |
| else if (text.charAt(index) == 'S') |
| className = "short" + className; |
| else if (text.charAt(index) == 'Z') |
| className = "boolean" + className; |
| else { |
| className = text.substring(index+1, text.indexOf(";")) + className; |
| } |
| } |
| return className; |
| } |
| |
| /** |
| * Map an XML name to a Java identifier per |
| * the mapping rules of JSR 101 (in version 1.0 this is |
| * "Chapter 20: Appendix: Mapping of XML Names" |
| * |
| * @param name is the xml name |
| * @return the java name per JSR 101 specification |
| */ |
| public static String xmlNameToJava(String name) |
| { |
| // protect ourselves from garbage |
| if (name == null || name.equals("")) |
| return name; |
| |
| char[] nameArray = name.toCharArray(); |
| int nameLen = name.length(); |
| StringBuffer result = new StringBuffer(nameLen); |
| boolean wordStart = false; |
| |
| // The mapping indicates to convert first character. |
| int i = 0; |
| while (i < nameLen |
| && (isPunctuation(nameArray[i]) |
| || !Character.isJavaIdentifierStart(nameArray[i]))) { |
| i++; |
| } |
| if (i < nameLen) { |
| // Decapitalization code used to be here, but we use the |
| // Introspector function now after we filter out all bad chars. |
| |
| result.append(nameArray[i]); |
| //wordStart = !Character.isLetter(nameArray[i]); |
| wordStart = !Character.isLetter(nameArray[i]) && nameArray[i] != "_".charAt(0); |
| } |
| else { |
| // The identifier cannot be mapped strictly according to |
| // JSR 101 |
| if (Character.isJavaIdentifierPart(nameArray[0])) { |
| result.append("_" + nameArray[0]); |
| } |
| else { |
| // The XML identifier does not contain any characters |
| // we can map to Java. Using the length of the string |
| // will make it somewhat unique. |
| result.append("_" + nameArray.length); |
| } |
| } |
| |
| // The mapping indicates to skip over |
| // all characters that are not letters or |
| // digits. The first letter/digit |
| // following a skipped character is |
| // upper-cased. |
| for (++i; i < nameLen; ++i) { |
| char c = nameArray[i]; |
| |
| // if this is a bad char, skip it and remember to capitalize next |
| // good character we encounter |
| if (isPunctuation(c) || !Character.isJavaIdentifierPart(c)) { |
| wordStart = true; |
| continue; |
| } |
| if (wordStart && Character.isLowerCase(c)) { |
| result.append(Character.toUpperCase(c)); |
| } |
| else { |
| result.append(c); |
| } |
| // If c is not a character, but is a legal Java |
| // identifier character, capitalize the next character. |
| // For example: "22hi" becomes "22Hi" |
| //wordStart = !Character.isLetter(c); |
| wordStart = !Character.isLetter(c) && c != "_".charAt(0); |
| } |
| |
| // covert back to a String |
| String newName = result.toString(); |
| |
| // Follow JavaBean rules, but we need to check if the first |
| // letter is uppercase first |
| if (Character.isUpperCase(newName.charAt(0))) |
| newName = Introspector.decapitalize(newName); |
| |
| // check for Java keywords |
| if (isJavaKeyword(newName)) |
| newName = makeNonJavaKeyword(newName); |
| |
| return newName; |
| } // xmlNameToJava |
| |
| /** |
| * Is this an XML punctuation character? |
| */ |
| private static boolean isPunctuation(char c) |
| { |
| return '-' == c |
| || '.' == c |
| || ':' == c |
| || '\u00B7' == c |
| || '\u0387' == c |
| || '\u06DD' == c |
| || '\u06DE' == c; |
| } // isPunctuation |
| |
| |
| /** |
| * replace: |
| * Like String.replace except that the old new items are strings. |
| * |
| * @param name string |
| * @param oldT old text to replace |
| * @param newT new text to use |
| * @return replacement string |
| **/ |
| public static final String replace (String name, |
| String oldT, String newT) { |
| |
| if (name == null) return ""; |
| |
| // Create a string buffer that is twice initial length. |
| // This is a good starting point. |
| StringBuffer sb = new StringBuffer(name.length()* 2); |
| |
| int len = oldT.length (); |
| try { |
| int start = 0; |
| int i = name.indexOf (oldT, start); |
| |
| while (i >= 0) { |
| sb.append(name.substring(start, i)); |
| sb.append(newT); |
| start = i+len; |
| i = name.indexOf(oldT, start); |
| } |
| if (start < name.length()) |
| sb.append(name.substring(start)); |
| } catch (NullPointerException e) { |
| } |
| |
| return new String(sb); |
| } |
| |
| /** |
| * Determines if the Class is a Holder class. If so returns Class of held type |
| * else returns null |
| * @param type the suspected Holder Class |
| * @return class of held type or null |
| */ |
| public static Class getHolderValueType(Class type) { |
| if (type != null) { |
| Class[] intf = type.getInterfaces(); |
| boolean isHolder = false; |
| for (int i=0; i<intf.length && !isHolder; i++) { |
| if (intf[i] == javax.xml.rpc.holders.Holder.class) { |
| isHolder = true; |
| } |
| } |
| if (isHolder == false) { |
| return null; |
| } |
| |
| // Holder is supposed to have a public value field. |
| java.lang.reflect.Field field; |
| try { |
| field = type.getField("value"); |
| } catch (Exception e) { |
| field = null; |
| } |
| if (field != null) { |
| return field.getType(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Gets the Holder value. |
| * @param holder Holder object |
| * @return value object |
| */ |
| public static Object getHolderValue(Object holder) throws HolderException { |
| if (!(holder instanceof javax.xml.rpc.holders.Holder)) { |
| throw new HolderException(Messages.getMessage("badHolder00")); |
| } |
| try { |
| Field valueField = holder.getClass().getField("value"); |
| return valueField.get(holder); |
| } catch (Exception e) { |
| throw new HolderException(Messages.getMessage("exception01", e.getMessage())); |
| } |
| } |
| |
| /** |
| * Sets the Holder value. |
| * @param holder Holder object |
| * @param value is the object value |
| */ |
| public static void setHolderValue(Object holder, Object value) throws HolderException { |
| if (!(holder instanceof javax.xml.rpc.holders.Holder)) { |
| throw new HolderException(Messages.getMessage("badHolder00")); |
| } |
| try { |
| Field valueField = holder.getClass().getField("value"); |
| if (valueField.getType().isPrimitive()) { |
| if (value == null) |
| ; // Don't need to set anything |
| else |
| valueField.set(holder, value); // Automatically unwraps value to primitive |
| } else { |
| valueField.set(holder, value); |
| } |
| } catch (Exception e) { |
| throw new HolderException(Messages.getMessage("exception01", e.getMessage())); |
| } |
| } |
| public static class HolderException extends Exception |
| { |
| public HolderException(String msg) { super(msg); } |
| } |
| |
| |
| /** |
| * Used to cache a result from IsEnumClassSub(). |
| * Class->Boolean mapping. |
| */ |
| private static WeakHashMap enumMap = new WeakHashMap(); |
| |
| /** |
| * Determine if the class is a JAX-RPC enum class. |
| * An enumeration class is recognized by |
| * a getValue() method, a toString() method, a fromString(String) method |
| * a fromValue(type) method and the lack |
| * of a setValue(type) method |
| */ |
| public static boolean isEnumClass(Class cls) { |
| Boolean b = (Boolean)enumMap.get(cls); |
| if (b == null) { |
| b = (isEnumClassSub(cls)) ? Boolean.TRUE : Boolean.FALSE; |
| synchronized (enumMap) { |
| enumMap.put(cls, b); |
| } |
| } |
| return b.booleanValue(); |
| } |
| |
| private static boolean isEnumClassSub(Class cls) { |
| try { |
| java.lang.reflect.Method[] methods = cls.getMethods(); |
| java.lang.reflect.Method getValueMethod = null, |
| fromValueMethod = null, |
| setValueMethod = null, fromStringMethod = null; |
| |
| // linear search: in practice, this is faster than |
| // sorting/searching a short array of methods. |
| for (int i = 0; i < methods.length; i++) { |
| String name = methods[i].getName(); |
| |
| if (name.equals("getValue") |
| && methods[i].getParameterTypes().length == 0) { // getValue() |
| getValueMethod = methods[i]; |
| } else if (name.equals("fromString")) { // fromString(String s) |
| Object[] params = methods[i].getParameterTypes(); |
| if (params.length == 1 |
| && params[0] == String.class) { |
| fromStringMethod = methods[i]; |
| } |
| } else if (name.equals("fromValue") |
| && methods[i].getParameterTypes().length == 1) { // fromValue(Something s) |
| fromValueMethod = methods[i]; |
| } else if (name.equals("setValue") |
| && methods[i].getParameterTypes().length == 1) { // setValue(Something s) |
| setValueMethod = methods[i]; |
| } |
| } |
| |
| // must have getValue and fromString, but not setValue |
| // must also have toString(), but every Object subclass has that, so |
| // no need to check for it. |
| if (null != getValueMethod && null != fromStringMethod) { |
| if (null != setValueMethod |
| && setValueMethod.getParameterTypes().length == 1 |
| && getValueMethod.getReturnType() == setValueMethod.getParameterTypes()[0]) { |
| // setValue exists: return false |
| return false; |
| } else { |
| return true; |
| } |
| } else { |
| return false; |
| } |
| } catch (java.lang.SecurityException e) { |
| return false; |
| } // end of catch |
| } |
| |
| public static String stackToString(Throwable e){ |
| java.io.StringWriter sw= new java.io.StringWriter(1024); |
| java.io.PrintWriter pw= new java.io.PrintWriter(sw); |
| e.printStackTrace(pw); |
| pw.close(); |
| return sw.toString(); |
| } |
| |
| /** |
| * Tests the String 'value': |
| * return 'false' if its 'false', '0', or 'no' - else 'true' |
| * |
| * Follow in 'C' tradition of boolean values: |
| * false is specific (0), everything else is true; |
| */ |
| public static final boolean isTrue(String value) { |
| return !isFalseExplicitly(value); |
| } |
| |
| /** |
| * Tests the String 'value': |
| * return 'true' if its 'true', '1', or 'yes' - else 'false' |
| */ |
| public static final boolean isTrueExplicitly(String value) { |
| return value != null && |
| (value.equalsIgnoreCase("true") || |
| value.equals("1") || |
| value.equalsIgnoreCase("yes")); |
| } |
| |
| /** |
| * Tests the Object 'value': |
| * if its null, return default. |
| * if its a Boolean, return booleanValue() |
| * if its an Integer, return 'false' if its '0' else 'true' |
| * if its a String, return isTrueExplicitly((String)value). |
| * All other types return 'true' |
| */ |
| public static final boolean isTrueExplicitly(Object value, boolean defaultVal) { |
| if ( value == null ) return defaultVal; |
| if ( value instanceof Boolean ) { |
| return ((Boolean)value).booleanValue(); |
| } |
| if ( value instanceof Integer ) { |
| return ((Integer)value).intValue() != 0; |
| } |
| if ( value instanceof String ) { |
| return isTrueExplicitly( (String)value ); |
| } |
| return true; |
| } |
| |
| public static final boolean isTrueExplicitly(Object value) { |
| return isTrueExplicitly(value, false); |
| } |
| |
| /** |
| * Tests the Object 'value': |
| * if its null, return default. |
| * if its a Boolean, return booleanValue() |
| * if its an Integer, return 'false' if its '0' else 'true' |
| * if its a String, return 'false' if its 'false', 'no', or '0' - else 'true' |
| * All other types return 'true' |
| */ |
| public static final boolean isTrue(Object value, boolean defaultVal) { |
| return !isFalseExplicitly(value, !defaultVal); |
| } |
| |
| public static final boolean isTrue(Object value) { |
| return isTrue(value, false); |
| } |
| |
| /** |
| * Tests the String 'value': |
| * return 'true' if its 'false', '0', or 'no' - else 'false' |
| * |
| * Follow in 'C' tradition of boolean values: |
| * false is specific (0), everything else is true; |
| */ |
| public static final boolean isFalse(String value) { |
| return isFalseExplicitly(value); |
| } |
| |
| /** |
| * Tests the String 'value': |
| * return 'true' if its null, 'false', '0', or 'no' - else 'false' |
| */ |
| public static final boolean isFalseExplicitly(String value) { |
| return value == null || |
| value.equalsIgnoreCase("false") || |
| value.equals("0") || |
| value.equalsIgnoreCase("no"); |
| } |
| |
| /** |
| * Tests the Object 'value': |
| * if its null, return default. |
| * if its a Boolean, return !booleanValue() |
| * if its an Integer, return 'true' if its '0' else 'false' |
| * if its a String, return isFalseExplicitly((String)value). |
| * All other types return 'false' |
| */ |
| public static final boolean isFalseExplicitly(Object value, boolean defaultVal) { |
| if ( value == null ) return defaultVal; |
| if ( value instanceof Boolean ) { |
| return !((Boolean)value).booleanValue(); |
| } |
| if ( value instanceof Integer ) { |
| return ((Integer)value).intValue() == 0; |
| } |
| if ( value instanceof String ) { |
| return isFalseExplicitly( (String)value ); |
| } |
| return false; |
| } |
| |
| public static final boolean isFalseExplicitly(Object value) { |
| return isFalseExplicitly(value, true); |
| } |
| |
| /** |
| * Tests the Object 'value': |
| * if its null, return default. |
| * if its a Boolean, return booleanValue() |
| * if its an Integer, return 'false' if its '0' else 'true' |
| * if its a String, return 'false' if its 'false', 'no', or '0' - else 'true' |
| * All other types return 'true' |
| */ |
| public static final boolean isFalse(Object value, boolean defaultVal) { |
| return isFalseExplicitly(value, defaultVal); |
| } |
| |
| public static final boolean isFalse(Object value) { |
| return isFalse(value, true); |
| } |
| |
| /** |
| * Given the MIME type string, return the Java mapping. |
| */ |
| public static String mimeToJava(String mime) { |
| if ("image/gif".equals(mime) || "image/jpeg".equals(mime)) { |
| return "java.awt.Image"; |
| } |
| else if ("text/plain".equals(mime)) { |
| return "java.lang.String"; |
| } |
| else if ("text/xml".equals(mime) || "application/xml".equals(mime)) { |
| return "javax.xml.transform.Source"; |
| } |
| else if ("application/octet-stream".equals(mime)|| |
| "application/octetstream".equals(mime)) { |
| return "org.apache.axis.attachments.OctetStream"; |
| } |
| else if (mime != null && mime.startsWith("multipart/")) { |
| return "javax.mail.internet.MimeMultipart"; |
| } |
| else { |
| return "javax.activation.DataHandler"; |
| } |
| } // mimeToJava |
| |
| //avoid testing and possibly failing everytime. |
| private static boolean checkForAttachmentSupport = true; |
| private static boolean attachmentSupportEnabled = false; |
| |
| /** |
| * Determine whether attachments are supported by checking if the following |
| * classes are available: javax.activation.DataHandler, |
| * javax.mail.internet.MimeMultipart. |
| */ |
| public static synchronized boolean isAttachmentSupported() { |
| |
| if (checkForAttachmentSupport) { |
| //aviod testing and possibly failing everytime. |
| checkForAttachmentSupport = false; |
| try { |
| // Attempt to resolve DataHandler and MimeMultipart and |
| // javax.xml.transform.Source, all necessary for full |
| // attachment support |
| ClassUtils.forName("javax.activation.DataHandler"); |
| ClassUtils.forName("javax.mail.internet.MimeMultipart"); |
| attachmentSupportEnabled = true; |
| } catch (Throwable t) { |
| } |
| log.debug(Messages.getMessage("attachEnabled") + " " + |
| attachmentSupportEnabled); |
| if(!attachmentSupportEnabled) { |
| log.warn(Messages.getMessage("attachDisabled")); |
| } |
| } |
| |
| return attachmentSupportEnabled; |
| } // isAttachmentSupported |
| |
| /** |
| * Makes the value passed in <code>initValue</code> unique among the |
| * {@link String} values contained in <code>values</code> by suffixing |
| * it with a decimal digit suffix. |
| */ |
| public static String getUniqueValue(Collection values, String initValue) { |
| |
| if (!values.contains(initValue)) { |
| return initValue; |
| } |
| else { |
| |
| StringBuffer unqVal = new StringBuffer(initValue); |
| int beg = unqVal.length(), cur, end; |
| while (Character.isDigit(unqVal.charAt(beg - 1))) { |
| beg--; |
| } |
| if (beg == unqVal.length()) { |
| unqVal.append('1'); |
| } |
| cur = end = unqVal.length() - 1; |
| |
| while (values.contains(unqVal.toString())) { |
| |
| if (unqVal.charAt(cur) < '9') { |
| unqVal.setCharAt(cur, (char) (unqVal.charAt(cur) + 1)); |
| } |
| |
| else { |
| |
| while (cur-- > beg) { |
| if (unqVal.charAt(cur) < '9') { |
| unqVal.setCharAt(cur, |
| (char) (unqVal.charAt(cur) + 1)); |
| break; |
| } |
| } |
| |
| // See if there's a need to insert a new digit. |
| if (cur < beg) { |
| unqVal.insert(++cur, '1'); end++; |
| } |
| while (cur < end) { |
| unqVal.setCharAt(++cur, '0'); |
| } |
| |
| } |
| |
| } |
| |
| return unqVal.toString(); |
| |
| } /* For else clause of selection-statement If(!values ... */ |
| |
| } /* For class method JavaUtils.getUniqueValue */ |
| } |