blob: 1a4d58862e81f7d08a2b5103d14db6569dcf40f7 [file] [log] [blame]
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";
}