package examples.xml.biztalk;
import java.io.*;
import java.util.*;
import javax.naming.*;
import weblogic.jndi.Environment;
import examples.xml.biztalk.ejb.BizBeanHome;
import weblogic.xml.dom.*;
import org.w3c.dom.*;
/**
* The BizConfig class is used to access the config parameters for
* the BizTalk server.
*
* @author Copyright (c) 2000 by BEA Systems, Inc. All Rights Reserved.
*/
public class BizConfig {
public final static String JNDI_FACTORY =
"weblogic.jndi.WLInitialContextFactory";
public final static String JMS_FACTORY = "javax.jms.QueueConnectionFactory";
public final static String IN_QUEUE1 = "biztalk.jms.";
public final static String IN_QUEUE2 = "Incoming";
public final static String ERROR_QUEUE1 = "biztalk.jms.";
public final static String ERROR_QUEUE2 = "Error";
public final static String BIZ_ADMIN = "Bizconfig";
public final static String BIZ_STOP = "Bizstop";
//
// config info variables
//
private boolean verbose = true;
private static Vector bizServers = new Vector(1,1);
private boolean loaded = false;
private String name;
private String configFile;
private String inQ;
private String errorQ;
private String URI;
private Hashtable mappings;
private Vector bizBeans;
private String bizHome;
String separator = System.getProperty("file.separator");
private PrintWriter log;
/**
* Constructor
*/
public BizConfig() {
bizHome = System.getProperty("user.dir");
log = new PrintWriter(System.out, true);
}
/**
* Establish log file to be used by this object.
*
* @param ps output class
*/
public void setLog(PrintWriter ps) {
log = ps;
}
/**
* The BizConfig loader reads the config file for the named BizServer
* and stores the info into this object. The list of loaded servers is
* maintained in the class and accessible via the <tt>getBizServers</tt>
* method.
* <P>
* The home directory used by a Bizserver is the user's current directory.
* From there the server is configured from <server-name>.xml
* <P>
* The queues are "biztalk.jms.<I>name</I>.Incoming" and
* "biztalk.jms.<I>name</I>.Error". Note that BizConfig only fully-qualifies the
* queue names. Actual setup of queues is the caller's responsibility.
* <P>
* All other config info comes from "<I>home</I>/<I>name</I>.xml which has
* the following 'schema':
* <P>
* <PRE>
* <?xml version=1.0>
* <Bizconfig>
* name = "a name"
* verbose = "true"|"false"
* uri="home address"
* <Bean> bean.name</Bean> (0..n)
* <Mapping> (0..n)
* doc="a doctype"
* bean="a bean"
* </Mapping>
* </Bizconfig>
* </PRE>
* <P>
* loadConfig reconfigures from scratch. i.e. a complete XML config
* file must be provided. Prior configuration is lost.
*
* @param bizName name of server to configure.
* @return true if successful, false if failed.
*/
public boolean loadConfig(String bizName) {
loaded = false;
if (verbose) log.println("loading config: "+bizName);
setName(bizName);
setConfigFile();
setInQ();
setErrorQ();
mappings = new Hashtable();
bizBeans = new Vector();
//
// parse the config file filling in the important stuff
//
try {
InputStream is = new FileInputStream(getConfigFile());
Reader r = new InputStreamReader(is);
DOMParser parser = DOMParser.getDOMParser("com.sun.xml.parser.Parser");
Document d = parser.getDocument(r);
Node node = d.getDocumentElement();
if (loadConfigDOM(node)) {
bizServers.addElement(this); // so other objects can find config
loaded = true;
}
}
catch (IOException ioe) {
log.println("Unable to read config file, "+getConfigFile());
}
catch (DOMParserException dome) {
log.println("Unable to parse config file, "+getConfigFile());
log.println(dome.getMessage());
}
return loaded;
}
/**
* reloadConfig reconfigures from an already configured Bizserver.
*
* @return true if successful, false if failed.
*/
public boolean reloadConfig() {
loaded = false;
if (verbose) log.println("reloading config: "+name);
mappings = new Hashtable();
bizBeans = new Vector();
//
// parse the config file filling in the important stuff
//
try {
InputStream is = new FileInputStream(getConfigFile());
Reader r = new InputStreamReader(is);
DOMParser parser = DOMParser.getDOMParser("com.sun.xml.parser.Parser");
Document d = parser.getDocument(r);
Node node = d.getDocumentElement();
if (loadConfigDOM(node)) {
bizServers.addElement(this); // so other objects can find config
loaded = true;
}
}
catch (IOException ioe) {
log.println("Unable to read config file, "+getConfigFile());
}
catch (DOMParserException dome) {
log.println("Unable to parse config file, "+getConfigFile());
log.println(dome.getMessage());
}
return loaded;
}
//
// load config info from a DOM
//
private boolean loadConfigDOM(Node node) {
//
// walk the tree. This code knows what the tree should look
// like and expects it to be valid.
//
if (node.getNodeName().equals(BIZ_ADMIN)) {
log.println("Node: "+node.getNodeName());
NamedNodeMap nm = node.getAttributes();
if (nm != null) {
int items = nm.getLength();
for (int i=0; i<items; i++) {
String attrName = nm.item(i).getNodeName();
String attrVal = nm.item(i).getNodeValue();
log.println("Attr: "+attrName+"="+attrVal);
if (attrName.equals("name")) {}
if (attrName.equals("verbose")) {
if (attrVal.equals("true")) {verbose = true;}
if (attrVal.equals("false")) {verbose = false;}
}
if (attrName.equals("uri")) {setURI(attrVal);}
}
}
else {
return false;
}
}
else {
return false;
}
//
// now process mappings
//
NodeList nl = node.getChildNodes();
int children = nl.getLength();
for (int i=0; i<children; i++) {
Node nd = nl.item(i);
log.println("Node: "+nd.getNodeName());
if (nd.getNodeName().equals("Bean")) {
//
// handle beans
//
Node nc = nd.getFirstChild();
log.println("Bean name: "+nc.getNodeValue());
addBizBean(nc.getNodeValue());
}
if (nd.getNodeName().equals("Mapping")) {
//
// handle mappings
//
NamedNodeMap nm = nd.getAttributes();
if (nm != null) {
int items = nm.getLength();
String doc = "";
String bean = "";
boolean gotdoc = false;
boolean gotbean = false;
for (int j=0; j<items; j++) {
String attrName = nm.item(j).getNodeName();
String attrVal = nm.item(j).getNodeValue();
log.println("Attr: "+attrName+"="+attrVal);
if (attrName.equals("doc")) {doc = attrVal; gotdoc = true;}
if (attrName.equals("bean")) {bean = attrVal; gotbean = true;}
if (gotdoc && gotbean) {
addMapping(doc, bean);
gotdoc = false;
gotbean = false;
}
}
if (gotdoc ^ gotbean) {
return false;
}
}
}
}
return true;
}
/**
* Returns the home directory for this server
*
* @return String containing home directory
*/
public String getBizHome() {
return bizHome;
}
/**
* Returns the names of loaded Biztalk Servers
*
* @return Vector containing the names of nstantiated Biztalk Servers.
*/
public Vector getBizServers() {
return bizServers;
}
/**
* Returns a BizConfig object.
*
* @param bizName Name of the Biztalk Server
*
* @return BizConfig object representing a particular Biztalk Server.
* Returns null if the named server is not loaded.
*/
public static BizConfig getConfig(String bizName) {
for (int i=0; i<bizServers.size(); i++) {
BizConfig bc = (BizConfig) bizServers.elementAt(i);
if (bizName.equals(bc.getName())) return bc;
}
return null;
}
/**
* prints the info in BizConfig object to an output stream
*/
public void printConfig() {
log.println("Name: "+ getName());
log.println("Home: "+ bizHome);
log.println("XML: "+ getConfigFile());
log.println("In Queue: "+ getInQ());
log.println("Error Queue: "+ getErrorQ());
if (!loaded) { // skip the rest if load failed
return;
}
log.println("URI:"+getURI());
log.println("Beans:");
Vector bn = getBizBeans();
for (int i=0;i<bn.size();i++) {
log.println(" "+bn.elementAt(i));
}
log.println("Doc Type Mappings:");
for (Enumeration e = mappings.keys() ; e.hasMoreElements() ;) {
String dt = (String)e.nextElement();
Vector v = getBizBeansForDoc(dt);
log.println(" Doc Type: "+dt);
for (int i=0;i<v.size();i++) {
log.println(" Bean: "+bn.elementAt(i).toString());
}
}
}
//
// accessors
//
private void setName(String nm) {
name = new String(nm);
}
private void setConfigFile() {
configFile = new String (bizHome + separator + name + ".xml");
}
private void setInQ() {
inQ = new String(IN_QUEUE1+getName()+IN_QUEUE2);
}
private void setErrorQ () {
errorQ = new String(ERROR_QUEUE1+getName()+ERROR_QUEUE2);
}
private void setURI(String uri) {
URI = uri;
}
private void addMapping(String docType, String beanName) {
//
// ensure the name maps to an actual bean
//
try {
Context context = (new Environment()).getInitialContext();
BizBeanHome bean = (BizBeanHome) context.lookup(beanName);
//
// check if docType is already a key and if so add the
// bean to its entry.
//
Vector beans = (Vector)mappings.get(docType);
if (beans == null) {
beans = new Vector(1,1);
}
beans.addElement(bean);
mappings.put(docType,beans);
}
catch (NamingException e) {
log.println(beanName+" not registered. Will not be mapped to "+docType+ " documents.");
}
}
private void addBizBean(String bean) {
bizBeans.addElement(bean);
}
/**
* Returns a Vector of registered EJB names (String objects).
* These are the beans that can be mapped to specific Biztalk document types.
*
* @return Vector of String objects naming registered EJBs.
* Returns null if BizConfig object has not been loaded.
*
*/
public Vector getBizBeans() {
if (loaded) return bizBeans;
return null;
}
/**
* Returns name of Biztalk server represented in this BizConfig object.
*
* @return Name of Biztalk server.
* Returns null if BizConfig object has not been loaded.
*
*/
public String getName() {
return name;
}
/**
* Returns debug level
*
* @return True if debugging.
*
*/
public boolean getVerbose() {
return verbose;
}
/**
* Returns name of Biztalk server config file used to configure this BizConfig object.
*
* @return Name of Biztalk server config file.
* Returns null if BizConfig object has not been loaded.
*
*/
public String getConfigFile() {
return configFile;
}
/**
* Returns name of JMS incoming queue name used by this Biztalk server.
*
* @return Name of Biztalk server incoming queue.
* Returns null if BizConfig object has not been loaded.
*
*/
public String getInQ() {
if (loaded) return inQ;
return null;
}
/**
* Returns name of JMS error queue name used by this Biztalk server. All
* documents received by the Biztalk Server that can not be processed
* are placed on this queue. Failures result from invalid document syntax
* or internal errors.
*
* @return Name of Biztalk server error queue
* Returns null if BizConfig object has not been loaded.
*
*/
public String getErrorQ() {
if (loaded) return errorQ;
return null;
}
/**
* Returns URI that this Biztalk server recognizes as its own.
* Documents received with <TT>To</TT> elements that do not match
* this URI will be routed to the error queue
*
* @return recognized URI.
* Returns null if BizConfig object has not been loaded.
*
*/
public String getURI() {
if (loaded) return URI;
return null;
}
/**
* Returns configured mapping between document types and EJBs. The
* Hashtable returned uses Biztalk document types for the keys. The value
* for each key is a Vector of EJB Class objects. The mapping is established
* via the Biztalk server configuration file.
*
* @return Hashtable representing mapping between doc type and EJBs.
* Returns null if BizConfig object has not been loaded.
*
*/
public Hashtable getMappings() {
if (loaded) return mappings;
return null;
}
/**
* Returns list of EJB Class objects for the named document type.
*
* @param docType String identifying a Biztalk document type. This
* document type is identified in the first element of a Biztalk
* document following the <TT>\<Body/></TT> element.
*
* @return Vector containing EJB Class objects.
* Returns null if BizConfig object has not been loaded.
*/
public Vector getBizBeansForDoc(String docType) {
if (loaded) return (Vector)mappings.get(docType);
return null;
}
}