001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.converter.jaxb;
018
019 import java.io.InputStream;
020 import java.io.Reader;
021 import java.io.StringReader;
022 import java.io.StringWriter;
023
024 import javax.xml.bind.JAXBContext;
025 import javax.xml.bind.JAXBException;
026 import javax.xml.bind.Unmarshaller;
027 import javax.xml.bind.Marshaller;
028 import javax.xml.bind.annotation.XmlRootElement;
029 import javax.xml.bind.util.JAXBSource;
030 import javax.xml.transform.Source;
031
032 import org.apache.camel.RuntimeCamelException;
033 import org.apache.camel.TypeConverter;
034 import org.apache.camel.spi.TypeConverterAware;
035 import org.apache.commons.logging.Log;
036 import org.apache.commons.logging.LogFactory;
037
038 /**
039 * @version $Revision: 1.1 $
040 */
041 public class FallbackTypeConverter implements TypeConverter, TypeConverterAware {
042 private static final transient Log LOG = LogFactory.getLog(FallbackTypeConverter.class);
043 private TypeConverter parentTypeConverter;
044 private boolean prettyPrint = true;
045
046 public boolean isPrettyPrint() {
047 return prettyPrint;
048 }
049
050 public void setPrettyPrint(boolean prettyPrint) {
051 this.prettyPrint = prettyPrint;
052 }
053
054 public void setTypeConverter(TypeConverter parentTypeConverter) {
055 this.parentTypeConverter = parentTypeConverter;
056 }
057
058 public <T> T convertTo(Class<T> type, Object value) {
059 try {
060 if (isJaxbType(type)) {
061 return unmarshall(type, value);
062 }
063 if (value != null) {
064 if (isJaxbType(value.getClass())) {
065 return marshall(type, value);
066 }
067 }
068 return null;
069 } catch (JAXBException e) {
070 throw new RuntimeCamelException(e);
071 }
072 }
073
074 protected <T> boolean isJaxbType(Class<T> type) {
075 XmlRootElement element = type.getAnnotation(XmlRootElement.class);
076 boolean jaxbType = element != null;
077 return jaxbType;
078 }
079
080 /**
081 * Lets try parse via JAXB
082 */
083 protected <T> T unmarshall(Class<T> type, Object value) throws JAXBException {
084 JAXBContext context = createContext(type);
085 Unmarshaller unmarshaller = context.createUnmarshaller();
086
087 if (parentTypeConverter != null) {
088 InputStream inputStream = parentTypeConverter.convertTo(InputStream.class, value);
089 if (inputStream != null) {
090 Object unmarshalled = unmarshaller.unmarshal(inputStream);
091 return type.cast(unmarshalled);
092 }
093 Reader reader = parentTypeConverter.convertTo(Reader.class, value);
094 if (reader != null) {
095 Object unmarshalled = unmarshaller.unmarshal(reader);
096 return type.cast(unmarshalled);
097 }
098 Source source = parentTypeConverter.convertTo(Source.class, value);
099 if (source != null) {
100 Object unmarshalled = unmarshaller.unmarshal(source);
101 return type.cast(unmarshalled);
102 }
103 }
104 if (value instanceof String) {
105 value = new StringReader((String)value);
106 }
107 if (value instanceof InputStream) {
108 Object unmarshalled = unmarshaller.unmarshal((InputStream)value);
109 return type.cast(unmarshalled);
110 }
111 if (value instanceof Reader) {
112 Object unmarshalled = unmarshaller.unmarshal((Reader)value);
113 return type.cast(unmarshalled);
114 }
115 return null;
116 }
117
118 protected <T> T marshall(Class<T> type, Object value) throws JAXBException {
119 if (parentTypeConverter != null) {
120 // lets convert the object to a JAXB source and try convert that to
121 // the required source
122 JAXBContext context = createContext(value.getClass());
123 JAXBSource source = new JAXBSource(context, value);
124 T answer = parentTypeConverter.convertTo(type, source);
125 if (answer == null) {
126 // lets try a stream
127 StringWriter buffer = new StringWriter();
128 Marshaller marshaller = context.createMarshaller();
129 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, isPrettyPrint() ? Boolean.TRUE : Boolean.FALSE);
130 marshaller.marshal(value, buffer);
131 return parentTypeConverter.convertTo(type, buffer.toString());
132 }
133 return answer;
134 }
135
136 // lets try convert to the type from JAXB
137 return null;
138 }
139
140 protected <T> JAXBContext createContext(Class<T> type) throws JAXBException {
141 JAXBContext context = JAXBContext.newInstance(type);
142 return context;
143 }
144 }