Post California version

png3 [2001-02-05 06:35:16]
Post California version
Filename
Email_Example.xml
Email_Example2.xml
MPUtil.java
Metaparser.java
ParserThread.java
SienaListenerThread.java
SienaTest.java
SmartEventSchema.xsd
SubParser.java
Validator.java
schema.xsd
spam_ex.xml
diff --git a/Email_Example.xml b/Email_Example.xml
new file mode 100644
index 0000000..b5ab800
--- /dev/null
+++ b/Email_Example.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<smartevent
+	xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
+	xsi:noNamespaceSchemaLocation="SmartEventSchema.xsd"
+>
+  <metadata>
+    <tag>31415</tag>
+    <source>
+      <ipAddr>mail.cs.columbia.edu</ipAddr>
+      <ipPort>2500</ipPort>
+    </source>
+    <time>2001-01-20T21:45:00</time>
+  </metadata>
+  <?FleXML type="schemaFrag" name="sendmail/biff" version="1.0"?>
+  <smtp>
+    <to>png3@cs.columbia.edu</to>
+    <from>jjp32@cs.columbia.edu</from>
+    <subject>Secret of Life, the Universe, and Everything</subject>
+    <sent>2000-11-20T19:00:00</sent>
+    <received>2000-11-20T19:02:00</received>
+  </smtp>
+</smartevent>
diff --git a/Email_Example2.xml b/Email_Example2.xml
new file mode 100644
index 0000000..0fc3afc
--- /dev/null
+++ b/Email_Example2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<smartevent
+	xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
+	xsi:noNamespaceSchemaLocation="schema.xsd"
+>
+  <metadata>
+    <tag>31415</tag>
+    <source>
+      <ipAddr>mail.cs.columbia.edu</ipAddr>
+      <ipPort>2500</ipPort>
+    </source>
+    <time>2001-01-20T21:45:00</time>
+  </metadata>
+  <?FleXML type="schemaFrag" name="sendmail/biff" version="1.0"?>
+  <smtp>
+    <to>png3@cs.columbia.edu</to>
+    <from>jjp32@cs.columbia.edu</from>
+    <subject>Secret of Life, the Universe, and Everything</subject>
+    <sent>2000-11-20T19:00:00</sent>
+    <received>2000-11-20T19:02:00</received>
+  </smtp>
+</smartevent>
diff --git a/MPUtil.java b/MPUtil.java
index 542cd07..30d0a6a 100644
--- a/MPUtil.java
+++ b/MPUtil.java
@@ -1,112 +1,115 @@
-package psl.metaparser;
-
-import java.text.DateFormat;
-import java.util.*;
-import java.io.*;
-import java.net.URL;
-
-// import oracle.xml.parser.schema.*;
-// import oracle.xml.parser.v2.*;
-import org.xml.sax.*;
-import org.xml.sax.helpers.*;
-
-/** Various static utility methods for metaparser.
-  *
+package psl.metaparser;
+
+import java.text.DateFormat;
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+
+// import oracle.xml.parser.schema.*;
+// import oracle.xml.parser.v2.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+/** Various static utility methods for metaparser.
+  *
   * $Log$
-  * Revision 2.3  2001-01-30 10:16:55  png3
-  * Almost working...
-  *
-  * Revision 2.2  2001/01/29 04:04:48  png3
-  * Added package psl.metaparser statements.  Can you say "Oops?"
-  *
-  * Revision 2.1  2001/01/28 17:52:17  png3
-  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
-  *
-  */
-class MPUtil {
-
-  /** Generate a timestamp string */
-  public static String timestamp() {
-    final DateFormat df =
-    	DateFormat.getTimeInstance(DateFormat.MEDIUM);
-    return df.format(new Date());
-  }
-
-  public static String makeQuery(String elm) {
-    String s = new String("<?xml version=\"1.0\"?>");
-    s += "<schemaQuery version=\"1.0\" name=\""+ elm+ "\">";
-    s += "<xpath>/" + elm + "</xpath>";
-    s += "</schemaQuery>";
-    return s;
-  }
-
-  public static String printLoc(Locator l) {
-    return ("(" + l.getLineNumber() + ":"
-    	+ l.getColumnNumber() + ")");
-  }
-
-  /** pulls module name out of oracle response XML */
-  // TODO: integrate with other logging...
-  public static String extractModuleName(String s) {
-    final String fn = "MPU_extractModuleName: ";
-    final String startTag = "<module";
-    final String endTok = ".";
-    int startIdx = s.indexOf(startTag);
-    startIdx = s.indexOf(">", startIdx);
-    int endIdx = s.indexOf(endTok, startIdx);
-    String result = s.substring(startIdx + 1, endIdx);
-    System.err.println(fn+"Extracted Module:\n" + result);
-    return result;
-  }
-
-  /** pulls subschema out of oracle response XML */
-  // TODO: integrate with other logging...
-  public static void extractSchema(String s) {
-    final String fn = "MPU_extractSchema: ";
-    final String startTag = "<subschema>";
-    final String endTag = "</subschema>";
-    int startIdx = s.indexOf(startTag)+startTag.length();
-    int endIdx = s.indexOf(endTag, startIdx);
-    String result = s.substring(startIdx, endIdx);
-    System.err.println(fn+"extracted schema String:\n" + result);
-
-    // StringReader sr = new StringReader(result);
-    // XMLSchema schema = null;
-    try {
-      FileWriter schema = new FileWriter("schema.xsd");
-      schema.write(result);
-      schema.close();
-      // URL base = new URL("http://www.w3.org/1999/XMLSchema-instance");
-      // XSDBuilder b = new XSDBuilder();
-      // schema = (XMLSchema)b.build(sr, base);
-    } catch (Exception e) {
-      System.err.println(fn+"error while building schema");
-      System.err.println(e);
-      return;
-    }
-  }
-
-  // got this from Oracle, but I think it's been superseded
-  // by the built-in toURL() method of File
-  /*
-  static URL fileToURL(String fname) {
-
-    File file = new File(fname);
-
-    String path = file.getAbsolutePath();
-    String fSep = System.getProperty("file.separator");
-
-    if ((fSep != null) && (fSep.length() == 1)) {
-      path = path.replace(fSep.charAt(0), '/');
-    }
-    if ((path.length() > 0) && (path.charAt(0) != '/')) {
-      path = '/' + path;
-    }
-    try {
-      return new URL("file", null, path);
-    } catch (java.net.MalformedURLException e) {
-      throw new Error("unexpected MalformedURLException");
-    }
-  }
-  */
-}
+  * Revision 2.4  2001-02-05 06:35:16  png3
+  * Post California version
+  *
+  * Revision 2.3  2001/01/30 10:16:55  png3
+  * Almost working...
+  *
+  * Revision 2.2  2001/01/29 04:04:48  png3
+  * Added package psl.metaparser statements.  Can you say "Oops?"
+  *
+  * Revision 2.1  2001/01/28 17:52:17  png3
+  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
+  *
+  */
+class MPUtil {
+
+  /** Generate a timestamp string */
+  public static String timestamp() {
+    final DateFormat df =
+    	DateFormat.getTimeInstance(DateFormat.MEDIUM);
+    return df.format(new Date());
+  }
+
+  public static String makeQuery(String elm) {
+    String s = new String("<?xml version=\"1.0\"?>");
+    s += "<schemaQuery version=\"1.0\" name=\""+ elm+ "\">";
+    s += "<xpath>/" + elm + "</xpath>";
+    s += "</schemaQuery>";
+    return s;
+  }
+
+  public static String printLoc(Locator l) {
+    return ("(" + l.getLineNumber() + ":"
+    	+ l.getColumnNumber() + ")");
+  }
+
+  /** pulls module name out of oracle response XML */
+  // TODO: integrate with other logging...
+  public static String extractModuleName(String s) {
+    final String fn = "MPU_extractModuleName: ";
+    final String startTag = "<module";
+    final String endTok = "</module>";
+    int startIdx = s.indexOf(startTag);
+    startIdx = s.indexOf(">", startIdx);
+    int endIdx = s.indexOf(endTok, startIdx);
+    String result = s.substring(startIdx + 1, endIdx);
+    System.err.println(fn+"Expected Module Name:\n" + result);
+    return result;
+  }
+
+  /** pulls subschema out of oracle response XML */
+  // TODO: integrate with other logging...
+  public static void extractSchema(String s) {
+    final String fn = "MPU_extractSchema: ";
+    final String startTag = "<subschema>";
+    final String endTag = "</subschema>";
+    int startIdx = s.indexOf(startTag)+startTag.length();
+    int endIdx = s.indexOf(endTag, startIdx);
+    String result = s.substring(startIdx, endIdx);
+    System.err.println(fn+"extracted schema String:\n" + result);
+
+    // StringReader sr = new StringReader(result);
+    // XMLSchema schema = null;
+    try {
+      FileWriter schema = new FileWriter("schema.xsd");
+      schema.write(result);
+      schema.close();
+      // URL base = new URL("http://www.w3.org/1999/XMLSchema-instance");
+      // XSDBuilder b = new XSDBuilder();
+      // schema = (XMLSchema)b.build(sr, base);
+    } catch (Exception e) {
+      System.err.println(fn+"error while building schema");
+      System.err.println(e);
+      return;
+    }
+  }
+
+  // got this from Oracle, but I think it's been superseded
+  // by the built-in toURL() method of File
+  /*
+  static URL fileToURL(String fname) {
+
+    File file = new File(fname);
+
+    String path = file.getAbsolutePath();
+    String fSep = System.getProperty("file.separator");
+
+    if ((fSep != null) && (fSep.length() == 1)) {
+      path = path.replace(fSep.charAt(0), '/');
+    }
+    if ((path.length() > 0) && (path.charAt(0) != '/')) {
+      path = '/' + path;
+    }
+    try {
+      return new URL("file", null, path);
+    } catch (java.net.MalformedURLException e) {
+      throw new Error("unexpected MalformedURLException");
+    }
+  }
+  */
+}
diff --git a/Metaparser.java b/Metaparser.java
index 677b04d..b3862b7 100644
--- a/Metaparser.java
+++ b/Metaparser.java
@@ -1,108 +1,112 @@
-package psl.metaparser;
-
-import java.util.*;
-import java.io.*;
-import java.net.*;
-
-import siena.SienaException;
-
-/** Root Metaparser class.
- *  Creates a SienaListenerThread, and establishes a few
- *  thread intercommunication data structures.
- *  If SienaListener gets a query from the Event Distiller,
- *  it starts a new SEParserThread.  The SEParserThread
- *  directs the data input of a subordinate Validator.
- *  This initial Validator validates against the smartevent
- *  schema.  When it encounters an unknown tag, the schema and
- *  processor for the unknown tag are requested from the Oracle,
- *  and the thread  goes to sleep.  When the response comes in, the
- *  Validator wakes up and validates the unknown portion.  When
- *  finished, it checks to see if the worklet has arrived and
- *  installed the tag processor.  If not, it goes to sleep again,
- *  and waits for the arrival.  When it comes, it applies the tag
- *  processor based on type: XSLT templates are applied, and
- *  XMLFilters are hooked up to an XMLReader.
- *
- *  Maybe.
- *
- *  TODO: properties instead of hardcoding
- *  TODO: caching of oracle responses.
- *  TODO: reacting to unknown tag, instead of faking it based on
- *  FleXML PI.  Requires actual streaming validation.
- *
+package psl.metaparser;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+import siena.SienaException;
+
+/** Root Metaparser class.
+ *  Creates a SienaListenerThread, and establishes a few
+ *  thread intercommunication data structures.
+ *  If SienaListener gets a query from the Event Distiller,
+ *  it starts a new SEParserThread.  The SEParserThread
+ *  directs the data input of a subordinate Validator.
+ *  This initial Validator validates against the smartevent
+ *  schema.  When it encounters an unknown tag, the schema and
+ *  processor for the unknown tag are requested from the Oracle,
+ *  and the thread  goes to sleep.  When the response comes in, the
+ *  Validator wakes up and validates the unknown portion.  When
+ *  finished, it checks to see if the worklet has arrived and
+ *  installed the tag processor.  If not, it goes to sleep again,
+ *  and waits for the arrival.  When it comes, it applies the tag
+ *  processor based on type: XSLT templates are applied, and
+ *  XMLFilters are hooked up to an XMLReader.
+ *
+ *  Maybe.
+ *
+ *  TODO: properties instead of hardcoding
+ *  TODO: caching of oracle responses.
+ *  TODO: reacting to unknown tag, instead of faking it based on
+ *  FleXML PI.  Requires actual streaming validation.
+ *
  *  $Log$
- *  Revision 2.3  2001-01-29 04:04:48  png3
- *  Added package psl.metaparser statements.  Can you say "Oops?"
- *
- *  Revision 2.2  2001/01/28 17:52:17  png3
- *  New version of Metaparser: fully multithreaded.  PrintWriter logs.
- *
- *
- */
-
-public class Metaparser {
-
-  /** when Parsers need to wait for a response, they register
-    * themselves here (key=requestid, value=the object they're
-    * wait()ing on, and wait for a notify().
-    * Synchronized HashMap;
-    */
-  static Map waitList = null;
-  SienaListenerThread slt = null;
-  private static final String fn = "Metaparser";
-  // should allow this from command line also...
-  private static final String prop = "metaparser.properties";
-  static boolean debug = false;
-  private static String seSchema = null;
-  static PrintWriter log = null;
-  static PrintWriter dbg = null;
-
-  public static void main(String args[]) {
-
-    Properties p = new Properties();
-    try {
-      FileInputStream fis = new FileInputStream(prop);
-      p.load(fis);
-    } catch (IOException ioe) {
-      System.out.println(fn + ": Warning: can't open properties file " +
-      	prop + ". Using defaults.");
-      System.out.println(ioe);
-    }
-
-    String sienaURL = p.getProperty("sienaURL",
-    	"senp://canal.psl.cs.columbia.edu:4321");
-    debug = Boolean.valueOf(p.getProperty("debug","false")).booleanValue();
-    String logFile = p.getProperty("logFile", "Metaparser.log");
-    String dbgFile = null;
-    if (debug) {
-      dbgFile = p.getProperty("dbgFile", "Metaparser.dbg");
-    }
-    seSchema = p.getProperty("seSchema", "SmartEventSchema.xsd");
-
-    try {
-      log = new PrintWriter(new FileWriter(logFile), true);
-      log.println("Log started " + MPUtil.timestamp());
-      if (debug) {
-	dbg = new PrintWriter(new FileWriter(dbgFile), true);
-	dbg.println("Debug Log started " + MPUtil.timestamp());
-      }
-    } catch (IOException ioe) {
-      System.err.println(fn + ": Can't open log/debug file:");
-      System.err.println(ioe);
-      // abort
-      return;
-    }
-
-    Metaparser mp = new Metaparser();
-    waitList = Collections.synchronizedMap(new HashMap());
-    // TODO: SienaListeners don't have to be threads...
-    mp.slt = new SienaListenerThread(sienaURL, log, dbg);
-    Thread t = new Thread(mp.slt);
-    if (debug) dbg.println(fn + ": starting slt");  // debug
-    t.start();
-  }
-
-  synchronized public static String getSESchema() {
-    return seSchema;
-  }
-}
+ *  Revision 2.4  2001-02-05 06:35:16  png3
+ *  Post California version
+ *
+ *  Revision 2.3  2001/01/29 04:04:48  png3
+ *  Added package psl.metaparser statements.  Can you say "Oops?"
+ *
+ *  Revision 2.2  2001/01/28 17:52:17  png3
+ *  New version of Metaparser: fully multithreaded.  PrintWriter logs.
+ *
+ *
+ */
+
+public class Metaparser {
+
+  /** when Parsers need to wait for a response, they register
+    * themselves here (key=requestid, value=the object they're
+    * wait()ing on, and wait for a notify().
+    * Synchronized HashMap;
+    */
+  static Map waitList = null;
+  SienaListenerThread slt = null;
+  private static final String fn = "Metaparser";
+  // should allow this from command line also...
+  private static final String prop = "metaparser.properties";
+  static boolean debug = false;
+  private static String seSchema = null;
+  static PrintWriter log = null;
+  static PrintWriter dbg = null;
+
+  public static void main(String args[]) {
+    System.out.println("Metaparser starting up");
+
+    Properties p = new Properties();
+    try {
+      FileInputStream fis = new FileInputStream(prop);
+      p.load(fis);
+    } catch (IOException ioe) {
+      System.out.println(fn + ": Warning: can't open properties file " +
+      	prop + ". Using defaults.");
+      System.out.println(ioe);
+    }
+
+    String sienaURL = p.getProperty("sienaURL",
+    	"senp://canal.psl.cs.columbia.edu:4321");
+    debug = Boolean.valueOf(p.getProperty("debug","false")).booleanValue();
+    String logFile = p.getProperty("logFile", "Metaparser.log");
+    String dbgFile = null;
+    if (debug) {
+      dbgFile = p.getProperty("dbgFile", "Metaparser.dbg");
+    }
+    seSchema = p.getProperty("seSchema", "SmartEventSchema.xsd");
+
+    try {
+      log = new PrintWriter(new FileWriter(logFile), true);
+      log.println("Log started " + MPUtil.timestamp());
+      if (debug) {
+	dbg = new PrintWriter(new FileWriter(dbgFile), true);
+	dbg.println("Debug Log started " + MPUtil.timestamp());
+      }
+    } catch (IOException ioe) {
+      System.err.println(fn + ": Can't open log/debug file:");
+      System.err.println(ioe);
+      // abort
+      return;
+    }
+
+    Metaparser mp = new Metaparser();
+    waitList = Collections.synchronizedMap(new HashMap());
+    // TODO: SienaListeners don't have to be threads...
+    mp.slt = new SienaListenerThread(sienaURL, log, dbg);
+    Thread t = new Thread(mp.slt);
+    if (debug) dbg.println(fn + ": starting slt");  // debug
+    t.start();
+  }
+
+  synchronized public static String getSESchema() {
+    return seSchema;
+  }
+}
diff --git a/ParserThread.java b/ParserThread.java
index 9bf51ee..6d1be3e 100644
--- a/ParserThread.java
+++ b/ParserThread.java
@@ -1,411 +1,439 @@
-package psl.metaparser;
-
-// import oracle.xml.parser.schema.*;
-// import oracle.xml.parser.v2.*;
-import org.xml.sax.*;
-import org.xml.sax.helpers.*;
-import org.apache.xerces.parsers.*;
-
-import psl.worklets2.wvm.*;
-import psl.worklets2.worklets.*;
-import psl.codetransfer.*;
-
-import siena.*;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import psl.tagprocessor.TagProcessor;
-
-/** Handles the parsing one input XML message.
-  * Spawns Validators/SubParsers to validate subcomponents.
-  *
+package psl.metaparser;
+
+// import oracle.xml.parser.schema.*;
+// import oracle.xml.parser.v2.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import org.apache.xerces.parsers.*;
+
+import psl.worklets2.wvm.*;
+import psl.worklets2.worklets.*;
+import psl.codetransfer.*;
+
+import siena.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import psl.tagprocessor.TagProcessor;
+
+/** Handles the parsing one input XML message.
+  * Spawns Validators/SubParsers to validate subcomponents.
+  *
   * $Log$
-  * Revision 2.4  2001-01-30 10:16:55  png3
-  * Almost working...
-  *
-  * Revision 2.3  2001/01/29 04:04:48  png3
-  * Added package psl.metaparser statements.  Can you say "Oops?"
-  *
-  * Revision 2.2  2001/01/29 03:55:34  png3
-  * zapping Def.java.  Replaced by the superior Simin tagprocessor stuff
-  *
-  * Revision 2.1  2001/01/28 17:52:17  png3
-  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
-  *
-  */
-class ParserThread extends DefaultHandler
-	implements Runnable, ClassFileReceiver {
-
-  String xml = null;
-  int instNr = 0;
-  Locator loc = null;
-  SienaListenerThread slt = null;
-  PrintWriter log = null;
-  PrintWriter dbg = null;
-  boolean debug = false;
-  int depth = 0;
-
-  WVM wvm = null;
-  String moduleName = null;
-
-  // for SmartEventSchema
-  // XMLSchema se = null;
-
-  Stack valStack = null;
-  Validator currentVal = null;
-  boolean spawnParser = false;
-
-  private final String source = "psl.metaparser.ParserThread";
-  String requestID = null;
-
-  public ParserThread(String xml, int instNr,
-  	SienaListenerThread slt, boolean debug) {
-    this.xml = xml;
-    this.instNr = instNr;
-    this.slt = slt;
-    this.debug = debug;
-  }
-
-  public String targetLocation() {return ".";}
-
-  public void classesDelivered() {
-    System.err.println("Classes hath been delivered!");
-  }
-
-  void prLog(String m) {log.println(m);}
-  void prDbg(String m) {if (debug) dbg.println(m);}
-
-  public void run() {
-    final String fn = "PT_run(): ";
-
-    try {
-      log = new PrintWriter(new FileWriter("PT"+instNr+".log"), true);
-      log.println("Log started " + MPUtil.timestamp());
-      if (debug) {
-	dbg = new PrintWriter(new FileWriter("PT"+instNr+".dbg"), true);
-	dbg.println("Debug Log started " + MPUtil.timestamp());
-      }
-    } catch (IOException ioe) {
-      System.err.println(fn + "unable to open log files");
-      System.err.println(ioe);
-      return;
-    }
-
-    valStack = new Stack();
-    /*
-    String seSchema = Metaparser.getSESchema();
-    if (debug) dbg.println(fn+"reading in schema " + seSchema); // debug
-    try {
-      File f = new File(seSchema);
-      URL seURL = f.toURL();
-      XSDBuilder b = new XSDBuilder();
-      se = (XMLSchema)b.build(seURL);
-    } catch (Exception e) {
-      log.println(fn+"error while building schema");
-      log.println(e);
-      return;
-    }
-    */
-
-    Hashtable ht = new Hashtable();
-    SAXParser p = new SAXParser();
-    // p.setValidationMode(XMLParser.NONVALIDATING);
-    p.setContentHandler(this);
-    p.setErrorHandler(this);
-    try {
-      p.setFeature("http://xml.org/sax/features/validation", false);
-      p.setFeature("http://xml.org/sax/features/namespaces", true);
-      p.setFeature("http://apache.org/xml/features/validation/schema", false);
-    } catch (SAXNotRecognizedException snre) {
-      prLog(fn+"Exception setting feature:" + snre.getMessage());
-      return;
-    } catch (SAXNotSupportedException snse) {
-      prLog(fn+"Feature not supported:" + snse.getMessage());
-      return;
-    }
-
-    if (debug) dbg.println(fn+"creating new validator");  // debug
-    try {
-      currentVal = new Validator(xml, new PipedWriter(),
-      	"SEValid" + instNr, debug);
-      // initialize outermost depth
-      currentVal.setDepth(-1);
-      currentVal.setElement(null);
-
-      if (debug) dbg.println(fn+"starting to parse");  // debug
-      p.parse(new InputSource(new StringReader(xml)));
-      currentVal.close(true);
-
-      prDbg(fn+"checking for processor");  // debug
-      if (moduleName != null) {
-	prDbg(fn+"module "+moduleName+" should be coming");  // debug
-        synchronized (_wklArrivals) {
-	  if (_wklArrivals.containsKey(requestID)) {
-	    prDbg(fn+"worklet had already arrived:"+
-	    	(Date)_wklArrivals.get(requestID));
-	  } else {
-	    Object lockObj = new Object();
-	    synchronized (lockObj) {
-	      prDbg(fn+"waiting for worklet arrival:" + MPUtil.timestamp());
-	      lockObj.wait();
-	    }
-	    prDbg(fn+"worklet arrived:" + MPUtil.timestamp());
-	  }
-	}
-	try {
-	// Let Simin work his magic
-	  URL[] jarPath = new URL[]{new URL("file://"+moduleName)};
-	  URLClassLoader loader = new URLClassLoader(jarPath);
-	  Class cls = Class.forName
-	      ("psl.tagprocessor.TagProcessorImpl", true, loader);
-
-	  // System.out.println("Working with " + xmlDoc);
-	  XMLReader reader = XMLReaderFactory.createXMLReader
-	  ("org.apache.xerces.parsers.SAXParser");
-	  try {
-	    reader.setFeature("http://xml.org/sax/features/validation", false);
-	    reader.setFeature("http://xml.org/sax/features/namespaces", true);
-	    reader.setFeature("http://apache.org/xml/features/validation/schema", false);
-	  } catch (SAXNotRecognizedException snre) {
-	    prLog(fn+"Exception setting feature:" + snre.getMessage());
-	    return;
-	  } catch (SAXNotSupportedException snse) {
-	    prLog(fn+"Feature not supported:" + snse.getMessage());
-	    return;
-	  }
-	  TagProcessor tp = (TagProcessor) cls.newInstance();
-	  //tp.setJarPath("file:");
-	  //tp.setResource(jarPath[0].getPath());
-	  tp.setResource(moduleName);
-	  tp.init(ht);
-	  reader.setContentHandler(tp.getContentHandler());
-	  reader.parse(new InputSource(new StringReader(xml)));
-	  tp.process();
-	} catch (Exception e) {
-	  log.println("Error during TagProcessor Execution:" + e);
-	  return;
-	}
-
-	prDbg(fn+"Resulting Hashtable is: " + ht);
-     }
-
-    } catch (Exception e) {
-      log.println(fn+"Exception during parsing at " +
-      	MPUtil.printLoc(loc));
-      log.println(e);
-      e.printStackTrace();
-      return;
-    }
-    prDbg(fn+"shutting down wvm");
-    wvm.shutdown();
-    if (debug) dbg.println(fn+"Done parsing");
-  }
-
-  public void setDocumentLocator(Locator loc) {
-
-    final String fn = "PT_setDocLoc: ";
-
-    prDbg(fn+"SetDocumentLocator:");
-    this.loc = loc;
-  }
-
-  public void startDocument() {
-
-    final String fn = "PT_startDoc: ";
-
-    prDbg(fn+"StartDocument");
-  }
-
-  public void endDocument() throws SAXException {
-
-    final String fn = "PT_endDoc: ";
-
-    prDbg(fn+"EndDocument");
-  }
-
-  public void startElement(
-          String namespaceURI, String localName, String qName, Attributes atts)
-            throws SAXException {
-
-    final String fn = "PT_startElement: ";
-    String oracleResp = null;
-
-    prDbg(fn+"StartElement " + MPUtil.printLoc(loc) + ":" + qName);
-    for (int i = 0; i < atts.getLength(); i++) {
-      String aname = atts.getQName(i);
-      String type  = atts.getType(i);
-      String value = atts.getValue(i);
-
-      prDbg(fn+"   " + aname + "(" + type + ")" + "=" + value);
-    }
-    if (spawnParser) {
-      prDbg(fn+"*** pushing currentVal");
-      valStack.push(currentVal);
-
-      // retrieve subparser
-      requestID = String.valueOf(System.currentTimeMillis());
-
-      prDbg(fn+"creating new WVM("+slt.hostname+","+requestID+")");
-      wvm = new WVM(this, slt.hostname, requestID);
-
-      Notification n = new Notification();
-      n.putAttribute("hostname", slt.hostname);
-      n.putAttribute("source", source);
-      n.putAttribute("SrcID", slt.SRC_ID);
-      n.putAttribute("RequestID", requestID);
-      n.putAttribute("type", "query");
-      n.putAttribute("query", MPUtil.makeQuery(qName));
-      prDbg(fn+"sending request to Oracle:" + n);
-      try {
-	slt.publish(n);
-	Object lockObj = new Object();
-	Metaparser.waitList.put(requestID, lockObj);
-	prDbg(fn+"going to sleep: " + MPUtil.timestamp());
-	synchronized (lockObj) {
-	  lockObj.wait();
-	}
-	prDbg(fn+"awake again: " + MPUtil.timestamp());
-	// hash entry now has the XML string
-	oracleResp = (String)Metaparser.waitList.get(requestID);
-	prDbg(fn+"retrieved OResp of:"+oracleResp);
-	// XMLSchema subSchema = MPUtil.extractSchema(oracleResp);
-	MPUtil.extractSchema(oracleResp);
-	moduleName = MPUtil.extractModuleName(oracleResp);
-	// we have a new schema.  parse it out, suck it in...
-	currentVal = new Validator(xml, new PipedWriter(),
-	  "SubValid" + instNr, debug, loc);
-	currentVal.send("<?xml version='1.0' encoding='UTF-8'?>");
-	// mega-hack -- defies description
-	// extracted XML is sitting in file schema.xsd
-	currentVal.send("<"+qName+
-		" xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance'" +
-  		" xsi:NoNamespaceSchemaLocation='schema.xsd'" +
-		 ">");
-      } catch (Exception e) {
-	prLog(fn+"Exception with Oracle communication: " + e);
-      }
-
-      prDbg(fn+"*** Saving depth info of depth:" + depth
-        + ", targetElement:" + qName);
-      currentVal.setDepth(depth);
-      currentVal.setElement(qName);
-      spawnParser = false;
-    }
-
-    // finally, spit out this tag
-    try {
-      currentVal.flush(loc);
-    } catch (IOException ioe) {
-      prLog(fn+"Flush error:" + ioe);
-    }
-    ++depth;
-  }
-
-
-  public void endElement(String namespaceURI, String localName, String qName)
-  	throws SAXException {
-    final String fn = "PT endElement: ";
-    --depth;
-    prDbg(fn + qName);
-    try {
-      currentVal.flush(loc);
-    } catch (IOException ioe) {
-      prDbg(fn+"Flush error:" + ioe);
-    }
-    if ((currentVal.getDepth() == depth) &&
-    	(currentVal.getElement().equals(qName))) {
-      prDbg(fn+"*** Popping back to previous parser");
-      try {
-	currentVal.close(false);
-	currentVal = (Validator)valStack.pop();
-	currentVal.skip(loc);
-      } catch (IOException ioe) {
-	prDbg(fn+"close error:" + ioe);
-      }
-    }
-  }
-
-  public void startPrefixMapping(String prefix, String uri) throws SAXException {
-    prDbg("PT: startPrefixMapping: prefix:" + prefix);
-    prDbg("PT: \turi:" + uri);
-  }
-
-  public void endPrefixMapping(String prefix) throws SAXException {
-    prDbg("PT: EndPrefixMapping:" + prefix);
-  }
-
-  public void skippedEntity(String entity) throws SAXException {
-    prDbg("PT: skippedEntity:" + entity);
-  }
-
-  public void characters(char[] cbuf, int start, int len) {
-    prDbg("PT: Characters:" + new String(cbuf, start, len));
-    try {
-      currentVal.flush(loc);
-    } catch (IOException ioe) {
-      prDbg("PT: Flush error:" + ioe);
-    }
-  }
-
-  public void ignorableWhitespace(char[] cbuf, int start, int len) {
-    prDbg("PT: IgnorableWhiteSpace");
-  }
-
-  public void processingInstruction(String target, String data)
-          throws SAXException {
-    final String fn = "PT PI: ";
-    prDbg(fn+"ProcessingInstruction:" + target + " " + data);
-    if (target.toLowerCase().equals("flexml")) {
-      ++depth;
-      prDbg(fn+"Found FleXML tag!");
-      ++depth;
-      StringTokenizer st = new StringTokenizer(data);
-      while (st.hasMoreTokens()) {
-        String piAttr = st.nextToken();
-        StringTokenizer st2 = new StringTokenizer(piAttr, "=\" ");
-	if (st2.countTokens() != 2) {
-	  prDbg(fn+"Malformed PI Attribute: " + piAttr);
-	} else {
-	  String piaName = st2.nextToken();
-	  String piaVal = st2.nextToken();
-	  prDbg(fn+piaName + " = " + piaVal);
-	  if (piaName.toLowerCase().equals("type")) {
-	    if (piaVal.toLowerCase().equals("schemafrag")) {
-	      ++depth;
-	      prDbg(fn+"*** found schemaFrag PI ***");
-	      // next element needs to be saved as "outermost"
-	      // element of subdocument
-	      spawnParser = true;
-	      --depth;
-	    }
-	  }
-	}
-      }
-      depth -= 2;
-    }
-
-    try {
-      currentVal.flush(loc);
-    } catch (IOException ioe) {
-      prDbg("PT Flush error:" + ioe);
-    }
-  }
-
-  public void warning(SAXParseException e) throws SAXException {
-    prLog("PT Warning:" + e.getMessage());
-  }
-
-  public void error(SAXParseException e) throws SAXException {
-    prLog("PT Error:" + e.getMessage());
-    throw new SAXException(e.getMessage());
-  }
-
-  public void fatalError(SAXParseException e) throws SAXException {
-    prLog("PT Fatal error" + e.getMessage());
-    throw new SAXException(e.getMessage());
-  }
-
-
-}
+  * Revision 2.5  2001-02-05 06:35:16  png3
+  * Post California version
+  *
+  * Revision 2.4  2001/01/30 10:16:55  png3
+  * Almost working...
+  *
+  * Revision 2.3  2001/01/29 04:04:48  png3
+  * Added package psl.metaparser statements.  Can you say "Oops?"
+  *
+  * Revision 2.2  2001/01/29 03:55:34  png3
+  * zapping Def.java.  Replaced by the superior Simin tagprocessor stuff
+  *
+  * Revision 2.1  2001/01/28 17:52:17  png3
+  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
+  *
+  */
+class ParserThread extends DefaultHandler
+	implements Runnable, ClassFileReceiver {
+
+  String xml = null;
+  int instNr = 0;
+  Locator loc = null;
+  SienaListenerThread slt = null;
+  PrintWriter log = null;
+  PrintWriter dbg = null;
+  boolean debug = false;
+  int depth = 0;
+
+  WVM wvm = null;
+  String moduleName = null;
+
+  // for SmartEventSchema
+  // XMLSchema se = null;
+
+  Stack valStack = null;
+  Validator currentVal = null;
+  boolean spawnParser = false;
+
+  private final String source = "psl.metaparser.ParserThread";
+  String requestID = null;
+
+  public ParserThread(String xml, int instNr,
+  	SienaListenerThread slt, boolean debug) {
+    this.xml = xml;
+    this.instNr = instNr;
+    this.slt = slt;
+    this.debug = debug;
+  }
+
+  public String targetLocation() {return ".";}
+
+  public void classesDelivered() {
+    System.err.println("Classes have been delivered!");
+  }
+
+  void prLog(String m) {log.println(m);}
+  void prDbg(String m) {if (debug) dbg.println(m);}
+
+  public void run() {
+    final String fn = "PT_run(): ";
+
+    try {
+      log = new PrintWriter(new FileWriter("PT"+instNr+".log"), true);
+      log.println("Log started " + MPUtil.timestamp());
+      if (debug) {
+	dbg = new PrintWriter(new FileWriter("PT"+instNr+".dbg"), true);
+	dbg.println("Debug Log started " + MPUtil.timestamp());
+      }
+    } catch (IOException ioe) {
+      System.err.println(fn + "unable to open log files");
+      System.err.println(ioe);
+      return;
+    }
+
+    valStack = new Stack();
+    /*
+    String seSchema = Metaparser.getSESchema();
+    if (debug) dbg.println(fn+"reading in schema " + seSchema); // debug
+    try {
+      File f = new File(seSchema);
+      URL seURL = f.toURL();
+      XSDBuilder b = new XSDBuilder();
+      se = (XMLSchema)b.build(seURL);
+    } catch (Exception e) {
+      log.println(fn+"error while building schema");
+      log.println(e);
+      return;
+    }
+    */
+
+    Hashtable ht = new Hashtable();
+    SAXParser p = new SAXParser();
+    // p.setValidationMode(XMLParser.NONVALIDATING);
+    p.setContentHandler(this);
+    p.setErrorHandler(this);
+    try {
+      p.setFeature("http://xml.org/sax/features/validation", false);
+      p.setFeature("http://xml.org/sax/features/namespaces", true);
+      p.setFeature("http://apache.org/xml/features/validation/schema", false);
+    } catch (SAXNotRecognizedException snre) {
+      prLog(fn+"Exception setting feature:" + snre.getMessage());
+      return;
+    } catch (SAXNotSupportedException snse) {
+      prLog(fn+"Feature not supported:" + snse.getMessage());
+      return;
+    }
+
+    if (debug) dbg.println(fn+"creating new validator");  // debug
+    try {
+      currentVal = new Validator(xml, new PipedWriter(),
+      	"SEValid" + instNr, debug);
+      // initialize outermost depth
+      currentVal.setDepth(-1);
+      currentVal.setElement(null);
+
+      if (debug) dbg.println(fn+"starting to parse");  // debug
+      p.parse(new InputSource(new StringReader(xml)));
+      currentVal.close(true);
+
+      prDbg(fn+"checking for processor");  // debug
+      if (moduleName != null) {
+
+	prDbg(fn+"module "+moduleName+" should be coming");  // debug
+	/*
+	// fake!
+	prDbg(fn+"waiting for worklet arrival:" + MPUtil.timestamp());
+	Thread.currentThread().sleep(1000);
+	prDbg(fn+"worklet arrived:" + MPUtil.timestamp());
+	*/
+
+        synchronized (_wklArrivals) {
+	  if (_wklArrivals.containsKey(requestID)) {
+	    prDbg(fn+"worklet had already arrived:"+
+	    	(Date)_wklArrivals.get(requestID));
+	  } else {
+	    Object lockObj = new Object();
+	    synchronized (lockObj) {
+	      prDbg(fn+"waiting for worklet arrival:" + MPUtil.timestamp());
+	      lockObj.wait();
+	    }
+	    prDbg(fn+"worklet arrived:" + MPUtil.timestamp());
+	  }
+	}
+
+	try {
+	// Let Simin work his magic
+	  URL[] jarPath = new URL[]{new URL("file://"+moduleName)};
+	  URLClassLoader loader = new URLClassLoader(jarPath);
+	  Class cls = Class.forName
+	      ("psl.tagprocessor.TagProcessorImpl", true, loader);
+
+	  // System.out.println("Working with " + xmlDoc);
+	  XMLReader reader = XMLReaderFactory.createXMLReader
+	  ("org.apache.xerces.parsers.SAXParser");
+	  try {
+	    reader.setFeature("http://xml.org/sax/features/validation", false);
+	    reader.setFeature("http://xml.org/sax/features/namespaces", true);
+	    reader.setFeature("http://apache.org/xml/features/validation/schema", false);
+	  } catch (SAXNotRecognizedException snre) {
+	    prLog(fn+"Exception setting feature:" + snre.getMessage());
+	    return;
+	  } catch (SAXNotSupportedException snse) {
+	    prLog(fn+"Feature not supported:" + snse.getMessage());
+	    return;
+	  }
+	  TagProcessor tp = (TagProcessor) cls.newInstance();
+	  //tp.setJarPath("file:");
+	  //tp.setResource(jarPath[0].getPath());
+	  tp.setResource(moduleName);
+	  tp.init(ht);
+	  reader.setContentHandler(tp.getContentHandler());
+	  dbg.println(fn+"TagProcessor about to parse");
+	  reader.parse(new InputSource(new StringReader(xml)));
+	  dbg.println(fn+"TagProcessor about to process");
+	  tp.process();
+	} catch (Exception e) {
+	  log.println("Error during TagProcessor Execution:" + e);
+	  e.printStackTrace();
+	  return;
+	}
+
+	prDbg(fn+"Resulting Hashtable is: " + ht);
+     }
+
+    } catch (Exception e) {
+      log.println(fn+"Exception during parsing at " +
+      	MPUtil.printLoc(loc));
+      log.println(e);
+      e.printStackTrace();
+      return;
+    }
+    prDbg(fn+"shutting down wvm");
+    // don't shutdown if fake
+    wvm.shutdown();
+    if (debug) dbg.println(fn+"Done parsing");
+  }
+
+  public void setDocumentLocator(Locator loc) {
+
+    final String fn = "PT_setDocLoc: ";
+
+    prDbg(fn+"SetDocumentLocator:");
+    this.loc = loc;
+  }
+
+  public void startDocument() {
+
+    final String fn = "PT_startDoc: ";
+
+    prDbg(fn+"StartDocument");
+  }
+
+  public void endDocument() throws SAXException {
+
+    final String fn = "PT_endDoc: ";
+
+    prDbg(fn+"EndDocument");
+  }
+
+  public void startElement(
+          String namespaceURI, String localName, String qName, Attributes atts)
+            throws SAXException {
+
+    final String fn = "PT_startElement: ";
+    String oracleResp = null;
+
+    prDbg(fn+MPUtil.printLoc(loc) + ":" + qName);
+    for (int i = 0; i < atts.getLength(); i++) {
+      String aname = atts.getQName(i);
+      String type  = atts.getType(i);
+      String value = atts.getValue(i);
+
+      prDbg(fn+"   " + aname + "(" + type + ")" + "=" + value);
+    }
+    if (spawnParser) {
+      prDbg(fn+"*** pushing currentVal");
+      valStack.push(currentVal);
+
+      // retrieve subparser
+      requestID = String.valueOf(System.currentTimeMillis());
+
+      prDbg(fn+"creating new WVM("+slt.hostname+","+requestID+")");
+      /*
+      // fake!
+      System.out.println("WVM created");
+      */
+      wvm = new WVM(this, slt.hostname, requestID);
+
+      Notification n = new Notification();
+      n.putAttribute("hostname", slt.hostname);
+      n.putAttribute("source", source);
+      n.putAttribute("SrcID", slt.SRC_ID);
+      n.putAttribute("RequestID", requestID);
+      n.putAttribute("type", "query");
+      n.putAttribute("query", MPUtil.makeQuery(qName));
+      prDbg(fn+"sending request to Oracle:" + n);
+      try {
+      /*
+	// fake!
+	prDbg(fn+"going to sleep: " + MPUtil.timestamp());
+	Thread.currentThread().sleep(1000);
+	prDbg(fn+"awake again: " + MPUtil.timestamp());
+	moduleName="tagprocessor.jar";
+      */
+	slt.publish(n);
+	Object lockObj = new Object();
+	Metaparser.waitList.put(requestID, lockObj);
+	prDbg(fn+"going to sleep: " + MPUtil.timestamp());
+	synchronized (lockObj) {
+	  lockObj.wait();
+	}
+	prDbg(fn+"awake again: " + MPUtil.timestamp());
+	// hash entry now has the XML string
+	oracleResp = (String)Metaparser.waitList.get(requestID);
+	prDbg(fn+"retrieved OResp of:"+oracleResp);
+	// XMLSchema subSchema = MPUtil.extractSchema(oracleResp);
+	MPUtil.extractSchema(oracleResp);
+	moduleName = MPUtil.extractModuleName(oracleResp);
+
+	// we have a new schema.  parse it out, suck it in...
+	currentVal = new Validator(xml, new PipedWriter(),
+	  "SubValid" + instNr, debug, loc);
+	currentVal.send("<?xml version='1.0' encoding='UTF-8'?>");
+	// mega-hack -- defies description
+	// extracted XML is sitting in file schema.xsd
+	currentVal.send("<"+qName+
+		" xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance'" +
+  		" xsi:noNamespaceSchemaLocation='schema.xsd'>");
+      } catch (Exception e) {
+	prLog(fn+"Exception with Oracle communication: " + e);
+	e.printStackTrace();
+      }
+
+      prDbg(fn+"*** Saving depth info of depth:" + depth
+        + ", targetElement:" + qName);
+      currentVal.setDepth(depth);
+      currentVal.setElement(qName);
+      spawnParser = false;
+    }
+
+    // finally, spit out this tag
+    try {
+      currentVal.flush(loc);
+    } catch (IOException ioe) {
+      prLog(fn+"Flush error:" + ioe);
+    }
+    ++depth;
+  }
+
+
+  public void endElement(String namespaceURI, String localName, String qName)
+  	throws SAXException {
+    final String fn = "PT endElement: ";
+    --depth;
+    prDbg(fn + qName);
+    try {
+      currentVal.flush(loc);
+    } catch (IOException ioe) {
+      prDbg(fn+"Flush error:" + ioe);
+    }
+    if ((currentVal.getDepth() == depth) &&
+    	(currentVal.getElement().equals(qName))) {
+      prDbg(fn+"*** Popping back to previous parser");
+      try {
+	currentVal.close(false);
+	currentVal = (Validator)valStack.pop();
+	currentVal.skip(loc);
+      } catch (IOException ioe) {
+	prDbg(fn+"close error:" + ioe);
+      }
+    }
+  }
+
+  public void startPrefixMapping(String prefix, String uri) throws SAXException {
+    prDbg("PT: startPrefixMapping: prefix:" + prefix);
+    prDbg("PT: \turi:" + uri);
+  }
+
+  public void endPrefixMapping(String prefix) throws SAXException {
+    prDbg("PT: EndPrefixMapping:" + prefix);
+  }
+
+  public void skippedEntity(String entity) throws SAXException {
+    prDbg("PT: skippedEntity:" + entity);
+  }
+
+  public void characters(char[] cbuf, int start, int len) {
+    prDbg("PT: Characters:" + new String(cbuf, start, len));
+    try {
+      currentVal.flush(loc);
+    } catch (IOException ioe) {
+      prDbg("PT: Flush error:" + ioe);
+    }
+  }
+
+  public void ignorableWhitespace(char[] cbuf, int start, int len) {
+    prDbg("PT: IgnorableWhiteSpace");
+  }
+
+  public void processingInstruction(String target, String data)
+          throws SAXException {
+    final String fn = "PT PI: ";
+    prDbg(fn+"ProcessingInstruction:" + target + " " + data);
+    if (target.toLowerCase().equals("flexml")) {
+      ++depth;
+      prDbg(fn+"Found FleXML tag!");
+      ++depth;
+      StringTokenizer st = new StringTokenizer(data);
+      while (st.hasMoreTokens()) {
+        String piAttr = st.nextToken();
+        StringTokenizer st2 = new StringTokenizer(piAttr, "=\" ");
+	if (st2.countTokens() != 2) {
+	  prDbg(fn+"Malformed PI Attribute: " + piAttr);
+	} else {
+	  String piaName = st2.nextToken();
+	  String piaVal = st2.nextToken();
+	  prDbg(fn+piaName + " = " + piaVal);
+	  if (piaName.toLowerCase().equals("type")) {
+	    if (piaVal.toLowerCase().equals("schemafrag")) {
+	      ++depth;
+	      prDbg(fn+"*** found schemaFrag PI ***");
+	      // next element needs to be saved as "outermost"
+	      // element of subdocument
+	      spawnParser = true;
+	      --depth;
+	    }
+	  }
+	}
+      }
+      depth -= 2;
+    }
+
+    try {
+      currentVal.flush(loc);
+    } catch (IOException ioe) {
+      prDbg("PT Flush error:" + ioe);
+    }
+  }
+
+  public void warning(SAXParseException e) throws SAXException {
+    prLog("PT Warning:" + e.getMessage());
+  }
+
+  public void error(SAXParseException e) throws SAXException {
+    prLog("PT Error:" + e.getMessage());
+    throw new SAXException(e.getMessage());
+  }
+
+  public void fatalError(SAXParseException e) throws SAXException {
+    prLog("PT Fatal error" + e.getMessage());
+    throw new SAXException(e.getMessage());
+  }
+
+
+}
diff --git a/SienaListenerThread.java b/SienaListenerThread.java
index 0230c23..395a9be 100644
--- a/SienaListenerThread.java
+++ b/SienaListenerThread.java
@@ -1,190 +1,198 @@
-package psl.metaparser;
-
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import siena.*;
-
-/** Listener for incoming Siena events.
-  * Spawns ParserThreads.
-  *
+package psl.metaparser;
+
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import siena.*;
+
+/** Listener for incoming Siena events.
+  * Spawns ParserThreads.
+  *
   * $Log$
-  * Revision 2.3  2001-01-30 10:16:55  png3
-  * Almost working...
-  *
-  * Revision 2.2  2001/01/29 04:04:48  png3
-  * Added package psl.metaparser statements.  Can you say "Oops?"
-  *
-  * Revision 2.1  2001/01/28 17:52:17  png3
-  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
-  *
-  */
-class SienaListenerThread implements Runnable {
-
-  private Siena s = null;
-  private String sienaURL = null;
-  private PrintWriter log = null;
-  private PrintWriter dbg = null;
-  boolean debug = false;
-
-  String hostname = null;
-  private final String source = "psl.metaparser.SienaListenerThread";
-
-
-
-  private static final int RECV_PORT = 31337;
-  //TODO: get from sequencer somewhere
-  static final int SRC_ID = 1;
-
-  static int instance_counter = 0;
-
-  SienaListenerThread (String sienaURL, PrintWriter log, PrintWriter dbg) {
-    this.sienaURL = sienaURL;
-    this.log = log;
-    this.dbg = dbg;
-    debug = (dbg == null);
-
-    try {
-      hostname = InetAddress.getLocalHost().getHostName();
-    } catch (UnknownHostException uhe) {
-      log.println("slt_ctor: can't get local host name:" + uhe);
-      return;
-    }
-  }
-
-  // TODO: not thread safe, but we're going to un-Thread this anyway...
-  void prLog(String m) {log.println(m);}
-  void prDbg(String m) {if (debug) dbg.println(m);}
-
-  synchronized static int get_inst_nr() {
-    return instance_counter++;
-  }
-
-  public void run() {
-
-    final String fn = "slt_run";
-
-    final HierarchicalDispatcher hd = new HierarchicalDispatcher();
-    try {
-      // debug
-      if (dbg != null) dbg.println(fn + " setting recv port to " +
-      	RECV_PORT + ", and sienaURL to " + sienaURL);
-      hd.setReceiver(new TCPPacketReceiver(RECV_PORT));
-      hd.setMaster(sienaURL);
-    } catch (InvalidSenderException ise) {
-      log.println(fn + ": Invalid Sender:" + ise);
-      return;
-    } catch (IOException ioe) {
-      log.println(fn + ": Unable to set hd receiver:" + ioe);
-      return;
-    }
-
-    // we have our Siena
-    synchronized (this) {
-      s = hd;
-    }
-
-    Runtime.getRuntime().addShutdownHook(new Thread() {
-      public void run() {
-	System.err.println("SLT shutting down");
-	hd.shutdown();
-      } });
-
-    // create filters
-    // #1, stuff coming from ED
-    Filter f1 = new Filter();
-    f1.addConstraint("Source", "EventDistiller");
-    f1.addConstraint("Type", "DataToMetaParser");
-    // debug
-    if (dbg != null) dbg.println("adding ED filter " + f1);
-    try {
-      synchronized (this) {
-	s.subscribe(f1,
-	  new Notifiable() {
-	    public void notify(Notification n) {handleEDNotification(n);}
-	    public void notify(Notification[] s) {}
-	  }
-	);
-      }
-    } catch (SienaException se) {
-      log.println(fn + ": SienaException adding filter 1:");
-      log.println(se);
-      return;
-    }
-
-    // #2: from Oracle
-    Filter f2 = new Filter();
-    f2.addConstraint("source", "psl.oracle.impl.OracleSienaInterface");
-    f2.addConstraint("type", "queryResult");
-    // TODO: when Oracle sends it, subscribe to it...
-    f2.addConstraint("MPHostname", hostname);
-    f2.addConstraint("MPSrcID", SRC_ID);
-    // debug
-    if (dbg != null) dbg.println(fn + " adding Oracle filter " + f2);
-    try {
-      synchronized (this) {
-	s.subscribe(f2,
-	  new Notifiable() {
-	    public void notify(Notification n) {handleOracleNotification(n);}
-	    public void notify(Notification[] s) {}
-	  }
-	);
-      }
-    } catch (SienaException se) {
-      log.println(fn + ": SienaException adding filter 2:");
-      log.println(se);
-      return;
-    }
-  }
-
-  public void handleEDNotification(Notification n) {
-    if (dbg != null) {  // debug
-      dbg.println("hEN(): got ED notification:" + n);
-    }
-    AttributeValue se = n.getAttribute("SmartEvent");
-    ParserThread pt = new ParserThread(se.stringValue(),
-    	get_inst_nr(), this, (dbg != null));
-    Thread t = new Thread(pt);
-    t.start();
-  }
-
-  public void handleOracleNotification(Notification n) {
-    String reqID = null;
-    String oracleResp = null;
-    final String fn="hON: ";
-
-    prDbg(fn+"got Oracle notification" + n);
-
-
-    // TODO: check for not found
-    AttributeValue se = n.getAttribute("MPRequestID");
-    reqID = se.stringValue();
-    se = n.getAttribute("value");
-    oracleResp = se.stringValue();
-
-    Object o = Metaparser.waitList.get(reqID);
-    // replace hash entry with oracle xml
-    prDbg(fn+"Hash replace: key="+reqID+"; val="+oracleResp);
-    Metaparser.waitList.put(reqID, oracleResp);
-    prDbg(fn+"notifying...");
-    synchronized(o) {
-      // wakey, wakey
-      o.notify();
-    }
-  }
-
-  // synchronized wrapper
-  synchronized public void publish(Notification n) {
-    final String fn = "SLT_publish: ";
-    if (dbg != null) { dbg.println("publishing " + n); } // debug
-    try {
-      s.publish(n);
-    } catch (SienaException se) {
-      log.println(fn+"SienaException while publishing " + n);
-      log.println(se);
-      return;
-    }
-  }
-
-}
+  * Revision 2.4  2001-02-05 06:35:16  png3
+  * Post California version
+  *
+  * Revision 2.3  2001/01/30 10:16:55  png3
+  * Almost working...
+  *
+  * Revision 2.2  2001/01/29 04:04:48  png3
+  * Added package psl.metaparser statements.  Can you say "Oops?"
+  *
+  * Revision 2.1  2001/01/28 17:52:17  png3
+  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
+  *
+  */
+class SienaListenerThread implements Runnable {
+
+  private Siena s = null;
+  private String sienaURL = null;
+  private PrintWriter log = null;
+  private PrintWriter dbg = null;
+  boolean debug = false;
+
+  String hostname = null;
+  private final String source = "psl.metaparser.SienaListenerThread";
+
+
+
+  private static final int RECV_PORT = 31337;
+  //TODO: get from sequencer somewhere
+  static final int SRC_ID = 1;
+
+  static int instance_counter = 0;
+
+  SienaListenerThread (String sienaURL, PrintWriter log, PrintWriter dbg) {
+    this.sienaURL = sienaURL;
+    this.log = log;
+    this.dbg = dbg;
+    debug = (dbg == null);
+
+    try {
+      hostname = InetAddress.getLocalHost().getHostName();
+    } catch (UnknownHostException uhe) {
+      log.println("slt_ctor: can't get local host name:" + uhe);
+      return;
+    }
+  }
+
+  // TODO: not thread safe, but we're going to un-Thread this anyway...
+  void prLog(String m) {log.println(m);}
+  void prDbg(String m) {if (debug) dbg.println(m);}
+
+  synchronized static int get_inst_nr() {
+    return instance_counter++;
+  }
+
+  public void run() {
+
+    final String fn = "slt_run";
+
+    final HierarchicalDispatcher hd = new HierarchicalDispatcher();
+    try {
+      // debug
+      if (dbg != null) dbg.println(fn + " setting recv port to " +
+      	RECV_PORT + ", and sienaURL to " + sienaURL);
+      hd.setReceiver(new TCPPacketReceiver(RECV_PORT));
+      hd.setMaster(sienaURL);
+    } catch (InvalidSenderException ise) {
+      log.println(fn + ": Invalid Sender:" + ise);
+      return;
+    } catch (IOException ioe) {
+      log.println(fn + ": Unable to set hd receiver:" + ioe);
+      return;
+    }
+
+    // we have our Siena
+    synchronized (this) {
+      s = hd;
+    }
+
+    System.out.println("Subscribed to siena " + sienaURL);
+
+    Runtime.getRuntime().addShutdownHook(new Thread() {
+      public void run() {
+	System.err.println("SLT shutting down");
+	hd.shutdown();
+      } });
+
+    // create filters
+    // #1, stuff coming from ED
+    Filter f1 = new Filter();
+    f1.addConstraint("Source", "EventDistiller");
+    f1.addConstraint("Type", "DataToMetaparser");
+    // debug
+    if (dbg != null) dbg.println("adding ED filter " + f1);
+    try {
+      synchronized (this) {
+	s.subscribe(f1,
+	  new Notifiable() {
+	    public void notify(Notification n) {handleEDNotification(n);}
+	    public void notify(Notification[] s) {}
+	  }
+	);
+      }
+    } catch (SienaException se) {
+      log.println(fn + ": SienaException adding filter 1:");
+      log.println(se);
+      return;
+    }
+
+    // #2: from Oracle
+    Filter f2 = new Filter();
+    f2.addConstraint("source", "psl.oracle.impl.OracleSienaInterface");
+    f2.addConstraint("type", "queryResult");
+    // TODO: when Oracle sends it, subscribe to it...
+    f2.addConstraint("MPHostname", hostname);
+    f2.addConstraint("MPSrcID", SRC_ID);
+    // debug
+    if (dbg != null) dbg.println(fn + " adding Oracle filter " + f2);
+    try {
+      synchronized (this) {
+	s.subscribe(f2,
+	  new Notifiable() {
+	    public void notify(Notification n) {handleOracleNotification(n);}
+	    public void notify(Notification[] s) {}
+	  }
+	);
+      }
+    } catch (SienaException se) {
+      log.println(fn + ": SienaException adding filter 2:");
+      log.println(se);
+      return;
+    }
+  }
+
+  public void handleEDNotification(Notification n) {
+    final String fn="handleEDNotification: ";
+    if (dbg != null) {  // debug
+      dbg.println("hEN(): got ED notification:" + n);
+    }
+    AttributeValue se = n.getAttribute("SmartEvent");
+    prLog(fn+"Received event from EventDistiller.  Starting ParserThread " +
+    	MPUtil.timestamp());
+    ParserThread pt = new ParserThread(se.stringValue(),
+    	get_inst_nr(), this, (dbg != null));
+    Thread t = new Thread(pt);
+    t.start();
+  }
+
+  public void handleOracleNotification(Notification n) {
+    String reqID = null;
+    String oracleResp = null;
+    final String fn="hON: ";
+
+    prDbg(fn+"got Oracle notification" + n);
+
+
+    // TODO: check for not found
+    AttributeValue se = n.getAttribute("MPRequestID");
+    reqID = se.stringValue();
+    se = n.getAttribute("value");
+    oracleResp = se.stringValue();
+
+    Object o = Metaparser.waitList.get(reqID);
+    // replace hash entry with oracle xml
+    prDbg(fn+"Hash replace: key="+reqID+"; val="+oracleResp);
+    Metaparser.waitList.put(reqID, oracleResp);
+    prDbg(fn+"notifying...");
+    synchronized(o) {
+      // wakey, wakey
+      o.notify();
+    }
+  }
+
+  // synchronized wrapper
+  synchronized public void publish(Notification n) {
+    final String fn = "SLT_publish: ";
+    if (dbg != null) { dbg.println("publishing " + n); } // debug
+    try {
+      s.publish(n);
+    } catch (SienaException se) {
+      log.println(fn+"SienaException while publishing " + n);
+      log.println(se);
+      return;
+    }
+  }
+
+}
diff --git a/SienaTest.java b/SienaTest.java
index c36c2b9..3848de2 100644
--- a/SienaTest.java
+++ b/SienaTest.java
@@ -1,75 +1,89 @@
-package psl.metaparser;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import siena.*;
-
-/** Generates ED-like XML notification.
-  * One argument: xml message to include.
-  *
+package psl.metaparser;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import psl.kx.*;
+
+import siena.*;
+
+/** Generates ED-like XML notification.
+  * One argument: xml message to include.
+  *
   * $Log$
-  * Revision 2.3  2001-01-30 10:16:55  png3
-  * Almost working...
-  *
-  * Revision 2.2  2001/01/29 04:04:48  png3
-  * Added package psl.metaparser statements.  Can you say "Oops?"
-  *
-  * Revision 2.1  2001/01/28 17:52:17  png3
-  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
-  *
-  */
-public class SienaTest {
-
-  /** Constructor */
-  public static void main(String[] args) {
-
-    String xml = null;
-    String s;
-
-    HierarchicalDispatcher hd = new HierarchicalDispatcher();
-    try {
-      hd.setReceiver(new TCPPacketReceiver(31339));
-      hd.setMaster("senp://canal.psl.cs.columbia.edu:4321");
-    } catch (IOException ioe) {
-      System.err.println("Unable to set hd receiver:" + ioe);
-      return;
-    } catch (InvalidSenderException ise) {
-      System.err.println("Invalid Sender:" + ise);
-      return;
-    }
-
-    System.err.println("Reading test file " + args[0]);
-    StringBuffer sb = new StringBuffer();
-    s = null;
-    try {
-      BufferedReader tf_br = new BufferedReader(new FileReader(args[0]));
-      do {
-	s = tf_br.readLine();
-	if (s != null) {
-	  sb.append(s);
-	  sb.append("\n");
-	}
-      } while (s != null);
-    } catch (IOException ioe) {
-      System.err.println("Exception when reading " + args[0] + ":" + ioe);
-      return;
-    }
-    xml = sb.toString();
-    System.err.println("About to parse:\n" + xml+"\n.");
-
-    Notification n = new Notification();
-    n.putAttribute("Source", "EventDistiller");
-    n.putAttribute("Type", "DataToMetaParser");
-    n.putAttribute("SmartEvent", xml);
-
-    try {
-      hd.publish(n);
-    } catch (SienaException se) {
-      System.err.println("Siena exception on publish:" + se);
-      return;
-    }
-    hd.shutdown();
-  }
-}
+  * Revision 2.4  2001-02-05 06:35:16  png3
+  * Post California version
+  *
+  * Revision 2.3  2001/01/30 10:16:55  png3
+  * Almost working...
+  *
+  * Revision 2.2  2001/01/29 04:04:48  png3
+  * Added package psl.metaparser statements.  Can you say "Oops?"
+  *
+  * Revision 2.1  2001/01/28 17:52:17  png3
+  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
+  *
+  */
+public class SienaTest {
+
+  /** Constructor */
+  public static void main(String[] args) {
+
+    String xml = null;
+    String s;
+    String master = "senp://canal.psl.cs.columbia.edu:4321";
+
+    if (args.length < 1) {
+    	System.err.println("Usage: SienaTest foo.xml [senp://blah]");
+    } else if (args.length == 2) {
+      master = args[1];
+    }
+
+
+    HierarchicalDispatcher hd = new HierarchicalDispatcher();
+    try {
+      hd.setReceiver(new TCPPacketReceiver(31339));
+      hd.setMaster(master);
+    } catch (IOException ioe) {
+      System.err.println("Unable to set hd receiver:" + ioe);
+      return;
+    } catch (InvalidSenderException ise) {
+      System.err.println("Invalid Sender:" + ise);
+      return;
+    }
+
+    System.err.println("Reading test file " + args[0]);
+    StringBuffer sb = new StringBuffer();
+    s = null;
+    try {
+      BufferedReader tf_br = new BufferedReader(new FileReader(args[0]));
+      do {
+	s = tf_br.readLine();
+	if (s != null) {
+	  sb.append(s);
+	  sb.append("\n");
+	}
+      } while (s != null);
+    } catch (IOException ioe) {
+      System.err.println("Exception when reading " + args[0] + ":" + ioe);
+      return;
+    }
+    xml = sb.toString();
+    System.err.println("About to parse:\n" + xml+"\n.");
+
+    Notification n = KXNotification.ProbeKXNotification("Biff-Probe", 666, xml);
+/*
+    n.putAttribute("Source", "EventDistiller");
+    n.putAttribute("Type", "DataToMetaParser");
+    n.putAttribute("SmartEvent", xml);
+*/
+    try {
+      hd.publish(n);
+    } catch (SienaException se) {
+      System.err.println("Siena exception on publish:" + se);
+      return;
+    }
+    hd.shutdown();
+  }
+}
diff --git a/SmartEventSchema.xsd b/SmartEventSchema.xsd
new file mode 100644
index 0000000..6ac552b
--- /dev/null
+++ b/SmartEventSchema.xsd
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema>
+    <annotation>
+      <documentation>
+        Preliminary SmartEvent Schema
+	Copyright 2001 Trustees of Columbia University
+	in the City of New York.  All rights reserved.
+      </documentation>
+    </annotation>
+
+  <!-- This type is used to identify a node participating in the system.
+       it's used for both source and target nodes -->
+  <element name="smartevent">
+    <complexType>
+      <sequence>
+        <!-- Basic metadata for an event.  The combination of source and tag
+	     should uniquely identify an event. -->
+	<element name="metadata">
+	  <!-- anonymous type -->
+	  <complexType>
+	    <sequence>
+	      <!-- sequential identifier -->
+	      <element name="tag" type="positiveInteger"/>
+	      <element name="source">
+	        <complexType>
+		  <sequence>
+		    <element name="ipAddr" type="string"/>
+		    <element name="ipPort" type="integer"/>
+		    <!-- Optional label: name, instance-id, etc. -->
+		    <element name="identifier" type="string" minOccurs="0"/>
+		  </sequence>
+	        </complexType>
+	      </element>
+
+	      <element name="dest" minOccurs="0">
+	        <complexType>
+		  <sequence>
+		    <element name="ipAddr" type="string"/>
+		    <element name="ipPort" type="integer"/>
+		    <!-- Optional label: name, instance-id, etc. -->
+		    <element name="identifier" type="string" minOccurs="0"/>
+		  </sequence>
+	        </complexType>
+	      </element>
+
+	      <!-- UTC timestamp -->
+	      <element name="time" type="timeInstant"/>
+	      <!-- tells KX system not to attempt to parse/distill XML -->
+	      <element name="kxOpaque" type="boolean" minOccurs="0"/>
+	      <!-- optional identifying info, e.g. probe name -->
+	      <element name="label" type="string" minOccurs="0"/>
+	      <!-- miscellaneous comment, passed through by the packager -->
+	      <element name="comment" type="string" minOccurs="0"/>
+
+	    </sequence>
+	  </complexType>
+	</element>
+
+	<!--  Indication that this is the position where
+	      schema fragments for the payload should be
+	      inserted.  See PSL FleXML documentation regarding
+              the semantics of FleXML hints.-->
+        <?FleXML type="schemaSubst"?>
+
+      </sequence>
+    </complexType>
+  </element>
+
+</schema>
diff --git a/SubParser.java b/SubParser.java
index fc15778..5a36f4f 100644
--- a/SubParser.java
+++ b/SubParser.java
@@ -1,226 +1,229 @@
-package psl.metaparser;
-
-import org.xml.sax.*;
-import org.xml.sax.helpers.*;
-import org.apache.xerces.parsers.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-/** Validating subordinate parser thread.
-  *
+package psl.metaparser;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import org.apache.xerces.parsers.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/** Validating subordinate parser thread.
+  *
   * $Log$
-  * Revision 2.4  2001-01-30 10:16:55  png3
-  * Almost working...
-  *
-  * Revision 2.3  2001/01/29 04:04:48  png3
-  * Added package psl.metaparser statements.  Can you say "Oops?"
-  *
-  * Revision 2.2  2001/01/28 17:52:17  png3
-  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
-  *
-  */
-public class SubParser extends DefaultHandler implements Runnable {
-
-  Locator loc;
-  int depth = 0;
-  static final String spc = "  ";
-  PipedReader pr = null;
-  // XMLSchema schema = null;
-  String inst = "";
-  // parent
-  Validator v = null;
-
-  SubParser(PipedWriter pw, String inst,
-  	Validator v) throws IOException {
-
-    final String fn = inst+"_SP_ctor: ";
-
-    this.inst = inst;
-    // schema = s;
-    this.v = v;
-    try {
-      pr = new PipedReader(pw);
-    } catch (IOException ioe) {
-      v.prLog(fn+"Error creating PipedReader:" + ioe);
-      throw ioe;
-    }
-  }
-
-  public void printMsg(String m) {
-    for (int i = 0; i < depth; ++i) {
-      System.err.print(spc);
-    }
-    System.err.println(inst + ": " + m);
-  }
-
-  public void run() {
-
-    final String fn = inst+"_SP_run: ";
-
-    SAXParser p = new SAXParser();
-    try {
-      p.setFeature("http://xml.org/sax/features/validation", true);
-      p.setFeature("http://xml.org/sax/features/namespaces", true);
-      p.setFeature("http://apache.org/xml/features/validation/schema", true);
-    } catch (SAXNotSupportedException snse) {
-      v.prLog(fn+"Feature not supported:" + snse.getMessage());
-      return;
-     } catch (SAXNotRecognizedException snre) {
-      v.prLog(fn+"Exception setting feature:" + snre.getMessage());
-      return;
-    }
-    p.setContentHandler(this);
-    p.setErrorHandler(this);
-
-    v.prDbg(fn+"starting to parse");
-    try {
-      p.parse(new InputSource(pr));
-    } catch (Exception e) {
-      v.prLog(fn+"Exception during parsing:" + e.getMessage());
-      return;
-    }
-    v.prDbg(fn+"Done parsing");
-  }
-
-  public void setDocumentLocator(Locator loc) {
-
-    final String fn = inst+"_SP_setDocLoc: ";
-
-    v.prDbg(fn+"SetDocumentLocator:");
-    this.loc = loc;
-  }
-
-  public void startDocument() {
-
-    final String fn = inst+"_SP_startDoc: ";
-
-    v.prDbg(fn+"StartDocument");
-  }
-
-  public void endDocument() throws SAXException {
-
-    final String fn = inst+"_SP_endDoc: ";
-
-    v.prDbg(fn+"EndDocument");
-  }
-
-  public void startElement(
-          String namespaceURI, String localName, String qName, Attributes atts)
-            throws SAXException {
-
-    final String fn = inst+"_SP_startElm: ";
-
-    v.prDbg(fn+"StartElement (" + MPUtil.printLoc(loc) + "):" + qName);
-    for (int i = 0; i < atts.getLength(); i++) {
-      String aname = atts.getQName(i);
-      String type  = atts.getType(i);
-      String value = atts.getValue(i);
-
-      v.prDbg(fn+"   " + aname + "(" + type + ")" + "=" + value);
-    }
-    ++depth;
-  }
-
-  public void endElement(String namespaceURI, String localName, String qName)
-  	throws SAXException {
-
-    final String fn = inst+"_SP_endElm: ";
-
-    --depth;
-    v.prDbg(fn+"EndElement:" + qName);
-  }
-
-  public void startPrefixMapping(String prefix, String uri) throws SAXException {
-
-    final String fn = inst+"_SP_startPM: ";
-
-    v.prDbg(fn+"startPrefixMapping: prefix:" + prefix);
-    v.prDbg(fn+"\turi:" + uri);
-  }
-
-  public void endPrefixMapping(String prefix) throws SAXException {
-
-    final String fn = inst+"_SP_endPM: ";
-
-    v.prDbg(fn+"EndPrefixMapping:" + prefix);
-  }
-
-  public void skippedEntity(String entity) throws SAXException {
-
-    final String fn = inst+"_SP_skippedEntity: ";
-
-    v.prDbg(fn+"skippedEntity:" + entity);
-  }
-
-  public void characters(char[] cbuf, int start, int len) {
-
-    final String fn = inst+"_SP_CData: ";
-
-    v.prDbg(fn+"Characters:" + new String(cbuf, start, len));
-  }
-
-  public void ignorableWhitespace(char[] cbuf, int start, int len) {
-
-    final String fn = inst+"_SP_WS: ";
-
-    v.prDbg(fn+"IgnorableWhiteSpace");
-  }
-
-  public void processingInstruction(String target, String data)
-          throws SAXException {
-
-    final String fn = inst+"_SP_PI: ";
-
-    v.prDbg(fn+"ProcessingInstruction:" + target + " " + data);
-    if (target.toLowerCase().equals("flexml")) {
-      ++depth;
-      v.prDbg(fn+"Found FleXML tag!");
-      ++depth;
-      StringTokenizer st = new StringTokenizer(data);
-      while (st.hasMoreTokens()) {
-        String piAttr = st.nextToken();
-        StringTokenizer st2 = new StringTokenizer(piAttr, "= \"");
-	if (st2.countTokens() != 2) {
-	  v.prDbg(fn+"Malformed PI Attribute: " + piAttr);
-	} else {
-	  String piaName = st2.nextToken();
-	  String piaVal = st2.nextToken();
-	  printMsg(piaName + " = " + piaVal);
-	  if (piaName.toLowerCase().equals("type")) {
-	    if (piaVal.toLowerCase().equals("schemafrag")) {
-	      ++depth;
-	      v.prDbg(fn+"*** found schemaFrag PI ***");
-	      --depth;
-	    }
-	  }
-	}
-      }
-      depth -= 2;
-    }
-
-  }
-
-  public void warning(SAXParseException e) throws SAXException {
-
-    final String fn = inst+"_SP_warning: ";
-
-    v.prLog(fn+"Warning:" + e.getMessage());
-  }
-
-  public void error(SAXParseException e) throws SAXException {
-
-    final String fn = inst+"_SP_error: ";
-
-    throw new SAXException(e.getMessage());
-  }
-
-  public void fatalError(SAXParseException e) throws SAXException {
-
-    final String fn = inst+"_SP_fatalError: ";
-
-    v.prLog(fn+"Fatal error");
-    throw new SAXException(e.getMessage());
-  }
-
-}
+  * Revision 2.5  2001-02-05 06:35:16  png3
+  * Post California version
+  *
+  * Revision 2.4  2001/01/30 10:16:55  png3
+  * Almost working...
+  *
+  * Revision 2.3  2001/01/29 04:04:48  png3
+  * Added package psl.metaparser statements.  Can you say "Oops?"
+  *
+  * Revision 2.2  2001/01/28 17:52:17  png3
+  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
+  *
+  */
+public class SubParser extends DefaultHandler implements Runnable {
+
+  Locator loc;
+  int depth = 0;
+  static final String spc = "  ";
+  PipedReader pr = null;
+  // XMLSchema schema = null;
+  String inst = "";
+  // parent
+  Validator v = null;
+
+  SubParser(PipedWriter pw, String inst,
+  	Validator v) throws IOException {
+
+    final String fn = inst+"_SP_ctor: ";
+
+    this.inst = inst;
+    // schema = s;
+    this.v = v;
+    try {
+      pr = new PipedReader(pw);
+    } catch (IOException ioe) {
+      v.prLog(fn+"Error creating PipedReader:" + ioe);
+      throw ioe;
+    }
+  }
+
+  public void printMsg(String m) {
+    for (int i = 0; i < depth; ++i) {
+      System.err.print(spc);
+    }
+    System.err.println(inst + ": " + m);
+  }
+
+  public void run() {
+
+    final String fn = inst+"_SP_run: ";
+
+    SAXParser p = new SAXParser();
+    try {
+      p.setFeature("http://xml.org/sax/features/validation", true);
+      p.setFeature("http://xml.org/sax/features/namespaces", true);
+      p.setFeature("http://apache.org/xml/features/validation/schema", true);
+    } catch (SAXNotSupportedException snse) {
+      v.prLog(fn+"Feature not supported:" + snse.getMessage());
+      return;
+     } catch (SAXNotRecognizedException snre) {
+      v.prLog(fn+"Exception setting feature:" + snre.getMessage());
+      return;
+    }
+    p.setContentHandler(this);
+    p.setErrorHandler(this);
+
+    v.prDbg(fn+"starting to parse");
+    try {
+      p.parse(new InputSource(pr));
+    } catch (Exception e) {
+      v.prLog(fn+"Exception during parsing:" + e.getMessage());
+      return;
+    }
+    v.prDbg(fn+"Done parsing");
+  }
+
+  public void setDocumentLocator(Locator loc) {
+
+    final String fn = inst+"_SP_setDocLoc: ";
+
+    v.prDbg(fn+"SetDocumentLocator:");
+    this.loc = loc;
+  }
+
+  public void startDocument() {
+
+    final String fn = inst+"_SP_startDoc: ";
+
+    v.prDbg(fn+"StartDocument");
+  }
+
+  public void endDocument() throws SAXException {
+
+    final String fn = inst+"_SP_endDoc: ";
+
+    v.prDbg(fn+"EndDocument");
+  }
+
+  public void startElement(
+          String namespaceURI, String localName, String qName, Attributes atts)
+            throws SAXException {
+
+    final String fn = inst+"_SP_startElm: ";
+
+    v.prDbg(fn+"StartElement (" + MPUtil.printLoc(loc) + "):" + qName);
+    for (int i = 0; i < atts.getLength(); i++) {
+      String aname = atts.getQName(i);
+      String type  = atts.getType(i);
+      String value = atts.getValue(i);
+
+      v.prDbg(fn+"   " + aname + "(" + type + ")" + "=" + value);
+    }
+    ++depth;
+  }
+
+  public void endElement(String namespaceURI, String localName, String qName)
+  	throws SAXException {
+
+    final String fn = inst+"_SP_endElm: ";
+
+    --depth;
+    v.prDbg(fn+"EndElement:" + qName);
+  }
+
+  public void startPrefixMapping(String prefix, String uri) throws SAXException {
+
+    final String fn = inst+"_SP_startPM: ";
+
+    v.prDbg(fn+"startPrefixMapping: prefix:" + prefix);
+    v.prDbg(fn+"\turi:" + uri);
+  }
+
+  public void endPrefixMapping(String prefix) throws SAXException {
+
+    final String fn = inst+"_SP_endPM: ";
+
+    v.prDbg(fn+"EndPrefixMapping:" + prefix);
+  }
+
+  public void skippedEntity(String entity) throws SAXException {
+
+    final String fn = inst+"_SP_skippedEntity: ";
+
+    v.prDbg(fn+"skippedEntity:" + entity);
+  }
+
+  public void characters(char[] cbuf, int start, int len) {
+
+    final String fn = inst+"_SP_CData: ";
+
+    v.prDbg(fn+"Characters:" + new String(cbuf, start, len));
+  }
+
+  public void ignorableWhitespace(char[] cbuf, int start, int len) {
+
+    final String fn = inst+"_SP_WS: ";
+
+    v.prDbg(fn+"IgnorableWhiteSpace");
+  }
+
+  public void processingInstruction(String target, String data)
+          throws SAXException {
+
+    final String fn = inst+"_SP_PI: ";
+
+    v.prDbg(fn+"ProcessingInstruction:" + target + " " + data);
+    if (target.toLowerCase().equals("flexml")) {
+      ++depth;
+      v.prDbg(fn+"Found FleXML tag!");
+      ++depth;
+      StringTokenizer st = new StringTokenizer(data);
+      while (st.hasMoreTokens()) {
+        String piAttr = st.nextToken();
+        StringTokenizer st2 = new StringTokenizer(piAttr, "= \"");
+	if (st2.countTokens() != 2) {
+	  v.prDbg(fn+"Malformed PI Attribute: " + piAttr);
+	} else {
+	  String piaName = st2.nextToken();
+	  String piaVal = st2.nextToken();
+	  printMsg(piaName + " = " + piaVal);
+	  if (piaName.toLowerCase().equals("type")) {
+	    if (piaVal.toLowerCase().equals("schemafrag")) {
+	      ++depth;
+	      v.prDbg(fn+"*** found schemaFrag PI ***");
+	      --depth;
+	    }
+	  }
+	}
+      }
+      depth -= 2;
+    }
+
+  }
+
+  public void warning(SAXParseException e) throws SAXException {
+
+    final String fn = inst+"_SP_warning: ";
+
+    v.prLog(fn+"Warning:" + e.getMessage());
+  }
+
+  public void error(SAXParseException e) throws SAXException {
+
+    final String fn = inst+"_SP_error: ";
+
+    throw new SAXException(e.getMessage());
+  }
+
+  public void fatalError(SAXParseException e) throws SAXException {
+
+    final String fn = inst+"_SP_fatalError: ";
+
+    v.prLog(fn+"Fatal error");
+    throw new SAXException(e.getMessage());
+  }
+
+}
diff --git a/Validator.java b/Validator.java
index a1f2cfa..14f7f33 100644
--- a/Validator.java
+++ b/Validator.java
@@ -1,190 +1,193 @@
-package psl.metaparser;
-
-import java.io.*;
-import org.xml.sax.*;
-
-/** Input controller.  Selectively feeds data to a SubParser.
-  *
+package psl.metaparser;
+
+import java.io.*;
+import org.xml.sax.*;
+
+/** Input controller.  Selectively feeds data to a SubParser.
+  *
   * $Log$
-  * Revision 2.3  2001-01-30 10:16:55  png3
-  * Almost working...
-  *
-  * Revision 2.2  2001/01/29 04:04:48  png3
-  * Added package psl.metaparser statements.  Can you say "Oops?"
-  *
-  * Revision 2.1  2001/01/28 17:52:17  png3
-  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
-  *
-  */
-class Validator {
-
-  BufferedReader br = null;
-  PipedWriter pos = null;
-  int curLine = 0;
-  int curCol = 0;
-  String buf = null;
-  SubParser sp = null;
-  String inst = null;
-  boolean debug;
-  PrintWriter log = null;
-  PrintWriter dbg = null;
-
-  // used for SubParsers: have we reached the "outermost" tag yet?
-  int depth;
-  String element;
-
-  synchronized void setDepth(int d) {depth = d;}
-  synchronized int getDepth() {return depth;}
-  synchronized void setElement(String e) {element = e;}
-  synchronized String getElement() {return element;}
-
-  synchronized void prLog(String m) {log.println(m);}
-  synchronized void prDbg(String m) {if (debug) dbg.println(m);}
-
-  Validator(String s, PipedWriter o, String inst,
-  	boolean debug)
-    throws IOException {
-
-    final String fn = inst+"_ctor_1: ";
-
-    try {
-      br = new BufferedReader(new StringReader(s));
-      sp = new SubParser(o, inst, this);
-    } catch (IOException ioe) {
-      System.err.println(fn + "I/O Exception:" + ioe);
-      throw ioe;
-    }
-
-    this.debug = debug;
-    try {
-      String f1 = inst+".log";
-      String f2 = inst+".dbg";
-      log = new PrintWriter(new FileWriter(f1), true);
-      log.println("Log started " + MPUtil.timestamp());
-      if (debug) {
-	dbg = new PrintWriter(new FileWriter(f2), true);
-	dbg.println("Debug Log started " + MPUtil.timestamp());
-      }
-    } catch (IOException ioe) {
-      System.err.println(fn + "unable to open log files");
-      System.err.println(ioe);
-      return;
-    }
-
-    this.inst = inst;
-    pos = o;
-    curLine = 0;
-    curCol = 1;
-
-    prDbg(fn+"Starting subParser");
-    Thread t = new Thread(sp);
-    t.start();
-  }
-
-  Validator(String s, PipedWriter o, String inst,
-  	boolean debug, Locator l) throws IOException {
-
-    this(s, o, inst, debug);
-
-    final String fn = inst+"_ctor_2: ";
-
-    skip(l);
-
-    prDbg(fn+"Validator buffer:" + buf);
-    prDbg(fn+"Validator(" + curCol + "):"
-    	+ buf.substring(curCol-1));
-
-  }
-
-  void skip(Locator l) throws IOException {
-
-    final String fn = inst+"_skip: ";
-
-    prDbg(fn+"skip(" + MPUtil.printLoc(l) + ")");
-    int tgtLine = l.getLineNumber();
-    try {
-      while (curLine < tgtLine) {
-        buf = br.readLine();
-	curLine++;
-      }
-    } catch (IOException ioe) {
-      prLog(fn+"Error in skip:"+ioe);
-      throw ioe;
-    }
-    curCol = l.getColumnNumber();
-  }
-
-
-  void send(String s) throws IOException {
-
-    final String fn = inst+"_send: ";
-
-    try {
-      prDbg(fn+"sending:" + s);
-      pos.write(s);
-    } catch (IOException ioe) {
-      prLog(fn+"Error in send:"+ioe);
-      throw ioe;
-    }
-  }
-
-  void flush(Locator l) throws IOException {
-
-    final String fn = inst+"_flush: ";
-
-    int tgtLine = l.getLineNumber();
-    int tgtCol = l.getColumnNumber();
-    // prDbg(fn+"req to flush " + tgtLine +":"+tgtCol);
-    // prDbg(fn+"cur= " + curLine +":"+curCol);
-
-    try {
-      if (tgtLine > curLine) {
-        if (buf != null) {
-	  String s = buf.substring(curCol-1);
-	  prDbg(fn+"flushing:" + s);
-	  pos.write(s);
-	}
-	curCol = 1;
-	while (tgtLine > curLine+1) {
-	  buf = br.readLine();
-	  prDbg(fn+"flushing:" + buf);
-	  pos.write(buf);
-	  curLine++;
-	}
-	buf = br.readLine();
-	curLine++;
-      }
-      // prDbg(fn+"cur= " + curLine +":"+curCol);
-      // prDbg(fn+"buf=" + buf);
-      if (buf != null) {
-        String s =buf.substring(curCol-1, tgtCol-1);
-	prDbg(fn+"flushing:" + s);
-	pos.write(s);
-      }
-      curCol = tgtCol;
-    } catch (IOException ioe) {
-      prLog(fn+"Error in flush:"+ioe);
-      throw ioe;
-    }
-  }
-
-  void close(boolean flush) throws IOException {
-
-    final String fn = inst+"_close: ";
-
-    prDbg(fn+"closing(" + flush + ")");
-    try {
-      if (flush) {
-	String s = buf.substring(curCol-1);
-	prDbg(fn+"flushing:" + s);
-	pos.write(s);
-      }
-      br.close();
-      pos.close();
-    } catch (IOException ioe) {
-      prLog(fn+"Error in close:"+ioe);
-      throw ioe;
-    }
-  }
-
-}
+  * Revision 2.4  2001-02-05 06:35:16  png3
+  * Post California version
+  *
+  * Revision 2.3  2001/01/30 10:16:55  png3
+  * Almost working...
+  *
+  * Revision 2.2  2001/01/29 04:04:48  png3
+  * Added package psl.metaparser statements.  Can you say "Oops?"
+  *
+  * Revision 2.1  2001/01/28 17:52:17  png3
+  * New version of Metaparser: fully multithreaded.  PrintWriter logs.
+  *
+  */
+class Validator {
+
+  BufferedReader br = null;
+  PipedWriter pos = null;
+  int curLine = 0;
+  int curCol = 0;
+  String buf = null;
+  SubParser sp = null;
+  String inst = null;
+  boolean debug;
+  PrintWriter log = null;
+  PrintWriter dbg = null;
+
+  // used for SubParsers: have we reached the "outermost" tag yet?
+  int depth;
+  String element;
+
+  synchronized void setDepth(int d) {depth = d;}
+  synchronized int getDepth() {return depth;}
+  synchronized void setElement(String e) {element = e;}
+  synchronized String getElement() {return element;}
+
+  synchronized void prLog(String m) {log.println(m);}
+  synchronized void prDbg(String m) {if (debug) dbg.println(m);}
+
+  Validator(String s, PipedWriter o, String inst,
+  	boolean debug)
+    throws IOException {
+
+    final String fn = inst+"_ctor_1: ";
+
+    try {
+      br = new BufferedReader(new StringReader(s));
+      sp = new SubParser(o, inst, this);
+    } catch (IOException ioe) {
+      System.err.println(fn + "I/O Exception:" + ioe);
+      throw ioe;
+    }
+
+    this.debug = debug;
+    try {
+      String f1 = inst+".log";
+      String f2 = inst+".dbg";
+      log = new PrintWriter(new FileWriter(f1), true);
+      log.println("Log started " + MPUtil.timestamp());
+      if (debug) {
+	dbg = new PrintWriter(new FileWriter(f2), true);
+	dbg.println("Debug Log started " + MPUtil.timestamp());
+      }
+    } catch (IOException ioe) {
+      System.err.println(fn + "unable to open log files");
+      System.err.println(ioe);
+      return;
+    }
+
+    this.inst = inst;
+    pos = o;
+    curLine = 0;
+    curCol = 1;
+
+    prDbg(fn+"Starting subParser");
+    Thread t = new Thread(sp);
+    t.start();
+  }
+
+  Validator(String s, PipedWriter o, String inst,
+  	boolean debug, Locator l) throws IOException {
+
+    this(s, o, inst, debug);
+
+    final String fn = inst+"_ctor_2: ";
+
+    skip(l);
+
+    prDbg(fn+"Validator buffer:" + buf);
+    prDbg(fn+"Validator(" + curCol + "):"
+    	+ buf.substring(curCol-1));
+
+  }
+
+  void skip(Locator l) throws IOException {
+
+    final String fn = inst+"_skip: ";
+
+    prDbg(fn+"skip(" + MPUtil.printLoc(l) + ")");
+    int tgtLine = l.getLineNumber();
+    try {
+      while (curLine < tgtLine) {
+        buf = br.readLine();
+	curLine++;
+      }
+    } catch (IOException ioe) {
+      prLog(fn+"Error in skip:"+ioe);
+      throw ioe;
+    }
+    curCol = l.getColumnNumber();
+  }
+
+
+  void send(String s) throws IOException {
+
+    final String fn = inst+"_send: ";
+
+    try {
+      prDbg(fn+"sending:" + s);
+      pos.write(s);
+    } catch (IOException ioe) {
+      prLog(fn+"Error in send:"+ioe);
+      throw ioe;
+    }
+  }
+
+  void flush(Locator l) throws IOException {
+
+    final String fn = inst+"_flush: ";
+
+    int tgtLine = l.getLineNumber();
+    int tgtCol = l.getColumnNumber();
+    // prDbg(fn+"req to flush " + tgtLine +":"+tgtCol);
+    // prDbg(fn+"cur= " + curLine +":"+curCol);
+
+    try {
+      if (tgtLine > curLine) {
+        if (buf != null) {
+	  String s = buf.substring(curCol-1);
+	  prDbg(fn+"flushing:" + s);
+	  pos.write(s);
+	}
+	curCol = 1;
+	while (tgtLine > curLine+1) {
+	  buf = br.readLine();
+	  prDbg(fn+"flushing:" + buf);
+	  pos.write(buf);
+	  curLine++;
+	}
+	buf = br.readLine();
+	curLine++;
+      }
+      // prDbg(fn+"cur= " + curLine +":"+curCol);
+      // prDbg(fn+"buf=" + buf);
+      if (buf != null) {
+        String s =buf.substring(curCol-1, tgtCol-1);
+	prDbg(fn+"flushing:" + s);
+	pos.write(s);
+      }
+      curCol = tgtCol;
+    } catch (IOException ioe) {
+      prLog(fn+"Error in flush:"+ioe);
+      throw ioe;
+    }
+  }
+
+  void close(boolean flush) throws IOException {
+
+    final String fn = inst+"_close: ";
+
+    prDbg(fn+"closing(" + flush + ")");
+    try {
+      if (flush) {
+	String s = buf.substring(curCol-1);
+	prDbg(fn+"flushing:" + s);
+	pos.write(s);
+      }
+      br.close();
+      pos.close();
+    } catch (IOException ioe) {
+      prLog(fn+"Error in close:"+ioe);
+      throw ioe;
+    }
+  }
+
+}
diff --git a/schema.xsd b/schema.xsd
new file mode 100644
index 0000000..c34aa0e
--- /dev/null
+++ b/schema.xsd
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><schema>  <?FleXML type="schemaFrag" name="sendmail/biff" version="1.0"?>    <annotation>      <documentation>        Schema fragment for data from sendmail/biff probes.	Copyright 2000 Trustees of Columbia University	in the City of New York.  All rights reserved.      </documentation>    </annotation>   <element name="smtp">    <complexType>      <sequence>        <element name="to" type="string"/>        <element name="from" type="string"/>        <element name="subject" type="string"/>        <element name="sent" type="timeInstant"/>        <element name="received" type="timeInstant" minOccurs="0"/>      </sequence>    </complexType>  </element>  <?FleXML type="/schemaFrag"?></schema>
\ No newline at end of file
diff --git a/spam_ex.xml b/spam_ex.xml
new file mode 100644
index 0000000..a4ab291
--- /dev/null
+++ b/spam_ex.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<smartevent
+	xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
+	xsi:noNamespaceSchemaLocation="SmartEventSchema.xsd"
+>
+  <metadata>
+    <tag>31415</tag>
+    <source>
+      <ipAddr>mail.cs.columbia.edu</ipAddr>
+      <ipPort>2500</ipPort>
+    </source>
+    <time>2001-01-20T21:45:00</time>
+  </metadata>
+  <?FleXML type="schemaFrag" name="sendmail/biff" version="1.0"?>
+  <smtp>
+    <to>jjp32@cs.columbia.edu</to>
+    <from>spammer@localhost.localdomain</from>
+    <subject>Make Money Fast</subject>
+    <sent>2000-11-20T19:00:00</sent>
+    <received>2000-11-20T19:02:00</received>
+  </smtp>
+</smartevent>