summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java')
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java378
1 files changed, 378 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java b/sca-java-2.x/tags/2.0.1-RC1/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java
new file mode 100644
index 0000000000..35adffe23b
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.awt.Image;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.activation.DataHandler;
+import javax.imageio.ImageIO;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Provides utilities to convert an object into a different kind of Object. For example, convert a
+ * String[] into a List<String>
+ */
+public class DataConverter {
+
+ /**
+ * This method should return true if the convert method will succeed.
+ * <p/>
+ * Note that any changes to isConvertable() must also be accompanied by similar changes to
+ * convert()
+ *
+ * @param obj source object or class
+ * @param dest destination class
+ * @return boolean true if convert(..) can convert obj to the destination class
+ */
+ public static boolean isConvertable(Object obj, Class dest) {
+ Class src = null;
+
+ if (obj != null) {
+ if (obj instanceof Class) {
+ src = (Class)obj;
+ } else {
+ src = obj.getClass();
+ }
+ }
+
+ if (dest == null) {
+ return false;
+ }
+
+ if (src == null) {
+ return true;
+ }
+
+ // If we're directly assignable, we're good.
+ if (dest.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())) {
+
+ // TODO this should consider the component types instead of returning true.
+ return true;
+ }
+
+ // Allow mapping of HashMaps to Hashtables
+ if (src == HashMap.class && dest == Hashtable.class)
+ return true;
+
+ // Allow mapping of Calendar to Date
+ if (Calendar.class.isAssignableFrom(src) && dest == Date.class) {
+ return true;
+ }
+
+ if (src.isPrimitive()) {
+ return isConvertable(getWrapperClass(src), dest);
+ }
+
+ if (InputStream.class.isAssignableFrom(src) && dest == byte[].class) {
+ return true;
+ }
+
+ if (Source.class.isAssignableFrom(src) && dest == byte[].class) {
+ return true;
+ }
+
+ if (DataHandler.class.isAssignableFrom(src) && isConvertable(byte[].class, dest)) {
+ return true;
+ }
+
+ if (DataHandler.class.isAssignableFrom(src) && dest == Image.class) {
+ return true;
+ }
+
+ if (DataHandler.class.isAssignableFrom(src) && dest == Source.class) {
+ return true;
+ }
+
+ if (byte[].class.isAssignableFrom(src) && dest == String.class) {
+ return true;
+ }
+
+ // If it's a MIME type mapping and we want a DataHandler,
+ // then we're good.
+ // REVIEW Do we want to support this
+ /*
+ if (dest.getName().equals("javax.activation.DataHandler")) {
+ String name = src.getName();
+ if (src == String.class
+ || src == java.awt.Image.class
+ || name.equals("javax.mail.internet.MimeMultipart")
+ || name.equals("javax.xml.transform.Source"))
+ return true;
+ }
+ */
+
+ return false;
+ }
+
+ /**
+ * Utility function to convert an Object to some desired Class.
+ * <p/>
+ * Normally this is used for T[] to List<T> processing. Other conversions are also done (i.e.
+ * HashMap <->Hashtable, etc.)
+ * <p/>
+ * Use the isConvertable() method to determine if conversion is possible. Note that any changes
+ * to convert() must also be accompanied by similar changes to isConvertable()
+ *
+ * @param arg the array to convert
+ * @param destClass the actual class we want
+ * @return object of destClass if conversion possible, otherwise returns arg
+ */
+ public static Object convert(Object arg, Class<?> destClass) {
+ if (destClass == null) {
+ return arg;
+ }
+
+ if (arg != null && destClass.isAssignableFrom(arg.getClass())) {
+ return arg;
+ }
+
+ // Convert between Calendar and Date
+ if (arg instanceof Calendar && destClass == Date.class) {
+ return ((Calendar)arg).getTime();
+ }
+
+ // Convert between HashMap and Hashtable
+ if (arg instanceof HashMap && destClass == Hashtable.class) {
+ return new Hashtable((HashMap)arg);
+ }
+
+ if (arg instanceof InputStream && destClass == byte[].class) {
+
+ try {
+ InputStream is = (InputStream)arg;
+ return getBytesFromStream(is);
+ } catch (IOException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ if (arg instanceof Source && destClass == byte[].class) {
+ try {
+ if (arg instanceof StreamSource) {
+ InputStream is = ((StreamSource)arg).getInputStream();
+ if (is != null) {
+ return getBytesFromStream(is);
+ }
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Result result = new StreamResult(out);
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.transform((Source)arg, result);
+ byte[] bytes = out.toByteArray();
+ return bytes;
+
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ if (arg instanceof DataHandler) {
+ try {
+ InputStream is = ((DataHandler)arg).getInputStream();
+ if (destClass == Image.class) {
+ return ImageIO.read(is);
+ } else if (destClass == Source.class) {
+ return new StreamSource(is);
+ }
+ byte[] bytes = getBytesFromStream(is);
+ return convert(bytes, destClass);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ if (arg instanceof byte[] && destClass == String.class) {
+ return new String((byte[])arg);
+ }
+
+ // If the destination is an array and the source
+ // is a suitable component, return an array with
+ // the single item.
+ /* REVIEW do we need to support atomic to array conversion ?
+ 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;
+ }
+ */
+
+ // Return if no conversion is available
+ if (!(arg instanceof Collection || (arg != null && arg.getClass().isArray()))) {
+ return arg;
+ }
+
+ if (arg == null) {
+ return null;
+ }
+
+ // The arg may be an array or List
+ Object destValue = null;
+ int length = 0;
+ if (arg.getClass().isArray()) {
+ length = Array.getLength(arg);
+ } else {
+ length = ((Collection)arg).size();
+ }
+
+ try {
+ 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) {
+ // No FFDC code needed
+ // 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;
+ }
+ } catch (Throwable t) {
+ throw new ServiceRuntimeException(t);
+ }
+
+ return destValue;
+ }
+
+ private static byte[] getBytesFromStream(InputStream is) throws IOException {
+ // TODO This code assumes that available is the length of the stream.
+ byte[] bytes = new byte[is.available()];
+ is.read(bytes);
+ return bytes;
+ }
+
+ 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;
+ }
+}