/*
* JBoss, Home of Professional Open Source
*
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.teiid.netty.handler.codec.serialization;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import org.teiid.core.util.ExternalizeUtil;
import org.teiid.core.util.MultiArrayOutputStream;
/**
* An {@link ObjectOutput} which is interoperable with {@link ObjectDecoderInputStream}.
*
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)
*
* @version $Rev: 595 $, $Date: 2008-12-08 03:02:33 -0600 (Mon, 08 Dec 2008) $
*
*/
public class ObjectEncoderOutputStream extends ObjectOutputStream {
private final DataOutputStream out;
private MultiArrayOutputStream baos;
public ObjectEncoderOutputStream(DataOutputStream out, int initialBufferSize) throws SecurityException, IOException {
super();
this.out = out;
baos = new MultiArrayOutputStream(initialBufferSize);
}
@Override
final protected void writeObjectOverride(Object obj) throws IOException {
baos.reset(4);
CompactObjectOutputStream oout = new CompactObjectOutputStream(baos);
oout.writeObject(obj);
ExternalizeUtil.writeCollection(oout, oout.getReferences());
oout.flush();
oout.close();
int val = baos.getCount()-4;
byte[] b = baos.getBuffers()[0];
b[3] = (byte) (val >>> 0);
b[2] = (byte) (val >>> 8);
b[1] = (byte) (val >>> 16);
b[0] = (byte) (val >>> 24);
baos.writeTo(out);
if (!oout.getStreams().isEmpty()) {
baos.reset(0);
byte[] chunk = new byte[(1 << 16)];
for (InputStream is : oout.getStreams()) {
while (true) {
int bytes = is.read(chunk, 2, chunk.length - 2);
int toWrite = Math.max(0, bytes);
chunk[1] = (byte) (toWrite >>> 0);
chunk[0] = (byte) (toWrite >>> 8);
if (baos.getIndex() + toWrite + 2 > b.length) {
//exceeds the first buffer
baos.writeTo(out);
baos.reset(0);
out.write(chunk, 0, toWrite + 2);
} else {
//buffer the small chunk
baos.write(chunk, 0, toWrite + 2);
}
if (bytes < 1) {
is.close();
break;
}
}
}
if (baos.getIndex() > 0) {
baos.writeTo(out);
}
}
}
@Override
public void close() throws IOException {
out.close();
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void reset() throws IOException {
//automatically resets with each use
}
}