org.jpos.iso.packager.GenericPackager Maven / Gradle / Ivy
Show all versions of jpos Show documentation
/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2020 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package org.jpos.iso.packager;
import org.jpos.core.Configurable;
import org.jpos.core.Configuration;
import org.jpos.core.ConfigurationException;
import org.jpos.iso.*;
import org.jpos.util.LogSource;
import org.jpos.util.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.TreeMap;
/**
*
* GenericPackager uses an XML config file to describe the layout of an ISOMessage
* The general format is as follows
* <isopackager>
* <isofield
* id="[field id]"
* name="[field name]"
* length="[max field length]"
* class="[org.jpos.iso.IF_*]"
* pad="true|false">
* </isofield>
* ...
* </isopackager>
*
* Fields that contain subfields can be handled as follows
* <isofieldpackager
* id="[field id]"
* name="[field name]"
* length="[field length]"
* class="[org.jpos.iso.IF_*]"
* packager="[org.jpos.iso.packager.*]">
*
* <isofield
* id="[subfield id]"
* name="[subfield name]"
* length="[max subfield length]"
* class="[org.jpos.iso.IF_*]"
* pad="true|false">
* </isofield>
* ...
* </isofieldpackager>
*
* The optional attributes maxValidField, bitmapField, thirdBitmapField, and emitBitmap
* are allowed on the isopackager node.
*
*
* @author Eoin Flood
* @version $Revision$ $Date$
* @see ISOPackager
* @see ISOBasePackager
*/
@SuppressWarnings("unchecked")
public class GenericPackager
extends ISOBasePackager implements Configurable
{
/* Values copied from ISOBasePackager
These can be changes using attributes on the isopackager node */
private int maxValidField=128;
private boolean emitBitmap=true;
private int bitmapField=1;
private String firstField = null;
private String filename;
public GenericPackager() throws ISOException
{
super();
}
/**
* Create a GenericPackager with the field descriptions
* from an XML File
* @param filename The XML field description file
*/
public GenericPackager(String filename) throws ISOException
{
this.filename = filename;
readFile(filename);
}
/**
* Create a GenericPackager with the field descriptions
* from an XML InputStream
* @param input The XML field description InputStream
*/
public GenericPackager(InputStream input) throws ISOException
{
readFile(input);
}
/**
* Packager Configuration.
*
*
* - packager-config
*
- packager-logger
*
- packager-realm
*
*
* @param cfg Configuration
*/
public void setConfiguration (Configuration cfg)
throws ConfigurationException
{
filename = cfg.get("packager-config", null);
if (filename == null)
throw new ConfigurationException("packager-config property cannot be null");
try
{
String loggerName = cfg.get("packager-logger");
if (loggerName != null)
setLogger(Logger.getLogger (loggerName),
cfg.get ("packager-realm"));
readFile(filename);
} catch (ISOException e)
{
throw new ConfigurationException(e.getMessage(), e.fillInStackTrace());
}
}
@Override
protected int getMaxValidField()
{
return maxValidField;
}
@Override
protected boolean emitBitMap()
{
return emitBitmap;
}
@Override
protected ISOFieldPackager getBitMapfieldPackager()
{
return fld[bitmapField];
}
/**
* Parse the field descriptions from an XML file.
*
*
* Uses the sax parser specified by the system property 'sax.parser'
* The default parser is org.apache.crimson.parser.XMLReaderImpl
*
* @param filename The XML field description file
*/
public void readFile(String filename) throws ISOException
{
try {
if (filename.startsWith("jar:") && filename.length()>4) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
readFile(
cl.getResourceAsStream(filename.substring(4))
);
} else {
createXMLReader().parse(filename);
}
}
catch (Exception e) {
throw new ISOException("Error reading " + filename, e);
}
}
/**
* Parse the field descriptions from an XML InputStream.
*
*
* Uses the sax parser specified by the system property 'sax.parser'
* The default parser is org.apache.crimson.parser.XMLReaderImpl
*
* @param input The XML field description InputStream
*/
public void readFile(InputStream input) throws ISOException
{
try {
createXMLReader().parse(new InputSource(input));
}
catch (Exception e) {
throw new ISOException(e);
}
}
@Override
public void setLogger (Logger logger, String realm) {
super.setLogger (logger, realm);
if (fld != null) {
for (int i=0; i
* The strategy we follow is:
* We first check whether the DTD points to a well defined URI,
* and resolve to our internal DTDs.
*
* If the systemId points to a file, then we attempt to read the
* DTD from the filesystem, in case they've been modified by the user.
* Otherwise, we fallback to the built-in DTDs inside jPOS.
*
* @param publicId The public identifier of the external entity
* being referenced, or null if none was supplied.
* @param systemId The system identifier of the external entity
* being referenced.
* @return An InputSource object describing the new input source,
* or null to request that the parser open a regular
* URI connection to the system identifier.
* @throws org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @throws java.io.IOException A Java-specific IO exception,
* possibly the result of creating a new InputStream
* or Reader for the InputSource.
* @see org.xml.sax.InputSource
*/
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
{
if(systemId==null) return null;
ClassLoader cl =Thread.currentThread().getContextClassLoader();
cl = cl ==null?ClassLoader.getSystemClassLoader() : cl;
if(systemId.equals("http://jpos.org/dtd/generic-packager-1.0.dtd"))
{
final URL resource = cl.getResource("org/jpos/iso/packager/genericpackager.dtd");
return new InputSource(resource.toExternalForm());
}
else if(systemId.equals("http://jpos.org/dtd/generic-validating-packager-1.0.dtd"))
{
final URL resource = cl.getResource("org/jpos/iso/packager/generic-validating-packager.dtd");
return new InputSource(resource.toExternalForm());
}
URL url=new URL(systemId);
if(url.getProtocol().equals("file"))
{
String file=url.getFile();
if(file.endsWith(".dtd"))
{
File f=new File(file);
InputStream res=null;
if(f.exists())
{
res=new FileInputStream(f);
}
if(res==null)
{
String dtdResource="org/jpos/iso/packager/"+f.getName();
res= cl.getResourceAsStream(dtdResource);
}
if(res!=null) return new InputSource(res);
}
}
return null;
}
}
public class GenericContentHandler extends DefaultHandler
{
private Stack