All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jsr107.ri.RISerializingInternalConverter Maven / Gradle / Ivy

There is a newer version: 62
Show newest version
/**
 *  Copyright 2011-2013 Terracotta, Inc.
 *  Copyright 2011-2013 Oracle America Incorporated
 *
 *  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 org.jsr107.ri;

import javax.cache.CacheException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.ref.WeakReference;
import java.util.Arrays;

/**
 * An {@link RIInternalConverter} that converts values to and from their
 * serialized representation.
 *
 * @param  the type of value to serialize
 * @author Brian Oliver
 */
class RISerializingInternalConverter implements RIInternalConverter {

  /**
   * The {@link ClassLoader} to use for locating classes to serialize/deserialize.
   * 

* This is a WeakReference to prevent ClassLoader memory leaks. *

*/ private WeakReference classLoaderReference; /** * Constructs a {@link RISerializingInternalConverter}. * * @param classLoader the {@link ClassLoader} to use for locating classes * when deserializing */ public RISerializingInternalConverter(ClassLoader classLoader) { this.classLoaderReference = new WeakReference(classLoader); } /** * Gets the {@link ClassLoader} that will be used to locate classes * during serialization and deserialization. * * @return the {@link ClassLoader} */ public ClassLoader getClassLoader() { return classLoaderReference.get(); } /** * {@inheritDoc} */ @Override public Object toInternal(T value) { return new Serialized(value); } /** * {@inheritDoc} */ @Override public T fromInternal(Object internal) { if (internal == null) { return null; } else if (internal instanceof Serialized) { return (T) ((Serialized) internal).deserialize(getClassLoader()); } else { throw new IllegalArgumentException("internal value is not a Serialized instance [" + internal + "]"); } } /** * A container for a serialized object. * * @param the type of value that was serialized */ private static class Serialized { /** * The serialized form of the value. */ private final byte[] bytes; /** * The hashcode of the value. */ private final int hashCode; /** * Constructs a {@link Serialized} representation of a value. * * @param value the value to be serialized (in a serialized form) */ Serialized(V value) { if (value == null) { this.hashCode = 0; this.bytes = null; } else { this.hashCode = value.hashCode(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(value); bos.flush(); this.bytes = bos.toByteArray(); } catch (IOException e) { throw new IllegalArgumentException("Failed to serialize: " + value + " due to " + e.getMessage(), e); } finally { try { bos.close(); } catch (IOException e) { // eat this up } } } } /** * Deserialize the {@link Serialized} value. * * @param classLoader the {@link ClassLoader} to use for resolving classes */ public V deserialize(ClassLoader classLoader) { ByteArrayInputStream bos = new ByteArrayInputStream(bytes); ObjectInputStream ois; try { ois = new CustomizedClassLoaderObjectInputStream(bos, classLoader); //this must fail if the types are incompatible return (V) ois.readObject(); } catch (IOException e) { throw new CacheException("Failed to deserialize: " + e.getMessage(), e); } catch (ClassNotFoundException e) { throw new CacheException("Failed to resolve a deserialized class: " + e.getMessage(), e); } finally { try { bos.close(); } catch (IOException e) { // eat this up } } } /** * {@inheritDoc} */ @Override public boolean equals(Object object) { if (this == object) { return true; } if (object == null) { return false; } if (!(object instanceof Serialized)) { return false; } Serialized serialized = (Serialized) object; if (!Arrays.equals(bytes, serialized.bytes)) { return false; } if (hashCode != serialized.hashCode) { return false; } return true; } /** * {@inheritDoc} */ @Override public int hashCode() { return hashCode; } } /** * An {@link ObjectInputStream} that uses a specific {@link ClassLoader}. */ private static final class CustomizedClassLoaderObjectInputStream extends ObjectInputStream { /** * The {@link ClassLoader} to use. */ private final ClassLoader classloader; /** * Constructs a {@link CustomizedClassLoaderObjectInputStream}. * * @param in the {@link InputStream} * @param classloader the {@link ClassLoader} * @throws IOException should the stream not be created */ private CustomizedClassLoaderObjectInputStream(InputStream in, ClassLoader classloader) throws IOException { super(in); this.classloader = classloader; } /** * {@inheritDoc} */ @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, classloader); } catch (ClassNotFoundException ex) { return super.resolveClass(desc); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy