/** * 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.dataformat.beanio; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.support.ServiceSupport; import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.ResourceHelper; import org.beanio.BeanReader; import org.beanio.BeanReaderErrorHandler; import org.beanio.BeanWriter; import org.beanio.StreamFactory; import static org.apache.camel.dataformat.beanio.BeanIOHelper.getOrCreateBeanReaderErrorHandler; /** * A <a href="http://camel.apache.org/data-format.html">data format</a> ( * {@link DataFormat}) for beanio data. */ public class BeanIODataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private transient CamelContext camelContext; private transient StreamFactory factory; private BeanIOConfiguration configuration = new BeanIOConfiguration(); public BeanIODataFormat() { } public BeanIODataFormat(String mapping, String streamName) { setMapping(mapping); setStreamName(streamName); } @Override public String getDataFormatName() { return "beanio"; } @Override protected void doStart() throws Exception { ObjectHelper.notNull(getStreamName(), "Stream name not configured."); if (factory == null) { // Create the stream factory that will be used to read/write objects. factory = StreamFactory.newInstance(); // Load the mapping file using the resource helper to ensure it can be loaded in OSGi and other environments InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), getMapping()); try { if (getProperties() != null) { factory.load(is, getProperties()); } else { factory.load(is); } } finally { IOHelper.close(is); } } } @Override protected void doStop() throws Exception { factory = null; } public CamelContext getCamelContext() { return camelContext; } public void setCamelContext(CamelContext camelContext) { this.camelContext = camelContext; } StreamFactory getFactory() { return factory; } public void marshal(Exchange exchange, Object body, OutputStream stream) throws Exception { List<Object> models = getModels(exchange, body); writeModels(stream, models); } public Object unmarshal(Exchange exchange, InputStream stream) throws Exception { return readModels(exchange, stream); } @SuppressWarnings("unchecked") private List<Object> getModels(Exchange exchange, Object body) { List<Object> models; if ((models = exchange.getContext().getTypeConverter().convertTo(List.class, body)) == null) { models = new ArrayList<Object>(); Iterator<Object> it = ObjectHelper.createIterator(body); while (it.hasNext()) { models.add(it.next()); } } return models; } private void writeModels(OutputStream stream, List<Object> models) { BufferedWriter streamWriter = IOHelper.buffered(new OutputStreamWriter(stream, getEncoding())); BeanWriter out = factory.createWriter(getStreamName(), streamWriter); for (Object obj : models) { out.write(obj); } out.flush(); out.close(); } private List<Object> readModels(Exchange exchange, InputStream stream) throws Exception { List<Object> results = new ArrayList<Object>(); BufferedReader streamReader = IOHelper.buffered(new InputStreamReader(stream, getEncoding())); BeanReader in = factory.createReader(getStreamName(), streamReader); BeanReaderErrorHandler errorHandler = getOrCreateBeanReaderErrorHandler(configuration, exchange, results, null); in.setErrorHandler(errorHandler); try { Object readObject; while ((readObject = in.read()) != null) { if (readObject instanceof BeanIOHeader) { exchange.getOut().getHeaders().putAll(((BeanIOHeader) readObject).getHeaders()); } results.add(readObject); } } finally { in.close(); } return results; } public String getMapping() { return configuration.getMapping(); } public void setIgnoreUnexpectedRecords(boolean ignoreUnexpectedRecords) { configuration.setIgnoreUnexpectedRecords(ignoreUnexpectedRecords); } public void setProperties(Properties properties) { configuration.setProperties(properties); } public void setStreamName(String streamName) { configuration.setStreamName(streamName); } public boolean isIgnoreUnidentifiedRecords() { return configuration.isIgnoreUnidentifiedRecords(); } public boolean isIgnoreInvalidRecords() { return configuration.isIgnoreInvalidRecords(); } public void setIgnoreInvalidRecords(boolean ignoreInvalidRecords) { configuration.setIgnoreInvalidRecords(ignoreInvalidRecords); } public void setEncoding(Charset encoding) { configuration.setEncoding(encoding); } public boolean isIgnoreUnexpectedRecords() { return configuration.isIgnoreUnexpectedRecords(); } public Properties getProperties() { return configuration.getProperties(); } public String getStreamName() { return configuration.getStreamName(); } public void setMapping(String mapping) { configuration.setMapping(mapping); } public void setIgnoreUnidentifiedRecords(boolean ignoreUnidentifiedRecords) { configuration.setIgnoreUnidentifiedRecords(ignoreUnidentifiedRecords); } public Charset getEncoding() { return configuration.getEncoding(); } public BeanReaderErrorHandler getBeanReaderErrorHandler() { return configuration.getBeanReaderErrorHandler(); } public void setBeanReaderErrorHandler(BeanReaderErrorHandler beanReaderErrorHandler) { configuration.setBeanReaderErrorHandler(beanReaderErrorHandler); } public String getBeanReaderErrorHandlerType() { return configuration.getBeanReaderErrorHandlerType(); } public void setBeanReaderErrorHandlerType(String beanReaderErrorHandlerType) { configuration.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType); } public void setBeanReaderErrorHandlerType(Class<?> beanReaderErrorHandlerType) { configuration.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType); } }