| package jpos.config.simple.xml; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // This software is provided "AS IS". The JavaPOS working group (including |
| // each of the Corporate members, contributors and individuals) MAKES NO |
| // REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, |
| // EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED |
| // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| // NON-INFRINGEMENT. The JavaPOS working group shall not be liable for |
| // any damages suffered as a result of using, modifying or distributing this |
| // software or its derivatives. Permission to use, copy, modify, and distribute |
| // the software and its documentation for any purpose is hereby granted. |
| // |
| // The JavaPOS Config/Loader (aka JCL) is now under the CPL license, which |
| // is an OSS Apache-like license. The complete license is located at: |
| // http://oss.software.ibm.com/developerworks/opensource/license-cpl.html |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| import java.io.*; |
| import java.util.*; |
| |
| import java.io.FileInputStream; |
| |
| import org.w3c.dom.*; |
| |
| import org.xml.sax.InputSource; |
| |
| import jpos.config.*; |
| import jpos.config.simple.*; |
| import jpos.util.*; |
| import jpos.util.tracing.Tracer; |
| import jpos.util.tracing.TracerFactory; |
| |
| /** |
| * Simple implementation of the JposRegPopulator that loads and saves |
| * the entries in XML using the "jpos/res/jcl.dtd" DTD and the XML4J |
| * (Xerces) API |
| * NOTE: this class must define a public no-argument ctor so that it may be |
| * created via reflection when its defined in the jpos.properties as |
| * the jpos.config.regPopulatorClass |
| * @see jpos.util.JposProperties#JPOS_REG_POPULATOR_CLASS_PROP_NAME |
| * @since 1.2 (NY 2K meeting) |
| * @author E. Michael Maximilien (maxim@us.ibm.com) |
| */ |
| public class XercesRegPopulator extends AbstractXercesRegPopulator |
| { |
| //------------------------------------------------------------------------- |
| // Ctor(s) |
| // |
| |
| /** |
| * Default ctor |
| * @since 1.2 (NY 2K meeting) |
| */ |
| public XercesRegPopulator() |
| { super( XercesRegPopulator.class.getName() ); } |
| |
| /** |
| * 1-arg constructor that takes the unique ID |
| * @param s the unique ID string |
| * @since 1.3 (Washington DC 2001) |
| */ |
| public XercesRegPopulator( String s ) { super( s ); } |
| |
| //------------------------------------------------------------------------- |
| // Public methods |
| // |
| |
| /** |
| * @return the fully qualified class name implementing the |
| * JposRegPopulator interface |
| * @since 1.3 (Washington DC 2001 meeting) |
| */ |
| public String getClassName() |
| { return XercesRegPopulator.class.getName(); } |
| |
| /** |
| * Tell the populator to load the entries |
| * @since 1.2 (NY 2K meeting) |
| */ |
| public void load() |
| { |
| tracer.println( "load(): isPopulatorFileDefined=" + |
| isPopulatorFileDefined() ); |
| |
| if( isPopulatorFileDefined() == false ) |
| { |
| getJposEntries().clear(); |
| xmlFileName = DEFAULT_XML_FILE_NAME; |
| load( xmlFileName ); |
| |
| return; |
| } |
| |
| try |
| { |
| getJposEntries().clear(); |
| |
| domParser.setEntityResolver(new XercesRegPopulator.JPOSDTDEntityResolver()); |
| |
| domParser.parse( new InputSource( getPopulatorFileIS() ) ); |
| |
| Document document = domParser.getDocument(); |
| |
| Enumeration entries = extractJposEntries( document ); |
| |
| while( entries.hasMoreElements() ) |
| { |
| JposEntry jposEntry = (JposEntry)entries.nextElement(); |
| |
| if( jposEntry.hasPropertyWithName( JposEntry. |
| LOGICAL_NAME_PROP_NAME ) ) |
| getJposEntries().put( jposEntry.getLogicalName(), |
| jposEntry ); |
| } |
| |
| lastLoadException = null; |
| } |
| catch( Exception e ) |
| { |
| lastLoadException = e; |
| tracer.println( "Error loading XML file. Exception.msg = " + |
| e.getMessage() ); |
| } |
| finally |
| { } |
| } |
| |
| /** |
| * Loads the entries specified in the xmlFileName |
| * @param xmlFileName the XML file name |
| * @since 1.3 (SF 2K meeting) |
| */ |
| public void load( String xmlFileName ) |
| { |
| tracer.println( "load: xmlFileName=" + xmlFileName ); |
| |
| InputStream is = null; |
| File xmlFile = new File( xmlFileName ); |
| |
| try |
| { |
| if( xmlFile.exists() ) |
| is = new FileInputStream( xmlFile ); |
| else |
| is = findFileInClasspath( xmlFileName ); |
| |
| if (is == null) |
| { |
| is = getClass().getClassLoader().getResourceAsStream(xmlFileName); |
| } |
| |
| if( is == null ) |
| { |
| getJposEntries().clear(); |
| |
| tracer.println( "Could not find file: " + xmlFileName + |
| " in path or CLASSPATH" ); |
| |
| lastLoadException = new FileNotFoundException( xmlFileName ); |
| |
| return; |
| } |
| |
| lastLoadException = null; |
| } |
| catch( Exception e ) |
| { |
| lastLoadException = e; |
| tracer.println( "Error loading XML file. Exception.message = " + |
| e.getMessage() ); |
| } |
| |
| try |
| { |
| getJposEntries().clear(); |
| |
| domParser.setEntityResolver(new XercesRegPopulator.JPOSDTDEntityResolver()); |
| |
| domParser.parse( new InputSource( is ) ); |
| |
| Document document = domParser.getDocument(); |
| |
| Enumeration entries = extractJposEntries( document ); |
| |
| while( entries.hasMoreElements() ) |
| { |
| JposEntry jposEntry = (JposEntry)entries.nextElement(); |
| |
| if( jposEntry.hasPropertyWithName( JposEntry. |
| LOGICAL_NAME_PROP_NAME ) ) |
| getJposEntries().put( jposEntry.getLogicalName(), |
| jposEntry ); |
| } |
| |
| lastLoadException = null; |
| |
| } |
| catch( Exception e ) |
| { |
| lastLoadException = e; |
| tracer.println( "Error loading XML file. Exception.message = " + |
| e.getMessage() ); |
| } |
| finally |
| { } |
| } |
| |
| /** |
| * @return the name of this populator. This should be a short descriptive name |
| * @since 1.3 (Washington DC 2001 meeting) |
| */ |
| public String getName() { return XERCES_REG_POPULATOR_NAME_STRING; } |
| |
| //-------------------------------------------------------------------------- |
| // Protected methods |
| // |
| |
| /** |
| * @return an enumeration of JposEntry objects read from the XML document object |
| * @param document the XML document object |
| * @since 1.2 (NY 2K meeting) |
| */ |
| protected Enumeration extractJposEntries( Document document ) |
| { |
| Vector entries = new Vector(); |
| |
| NodeList nodeList = document.getElementsByTagName( "JposEntry" ); |
| |
| String currentEntryLogicalName = ""; |
| |
| try |
| { |
| for( int i = 0; i < nodeList.getLength(); ++i ) |
| { |
| Node node = nodeList.item( i ); |
| |
| if( node.getNodeType() != Node.ELEMENT_NODE ) |
| continue; |
| |
| JposEntry jposEntry = new SimpleEntry(); |
| |
| Element jposEntryElement = (Element)node; |
| |
| currentEntryLogicalName = jposEntryElement. |
| getAttribute( "logicalName" ); |
| jposEntry.addProperty( "logicalName", currentEntryLogicalName ); |
| |
| NodeList childList = nodeList.item( i ).getChildNodes(); |
| |
| for( int j = 0; j < childList.getLength(); ++j ) |
| { |
| Node child = childList.item( j ); |
| |
| if( child.getNodeType() != Node.ELEMENT_NODE ) |
| continue; |
| |
| Element element = (Element)child; |
| |
| String elementName = element.getNodeName(); |
| |
| if( elementName.equals( "creation" ) ) |
| extractCreationAttr( jposEntry, element ); |
| else |
| if( elementName.equals( "vendor" ) ) |
| extractVendorAttr( jposEntry, element ); |
| else |
| if( elementName.equals( "jpos" ) ) |
| extractJposAttr( jposEntry, element ); |
| else |
| if( elementName.equals( "product" ) ) |
| extractProductAttr( jposEntry, element ); |
| else |
| extractPropAttr( jposEntry, element ); |
| } |
| |
| if( JposEntryUtility.isValidJposEntry( jposEntry ) ) |
| entries.addElement( jposEntry ); |
| else |
| { |
| String msg = "JposEntry with logicalName: " + |
| currentEntryLogicalName + |
| " is not valid (missing required properties)"; |
| throw new JposConfigException( msg ); |
| } |
| } |
| } |
| catch( JposConfigException jce ) |
| { |
| tracer.println( "Skipping invalid entry with logicalName: " + |
| currentEntryLogicalName ); |
| tracer.println( "--->JposConfigException.message = " + |
| jce.getMessage() ); |
| |
| tracer.print( jce ); |
| |
| if( jce.getOrigException() != null ) |
| tracer.print( jce.getOrigException() ); |
| } |
| |
| return entries.elements(); |
| } |
| |
| /** |
| * Get the <creation> element attributes and adds corresponding |
| * properties to JposEntry |
| * @param jposEntry the entry to add properties to |
| * @param element the <creation> XML element |
| * @since 1.2 (NY 2K meeting) |
| */ |
| protected void extractCreationAttr( JposEntry jposEntry, Element element ) |
| { |
| jposEntry.addProperty( "serviceInstanceFactoryClass", |
| element.getAttribute( "factoryClass" ) ); |
| |
| jposEntry.addProperty( "serviceClass", |
| element.getAttribute( "serviceClass" ) ); |
| } |
| |
| /** |
| * Get the <vendor> element attributes and adds corresponding |
| * properties to JposEntry |
| * @param jposEntry the entry to add properties to |
| * @param element the <vendor> XML element |
| * @since 1.2 (NY 2K meeting) |
| */ |
| protected void extractVendorAttr( JposEntry jposEntry, Element element ) |
| { |
| jposEntry.addProperty( "vendorName", element.getAttribute( "name" ) ); |
| jposEntry.addProperty( "vendorURL", element.getAttribute( "url" ) ); |
| } |
| |
| /** |
| * Get the <jpos> element attributes and adds corresponding properties |
| * to JposEntry |
| * @param jposEntry the entry to add properties to |
| * @param element the <jpos> XML element |
| * @since 1.2 (NY 2K meeting) |
| */ |
| protected void extractJposAttr( JposEntry jposEntry, Element element ) |
| { |
| jposEntry.addProperty( "jposVersion", |
| element.getAttribute( "version" ) ); |
| |
| jposEntry.addProperty( "deviceCategory", |
| element.getAttribute( "category" ) ); |
| } |
| |
| /** |
| * Get the <product> element attributes and adds corresponding |
| * properties to JposEntry |
| * @param jposEntry the entry to add properties to |
| * @param element the <product> XML element |
| * @since 1.2 (NY 2K meeting) |
| */ |
| protected void extractProductAttr( JposEntry jposEntry, Element element ) |
| { |
| jposEntry.addProperty( "productName", element.getAttribute( "name" ) ); |
| |
| jposEntry.addProperty( "productDescription", |
| element.getAttribute( "description" ) ); |
| |
| jposEntry.addProperty( "productURL", element.getAttribute( "url" ) ); |
| } |
| |
| /** |
| * Get the <prop> element attributes and adds corresponding properties |
| * to JposEntry |
| * @param jposEntry the entry to add properties to |
| * @param element the <prop> XML element |
| * @since 1.2 (NY 2K meeting) |
| * @throws jpos.config.JposConfigException if the property value does |
| * not match the type or is not a valid value (like for instance |
| * an invalid number) |
| */ |
| protected void extractPropAttr( JposEntry jposEntry, Element element ) |
| throws JposConfigException |
| { |
| String propName = element.getAttribute( "name" ); |
| String propValueString = element.getAttribute( "value" ); |
| String propTypeString = element.getAttribute( "type" ); |
| |
| if( propTypeString.equals( "" ) ) propTypeString = "String"; |
| |
| Object propValue = null; |
| Class propType = null; |
| |
| try |
| { |
| propType = Class.forName( ( propTypeString. |
| startsWith( "java.lang." ) ? |
| propTypeString : |
| "java.lang." + propTypeString ) ); |
| } |
| catch( ClassNotFoundException cnfe ) |
| { |
| throw new JposConfigException( "Invalid property type: " + |
| propTypeString + |
| " for property named: " + |
| propName , cnfe ); |
| } |
| |
| if( JposEntryUtility.isValidPropType( propType ) == false ) |
| throw new JposConfigException( "Invalid property type: " + |
| propTypeString + |
| " for property named: " + |
| propName ); |
| |
| propValue = JposEntryUtility. |
| parsePropValue( propValueString, propType ); |
| |
| if( JposEntryUtility.validatePropValue( propValue, propType ) == false ) |
| throw new JposConfigException( "Invalid property type: " + |
| propTypeString + |
| " for property named: " + |
| propName ); |
| |
| jposEntry.add( jposEntry.createProp( propName, propValue, propType ) ); |
| } |
| |
| /** |
| * JposDTDEntityResolver to resolve DTD |
| */ |
| public class JPOSDTDEntityResolver implements org.xml.sax.EntityResolver |
| { |
| /** |
| * @return the DTD as an InputSource if it is found in a JAR |
| * file in the CLASSPATH otherwise return null |
| */ |
| public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) throws org.xml.sax.SAXException, java.io.IOException |
| { |
| if (publicId.equals("-//JavaPOS//DTD//EN")) |
| { |
| InputStream is = getClass().getResourceAsStream( DTD_JAR_FILE_NAME ); |
| |
| if (is != null) |
| { |
| return (new org.xml.sax.InputSource(new InputStreamReader(is))); |
| } |
| } |
| |
| return null; |
| } |
| |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Instance variables |
| // |
| |
| private Tracer tracer = TracerFactory.getInstance(). |
| createTracer( "XercesRegPopulator" ); |
| |
| //-------------------------------------------------------------------------- |
| // Public constants |
| // |
| |
| public static final String DTD_JAR_FILE_NAME = "/jpos/res/jcl.dtd"; |
| |
| public static final String XERCES_REG_POPULATOR_NAME_STRING = |
| "JCL XML Entries Populator"; |
| } |