/* * Copyright 2012 Michael Bischoff * * Licensed 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 de.jpaw.bonaparte.camel; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.util.Collection; import java.util.List; import org.apache.camel.Exchange; import org.apache.camel.spi.DataFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.jpaw.bonaparte.core.BonaCustom; import de.jpaw.bonaparte.core.BonaPortable; import de.jpaw.bonaparte.core.ByteArrayComposer; import de.jpaw.bonaparte.core.ByteArrayConstants; import de.jpaw.bonaparte.core.ByteArrayParser; import de.jpaw.util.ByteArray; /** * The NewDataFormat class. * * @author Michael Bischoff * @version $Revision$ * * Implements the Apache Camel DataFormat interface using the ByteArray bonaparte implementation. * Work in progress - needs major rework to provide better separation of outer transmission layer. */ public final class Bonaparte2ByteDataFormat implements DataFormat { private static final Logger logger = LoggerFactory.getLogger(Bonaparte2ByteDataFormat.class); private boolean writeCRs = false; // the character set used for backend communication: UTF-8 or ISO-8859-something or windows-125x private Charset useCharset = ByteArray.CHARSET_UTF8; // Charset.defaultCharset(); or "windows-1252" private int initialBufferSize = 16000; // start big to avoid frequent reallocation private void toStream(ByteArrayComposer w, OutputStream stream) throws IOException { stream.write(w.getBuffer(), 0, w.getLength()); w.reset(); } @Override public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception { ByteArrayComposer w = new ByteArrayComposer(); w.setCharset(useCharset); if (Collection.class.isInstance(graph)) { w.startTransmission(); // writeOptions(stream, w); toStream(w, stream); for (Object o : (Collection)graph) { w.writeRecord((BonaCustom) o); toStream(w, stream); } w.terminateTransmission(); toStream(w, stream); } else { // assume single record w.writeRecord((BonaCustom) graph); toStream(w, stream); } } @Override public Object unmarshal(Exchange exchange, InputStream stream) throws Exception { // get the bytes, convert to String, parse // TODO: avoid byte buffer breaks within UTF-8-sequence! boolean isMultiRecord = false; byte [] byteBuffer = new byte[initialBufferSize]; int numbytes = stream.read(byteBuffer, 0, initialBufferSize); logger.debug("read {} bytes from the input stream", numbytes); if (numbytes == initialBufferSize) throw new Exception("multi-reads for big messages not yet supported"); if (byteBuffer[0] == ByteArrayConstants.TRANSMISSION_BEGIN) // multi record (transmission) isMultiRecord = true; ByteArrayParser p = new ByteArrayParser(byteBuffer, 0, numbytes); List<BonaPortable> resultSet = p.readTransmission(); if (isMultiRecord) return resultSet; // which may be empty else if (resultSet.size() == 0) return null; else { if (resultSet.size() > 1) throw new Exception("more than 1 record without a transmission header!"); return resultSet.get(0); } } public boolean isWriteCRs() { return writeCRs; } public void setWriteCRs(boolean writeCRs) { this.writeCRs = writeCRs; } public Charset getUseCharset() { return useCharset; } public void setUseCharset(Charset useCharset) { this.useCharset = useCharset; } public int getInitialBufferSize() { return initialBufferSize; } public void setInitialBufferSize(int initialBufferSize) { this.initialBufferSize = initialBufferSize; } }