--- /dev/null
+package mir.xml;
+
+
+// XXX this interface is not final, but a prototype.
+
+/** SAX Context - used to match and perform actions
+ * provide access to the current stack and XML elements.
+ *
+ * Inspired by Tomcat's SAX context, although our's is
+ * implemented and used slightly differently.
+ *
+ * @author
+ */
+public class SaxContext {
+
+ private String tagStack[];
+ private int pos;
+
+ // -------------------- Konstruktor
+
+ public SaxContext() {
+ pos=0;
+ tagStack = new String[256];
+ }
+
+ // -------------------- Access to parsing context
+
+ /** Depth of the tag stack.
+ */
+ public int getTagCount() {
+ return pos;
+ }
+
+ /** Access a particular tag
+ */
+ public String getTag( int pos ) {
+ return tagStack[pos];
+ }
+
+ // ------------------- Adjusting the parsing context
+ public void push(String tag) {
+ tagStack[pos] = tag;
+ pos++;
+ }
+
+ public void pop() {
+ if(pos > 1)
+ tagStack[pos]=null;
+
+ pos--;
+ }
+
+}
+
private File configFileParent;
private Locator locator;
- //private SaxContext saxContext;
+ private SaxContext saxContext;
+
+ XmlMatch requiredXmlMatch[]=new XmlMatch[256]; //maximum amount of rules
+ int requiredXmlMatchCount=0;
+ boolean matched[] = new boolean[256];
+ int matchedCount=0;
+
+ private static XmlConfigurator instance = new XmlConfigurator();
+ public static XmlConfigurator getInstance() { return instance; }
/**
* Configures the Project with the contents of the specified XML file.
*/
- public static void configure(File configFile) throws ConfigException {
- new XmlConfigurator(configFile).parse();
+ public void configure(File configFile) throws ConfigException {
+ setConfigFile(configFile);
+ parse();
}
/**
+ * konstruktor. private so no one calls "new" on us.
+ */
+ private XmlConfigurator() {}
+
+
+ /**
* Constructs a new Ant parser for the specified XML file.
*/
- private XmlConfigurator(File configFile) {
+ private void setConfigFile(File configFile) {
this.configFile = new File(configFile.getAbsolutePath());
configFileParent = new File(this.configFile.getParent());
+ saxContext = new SaxContext();
}
/**
inputSource = new InputSource(inputStream);
inputSource.setSystemId(uri);
saxParser.parse(inputSource, new RootHandler());
+ if(matchedCount < requiredXmlMatchCount) {
+ for( int i=0; i<requiredXmlMatchCount; i++) {
+ if( !matched[i] )
+ throw new ConfigException("Error parsing config file, missing required element: "+requiredXmlMatch[i].toString());
+ }
+ }
}
catch(ParserConfigurationException exc) {
throw new ConfigException("Parser has not been configured correctly", exc);
*/
protected void finished() {}
- public void endElement() throws SAXException {
-
+ public void endElement(String uri, String tag, String qName) throws SAXException {
finished();
// Let parent resume handling SAX events
saxParser.getXMLReader().setContentHandler(parentHandler);
locator);
}
+ saxContext.push(tag);
+ matchedCount += checkRequiredTag(saxContext);
+
//MirConfig.setName(name);
}
}
}
+ public void finished() {
+ System.out.println("COUNT "+saxContext.getTagCount()+" TAG "+saxContext.getTag(saxContext.getTagCount()-1));
+ saxContext.pop();
+ }
+
private void handleClassdef(String name, Attributes attrs) throws SAXParseException {
(new ClassHandler(this)).init(name, attrs);
}
throw new SAXParseException("class element appears without a \"name\" attribute", locator);
}
+ saxContext.push(tag+":"+name);
+ matchedCount += checkRequiredTag(saxContext);
try {
classN=Class.forName(name);
} catch (ClassNotFoundException e) {
}
}
+ public void finished() {
+ System.out.println("COUNT "+saxContext.getTagCount()+" TAG "+saxContext.getTag(saxContext.getTagCount()-1));
+ System.out.println("COUNT "+saxContext.getTagCount());
+ saxContext.pop();
+ }
+
private void handleProperties(String name, Attributes attrs) throws SAXParseException {
(new PropertiesHandler(this, classN )).init(name, attrs);
}
if (value == null) {
throw new SAXParseException("property element appears without a \"value\" attribute", locator);
}
+ saxContext.push(tag+":"+name);
+ matchedCount += checkRequiredTag(saxContext);
/////
}
protected void finished() {
- //do the setting here?
+ System.out.println("COUNT "+saxContext.getTagCount()+" TAG "+saxContext.getTag(saxContext.getTagCount()-1));
+ System.out.println("COUNT "+saxContext.getTagCount());
+ saxContext.pop();
}
}
+ public void addRequiredTag(String xmlPath) {
+ requiredXmlMatch[requiredXmlMatchCount]=new XmlMatch(xmlPath);
+ matched[requiredXmlMatchCount]=false;
+ requiredXmlMatchCount++;
+ }
+
+ private int checkRequiredTag(SaxContext ctx) {
+ int matchCount=0;
+ for( int i=0; i<requiredXmlMatchCount; i++ ) {
+ if( requiredXmlMatch[i].match(ctx) ) {
+ matched[i]=true;
+ matchCount++;
+ }
+ }
+ return matchCount;
+ }
+
+
private static String capitalize(String name) {
if (name == null || name.length() == 0) {
return name;
--- /dev/null
+package mir.xml;
+
+import java.util.*;
+import java.util.StringTokenizer;
+
+/** micro-XPath match - match a path
+ */
+class XmlMatch {
+ String names[]=new String[10]; //max path depth
+ int pos=0;
+
+ public XmlMatch( String tagName ) {
+ StringTokenizer st=new StringTokenizer( tagName, "/" );
+ while( st.hasMoreTokens() ) {
+ names[pos]=st.nextToken();
+ pos++;
+ }
+ }
+
+ public boolean match( SaxContext ctx ) {
+ int depth=ctx.getTagCount();
+
+ for( int j=pos-1; j>=0; j--) {
+ if( depth<1) {
+ // System.out.println("Pattern too long ");
+ return false;
+ }
+ String tag=ctx.getTag(depth-1);
+ if( ! names[j].equals( tag ) ) {
+ // System.out.println("XXX" + names[j] + " " + tag);
+ return false;
+ }
+ depth--;
+ }
+
+
+ return true;
+ }
+
+ public String toString() {
+ return "Tag("+names+")";
+ }
+
+}
+