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) {
300 scriptedNodeBuilderLibrary.registerFactory(name,
301 new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
302 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
304 else throw new ProducerConfigExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
307 public void finishSection() throws ProducerConfigExc {
311 public class ProducerSectionHandler extends SectionHandler {
312 private ProducerFactory producerFactory;
314 private ProducerNode body;
316 private String defaultVerb;
318 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
319 if (aTag.equals("verbs")) {
321 throw new ProducerConfigExc("Verbs already processed");
323 throw new ProducerConfigExc("Verbs should come before body");
325 return new ProducerVerbsSectionHandler();
327 else if (aTag.equals("body")) {
329 return new ProducerNodeSectionHandler();
331 throw new ProducerConfigExc("Body already processed");
333 throw new ProducerConfigExc("Unexpected tag: '"+aTag+"'");
336 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
337 if (aHandler instanceof ProducerNodeSectionHandler) {
338 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
340 else if (aHandler instanceof ProducerVerbsSectionHandler)
342 verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
343 defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
345 else throw new ProducerConfigExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
348 public void finishSection() throws ProducerConfigExc {
350 throw new ProducerConfigExc("No verbs defined");
353 throw new ProducerConfigExc("No body defined");
355 producerFactory = new ScriptedProducerFactory(verbs, body, defaultVerb);
358 public ProducerFactory getProducerFactory() {
359 return producerFactory;
363 private final static String PRODUCER_VERB_NAME_ATTRIBUTE = "name";
364 private final static String PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
365 private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
366 private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE };
368 public class ProducerVerbsSectionHandler extends SectionHandler {
370 private String defaultVerb;
371 private String currentVerb;
373 public ProducerVerbsSectionHandler() {
374 verbs = new HashMap();
378 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
379 if (aTag.equals("verb")) {
380 ReaderTool.checkAttributes(anAttributes, PRODUCER_VERB_REQUIRED_ATTRIBUTES, PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
381 currentVerb = (String) anAttributes.get( PRODUCER_VERB_NAME_ATTRIBUTE );
383 ReaderTool.checkValidIdentifier( currentVerb );
385 if (verbs.containsKey(currentVerb))
386 throw new ProducerConfigExc( "Duplicate definition of verb '" + currentVerb + "'" );
388 if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
389 if (defaultVerb!=null)
390 throw new ProducerConfigExc( "Default verb already declared" );
392 defaultVerb = currentVerb;
395 return new ProducerNodeSectionHandler();
397 else throw new ProducerConfigExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
400 public void endElement(SectionHandler aHandler) {
401 verbs.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
404 public void finishSection() {
407 public String getDefaultVerb() {
411 public Map getVerbs() {
416 public class EmptySectionHandler extends SectionHandler {
417 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
418 throw new ProducerConfigExc("No tags are allowed here");
421 public void endElement(SectionHandler aHandler) {
426 public class MultiProducerNodeSectionHandler extends SectionHandler {
427 private Map nodeParameters;
428 private Set validNodeParameters;
429 private String currentNodeParameter;
430 private String scriptedNodeName;
431 private Set allowedNodeParameterReferences;
433 public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
434 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
435 scriptedNodeName = aScriptedNodeName;
436 validNodeParameters = aValidNodeParameters;
437 nodeParameters = new HashMap();
439 public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
440 this("", new HashSet(), aValidNodeParameters);
443 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
444 if (!validNodeParameters.contains(aTag))
445 throw new ProducerConfigExc("Invalid node parameter: '" + aTag + "'");
446 else if (nodeParameters.containsKey(aTag))
447 throw new ProducerConfigExc("Node parameter: '" + aTag + "' already specified");
448 else if (anAttributes.size()>0)
449 throw new ProducerConfigExc("No parameters are allowed here");
451 currentNodeParameter = aTag;
453 return new ProducerNodeSectionHandler(scriptedNodeName, validNodeParameters);
456 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
457 if (aHandler instanceof ProducerNodeSectionHandler) {
458 nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
461 throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
465 public Map getNodeParameters() {
466 return nodeParameters;
470 public class ProducerNodeSectionHandler extends SectionHandler {
471 private CompositeProducerNode producerNode;
472 private ProducerNodeBuilder currentBuilder;
473 private String scriptedNodeName;
474 private Set allowedNodeParameterReferences;
476 public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
477 producerNode = new CompositeProducerNode();
478 scriptedNodeName = aScriptedNodeName;
479 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
482 public ProducerNodeSectionHandler() {
483 this("", new HashSet());
486 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
487 if (allowedNodeParameterReferences.contains((aTag))) {
488 if (!anAttributes.isEmpty()) {
489 throw new ProducerConfigExc( "No attributes allowed" );
491 producerNode.addSubNode(new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, aTag));
493 return new EmptySectionHandler();
495 else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) || builderLibrary.hasBuilderForName((aTag))) {
497 if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
498 currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
500 currentBuilder = builderLibrary.constructBuilder(aTag);
502 currentBuilder.setAttributes(anAttributes);
503 if (currentBuilder.getAvailableSubNodes().isEmpty()) {
504 return new EmptySectionHandler();
506 if (currentBuilder.getAvailableSubNodes().size()>1)
507 return new MultiProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences, currentBuilder.getAvailableSubNodes());
508 else if (currentBuilder.getAvailableSubNodes().size()<1)
509 return new EmptySectionHandler();
511 return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
515 throw new ProducerConfigExc("Unknown producer node tag: '" + aTag + "'");
518 public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
519 if (aHandler instanceof ProducerNodeSectionHandler) {
520 currentBuilder.setSubNode((String) (currentBuilder.getAvailableSubNodes().iterator().next()),
521 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
523 else if (aHandler instanceof MultiProducerNodeSectionHandler) {
528 nodeParameters = ((MultiProducerNodeSectionHandler) aHandler).getNodeParameters();
529 i = nodeParameters.entrySet().iterator();
530 while (i.hasNext()) {
531 entry = (Map.Entry) i.next();
532 currentBuilder.setSubNode((String) entry.getKey(), (ProducerNode) entry.getValue());
535 else if (aHandler instanceof EmptySectionHandler) {
536 // deliberately empty: nothing expected, so nothing to process
539 throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
542 producerNode.addSubNode(currentBuilder.constructNode());
543 currentBuilder = null;
546 public ProducerNode getProducerNode() {
547 if (producerNode.getNrSubNodes()==1) {
548 return producerNode.getSubNode(0);
556 public class NodeDefinitionSectionHandler extends SectionHandler {
557 private ScriptedProducerNodeDefinition nodeDefinition;
558 private ProducerNode definition;
559 private Map stringParameters;
560 private Map nodeParameters;
563 public NodeDefinitionSectionHandler(String aName) {
565 nodeParameters = null;
566 stringParameters = null;
570 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
571 if (aTag.equals("parameters")) {
572 if (!anAttributes.isEmpty()) {
573 throw new ProducerConfigExc( "No attributes allowed for tag 'parameters'" );
575 if (nodeParameters!=null) {
576 throw new ProducerConfigExc( "Parameters have already been declared" );
578 if (definition!=null) {
579 throw new ProducerConfigExc( "Parameters should come before definition" );
582 return new NodeDefinitionParametersSectionHandler();
584 else if (aTag.equals("definition")) {
585 return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
587 else throw new ProducerConfigExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
590 public void endElement(SectionHandler aHandler) {
591 if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
592 stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
593 nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
595 else if (aHandler instanceof ProducerNodeSectionHandler) {
596 definition = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
600 public void finishSection() throws ProducerConfigExc {
602 if (definition == null)
603 throw new ProducerConfigExc( "Definition missing" );
605 nodeDefinition = new ScriptedProducerNodeDefinition(name);
607 i = nodeParameters.keySet().iterator();
608 while (i.hasNext()) {
609 nodeDefinition.addNodeParameter((String) i.next());
612 i = stringParameters.entrySet().iterator();
613 while (i.hasNext()) {
614 Map.Entry entry = (Map.Entry) i.next();
615 nodeDefinition.addParameter((String) entry.getKey(), (String) entry.getValue());
619 public ScriptedProducerNodeDefinition getDefinition() {
620 return nodeDefinition;
624 private final static String NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
625 private final static String NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
626 private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
627 private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
628 private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
630 public class NodeDefinitionParametersSectionHandler extends SectionHandler {
631 private Map nodeParameters;
632 private Map stringParameters;
634 public NodeDefinitionParametersSectionHandler() {
635 nodeParameters = new HashMap();
636 stringParameters = new HashMap();
639 public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
640 String parameterName;
643 if (aTag.equals("node")) {
644 ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
645 parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
647 if (nodeParameters.containsKey(parameterName))
648 throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
650 ReaderTool.checkValidIdentifier( parameterName );
652 nodeParameters.put(parameterName, parameterName);
654 return new EmptySectionHandler();
656 else if (aTag.equals("string")) {
657 ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
658 parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
660 if (stringParameters.containsKey(parameterName))
661 throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
663 ReaderTool.checkValidIdentifier( parameterName );
665 defaultValue = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE );
667 stringParameters.put(parameterName, defaultValue);
669 return new EmptySectionHandler();
671 else throw new ProducerConfigExc("Only 'string' and 'node' tags allowed here, '" + aTag + "' encountered.");
675 public void endElement(SectionHandler aHandler) {
678 public void finishSection() {
681 public Map getNodeParameters() {
682 return nodeParameters;
685 public Map getStringParameters() {
686 return stringParameters;
693 / (expecting producers)
694 producers/ (expecting nodedefinition, producer)
695 nodedefinition (expecting parameters, definition)
696 parameters (expecting parameter declarations)
697 definition (expecting nodes, subnodes)