From 4c597a314f9f5cdcf3f9475cab739442b7cb8fe0 Mon Sep 17 00:00:00 2001 From: RuedigerMoeller Date: Thu, 28 May 2015 21:37:56 +0200 Subject: [PATCH] . --- .../nustaq/serialization/FSTClazzInfo.java | 16 +++- .../serialization/FSTConfiguration.java | 10 +++ .../serialization/coders/FSTJsonDecoder.java | 69 +++++++-------- .../serialization/coders/FSTJsonEncoder.java | 88 ++++++++++++++----- .../coders/FSTMinBinEncoder.java | 2 +- 5 files changed, 120 insertions(+), 65 deletions(-) diff --git a/src/main/java/org/nustaq/serialization/FSTClazzInfo.java b/src/main/java/org/nustaq/serialization/FSTClazzInfo.java index 8a1d63f5..0f98b3ac 100644 --- a/src/main/java/org/nustaq/serialization/FSTClazzInfo.java +++ b/src/main/java/org/nustaq/serialization/FSTClazzInfo.java @@ -75,6 +75,16 @@ public int compare(FSTFieldInfo o1, FSTFieldInfo o2) { Method writeReplaceMethod, readResolveMethod; HashMap compInfo = new HashMap(7); + Object decoderAttached; // for decoders + + public Object getDecoderAttached() { + return decoderAttached; + } + + public void setDecoderAttached(Object decoderAttached) { + this.decoderAttached = decoderAttached; + } + boolean requiresCompatibleMode; boolean externalizable; boolean flat; // never share instances of this class @@ -480,7 +490,7 @@ public final static class FSTFieldInfo { int indexId; // position in serializable fields array int align = 0; int alignPad = 0; - byte[] bufferedName; // cache byte rep of field name (used for cross platform) + Object bufferedName; // cache byte rep of field name (used for cross platform) // hacke required for compatibility with ancient JDK mechanics (cross JDK, e.g. Android <=> OpenJDK ). // in rare cases, a field used in putField is not present as a real field @@ -532,11 +542,11 @@ public byte getVersion() { return version; } - public byte[] getBufferedName() { + public Object getBufferedName() { return bufferedName; } - public void setBufferedName(byte[] bufferedName) { + public void setBufferedName(Object bufferedName) { this.bufferedName = bufferedName; } diff --git a/src/main/java/org/nustaq/serialization/FSTConfiguration.java b/src/main/java/org/nustaq/serialization/FSTConfiguration.java index 89e40784..72b2e9e3 100644 --- a/src/main/java/org/nustaq/serialization/FSTConfiguration.java +++ b/src/main/java/org/nustaq/serialization/FSTConfiguration.java @@ -968,6 +968,16 @@ public FSTConfiguration registerCrossPlatformClassMapping( String shortName, St return this; } + /** + * shorthand for registerCrossPlatformClassMapping(_,_) + * @param shortName - class name in json type field + * @param clz - class + * @return + */ + public FSTConfiguration cpMap(String shortName, Class clz) { + return registerCrossPlatformClassMapping(shortName,clz.getName()); + } + /** * init right after creation of configuration, not during operation as it is not threadsafe regarding mutation */ diff --git a/src/main/java/org/nustaq/serialization/coders/FSTJsonDecoder.java b/src/main/java/org/nustaq/serialization/coders/FSTJsonDecoder.java index d6bdce34..9562a85d 100644 --- a/src/main/java/org/nustaq/serialization/coders/FSTJsonDecoder.java +++ b/src/main/java/org/nustaq/serialization/coders/FSTJsonDecoder.java @@ -54,27 +54,34 @@ public String readStringAsc() throws IOException { */ public Object readFPrimitiveArray(Object array, Class componentType, int len) { try { - if (componentType == double.class) { + if (componentType == int.class) { + int[] da = (int[]) array; + for (int i = 0; i < da.length; i++) { + input.nextToken(); da[i] = (int) input.getIntValue(); + } + return da; + } + else if (componentType == long.class) { + long[] da = (long[]) array; + for (int i = 0; i < da.length; i++) { + input.nextToken(); da[i] = input.getLongValue(); + } + return da; + } else if (componentType == double.class) { double[] da = (double[]) array; for (int i = 0; i < da.length; i++) { input.nextToken(); da[i] = input.getDoubleValue(); } return da; - } - if (componentType == float.class) { + } else if (componentType == float.class) { float[] da = (float[]) array; for (int i = 0; i < da.length; i++) { input.nextToken(); da[i] = input.getFloatValue(); } return da; - } - Object arr = array; - int length = Array.getLength(arr); - if (len != -1 && len != length) - throw new RuntimeException("unexpected arrays size"); - if (componentType == boolean.class) { + } else if (componentType == boolean.class) { boolean[] da = (boolean[]) array; for (int i = 0; i < da.length; i++) { input.nextToken(); da[i] = input.getBooleanValue(); @@ -102,20 +109,6 @@ else if (componentType == char.class) { } return da; } - else if (componentType == int.class) { - int[] da = (int[]) array; - for (int i = 0; i < da.length; i++) { - input.nextToken(); da[i] = (int) input.getIntValue(); - } - return da; - } - else if (componentType == long.class) { - long[] da = (long[]) array; - for (int i = 0; i < da.length; i++) { - input.nextToken(); da[i] = input.getLongValue(); - } - return da; - } else throw new RuntimeException("unsupported type " + componentType.getName()); } catch (Exception e) { FSTUtil.rethrow(e); @@ -308,11 +301,11 @@ public byte readObjectHeaderTag() throws IOException { } String typeTag = input.nextFieldName(); - if ( typeTag.equals("type") ) { + if ( typeTag.equals(FSTJsonEncoder.TYPE) ) { // object String type = input.nextTextValue(); String valueTag = input.nextFieldName(); - if ( ! "obj".equals(valueTag) ) { + if ( ! FSTJsonEncoder.OBJ.equals(valueTag) ) { throw new RuntimeException("expected value attribute for object of type:"+type); } if ( ! input.nextToken().isStructStart() ) { @@ -324,13 +317,13 @@ public byte readObjectHeaderTag() throws IOException { FSTUtil.rethrow(e); } return FSTObjectOutput.OBJECT; - } else if ( typeTag.equals("seqType") ) { + } else if ( typeTag.equals(FSTJsonEncoder.SEQ_TYPE) ) { // sequence String type = input.nextTextValue(); try { lastDirectClass = classForName(conf.getClassForCPName(type)); String valueTag = input.nextFieldName(); - if ( ! "seq".equals(valueTag) ) { + if ( ! FSTJsonEncoder.SEQ.equals(valueTag) ) { throw new RuntimeException("expected value attribute for object of type:"+type); } if ( ! input.nextToken().isStructStart() ) { @@ -340,14 +333,14 @@ public byte readObjectHeaderTag() throws IOException { FSTUtil.rethrow(e); } return FSTObjectOutput.ARRAY; - } else if ( typeTag.equals("ref") ) { + } else if ( typeTag.equals(FSTJsonEncoder.REF) ) { return FSTObjectOutput.HANDLE; - } else if ( typeTag.equals("enum") ) { + } else if ( typeTag.equals(FSTJsonEncoder.ENUM) ) { try { String clName = input.nextTextValue(); Class aClass = classForName(conf.getClassForCPName(clName)); String valueTag = input.nextFieldName(); - if ( ! "val".equals(valueTag) ) { + if ( ! FSTJsonEncoder.VAL.equals(valueTag) ) { throw new RuntimeException("expected value attribute for enum of type:"+clName); } String enumString = input.nextTextValue(); @@ -448,11 +441,9 @@ public FSTClazzInfo readClass() throws IOException, ClassNotFoundException { return null; } - HashMap clzCache = new HashMap<>(); + HashMap clzCache = new HashMap<>(31); @Override public Class classForName(String name) throws ClassNotFoundException { - if ("Object".equals(name)) - return MBObject.class; Class aClass = clzCache.get(name); if (aClass!=null) return aClass; @@ -463,13 +454,13 @@ public Class classForName(String name) throws ClassNotFoundException { @Override public void registerClass(Class possible) { - throw new RuntimeException("not implemented"); +// throw new RuntimeException("not implemented"); } @Override public void close() { - //TODO - throw new RuntimeException("not implemented"); + //nothing to do (?) +// throw new RuntimeException("not implemented"); } @Override @@ -509,16 +500,16 @@ public Object readArrayHeader() throws Exception { return null; } else { jsonToken = input.nextToken(); // seqType - if ( "type".equals(input.getText())) { + if ( FSTJsonEncoder.TYPE.equals(input.getText())) { // object type = input.nextTextValue(); String valueTag = input.nextFieldName(); - if ( ! "obj".equals(valueTag) ) { + if ( !FSTJsonEncoder.OBJ.equals(valueTag) ) { throw new RuntimeException("expected value attribute for object of type:"+type); } return classForName(conf.getClassForCPName(type)); } - if ( ! "seqType".equals(input.getText()) ) { + if (!FSTJsonEncoder.SEQ_TYPE.equals(input.getText()) ) { System.out.println(">" + input.getCurrentToken()+" "+input.getText()); input.nextToken(); System.out.println(">" + input.getCurrentToken()+" "+input.getText()); diff --git a/src/main/java/org/nustaq/serialization/coders/FSTJsonEncoder.java b/src/main/java/org/nustaq/serialization/coders/FSTJsonEncoder.java index 1a462094..66b24846 100644 --- a/src/main/java/org/nustaq/serialization/coders/FSTJsonEncoder.java +++ b/src/main/java/org/nustaq/serialization/coders/FSTJsonEncoder.java @@ -3,18 +3,14 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonStreamContext; -import com.fasterxml.jackson.core.SerializableString; -import com.fasterxml.jackson.core.io.IOContext; -import com.fasterxml.jackson.core.json.UTF8JsonGenerator; +import com.fasterxml.jackson.core.io.SerializedString; import org.nustaq.serialization.*; import org.nustaq.serialization.util.FSTOutputStream; import org.nustaq.serialization.util.FSTUtil; import java.io.IOException; import java.io.OutputStream; -import java.io.Serializable; import java.lang.reflect.Array; -import java.math.BigDecimal; /** * Created by ruedi on 20/05/15. @@ -22,6 +18,22 @@ */ public class FSTJsonEncoder implements FSTEncoder { + public static final String TYPE = "typ"; + public static final String OBJ = "obj"; + public static final String SEQ_TYPE = "styp"; + public static final String SEQ = "seq"; + public static final String ENUM = "enum"; + public static final String VAL = "val"; + public static final String REF = "ref"; + + public static final SerializedString TYPE_S = new SerializedString(TYPE); + public static final SerializedString OBJ_S = new SerializedString(OBJ); + public static final SerializedString SEQ_TYPE_S = new SerializedString(SEQ_TYPE); + public static final SerializedString SEQ_S = new SerializedString(SEQ); + public static final SerializedString ENUM_S = new SerializedString(ENUM); + public static final SerializedString VAL_S = new SerializedString(VAL); + public static final SerializedString REF_S = new SerializedString(REF); + JsonFactory fac; FSTConfiguration conf; @@ -44,12 +56,29 @@ public void writePrimitiveArray(Object array, int start, int length) throws IOEx Class componentType = array.getClass().getComponentType(); if ( componentType != int.class ) { gen.writeString(componentType.getSimpleName()); + } else { // fast path for int + int arr[] = (int[]) array; + for (int i=0; i < length; i++ ) { + gen.writeNumber(arr[i]); + } + gen.writeEndArray(); + return; } if ( array instanceof boolean[] ) { boolean arr[] = (boolean[]) array; for (int i=0; i < length; i++ ) { gen.writeBoolean(arr[i]); } + } else if ( array instanceof long[] ) { + long arr[] = (long[]) array; + for (int i=0; i < length; i++ ) { + gen.writeNumber(arr[i]); + } + } else if ( array instanceof double[] ) { + double arr[] = (double[]) array; + for (int i=0; i < length; i++ ) { + gen.writeNumber(arr[i]); + } } else if ( array instanceof char[] ) { char arr[] = (char[]) array; for (int i=0; i < length; i++ ) { @@ -200,7 +229,7 @@ public boolean writeTag(byte tag, Object infoOrObject, long somValue, Object toW switch (tag) { case FSTObjectOutput.HANDLE: gen.writeStartObject(); - gen.writeFieldName("ref"); + gen.writeFieldName(REF_S); gen.writeNumber(somValue); gen.writeEndObject(); return true; @@ -234,16 +263,16 @@ public boolean writeTag(byte tag, Object infoOrObject, long somValue, Object toW break; if ( clzInfo.getSer()!=null || clzInfo.isExternalizable() ) { gen.writeStartObject(); - gen.writeFieldName("type"); - writeSymbolicClazz(clzInfo.getClazz()); - gen.writeFieldName("obj"); + gen.writeFieldName(TYPE_S); + writeSymbolicClazz(clzInfo, clzInfo.getClazz()); + gen.writeFieldName(OBJ_S); gen.writeStartArray(); } else { gen.writeStartObject(); - gen.writeFieldName("type"); - writeSymbolicClazz(clzInfo.getClazz()); - gen.writeFieldName("obj"); + gen.writeFieldName(TYPE_S); + writeSymbolicClazz(clzInfo,clzInfo.getClazz()); + gen.writeFieldName(OBJ_S); gen.writeStartObject(); } break; @@ -270,9 +299,9 @@ public boolean writeTag(byte tag, Object infoOrObject, long somValue, Object toW return true; } else { gen.writeStartObject(); - gen.writeFieldName("seqType"); - writeSymbolicClazz(clz); - gen.writeFieldName("seq"); + gen.writeFieldName(SEQ_TYPE_S); + writeSymbolicClazz(null,clz); + gen.writeFieldName(SEQ_S); gen.writeStartArray(); } break; @@ -289,9 +318,9 @@ public boolean writeTag(byte tag, Object infoOrObject, long somValue, Object toW } } gen.writeStartObject(); - gen.writeFieldName("enum"); - writeSymbolicClazz(c); - gen.writeFieldName("val"); + gen.writeFieldName(ENUM_S); + writeSymbolicClazz(null,c); + gen.writeFieldName(VAL_S); gen.writeString(toWrite.toString()); gen.writeEndObject(); return true; @@ -301,9 +330,18 @@ public boolean writeTag(byte tag, Object infoOrObject, long somValue, Object toW return false; } - private void writeSymbolicClazz(Class clz) { + private void writeSymbolicClazz(FSTClazzInfo clzInfo, Class clz) { try { - gen.writeString(classToString(clz)); + if ( clzInfo != null ) { + SerializedString buffered = (SerializedString) clzInfo.getDecoderAttached(); + if ( buffered == null ) { + buffered = new SerializedString(classToString(clz)); + clzInfo.setDecoderAttached(buffered); + } + gen.writeString(buffered); + } else { + gen.writeString(classToString(clz)); + } } catch (IOException e) { FSTUtil.rethrow(e); } @@ -318,8 +356,14 @@ public void writeAttributeName(FSTClazzInfo.FSTFieldInfo subInfo) { try { if ( gen.getOutputContext().inArray() ) gen.writeString(subInfo.getName()); - else - gen.writeFieldName(subInfo.getName()); + else { + SerializedString bufferedName = (SerializedString) subInfo.getBufferedName(); + if ( bufferedName == null ) { + bufferedName = new SerializedString(subInfo.getName()); + subInfo.setBufferedName(bufferedName); + } + gen.writeFieldName(bufferedName); + } } catch (IOException e) { FSTUtil.rethrow(e); } diff --git a/src/main/java/org/nustaq/serialization/coders/FSTMinBinEncoder.java b/src/main/java/org/nustaq/serialization/coders/FSTMinBinEncoder.java index a3b7030b..9633b96b 100644 --- a/src/main/java/org/nustaq/serialization/coders/FSTMinBinEncoder.java +++ b/src/main/java/org/nustaq/serialization/coders/FSTMinBinEncoder.java @@ -193,7 +193,7 @@ public void writeClass(FSTClazzInfo clInf) { @Override public void writeAttributeName(FSTClazzInfo.FSTFieldInfo subInfo) { - byte[] bufferedName = subInfo.getBufferedName(); + byte[] bufferedName = (byte[]) subInfo.getBufferedName(); if ( bufferedName != null ) { out.writeRaw(bufferedName,0,bufferedName.length); } else {