/**
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;
}
};
}
}