/*
* Copyright 2009 Martin Grotzke
*
* 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 de.javakaffee.web.msm.serializer.javolution;
import static de.javakaffee.web.msm.serializer.javolution.TestClasses.createPerson;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import javolution.xml.XMLObjectReader;
import javolution.xml.XMLObjectWriter;
import javolution.xml.XMLReferenceResolver;
import javolution.xml.stream.XMLStreamException;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.session.StandardSession;
import org.apache.commons.lang.mutable.MutableInt;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import de.javakaffee.web.msm.MemcachedBackupSession;
import de.javakaffee.web.msm.MemcachedBackupSessionManager;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.Container;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.CounterHolder;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.CounterHolderArray;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.Email;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.HashMapWithIntConstructorOnly;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.Holder;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.HolderArray;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.HolderList;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.MyContainer;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.MyXMLSerializable;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.Person;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.Person.Gender;
import de.javakaffee.web.msm.serializer.javolution.TestClasses.SomeInterface;
/**
* Test for {@link JavolutionTranscoder}
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class JavolutionTranscoderTest {
private MemcachedBackupSessionManager _manager;
private JavolutionTranscoder _transcoder;
@BeforeClass
public void beforeTest() {
_manager = new MemcachedBackupSessionManager();
final StandardContext container = new StandardContext();
_manager.setContainer( container );
final WebappLoader webappLoader = mock( WebappLoader.class );
when( webappLoader.getClassLoader() ).thenReturn( Thread.currentThread().getContextClassLoader() );
Assert.assertNotNull( webappLoader.getClassLoader(), "Webapp Classloader is null." );
_manager.getContainer().setLoader( webappLoader );
Assert.assertNotNull( _manager.getContainer().getLoader().getClassLoader(), "Classloader is null." );
_transcoder = new JavolutionTranscoder( _manager, true );
}
@Test( enabled = true )
public void testStringBufferAndStringBuilderFormat() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "stringbuffer", new StringBuffer( "<string\n&buffer/>" ) );
session.setAttribute( "stringbuilder", new StringBuilder( "<string\n&buffer/>" ) );
System.out.println( new String( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) ));
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
/**
* This is test for issue #55:
* Wicket's MiniMap cannot be deserialized with javolution serializer
*
* See http://code.google.com/p/memcached-session-manager/issues/detail?id=55
*
* @throws Exception
*/
@Test( enabled = true )
public void testMapWithIntConstructorOnly() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
final HashMapWithIntConstructorOnly map = new HashMapWithIntConstructorOnly( 5 );
session.setAttribute( "map", map );
System.out.println( new String( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) ));
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
assertDeepEquals( deserialized.get( "map" ), map );
}
/**
* This is test for issue #34:
* msm-javolution-serializer: java.util.Currency gets deserialized with ReflectionFormat
*
* See http://code.google.com/p/memcached-session-manager/issues/detail?id=34
*
* @throws Exception
*/
@Test( enabled = true )
public void testCurrency() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
final Currency orig = Currency.getInstance( "EUR" );
session.setAttribute( "currency1", orig );
session.setAttribute( "currency2", orig );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
// Check that the transient field defaultFractionDigits is initialized correctly (that was the bug)
final Currency currency1 = (Currency) deserialized.get( "currency1" );
Assert.assertEquals( currency1.getCurrencyCode(), orig.getCurrencyCode() );
Assert.assertEquals( currency1.getDefaultFractionDigits(), orig.getDefaultFractionDigits() );
}
/**
* This is test for issue #33:
* msm-javolution-serializer: ReflectionBinding does not honor XMLSerializable interface
*
* See http://code.google.com/p/memcached-session-manager/issues/detail?id=33
*
* @throws Exception
*/
@Test( enabled = true )
public void testXMLSerializableSupport() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
final String attributeName = "myxmlserializable";
session.setAttribute( attributeName, new MyXMLSerializable( Runtime.getRuntime() ) );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
final MyXMLSerializable myXMLSerializable = (MyXMLSerializable) deserialized.get( attributeName );
Assert.assertNotNull( myXMLSerializable.getRuntime(), "Transient field runtime should be initialized by XMLFormat" +
" used due to implementation of XMLSerializable." );
}
/**
* This is test for issue #30:
* msm-javolution-serializer should support serialization of java.util.Collections$UnmodifiableMap
*
* See http://code.google.com/p/memcached-session-manager/issues/detail?id=30
*
* @throws Exception
*/
@Test( enabled = true )
public void testJavaUtilCollectionsUnmodifiable() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "unmodifiableList", Collections.unmodifiableList( new ArrayList<String>( Arrays.asList( "foo", "bar" ) ) ) );
final HashMap<String, String> m = new HashMap<String, String>();
m.put( "foo", "bar" );
session.setAttribute( "unmodifiableList", Collections.unmodifiableMap( m ) );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
/**
* This is the test for issue #28:
* msm-javolution-serializer should support serialization of java.util.Collections$EmptyList
*
* See http://code.google.com/p/memcached-session-manager/issues/detail?id=28
*
* @throws Exception
*/
@Test( enabled = true )
public void testJavaUtilLists() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "emptyList", Collections.<String>emptyList() );
session.setAttribute( "arrayList", new ArrayList<String>() );
session.setAttribute( "arraysAsList", Arrays.asList( "foo", "bar" ) );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
/**
* This is another test for issue #28, just for maps:
* msm-javolution-serializer should support serialization of java.util.Collections$EmptyList
*
* See http://code.google.com/p/memcached-session-manager/issues/detail?id=28
*
* @throws Exception
*/
@Test( enabled = true )
public void testJavaUtilCollectionsEmptyMap() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "emptyMap", Collections.<String, String>emptyMap() );
session.setAttribute( "hashMap", new HashMap<String, String>() );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
@Test( enabled = true )
public void testProxy() throws Exception {
final SomeInterface bean = TestClasses.createProxy();
final byte[] bytes = serialize( bean );
assertDeepEquals( deserialize( bytes ), bean );
}
@Test( enabled = true )
public void testInnerClass() throws Exception {
final Container container = TestClasses.createContainer( "some content" );
assertDeepEquals( deserialize( serialize( container ) ), container );
}
@DataProvider( name = "sharedObjectIdentityProvider" )
protected Object[][] createSharedObjectIdentityProviderData() {
return new Object[][] { { AtomicInteger.class.getSimpleName(), new AtomicInteger( 42 ) },
{ Email.class.getSimpleName(), new Email( "foo bar", "foo.bar@example.com" ) } };
}
@Test( enabled = true )
public <T> void testSharedObjectIdentity_CounterHolder() throws Exception {
final AtomicInteger sharedObject = new AtomicInteger( 42 );
final CounterHolder holder1 = new CounterHolder( sharedObject );
final CounterHolder holder2 = new CounterHolder( sharedObject );
final CounterHolderArray holderHolder = new CounterHolderArray( holder1, holder2 );
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "hh", holderHolder );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
final CounterHolderArray hhd = (CounterHolderArray) deserialized.get( "hh" );
Assert.assertTrue( hhd.holders[0].item == hhd.holders[1].item );
}
@Test( enabled = true, dataProvider = "sharedObjectIdentityProvider" )
public <T> void testSharedObjectIdentityWithArray( final String name, final T sharedObject ) throws Exception {
final Holder<T> holder1 = new Holder<T>( sharedObject );
final Holder<T> holder2 = new Holder<T>( sharedObject );
@SuppressWarnings( "unchecked" )
final HolderArray<T> holderHolder = new HolderArray<T>( holder1, holder2 );
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( name, holderHolder );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
@SuppressWarnings( "unchecked" )
final HolderArray<T> hhd = (HolderArray<T>) deserialized.get( name );
Assert.assertTrue( hhd.holders[0].item == hhd.holders[1].item );
}
@Test( enabled = true, dataProvider = "sharedObjectIdentityProvider" )
public <T> void testSharedObjectIdentity( final String name, final T sharedObject ) throws Exception {
final Holder<T> holder1 = new Holder<T>( sharedObject );
final Holder<T> holder2 = new Holder<T>( sharedObject );
@SuppressWarnings( "unchecked" )
final HolderList<T> holderHolder = new HolderList<T>( new ArrayList<Holder<T>>( Arrays.asList( holder1, holder2 ) ) );
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( name, holderHolder );
final Map<String, Object> deserialized =
_transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
@SuppressWarnings( "unchecked" )
final HolderList<T> hhd = (HolderList<T>) deserialized.get( name );
Assert.assertTrue( hhd.holders.get( 0 ).item == hhd.holders.get( 1 ).item );
}
@DataProvider( name = "typesAsSessionAttributesProvider" )
protected Object[][] createTypesAsSessionAttributesData() {
return new Object[][] { { int.class, 42 },
{ long.class, 42 },
{ Boolean.class, Boolean.TRUE },
{ String.class, "42" },
{ StringBuilder.class, new StringBuilder( "42" ) },
{ StringBuffer.class, new StringBuffer( "42" ) },
{ Class.class, String.class },
{ Long.class, Long.valueOf( 42 ) },
{ Integer.class, Integer.valueOf( 42 ) },
{ Character.class, Character.valueOf( 'c' ) },
{ Byte.class, Byte.valueOf( "b".getBytes()[0] ) },
{ Double.class, Double.valueOf( 42d ) },
{ Float.class, Float.valueOf( 42f ) },
{ Short.class, Short.valueOf( (short) 42 ) },
{ BigDecimal.class, new BigDecimal( 42 ) },
{ AtomicInteger.class, new AtomicInteger( 42 ) },
{ AtomicLong.class, new AtomicLong( 42 ) },
{ MutableInt.class, new MutableInt( 42 ) },
{ Integer[].class, new Integer[] { 42 } },
{ Date.class, new Date( System.currentTimeMillis() - 10000 ) },
{ Calendar.class, Calendar.getInstance() },
{ Currency.class, Currency.getInstance( "EUR" ) },
{ ArrayList.class, new ArrayList<String>( Arrays.asList( "foo" ) ) },
{ int[].class, new int[] { 1, 2 } },
{ long[].class, new long[] { 1, 2 } },
{ short[].class, new short[] { 1, 2 } },
{ float[].class, new float[] { 1, 2 } },
{ double[].class, new double[] { 1, 2 } },
{ int[].class, new int[] { 1, 2 } },
{ byte[].class, "42".getBytes() },
{ char[].class, "42".toCharArray() },
{ String[].class, new String[] { "23", "42" } },
{ Person[].class, new Person[] { createPerson( "foo bar", Gender.MALE, 42 ) } } };
}
@Test( enabled = true, dataProvider = "typesAsSessionAttributesProvider" )
public <T> void testTypesAsSessionAttributes( final Class<T> type, final T instance ) throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( type.getSimpleName(), instance );
final byte[] bytes = _transcoder.serializeAttributes( session, session.getAttributesInternal() );
assertDeepEquals( _transcoder.deserializeAttributes( bytes ), session.getAttributesInternal());
}
@Test( enabled = true )
public void testTypesInContainerClass() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( MyContainer.class.getSimpleName(), new MyContainer() );
final Map<String, Object> deserialized = _transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
@Test( enabled = true )
public void testClassWithoutDefaultConstructor() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "no-default constructor", TestClasses.createClassWithoutDefaultConstructor( "foo" ) );
final Map<String, Object> deserialized = _transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
@Test( enabled = true )
public void testPrivateClass() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "pc", TestClasses.createPrivateClass( "foo" ) );
final Map<String, Object> deserialized = _transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
@Test( enabled = true )
public void testCollections() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setAttribute( "foo", new EntityWithCollections() );
final Map<String, Object> deserialized = _transcoder.deserializeAttributes( _transcoder.serializeAttributes( session, session.getAttributesInternal() ) );
assertDeepEquals( deserialized, session.getAttributesInternal() );
}
@Test( enabled = true )
public void testCyclicDependencies() throws Exception {
final MemcachedBackupSession session = _manager.createEmptySession();
session.setValid( true );
session.setCreationTime( System.currentTimeMillis() );
getField( StandardSession.class, "lastAccessedTime" ).set( session, System.currentTimeMillis() + 100 );
session.setMaxInactiveInterval( 600 );
final Person p1 = createPerson( "foo bar", Gender.MALE, 42, "foo.bar@example.org", "foo.bar@example.com" );
final Person p2 = createPerson( "bar baz", Gender.FEMALE, 42, "bar.baz@example.org", "bar.baz@example.com" );
p1.addFriend( p2 );
p2.addFriend( p1 );
session.setAttribute( "person1", p1 );
session.setAttribute( "person2", p2 );
final byte[] bytes = _transcoder.serializeAttributes( session, session.getAttributesInternal() );
assertDeepEquals( session.getAttributesInternal(), _transcoder.deserializeAttributes( bytes ) );
}
public static class EntityWithCollections {
private final String[] _bars;
private final List<String> _foos;
private final Map<String, Integer> _bazens;
public EntityWithCollections() {
_bars = new String[] { "foo", "bar" };
_foos = new ArrayList<String>( Arrays.asList( "foo", "bar" ) );
_bazens = new HashMap<String, Integer>();
_bazens.put( "foo", 1 );
_bazens.put( "bar", 2 );
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode( _bars );
result = prime * result + ( ( _bazens == null )
? 0
: _bazens.hashCode() );
result = prime * result + ( ( _foos == null )
? 0
: _foos.hashCode() );
return result;
}
@Override
public boolean equals( final Object obj ) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final EntityWithCollections other = (EntityWithCollections) obj;
if ( !Arrays.equals( _bars, other._bars ) ) {
return false;
}
if ( _bazens == null ) {
if ( other._bazens != null ) {
return false;
}
} else if ( !_bazens.equals( other._bazens ) ) {
return false;
}
if ( _foos == null ) {
if ( other._foos != null ) {
return false;
}
} else if ( !_foos.equals( other._foos ) ) {
return false;
}
return true;
}
}
private Field getField( final Class<?> clazz, final String name ) throws NoSuchFieldException {
final Field field = clazz.getDeclaredField( name );
field.setAccessible( true );
return field;
}
/*
* person2=Person [_gender=FEMALE, _name=bar baz, _props={email0=Email
* [_email=bar.baz@example.org, _name=bar baz], email1=Email
* [_email=bar.baz@example.com, _name=bar baz]}], person1=Person
* [_gender=MALE, _name=foo bar, _props={email0=Email
* [_email=foo.bar@example.org, _name=foo bar], email1=Email
* [_email=foo.bar@example.com, _name=foo bar]}]}
*
* but was: person2={name=bar baz, props={email0={name=bar baz,
* email=bar.baz@example.org}, email1={name=bar baz,
* email=bar.baz@example.com}}, gender=FEMALE} person1={name=foo bar,
* props={email0={name=foo bar, email=foo.bar@example.org}, email1={name=foo
* bar, email=foo.bar@example.com}}, gender=MALE}}
*/
private void assertDeepEquals( final Object one, final Object another ) throws Exception {
assertDeepEquals( one, another, new IdentityHashMap<Object, Object>() );
}
private void assertDeepEquals( final Object one, final Object another, final Map<Object, Object> alreadyChecked )
throws Exception {
if ( one == another ) {
return;
}
if ( one == null && another != null || one != null && another == null ) {
Assert.fail( "One of both is null: " + one + ", " + another );
}
if ( alreadyChecked.containsKey( one ) ) {
return;
}
alreadyChecked.put( one, another );
Assert.assertEquals( one.getClass(), another.getClass() );
if ( one.getClass().isPrimitive() || one instanceof String || one instanceof Character || one instanceof Boolean ) {
Assert.assertEquals( one, another );
return;
}
if ( Map.class.isAssignableFrom( one.getClass() ) ) {
final Map<?, ?> m1 = (Map<?, ?>) one;
final Map<?, ?> m2 = (Map<?, ?>) another;
Assert.assertEquals( m1.size(), m2.size() );
for ( final Map.Entry<?, ?> entry : m1.entrySet() ) {
assertDeepEquals( entry.getValue(), m2.get( entry.getKey() ) );
}
return;
}
if ( Number.class.isAssignableFrom( one.getClass() ) ) {
Assert.assertEquals( ( (Number) one ).longValue(), ( (Number) another ).longValue() );
return;
}
if ( one instanceof Currency ) {
// Check that the transient field defaultFractionDigits is initialized correctly (that was issue #34)
final Currency currency1 = ( Currency) one;
final Currency currency2 = ( Currency) another;
Assert.assertEquals( currency1.getCurrencyCode(), currency2.getCurrencyCode() );
Assert.assertEquals( currency1.getDefaultFractionDigits(), currency2.getDefaultFractionDigits() );
}
Class<? extends Object> clazz = one.getClass();
while ( clazz != null ) {
assertEqualDeclaredFields( clazz, one, another, alreadyChecked );
clazz = clazz.getSuperclass();
}
}
private void assertEqualDeclaredFields( final Class<? extends Object> clazz, final Object one, final Object another,
final Map<Object, Object> alreadyChecked ) throws Exception, IllegalAccessException {
for ( final Field field : clazz.getDeclaredFields() ) {
field.setAccessible( true );
if ( !Modifier.isTransient( field.getModifiers() ) ) {
assertDeepEquals( field.get( one ), field.get( another ), alreadyChecked );
}
}
}
protected byte[] serialize( final Object o ) {
if ( o == null ) {
throw new NullPointerException( "Can't serialize null" );
}
XMLObjectWriter writer = null;
try {
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
writer = XMLObjectWriter.newInstance( bos );
final XMLReferenceResolver xmlReferenceResolver = new XMLReferenceResolver();
xmlReferenceResolver.setIdentifierAttribute( JavolutionTranscoder.REFERENCE_ATTRIBUTE_ID );
xmlReferenceResolver.setReferenceAttribute( JavolutionTranscoder.REFERENCE_ATTRIBUTE_REF_ID );
writer.setReferenceResolver( xmlReferenceResolver );
writer.setBinding( new ReflectionBinding( getClass().getClassLoader() ) );
writer.write( o, "session" );
writer.flush();
return bos.toByteArray();
} catch ( final Exception e ) {
throw new IllegalArgumentException( "Non-serializable object", e );
} finally {
try {
writer.close();
} catch ( final XMLStreamException e ) {
// fail silently
}
}
}
protected Object deserialize( final byte[] in ) {
XMLObjectReader reader = null;
try {
final ByteArrayInputStream bis = new ByteArrayInputStream( in );
reader = XMLObjectReader.newInstance( bis );
final XMLReferenceResolver xmlReferenceResolver = new XMLReferenceResolver();
xmlReferenceResolver.setIdentifierAttribute( JavolutionTranscoder.REFERENCE_ATTRIBUTE_ID );
xmlReferenceResolver.setReferenceAttribute( JavolutionTranscoder.REFERENCE_ATTRIBUTE_REF_ID );
reader.setReferenceResolver( xmlReferenceResolver );
reader.setBinding( new ReflectionBinding( getClass().getClassLoader() ) );
if ( !reader.hasNext() ) {
throw new IllegalStateException( "reader has no input" );
}
return reader.read( "session" );
} catch ( final RuntimeException e ) {
throw e;
} catch ( final javolution.xml.stream.XMLStreamException e ) {
throw new RuntimeException( e );
} finally {
try {
reader.close();
} catch ( final XMLStreamException e ) {
// fail silently
}
}
}
}