package com.c2kernel.utils; //Java import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; import java.util.HashSet; import java.util.StringTokenizer; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; import org.exolab.castor.xml.ValidationException; import com.c2kernel.common.InvalidDataException; import com.c2kernel.persistency.outcome.Outcome; /************************************************************************** * Loads all mapfiles, and wraps marshalling/unmarshalling * * @author $Author: abranson $ $Date: 2004/10/20 14:10:21 $ * @version $Revision: 1.12 $ **************************************************************************/ public class CastorXMLUtility { private final Mapping mMapping = new Mapping(); private final HashSet mMappingKeys = new HashSet(); /** * Looks for a file called 'index.xml' at the given URL, and loads every file * listed in there by relative path * * @param mapURL - map root */ public CastorXMLUtility(URL mapURL) throws InvalidDataException { // load index Logger.msg(3, "Loading maps from "+mapURL); String index; try { index = FileStringUtility.url2String( new URL(mapURL, "index") ); } catch (Exception e) { Logger.warning("Could not load map index from "+mapURL.toString()); return; } StringTokenizer sTokenizer = new StringTokenizer(index); while( sTokenizer.hasMoreTokens() ) { String thisMap = sTokenizer.nextToken(); try { addMapping( new URL(mapURL, thisMap)); } catch (Exception e) { Logger.error(e); throw new InvalidDataException("Error loading map '"+thisMap+"'", ""); } } // Test the maps now, instead of on first use. try { new Unmarshaller( mMapping ); } catch (MappingException e) { Logger.error(e); throw new InvalidDataException("Castor mapfiles are not valid", ""); } Logger.msg(1, "Loaded all maps from "+mapURL.toString()); } /************************************************************************** * Updates a mapping referenced by the mapID. * The same mapping cannot be loaded many times as it generates an exception. * That is the reason for this method as it maintains the HashSet of MappingKeys. **************************************************************************/ private void addMapping( URL mapID ) throws IOException, MappingException, MarshalException, ValidationException { if( !mMappingKeys.contains(mapID) ) { Logger.msg(7, "Added mapping file:"+mapID); mMapping.loadMapping( mapID ); mMappingKeys.add( mapID ); } else { Logger.msg(1, "Map file already loaded:"+mapID); } } /************************************************************************** * Marshalls a mapped object to string. The mapping must be loaded before. * See updateMapping(). **************************************************************************/ public String marshall( Object obj ) throws IOException, MappingException, MarshalException, ValidationException { if (obj == null) return ""; if (obj instanceof Outcome) return ((Outcome)obj).getData(); StringWriter sWriter = new StringWriter(); Marshaller marshaller = new Marshaller( sWriter ); marshaller.setMapping( mMapping ); marshaller.setMarshalAsDocument( false ); marshaller.marshal( obj ); return sWriter.toString(); } /************************************************************************** * Unmarshalls a mapped object from string. The mapping must be loaded before. * See updateMapping(). **************************************************************************/ public Object unmarshall( String data ) throws IOException, MappingException, MarshalException, ValidationException { StringReader sReader = new StringReader( data ); Unmarshaller unmarshaller = new Unmarshaller( mMapping ); if (data.equals("")) return null; return unmarshaller.unmarshal( sReader ); } }