/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.bigdata.io; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.ByteChannel; import java.nio.channels.Channel; import java.nio.channels.Channels; import java.nio.channels.SocketChannel; import org.apache.log4j.Logger; /** * Utility class that provides dual Channel/ObjectStream access. * * @author Martyn Cutcher * */ public class ObjectSocketChannelStream { protected static final Logger log = Logger.getLogger(ObjectSocketChannelStream.class); ObjectOutputStream outStr = null; ObjectInputStream inStr = null; final ByteChannel channel; byte[] buf = new byte[2048]; public ObjectSocketChannelStream(ByteChannel channel) { this.channel = channel; } public ByteChannel getChannel() { return channel; } public void writeObject(Object obj) throws IOException { ByteArrayOutputStream baout = new ByteArrayOutputStream(); ObjectOutputStream outobj = new ObjectOutputStream(baout); outobj.writeObject(obj); outobj.flush(); byte[] buf = baout.toByteArray(); channel.write(ByteBuffer.wrap(buf)); } public Object readObject() throws IOException { ByteArrayOutputStream baout = new ByteArrayOutputStream(); ObjectOutputStream outobj = new ObjectOutputStream(baout); // outobj.writeObject(obj); outobj.flush(); byte[] buf = baout.toByteArray(); channel.write(ByteBuffer.wrap(buf)); return null; } public ObjectInputStream getInputStream() { if (inStr == null) { try { this.inStr = new ObjectInputStream(Channels.newInputStream(channel)); } catch (IOException e) { throw new RuntimeException(e); } } return inStr; } public ObjectOutputStream getOutputStream() { if (outStr == null) { try { this.outStr = new ObjectOutputStream(Channels.newOutputStream(channel)); } catch (IOException e) { throw new RuntimeException(e); } } return outStr; } private void checkBuffer(int sze) { if (buf.length < sze) { buf = new byte[sze + 2048]; } } public byte[] readByteArray(final int sze) throws IOException { if (log.isTraceEnabled()) log.trace("readByteArray: " + sze); checkBuffer(sze); int totrd = 0; int tsze = sze; while (tsze > 0) { int rdlen = getInputStream().read(buf, totrd, tsze); tsze -= rdlen; totrd += rdlen; } if (log.isTraceEnabled()) log.trace("Read buffer of " + sze + " bytes, actual: " + totrd); return buf; } public void write(ByteBuffer tmp) throws IOException { int sze = tmp.limit(); // tmp.position(0); byte[] loc = null; if (tmp.hasArray()) { loc = tmp.array(); } else { checkBuffer(sze); tmp.get(buf, 0, sze); loc = buf; } if (log.isTraceEnabled()) { log.trace("Writing buffer of " + sze + " bytes"); } getOutputStream().write(loc, 0, sze); } public static OutputStream newOutputStream(final ByteChannel channel) { return new OutputStream() { final ByteBuffer buf = ByteBuffer.allocate(2048); public synchronized void write(int b) throws IOException { if (buf.remaining() == 0) { flush(); } buf.put((byte) b); } public synchronized void write(byte[] bytes, int off, int len) throws IOException { int rem = buf.remaining(); while (len > rem) { len -= rem; buf.put(bytes, off, rem); off += rem; flush(); rem = buf.remaining(); } buf.put(bytes, off, len); } public synchronized void flush() { try { channel.write(buf); buf.reset(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; } // Returns an input stream for a ByteBuffer. // The read() methods use the relative ByteBuffer get() methods. public static InputStream newInputStream(final ByteChannel channel) { final ByteBuffer buf = ByteBuffer.allocate(2048); return new InputStream() { public synchronized int read() throws IOException { if (!buf.hasRemaining()) { channel.read(buf); } return buf.get(); } public synchronized int read(byte[] bytes, int off, int len) throws IOException { int rem = buf.remaining(); while (rem < len) { if (rem > 0) { buf.get(bytes, off, rem); off += rem; len -= rem; } channel.read(buf); rem = buf.remaining(); } buf.get(bytes, off, len); return len; } }; } }