cleanup / abuse system fix / prepping for a release
[mir.git] / source / mir / producer / reader / ProducerConfigReader.java
index 8ad2acf..3b10689 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001, 2002  The Mir-coders group
+ * Copyright (C) 2001, 2002 The Mir-coders group
  *
  * This file is part of Mir.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with the com.oreilly.servlet library, any library
- * licensed under the Apache Software License, The Sun (tm) Java Advanced
- * Imaging library (JAI), The Sun JIMI library (or with modified versions of
- * the above that use the same license as the above), and distribute linked
- * combinations including the two.  You must obey the GNU General Public
- * License in all respects for all of the code used other than the above
- * mentioned libraries.  If you modify this file, you may extend this exception
- * to your version of the file, but you are not obligated to do so.  If you do
- * not wish to do so, delete this exception statement from your version.
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your version.
  */
-
 package  mir.producer.reader;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Stack;
-import java.util.Vector;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import mir.producer.CompositeProducerNode;
 import mir.producer.ProducerFactory;
 import mir.producer.ProducerNode;
 import mir.producer.SimpleProducerVerb;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.helpers.DefaultHandler;
+import mir.util.ExceptionRoutines;
+import mir.util.xml.XMLParserEngine;
+import mir.util.xml.XMLParserExc;
+import mir.util.xml.XMLParserFailure;
 
 public class ProducerConfigReader {
   private ProducerNodeBuilderLibrary builderLibrary;
@@ -66,229 +54,66 @@ public class ProducerConfigReader {
 
   public ProducerConfigReader() {
     super();
-  };
-
-  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
-    parseFile(aFileName, aBuilderLibrary, aProducerFactories, new Vector());
   }
 
-  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories, List aUsedFiles) throws ProducerConfigFailure {
+  public void parse(Reader aReader, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
     try {
       builderLibrary = aBuilderLibrary;
       scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
 
-      SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-
-      parserFactory.setNamespaceAware(false);
-      parserFactory.setValidating(true);
+      XMLParserEngine.getInstance().parse("", aReader, new RootSectionHandler(aProducerFactories));
 
-      ProducerConfigHandler handler = new ProducerConfigHandler(parserFactory, aProducerFactories, aUsedFiles);
-
-      handler.includeFile(aFileName);
     }
     catch (Throwable e) {
-      if (e instanceof SAXParseException && ((SAXParseException) e).getException() instanceof ProducerConfigFailure) {
-        throw (ProducerConfigFailure) ((SAXParseException) e).getException();
-      }
-      else {
-        throw new ProducerConfigFailure( e );
-      }
-    }
-  }
-
-  private class ProducerConfigHandler extends DefaultHandler {
-    private Locator locator;
-    private Stack includeFileStack;
-    private SAXParserFactory parserFactory;
-    private SectionsManager manager;
-    private List usedFiles;
-    private InputSource inputSource;
-
-    public ProducerConfigHandler(SAXParserFactory aParserFactory, List aProducers, List aUsedFiles) {
-      super();
-
-      includeFileStack=new Stack();
-      parserFactory=aParserFactory;
-      includeFileStack = new Stack();
-      manager = new SectionsManager();
-      usedFiles = aUsedFiles;
-
-      manager.pushHandler(new RootSectionHandler(aProducers));
-   }
-
-    public String getLocatorDescription(Locator aLocator) {
-      return aLocator.getPublicId()+" ("+aLocator.getLineNumber()+")";
-    }
+      Throwable root = ExceptionRoutines.traceCauseException(e);
 
-    public void setDocumentLocator(Locator aLocator) {
-      locator=aLocator;
-    }
-
-    private void includeFile(String aFileName) throws ProducerConfigExc, ProducerConfigFailure, SAXParseException, SAXException {
-      File file;
-      SAXParser parser;
-
-      try {
-        if (!includeFileStack.empty())
-          file = new File(new File((String) includeFileStack.peek()).getParent(), aFileName);
-        else
-          file = new File(aFileName);
-
-        System.err.println("about to include "+file.getCanonicalPath());
-
-        if (includeFileStack.contains(file.getCanonicalPath())) {
-          throw new ProducerConfigExc("recursive inclusion of file "+file.getCanonicalPath());
-        }
-
-        usedFiles.add(file);
-
-        parser=parserFactory.newSAXParser();
-
-        inputSource = new InputSource(new FileInputStream(file));
-        inputSource.setPublicId(file.getCanonicalPath());
-
-        includeFileStack.push(file.getCanonicalPath());
-        try {
-          parser.parse(inputSource, this);
-        }
-        finally {
-          includeFileStack.pop();
-        }
-      }
-      catch (ParserConfigurationException e) {
-        throw new ProducerConfigExc("Internal exception while including \""+aFileName+"\": "+e.getMessage());
-      }
-      catch (SAXParseException e) {
-        throw e;
-      }
-      catch (ProducerConfigFailure e) {
-        throw e;
-      }
-      catch (FileNotFoundException e) {
-        throw new ProducerConfigExc("Include file \""+aFileName+"\" not found: "+e.getMessage());
-      }
-      catch (IOException e) {
-        throw new ProducerConfigExc("unable to open include file \""+aFileName+"\": "+e.getMessage());
-      }
-    }
-
-    public void startElement(String aUri, String aTag, String aQualifiedName, Attributes anAttributes) throws SAXException {
-      Map attributesMap;
-      int i;
-
-      try {
-        if (aQualifiedName.equals("include")) {
-          String fileName=anAttributes.getValue("file");
-
-          if (fileName==null) {
-            throw new ProducerConfigExc("include has no file attribute");
-          }
-
-          includeFile(fileName);
-        }
-        else {
-          attributesMap = new HashMap();
-          for (i=0; i<anAttributes.getLength(); i++)
-            attributesMap.put(anAttributes.getQName(i), anAttributes.getValue(i));
-
-          manager.pushHandler( manager.currentHandler().startElement(aQualifiedName, attributesMap) );
-        }
-      }
-      catch (ProducerConfigExc e) {
-        throw new SAXParseException(e.getMessage(), locator, new ProducerConfigExc("Config error at ["+getLocatorDescription(locator)+"]: "+e.getMessage()));
-      }
-      catch (Exception e) {
-        throw new SAXException(e);
-      }
-    }
-
-    public void endElement(String aUri, String aTag, String aQualifiedName) throws SAXException {
-      try
-      {
-        if (!aQualifiedName.equals("include")) {
-          SectionHandler handler = manager.popHandler();
-
-          handler.finishSection();
-
-          if (!manager.isEmpty()) {
-            manager.currentHandler().endElement(handler);
-          }
-        }
-      }
-      catch (ProducerConfigExc e) {
-        throw new SAXParseException(e.getMessage(), locator, new ProducerConfigExc("Config error at ["+getLocatorDescription(locator)+"]: "+e.getMessage()));
-      }
-      catch (Exception e) {
-        throw new SAXException(e);
-      }
-    }
-
-    public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXParseException {
-      String text = new String(aBuffer, aStart, anEnd).trim();
-      if ( text.length() > 0) {
-        throw new SAXParseException("Text not allowed", locator, new ProducerConfigExc("Config error at ["+getLocatorDescription(locator)+"]: Text not allowed"));
+      if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
+        XMLParserExc f = (XMLParserExc) root;
+        throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
       }
+      throw new ProducerConfigFailure(root);
     }
-
   }
-  public class SectionsManager {
-    Stack handlerStack;
-
-    public SectionsManager() {
-      handlerStack = new Stack();
-    }
-
-    public void pushHandler(SectionHandler aSectionHandler) {
-      handlerStack.push(aSectionHandler);
-    }
-
-    public SectionHandler popHandler() {
-      return (SectionHandler) handlerStack.pop();
-    }
+  public void parse(File aFile, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
+    try {
+      builderLibrary = aBuilderLibrary;
+      scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
 
-    public SectionHandler currentHandler() {
-      return (SectionHandler) handlerStack.peek();
-    }
+      XMLParserEngine.getInstance().parse("", aFile, new RootSectionHandler(aProducerFactories));
 
-    public boolean isEmpty() {
-      return handlerStack.isEmpty();
     }
-  }
-
-  public abstract class SectionHandler {
-    public abstract SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc;
-
-    public abstract void endElement(SectionHandler aHandler) throws ProducerConfigExc;
-//    {
-//    }
+    catch (Throwable e) {
+      Throwable root = ExceptionRoutines.traceCauseException(e);
 
-    public void finishSection() throws ProducerConfigExc {
+      if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
+        XMLParserExc f = (XMLParserExc) root;
+        throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
+      }
+      throw new ProducerConfigFailure(root);
     }
   }
 
-  public class RootSectionHandler extends SectionHandler {
+  public class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private List producers;
 
     public RootSectionHandler(List aProducers) {
       producers = aProducers;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       if (aTag.equals("producers")) {
         return new ProducersSectionHandler(producers);
       }
-      else
-        throw new ProducerConfigExc ("Tag 'producers' expected, tag '"+aTag+"' found");
+                       throw new XMLParserExc("Tag 'producers' expected, tag '"+aTag+"' found");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(mir.util.xml.SectionHandler aHandler) {
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() {
     }
   }
 
-
   private final static String   PRODUCER_NAME_ATTRIBUTE = "name";
   private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
   private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
@@ -297,7 +122,7 @@ public class ProducerConfigReader {
   private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
   private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = {  };
 
-  public class ProducersSectionHandler extends SectionHandler {
+  public class ProducersSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private List producers;
     private Set producerNames;
     private String name;
@@ -307,39 +132,39 @@ public class ProducerConfigReader {
       producerNames = new HashSet();
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       if (aTag.equals("producer")) {
-        ReaderTool.checkAttributes(anAttributes, PRODUCER_REQUIRED_ATTRIBUTES, PRODUCER_OPTIONAL_ATTRIBUTES);
+        mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
+                                      PRODUCER_REQUIRED_ATTRIBUTES,
+                                      PRODUCER_OPTIONAL_ATTRIBUTES);
 
         name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
-        ReaderTool.checkValidIdentifier( name );
+        mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
 
         if (producerNames.contains(name))
-          throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
+          throw new XMLParserExc("Duplicate producer name: '" +
+                                           name + "'");
 
         name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
 
         return new ProducerSectionHandler(name);
       }
       else if (aTag.equals("nodedefinition")) {
-        ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_REQUIRED_ATTRIBUTES, NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
+        mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
+                                      NODE_DEFINITION_REQUIRED_ATTRIBUTES,
+                                      NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
 
         name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
-        ReaderTool.checkValidIdentifier( name );
-
-//        if (producers.containsKey(name))
-//          throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
+        mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
 
         name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
 
         return new NodeDefinitionSectionHandler(name);
       }
-
-      throw new ProducerConfigExc("Unexpected tag: "+aTag );
+      throw new XMLParserExc("Unexpected tag: " + aTag);
     }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
+    public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
       if (aHandler instanceof ProducerSectionHandler) {
         producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());
         producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());
@@ -349,14 +174,14 @@ public class ProducerConfigReader {
             new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
                 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
       }
-      else throw new ProducerConfigExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
+      else throw new XMLParserExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() {
     }
   }
 
-  public class ProducerSectionHandler extends SectionHandler {
+  public class ProducerSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private ProducerFactory producerFactory;
     private String factoryName;
 
@@ -369,25 +194,23 @@ public class ProducerConfigReader {
       factoryName = aName;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes)  throws ProducerConfigExc {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       if (aTag.equals("verbs")) {
         if (verbs!=null)
-          throw new ProducerConfigExc("Verbs already processed");
+          throw new XMLParserExc("Verbs already processed");
         if (body!=null)
-          throw new ProducerConfigExc("Verbs should come before body");
-        else
-          return new ProducerVerbsSectionHandler();
+          throw new XMLParserExc("Verbs should come before body");
+                               return new ProducerVerbsSectionHandler();
       }
       else if (aTag.equals("body")) {
         if (body==null)
           return new ProducerNodeSectionHandler();
-        else
-          throw new ProducerConfigExc("Body already processed");
+                               throw new XMLParserExc("Body already processed");
       }
-      throw new ProducerConfigExc("Unexpected tag: '"+aTag+"'");
+      throw new XMLParserExc("Unexpected tag: '"+aTag+"'");
     }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
+    public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
       if (aHandler instanceof ProducerNodeSectionHandler) {
         body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
       }
@@ -397,15 +220,15 @@ public class ProducerConfigReader {
         verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
         defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
       }
-      else throw new ProducerConfigExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
+      else throw new XMLParserExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() throws XMLParserExc {
       if (verbs==null)
-        throw new ProducerConfigExc("No verbs defined");
+        throw new XMLParserExc("No verbs defined");
 
       if (body==null)
-        throw new ProducerConfigExc("No body defined");
+        throw new XMLParserExc("No body defined");
 
       producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
     }
@@ -421,7 +244,7 @@ public class ProducerConfigReader {
   private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
   private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
 
-  public class ProducerVerbsSectionHandler extends SectionHandler {
+  public class ProducerVerbsSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private Map verbNodes;
     private List verbs;
     private String defaultVerb;
@@ -430,38 +253,42 @@ public class ProducerConfigReader {
 
     public ProducerVerbsSectionHandler() {
       verbNodes = new HashMap();
-      verbs = new Vector();
+      verbs = new ArrayList();
       defaultVerb = null;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       if (aTag.equals("verb")) {
-        ReaderTool.checkAttributes(anAttributes, PRODUCER_VERB_REQUIRED_ATTRIBUTES, PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
-        currentVerb = (String) anAttributes.get( PRODUCER_VERB_NAME_ATTRIBUTE );
+        mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
+                                      PRODUCER_VERB_REQUIRED_ATTRIBUTES,
+                                      PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
+        currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);
 
-        ReaderTool.checkValidIdentifier( currentVerb );
+        mir.util.xml.XMLReaderTool.checkValidIdentifier(currentVerb);
 
         if (verbNodes.containsKey(currentVerb))
-          throw new ProducerConfigExc( "Duplicate definition of verb '" + currentVerb + "'" );
+          throw new XMLParserExc("Duplicate definition of verb '" +
+                                           currentVerb + "'");
 
         if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
-          if (defaultVerb!=null)
-            throw new ProducerConfigExc( "Default verb already declared" );
+          if (defaultVerb != null)
+            throw new XMLParserExc("Default verb already declared");
 
           defaultVerb = currentVerb;
         }
 
-        if (anAttributes.containsKey( PRODUCER_VERB_DESCRIPTION_ATTRIBUTE ))
-          currentVerbDescription = (String) anAttributes.get( PRODUCER_VERB_DESCRIPTION_ATTRIBUTE );
+        if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
+          currentVerbDescription = (String) anAttributes.get(
+              PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
         else
           currentVerbDescription = "";
 
         return new ProducerNodeSectionHandler();
       }
-      else throw new ProducerConfigExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
+                       throw new XMLParserExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(mir.util.xml.SectionHandler aHandler) {
       verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
       verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
     }
@@ -482,17 +309,19 @@ public class ProducerConfigReader {
     }
   }
 
-  public class EmptySectionHandler extends SectionHandler {
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      throw new ProducerConfigExc("No tags are allowed here");
+  public class EmptySectionHandler extends mir.util.xml.AbstractSectionHandler {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
+      throw new XMLParserExc("No tags are allowed here");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(mir.util.xml.SectionHandler aHandler) {
     }
 
+    public void finishSection() {
+    }
   }
 
-  public class MultiProducerNodeSectionHandler extends SectionHandler {
+  public class MultiProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private Map nodeParameters;
     private Set validNodeParameters;
     private String currentNodeParameter;
@@ -509,34 +338,37 @@ public class ProducerConfigReader {
       this("", new HashSet(), aValidNodeParameters);
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       if (!validNodeParameters.contains(aTag))
-        throw new ProducerConfigExc("Invalid node parameter: '" + aTag + "'");
+        throw new XMLParserExc("Invalid node parameter: '" + aTag + "'");
       else if (nodeParameters.containsKey(aTag))
-        throw new ProducerConfigExc("Node parameter: '" + aTag + "' already specified");
+        throw new XMLParserExc("Node parameter: '" + aTag + "' already specified");
       else if (anAttributes.size()>0)
-        throw new ProducerConfigExc("No parameters are allowed here");
+        throw new XMLParserExc("No parameters are allowed here");
 
       currentNodeParameter = aTag;
 
-      return new ProducerNodeSectionHandler(scriptedNodeName, validNodeParameters);
+      return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
     }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc  {
+    public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc  {
       if (aHandler instanceof ProducerNodeSectionHandler) {
         nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
       }
       else {
-        throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
+        throw new XMLParserExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
       }
     }
 
     public Map getNodeParameters() {
       return nodeParameters;
     }
+
+    public void finishSection() {
+    }
   }
 
-  public class ProducerNodeSectionHandler extends SectionHandler {
+  public class ProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private CompositeProducerNode producerNode;
     private ProducerNodeBuilder currentBuilder;
     private String scriptedNodeName;
@@ -552,79 +384,98 @@ public class ProducerConfigReader {
       this("", new HashSet());
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      if (allowedNodeParameterReferences.contains((aTag))) {
-        if (!anAttributes.isEmpty()) {
-          throw new ProducerConfigExc( "No attributes allowed" );
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
+      try {
+        if (allowedNodeParameterReferences.contains( (aTag))) {
+          if (!anAttributes.isEmpty()) {
+            throw new XMLParserExc("No attributes allowed");
+          }
+
+          currentBuilder = new DefaultProducerNodeBuilders.
+              ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
+          return new EmptySectionHandler();
         }
+        else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
+                 builderLibrary.hasBuilderForName( (aTag))) {
 
-        currentBuilder = new DefaultProducerNodeBuilders.ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
-//        producerNode.addSubNode(
-//        new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, aTag));
-        return new EmptySectionHandler();
-      }
-      else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) || builderLibrary.hasBuilderForName((aTag))) {
+          if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
+            currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
+          else
+            currentBuilder = builderLibrary.constructBuilder(aTag);
 
-        if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
-          currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
+          currentBuilder.setAttributes(anAttributes);
+          if (currentBuilder.getAvailableSubNodes().isEmpty()) {
+            return new EmptySectionHandler();
+          }
+          if (currentBuilder.getAvailableSubNodes().size() > 1)
+            return new MultiProducerNodeSectionHandler(scriptedNodeName,
+                allowedNodeParameterReferences,
+                currentBuilder.getAvailableSubNodes());
+          else if (currentBuilder.getAvailableSubNodes().size() < 1)
+            return new EmptySectionHandler();
+          else {
+            return new ProducerNodeSectionHandler(scriptedNodeName,
+                allowedNodeParameterReferences);
+          }
+        }
         else
-          currentBuilder = builderLibrary.constructBuilder(aTag);
+          throw new XMLParserExc("Unknown producer node tag: '" + aTag + "'");
+      }
+      catch (Throwable t) {
+        throw new XMLParserFailure(t);
+      }
+    }
 
-        currentBuilder.setAttributes(anAttributes);
-        if (currentBuilder.getAvailableSubNodes().isEmpty())  {
-          return new EmptySectionHandler();
+    public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc  {
+      try {
+        if (aHandler instanceof ProducerNodeSectionHandler) {
+          currentBuilder.setSubNode(
+                (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
+                ((ProducerNodeSectionHandler) aHandler).getProducerNode());
+        }
+        else if (aHandler instanceof MultiProducerNodeSectionHandler) {
+          Iterator i;
+          Map nodeParameters;
+          Map.Entry entry;
+
+          nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
+              getNodeParameters();
+          i = nodeParameters.entrySet().iterator();
+          while (i.hasNext()) {
+            entry = (Map.Entry) i.next();
+            currentBuilder.setSubNode( (String) entry.getKey(),
+                                      (ProducerNode) entry.getValue());
+          }
+        }
+        else if (aHandler instanceof EmptySectionHandler) {
+          // deliberately empty: nothing expected, so nothing to process
         }
-        if (currentBuilder.getAvailableSubNodes().size()>1)
-          return new MultiProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences, currentBuilder.getAvailableSubNodes());
-        else if (currentBuilder.getAvailableSubNodes().size()<1)
-          return new EmptySectionHandler();
         else {
-          return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
+          throw new XMLParserExc(
+              "Internal error: unknown section handler '" +
+              aHandler.getClass().getName() + "'");
         }
-      }
-      else
-        throw new ProducerConfigExc("Unknown producer node tag: '" + aTag + "'");
-    }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc  {
-      if (aHandler instanceof ProducerNodeSectionHandler) {
-        currentBuilder.setSubNode((String) (currentBuilder.getAvailableSubNodes().iterator().next()),
-                    ((ProducerNodeSectionHandler) aHandler).getProducerNode());
-      }
-      else if (aHandler instanceof MultiProducerNodeSectionHandler) {
-        Iterator i;
-        Map nodeParameters;
-        Map.Entry entry;
-
-        nodeParameters = ((MultiProducerNodeSectionHandler) aHandler).getNodeParameters();
-        i = nodeParameters.entrySet().iterator();
-        while (i.hasNext()) {
-          entry = (Map.Entry) i.next();
-          currentBuilder.setSubNode((String) entry.getKey(), (ProducerNode) entry.getValue());
-        }
-      }
-      else if (aHandler instanceof EmptySectionHandler) {
-        // deliberately empty: nothing expected, so nothing to process
+        producerNode.addSubNode(currentBuilder.constructNode());
+        currentBuilder = null;
       }
-      else {
-        throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
+      catch (Throwable t) {
+        throw new XMLParserFailure(t);
       }
-
-      producerNode.addSubNode(currentBuilder.constructNode());
-      currentBuilder = null;
     }
 
     public ProducerNode getProducerNode() {
       if (producerNode.getNrSubNodes()==1) {
         return producerNode.getSubNode(0);
       }
-      else {
-        return producerNode;
-      }
+                       return producerNode;
+    }
+
+    public void finishSection() {
     }
   }
 
-  public class NodeDefinitionSectionHandler extends SectionHandler {
+  public class NodeDefinitionSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private ScriptedProducerNodeDefinition nodeDefinition;
     private ProducerNode body;
     private Map stringParameters;
@@ -640,27 +491,30 @@ public class ProducerConfigReader {
       name = aName;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       if (aTag.equals("parameters")) {
         if (!anAttributes.isEmpty()) {
-          throw new ProducerConfigExc( "No attributes allowed for tag 'parameters'" );
+          throw new XMLParserExc( "No attributes allowed for tag 'parameters'" );
         }
         if (nodeParameters!=null) {
-          throw new ProducerConfigExc( "Parameters have already been declared" );
+          throw new XMLParserExc( "Parameters have already been declared" );
         }
         if (body!=null) {
-          throw new ProducerConfigExc( "Parameters should come before definition" );
+          throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
         }
 
         return new NodeDefinitionParametersSectionHandler();
       }
       else if (aTag.equals("definition")) {
+        if (nodeParameters==null)
+          throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'"  );
+
         return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
       }
-      else throw new ProducerConfigExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
+      else throw new XMLParserExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(mir.util.xml.SectionHandler aHandler) {
       if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
         stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
         integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
@@ -671,10 +525,10 @@ public class ProducerConfigReader {
       }
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() throws XMLParserExc {
       Iterator i;
       if (body == null)
-        throw new ProducerConfigExc( "Definition missing" );
+        throw new XMLParserExc( "Definition missing" );
 
       nodeDefinition = new ScriptedProducerNodeDefinition(name);
 
@@ -709,7 +563,7 @@ public class ProducerConfigReader {
   private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
   private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
 
-  public class NodeDefinitionParametersSectionHandler extends SectionHandler {
+  public class NodeDefinitionParametersSectionHandler extends mir.util.xml.AbstractSectionHandler {
     private Map nodeParameters;
     private Map stringParameters;
     private Map integerParameters;
@@ -720,33 +574,43 @@ public class ProducerConfigReader {
       integerParameters = new HashMap();
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
       String parameterName;
       String defaultValue;
 
       if (aTag.equals("node")) {
-        ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
-        parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
+        mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
+            NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
+            NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
+        parameterName = (String) anAttributes.get(
+            NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
 
         if (nodeParameters.containsKey(parameterName))
-          throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
+          throw new XMLParserExc("Duplicate parameter name: '" +
+                                           parameterName + "'");
 
-        ReaderTool.checkValidIdentifier( parameterName );
+        mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
 
         nodeParameters.put(parameterName, parameterName);
 
         return new EmptySectionHandler();
       }
       else if (aTag.equals("string") || aTag.equals("integer")) {
-        ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
-        parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
+        mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
+            NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
+            NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
+        parameterName = (String) anAttributes.get(
+            NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
 
-        if (stringParameters.containsKey(parameterName) || integerParameters.containsKey(parameterName))
-          throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
+        if (stringParameters.containsKey(parameterName) ||
+            integerParameters.containsKey(parameterName))
+          throw new XMLParserExc("Duplicate parameter name: '" +
+                                           parameterName + "'");
 
-        ReaderTool.checkValidIdentifier( parameterName );
+        mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
 
-        defaultValue = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE );
+        defaultValue = (String) anAttributes.get(
+            NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
 
         if (aTag.equals("string"))
           stringParameters.put(parameterName, defaultValue);
@@ -755,11 +619,12 @@ public class ProducerConfigReader {
 
         return new EmptySectionHandler();
       }
-      else throw new ProducerConfigExc("Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
-
+      else
+        throw new XMLParserExc(
+            "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(mir.util.xml.SectionHandler aHandler) {
     }
 
     public void finishSection() {