/** * Copyright 2013-2014 Recruit Technologies Co., Ltd. and contributors * (see CONTRIBUTORS.md) * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. A copy of the * License is distributed with this work in the LICENSE.md file. You may * also obtain a copy of the License from * * 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 org.gennai.gungnir.utils; import java.lang.reflect.Constructor; import java.util.Comparator; import java.util.Map; import java.util.TreeMap; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.MapSerializer; import com.google.common.collect.Maps; public class KryoSerializer { private Kryo kryo = new Kryo(); private Output output = new Output(2048, 100 * 1240 * 1024); private Input input = new Input(); @SuppressWarnings("rawtypes") private static class TreeMapSerializer extends MapSerializer { @Override public void write(Kryo kryo, Output output, Map map) { kryo.writeClassAndObject(output, ((TreeMap) map).comparator()); super.write(kryo, output, map); } @Override protected Map create(Kryo kryo, Input input, Class<Map> type) { return createTreeMap(type, (Comparator) kryo.readClassAndObject(input)); } @Override protected Map createCopy(Kryo kryo, Map original) { return createTreeMap(original.getClass(), ((TreeMap) original).comparator()); } // https://github.com/EsotericSoftware/kryo/issues/166 @SuppressWarnings("unchecked") private Map createTreeMap(Class<? extends Map> type, Comparator comparator) { if (type != TreeMap.class && type != null) { try { Constructor constructor = type.getConstructor(Comparator.class); if (!constructor.isAccessible()) { try { constructor.setAccessible(true); } catch (SecurityException se) { se = null; } } return (TreeMap) constructor.newInstance(comparator); } catch (Exception ex) { throw new KryoException(ex); } } return Maps.newTreeMap(comparator); } } public KryoSerializer() { kryo.register(TreeMap.class, new TreeMapSerializer()); } public <T> void register(Class<T> type) { kryo.register(type); } public <T> void register(Class<T> type, Serializer<T> serializer) { kryo.register(type, serializer); } public byte[] serialize(Object object, boolean classInclusive) { output.clear(); if (classInclusive) { kryo.writeClassAndObject(output, object); } else { kryo.writeObject(output, object); } return output.toBytes(); } public byte[] serialize(Object object) { return serialize(object, false); } public <T> T deserialize(byte[] bytes, Class<T> type) { input.setBuffer(bytes); return kryo.readObject(input, type); } public Object deserialize(byte[] bytes) { input.setBuffer(bytes); return kryo.readClassAndObject(input); } }