package gov.nih.nci.cagrid.encoding; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Hashtable; import java.util.Map; import org.apache.axis.MessageContext; import org.apache.axis.utils.ClassUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.exolab.castor.mapping.Mapping; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; public class EncodingUtils { public static final String CASTOR_MAPPING_DTD = "mapping.dtd"; public static final String CASTOR_MAPPING_DTD_ENTITY = "-//EXOLAB/Castor Object Mapping DTD Version 1.0//EN"; public static final String DEFAULT_XML_MAPPING = "/xml-mapping.xml"; public static final String CASTOR_MAPPING_PROPERTY = "castorMapping"; protected static Log LOG = LogFactory.getLog(EncodingUtils.class.getName()); // maps <mapping location> to bytes of the Mapping file // using Hashtable for synchronization correctness protected static Map<String, byte[]> mappingCacheMap = new Hashtable<String, byte[]>(); public static Mapping getMapping(MessageContext context) { return getMapping(context, CASTOR_MAPPING_PROPERTY); } private static Mapping getMapping(MessageContext context, String mappingProperty) { long startTime = System.currentTimeMillis(); EntityResolver resolver = new EntityResolver() { public InputSource resolveEntity(String publicId, String systemId) { if (publicId.equals(CASTOR_MAPPING_DTD_ENTITY)) { InputStream in = ClassUtils.getResourceAsStream(EncodingUtils.class, CASTOR_MAPPING_DTD); return new InputSource(in); } return null; } }; // determine the mapping location, starting with a default based on the // property String mappingLocation = DEFAULT_XML_MAPPING; if (context != null) { String prop = (String) context.getProperty(mappingProperty); if (prop != null && !prop.trim().equals("")) { // the property exists in the message context, use the property // value mappingLocation = prop; LOG.debug("Loading castor mapping from message context property[" + mappingProperty + "]"); } else { try { // attempt to find the property in the wsdd global // configuration prop = (String) context.getAxisEngine().getConfig().getGlobalOptions().get(mappingProperty); } catch (Exception e) { LOG.debug("Error reading global configuration:" + e.getMessage(), e); } if (prop != null && !prop.trim().equals("")) { mappingLocation = prop; LOG.debug("Loading castor mapping from globalConfiguration property[" + mappingProperty + "]"); } else { LOG.debug("Unable to locate castor mapping property[" + mappingProperty + "], using default mapping location:" + mappingLocation); } } } else { LOG.debug("Unable to determine message context, using default mapping location:" + mappingLocation); } // locate the bytes of the mapping file byte[] mappingBytes = null; if (mappingCacheMap.containsKey(mappingLocation)) { LOG.debug("Loading Mapping from cache for location:" + mappingLocation); mappingBytes = mappingCacheMap.get(mappingLocation); } else { LOG.debug("Unable to loading Mapping from cache for location:" + mappingLocation); LOG.debug("Attempting to load mapping from mapping location:" + mappingLocation); InputStream mappingStream = ClassUtils.getResourceAsStream(EncodingUtils.class, mappingLocation); if (mappingStream == null) { LOG.error("Mapping file [" + mappingLocation + "] was null!"); } else { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; int len = -1; try { while ((len = mappingStream.read(buffer)) != -1) { bos.write(buffer, 0, len); } mappingBytes = bos.toByteArray(); mappingCacheMap.put(mappingLocation, mappingBytes); mappingStream.close(); } catch (IOException ex) { LOG.error("Error loading mapping file [" + mappingLocation + "] : " + ex.getMessage(), ex); } } } ByteArrayInputStream mappingStream = new ByteArrayInputStream(mappingBytes); Mapping mapping = loadMappingFromStream(mappingLocation, mappingStream, resolver); long duration = System.currentTimeMillis() - startTime; LOG.debug("Time to load mapping file:" + duration + " ms."); return mapping; } private static Mapping loadMappingFromStream(String mappingLocation, InputStream mappingStream, EntityResolver resolver) { InputSource mappIS = new org.xml.sax.InputSource(mappingStream); Mapping mapping = new Mapping(); mapping.setEntityResolver(resolver); try { mapping.loadMapping(mappIS); } catch (Exception ex) { LOG.error("Error loading castor mapping (" + mappingLocation + "): " + ex.getMessage(), ex); } return mapping; } }