/*
* Copyright 2010 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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javolution.xml.XMLBinding;
import javolution.xml.XMLObjectReader;
import javolution.xml.XMLObjectWriter;
import javolution.xml.XMLReferenceResolver;
import javolution.xml.stream.XMLStreamException;
import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.core.Predicate;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.InvocationHandler;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
/**
* Test for {@link CGLibProxyFormat}.
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class CGLibProxyFormatTest {
private static final Log LOG = LogFactory.getLog( CGLibProxyFormatTest.class );
private ReflectionBinding _binding;
@BeforeTest
protected void beforeTest() {
_binding = new ReflectionBinding( getClass().getClassLoader(), false, new CGLibProxyFormat() );
}
@Test( enabled = true )
public void testCGLibProxy() throws XMLStreamException {
final ClassToProxy proxy = createProxy( new ClassToProxy() );
proxy.setValue( "foo" );
final byte[] serialized = serialize( proxy, _binding );
System.out.println( new String( serialized ) );
final ClassToProxy deserialized = deserialize( serialized, _binding );
Assert.assertEquals( deserialized.getValue(), proxy.getValue() );
}
/**
* Test that a proxy for another existing xmlformat is handled correctly.
*
* @throws XMLStreamException
*/
@Test( enabled = true )
public void testCGLibProxyForExistingFormat() throws XMLStreamException {
final Map<String, String> proxy = createProxy( new HashMap<String, String>() );
proxy.put( "foo", "bar" );
Assert.assertEquals( proxy.get( "foo" ), "bar" );
final byte[] serialized = serialize( proxy, _binding );
System.out.println( new String( serialized ) );
final Map<String, String> deserialized = deserialize( serialized, _binding );
Assert.assertEquals( deserialized.get( "foo" ), proxy.get( "foo" ) );
}
@SuppressWarnings( "unchecked" )
private <T> T createProxy( final T obj ) {
final Enhancer e = new Enhancer();
e.setInterfaces( new Class[] { Serializable.class } );
final Class<? extends Object> class1 = obj.getClass();
e.setSuperclass( class1 );
e.setCallback( new DelegatingHandler( obj ) );
e.setNamingPolicy( new DefaultNamingPolicy() {
@Override
public String getClassName(final String prefix, final String source,
final Object key, final Predicate names) {
return super.getClassName( "MSM_" + prefix, source, key, names );
}
} );
return (T) e.create();
}
protected byte[] serialize( final Object o, final XMLBinding binding ) {
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( binding );
writer.write( o, "root" );
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 <T> T deserialize( final byte[] in, final XMLBinding binding ) {
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( binding );
if ( !reader.hasNext() ) {
throw new IllegalStateException( "reader has no input" );
}
return reader.<T> read( "root" );
} catch ( final RuntimeException e ) {
LOG.error( "Could not deserialize.", e );
throw e;
} catch ( final javolution.xml.stream.XMLStreamException e ) {
LOG.error( "Could not deserialize.", e );
throw new RuntimeException( e );
} finally {
try {
reader.close();
} catch ( final XMLStreamException e ) {
// fail silently
}
}
}
public static class DelegatingHandler implements InvocationHandler, Serializable {
private static final long serialVersionUID = 1L;
private final Object _delegate;
public DelegatingHandler( final Object delegate ) {
_delegate = delegate;
}
public Object invoke( final Object obj, final Method method, final Object[] args ) throws Throwable {
return method.invoke( _delegate, args );
}
}
public static class ClassToProxy {
private String _value;
/**
* @param value the value to set
*/
public void setValue( final String value ) {
_value = value;
}
/**
* @return the value
*/
public String getValue() {
return _value;
}
}
}