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.IOException;
020    import java.io.InputStream;
021    import java.io.OutputStream;
022    import javax.xml.bind.JAXBContext;
023    import javax.xml.bind.JAXBElement;
024    import javax.xml.bind.JAXBException;
025    import javax.xml.bind.Marshaller;
026    
027    import org.apache.camel.Exchange;
028    import org.apache.camel.spi.DataFormat;
029    import org.apache.camel.util.IOHelper;
030    
031    /**
032     * A <a href="http://camel.apache.org/data-format.html">data format</a> ({@link DataFormat})
033     * using JAXB2 to marshal to and from XML
034     *
035     * @version $Revision: 834590 $
036     */
037    public class JaxbDataFormat implements DataFormat {
038        private JAXBContext context;
039        private String contextPath;
040        private boolean prettyPrint = true;
041        private boolean ignoreJAXBElement = true;
042        private String encoding;
043    
044        public JaxbDataFormat() {
045        }
046    
047        public JaxbDataFormat(JAXBContext context) {
048            this.context = context;
049        }
050    
051        public JaxbDataFormat(String contextPath) {
052            this.contextPath = contextPath;
053        }
054    
055        public void marshal(Exchange exchange, Object graph, OutputStream stream) throws IOException {
056            try {            
057                // must create a new instance of marshaller as its not thread safe
058                Marshaller marshaller = getContext().createMarshaller();
059                if (isPrettyPrint()) {
060                    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
061                } 
062                // exchange take precedense over encoding option
063                String charset = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
064                if (charset == null) {
065                    charset = encoding;
066                }
067                if (charset != null) {
068                    marshaller.setProperty(Marshaller.JAXB_ENCODING, charset);
069                }
070    
071                marshaller.marshal(graph, stream);
072    
073            } catch (JAXBException e) {
074                throw IOHelper.createIOException(e);
075            }
076        }
077    
078        public Object unmarshal(Exchange exchange, InputStream stream) throws IOException, ClassNotFoundException {
079            try {
080                // must create a new instance of unmarshaller as its not thread safe
081                Object answer = getContext().createUnmarshaller().unmarshal(stream);
082                if (answer instanceof JAXBElement && isIgnoreJAXBElement()) {
083                    answer = ((JAXBElement<?>)answer).getValue();
084                }
085                return answer;
086            } catch (JAXBException e) {
087                throw IOHelper.createIOException(e);
088            }
089        }    
090    
091        // Properties
092        // -------------------------------------------------------------------------
093        public boolean isIgnoreJAXBElement() {        
094            return ignoreJAXBElement;
095        }
096        
097        public void setIgnoreJAXBElement(boolean flag) {
098            ignoreJAXBElement = flag;
099        }
100        
101        public synchronized JAXBContext getContext() throws JAXBException {
102            if (context == null) {
103                context = createContext();
104            }
105            return context;
106        }
107    
108        public void setContext(JAXBContext context) {
109            this.context = context;
110        }
111    
112        public String getContextPath() {
113            return contextPath;
114        }
115    
116        public void setContextPath(String contextPath) {
117            this.contextPath = contextPath;
118        }
119    
120        public boolean isPrettyPrint() {
121            return prettyPrint;
122        }
123    
124        public void setPrettyPrint(boolean prettyPrint) {
125            this.prettyPrint = prettyPrint;
126        }
127    
128        public String getEncoding() {
129            return encoding;
130        }
131    
132        public void setEncoding(String encoding) {
133            this.encoding = encoding;
134        }
135    
136        protected JAXBContext createContext() throws JAXBException {
137            if (contextPath != null) {
138                return JAXBContext.newInstance(contextPath);
139            } else {
140                return JAXBContext.newInstance();
141            }
142        }
143    }