/*********************************************************************
* JavolutionAdapter.java
* created on 13.08.2004 by netseeker
* $Source$
* $Date$
* $Revision$
*
* ====================================================================
*
* Copyright 2005-2006 netseeker aka Michael Manske
*
* 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.
* ====================================================================
*
* This file is part of the ejoe framework.
* For more information on the author, please see
* <http://www.manskes.de/>.
*
*********************************************************************/
package de.netseeker.ejoe.adapter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.xml.XmlElement;
import javolution.xml.XmlFormat;
import javolution.xml.XmlInputStream;
import javolution.xml.XmlOutputStream;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import de.netseeker.ejoe.request.RemotingRequest;
/**
* An adapter for (de)serializing objects via the javolution library
*
* @author netseeker
* @since 0.3.9.1
* @see http://javolution.org/
*/
public class JavolutionAdapter extends BaseAdapter
{
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger( JavolutionAdapter.class.getName() );
private static final String DATE_FORMAT = "yyMMddHHmmssZ";
/**
* Creates a new instance of JavolutionAdapter preconfigured with additional custom XmlFormats for
* <ul>
* <li>java.math.BigDecimal</li>
* <li>java.math.BigInteger</li>
* </ul>
*/
public JavolutionAdapter()
{
this( new Class[] {}, new XmlFormat[] {} );
}
/**
* Creates a new instance of JavolutionAdapter preconfigured with the provided XmlFormats.
*
* @param classes array of classes for which custom XmlFormats are provided in the formats parameter
* @param formats array of XmlFormats
*/
public JavolutionAdapter(Class[] classes, XmlFormat[] formats)
{
XmlFormat.setFormat( BigDecimal.class, BigDecimalFormat );
XmlFormat.setFormat( BigInteger.class, BigIntegerFormat );
XmlFormat.setFormat( Date.class, DateFormat );
XmlFormat.setFormat( String[].class, StringArrayFormat );
XmlFormat.setFormat( byte[].class, ByteArrayFormat );
XmlFormat.setFormat( RemotingRequest.class, RemotingRequestFormat );
for ( int i = 0; i < classes.length; i++ )
{
if ( !(XmlFormat.getInstance( classes[i] ).equals( formats[i] )) )
{
XmlFormat.setFormat( classes[i], formats[i] );
}
}
}
/*
* (non-Javadoc)
*
* @see de.netseeker.ejoe.adapter.SerializeAdapter#read(java.io.InputStream)
*/
public Object read( InputStream in ) throws Exception
{
XmlInputStream reader = new XmlInputStream();
Object obj = null;
try
{
reader.setInputStream( in );
obj = reader.readObject();
}
finally
{
reader.close();
}
return obj;
}
/*
* (non-Javadoc)
*
* @see de.netseeker.ejoe.adapter.SerializeAdapter#write(java.lang.Object, java.io.OutputStream)
*/
public void write( Object obj, OutputStream out ) throws Exception
{
XmlOutputStream writer = new XmlOutputStream();
try
{
writer.setOutputStream( out );
writer.writeObject( obj );
}
finally
{
writer.close();
}
}
/*
* (non-Javadoc)
*
* @see de.netseeker.ejoe.adapter.BaseAdapter#getContentType()
*/
public String getContentType()
{
return "text/xml";
}
private static final XmlFormat BigDecimalFormat = new XmlFormat( BigDecimal.class )
{
public void format( Object foo, XmlElement xml )
{
xml.setAttribute( "value", foo.toString() );
}
public Object parse( XmlElement xml )
{
BigDecimal foo = new BigDecimal( xml
.getAttribute( "value", "-1" ) );
return foo;
}
};
private static final XmlFormat BigIntegerFormat = new XmlFormat( BigInteger.class )
{
public void format( Object foo, XmlElement xml )
{
xml.setAttribute( "value", foo.toString() );
}
public Object parse( XmlElement xml )
{
BigInteger foo = new BigInteger( xml
.getAttribute( "value", "-1" ) );
return foo;
}
};
private static final XmlFormat DateFormat = new XmlFormat( Date.class )
{
SimpleDateFormat sdf = new SimpleDateFormat(
DATE_FORMAT );
public void format( Object foo, XmlElement xml )
{
xml
.setAttribute( "value", sdf
.format( (Date) foo ) );
}
public Object parse( XmlElement xml )
{
Date foo = null;
try
{
foo = sdf.parse( xml
.getAttribute( "value", "" ) );
}
catch ( ParseException e )
{
}
return foo;
}
};
private static final XmlFormat StringArrayFormat = new XmlFormat( String[].class )
{
public void format( Object foo, XmlElement xml )
{
String[] arr = (String[]) foo;
int len = arr.length;
int prelen = len - 1;
StringBuffer sb = new StringBuffer();
for ( int i = 0; i < len; i++ )
{
sb.append( arr[i] );
if ( i < prelen ) sb.append( ',' );
}
xml.setAttribute( "value", sb.toString() );
}
public Object parse( XmlElement xml )
{
return xml.getAttribute( "value", "" ).split( "," );
}
};
private static final XmlFormat RemotingRequestFormat = new XmlFormat( RemotingRequest.class )
{
public void format( Object foo, XmlElement xml )
{
RemotingRequest r = (RemotingRequest) foo;
xml.setAttribute( "clazz", r.getClazz() );
xml.setAttribute( "mtd", r.getMethod() );
Object[] args = r.getArgs();
xml.setAttribute( "entries",
new Integer( args.length ) );
int i = 0;
for ( ; i < args.length; i++ )
{
xml.add( args[i], "arg" + i );
}
}
public Object parse( XmlElement xml )
{
RemotingRequest r = new RemotingRequest();
r.setClazz( xml.getAttribute( "clazz", "" ) );
r.setMethod( xml.getAttribute( "mtd", "" ) );
int entries = xml.getAttribute( "entries",
new Integer( 0 ) )
.intValue();
if ( entries > 0 )
{
Object args[] = new Object[entries];
for ( int i = 0; i < entries; i++ )
{
args[i] = xml.get( "arg" + i );
}
r.setArgs( args );
}
return r;
}
};
private static final XmlFormat ByteArrayFormat = new XmlFormat( byte[].class )
{
public void format( Object foo, XmlElement xml )
{
byte[] bArray = (byte[]) foo;
BASE64Encoder enc = new BASE64Encoder();
xml.add( enc.encode( bArray ), "bArray" );
}
public Object parse( XmlElement xml )
{
String bString = (String) xml.get( "bArray" );
BASE64Decoder dec = new BASE64Decoder();
byte[] result = null;
try
{
result = dec.decodeBuffer( bString );
}
catch ( IOException e )
{
logger
.log(
Level.SEVERE,
"Error occured while deserializing Base64 encoded array of bytes!",
e );
}
return result;
}
};
}