summaryrefslogtreecommitdiff
path: root/lang/src/main/java/net/openhft/lang/io/serialization
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2016-08-03 10:17:09 +0200
committerEmmanuel Bourg <ebourg@apache.org>2016-08-03 10:17:09 +0200
commit3d9b009255ffd897a9bd84ca3977cd3f553da8ef (patch)
tree13a8296e2989ff8da3fc50d335fd48b2dd0c6064 /lang/src/main/java/net/openhft/lang/io/serialization
parentb2ec1a2d459cfef3ff13133c1f7f5972e3740258 (diff)
Imported Upstream version 6.7.6
Diffstat (limited to 'lang/src/main/java/net/openhft/lang/io/serialization')
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallable.java22
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallableSerializer.java196
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshaller.java49
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallerFactory.java26
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/CompactBytesMarshaller.java35
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/JDKObjectSerializer.java38
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/JDKZObjectSerializer.java71
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/ObjectFactory.java23
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/ObjectSerializer.java65
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/RawCopier.java104
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationFilter.java29
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationMetadata.java89
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/direct/FieldMetadata.java22
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/direct/Introspect.java63
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshaller.java50
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshallers.java72
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/AllocateInstanceObjectFactory.java68
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferMarshaller.java71
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferZMarshaller.java103
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/BytesMarshallableMarshaller.java72
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/ClassMarshaller.java46
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/CollectionMarshaller.java72
-rwxr-xr-x[-rw-r--r--]lang/src/main/java/net/openhft/lang/io/serialization/impl/CompactEnumBytesMarshaller.java24
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/DateMarshaller.java43
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/EnumBytesMarshaller.java46
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/ExternalizableMarshaller.java65
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/GenericEnumMarshaller.java49
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/ImmutableMarshaller.java29
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/ListMarshaller.java57
-rwxr-xr-xlang/src/main/java/net/openhft/lang/io/serialization/impl/MapMarshaller.java75
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/NewInstanceObjectFactory.java62
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/NoMarshaller.java27
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/NoObjectFactory.java37
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/NullObjectFactory.java40
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/SetMarshaller.java55
-rwxr-xr-xlang/src/main/java/net/openhft/lang/io/serialization/impl/SnappyStringMarshaller.java208
-rwxr-xr-xlang/src/main/java/net/openhft/lang/io/serialization/impl/StringBuilderPool.java33
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/StringMarshaller.java46
-rwxr-xr-xlang/src/main/java/net/openhft/lang/io/serialization/impl/StringZMapMarshaller.java121
-rw-r--r--lang/src/main/java/net/openhft/lang/io/serialization/impl/VanillaBytesMarshallerFactory.java85
40 files changed, 1828 insertions, 660 deletions
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallable.java b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallable.java
index a92b316..5ac643e 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallable.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallable.java
@@ -1,23 +1,23 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization;
import net.openhft.lang.io.Bytes;
-import org.jetbrains.annotations.NotNull;
+import net.openhft.lang.model.constraints.NotNull;
/**
* Integrated marshaller for objects.
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallableSerializer.java b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallableSerializer.java
new file mode 100644
index 0000000..d68e355
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallableSerializer.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization;
+
+import net.openhft.lang.io.AbstractBytes;
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.NativeBytes;
+import net.openhft.lang.io.serialization.impl.NoMarshaller;
+import net.openhft.lang.io.serialization.impl.StringBuilderPool;
+import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.pool.EnumInterner;
+
+import java.io.Externalizable;
+import java.io.IOException;
+
+/**
+ * An extension of built-in Java serialization, featuring special treatment of {@link
+ * BytesMarshallable} objects, compact {@link String} encoding and support of pluggable custom
+ * serializers for arbitrary classes.
+ *
+ * <p>{@code BytesMarshallableSerializer} could benefit if objects (either top-level serialized or
+ * nested fields) implement {@link BytesMarshallable} interface the same way as built-in
+ * serialization benefit if objects implement {@link Externalizable} (of cause, {@code
+ * BytesMarshallableSerializer} supports {@code Externalizable} too).
+ *
+ * <p>{@link CharSequence}s, including {@code String}s (either top-level serialized or nested
+ * fields) are serialized in UTF-8 encoding.
+ *
+ * <p>Custom per-class serializers are held by {@link BytesMarshallerFactory}, which could be
+ * passed via constructor or static factory {@link #create create()} method.
+ *
+ * @see #create(BytesMarshallerFactory, ObjectSerializer)
+ */
+public class BytesMarshallableSerializer implements ObjectSerializer {
+ private static final long serialVersionUID = 0L;
+
+ private static final byte NULL = 'N';
+ private static final byte ENUMED = 'E';
+ private static final byte SERIALIZED = 'S';
+ private static final StringBuilderPool SBP = new StringBuilderPool();
+
+ private final BytesMarshallerFactory bytesMarshallerFactory;
+ private final ObjectSerializer objectSerializer;
+
+ protected BytesMarshallableSerializer(BytesMarshallerFactory bytesMarshallerFactory, ObjectSerializer objectSerializer) {
+ this.bytesMarshallerFactory = bytesMarshallerFactory;
+ this.objectSerializer = objectSerializer;
+ }
+
+ @Override
+ public void writeSerializable(Bytes bytes, Object object, Class expectedClass) throws IOException {
+ if (object == null) {
+ bytes.writeByte(NULL);
+ return;
+ }
+ if (expectedClass != null) {
+ if (BytesMarshallable.class.isAssignableFrom(expectedClass)) {
+ ((BytesMarshallable) object).writeMarshallable(bytes);
+ return;
+
+ } else if (Externalizable.class.isAssignableFrom(expectedClass)) {
+ ((Externalizable) object).writeExternal(bytes);
+ return;
+
+ } else if (CharSequence.class.isAssignableFrom(expectedClass)) {
+ bytes.writeUTFΔ((CharSequence) object);
+ return;
+
+ } else if (Enum.class.isAssignableFrom(expectedClass)) {
+ bytes.write8bitText(object.toString());
+ return;
+ }
+ }
+ writeSerializable2(bytes, object);
+ }
+
+ private void writeSerializable2(Bytes bytes, Object object) throws IOException {
+ Class<?> clazz = object.getClass();
+ BytesMarshaller em = bytesMarshallerFactory.acquireMarshaller(clazz, false);
+ if (em == NoMarshaller.INSTANCE && autoGenerateMarshaller(object))
+ em = bytesMarshallerFactory.acquireMarshaller(clazz, true);
+
+ if (em != NoMarshaller.INSTANCE) {
+ if (em instanceof CompactBytesMarshaller) {
+ bytes.writeByte(((CompactBytesMarshaller) em).code());
+ em.write(bytes, object);
+ return;
+ }
+ bytes.writeByte(ENUMED);
+ this.writeSerializable(bytes, clazz, Class.class);
+ em.write(bytes, object);
+ return;
+ }
+ bytes.writeByte(SERIALIZED);
+ // TODO this is the lame implementation, but it works.
+ objectSerializer.writeSerializable(bytes, object, null);
+ }
+
+ static boolean autoGenerateMarshaller(Object obj) {
+ return (obj instanceof Comparable && obj.getClass().getPackage().getName().startsWith("java"))
+ || obj instanceof Externalizable
+ || obj instanceof BytesMarshallable;
+ }
+
+ @Override
+ public <T> T readSerializable(@NotNull Bytes bytes, Class<T> expectedClass, T object) throws IOException, ClassNotFoundException {
+ if (expectedClass != null) {
+ try {
+ if (BytesMarshallable.class.isAssignableFrom(expectedClass)) {
+ return readBytesMarshallable(bytes, expectedClass, object);
+
+ } else if (Externalizable.class.isAssignableFrom(expectedClass)) {
+ return readExternalizable(bytes, expectedClass, object);
+
+ } else if (CharSequence.class.isAssignableFrom(expectedClass)) {
+ return readCharSequence(bytes, object);
+
+ } else if (Enum.class.isAssignableFrom(expectedClass)) {
+ StringBuilder sb = SBP.acquireStringBuilder();
+ bytes.read8bitText(sb);
+ return (T) EnumInterner.intern((Class<Enum>) expectedClass, sb);
+ }
+ } catch (InstantiationException e) {
+ throw new IOException("Unable to create " + expectedClass, e);
+ }
+ }
+ int type = bytes.readUnsignedByteOrThrow();
+ switch (type) {
+ case AbstractBytes.END_OF_BUFFER:
+ case NULL:
+ return null;
+ case ENUMED: {
+ Class clazz = this.readSerializable(bytes, Class.class, null);
+ assert clazz != null;
+ return (T) bytesMarshallerFactory.acquireMarshaller(clazz, true).read(bytes, object);
+ }
+
+ case SERIALIZED: {
+ return objectSerializer.readSerializable(bytes, expectedClass, object);
+ }
+
+ default:
+ BytesMarshaller<Object> m = bytesMarshallerFactory.getMarshaller((byte) type);
+ if (m == null)
+ throw new IllegalStateException("Unknown type " + (char) type);
+ return (T) m.read(bytes);
+ }
+ }
+
+ private <T> T readCharSequence(Bytes bytes, T object) {
+ if (object instanceof StringBuilder) {
+ bytes.readUTFΔ(((StringBuilder) object));
+ return object;
+
+ } else {
+ return (T) bytes.readUTFΔ();
+ }
+ }
+
+ private <T> T readExternalizable(Bytes bytes, Class<T> expectedClass, T object) throws InstantiationException, IOException, ClassNotFoundException {
+ if (object == null)
+ object = (T) NativeBytes.UNSAFE.allocateInstance(expectedClass);
+ ((Externalizable) object).readExternal(bytes);
+ return object;
+ }
+
+ private <T> T readBytesMarshallable(Bytes bytes, Class<T> expectedClass, T object) throws InstantiationException {
+ if (object == null)
+ object = (T) NativeBytes.UNSAFE.allocateInstance(expectedClass);
+ ((BytesMarshallable) object).readMarshallable(bytes);
+ return object;
+ }
+
+ public static ObjectSerializer create() {
+ return create(new VanillaBytesMarshallerFactory(), JDKZObjectSerializer.INSTANCE);
+ }
+
+ public static ObjectSerializer create(BytesMarshallerFactory bytesMarshallerFactory, ObjectSerializer instance) {
+ return bytesMarshallerFactory == null ? instance : new BytesMarshallableSerializer(bytesMarshallerFactory, instance);
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshaller.java
index d9a4fa2..d2593aa 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshaller.java
@@ -1,45 +1,60 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization;
import net.openhft.lang.io.Bytes;
-import org.jetbrains.annotations.Nullable;
+import net.openhft.lang.model.constraints.Nullable;
+
+import java.io.Serializable;
/**
- * External marshaller for classes.
+ * External marshaller for classes. From design patterns point of view, this interface
+ * is marshalling <i>strategy</i>.
*
* @author peter.lawrey
* @see BytesMarshallable
*/
-public interface BytesMarshaller<E> {
+public interface BytesMarshaller<E> extends Serializable {
+
/**
- * write the object out as bytes.
+ * Write the object out to the {@code bytes}.
*
* @param bytes to write to
- * @param e to write
+ * @param e the object to write
*/
void write(Bytes bytes, E e);
/**
- * Read bytes and obtain an object
+ * Reads and returns an object from {@code bytes}.
*
* @param bytes to read
- * @return the object
+ * @return the read object
*/
@Nullable
E read(Bytes bytes);
+
+ /**
+ * Reads and returns an object from {@code bytes}, reusing the given object, if possible.
+ *
+ * @param bytes to read
+ * @param e an object to reuse, if possible. {@code null} could be passed, in this case
+ * a new object should be allocated anyway.
+ * @return the read object
+ */
+ @Nullable
+ E read(Bytes bytes, @Nullable E e);
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallerFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallerFactory.java
index 87218b7..6814fe8 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallerFactory.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/BytesMarshallerFactory.java
@@ -1,27 +1,29 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization;
-import org.jetbrains.annotations.NotNull;
+import net.openhft.lang.model.constraints.NotNull;
+
+import java.io.Serializable;
/**
* @author peter.lawrey
*/
-public interface BytesMarshallerFactory {
+public interface BytesMarshallerFactory extends Serializable {
@NotNull
<E> BytesMarshaller<E> acquireMarshaller(@NotNull Class<E> eClass, boolean create);
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/CompactBytesMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/CompactBytesMarshaller.java
index 6ee1f87..5b8ef29 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/CompactBytesMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/CompactBytesMarshaller.java
@@ -1,17 +1,17 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization;
@@ -20,8 +20,21 @@ package net.openhft.lang.io.serialization;
* A BytesMarshaller with a byte code for the class.
*/
public interface CompactBytesMarshaller<E> extends BytesMarshaller<E> {
+ byte BYTE_BUFFER_CODE = 'B' & 31;
+ byte CLASS_CODE = 'C' & 31;
+ byte INT_CODE = 'I' & 31;
+ byte LONG_CODE = 'L' & 31;
+ byte DOUBLE_CODE = 'D' & 31;
+ byte DATE_CODE = 'T' & 31;
+ byte STRING_CODE = 'S' & 31;
+ byte STRINGZ_MAP_CODE = 'Y' & 31; // compressed string.
+ byte STRINGZ_CODE = 'Z' & 31; // compressed string.
+ byte LIST_CODE = '[';
+ byte SET_CODE = '[' & 31;
+ byte MAP_CODE = '{';
+
/**
- * the code for this marshaller
+ * @return the code for this marshaller
*/
byte code();
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/JDKObjectSerializer.java b/lang/src/main/java/net/openhft/lang/io/serialization/JDKObjectSerializer.java
new file mode 100644
index 0000000..30557fe
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/JDKObjectSerializer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.model.constraints.NotNull;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+public enum JDKObjectSerializer implements ObjectSerializer {
+ INSTANCE;
+
+ @Override
+ public void writeSerializable(Bytes bytes, Object object, Class expectedClass) throws IOException {
+ new ObjectOutputStream(bytes.outputStream()).writeObject(object);
+ }
+
+ @Override
+ public <T> T readSerializable(@NotNull Bytes bytes, Class<T> expectedClass, T object) throws IOException, ClassNotFoundException {
+ return (T) new ObjectInputStream(bytes.inputStream()).readObject();
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/JDKZObjectSerializer.java b/lang/src/main/java/net/openhft/lang/io/serialization/JDKZObjectSerializer.java
new file mode 100644
index 0000000..784e7a9
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/JDKZObjectSerializer.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.model.constraints.NotNull;
+
+import java.io.*;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+public enum JDKZObjectSerializer implements ObjectSerializer {
+ INSTANCE;
+
+ @Override
+ public void writeSerializable(Bytes bytes, Object object, Class expectedClass) throws IOException {
+ // reset the finished flag and append
+ long position = bytes.position();
+ bytes.clear();
+ bytes.position(position + 4);
+ OutputStream out = bytes.outputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(new DeflaterOutputStream(out));
+ oos.writeObject(object);
+ oos.close();
+ long length = bytes.position() - position - 4;
+ bytes.writeUnsignedInt(position, length);
+ }
+
+ @Override
+ public <T> T readSerializable(@NotNull Bytes bytes, Class<T> expectedClass, T object) throws IOException, ClassNotFoundException {
+ long length = bytes.readUnsignedInt();
+ if (length < 8 || length > Integer.MAX_VALUE)
+ throw new StreamCorruptedException("length = " + Long.toHexString(length));
+ long end = bytes.position() + length;
+ long lim = bytes.limit();
+ bytes.limit(end);
+ int magic = bytes.readUnsignedShort(bytes.position());
+ InputStream in = bytes.inputStream();
+ switch (magic) {
+ case 0xEDAC:
+ break;
+
+ case 0x9c78:
+ in = new InflaterInputStream(in);
+ break;
+ default:
+ throw new StreamCorruptedException("Unknown magic number " + Integer.toHexString(magic));
+ }
+ T t = (T) new ObjectInputStream(in).readObject();
+ bytes.limit(lim);
+ if (end != bytes.position()) {
+ System.out.println("diff: " + (end - bytes.position()));
+ bytes.position(end);
+ }
+ return t;
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/ObjectFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/ObjectFactory.java
new file mode 100644
index 0000000..40dea33
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/ObjectFactory.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization;
+
+import java.io.Serializable;
+
+public interface ObjectFactory<E> extends Serializable {
+ E create() throws InstantiationException, IllegalAccessException;
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/ObjectSerializer.java b/lang/src/main/java/net/openhft/lang/io/serialization/ObjectSerializer.java
new file mode 100644
index 0000000..7683862
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/ObjectSerializer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.model.constraints.NotNull;
+
+import java.io.*;
+
+/**
+ * Abstracts serialization implementation, which at least should be able to serialize objects that
+ * Java built-in serialization is able serialize. In other words, {@code ObjectSerializer} abstracts
+ * Java serialization re-implementations and extensions. {@link Bytes} is used as core IO interface
+ * instead of {@link InputStream} + {@link OutputStream} pair, which Java built-in serialization
+ * use. However, note that {@code Bytes} could always be converted to these old interfaces by
+ * {@link Bytes#inputStream()} and {@link Bytes#outputStream()}, if needed.
+ *
+ * <p>The default fallback implementation is Java built-in serialization itself:
+ * {@link JDKObjectSerializer}.
+ *
+ * <p>Another provided implementation is {@link BytesMarshallableSerializer}, which basically
+ * extends built-in serialization with some improvements. For example, it could benefit if objects
+ * implement {@link BytesMarshallable} interface the same way as built-in serialization benefit
+ * if objects implement {@link Externalizable}. See {@link BytesMarshallableSerializer} docs for
+ * more information.
+ *
+ * <p>This interface is supposed to be implemented to plug such third-party serialization
+ * re-implementations, as Kryo, fast-serialization, etc.
+ */
+public interface ObjectSerializer extends Serializable {
+ /**
+ * write an object
+ *
+ * @param bytes to write to
+ * @param object object to write
+ * @param expectedClass which will be provided on read, can be null
+ */
+ void writeSerializable(@NotNull Bytes bytes, Object object, Class expectedClass) throws IOException;
+
+ /**
+ * Read an object
+ *
+ * @param bytes to read
+ * @param expectedClass proved when writing, can be null
+ * @param object to populate, can be null
+ * @return object read.
+ * @throws IOException if it not possible to serialize the object
+ * @throws ClassNotFoundException if the expectedClass can not be created
+ */
+ <T> T readSerializable(@NotNull Bytes bytes, Class<T> expectedClass, T object) throws IOException, ClassNotFoundException;
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/RawCopier.java b/lang/src/main/java/net/openhft/lang/io/serialization/RawCopier.java
deleted file mode 100644
index eaf5760..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/RawCopier.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2013 Peter Lawrey
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * 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 net.openhft.lang.io.serialization;
-
-import net.openhft.lang.io.Bytes;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import static net.openhft.lang.io.NativeBytes.UNSAFE;
-
-/**
- * User: peter.lawrey Date: 22/09/13 Time: 16:51
- */
-public class RawCopier<T> {
- final int start, end;
- private final Class<T> tClass;
-
- public RawCopier(Class<T> tClass) {
- this.tClass = tClass;
- List<Field> fields = new ArrayList<Field>();
- addAllFields(fields, tClass);
- Collections.sort(fields, new Comparator<Field>() {
- @Override
- public int compare(Field o1, Field o2) {
- long off1 = UNSAFE.objectFieldOffset(o1);
- long off2 = UNSAFE.objectFieldOffset(o2);
- return Double.compare(off1, off2);
- }
- });
- start = (int) UNSAFE.objectFieldOffset(fields.get(0));
- Field lastField = null;
- for (Field field : fields) {
- if (Modifier.isTransient(field.getModifiers()) || !field.getType().isPrimitive())
- break;
- lastField = field;
- }
- end = (int) UNSAFE.objectFieldOffset(lastField) + sizeOf(lastField.getType());
-
- assert end > start : "end <= start, start: " + start + ", end: " + end;
- }
-
- public static <T> RawCopier<T> copies(Class<T> tClass) {
- return new RawCopier<T>(tClass);
- }
-
- private static int sizeOf(Class<?> type) {
- return UNSAFE.arrayIndexScale(Array.newInstance(type, 0).getClass());
- }
-
- public int start() {
- return start;
- }
-
- public int end() {
- return end;
- }
-
- public void toBytes(Object obj, Bytes bytes) {
- bytes.writeObject(obj, start, end);
- }
-
- public void fromBytes(Bytes bytes, Object obj) {
- bytes.readObject(obj, start, end);
- }
-
- public void copy(T from, T to) {
- long i;
- for (i = start; i < end - 7; i += 8) {
- UNSAFE.putLong(to, i, UNSAFE.getLong(from, i));
- }
- for (; i < end; i++) {
- UNSAFE.putByte(to, i, UNSAFE.getByte(from, i));
- }
- }
-
- private void addAllFields(List<Field> fields, Class tClass) {
- if (tClass != null && tClass != Object.class)
- addAllFields(fields, tClass.getSuperclass());
- for (Field field : tClass.getDeclaredFields()) {
- if (!Modifier.isStatic(field.getModifiers()))
- fields.add(field);
- }
- }
-}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationFilter.java b/lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationFilter.java
deleted file mode 100644
index c6b5b2e..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationFilter.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.openhft.lang.io.serialization.direct;
-
-import java.lang.reflect.Field;
-import java.util.*;
-
-import static net.openhft.lang.io.serialization.direct.FieldMetadata.*;
-
-public final class DirectSerializationFilter {
- public static List<Field> stopAtFirstIneligibleField(List<Field> fields) {
- ArrayList<Field> eligibleFields = new ArrayList<Field>();
- for (Field f : fields) {
- if (checkEligible(f)) {
- eligibleFields.add(f);
- } else {
- break;
- }
- }
-
- return eligibleFields.isEmpty() ?
- Collections.<Field>emptyList() :
- eligibleFields;
- }
-
- private static boolean checkEligible(Field f) {
- return isPrimitive(f) &&
- !isStatic(f) &&
- !isTransient(f);
- }
-} \ No newline at end of file
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationMetadata.java b/lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationMetadata.java
deleted file mode 100644
index 2fcd50c..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/direct/DirectSerializationMetadata.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package net.openhft.lang.io.serialization.direct;
-
-import net.openhft.lang.Jvm;
-
-import java.lang.reflect.Field;
-import java.util.List;
-
-import static net.openhft.lang.io.NativeBytes.UNSAFE;
-
-public class DirectSerializationMetadata {
- private static final int OBJECT_ALIGNMENT = 8;
- private static final int OBJECT_ALIGNMENT_MASK = OBJECT_ALIGNMENT - 1;
-
- static final long NATIVE_WORD_SIZE = Jvm.is64Bit() ? 8 : 4;
- static final long OOP_SIZE = UNSAFE.arrayIndexScale(Object[].class);
- static final long OBJECT_HEADER_SIZE = NATIVE_WORD_SIZE + OOP_SIZE; // Object header has a native sized mark word + variable sized oop to klass meta object
-
- public static final SerializationMetadata EmptyObjectMetadata = new SerializationMetadata(0, 0);
-
- public static final class SerializationMetadata {
- final long start;
- final long length;
-
- SerializationMetadata(long start, long length) {
- this.start = start;
- this.length = length;
- }
-
- @Override
- public String toString() {
- return String.format("SerializationMetadata: Start %s Length %s", start, length);
- }
- }
-
- public static SerializationMetadata extractMetadata(List<Field> fields) {
- if (fields.isEmpty()) return EmptyObjectMetadata;
-
- Offsets offsets = minMaxOffsets(fields);
-
- long totalSize = OBJECT_HEADER_SIZE + offsets.max - offsets.min + 1;
- return new SerializationMetadata(offsets.min, padToObjectAlignment(totalSize) - OBJECT_HEADER_SIZE);
- }
-
- public static SerializationMetadata extractMetadataForPartialCopy(List<Field> fields) {
- if (fields.isEmpty()) return EmptyObjectMetadata;
-
- Offsets offsets = minMaxOffsets(fields);
-
- Field lastField = fields.get(fields.size() - 1);
-
- return new SerializationMetadata(offsets.min, offsets.max + sizeOf(lastField) - OBJECT_HEADER_SIZE);
- }
-
- private static Offsets minMaxOffsets(List<Field> fields) {
- long minOffset = UNSAFE.objectFieldOffset(fields.get(0));
- long maxOffset = UNSAFE.objectFieldOffset(fields.get(fields.size() - 1));
-
- return new Offsets(minOffset, maxOffset);
- }
-
- static long padToObjectAlignment(long length) {
- if ((length & OBJECT_ALIGNMENT_MASK) != 0) {
- long padding = OBJECT_ALIGNMENT - (length & OBJECT_ALIGNMENT_MASK);
- length += padding;
- }
-
- return length;
- }
-
- private static long sizeOf(Field field) {
- if (boolean.class.equals(field.getType())) return 1;
- else if (byte.class.equals(field.getType())) return 1;
- else if (short.class.equals(field.getType())) return 2;
- else if (char.class.equals(field.getType())) return 2;
- else if (int.class.equals(field.getType())) return 4;
- else if (float.class.equals(field.getType())) return 4;
- else return 8;
- }
-
- private static final class Offsets {
- public final long min;
- public final long max;
-
- private Offsets(long min, long max) {
- this.min = min;
- this.max = max;
- }
- }
-} \ No newline at end of file
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/direct/FieldMetadata.java b/lang/src/main/java/net/openhft/lang/io/serialization/direct/FieldMetadata.java
deleted file mode 100644
index d186c77..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/direct/FieldMetadata.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package net.openhft.lang.io.serialization.direct;
-
-import java.lang.reflect.*;
-
-public final class FieldMetadata {
- public static boolean isPrimitive(Field f) {
- return f.getType().isPrimitive();
- }
-
- public static boolean isPrimitiveArray(Field f) {
- Class<?> clazz = f.getType();
- return clazz.isArray() && clazz.getComponentType().isPrimitive();
- }
-
- public static boolean isStatic(Field f) {
- return Modifier.isStatic(f.getModifiers());
- }
-
- public static boolean isTransient(Field f) {
- return Modifier.isTransient(f.getModifiers());
- }
-}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/direct/Introspect.java b/lang/src/main/java/net/openhft/lang/io/serialization/direct/Introspect.java
deleted file mode 100644
index 28ff782..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/direct/Introspect.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2013 Peter Lawrey
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * 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 net.openhft.lang.io.serialization.direct;
-
-import net.openhft.lang.Maths;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import static net.openhft.lang.io.NativeBytes.UNSAFE;
-import static net.openhft.lang.io.serialization.direct.FieldMetadata.isStatic;
-
-public class Introspect {
- public static List<Field> fields(Class<?> clazz) {
- ArrayList<Field> fields = new ArrayList<Field>();
-
- addToFields(clazz, fields);
- Collections.sort(fields, FieldOffsetComparator.Instance);
-
- return fields;
- }
-
- private static List<Field> addToFields(Class<?> clazz, ArrayList<Field> accumulator) {
- Collections.addAll(accumulator, clazz.getDeclaredFields());
- Class<?> maybeSuper = clazz.getSuperclass();
-
- return maybeSuper != null ?
- addToFields(maybeSuper, accumulator) :
- accumulator;
- }
-
- private static final class FieldOffsetComparator implements Comparator<Field> {
- public static final FieldOffsetComparator Instance = new FieldOffsetComparator();
-
- @Override
- public int compare(Field first, Field second) {
- return Maths.compare(offset(first), offset(second));
- }
-
- private static long offset(Field field) {
- return isStatic(field) ?
- UNSAFE.staticFieldOffset(field) :
- UNSAFE.objectFieldOffset(field);
- }
- }
-} \ No newline at end of file
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshaller.java
deleted file mode 100644
index 24f8a48..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshaller.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package net.openhft.lang.io.serialization.direct;
-
-import net.openhft.lang.io.Bytes;
-
-import static net.openhft.lang.io.NativeBytes.UNSAFE;
-import static net.openhft.lang.io.serialization.direct.DirectSerializationMetadata.SerializationMetadata;
-
-public final class ObjectMarshaller<T> {
- private final SerializationMetadata metadata;
-
- public ObjectMarshaller(SerializationMetadata metadata) {
- this.metadata = metadata;
- }
-
- public void write(Bytes bytes, T tObject) {
- long i = metadata.start;
- long end = metadata.start + metadata.length;
-
- while (i < end - 7) {
- bytes.writeLong(UNSAFE.getLong(tObject, i));
- i += 8;
- }
-
- while (i < end) {
- bytes.writeByte(UNSAFE.getByte(tObject, i));
- ++i;
- }
- }
-
- public T read(Bytes bytes, T tObject) {
- long i = metadata.start;
- long end = metadata.start + metadata.length;
-
- while (i < end - 7) {
- UNSAFE.putLong(tObject, i, bytes.readLong());
- i += 8;
- }
-
- while (i < end) {
- UNSAFE.putByte(tObject, i, bytes.readByte());
- ++i;
- }
-
- return tObject;
- }
-
- public long length() {
- return metadata.length;
- }
-} \ No newline at end of file
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshallers.java b/lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshallers.java
deleted file mode 100644
index bb9e35d..0000000
--- a/lang/src/main/java/net/openhft/lang/io/serialization/direct/ObjectMarshallers.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package net.openhft.lang.io.serialization.direct;
-
-import net.openhft.lang.io.NativeBytes;
-
-import java.lang.reflect.Field;
-import java.util.*;
-import java.util.logging.Logger;
-
-import static java.util.logging.Level.WARNING;
-import static net.openhft.lang.io.serialization.direct.DirectSerializationMetadata.SerializationMetadata;
-
-public final class ObjectMarshallers {
- private static final Logger Log = Logger.getLogger(ObjectMarshallers.class.getName());
-
- private static final Map<Class, ObjectMarshaller> metadata = new HashMap<Class, ObjectMarshaller>();
-
- @SuppressWarnings("unchecked")
- public static <T> ObjectMarshaller<T> forClass(Class<T> clazz) {
- ObjectMarshaller om = metadata.get(clazz);
- if (om == null) {
- List<Field> fields = Introspect.fields(clazz);
- List<Field> eligibleFields = DirectSerializationFilter.stopAtFirstIneligibleField(fields);
-
- SerializationMetadata serializationMetadata;
-
- if (hasIneligibleFields(fields, eligibleFields)) {
- WarnAboutIneligibleFields.apply(clazz, fields, eligibleFields);
- serializationMetadata = DirectSerializationMetadata.extractMetadataForPartialCopy(eligibleFields);
- } else {
- serializationMetadata = DirectSerializationMetadata.extractMetadata(eligibleFields);
- }
-
- om = new ObjectMarshaller<T>(serializationMetadata);
- Log.log(WARNING, String.format("Class %s has metadata %s", clazz.getName(), serializationMetadata));
- metadata.put(clazz, om);
- }
-
- return (ObjectMarshaller<T>) om;
- }
-
- private static boolean hasIneligibleFields(List<Field> allFields, List<Field> eligibleFields) {
- return allFields.size() != eligibleFields.size();
- }
-
- private static class WarnAboutIneligibleFields {
- static void apply(Class clazz, List<Field> allFields, List<Field> eligibleFields) {
- List<Field> ineligibleFields = allFields.subList(eligibleFields.size(), allFields.size());
- Log.log(WARNING, String.format(
- "The following fields in Class %s will not be copied by ObjectMarshaller:\n%s",
- clazz.getName(),
- commaSeparate(ineligibleFields)
- ));
- }
-
- private static String commaSeparate(Collection<Field> fields) {
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for (Field field : fields) {
- if (first) {
- sb.append("\t");
- sb.append(field.getName());
- first = false;
- } else {
- sb.append("\n\t");
- sb.append(field.getName());
- }
- }
-
- return sb.toString();
- }
- }
-}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/AllocateInstanceObjectFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/AllocateInstanceObjectFactory.java
new file mode 100644
index 0000000..70ac6f7
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/AllocateInstanceObjectFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.NativeBytes;
+import net.openhft.lang.io.serialization.ObjectFactory;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Object factory which creates an object by means of {@code Unsafe.allocateInstance()} call,
+ * i. e. without calling constructor.
+ *
+ * @param <E> type of created objects
+ */
+public final class AllocateInstanceObjectFactory<E> implements ObjectFactory<E> {
+ private static final long serialVersionUID = 0L;
+
+ private final Class<E> eClass;
+
+ public AllocateInstanceObjectFactory(Class<E> eClass) {
+ if (eClass.isInterface() || Modifier.isAbstract(eClass.getModifiers()) ||
+ eClass.isEnum()) {
+ throw new IllegalArgumentException(eClass + " should be a non-abstract non-enum class");
+ }
+ this.eClass = eClass;
+ }
+
+ public Class<E> allocatedClass() {
+ return eClass;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E create() throws InstantiationException {
+ return (E) NativeBytes.UNSAFE.allocateInstance(eClass);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass() == getClass() &&
+ ((AllocateInstanceObjectFactory) obj).eClass == eClass;
+ }
+
+ @Override
+ public int hashCode() {
+ return eClass.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{eClass=" + eClass + "}";
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferMarshaller.java
new file mode 100644
index 0000000..ac4051f
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferMarshaller.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+
+import java.nio.ByteBuffer;
+
+public enum ByteBufferMarshaller implements CompactBytesMarshaller<ByteBuffer> {
+ INSTANCE;
+
+ @Override
+ public byte code() {
+ return BYTE_BUFFER_CODE;
+ }
+
+ @Override
+ public void write(Bytes bytes, ByteBuffer byteBuffer) {
+ int position = byteBuffer.position();
+ bytes.writeStopBit(byteBuffer.remaining());
+ bytes.write(byteBuffer);
+
+ // reset the position back as we found it
+ byteBuffer.position(position);
+ }
+
+ @Override
+ public ByteBuffer read(Bytes bytes) {
+ return read(bytes, null);
+ }
+
+ @Override
+ public ByteBuffer read(Bytes bytes, @Nullable ByteBuffer byteBuffer) {
+ long length = bytes.readStopBit();
+ assert length <= Integer.MAX_VALUE;
+ if (length < 0 || length > Integer.MAX_VALUE) {
+ throw new IllegalStateException("Invalid length: " + length);
+ }
+ if (byteBuffer == null || byteBuffer.capacity() < length) {
+ byteBuffer = newByteBuffer((int) length);
+
+ } else {
+ byteBuffer.position(0);
+ byteBuffer.limit((int) length);
+ }
+
+ bytes.read(byteBuffer);
+ byteBuffer.flip();
+ return byteBuffer;
+ }
+
+ protected ByteBuffer newByteBuffer(int length) {
+ return ByteBuffer.allocate(length);
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferZMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferZMarshaller.java
new file mode 100644
index 0000000..fe648e9
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ByteBufferZMarshaller.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+public enum ByteBufferZMarshaller implements CompactBytesMarshaller<ByteBuffer> {
+ INSTANCE;
+
+ @Override
+ public byte code() {
+ return BYTE_BUFFER_CODE;
+ }
+
+ @Override
+ public void write(Bytes bytes, ByteBuffer byteBuffer) {
+ bytes.writeStopBit(byteBuffer.remaining());
+ long position = bytes.position();
+ bytes.clear();
+ bytes.position(position + 4);
+ DataOutputStream dos = new DataOutputStream(new DeflaterOutputStream(bytes.outputStream()));
+ try {
+ while (byteBuffer.remaining() >= 8)
+ dos.writeLong(byteBuffer.getLong());
+ while (byteBuffer.remaining() > 0)
+ dos.write(byteBuffer.get());
+ dos.close();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ bytes.writeUnsignedInt(position, bytes.position() - position - 4);
+
+ bytes.write(byteBuffer);
+ }
+
+ @Override
+ public ByteBuffer read(Bytes bytes) {
+ return read(bytes, null);
+ }
+
+ @Override
+ public ByteBuffer read(Bytes bytes, @Nullable ByteBuffer byteBuffer) {
+ long length = bytes.readStopBit();
+ if (length < 0 || length > Integer.MAX_VALUE) {
+ throw new IllegalStateException("Invalid length: " + length);
+ }
+ if (byteBuffer == null || byteBuffer.capacity() < length) {
+ byteBuffer = newByteBuffer((int) length);
+
+ } else {
+ byteBuffer.clear();
+ }
+ byteBuffer.limit((int) length);
+
+ long position = bytes.position();
+ long end = position + length;
+
+ long limit = bytes.limit();
+ bytes.limit(end);
+
+ DataInputStream dis = new DataInputStream(new InflaterInputStream(bytes.inputStream()));
+ try {
+ while (byteBuffer.remaining() >= 8)
+ byteBuffer.putLong(dis.readLong());
+ while (byteBuffer.remaining() >= 0)
+ byteBuffer.put(dis.readByte());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ bytes.position(end);
+ bytes.limit(limit);
+
+ byteBuffer.flip();
+ return byteBuffer;
+ }
+
+ protected ByteBuffer newByteBuffer(int length) {
+ return ByteBuffer.allocate(length);
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/BytesMarshallableMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/BytesMarshallableMarshaller.java
index ebcb95f..59ea161 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/BytesMarshallableMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/BytesMarshallableMarshaller.java
@@ -1,31 +1,34 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.NativeBytes;
import net.openhft.lang.io.serialization.BytesMarshallable;
import net.openhft.lang.io.serialization.BytesMarshaller;
-import net.openhft.lang.io.NativeBytes;
-import org.jetbrains.annotations.NotNull;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
/**
* @author peter.lawrey
*/
-public class BytesMarshallableMarshaller<E extends BytesMarshallable> implements BytesMarshaller<E> {
+public class BytesMarshallableMarshaller<E extends BytesMarshallable>
+ implements BytesMarshaller<E> {
+ private static final long serialVersionUID = 0L;
@NotNull
private final Class<E> classMarshaled;
@@ -33,6 +36,10 @@ public class BytesMarshallableMarshaller<E extends BytesMarshallable> implements
this.classMarshaled = classMarshaled;
}
+ public final Class<E> marshaledClass() {
+ return classMarshaled;
+ }
+
@Override
public void write(@NotNull Bytes bytes, @NotNull E e) {
e.writeMarshallable(bytes);
@@ -40,13 +47,42 @@ public class BytesMarshallableMarshaller<E extends BytesMarshallable> implements
@Override
public E read(@NotNull Bytes bytes) {
- E e;
- try {
- e = (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
- } catch (Exception e2) {
- throw new IllegalStateException(e2);
+ return read(bytes, null);
+ }
+
+ @Nullable
+ @Override
+ public E read(Bytes bytes, @Nullable E e) {
+ if (e == null) {
+ try {
+ e = getInstance();
+ } catch (Exception e2) {
+ throw new IllegalStateException(e2);
+ }
}
e.readMarshallable(bytes);
return e;
}
+
+ @SuppressWarnings("unchecked")
+ @NotNull
+ protected E getInstance() throws Exception {
+ return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass() == getClass() &&
+ ((BytesMarshallableMarshaller) obj).classMarshaled == classMarshaled;
+ }
+
+ @Override
+ public int hashCode() {
+ return classMarshaled.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{classMarshaled=" + classMarshaled + "}";
+ }
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ClassMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ClassMarshaller.java
index db36c37..92be9bd 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ClassMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ClassMarshaller.java
@@ -1,17 +1,17 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
@@ -19,8 +19,9 @@ package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.Compare;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.CompactBytesMarshaller;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
+import net.openhft.lang.pool.StringInterner;
import java.lang.ref.WeakReference;
import java.math.BigDecimal;
@@ -32,7 +33,8 @@ import java.util.Map;
/**
* @author peter.lawrey
*/
-public class ClassMarshaller implements CompactBytesMarshaller<Class> {
+public class ClassMarshaller extends ImmutableMarshaller<Class>
+ implements CompactBytesMarshaller<Class> {
private static final int CACHE_SIZE = 1019;
private static final Map<String, Class> SC_SHORT_NAME = new LinkedHashMap<String, Class>();
private static final Map<Class, String> CS_SHORT_NAME = new LinkedHashMap<Class, String>();
@@ -48,7 +50,7 @@ public class ClassMarshaller implements CompactBytesMarshaller<Class> {
}
private final ClassLoader classLoader;
- private final StringBuilder className = new StringBuilder(40);
+ private static final StringBuilderPool sbp = new StringBuilderPool();
@Nullable
@SuppressWarnings("unchecked")
private WeakReference<Class>[] classWeakReference = null;
@@ -68,9 +70,9 @@ public class ClassMarshaller implements CompactBytesMarshaller<Class> {
@Nullable
@Override
public Class read(@NotNull Bytes bytes) {
- className.setLength(0);
- bytes.readUTFΔ(className);
- return load(className);
+ StringBuilder sb = sbp.acquireStringBuilder();
+ bytes.readUTFΔ(sb);
+ return load(sb);
}
@Nullable
@@ -82,15 +84,16 @@ public class ClassMarshaller implements CompactBytesMarshaller<Class> {
WeakReference<Class> ref = classWeakReference[hash];
if (ref != null) {
Class clazz = ref.get();
- if (clazz != null && clazz.getName().equals(name))
+ if (clazz != null && StringInterner.isEqual(clazz.getName(), name))
return clazz;
}
try {
- Class<?> clazz = SC_SHORT_NAME.get(name.toString());
+ String className = name.toString();
+ Class<?> clazz = SC_SHORT_NAME.get(className);
if (clazz != null)
return clazz;
- clazz = classLoader.loadClass(name.toString());
+ clazz = classLoader.loadClass(className);
classWeakReference[hash] = new WeakReference<Class>(clazz);
return clazz;
} catch (ClassNotFoundException e) {
@@ -100,6 +103,7 @@ public class ClassMarshaller implements CompactBytesMarshaller<Class> {
@Override
public byte code() {
- return 'C' & 31; // control C
+ return CLASS_CODE; // control C
}
}
+ \ No newline at end of file
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/CollectionMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/CollectionMarshaller.java
new file mode 100644
index 0000000..dbf8f53
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/CollectionMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+
+import java.util.Collection;
+
+abstract class CollectionMarshaller<E, C extends Collection<E>> {
+
+ public static final int NULL_LENGTH = -1;
+ final BytesMarshaller<E> eBytesMarshaller;
+
+ protected CollectionMarshaller(BytesMarshaller<E> eBytesMarshaller) {
+ this.eBytesMarshaller = eBytesMarshaller;
+ }
+
+ public void write(Bytes bytes, C c) {
+ if (c == null) {
+ bytes.writeStopBit(NULL_LENGTH);
+ return;
+ }
+ bytes.writeStopBit(c.size());
+ for (E e : c) {
+ eBytesMarshaller.write(bytes, e);
+ }
+ }
+
+ public C read(Bytes bytes) {
+ return read(bytes, null);
+ }
+
+ abstract C newCollection();
+
+ public C read(Bytes bytes, @Nullable C c) {
+ long length = bytes.readStopBit();
+
+ if (length == 0 && c != null) {
+ c.clear();
+ return c;
+ }
+
+ if (length < NULL_LENGTH || length > Integer.MAX_VALUE)
+ throw new IllegalStateException("Invalid length: " + length);
+
+ if (length == NULL_LENGTH)
+ return null;
+
+ if (c == null)
+ c = newCollection();
+
+ return readCollection(bytes, c, (int) length);
+ }
+
+ abstract C readCollection(Bytes bytes, C c, int length);
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/CompactEnumBytesMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/CompactEnumBytesMarshaller.java
index 08f66e4..676c86c 100644..100755
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/CompactEnumBytesMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/CompactEnumBytesMarshaller.java
@@ -1,26 +1,26 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.serialization.CompactBytesMarshaller;
-import org.jetbrains.annotations.NotNull;
+import net.openhft.lang.model.constraints.NotNull;
/**
- * Created with IntelliJ IDEA. User: peter Date: 09/12/13 Time: 17:05 To change this template use File | Settings | File
+ * Created with IntelliJ IDEA. User: peter.lawrey Date: 09/12/13 Time: 17:05
* Templates.
*/
public class CompactEnumBytesMarshaller<E> extends GenericEnumMarshaller<E> implements CompactBytesMarshaller<E> {
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/DateMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/DateMarshaller.java
index 03f6bb1..1e949c5 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/DateMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/DateMarshaller.java
@@ -1,25 +1,25 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.CompactBytesMarshaller;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
import java.util.Date;
@@ -27,8 +27,8 @@ import java.util.Date;
* @author peter.lawrey
*/
public class DateMarshaller implements CompactBytesMarshaller<Date> {
- final int size1;
- private final StringBuilder sb = new StringBuilder();
+ private final int size1;
+ private static final StringBuilderPool sbp = new StringBuilderPool();
@Nullable
private Date[] interner = null;
@@ -65,12 +65,25 @@ public class DateMarshaller implements CompactBytesMarshaller<Date> {
@Nullable
@Override
public Date read(@NotNull Bytes bytes) {
+ StringBuilder sb = sbp.acquireStringBuilder();
bytes.readUTFΔ(sb);
long time = parseLong(sb);
return lookupDate(time);
}
@Nullable
+ @Override
+ public Date read(Bytes bytes, @Nullable Date date) {
+ if (date == null)
+ return read(bytes);
+ StringBuilder sb = sbp.acquireStringBuilder();
+ bytes.readUTFΔ(sb);
+ long time = parseLong(sb);
+ date.setTime(time);
+ return date;
+ }
+
+ @Nullable
private Date lookupDate(long time) {
int idx = hashFor(time);
if (interner == null)
@@ -90,6 +103,6 @@ public class DateMarshaller implements CompactBytesMarshaller<Date> {
@Override
public byte code() {
- return 'T' & 31; // Control T.
+ return DATE_CODE; // Control T.
}
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/EnumBytesMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/EnumBytesMarshaller.java
index 11f060b..189f7f5 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/EnumBytesMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/EnumBytesMarshaller.java
@@ -1,25 +1,25 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.BytesMarshaller;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
import java.util.BitSet;
import java.util.LinkedHashMap;
@@ -28,19 +28,17 @@ import java.util.Map;
/**
* @author peter.lawrey
*/
-public class EnumBytesMarshaller<E extends Enum<E>> implements BytesMarshaller<E> {
- @NotNull
- private final Class<E> classMarshaled;
+public class EnumBytesMarshaller<E extends Enum<E>> extends ImmutableMarshaller<E>
+ implements BytesMarshaller<E> {
@SuppressWarnings("unchecked")
private final E[] interner = (E[]) new Enum[1024];
private final BitSet internerDup = new BitSet(1024);
- private final Map<String, E> map = new LinkedHashMap<String, E>();
+ private final Map<String, E> map = new LinkedHashMap<String, E>(64);
private final E defaultValue;
private final int mask;
- private final StringBuilder reader = new StringBuilder();
+ private static final StringBuilderPool sbp = new StringBuilderPool();
public EnumBytesMarshaller(@NotNull Class<E> classMarshaled, E defaultValue) {
- this.classMarshaled = classMarshaled;
this.defaultValue = defaultValue;
mask = interner.length - 1;
@@ -52,6 +50,7 @@ public class EnumBytesMarshaller<E extends Enum<E>> implements BytesMarshaller<E
//noinspection UnqualifiedFieldAccess,AssignmentToNull
interner[idx] = null;
internerDup.set(idx);
+
} else {
interner[idx] = e;
}
@@ -77,17 +76,18 @@ public class EnumBytesMarshaller<E extends Enum<E>> implements BytesMarshaller<E
@Override
public E read(@NotNull Bytes bytes) {
- bytes.readUTFΔ(reader);
- return builderToEnum();
+ StringBuilder sb = sbp.acquireStringBuilder();
+ bytes.readUTFΔ(sb);
+ return builderToEnum(sb);
}
- private E builderToEnum() {
- int num = hashFor(reader);
+ private E builderToEnum(StringBuilder sb) {
+ int num = hashFor(sb);
int idx = num & mask;
E e = interner[idx];
if (e != null) return e;
if (!internerDup.get(idx)) return defaultValue;
- e = map.get(reader.toString());
+ e = map.get(sb.toString());
return e == null ? defaultValue : e;
}
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ExternalizableMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ExternalizableMarshaller.java
index 05f5390..4e9b82c 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ExternalizableMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ExternalizableMarshaller.java
@@ -1,25 +1,26 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
-import net.openhft.lang.io.serialization.BytesMarshaller;
import net.openhft.lang.io.NativeBytes;
-import org.jetbrains.annotations.NotNull;
+import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
import java.io.Externalizable;
import java.io.IOException;
@@ -28,6 +29,8 @@ import java.io.IOException;
* @author peter.lawrey
*/
public class ExternalizableMarshaller<E extends Externalizable> implements BytesMarshaller<E> {
+ private static final long serialVersionUID = 0L;
+
@NotNull
private final Class<E> classMarshaled;
@@ -35,6 +38,10 @@ public class ExternalizableMarshaller<E extends Externalizable> implements Bytes
this.classMarshaled = classMarshaled;
}
+ public final Class<E> marshaledClass() {
+ return classMarshaled;
+ }
+
@Override
public void write(Bytes bytes, @NotNull E e) {
try {
@@ -46,13 +53,41 @@ public class ExternalizableMarshaller<E extends Externalizable> implements Bytes
@Override
public E read(Bytes bytes) {
- E e;
+ return read(bytes, null);
+ }
+
+ @Nullable
+ @Override
+ public E read(Bytes bytes, @Nullable E e) {
try {
- e = (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
+ if (e == null)
+ e = getInstance();
e.readExternal(bytes);
+ return e;
} catch (Exception e2) {
throw new IllegalStateException(e2);
}
- return e;
+ }
+
+ @SuppressWarnings("unchecked")
+ @NotNull
+ protected E getInstance() throws Exception {
+ return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass() == getClass() &&
+ ((ExternalizableMarshaller) obj).classMarshaled == classMarshaled;
+ }
+
+ @Override
+ public int hashCode() {
+ return classMarshaled.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{marshaledClass=" + classMarshaled + "}";
}
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/GenericEnumMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/GenericEnumMarshaller.java
index 8a1b52d..8ed4590 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/GenericEnumMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/GenericEnumMarshaller.java
@@ -1,25 +1,25 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.BytesMarshaller;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@@ -30,17 +30,20 @@ import java.util.Map;
* @author peter.lawrey
*/
public class GenericEnumMarshaller<E> implements BytesMarshaller<E> {
- @NotNull
- private final Class<E> classMarshaled;
+ private final int capacity;
@Nullable
- private final Constructor<E> constructor;
+ private transient final Constructor<E> constructor;
@Nullable
- private final Method valueOf;
+ private transient final Method valueOf;
@NotNull
private final Map<String, E> map;
+ //used by the read resolve method
+ private final Class<E> classMarshaled;
+
public GenericEnumMarshaller(@NotNull Class<E> classMarshaled, final int capacity) {
this.classMarshaled = classMarshaled;
+ this.capacity = capacity;
Constructor<E> constructor = null;
Method valueOf = null;
try {
@@ -48,6 +51,7 @@ public class GenericEnumMarshaller<E> implements BytesMarshaller<E> {
} catch (NoSuchMethodException e) {
try {
constructor = classMarshaled.getConstructor(String.class);
+ constructor.setAccessible(true);
} catch (NoSuchMethodException e1) {
throw new IllegalArgumentException(classMarshaled + " doesn't have a valueOf(String) or a Constructor(String)");
}
@@ -62,6 +66,10 @@ public class GenericEnumMarshaller<E> implements BytesMarshaller<E> {
};
}
+ private Object readResolve() {
+ return new GenericEnumMarshaller(classMarshaled, capacity);
+ }
+
@Override
public void write(@NotNull Bytes bytes, @Nullable E e) {
bytes.writeUTFΔ(e == null ? null : e.toString());
@@ -74,19 +82,26 @@ public class GenericEnumMarshaller<E> implements BytesMarshaller<E> {
return s == null ? null : valueOf(s);
}
+ @Nullable
+ @Override
+ public E read(Bytes bytes, @Nullable E e) {
+ return read(bytes);
+ }
+
private E valueOf(String s) {
E e = map.get(s);
if (e == null)
try {
if (constructor != null) {
map.put(s, e = constructor.newInstance(s));
+
} else {
@SuppressWarnings("unchecked")
E invoke = (E) valueOf.invoke(null, s);
map.put(s, e = invoke);
}
} catch (Exception t) {
- throw new AssertionError(t.getCause());
+ throw new AssertionError(t);
}
return e;
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ImmutableMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ImmutableMarshaller.java
new file mode 100644
index 0000000..de55a9c
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ImmutableMarshaller.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+
+abstract class ImmutableMarshaller<E> implements BytesMarshaller<E> {
+ @Nullable
+ @Override
+ public final E read(Bytes bytes, @Nullable E e) {
+ return read(bytes);
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/ListMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ListMarshaller.java
new file mode 100644
index 0000000..cc9b592
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/ListMarshaller.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ListMarshaller<E> extends CollectionMarshaller<E, List<E>> implements CompactBytesMarshaller<List<E>> {
+
+ ListMarshaller(BytesMarshaller<E> eBytesMarshaller) {
+ super(eBytesMarshaller);
+ }
+
+ public static <E> BytesMarshaller<List<E>> of(BytesMarshaller<E> eBytesMarshaller) {
+ return new ListMarshaller<E>(eBytesMarshaller);
+ }
+
+ @Override
+ public byte code() {
+ return LIST_CODE;
+ }
+
+ @Override
+ List<E> newCollection() {
+ return new ArrayList<E>();
+ }
+
+ @Override
+ List<E> readCollection(Bytes bytes, List<E> es, int length) {
+ List<E> ret = es;
+ ret.clear();
+
+ for (int i = 0; i < length; i++) {
+ ret.add(eBytesMarshaller.read(bytes));
+ }
+
+ return ret;
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/MapMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/MapMarshaller.java
new file mode 100755
index 0000000..195d96d
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/MapMarshaller.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Created by peter.lawrey on 24/10/14.
+ */
+public class MapMarshaller<K, V> implements CompactBytesMarshaller<Map<K, V>> {
+ private final BytesMarshaller<K> kBytesMarshaller;
+ private final BytesMarshaller<V> vBytesMarshaller;
+
+ MapMarshaller(BytesMarshaller<K> kBytesMarshaller, BytesMarshaller<V> vBytesMarshaller) {
+ this.kBytesMarshaller = kBytesMarshaller;
+ this.vBytesMarshaller = vBytesMarshaller;
+ }
+
+ @Override
+ public byte code() {
+ return MAP_CODE;
+ }
+
+ @Override
+ public void write(Bytes bytes, Map<K, V> kvMap) {
+ bytes.writeInt(kvMap.size());
+ for (Map.Entry<K, V> entry : kvMap.entrySet()) {
+ kBytesMarshaller.write(bytes, entry.getKey());
+ vBytesMarshaller.write(bytes, entry.getValue());
+ }
+ }
+
+ @Override
+ public Map<K, V> read(Bytes bytes) {
+ return read(bytes, null);
+ }
+
+ @Override
+ public Map<K, V> read(Bytes bytes, @Nullable Map<K, V> kvMap) {
+ if (kvMap == null) {
+ kvMap = new LinkedHashMap<K, V>();
+
+ } else {
+ kvMap.clear();
+ }
+ int size = bytes.readInt();
+ for (int i = 0; i < size; i++)
+ kvMap.put(kBytesMarshaller.read(bytes), vBytesMarshaller.read(bytes));
+ return kvMap;
+ }
+
+ public static <K, V> BytesMarshaller<Map<K, V>> of(BytesMarshaller<K> keyMarshaller, BytesMarshaller<V> valueMarshaller) {
+ return new MapMarshaller<K, V>(keyMarshaller, valueMarshaller);
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/NewInstanceObjectFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NewInstanceObjectFactory.java
new file mode 100644
index 0000000..0fba720
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NewInstanceObjectFactory.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.serialization.ObjectFactory;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Object factory which creates an object by means of {@link Class#newInstance()} call,
+ * i. e. with calling the default no-arg constructor of the class.
+ *
+ * @param <E> type of created objects
+ */
+public final class NewInstanceObjectFactory<E> implements ObjectFactory<E> {
+ private static final long serialVersionUID = 0L;
+
+ private final Class<E> eClass;
+
+ public NewInstanceObjectFactory(Class<E> eClass) {
+ if (eClass.isInterface() || Modifier.isAbstract(eClass.getModifiers()) ||
+ eClass.isEnum()) {
+ throw new IllegalArgumentException(eClass + " should be a non-abstract non-enum class");
+ }
+ this.eClass = eClass;
+ }
+
+ @Override
+ public E create() throws IllegalAccessException, InstantiationException {
+ return eClass.newInstance();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass() == getClass() &&
+ ((NewInstanceObjectFactory) obj).eClass == eClass;
+ }
+
+ @Override
+ public int hashCode() {
+ return eClass.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{eClass=" + eClass + "}";
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoMarshaller.java
index 1369c4a..c76054c 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoMarshaller.java
@@ -1,23 +1,24 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
/**
* Created with IntelliJ IDEA. User: peter.lawrey Date: 19/09/13 Time: 18:26 To change this template use File | Settings | File
@@ -35,4 +36,10 @@ public enum NoMarshaller implements BytesMarshaller<Void> {
public Void read(Bytes bytes) {
throw new UnsupportedOperationException();
}
+
+ @Nullable
+ @Override
+ public Void read(Bytes bytes, @Nullable Void aVoid) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoObjectFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoObjectFactory.java
new file mode 100644
index 0000000..c3e061f
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NoObjectFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.serialization.ObjectFactory;
+
+/**
+ * Placeholder object factory which always throws {@code UnsupportedOperationException}.
+ */
+public enum NoObjectFactory implements ObjectFactory {
+ INSTANCE;
+
+ /**
+ * Always throws {@code UnsupportedOperationException}.
+ *
+ * @return nothing
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public Object create() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/NullObjectFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NullObjectFactory.java
new file mode 100644
index 0000000..af76bc7
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/NullObjectFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.serialization.ObjectFactory;
+
+/**
+ * Object factory which always returns {@code null}.
+ */
+public enum NullObjectFactory implements ObjectFactory {
+ INSTANCE;
+
+ public static <E> ObjectFactory<E> of() {
+ return INSTANCE;
+ }
+
+ /**
+ * Always returns {@code null}.
+ *
+ * @return {@code null}
+ */
+ @Override
+ public Object create() {
+ return null;
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/SetMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/SetMarshaller.java
new file mode 100644
index 0000000..e401722
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/SetMarshaller.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.BytesMarshaller;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class SetMarshaller<E> extends CollectionMarshaller<E, Set<E>> implements CompactBytesMarshaller<Set<E>> {
+ SetMarshaller(BytesMarshaller<E> eBytesMarshaller) {
+ super(eBytesMarshaller);
+ }
+
+ public static <E> BytesMarshaller<Set<E>> of(BytesMarshaller<E> eBytesMarshaller) {
+ return new SetMarshaller<E>(eBytesMarshaller);
+ }
+
+ @Override
+ public byte code() {
+ return SET_CODE;
+ }
+
+ @Override
+ Set<E> newCollection() {
+ return new LinkedHashSet<E>();
+ }
+
+ @Override
+ Set<E> readCollection(Bytes bytes, Set<E> es, int length) {
+ es.clear();
+
+ for (int i = 0; i < length; i++) {
+ es.add(eBytesMarshaller.read(bytes));
+ }
+
+ return es;
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/SnappyStringMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/SnappyStringMarshaller.java
new file mode 100755
index 0000000..14ff64f
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/SnappyStringMarshaller.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.ByteBufferBytes;
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+import org.xerial.snappy.Snappy;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.ByteBuffer;
+
+/**
+ * Created by peter.lawrey on 24/10/14.
+ */
+public enum SnappyStringMarshaller implements CompactBytesMarshaller<CharSequence> {
+ INSTANCE;
+ private static final StringFactory STRING_FACTORY = getStringFactory();
+
+ private static final int NULL_LENGTH = -1;
+
+ private static StringFactory getStringFactory() {
+ try {
+ return new StringFactory17();
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ try {
+ return new StringFactory16();
+ } catch (Exception e) {
+ // no more alternatives
+ throw new AssertionError(e);
+ }
+ }
+
+ private static final ThreadLocal<ThreadLocals> THREAD_LOCALS = new ThreadLocal<ThreadLocals>();
+
+ static class ThreadLocals {
+ ByteBuffer decompressedByteBuffer = ByteBuffer.allocateDirect(32 * 1024);
+ Bytes decompressedBytes = ByteBufferBytes.wrap(decompressedByteBuffer);
+ ByteBuffer compressedByteBuffer = ByteBuffer.allocateDirect(0);
+
+ public void clear() {
+ decompressedByteBuffer.clear();
+ decompressedBytes.clear();
+ compressedByteBuffer.clear();
+ }
+ }
+
+ @Override
+ public byte code() {
+ return STRINGZ_CODE;
+ }
+
+ public ThreadLocals acquireThreadLocals() {
+ ThreadLocals threadLocals = THREAD_LOCALS.get();
+ if (threadLocals == null)
+ THREAD_LOCALS.set(threadLocals = new ThreadLocals());
+ threadLocals.clear();
+ return threadLocals;
+ }
+
+ @Override
+ public void write(Bytes bytes, CharSequence s) {
+ if (s == null) {
+ bytes.writeStopBit(NULL_LENGTH);
+ return;
+
+ } else if (s.length() == 0) {
+ bytes.writeStopBit(0);
+ return;
+ }
+ // write the total length.
+ int length = s.length();
+ bytes.writeStopBit(length);
+
+ ThreadLocals threadLocals = acquireThreadLocals();
+ // stream the portions of the string.
+ Bytes db = threadLocals.decompressedBytes;
+ ByteBuffer dbb = threadLocals.decompressedByteBuffer;
+ ByteBuffer cbb = bytes.sliceAsByteBuffer(threadLocals.compressedByteBuffer);
+
+ int position = 0;
+ while (position < length) {
+ // 3 is the longest encoding.
+ while (position < length && db.remaining() >= 3)
+ db.writeStopBit(s.charAt(position++));
+ dbb.position(0);
+ dbb.limit((int) db.position());
+ // portion copied now compress it.
+ int portionLengthPos = cbb.position();
+ cbb.putShort((short) 0);
+ int compressedLength;
+ try {
+ Snappy.compress(dbb, cbb);
+ compressedLength = cbb.remaining();
+ if (compressedLength >= 1 << 16)
+ throw new AssertionError();
+ // unflip.
+ cbb.position(cbb.limit());
+ cbb.limit(cbb.capacity());
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ cbb.putShort(portionLengthPos, (short) compressedLength);
+ db.clear();
+ }
+ // the end.
+ cbb.putShort((short) 0);
+ bytes.position(bytes.position() + cbb.position());
+ }
+
+ @Override
+ public String read(Bytes bytes) {
+ return read(bytes, null);
+ }
+
+ @Override
+ public String read(Bytes bytes, @Nullable CharSequence ignored) {
+ long size = bytes.readStopBit();
+ if (size == NULL_LENGTH)
+ return null;
+ if (size < 0 || size > Integer.MAX_VALUE)
+ throw new IllegalStateException("Invalid length: " + size);
+ if (size == 0)
+ return "";
+ ThreadLocals threadLocals = acquireThreadLocals();
+ // stream the portions of the string.
+ Bytes db = threadLocals.decompressedBytes;
+ ByteBuffer dbb = threadLocals.decompressedByteBuffer;
+ ByteBuffer cbb = bytes.sliceAsByteBuffer(threadLocals.compressedByteBuffer);
+
+ char[] chars = new char[(int) size];
+ int pos = 0;
+ for (int chunkLen; (chunkLen = cbb.getShort() & 0xFFFF) > 0; ) {
+ cbb.limit(cbb.position() + chunkLen);
+ dbb.clear();
+ try {
+ Snappy.uncompress(cbb, dbb);
+ cbb.position(cbb.limit());
+ cbb.limit(cbb.capacity());
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ db.position(0);
+ db.limit(dbb.limit());
+ while (db.remaining() > 0)
+ chars[pos++] = (char) db.readStopBit();
+ }
+ bytes.position(bytes.position() + cbb.position());
+ try {
+ return STRING_FACTORY.fromChars(chars);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private static abstract class StringFactory {
+ abstract String fromChars(char[] chars) throws IllegalAccessException, InvocationTargetException, InstantiationException;
+ }
+
+ private static final class StringFactory16 extends StringFactory {
+ private final Constructor<String> constructor;
+
+ private StringFactory16() throws NoSuchMethodException {
+ constructor = String.class.getDeclaredConstructor(int.class,
+ int.class, char[].class);
+ constructor.setAccessible(true);
+ }
+
+ @Override
+ String fromChars(char[] chars) throws IllegalAccessException, InvocationTargetException, InstantiationException {
+ return constructor.newInstance(0, chars.length, chars);
+ }
+ }
+
+ private static final class StringFactory17 extends StringFactory {
+ private final Constructor<String> constructor;
+
+ private StringFactory17() throws NoSuchMethodException {
+ constructor = String.class.getDeclaredConstructor(char[].class, boolean.class);
+ constructor.setAccessible(true);
+ }
+
+ @Override
+ String fromChars(char[] chars) throws IllegalAccessException, InvocationTargetException, InstantiationException {
+ return constructor.newInstance(chars, true);
+ }
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringBuilderPool.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringBuilderPool.java
new file mode 100755
index 0000000..d7ca469
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringBuilderPool.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+/**
+ * Created by peter.lawrey on 29/10/14.
+ */
+public class StringBuilderPool {
+ final ThreadLocal<StringBuilder> sbtl = new ThreadLocal<StringBuilder>();
+
+ public StringBuilder acquireStringBuilder() {
+ StringBuilder sb = sbtl.get();
+ if (sb == null) {
+ sbtl.set(sb = new StringBuilder(128));
+ }
+ sb.setLength(0);
+ return sb;
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringMarshaller.java
index 2fb2ee5..67843ae 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringMarshaller.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringMarshaller.java
@@ -1,34 +1,35 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+import net.openhft.lang.model.constraints.NotNull;
+import net.openhft.lang.model.constraints.Nullable;
import net.openhft.lang.pool.StringInterner;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* @author peter.lawrey
*/
-public class StringMarshaller implements CompactBytesMarshaller<String> {
+public class StringMarshaller extends ImmutableMarshaller<String>
+ implements CompactBytesMarshaller<String> {
private final int size;
- private final StringBuilder reader = new StringBuilder();
- private StringInterner interner;
+ private static final StringBuilderPool sbp = new StringBuilderPool();
+ private transient StringInterner interner;
public StringMarshaller(int size) {
this.size = size;
@@ -42,19 +43,22 @@ public class StringMarshaller implements CompactBytesMarshaller<String> {
@Nullable
@Override
public String read(@NotNull Bytes bytes) {
- if (bytes.readUTFΔ(reader))
- return builderToString();
+ StringBuilder sb = sbp.acquireStringBuilder();
+ if (bytes.readUTFΔ(sb))
+ return builderToString(sb);
return null;
}
-
- private String builderToString() {
- if (interner == null)
+ private String builderToString(StringBuilder reader) {
+ if (interner == null) {
+ if (size == 0)
+ return reader.toString();
interner = new StringInterner(size);
+ }
return interner.intern(reader);
}
public byte code() {
- return 'S' & 31;
+ return STRING_CODE;
}
}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringZMapMarshaller.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringZMapMarshaller.java
new file mode 100755
index 0000000..efec05e
--- /dev/null
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/StringZMapMarshaller.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 higherfrequencytrading.com
+ *
+ * This program 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 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.openhft.lang.io.serialization.impl;
+
+import net.openhft.lang.io.Bytes;
+import net.openhft.lang.io.serialization.CompactBytesMarshaller;
+import net.openhft.lang.model.constraints.Nullable;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.StreamCorruptedException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+/**
+ * Created by peter.lawrey on 24/10/14.
+ */
+public enum StringZMapMarshaller implements CompactBytesMarshaller<Map<String, String>> {
+ FAST(Deflater.BEST_SPEED),
+ COMPACT(Deflater.BEST_COMPRESSION),
+ INSTANCE(Deflater.DEFAULT_STRATEGY);
+
+ private final int level;
+
+ private static final long NULL_SIZE = -1;
+
+ StringZMapMarshaller(int level) {
+ this.level = level;
+ }
+
+ @Override
+ public byte code() {
+ return STRINGZ_MAP_CODE;
+ }
+
+ @Override
+ public void write(Bytes bytes, Map<String, String> kvMap) {
+ if (kvMap == null) {
+ bytes.writeStopBit(NULL_SIZE);
+ return;
+ }
+
+ bytes.writeStopBit(kvMap.size());
+ long position = bytes.position();
+ bytes.clear();
+ bytes.position(position + 4);
+ DataOutputStream dos = new DataOutputStream(
+ new DeflaterOutputStream(bytes.outputStream(), new Deflater(level)));
+ try {
+ for (Map.Entry<String, String> entry : kvMap.entrySet()) {
+ dos.writeUTF(entry.getKey());
+ dos.writeUTF(entry.getValue());
+ }
+ dos.close();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ bytes.writeUnsignedInt(position, bytes.position() - position - 4);
+ }
+
+ @Override
+ public Map<String, String> read(Bytes bytes) {
+ return read(bytes, null);
+ }
+
+ @Override
+ public Map<String, String> read(Bytes bytes, @Nullable Map<String, String> kvMap) {
+ long size = bytes.readStopBit();
+ if (size == NULL_SIZE)
+ return null;
+ if (size < 0 || size > Integer.MAX_VALUE)
+ throw new IllegalStateException("Invalid length: " + size);
+
+ long length = bytes.readUnsignedInt();
+ if (length < 0 || length > Integer.MAX_VALUE)
+ throw new IllegalStateException(new StreamCorruptedException());
+ long position = bytes.position();
+ long end = position + length;
+
+ long limit = bytes.limit();
+ bytes.limit(end);
+
+ DataInputStream dis = new DataInputStream(new InflaterInputStream(bytes.inputStream()));
+ if (kvMap == null) {
+ kvMap = new LinkedHashMap<String, String>();
+
+ } else {
+ kvMap.clear();
+ }
+ try {
+ for (int i = 0; i < size; i++) {
+ String key = dis.readUTF();
+ String value = dis.readUTF();
+ kvMap.put(key, value);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ bytes.position(end);
+ bytes.limit(limit);
+ return kvMap;
+ }
+}
diff --git a/lang/src/main/java/net/openhft/lang/io/serialization/impl/VanillaBytesMarshallerFactory.java b/lang/src/main/java/net/openhft/lang/io/serialization/impl/VanillaBytesMarshallerFactory.java
index 6fc66ee..3e8d94a 100644
--- a/lang/src/main/java/net/openhft/lang/io/serialization/impl/VanillaBytesMarshallerFactory.java
+++ b/lang/src/main/java/net/openhft/lang/io/serialization/impl/VanillaBytesMarshallerFactory.java
@@ -1,17 +1,17 @@
/*
- * Copyright 2013 Peter Lawrey
+ * Copyright (C) 2015 higherfrequencytrading.com
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program 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 3 of the License.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 Lesser General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.lang.io.serialization.impl;
@@ -20,63 +20,92 @@ import net.openhft.lang.io.serialization.BytesMarshallable;
import net.openhft.lang.io.serialization.BytesMarshaller;
import net.openhft.lang.io.serialization.BytesMarshallerFactory;
import net.openhft.lang.io.serialization.CompactBytesMarshaller;
-import org.jetbrains.annotations.NotNull;
+import net.openhft.lang.model.constraints.NotNull;
import java.io.Externalizable;
+import java.nio.ByteBuffer;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
+import static net.openhft.lang.io.serialization.CompactBytesMarshaller.*;
+
/**
* @author peter.lawrey
*/
-public class VanillaBytesMarshallerFactory implements BytesMarshallerFactory {
+public final class VanillaBytesMarshallerFactory implements BytesMarshallerFactory {
+ private static final long serialVersionUID = 1L;
+
+ private transient Map<Class<?>, BytesMarshaller<?>> marshallerMap;
+ private transient BytesMarshaller<?>[] compactMarshallerMap;
- private final Map<Class, BytesMarshaller> marshallerMap = new LinkedHashMap<Class, BytesMarshaller>();
- private final BytesMarshaller[] compactMarshallerMap = new BytesMarshaller[256];
+ private void init() {
+ marshallerMap = new LinkedHashMap<Class<?>, BytesMarshaller<?>>();
+ compactMarshallerMap = new BytesMarshaller[256];
- // private final Map<Class, BytesMarshaller> marshallerTextMap = new LinkedHashMap<Class, BytesMarshaller>();
- {
- BytesMarshaller stringMarshaller = new StringMarshaller(16 * 1024);
+ BytesMarshaller<String> stringMarshaller = new StringMarshaller(16 * 1024);
addMarshaller(String.class, stringMarshaller);
- addMarshaller(CharSequence.class, stringMarshaller);
+ addMarshaller(CharSequence.class, (BytesMarshaller)stringMarshaller);
addMarshaller(Class.class, new ClassMarshaller(Thread.currentThread().getContextClassLoader()));
addMarshaller(Date.class, new DateMarshaller(10191));
- addMarshaller(Integer.class, new CompactEnumBytesMarshaller<Integer>(Integer.class, 10191, (byte) ('I' & 31)));
- addMarshaller(Long.class, new CompactEnumBytesMarshaller<Long>(Long.class, 10191, (byte) ('L' & 31)));
- addMarshaller(Double.class, new CompactEnumBytesMarshaller<Double>(Double.class, 10191, (byte) ('D' & 31)));
+ addMarshaller(Integer.class, new CompactEnumBytesMarshaller<Integer>(Integer.class, 10191, INT_CODE));
+ addMarshaller(Long.class, new CompactEnumBytesMarshaller<Long>(Long.class, 10191, LONG_CODE));
+ addMarshaller(Double.class, new CompactEnumBytesMarshaller<Double>(Double.class, 10191, DOUBLE_CODE));
+ addMarshaller(ByteBuffer.class, ByteBufferMarshaller.INSTANCE);
}
@NotNull
@SuppressWarnings("unchecked")
@Override
public <E> BytesMarshaller<E> acquireMarshaller(@NotNull Class<E> eClass, boolean create) {
+ if (marshallerMap == null) {
+ init();
+ }
+
BytesMarshaller em = marshallerMap.get(eClass);
- if (em == null)
- if (eClass.isEnum())
+ if (em == null) {
+ if (eClass.isEnum()) {
marshallerMap.put(eClass, em = new EnumBytesMarshaller(eClass, null));
- else if (BytesMarshallable.class.isAssignableFrom(eClass))
+
+ } else if (BytesMarshallable.class.isAssignableFrom(eClass)) {
marshallerMap.put(eClass, em = new BytesMarshallableMarshaller((Class) eClass));
- else if (Externalizable.class.isAssignableFrom(eClass))
+
+ } else if (Externalizable.class.isAssignableFrom(eClass)) {
marshallerMap.put(eClass, em = new ExternalizableMarshaller((Class) eClass));
- else {
+
+ } else if (Throwable.class.isAssignableFrom(eClass)) {
+ marshallerMap.put(eClass, em = NoMarshaller.INSTANCE);
+
+ } else {
try {
marshallerMap.put(eClass, em = new GenericEnumMarshaller<E>(eClass, 1000));
} catch (Exception e) {
marshallerMap.put(eClass, em = NoMarshaller.INSTANCE);
}
}
+ }
+
return em;
}
@Override
+ @SuppressWarnings("unchecked")
public <E> BytesMarshaller<E> getMarshaller(byte code) {
- return compactMarshallerMap[code & 0xFF];
+ if (marshallerMap == null) {
+ init();
+ }
+
+ return (BytesMarshaller<E>) compactMarshallerMap[code & 0xFF];
}
public <E> void addMarshaller(Class<E> eClass, BytesMarshaller<E> marshaller) {
+ if (marshallerMap == null) {
+ init();
+ }
+
marshallerMap.put(eClass, marshaller);
- if (marshaller instanceof CompactBytesMarshaller)
+ if (marshaller instanceof CompactBytesMarshaller) {
compactMarshallerMap[((CompactBytesMarshaller) marshaller).code()] = marshaller;
+ }
}
}