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.spring.handler;
018    
019    import java.io.File;
020    import java.io.FileNotFoundException;
021    import java.io.FileOutputStream;
022    import java.io.IOException;
023    import java.io.OutputStream;
024    import java.io.OutputStreamWriter;
025    import java.util.List;
026    import java.util.Properties;
027    
028    import javax.xml.bind.JAXBException;
029    import javax.xml.bind.annotation.XmlRootElement;
030    import javax.xml.parsers.ParserConfigurationException;
031    import javax.xml.transform.OutputKeys;
032    import javax.xml.transform.Result;
033    import javax.xml.transform.TransformerException;
034    import javax.xml.transform.TransformerFactory;
035    import javax.xml.transform.stream.StreamResult;
036    
037    import org.w3c.dom.Document;
038    import org.w3c.dom.Element;
039    import org.w3c.dom.Node;
040    
041    
042    import org.apache.camel.RuntimeCamelException;
043    import org.apache.camel.RuntimeTransformException;
044    import org.apache.camel.builder.xml.Namespaces;
045    import org.apache.camel.converter.jaxp.XmlConverter;
046    import org.apache.camel.model.RouteType;
047    import org.apache.camel.model.RoutesType;
048    import org.apache.camel.util.ObjectHelper;
049    
050    
051    public class ModelFileGenerator extends CamelNamespaceHandler {
052    
053        private static final String DEFAULT_ROOT_ELEMENT_NAME = "routes";
054    
055        /**
056         * Write the specified 'routeTypes' to 'fileName' as XML using JAXB.
057         */
058        public void marshalRoutesUsingJaxb(String fileName, List<RouteType> routeTypes) throws IOException {
059            OutputStream outputStream = outputStream(fileName);
060    
061            try {
062                XmlConverter converter = converter();
063                Document doc = converter.createDocument();
064    
065                Element root = doc.createElement(rootElementName());
066                root.setAttribute("xmlns", Namespaces.DEFAULT_NAMESPACE);
067                doc.appendChild(root);
068    
069                for (RouteType routeType : routeTypes) {
070                    addJaxbElementToNode(root, routeType);
071                }
072    
073                Result result = new StreamResult(new OutputStreamWriter(outputStream, XmlConverter.defaultCharset));
074    
075                copyToResult(converter, doc, result);
076            } catch (ParserConfigurationException e) {
077                throw new RuntimeTransformException(e);
078            } catch (TransformerException e) {
079                throw new RuntimeTransformException(e);
080            } finally {
081                outputStream.close();
082            }
083        }
084    
085        /**
086         * Returns a configured XmlConverter
087         */
088        private XmlConverter converter() {
089            XmlConverter converter = new XmlConverter();
090            TransformerFactory transformerFactory = converter.getTransformerFactory();
091            transformerFactory.setAttribute("indent-number", new Integer(2));
092            return converter;
093        }
094    
095        /**
096         * Copies the given input Document into the required result using the provided converter.
097         */
098        private void copyToResult(XmlConverter converter, Document doc, Result result) throws TransformerException {
099            Properties outputProperties = converter.defaultOutputProperties();
100            outputProperties.put(OutputKeys.OMIT_XML_DECLARATION, "no");
101            outputProperties.put(OutputKeys.INDENT, "yes");
102    
103            converter.toResult(converter.toSource(doc), result, outputProperties);
104        }
105    
106        /**
107         * Convert the specified object into XML and add it as a child of 'node' using JAXB.
108         */
109        private void addJaxbElementToNode(Node node, Object jaxbElement) {
110            try {
111                binder = getJaxbContext().createBinder();
112                binder.marshal(jaxbElement, node);
113            } catch (JAXBException e) {
114                throw new RuntimeCamelException(e);
115            }
116        }
117    
118        /**
119         * Return the root element name for the list of routes.
120         */
121        private String rootElementName() {
122            XmlRootElement annotation = (RoutesType.class).getAnnotation(XmlRootElement.class);
123            if (annotation != null) {
124                String elementName = annotation.name();
125                if (ObjectHelper.isNotNullAndNonEmpty(elementName)) {
126                    return elementName;
127                }
128            }
129            return DEFAULT_ROOT_ELEMENT_NAME;
130        }
131    
132        /**
133         * returns an output stream for the filename specified.
134         */
135        private OutputStream outputStream(String fileName) throws FileNotFoundException {
136            File file = new File(fileName);
137            if (!file.exists()) {
138                File parentFile = file.getParentFile();
139                if (parentFile != null) {
140                    parentFile.mkdirs();
141                }
142            }
143            return new FileOutputStream(file);
144        }
145    }