revised initial cut of serializer package; moved Converter adapters to sub-package 'support'

This commit is contained in:
Juergen Hoeller 2010-10-11 21:15:12 +00:00
parent 3740380a7a
commit b062de1133
14 changed files with 96 additions and 172 deletions

View File

@ -20,6 +20,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import org.springframework.core.NestedIOException;
/** /**
* Deserializer that reads an input stream using Java Serialization. * Deserializer that reads an input stream using Java Serialization.
* *
@ -33,16 +35,12 @@ public class DefaultDeserializer implements Deserializer<Object> {
* Reads the input stream and deserializes into an object. * Reads the input stream and deserializes into an object.
*/ */
public Object deserialize(InputStream inputStream) throws IOException { public Object deserialize(InputStream inputStream) throws IOException {
ObjectInputStream objectInputStream = null; ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
try { try {
objectInputStream = new ObjectInputStream(inputStream);
return objectInputStream.readObject(); return objectInputStream.readObject();
} }
catch (ClassNotFoundException e) { catch (ClassNotFoundException ex) {
if (objectInputStream != null) { throw new NestedIOException("Failed to deserialize object type", ex);
objectInputStream.close();
}
throw new IOException(e.getMessage());
} }
} }

View File

@ -21,8 +21,6 @@ import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import org.springframework.util.Assert;
/** /**
* Serializer that writes an object to an output stream using Java Serialization. * Serializer that writes an object to an output stream using Java Serialization.
* *
@ -34,11 +32,13 @@ public class DefaultSerializer implements Serializer<Object> {
/** /**
* Writes the source object to an output stream using Java Serialization. * Writes the source object to an output stream using Java Serialization.
* Source object must implement {@link Serializable}. * The source object must implement {@link Serializable}.
*/ */
public void serialize(Object object, OutputStream outputStream) throws IOException { public void serialize(Object object, OutputStream outputStream) throws IOException {
Assert.isTrue(object instanceof Serializable, this.getClass().getName() if (!(object instanceof Serializable)) {
+ " requires a Serializable payload, but received [" + object.getClass().getName() + "]"); throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +
"but received an object of type [" + object.getClass().getName() + "]");
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object); objectOutputStream.writeObject(object);
objectOutputStream.flush(); objectOutputStream.flush();

View File

@ -1,46 +0,0 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* 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.springframework.core.serializer;
/**
* Exception to be thrown when a failure occurs while deserializing an object.
*
* @author Gary Russell
* @since 3.0.5
*/
@SuppressWarnings("serial")
public class DeserializationFailureException extends SerializationException {
/**
* Construct a <code>DeserializationFailureException</code> with the specified detail message.
* @param message the detail message
*/
public DeserializationFailureException(String message) {
super(message);
}
/**
* Construct a <code>DeserializationFailureException</code> with the specified detail message
* and nested exception.
* @param message the detail message
* @param cause the nested exception
*/
public DeserializationFailureException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -29,11 +29,14 @@ import java.io.InputStream;
public interface Deserializer<T> { public interface Deserializer<T> {
/** /**
* Read (assemble an object of type T) from an InputStream. * Read (assemble) an object of type T from the given InputStream.
* @param inputStream The InputStream. * <p>Note: Implementations should not close the given InputStream
* (or any decorators of that InputStream) but rather leave this up
* to the caller.
* @param inputStream the input stream
* @return the deserialized object * @return the deserialized object
* @throws IOException in case of errors reading the stream * @throws IOException in case of errors reading from the stream
*/ */
public T deserialize(InputStream inputStream) throws IOException; T deserialize(InputStream inputStream) throws IOException;
} }

View File

@ -1,46 +0,0 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* 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.springframework.core.serializer;
/**
* Exception to be thrown when a failure occurs while serializing an object.
*
* @author Gary Russell
* @since 3.0.5
*/
@SuppressWarnings("serial")
public class SerializationFailureException extends SerializationException {
/**
* Construct a <code>SerializationFailureException</code> with the specified detail message.
* @param message the detail message
*/
public SerializationFailureException(String message) {
super(message);
}
/**
* Construct a <code>SerializationFailureException</code> with the specified detail message
* and nested exception.
* @param message the detail message
* @param cause the nested exception
*/
public SerializationFailureException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -29,11 +29,14 @@ import java.io.OutputStream;
public interface Serializer<T> { public interface Serializer<T> {
/** /**
* Write an object of type T to the outputSream. * Write an object of type T to the given OutputStream.
* @param object The object. * <p>Note: Implementations should not close the given OutputStream
* @param outputStream the outputStream * (or any decorators of that OutputStream) but rather leave this up
* to the caller.
* @param object the object to serialize
* @param outputStream the output stream
* @throws IOException in case of errors writing to the stream * @throws IOException in case of errors writing to the stream
*/ */
public void serialize(T object, OutputStream outputStream) throws IOException; void serialize(T object, OutputStream outputStream) throws IOException;
} }

View File

@ -1,6 +1,10 @@
/** /**
*
* Root package for Spring's serializer interfaces and implementations. * Root package for Spring's serializer interfaces and implementations.
* Provides an abstraction over various serialization techniques. * Provides an abstraction over various serialization techniques.
* Includes exceptions for serialization and deserialization failures. * Includes exceptions for serialization and deserialization failures.
*
*/ */
package org.springframework.core.serializer; package org.springframework.core.serializer;

View File

@ -14,16 +14,17 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.core.serializer; package org.springframework.core.serializer.support;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.core.serializer.Deserializer;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* A {@link Converter} that delegates to a {@link Deserializer} * A {@link Converter} that delegates to a {@link org.springframework.core.serializer.Deserializer}
* to convert data in a byte array to an object. * to convert data in a byte array to an object.
* *
* @author Gary Russell * @author Gary Russell
@ -43,10 +44,10 @@ public class DeserializingConverter implements Converter<byte[], Object> {
} }
/** /**
* Create a DeserializingConverter that delegates to the provided {@link Deserializer} * Create a DeserializingConverter that delegates to the provided {@link Deserializer}.
*/ */
public DeserializingConverter(Deserializer<Object> deserializer) { public DeserializingConverter(Deserializer<Object> deserializer) {
Assert.notNull(deserializer, "deserializer must not be null"); Assert.notNull(deserializer, "Deserializer must not be null");
this.deserializer = deserializer; this.deserializer = deserializer;
} }
@ -56,15 +57,10 @@ public class DeserializingConverter implements Converter<byte[], Object> {
try { try {
return this.deserializer.deserialize(byteStream); return this.deserializer.deserialize(byteStream);
} }
catch (Exception e) { catch (Throwable ex) {
try { throw new SerializationFailedException("Failed to deserialize payload. " +
byteStream.close();
}
catch (IOException e1) { /* ignore */ }
throw new DeserializationFailureException(
"Failed to deserialize payload. " +
"Is the byte array a result of corresponding serialization for " + "Is the byte array a result of corresponding serialization for " +
this.deserializer.getClass().getName() + "?", e); this.deserializer.getClass().getSimpleName() + "?", ex);
} }
} }

View File

@ -14,24 +14,27 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.core.serializer; package org.springframework.core.serializer.support;
import org.springframework.core.NestedRuntimeException; import org.springframework.core.NestedRuntimeException;
/** /**
* Root exception for serialization and deserialization exceptions. * Wrapper for the native IOException (or similar) when a
* {@link org.springframework.core.serializer.Serializer} or
* {@link org.springframework.core.serializer.Deserializer} failed.
* Thrown by {@link SerializingConverter} and {@link DeserializingConverter}.
* *
* @author Gary Russell * @author Gary Russell
* @author Juergen Hoeller
* @since 3.0.5 * @since 3.0.5
*/ */
@SuppressWarnings("serial") public class SerializationFailedException extends NestedRuntimeException {
public abstract class SerializationException extends NestedRuntimeException {
/** /**
* Construct a <code>SerializationException</code> with the specified detail message. * Construct a <code>SerializationException</code> with the specified detail message.
* @param message the detail message * @param message the detail message
*/ */
public SerializationException(String message) { public SerializationFailedException(String message) {
super(message); super(message);
} }
@ -41,7 +44,7 @@ public abstract class SerializationException extends NestedRuntimeException {
* @param message the detail message * @param message the detail message
* @param cause the nested exception * @param cause the nested exception
*/ */
public SerializationException(String message, Throwable cause) { public SerializationFailedException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -14,15 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.core.serializer; package org.springframework.core.serializer.support;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.DefaultSerializer;
import org.springframework.core.serializer.Serializer;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* A {@Link Converter} that delegates to a {@link Serializer} to convert an object to a byte array. * A {@Link Converter} that delegates to a {@link org.springframework.core.serializer.Serializer}
* to convert an object to a byte array.
* *
* @author Gary Russell * @author Gary Russell
* @author Mark Fisher * @author Mark Fisher
@ -44,7 +47,7 @@ public class SerializingConverter implements Converter<Object, byte[]> {
* Create a SerializingConverter that delegates to the provided {@link Serializer} * Create a SerializingConverter that delegates to the provided {@link Serializer}
*/ */
public SerializingConverter(Serializer<Object> serializer) { public SerializingConverter(Serializer<Object> serializer) {
Assert.notNull(serializer, "serializer must not be null"); Assert.notNull(serializer, "Serializer must not be null");
this.serializer = serializer; this.serializer = serializer;
} }
@ -58,8 +61,9 @@ public class SerializingConverter implements Converter<Object, byte[]> {
this.serializer.serialize(source, byteStream); this.serializer.serialize(source, byteStream);
return byteStream.toByteArray(); return byteStream.toByteArray();
} }
catch (Exception e) { catch (Throwable ex) {
throw new SerializationFailureException("failed to serialize object", e); throw new SerializationFailedException("Failed to serialize object using " +
this.serializer.getClass().getSimpleName(), ex);
} }
} }

View File

@ -0,0 +1,9 @@
/**
*
* Support classes for Spring's serializer abstraction.
* Includes adapters to the Converter SPI.
*
*/
package org.springframework.core.io.support;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.core.serializer; package org.springframework.util;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -23,7 +23,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
/** /**
* Static utility for serialization and deserialization. * Static utilities for serialization and deserialization.
* *
* @author Dave Syer * @author Dave Syer
* @since 3.0.5 * @since 3.0.5
@ -31,8 +31,7 @@ import java.io.ObjectOutputStream;
public abstract class SerializationUtils { public abstract class SerializationUtils {
/** /**
* Serialize the object provided. * Serialize the given object to a byte array.
*
* @param object the object to serialize * @param object the object to serialize
* @return an array of bytes representing the object in a portable fashion * @return an array of bytes representing the object in a portable fashion
*/ */
@ -40,19 +39,20 @@ public abstract class SerializationUtils {
if (object == null) { if (object == null) {
return null; return null;
} }
ByteArrayOutputStream stream = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new ObjectOutputStream(stream).writeObject(object); ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
} }
catch (IOException e) { catch (IOException ex) {
throw new IllegalArgumentException("failed to serialize object of type: " + object.getClass(), e); throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
} }
return stream.toByteArray(); return baos.toByteArray();
} }
/** /**
* Deserialize the byte array into an object. * Deserialize the byte array into an object.
*
* @param bytes a serialized object * @param bytes a serialized object
* @return the result of deserializing the bytes * @return the result of deserializing the bytes
*/ */
@ -61,13 +61,14 @@ public abstract class SerializationUtils {
return null; return null;
} }
try { try {
return new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return ois.readObject();
} }
catch (IOException e) { catch (IOException ex) {
throw new IllegalArgumentException("failed to deserialize object", e); throw new IllegalArgumentException("Failed to deserialize object", ex);
} }
catch (ClassNotFoundException e) { catch (ClassNotFoundException ex) {
throw new IllegalStateException("failed to deserialize object type", e); throw new IllegalStateException("Failed to deserialize object type", ex);
} }
} }

