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 */
017package org.apache.camel.model;
018
019import java.io.InputStream;
020import java.io.StringReader;
021import java.io.StringWriter;
022import javax.xml.bind.JAXBContext;
023import javax.xml.bind.JAXBException;
024import javax.xml.bind.Marshaller;
025import javax.xml.bind.Unmarshaller;
026
027import org.apache.camel.CamelContext;
028import org.apache.camel.NamedNode;
029import org.apache.camel.util.IOHelper;
030
031/**
032 * Helper for the Camel {@link org.apache.camel.model model} classes.
033 */
034public final class ModelHelper {
035
036    private ModelHelper() {
037        // utility class
038    }
039
040    /**
041     * Dumps the definition as XML
042     *
043     * @param context    the CamelContext, if <tt>null</tt> then {@link org.apache.camel.spi.ModelJAXBContextFactory} is not in use
044     * @param definition the definition, such as a {@link org.apache.camel.NamedNode}
045     * @return the output in XML (is formatted)
046     * @throws JAXBException is throw if error marshalling to XML
047     */
048    public static String dumpModelAsXml(CamelContext context, NamedNode definition) throws JAXBException {
049        JAXBContext jaxbContext;
050        if (context == null) {
051            jaxbContext = createJAXBContext();
052        } else {
053            jaxbContext = context.getModelJAXBContextFactory().newJAXBContext();
054        }
055
056        Marshaller marshaller = jaxbContext.createMarshaller();
057        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
058        StringWriter buffer = new StringWriter();
059        marshaller.marshal(definition, buffer);
060
061        return buffer.toString();
062    }
063
064    /**
065     * Marshal the xml to the model definition
066     *
067     * @param context the CamelContext, if <tt>null</tt> then {@link org.apache.camel.spi.ModelJAXBContextFactory} is not in use
068     * @param xml     the xml
069     * @param type    the definition type to return, will throw a {@link ClassCastException} if not the expected type
070     * @return the model definition
071     * @throws javax.xml.bind.JAXBException is thrown if error unmarshalling from xml to model
072     */
073    public static <T extends NamedNode> T createModelFromXml(CamelContext context, String xml, Class<T> type) throws JAXBException {
074        JAXBContext jaxbContext;
075        if (context == null) {
076            jaxbContext = createJAXBContext();
077        } else {
078            jaxbContext = context.getModelJAXBContextFactory().newJAXBContext();
079        }
080
081        StringReader reader = new StringReader(xml);
082        Object result;
083        try {
084            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
085            result = unmarshaller.unmarshal(reader);
086        } finally {
087            IOHelper.close(reader);
088        }
089
090        if (result == null) {
091            throw new JAXBException("Cannot unmarshal to " + type + " using JAXB from XML: " + xml);
092        }
093        return type.cast(result);
094    }
095
096    /**
097     * Marshal the xml to the model definition
098     *
099     * @param context the CamelContext, if <tt>null</tt> then {@link org.apache.camel.spi.ModelJAXBContextFactory} is not in use
100     * @param stream  the xml stream
101     * @param type    the definition type to return, will throw a {@link ClassCastException} if not the expected type
102     * @return the model definition
103     * @throws javax.xml.bind.JAXBException is thrown if error unmarshalling from xml to model
104     */
105    public static <T extends NamedNode> T createModelFromXml(CamelContext context, InputStream stream, Class<T> type) throws JAXBException {
106        JAXBContext jaxbContext;
107        if (context == null) {
108            jaxbContext = createJAXBContext();
109        } else {
110            jaxbContext = context.getModelJAXBContextFactory().newJAXBContext();
111        }
112
113        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
114        Object result = unmarshaller.unmarshal(stream);
115        return type.cast(result);
116    }
117
118    private static JAXBContext createJAXBContext() throws JAXBException {
119        // must use classloader from CamelContext to have JAXB working
120        return JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader());
121    }
122}