001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.camel.builder.xml;
019
020 import org.apache.camel.Exchange;
021 import org.apache.camel.ExpectedBodyTypeException;
022 import org.apache.camel.Message;
023 import org.apache.camel.Processor;
024 import org.apache.camel.RuntimeTransformException;
025 import org.apache.camel.converter.jaxp.XmlConverter;
026 import static org.apache.camel.util.ObjectHelper.notNull;
027
028 import javax.xml.parsers.ParserConfigurationException;
029 import javax.xml.transform.Result;
030 import javax.xml.transform.Source;
031 import javax.xml.transform.Transformer;
032 import javax.xml.transform.TransformerConfigurationException;
033 import javax.xml.transform.stream.StreamSource;
034 import java.io.File;
035 import java.io.IOException;
036 import java.io.InputStream;
037 import java.net.URL;
038 import java.util.HashMap;
039 import java.util.Map;
040 import java.util.Set;
041
042 /**
043 * Creates a <a href="http://activemq.apache.org/camel/processor.html">Processor</a>
044 * which performs an XSLT transformation of the IN message body
045 *
046 * @version $Revision: 531854 $
047 */
048 public class XsltBuilder implements Processor {
049 private Map<String, Object> parameters = new HashMap<String, Object>();
050 private XmlConverter converter = new XmlConverter();
051 private Transformer transformer;
052 private ResultHandler resultHandler = new StringResultHandler();
053 private boolean failOnNullBody = true;
054
055 public XsltBuilder() {
056 }
057
058 public XsltBuilder(Transformer transformer) {
059 this.transformer = transformer;
060 }
061
062 @Override
063 public String toString() {
064 return "XSLT[" + transformer + "]";
065 }
066
067 public synchronized void process(Exchange exchange) throws Exception {
068 Transformer transformer = getTransformer();
069 if (transformer == null) {
070 throw new IllegalArgumentException("No transformer configured!");
071 }
072 configureTransformer(transformer, exchange);
073 Source source = getSource(exchange);
074 Result result = resultHandler.getResult();
075 transformer.transform(source, result);
076 resultHandler.setBody(exchange.getIn());
077 }
078
079 // Builder methods
080 //-------------------------------------------------------------------------
081
082 /**
083 * Creates an XSLT processor using the given transformer instance
084 */
085 public static XsltBuilder xslt(Transformer transformer) {
086 return new XsltBuilder(transformer);
087 }
088
089 /**
090 * Creates an XSLT processor using the given XSLT source
091 */
092 public static XsltBuilder xslt(Source xslt) throws TransformerConfigurationException {
093 notNull(xslt, "xslt");
094 XsltBuilder answer = new XsltBuilder();
095 answer.setTransformerSource(xslt);
096 return answer;
097 }
098
099 /**
100 * Creates an XSLT processor using the given XSLT source
101 */
102 public static XsltBuilder xslt(File xslt) throws TransformerConfigurationException {
103 notNull(xslt, "xslt");
104 return xslt(new StreamSource(xslt));
105 }
106
107 /**
108 * Creates an XSLT processor using the given XSLT source
109 */
110 public static XsltBuilder xslt(URL xslt) throws TransformerConfigurationException, IOException {
111 notNull(xslt, "xslt");
112 return xslt(xslt.openStream());
113 }
114
115 /**
116 * Creates an XSLT processor using the given XSLT source
117 */
118 public static XsltBuilder xslt(InputStream xslt) throws TransformerConfigurationException, IOException {
119 notNull(xslt, "xslt");
120 return xslt(new StreamSource(xslt));
121 }
122
123 /**
124 * Sets the output as being a byte[]
125 */
126 public XsltBuilder outputBytes() {
127 setResultHandler(new StreamResultHandler());
128 return this;
129 }
130
131 /**
132 * Sets the output as being a String
133 */
134 public XsltBuilder outputString() {
135 setResultHandler(new StringResultHandler());
136 return this;
137 }
138
139 /**
140 * Sets the output as being a DOM
141 */
142 public XsltBuilder outputDOM() {
143 setResultHandler(new DomResultHandler());
144 return this;
145 }
146
147 public XsltBuilder parameter(String name, Object value) {
148 parameters.put(name, value);
149 return this;
150 }
151
152 // Properties
153 //-------------------------------------------------------------------------
154
155 public Map<String, Object> getParameters() {
156 return parameters;
157 }
158
159 public void setParameters(Map<String, Object> parameters) {
160 this.parameters = parameters;
161 }
162
163 public Transformer getTransformer() {
164 return transformer;
165 }
166
167 public void setTransformer(Transformer transformer) {
168 this.transformer = transformer;
169 }
170
171 public boolean isFailOnNullBody() {
172 return failOnNullBody;
173 }
174
175 public void setFailOnNullBody(boolean failOnNullBody) {
176 this.failOnNullBody = failOnNullBody;
177 }
178
179 public ResultHandler getResultHandler() {
180 return resultHandler;
181 }
182
183 public void setResultHandler(ResultHandler resultHandler) {
184 this.resultHandler = resultHandler;
185 }
186
187 public void setTransformerSource(Source source) throws TransformerConfigurationException {
188 setTransformer(converter.getTransformerFactory().newTransformer(source));
189 }
190
191 // Implementation methods
192 // -------------------------------------------------------------------------
193
194 /**
195 * Converts the inbound body to a {@link Source}
196 */
197 protected Source getSource(Exchange exchange) {
198 Message in = exchange.getIn();
199 Source source = in.getBody(Source.class);
200 if (source == null) {
201 if (isFailOnNullBody()) {
202 throw new ExpectedBodyTypeException(exchange, Source.class);
203 }
204 else {
205 try {
206 source = converter.toSource(converter.createDocument());
207 }
208 catch (ParserConfigurationException e) {
209 throw new RuntimeTransformException(e);
210 }
211 }
212 }
213 return source;
214 }
215
216 /**
217 * Configures the transformerwith exchange specific parameters
218 */
219 protected void configureTransformer(Transformer transformer, Exchange exchange) {
220 transformer.clearParameters();
221
222 addParameters(transformer, exchange.getProperties());
223 addParameters(transformer, exchange.getIn().getHeaders());
224 addParameters(transformer, getParameters());
225
226 transformer.setParameter("exchange", exchange);
227 transformer.setParameter("in", exchange.getIn());
228 transformer.setParameter("out", exchange.getOut());
229 }
230
231 protected void addParameters(Transformer transformer, Map<String, Object> map) {
232 Set<Map.Entry<String, Object>> propertyEntries = map.entrySet();
233 for (Map.Entry<String, Object> entry : propertyEntries) {
234 transformer.setParameter(entry.getKey(), entry.getValue());
235 }
236 }
237 }