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; } /** * 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(); } } }