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 }