/*
Netwrapper - A library for easy networking in Java
Copyright (C) 2014, University of Lugano
This file is part of Netwrapper.
Netwrapper 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 library 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 library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package ch.usi.dslab.bezerra.netwrapper.codecs;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.ByteBufferInputStream;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import ch.usi.dslab.bezerra.netwrapper.Message;
@SuppressWarnings("rawtypes")
public class CodecUncompressedKryo implements Codec {
private static Map<Integer, Class> classesToRegister = new ConcurrentHashMap<Integer, Class>();
public static void registerClassInSerializationIndex(Class c, int id) {
classesToRegister.put(id, c);
}
private static ThreadLocal<Kryo> threadKryo = new ThreadLocal<Kryo>() {
@Override protected Kryo initialValue() {
Kryo kryo = new Kryo();
kryo.register(Message.class);
for (Entry<Integer, Class> pair : classesToRegister.entrySet())
kryo.register(pair.getValue(), pair.getKey());
return kryo;
}
};
private static Kryo getCurrentThreadKryo() {
Kryo kryo = threadKryo.get();
return kryo;
}
@Override
public byte[] getBytes(Object m) {
Kryo kryo = getCurrentThreadKryo();
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Output out = new Output(bos);
try {
kryo.writeClassAndObject(out, m);
out.flush();
bytes = bos.toByteArray();
bos.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
@Override
public ByteBuffer getByteBufferWithLengthHeader(Object obj) {
byte[] objectArray = getBytes(obj);
int byteBufferLength = 4 + objectArray.length;
ByteBuffer extByteBuffer = ByteBuffer.allocate(byteBufferLength);
extByteBuffer.putInt(byteBufferLength - 4); // length in first header doesn't
// include that header's length
extByteBuffer.put(objectArray);
extByteBuffer.flip();
return extByteBuffer;
}
@Override
public Object createObjectFromBytes(byte[] bytes) {
Kryo kryo = getCurrentThreadKryo();
Object obj = null;
Input in = new Input(bytes);
obj = (Object) kryo.readClassAndObject(in);
in.close();
return obj;
}
@Override
public Object createObjectFromByteBufferWithLengthHeader(ByteBuffer buffer) {
Kryo kryo = getCurrentThreadKryo();
// skip the buffer length parameter
buffer.position(buffer.position() + 4);
Input in = new Input(new ByteBufferInputStream(buffer));
Message msg = (Message) kryo.readClassAndObject(in);
in.close();
msg.rewind();
return msg;
}
@Override
public Object deepDuplicate(Object o) {
Kryo kryo = getCurrentThreadKryo();
return kryo.copy(o);
}
}