package com.c2kernel.utils; //Java import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.HashSet; import java.util.Properties; 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 org.exolab.castor.xml.XMLContext; import com.c2kernel.common.InvalidDataException; import com.c2kernel.persistency.outcome.Outcome; import com.c2kernel.process.resource.ResourceLoader; /************************************************************************** * Loads all mapfiles, and wraps marshalling/unmarshalling * * @author $Author: abranson $ $Date: 2004/10/20 14:10:21 $ * @version $Revision: 1.12 $ **************************************************************************/ public class CastorXMLUtility{ public static final String CASTOR_XML_SERIALIZER_FACTORY = "org.exolab.castor.xml.serializer.factory"; private XMLContext pCastorContext; /** * Looks for a file called 'index.xml' at the given URL, and loads every * file listed in there by relative path * * @param aResourceLoader * the resource loader able to return the right class loader * @param aAppProperties * the application properties containint optionnal castor * configuration * @param aMapsSubPath * the map root sub path (in the kernel path) * @throws InvalidDataException */ public CastorXMLUtility(final ResourceLoader aResourceLoader, final Properties aAppProperties, final String aMapsSubPath) throws InvalidDataException { // build base url URL wMapsURL ; try { wMapsURL = aResourceLoader.getKernelResourceURL(aMapsSubPath); } catch (MalformedURLException e) { throw new InvalidDataException(String.format( "Invalid Resource Location [%s]. Cause:%s", aMapsSubPath, e.getLocalizedMessage())); } // load index Logger.msg(3,String.format( "CastorXMLUtility. Loading maps from [%s]",wMapsURL)); String index; try { index = FileStringUtility.url2String( new URL(wMapsURL, "index") ); } catch (Exception e) { throw new InvalidDataException(String.format("Could not load map index from [%s]",wMapsURL)); } // retrieve the class loader of the class "CastorXMLUtility" ClassLoader wKernelClassLoader = aResourceLoader .getClassLoader(CastorXMLUtility.class.getName()); Logger.msg(3, String.format( "CastorXMLUtility.: iuse KernelClassLoader=[%s]", wKernelClassLoader)); StringTokenizer sTokenizer = new StringTokenizer(index); int wNbMap = sTokenizer.countTokens(); // init the castor mapping using the classloader of the class "CastorXMLUtility" Mapping wCastorMapping = new Mapping(wKernelClassLoader); HashSet loadedMapURLs = new HashSet(); try { int wMapIdx=0; while( sTokenizer.hasMoreTokens() ) { String wCurrentMap = sTokenizer.nextToken(); URL wCurrentMapURL = new URL(wMapsURL, wCurrentMap); wMapIdx++; if( !loadedMapURLs.contains(wCurrentMapURL) ) { Logger.msg( 3, String.format( "CastorXMLUtility.: Adding mapping file (%d/%d):[%s]", wMapIdx, wNbMap, wCurrentMapURL)); wCastorMapping.loadMapping( wCurrentMapURL ); loadedMapURLs.add( wCurrentMapURL ); } else { Logger.msg(3,"Map file already loaded:"+wCurrentMapURL); } } pCastorContext = new XMLContext(); pCastorContext.setClassLoader(wKernelClassLoader); // if the aAppProperties contains castor properties then if (aAppProperties.contains(CASTOR_XML_SERIALIZER_FACTORY)) { pCastorContext.setProperty(CASTOR_XML_SERIALIZER_FACTORY, aAppProperties .getProperty(CASTOR_XML_SERIALIZER_FACTORY)); Logger.msg(3, String.format( "CastorXMLUtility.: castor prop: %s=[%s]", CASTOR_XML_SERIALIZER_FACTORY, pCastorContext .getProperty(CASTOR_XML_SERIALIZER_FACTORY))); } pCastorContext.addMapping(wCastorMapping); } catch (MappingException ex) { Logger.error(ex); throw new InvalidDataException("XML Mapping files are not valid: "+ex.getMessage(), ""); } catch (MalformedURLException ex) { Logger.error(ex); throw new InvalidDataException("Mapping file location invalid: "+ex.getMessage(), ""); } catch (IOException ex) { Logger.error(ex); throw new InvalidDataException("Could not read XML mapping files: "+ex.getMessage(), ""); } Logger.msg(1, String.format("Loaded [%d] maps from [%s]",loadedMapURLs.size(),wMapsURL)); } /************************************************************************** * 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 = pCastorContext.createMarshaller(); marshaller.setWriter(sWriter); 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 { if (data.equals("")) return null; StringReader sReader = new StringReader( data ); Unmarshaller unmarshaller = pCastorContext.createUnmarshaller(); return unmarshaller.unmarshal( sReader ); } }