1 package mir.producer.reader;
5 import java.lang.System;
6 import org.xml.sax.helpers.DefaultHandler;
8 import javax.xml.parsers.ParserConfigurationException;
9 import javax.xml.parsers.SAXParser;
10 import javax.xml.parsers.SAXParserFactory;
13 import mir.config.exceptions.*;
14 import mir.producer.*;
16 //import mir.producer.exceptions.*;
17 import mir.misc.Location;
19 public class ProducerConfigReader {
20 private ProducerNodeBuilderLibrary builderLibrary;
21 private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;
23 public ProducerConfigReader() {
27 public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, Map aProducerFactories) throws ConfigFailure {
28 parseFile(aFileName, aBuilderLibrary, aProducerFactories, new Vector());
32 public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, Map aProducerFactories, List aUsedFiles) throws ConfigFailure {
34 builderLibrary = aBuilderLibrary;
35 scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
37 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
39 parserFactory.setNamespaceAware(false);
40 parserFactory.setValidating(true);
42 ProducerConfigHandler handler = new ProducerConfigHandler(parserFactory, aProducerFactories, aUsedFiles);
44 handler.includeFile(aFileName);
47 if (e instanceof SAXParseException && ((SAXParseException) e).getException() instanceof ConfigFailure) {
48 throw (ConfigFailure) ((SAXParseException) e).getException();
52 throw new ConfigFailure( e.getMessage() );
57 private class ProducerConfigHandler extends DefaultHandler {
58 private Locator locator;
59 private Stack includeFileStack;
60 private SAXParserFactory parserFactory;
61 private SectionsManager manager;
62 private List usedFiles;
63 private InputSource inputSource;
65 public ProducerConfigHandler(SAXParserFactory aParserFactory, Map aProducers, List aUsedFiles) {
68 includeFileStack=new Stack();
69 parserFactory=aParserFactory;
70 includeFileStack = new Stack();
71 manager = new SectionsManager();
72 usedFiles = aUsedFiles;
74 manager.pushHandler(new RootSectionHandler(aProducers));
77 public String getLocatorDescription(Locator aLocator) {
78 return aLocator.getPublicId()+" ("+aLocator.getLineNumber()+")";
81 public void setDocumentLocator(Locator aLocator) {
85 private void includeFile(String aFileName) throws ConfigFailure, SAXParseException, SAXException {
90 if (!includeFileStack.empty())
91 file = new File(new File((String) includeFileStack.peek()).getParent(), aFileName);
93 file = new File(aFileName);
95 System.err.println("about to include "+file.getCanonicalPath());
97 if (includeFileStack.contains(file.getCanonicalPath())) {
98 throw new ConfigFailure("recursive inclusion of file "+file.getCanonicalPath(), getLocatorDescription(locator));
103 parser=parserFactory.newSAXParser();
105 inputSource = new InputSource(new FileInputStream(file));
106 inputSource.setPublicId(file.getCanonicalPath());
108 includeFileStack.push(file.getCanonicalPath());
110 parser.parse(inputSource, this);
113 includeFileStack.pop();
116 catch (ParserConfigurationException e) {
117 throw new ConfigFailure("Internal exception while including \""+aFileName+"\": "+e.getMessage(), e, getLocatorDescription(locator));
119 catch (SAXParseException e) {
122 catch (ConfigFailure e) {
125 catch (FileNotFoundException e) {
126 throw new ConfigFailure("Include file \""+aFileName+"\" not found: "+e.getMessage(), e, getLocatorDescription(locator));
128 catch (IOException e) {
129 throw new ConfigFailure("unable to open include file \""+aFileName+"\": "+e.getMessage(), e, getLocatorDescription(locator));
133 public void startElement(String aUri, String aTag, String aQualifiedName, Attributes anAttributes) throws SAXException {
138 if (aQualifiedName.equals("include")) {
139 String fileName=anAttributes.getValue("file");
141 if (fileName==null) {
142 throw new ConfigFailure("include has no file attribute", getLocatorDescription(locator));
145 includeFile(fileName);
148 attributesMap = new HashMap();
149 for (i=0; i<anAttributes.getLength(); i++)
150 attributesMap.put(anAttributes.getQName(i), anAttributes.getValue(i));
152 manager.pushHandler( manager.currentHandler().startElement(aQualifiedName, attributesMap) );
155 catch (Exception e) {
156 e.printStackTrace(System.out);
157 throw new SAXException(e);
161 public void endElement(String aUri, String aTag, String aQualifiedName) throws SAXException {
164 if (!aQualifiedName.equals("include")) {
165 SectionHandler handler = manager.popHandler();
167 handler.finishSection();
169 if (!manager.isEmpty()) {
170 manager.currentHandler().endElement(handler);
174 catch (Exception e) {
175 e.printStackTrace(System.out);
176 throw new SAXException(e);
180 public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXParseException {
181 String text = new String(aBuffer, aStart, anEnd).trim();
182 if ( text.length() > 0) {
183 throw new SAXParseException("Text not allowed", locator, new ConfigFailure("text not allowed", getLocatorDescription(locator)));
188 public class SectionsManager {
191 public SectionsManager() {
192 handlerStack = new Stack();
195 public void pushHandler(SectionHandler aSectionHandler) {
196 handlerStack.push(aSectionHandler);
199 public SectionHandler popHandler() {
200 return (SectionHandler) handlerStack.pop();
203 public SectionHandler currentHandler() {
204 return (SectionHandler) handlerStack.peek();
207 public boolean isEmpty() {
208 return handlerStack.isEmpty();
212 public abstract class SectionHandler {
213 public abstract SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc;
215 public abstract void endElement(SectionHandler aHandler) throws ProducerConfigExc;
219 public void finishSection() throws ProducerConfigExc {
223 public class RootSectionHandler extends SectionHandler {
224 private Map producers;
226 public RootSectionHandler(Map aProducers) {
227 producers = aProducers;
230 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
231 if (aTag.equals("producers")) {
232 return new ProducersSectionHandler(producers);
235 throw new ProducerConfigExc ("Tag 'producers' expected, tag '"+aTag+"' found");
238 public void endElement(SectionHandler aHandler) {
241 public void finishSection() throws ProducerConfigExc {
246 private final static String PRODUCER_NAME_ATTRIBUTE = "name";
247 private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
248 private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
250 private final static String NODE_DEFINITION_NAME_ATTRIBUTE = "name";
251 private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
252 private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = { };
254 public class ProducersSectionHandler extends SectionHandler {
255 private Map producers;
258 public ProducersSectionHandler(Map aProducers) {
259 producers = aProducers;
262 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
264 if (aTag.equals("producer")) {
265 ReaderTool.checkAttributes(anAttributes, PRODUCER_REQUIRED_ATTRIBUTES, PRODUCER_OPTIONAL_ATTRIBUTES);
267 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
268 ReaderTool.checkValidIdentifier( name );
270 if (producers.containsKey(name))
271 throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
273 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
275 return new ProducerSectionHandler();
277 else if (aTag.equals("nodedefinition")) {
278 ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_REQUIRED_ATTRIBUTES, NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
280 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
281 ReaderTool.checkValidIdentifier( name );
283 // if (producers.containsKey(name))
284 // throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
286 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
288 return new NodeDefinitionSectionHandler(name);
291 throw new ProducerConfigExc("Unexpected tag: "+aTag );
294 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
295 if (aHandler instanceof ProducerSectionHandler) {
296 producers.put(name, ((ProducerSectionHandler) aHandler).getProducerFactory());
298 else if (aHandler instanceof NodeDefinitionSectionHandler) {
299 scriptedNodeBuilderLibrary.registerFactory(name,
300 new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
301 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
303 else throw new ProducerConfigExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
306 public void finishSection() throws ProducerConfigExc {
310 public class ProducerSectionHandler extends SectionHandler {
311 private ProducerFactory producerFactory;
313 private ProducerNode body;
315 private String defaultVerb;
317 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
318 if (aTag.equals("verbs")) {
320 throw new ProducerConfigExc("Verbs already processed");
322 throw new ProducerConfigExc("Verbs should come before body");
324 return new ProducerVerbsSectionHandler();
326 else if (aTag.equals("body")) {
328 return new ProducerNodeSectionHandler();
330 throw new ProducerConfigExc("Body already processed");
332 throw new ProducerConfigExc("Unexpected tag: '"+aTag+"'");
335 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
336 if (aHandler instanceof ProducerNodeSectionHandler) {
337 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
339 else if (aHandler instanceof ProducerVerbsSectionHandler)
341 verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
342 defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
344 else throw new ProducerConfigExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
347 public void finishSection() throws ProducerConfigExc {
349 throw new ProducerConfigExc("No verbs defined");
352 throw new ProducerConfigExc("No body defined");
354 producerFactory = new ScriptedProducerFactory(verbs, body, defaultVerb);
357 public ProducerFactory getProducerFactory() {
358 return producerFactory;
362 private final static String PRODUCER_VERB_NAME_ATTRIBUTE = "name";
363 private final static String PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
364 private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
365 private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE };
367 public class ProducerVerbsSectionHandler extends SectionHandler {
369 private String defaultVerb;
370 private String currentVerb;
372 public ProducerVerbsSectionHandler() {
373 verbs = new HashMap();
377 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
378 if (aTag.equals("verb")) {
379 ReaderTool.checkAttributes(anAttributes, PRODUCER_VERB_REQUIRED_ATTRIBUTES, PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
380 currentVerb = (String) anAttributes.get( PRODUCER_VERB_NAME_ATTRIBUTE );
382 ReaderTool.checkValidIdentifier( currentVerb );
384 if (verbs.containsKey(currentVerb))
385 throw new ProducerConfigExc( "Duplicate definition of verb '" + currentVerb + "'" );
387 if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
388 if (defaultVerb!=null)
389 throw new ProducerConfigExc( "Default verb already declared" );
391 defaultVerb = currentVerb;
394 return new ProducerNodeSectionHandler();
396 else throw new ProducerConfigExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
399 public void endElement(SectionHandler aHandler) {
400 verbs.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
403 public void finishSection() {
406 public String getDefaultVerb() {
410 public Map getVerbs() {
415 public class EmptySectionHandler extends SectionHandler {
416 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
417 throw new ProducerConfigExc("No tags are allowed here");
420 public void endElement(SectionHandler aHandler) {
425 public class MultiProducerNodeSectionHandler extends SectionHandler {
426 private Map nodeParameters;
427 private Set validNodeParameters;
428 private String currentNodeParameter;
429 private String scriptedNodeName;
430 private Set allowedNodeParameterReferences;
432 public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
433 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
434 scriptedNodeName = aScriptedNodeName;
435 validNodeParameters = aValidNodeParameters;
436 nodeParameters = new HashMap();
438 public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
439 this("", new HashSet(), aValidNodeParameters);
442 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
443 if (!validNodeParameters.contains(aTag))
444 throw new ProducerConfigExc("Invalid node parameter: '" + aTag + "'");
445 else if (nodeParameters.containsKey(aTag))
446 throw new ProducerConfigExc("Node parameter: '" + aTag + "' already specified");
447 else if (anAttributes.size()>0)
448 throw new ProducerConfigExc("No parameters are allowed here");
450 currentNodeParameter = aTag;
452 return new ProducerNodeSectionHandler(scriptedNodeName, validNodeParameters);
455 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
456 if (aHandler instanceof ProducerNodeSectionHandler) {
457 nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
460 throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
464 public Map getNodeParameters() {
465 return nodeParameters;
469 public class ProducerNodeSectionHandler extends SectionHandler {
470 private CompositeProducerNode producerNode;
471 private ProducerNodeBuilder currentBuilder;
472 private String scriptedNodeName;
473 private Set allowedNodeParameterReferences;
475 public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
476 producerNode = new CompositeProducerNode();
477 scriptedNodeName = aScriptedNodeName;
478 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
481 public ProducerNodeSectionHandler() {
482 this("", new HashSet());
485 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
486 if (allowedNodeParameterReferences.contains((aTag))) {
487 if (!anAttributes.isEmpty()) {
488 throw new ProducerConfigExc( "No attributes allowed" );
491 currentBuilder = new DefaultProducerNodeBuilders.ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
492 // producerNode.addSubNode(
493 // new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, aTag));
494 return new EmptySectionHandler();
496 else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) || builderLibrary.hasBuilderForName((aTag))) {
498 if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
499 currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
501 currentBuilder = builderLibrary.constructBuilder(aTag);
503 currentBuilder.setAttributes(anAttributes);
504 if (currentBuilder.getAvailableSubNodes().isEmpty()) {
505 return new EmptySectionHandler();
507 if (currentBuilder.getAvailableSubNodes().size()>1)
508 return new MultiProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences, currentBuilder.getAvailableSubNodes());
509 else if (currentBuilder.getAvailableSubNodes().size()<1)
510 return new EmptySectionHandler();
512 return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
516 throw new ProducerConfigExc("Unknown producer node tag: '" + aTag + "'");
519 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
520 if (aHandler instanceof ProducerNodeSectionHandler) {
521 currentBuilder.setSubNode((String) (currentBuilder.getAvailableSubNodes().iterator().next()),
522 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
524 else if (aHandler instanceof MultiProducerNodeSectionHandler) {
529 nodeParameters = ((MultiProducerNodeSectionHandler) aHandler).getNodeParameters();
530 i = nodeParameters.entrySet().iterator();
531 while (i.hasNext()) {
532 entry = (Map.Entry) i.next();
533 currentBuilder.setSubNode((String) entry.getKey(), (ProducerNode) entry.getValue());
536 else if (aHandler instanceof EmptySectionHandler) {
537 // deliberately empty: nothing expected, so nothing to process
540 throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
543 producerNode.addSubNode(currentBuilder.constructNode());
544 currentBuilder = null;
547 public ProducerNode getProducerNode() {
548 if (producerNode.getNrSubNodes()==1) {
549 return producerNode.getSubNode(0);
557 public class NodeDefinitionSectionHandler extends SectionHandler {
558 private ScriptedProducerNodeDefinition nodeDefinition;
559 private ProducerNode body;
560 private Map stringParameters;
561 private Map nodeParameters;
564 public NodeDefinitionSectionHandler(String aName) {
566 nodeParameters = null;
567 stringParameters = null;
571 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
572 if (aTag.equals("parameters")) {
573 if (!anAttributes.isEmpty()) {
574 throw new ProducerConfigExc( "No attributes allowed for tag 'parameters'" );
576 if (nodeParameters!=null) {
577 throw new ProducerConfigExc( "Parameters have already been declared" );
580 throw new ProducerConfigExc( "Parameters should come before definition" );
583 return new NodeDefinitionParametersSectionHandler();
585 else if (aTag.equals("definition")) {
586 return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
588 else throw new ProducerConfigExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
591 public void endElement(SectionHandler aHandler) {
592 if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
593 stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
594 nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
596 else if (aHandler instanceof ProducerNodeSectionHandler) {
597 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
601 public void finishSection() throws ProducerConfigExc {
604 throw new ProducerConfigExc( "Definition missing" );
606 nodeDefinition = new ScriptedProducerNodeDefinition(name);
608 nodeDefinition.setBody(body);
610 i = nodeParameters.keySet().iterator();
611 while (i.hasNext()) {
612 nodeDefinition.addNodeParameter((String) i.next());
615 i = stringParameters.entrySet().iterator();
616 while (i.hasNext()) {
617 Map.Entry entry = (Map.Entry) i.next();
618 nodeDefinition.addParameter((String) entry.getKey(), (String) entry.getValue());
622 public ScriptedProducerNodeDefinition getDefinition() {
623 return nodeDefinition;
627 private final static String NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
628 private final static String NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
629 private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
630 private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
631 private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
633 public class NodeDefinitionParametersSectionHandler extends SectionHandler {
634 private Map nodeParameters;
635 private Map stringParameters;
637 public NodeDefinitionParametersSectionHandler() {
638 nodeParameters = new HashMap();
639 stringParameters = new HashMap();
642 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
643 String parameterName;
646 if (aTag.equals("node")) {
647 ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
648 parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
650 if (nodeParameters.containsKey(parameterName))
651 throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
653 ReaderTool.checkValidIdentifier( parameterName );
655 nodeParameters.put(parameterName, parameterName);
657 return new EmptySectionHandler();
659 else if (aTag.equals("string")) {
660 ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
661 parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
663 if (stringParameters.containsKey(parameterName))
664 throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
666 ReaderTool.checkValidIdentifier( parameterName );
668 defaultValue = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE );
670 stringParameters.put(parameterName, defaultValue);
672 return new EmptySectionHandler();
674 else throw new ProducerConfigExc("Only 'string' and 'node' tags allowed here, '" + aTag + "' encountered.");
678 public void endElement(SectionHandler aHandler) {
681 public void finishSection() {
684 public Map getNodeParameters() {
685 return nodeParameters;
688 public Map getStringParameters() {
689 return stringParameters;
696 / (expecting producers)
697 producers/ (expecting nodedefinition, producer)
698 nodedefinition (expecting parameters, definition)
699 parameters (expecting parameter declarations)
700 definition (expecting nodes, subnodes)