View File

@ -16,20 +16,15 @@
package org.springframework.core.serializer; package org.springframework.core.serializer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.io.Serializable; import java.io.Serializable;
import static org.junit.Assert.*;
import org.junit.Test; import org.junit.Test;
import org.springframework.core.serializer.DeserializationFailureException; import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.DeserializingConverter; import org.springframework.core.serializer.support.SerializationFailedException;
import org.springframework.core.serializer.SerializationFailureException; import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.core.serializer.SerializingConverter;
/** /**
* @author Gary Russell * @author Gary Russell
@ -53,7 +48,7 @@ public class SerializationConverterTests {
toBytes.convert(new Object()); toBytes.convert(new Object());
fail("Expected IllegalArgumentException"); fail("Expected IllegalArgumentException");
} }
catch (SerializationFailureException e) { catch (SerializationFailedException e) {
assertNotNull(e.getCause()); assertNotNull(e.getCause());
assertTrue(e.getCause() instanceof IllegalArgumentException); assertTrue(e.getCause() instanceof IllegalArgumentException);
} }
@ -66,13 +61,13 @@ public class SerializationConverterTests {
toBytes.convert(new UnSerializable()); toBytes.convert(new UnSerializable());
fail("Expected SerializationFailureException"); fail("Expected SerializationFailureException");
} }
catch (SerializationFailureException e) { catch (SerializationFailedException e) {
assertNotNull(e.getCause()); assertNotNull(e.getCause());
assertTrue(e.getCause() instanceof NotSerializableException); assertTrue(e.getCause() instanceof NotSerializableException);
} }
} }
@Test(expected = DeserializationFailureException.class) @Test(expected = SerializationFailedException.class)
public void deserializationFailure() { public void deserializationFailure() {
DeserializingConverter fromBytes = new DeserializingConverter(); DeserializingConverter fromBytes = new DeserializingConverter();
fromBytes.convert("Junk".getBytes()); fromBytes.convert("Junk".getBytes());

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.core.serializer; package org.springframework.util;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@ -24,7 +24,7 @@ import java.math.BigInteger;
import org.junit.Test; import org.junit.Test;
import org.springframework.core.serializer.SerializationUtils; import org.springframework.util.SerializationUtils;
/** /**
* Test for static utility to help with serialization. * Test for static utility to help with serialization.