| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal.util; |
| |
| import java.io.IOException; |
| |
| import org.apache.geode.DataSerializer; |
| import org.apache.geode.distributed.internal.DMStats; |
| import org.apache.geode.distributed.internal.InternalDistributedSystem; |
| import org.apache.geode.internal.ByteArrayDataInput; |
| import org.apache.geode.internal.DSCODE; |
| import org.apache.geode.internal.HeapDataOutputStream; |
| import org.apache.geode.internal.Version; |
| import org.apache.geode.internal.offheap.StoredObject; |
| import org.apache.geode.internal.offheap.annotations.Unretained; |
| import org.apache.geode.pdx.internal.PdxInputStream; |
| |
| /** |
| * A "blob" is a serialized representation of an object into a byte[]. BlobHelper provides utility |
| * methods for serializing and deserializing the object. |
| * |
| * TODO: compare performance with org.apache.commons.lang3.SerializationUtils |
| */ |
| public class BlobHelper { |
| |
| /** |
| * A blob is a serialized Object. This method serializes the object into a blob and returns the |
| * byte array that contains the blob. |
| */ |
| public static byte[] serializeToBlob(Object obj) throws IOException { |
| return serializeToBlob(obj, null); |
| } |
| |
| /** |
| * A blob is a serialized Object. This method serializes the object into a blob and returns the |
| * byte array that contains the blob. |
| */ |
| public static byte[] serializeToBlob(Object obj, Version version) throws IOException { |
| final long start = startSerialization(); |
| HeapDataOutputStream hdos = new HeapDataOutputStream(version); |
| DataSerializer.writeObject(obj, hdos); |
| byte[] result = hdos.toByteArray(); |
| endSerialization(start, result.length); |
| return result; |
| } |
| |
| /** |
| * A blob is a serialized Object. This method serializes the object into the given |
| * HeapDataOutputStream. |
| */ |
| public static void serializeTo(Object obj, HeapDataOutputStream hdos) throws IOException { |
| final int startBytes = hdos.size(); |
| final long start = startSerialization(); |
| DataSerializer.writeObject(obj, hdos); |
| endSerialization(start, hdos.size() - startBytes); |
| } |
| |
| /** |
| * A blob is a serialized Object. This method returns the deserialized object. |
| */ |
| public static Object deserializeBlob(byte[] blob) throws IOException, ClassNotFoundException { |
| return deserializeBlob(blob, null, null); |
| } |
| |
| /** |
| * A blob is a serialized Object. This method returns the deserialized object. |
| */ |
| public static Object deserializeBlob(byte[] blob, Version version, ByteArrayDataInput in) |
| throws IOException, ClassNotFoundException { |
| Object result; |
| final long start = startDeserialization(); |
| if (blob.length > 0 && blob[0] == DSCODE.PDX.toByte()) { |
| // If the first byte of blob indicates a pdx then wrap |
| // blob in a PdxInputStream instead. |
| // This will prevent us from making a copy of the byte[] |
| // every time we deserialize a PdxInstance. |
| PdxInputStream is = new PdxInputStream(blob); |
| result = DataSerializer.readObject(is); |
| } else { |
| // if we have a nested pdx then we want to make a copy |
| // when a PdxInstance is created so that the byte[] will |
| // just have the pdx bytes and not the outer objects bytes. |
| if (in == null) { |
| in = new ByteArrayDataInput(); |
| } |
| in.initialize(blob, version); |
| result = DataSerializer.readObject(in); |
| } |
| endDeserialization(start, blob.length); |
| return result; |
| } |
| |
| /** |
| * A blob is a serialized Object. This method returns the deserialized object. If a PdxInstance is |
| * returned then it will refer to Chunk's off-heap memory with an unretained reference. |
| */ |
| public static @Unretained Object deserializeOffHeapBlob(StoredObject blob) |
| throws IOException, ClassNotFoundException { |
| Object result; |
| final long start = startDeserialization(); |
| // For both top level and nested pdxs we just want a reference to this off-heap blob. |
| // No copies. |
| // For non-pdx we want a stream that will read directly from the chunk. |
| PdxInputStream is = new PdxInputStream(blob); |
| result = DataSerializer.readObject(is); |
| endDeserialization(start, blob.getDataSize()); |
| return result; |
| } |
| |
| /** |
| * Unused |
| */ |
| public static Object deserializeBuffer(ByteArrayDataInput in, int numBytes) |
| throws IOException, ClassNotFoundException { |
| final long start = startDeserialization(); |
| Object result = DataSerializer.readObject(in); |
| endDeserialization(start, numBytes); |
| return result; |
| } |
| |
| private static long startSerialization() { |
| long result = 0; |
| DMStats stats = InternalDistributedSystem.getDMStats(); |
| if (stats != null) { |
| result = stats.startSerialization(); |
| } |
| return result; |
| } |
| |
| private static void endSerialization(long start, int bytes) { |
| DMStats stats = InternalDistributedSystem.getDMStats(); |
| if (stats != null) { |
| stats.endSerialization(start, bytes); |
| } |
| } |
| |
| private static long startDeserialization() { |
| long result = 0; |
| DMStats stats = InternalDistributedSystem.getDMStats(); |
| if (stats != null) { |
| result = stats.startDeserialization(); |
| } |
| return result; |
| } |
| |
| private static void endDeserialization(long start, int bytes) { |
| DMStats stats = InternalDistributedSystem.getDMStats(); |
| if (stats != null) { |
| stats.endDeserialization(start, bytes); |
| } |
| } |
| |
| } |