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 }