blob: 7375d9eb3a51be80f7d01ce395872806bcabbd28 [file] [log] [blame]
/*
* 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 */
}