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