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.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.text.DateFormat; import java.util.Date; import java.util.Enumeration; import jpos.config.JposEntry; import jpos.config.Version; import jpos.config.simple.AbstractRegPopulator; import jpos.util.JposEntryUtility; import jpos.util.tracing.Tracer; import jpos.util.tracing.TracerFactory; import org.apache.xerces.dom.DOMImplementationImpl; import org.apache.xerces.parsers.DOMParser; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.w3c.dom.Attr; import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; /** * This class is an abstract super class for all Xerces based parser/reg * populator with functionality to serialize an enumeration of JposEntry * objects into XML * <p> * <b>NOTE</b>: 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 * </p> * @see jpos.util.JposProperties#JPOS_REG_POPULATOR_CLASS_PROP_NAME * @since 2.1.0 * @author E. Michael Maximilien (maxim@us.ibm.com) */ public abstract class AbstractXercesRegPopulator extends AbstractRegPopulator implements XmlRegPopulator { //------------------------------------------------------------------------- // Ctor(s) // /** * 1-arg constructor that takes the unique ID * @param s the unique ID string * @since 1.3 (Washington DC 2001) */ public AbstractXercesRegPopulator(String s) { super(s); } //------------------------------------------------------------------------- // Public methods // /** * Tell the populator to save the current entries * @param entries an enumeration of JposEntry objects * @since 1.2 (NY 2K meeting) * @throws java.lang.Exception if any error occurs while saving */ public void save(Enumeration entries) throws Exception { if (isPopulatorFileDefined()) convertJposEntriesToXml(entries, getPopulatorFileOS()); else convertJposEntriesToXml(entries, new FileOutputStream( getDefaultXmlFileName())); } /** * Tell the populator to save the current entries in the file specified * @param entries an enumeration of JposEntry objects * @param xmlFileName the XML file name to save entries * @since 1.3 (SF 2K meeting) * @throws java.lang.Exception if any error occurs while saving */ public void save(Enumeration entries, String xmlFileName) throws Exception { File xmlFile = new File(xmlFileName); FileOutputStream fos = new FileOutputStream(xmlFile); convertJposEntriesToXml(entries, fos); fos.close(); } /** * @return the URL pointing to the entries file loaded or saved * @since 1.2 (NY 2K meeting) */ public URL getEntriesURL() { URL url = null; if (getPopulatorFileURL() != null && !getPopulatorFileURL().equals("")) try { url = new URL(getPopulatorFileURL()); } catch (Exception e) { tracer.println("getEntriesURL: Exception.message=" + e.getMessage()); } else url = createURLFromFile(new File(getPopulatorFileName())); //<temp> tracer.println("getPopulatorFileURL()=" + getPopulatorFileURL()); tracer.println("getPopulatorFileName()=" + getPopulatorFileName()); //</temp> return url; } //-------------------------------------------------------------------------- // Protected methods // /** @return the Tracer object */ protected Tracer getTracer() { return tracer; } /** * @return the default XML file name that this populator will save * entries to */ protected String getDefaultXmlFileName() { return xmlFileName; } /** * Converts an Enumeration of JposEntry objects to XML * @param entries an Enumeration of JposEntry objects * @param os the OutputStream to stream the entries to * @exception java.lang.Exception if something goes wrong serializing * @since 1.2 (NY 2K meeting) */ protected void convertJposEntriesToXml(Enumeration entries, OutputStream os) throws Exception { Document document = getParser().getDocument(); serializeDocument(document, entries, os); } /** * @return the DOM parser object * @since 1.2 (NY 2K meeting) */ protected DOMParser getParser() { return domParser; } /** * Serializes the JposEntry objects to an XML document and save to OutputStream * @param document the XML document object * @param entries an Enumeration of JposEntry objects * @param os the OuputStream object * @exception java.lang.Exception anything goes wrong while saving * @since 1.2 (NY 2K meeting) */ protected void serializeDocument(Document document, Enumeration entries, OutputStream os) throws Exception { Document newDoc = createEmptyDocument(); insertJposEntriesInDoc(newDoc, entries); insertDateSavedComment(newDoc); OutputFormat outFormat = new OutputFormat("xml", "UTF-8", true); outFormat.setStandalone(false); outFormat.setIndenting(true); outFormat.setIndent(4); outFormat.setPreserveSpace(true); outFormat.setLineWidth(0); insertDTDInfo(newDoc, outFormat); PrintWriter outWriter = null; try { outWriter = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os, "UTF-8"))); } catch (UnsupportedEncodingException ex) { tracer.println("Error making PrintWriter: " + "UnsupportedEncodingException.message = " + ex.getMessage()); } if (outWriter != null) { XMLSerializer xmlSerializer = new XMLSerializer(outWriter, outFormat); xmlSerializer.serialize(newDoc); } } /** * @return a String with the document type definition value. For DTD this * would be the DTD relative path/file and for schemas the XSD * relative path/file * @since 2.1.0 */ protected String getDoctypeValue() { return "jpos/res/jcl.dtd"; } /** * Inset DTD information in the XML Document object * @param doc the XML Document object * @param outFormat the OuputFormat object * @exception java.lang.Exception in case something goes wrong * @since 1.2 (NY 2K meeting) */ protected void insertDTDInfo(Document doc, OutputFormat outFormat) throws Exception { //String publicId = OutputFormat.whichDoctypePublic(doc); //String systemId = OutputFormat.whichDoctypeSystem(doc); outFormat.setDoctype("JposEntries", getDoctypeValue()); } /** * @return an empty XML Document object * @since 1.2 (NY 2K meeting) */ protected Document createEmptyDocument() { DOMImplementationImpl domImpImpl = (DOMImplementationImpl) DOMImplementationImpl .getDOMImplementation(); DocumentType docType = domImpImpl.createDocumentType("JposEntries", "-//JavaPOS//DTD//EN", getDoctypeValue()); Document doc = domImpImpl.createDocument(null, "JposEntries", docType); return doc; } /** * Inserts date and info saved in the XML Document object * @param document the XML Document object * @exception java.lang.Exception in case something goes wrong * @since 1.2 (NY 2K meeting) */ protected void insertDateSavedComment(Document document) throws Exception { String dateString = DateFormat.getInstance().format( new Date(System.currentTimeMillis())); String commentString = "Saved by JavaPOS jpos.config/loader (JCL) version " + Version.getVersionString() + " on " + dateString; Comment comment = document.createComment(commentString); document.getDocumentElement().insertBefore(comment, document.getDocumentElement().getFirstChild()); document.getDocumentElement().insertBefore( document.createTextNode("\n"), comment); document.getDocumentElement() .appendChild(document.createTextNode("\n")); } /** * Appends the <creation> element to the document * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param jposEntry the JposEntry object * @since 1.2 (NY 2K meeting) */ protected void appendCreationElement(Document doc, Element jposEntryElement, JposEntry jposEntry) { jposEntryElement.appendChild(doc.createTextNode(" " + " ")); Element creationElement = doc.createElement("creation"); Attr factoryClassAttr = doc.createAttribute("factoryClass"); Attr serviceClassAttr = doc.createAttribute("serviceClass"); factoryClassAttr.setValue((String) jposEntry .getPropertyValue("serviceInstanceFactoryClass")); serviceClassAttr.setValue((String) jposEntry .getPropertyValue("serviceClass")); creationElement.setAttributeNode(factoryClassAttr); creationElement.setAttributeNode(serviceClassAttr); jposEntryElement.appendChild(creationElement); jposEntryElement.appendChild(doc.createTextNode("\n")); } /** * Appends the <vendor> element to the document * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param jposEntry the JposEntry object * @since 1.2 (NY 2K meeting) */ protected void appendVendorElement(Document doc, Element jposEntryElement, JposEntry jposEntry) { jposEntryElement.appendChild(doc.createTextNode(" " + " ")); Element vendorElement = doc.createElement("vendor"); Attr nameAttr = doc.createAttribute("name"); Attr urlAttr = doc.createAttribute("url"); nameAttr.setValue((String) jposEntry.getPropertyValue("vendorName")); urlAttr.setValue((String) jposEntry.getPropertyValue("vendorURL")); vendorElement.setAttributeNode(nameAttr); vendorElement.setAttributeNode(urlAttr); jposEntryElement.appendChild(vendorElement); jposEntryElement.appendChild(doc.createTextNode("\n")); } /** * Appends the <jpos> element to the document * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param jposEntry the JposEntry object * @since 1.2 (NY 2K meeting) */ protected void appendJposElement(Document doc, Element jposEntryElement, JposEntry jposEntry) { jposEntryElement.appendChild(doc.createTextNode(" " + " ")); Element jposElement = doc.createElement("jpos"); Attr versionAttr = doc.createAttribute("version"); Attr categoryAttr = doc.createAttribute("category"); versionAttr .setValue((String) jposEntry.getPropertyValue("jposVersion")); categoryAttr.setValue((String) jposEntry .getPropertyValue("deviceCategory")); jposElement.setAttributeNode(versionAttr); jposElement.setAttributeNode(categoryAttr); jposEntryElement.appendChild(jposElement); jposEntryElement.appendChild(doc.createTextNode("\n")); } /** * Appends the <product> element to the document * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param jposEntry the JposEntry object * @since 1.2 (NY 2K meeting) */ protected void appendProductElement(Document doc, Element jposEntryElement, JposEntry jposEntry) { jposEntryElement.appendChild(doc.createTextNode(" " + " ")); Element productElement = doc.createElement("product"); Attr nameAttr = doc.createAttribute("name"); Attr descriptionAttr = doc.createAttribute("description"); Attr urlAttr = doc.createAttribute("url"); nameAttr.setValue((String) jposEntry.getPropertyValue("productName")); descriptionAttr.setValue((String) jposEntry .getPropertyValue("productDescription")); urlAttr.setValue((String) jposEntry.getPropertyValue("productURL")); productElement.setAttributeNode(nameAttr); productElement.setAttributeNode(descriptionAttr); productElement.setAttributeNode(urlAttr); jposEntryElement.appendChild(productElement); jposEntryElement.appendChild(doc.createTextNode("\n")); } /** * Appends the <prop> element to the document * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param propName the property name * @param propValue the property value * @since 1.2 (NY 2K meeting) */ protected void appendPropElement(Document doc, Element jposEntryElement, String propName, Object propValue) { jposEntryElement.appendChild(doc.createTextNode(" " + " ")); Element propElement = doc.createElement("prop"); Attr nameAttr = doc.createAttribute("name"); Attr valueAttr = doc.createAttribute("value"); Attr typeAttr = doc.createAttribute("type"); nameAttr.setValue(propName); valueAttr.setValue(propValue.toString()); typeAttr .setValue(JposEntryUtility.shortClassName(propValue.getClass())); propElement.setAttributeNode(nameAttr); propElement.setAttributeNode(valueAttr); propElement.setAttributeNode(typeAttr); jposEntryElement.appendChild(propElement); jposEntryElement.appendChild(doc.createTextNode("\n")); } /** * Appends non-required properties name and value * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param jposEntry the JposEntry object * @since 1.2 (NY 2K meeting) */ protected void appendPropElements(Document doc, Element jposEntryElement, JposEntry jposEntry) { jposEntryElement .appendChild(doc.createTextNode("\n" + " " + " ")); String comment = "Other non JavaPOS required property" + " (mostly vendor properties and bus specific " + "properties i.e. RS232 )"; jposEntryElement.appendChild(doc.createComment(comment)); jposEntryElement.appendChild(doc.createTextNode("\n")); Enumeration props = jposEntry.getPropertyNames(); while (props.hasMoreElements()) { String propName = (String) props.nextElement(); if (!JposEntryUtility.isRequiredPropName(propName)) appendPropElement(doc, jposEntryElement, propName, jposEntry .getPropertyValue(propName)); } } /** * Insert the <JposEntryElement> in the XML document object * @param doc the XML Document object * @param jposEntryElement the <JposEntryElement> XML Element object * @param jposEntry the JposEntry object * @since 1.2 (NY 2K meeting) */ protected void insertJposEntryInDoc(Document doc, Element jposEntryElement, JposEntry jposEntry) { appendCreationElement(doc, jposEntryElement, jposEntry); appendVendorElement(doc, jposEntryElement, jposEntry); appendJposElement(doc, jposEntryElement, jposEntry); appendProductElement(doc, jposEntryElement, jposEntry); appendPropElements(doc, jposEntryElement, jposEntry); doc.getDocumentElement().appendChild(doc.createTextNode("\n" + " ")); doc.getDocumentElement().appendChild(jposEntryElement); doc.getDocumentElement().appendChild(doc.createTextNode("\n" + " ")); } /** * Insert an Enumeration of <JposEntryElement> objects in the XML document * @param doc the XML Document object * @param entries an Enumeration of JposEntry objects * @since 1.2 (NY 2K meeting) */ protected void insertJposEntriesInDoc(Document doc, Enumeration entries) { while (entries.hasMoreElements()) { JposEntry jposEntry = (JposEntry) entries.nextElement(); if (JposEntryUtility.isValidJposEntry(jposEntry)) { doc.getDocumentElement().appendChild( doc.createTextNode("\n" + " ")); Element jposEntryElement = doc.createElement("JposEntry"); Attr logicalNameAttr = doc.createAttribute("logicalName"); logicalNameAttr.setValue((String) jposEntry .getPropertyValue("logicalName")); jposEntryElement.setAttributeNode(logicalNameAttr); jposEntryElement.appendChild(doc.createTextNode("\n")); insertJposEntryInDoc(doc, jposEntryElement, jposEntry); } } } //-------------------------------------------------------------------------- // Instance variables // protected String xmlFileName = DEFAULT_XML_FILE_NAME; protected DOMParser domParser = new DOMParser(); private Tracer tracer = TracerFactory.getInstance().createTracer( "AbstractXercesRegPopulator"); //-------------------------------------------------------------------------- // Public constants // public static final String DTD_FILE_PATH = "jpos" + File.separator + "res"; public static final String DTD_FILE_NAME = DTD_FILE_PATH + File.separator + "jcl.dtd"; }