/*
* Milyn - Copyright (C) 2006 - 2010
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (version 2.1) as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details:
* http://www.gnu.org/licenses/lgpl.txt
*/
package org.milyn.smooks.camel.dataformat;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
import org.apache.camel.Exchange;
import org.apache.camel.Service;
import org.apache.camel.TypeConverter;
import org.apache.camel.processor.MarshalProcessor;
import org.apache.camel.spi.DataFormat;
import org.milyn.Smooks;
import org.milyn.SmooksFactory;
import org.milyn.container.ExecutionContext;
import org.milyn.payload.Exports;
import org.milyn.payload.StringResult;
import org.milyn.payload.JavaSource;
import org.milyn.smooks.camel.component.SmooksComponent;
import org.milyn.smooks.camel.processor.SmooksProcessor;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamSource;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
/**
* SmooksDataFormat is a Camel data format which is a pluggable transformer
* capable of transforming from one dataformat to another and back again.
* This means that what is marshaled can be unmarshaled by an instance of this
* class.
* <p/>
* <p/>
* A smooks configuration for a SmooksDataFormat should not utilize Smooks
* features such as routing that might allocated system resources. The reason
* for this is that there is no functionality in the SmooksDataFormat which will
* close those resources. If you need to use these Smooks features please take a
* look at the {@link SmooksComponent} or {@link SmooksProcessor} as they hook
* into Camels lifecycle manegment and will close resources correctly.
* <p/>
*
* @author Christian Mueller
* @author Daniel Bevenius
*/
public class SmooksDataFormat implements DataFormat, CamelContextAware, Service {
private Smooks smooks;
private CamelContext camelContext;
private final String smooksConfig;
public SmooksDataFormat(final String smooksConfig) throws Exception {
this.smooksConfig = smooksConfig;
}
/**
* Marshals the Object 'fromBody' to an OutputStream 'toStream'
* </p>
* <p/>
* The Camel framework will call this method from {@link MarshalProcessor#process(Exchange)}
* and it will take care of setting the Out Message's body to the bytes written to the toStream
* OutputStream.
*
* @param exchange The Camel {@link Exchange}.
* @param fromBody The object to be marshalled into the output stream.
* @param toStream The output stream that will be written to.
*/
public void marshal(final Exchange exchange, final Object fromBody, final OutputStream toStream) throws Exception {
final ExecutionContext execContext = smooks.createExecutionContext();
final TypeConverter typeConverter = exchange.getContext().getTypeConverter();
final JavaSource source = typeConverter.mandatoryConvertTo(JavaSource.class, exchange, fromBody);
final StringResult stringResult = new StringResult();
smooks.filterSource(execContext, source, stringResult);
toStream.write(stringResult.getResult().getBytes(execContext.getContentEncoding()));
}
/**
* Unmarshals the fromStream to an Object.
* </p>
* The Camel framework will call this method from {@link UnMarshalProcessor#process(Exchange)}
* and it will take care of setting the returned Object on the Out Message's body.
*
* @param exchange The Camel {@link Exchange}.
* @param fromStream The InputStream that will be unmarshalled into an Object instance.
*/
public Object unmarshal(final Exchange exchange, final InputStream fromStream) throws Exception {
final ExecutionContext execContext = smooks.createExecutionContext();
final Exports exports = Exports.getExports(smooks.getApplicationContext());
final Result[] results = exports.createResults();
smooks.filterSource(execContext, new StreamSource(fromStream), results);
return getResult(exports, results, exchange);
}
protected Object getResult(final Exports exports, final Result[] results, final Exchange exchange) {
final List<Object> objects = Exports.extractResults(results, exports);
if (objects.size() == 1) {
return objects.get(0);
} else {
return objects;
}
}
public void setCamelContext(CamelContext camelContext) {
this.camelContext = camelContext;
}
public CamelContext getCamelContext() {
return camelContext;
}
public void start() throws Exception {
final SmooksFactory smooksFactory = (SmooksFactory) camelContext.getRegistry().lookupByName(SmooksFactory.class.getName());
if (smooksFactory != null) {
smooks = smooksFactory.createInstance(smooksConfig);
} else {
smooks = new Smooks(smooksConfig);
}
}
public void stop() throws Exception {
if (smooks != null) {
smooks.close();
}
}
}