package hudson.plugins.violations.parse; import java.io.IOException; import java.io.InputStream; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; /** * Base class for parsing xml files. Contains a number of utility protected * methods to aid in use of XmlPullParser. */ public abstract class AbstractParser { private XmlPullParser parser; /** * Get the parser. * * @return the parser. */ protected XmlPullParser getParser() { return parser; } /** * Set the parser. * * @param parser * the value to use. */ public void setParser(XmlPullParser parser) { this.parser = parser; } /** * Abstract method to run the parsing. * * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected abstract void execute() throws IOException, XmlPullParserException; /** * Parse an input stream. * * @param in * the stream to parse. */ /* package */void parse(InputStream in) throws IOException, XmlPullParserException { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); parser = factory.newPullParser(); parser.setInput(in, null); execute(); } // ----------------------------------------------- // // Utility methods // // ----------------------------------------------- /** * Get an attribute value as a string. * * @param name * the name of the attribute. * @return the int value of the attribute, or "" if the attribute is not * present. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected String getString(String name) throws IOException, XmlPullParserException { String v = parser.getAttributeValue("", name); return (v == null) ? "" : v; } /** * Get an attribute value as an int. * * @param name * the name of the attribute. * @return the int value of the attribute, or 0 if the attribute is not * present or is not an int. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected int getInt(String name) throws IOException, XmlPullParserException { String v = parser.getAttributeValue("", name); try { return Integer.parseInt(v); } catch (Exception ex) { return 0; } } /** * Get an attribute value as an int and ensure that the attribute is * present. * * @param name * the name of the attribute. * @return the int value of the attribute, or 0 if the attribute is not an * int. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax or the attribute is not * present. */ protected int checkGetInt(String name) throws IOException, XmlPullParserException { String v = checkGetAttribute(name); try { return Integer.parseInt(v); } catch (Exception ex) { return 0; } } /** * Get an attribute value as a long and ensure that the attribute is * present. * * @param name * the name of the attribute. * @return the long value of the attribute, or 0 if the attribute is not an * long. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax, of the attribute is not * present. */ protected long checkGetLong(String name) throws IOException, XmlPullParserException { String v = checkGetAttribute(name); try { return Long.parseLong(v); } catch (Exception ex) { return 0; } } /** * Get an attribute value and ensure that the attribute is present. * * @param name * the name of the attribute. * @return the value of the attribute. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax, or the attribute is not * present. */ protected String checkGetAttribute(String name) throws IOException, XmlPullParserException { String ret = parser.getAttributeValue("", name); if (ret == null) { throw new XmlPullParserException("Expecting attribute " + name + " in element " + parser.getName()); } return ret; } /** * Get an attribute value and ensure that the attribute is present and is * not blank. * * @param name * the name of the attribute. * @return the value of the attribute. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. or the attribute is not * present or is blank. */ protected String checkNotBlank(String name) throws IOException, XmlPullParserException { String ret = parser.getAttributeValue("", name); if (ret == null || ret.trim().equals("")) { throw new XmlPullParserException("Expecting attribute " + name + " in element " + parser.getName()); } return ret; } protected String checkNotNull(String name) throws IOException, XmlPullParserException { String ret = parser.getAttributeValue("", name); if (ret == null) { throw new XmlPullParserException("Expecting attribute " + name + " in element " + parser.getName()); } return ret; } /** * Skip to a specific tag within a element. * * @param tagName * the tag to look for. * @return true if the tag is found, false otherwise. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected boolean skipToTag(String tagName) throws IOException, XmlPullParserException { while (true) { if (parser.getEventType() == XmlPullParser.END_TAG) { return false; } if (parser.getEventType() != XmlPullParser.START_TAG) { parser.next(); continue; } if (parser.getName().equals(tagName)) { return true; } skipTag(); } } /** * get the next sibling element. * * @return the tag of the element or none if there are no more elements. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected String getSibTag() throws IOException, XmlPullParserException { while (true) { if (parser.getEventType() == XmlPullParser.END_TAG) { return null; } if (parser.getEventType() == XmlPullParser.START_TAG) { return parser.getName(); } parser.next(); } } /** * Assume at a start tag, skip it and the rest of the element. * * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected void skipTag() throws IOException, XmlPullParserException { parser.next(); endElement(); } /** * Find the next START_TAG event and throw an exception if the tagname is * not "tag"; * * @param tag * the tag to expect. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected void expectStartTag(String tag) throws IOException, XmlPullParserException { while (true) { if (parser.getEventType() != XmlPullParser.START_TAG) { parser.next(); continue; } if (parser.getName().equals(tag)) { return; } } } /** * Find the next START_TAG event and throw an exception if the tagname is * not "tag"; * * @param tag * the tag to expect. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected void expectNextTag(String tag) throws IOException, XmlPullParserException { while (true) { if (parser.getEventType() != XmlPullParser.START_TAG) { parser.next(); continue; } if (parser.getName().equals(tag)) { return; } throw new IOException("Expecting tag " + tag); } } /** * check the current event type. * * @param event * the event type expected. * @param message * a message to use in the RT exception if the event is not * found. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected void checkEvent(int event, String message) throws IOException, XmlPullParserException { if (parser.getEventType() != event) { throw new RuntimeException(message); } } /** * get the next event and check the type. * * @param event * the event type expected. * @param message * a message to use in the RT exception if the event is not * found. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected void checkNextEvent(int event, String message) throws IOException, XmlPullParserException { parser.next(); checkEvent(event, message); } /** * Get the next event and check it is a text event. * * @param message * a message to use in the RT exception if the TEXT event is not * found. * @return the text in the event. * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected String getNextText(String message) throws IOException, XmlPullParserException { checkNextEvent(XmlPullParser.TEXT, message); return parser.getText(); } /** * skip to the end of the element. recursivly skip over nested elements. * * @throws IOException * if there is a problem writing or reading. * @throws XmlPullParserException * if there is a problem in the syntax. */ protected void endElement() throws IOException, XmlPullParserException { // In a tag (after the tag has been consumed, // get and consume the end tag (recursively) while (true) { if (parser.getEventType() == XmlPullParser.START_TAG) { parser.next(); endElement(); continue; } if (parser.getEventType() == XmlPullParser.END_TAG) { parser.next(); return; } parser.next(); } } }