/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.impl.transformer; import java.io.InputStream; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.converter.stream.OutputStreamBuilder; import org.apache.camel.model.DataFormatDefinition; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataType; import org.apache.camel.spi.Transformer; import org.apache.camel.util.ServiceHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link Transformer} implementation which leverages {@link DataFormat} to perform transformation. * * {@see Transformer} */ public class DataFormatTransformer extends Transformer { private static final Logger LOG = LoggerFactory.getLogger(DataFormatTransformer.class); private String dataFormatRef; private DataFormatDefinition dataFormatType; private DataFormat dataFormat; private String transformerString; public DataFormatTransformer(CamelContext context) { setCamelContext(context); } /** * Perform data transformation with specified from/to type using DataFormat. * @param message message to apply transformation * @param from 'from' data type * @param to 'to' data type */ @Override public void transform(Message message, DataType from, DataType to) throws Exception { Exchange exchange = message.getExchange(); CamelContext context = exchange.getContext(); // Unmarshaling into Java Object if ((to == null || to.isJavaType()) && (from.equals(getFrom()) || from.getModel().equals(getModel()))) { DataFormat dataFormat = getDataFormat(exchange); LOG.debug("Unmarshaling with '{}'", dataFormat); Object answer = dataFormat.unmarshal(exchange, message.getBody(InputStream.class)); if (to != null && to.getName() != null) { Class<?> toClass = context.getClassResolver().resolveClass(to.getName()); if (!toClass.isAssignableFrom(answer.getClass())) { LOG.debug("Converting to '{}'", toClass.getName()); answer = context.getTypeConverter().mandatoryConvertTo(toClass, answer); } } message.setBody(answer); // Marshaling from Java Object } else if ((from == null || from.isJavaType()) && (to.equals(getTo()) || to.getModel().equals(getModel()))) { Object input = message.getBody(); if (from != null && from.getName() != null) { Class<?> fromClass = context.getClassResolver().resolveClass(from.getName()); if (!fromClass.isAssignableFrom(input.getClass())) { LOG.debug("Converting to '{}'", fromClass.getName()); input = context.getTypeConverter().mandatoryConvertTo(fromClass, input); } } OutputStreamBuilder osb = OutputStreamBuilder.withExchange(exchange); DataFormat dataFormat = getDataFormat(exchange); LOG.debug("Marshaling with '{}'", dataFormat); dataFormat.marshal(exchange, message.getBody(), osb); message.setBody(osb.build()); } else { throw new IllegalArgumentException("Unsupported transformation: from='" + from + ", to='" + to + "'"); } } /** * A bit dirty hack to create DataFormat instance, as it requires a RouteContext anyway. */ private DataFormat getDataFormat(Exchange exchange) throws Exception { if (this.dataFormat == null) { this.dataFormat = DataFormatDefinition.getDataFormat( exchange.getUnitOfWork().getRouteContext(), this.dataFormatType, this.dataFormatRef); if (this.dataFormat != null && !getCamelContext().hasService(this.dataFormat)) { getCamelContext().addService(this.dataFormat, false); } } return this.dataFormat; } /** * Set DataFormat ref. * @param ref DataFormat ref * @return this DataFormatTransformer instance */ public DataFormatTransformer setDataFormatRef(String ref) { this.dataFormatRef = ref; this.transformerString = null; return this; } /** * Set DataFormatDefinition. * @param dataFormatType DataFormatDefinition * @return this DataFormatTransformer instance */ public DataFormatTransformer setDataFormatType(DataFormatDefinition dataFormatType) { this.dataFormatType = dataFormatType; this.transformerString = null; return this; } @Override public String toString() { if (transformerString == null) { transformerString = String.format("DataFormatTransformer[scheme='%s', from='%s', to='%s', ref='%s', type='%s']", getModel(), getFrom(), getTo(), dataFormatRef, dataFormatType); } return transformerString; } @Override public void doStart() throws Exception { // no-op } @Override public void doStop() throws Exception { ServiceHelper.stopService(this.dataFormat); getCamelContext().removeService(this.dataFormat); } }