public List<ExtensionInfo> parse() {
   List<ExtensionInfo> result = Lists.newArrayList();
   try {
     XMLReader reader = XMLReaderFactory.createXMLReader();
     PluginXMLContentHandler handler = new PluginXMLContentHandler();
     reader.setContentHandler(handler);
     for (URL u : getAllPluginResourceURLs()) {
       InputStream openStream = null;
       try {
         openStream = u.openStream();
         reader.parse(new InputSource(openStream));
       } catch (IOException e) {
         throw new RuntimeException(e);
       } finally {
         if (openStream != null)
           try {
             openStream.close();
           } catch (IOException e) {
             throw new RuntimeException(e);
           }
       }
     }
     for (ExtensionPointHandler h : handler.getFinishedHandlers())
       for (ExtensionInfo pi : h.getInfo()) result.add(pi);
   } catch (SAXException e) {
     throw new RuntimeException(e);
   }
   return result;
 }
 @Override
 public void endElement(String uri, String localName, String qName) throws SAXException {
   if ("extension".equals(qName) && currentHandler != null) {
     finishedHandlers.add(currentHandler);
     currentHandler = null;
   }
   if (currentHandler != null) currentHandler.endElement(uri, localName, qName);
 }
 @Override
 public void startElement(String uri, String localName, String qName, Attributes attributes)
     throws SAXException {
   if ("extension".equals(qName)) {
     String point = attributes.getValue("point");
     Class<? extends ExtensionPointHandler> clazz = handlers.get(point);
     if (clazz != null) {
       try {
         currentHandler = clazz.newInstance();
         currentHandler.beginElement(uri, localName, qName, attributes);
       } catch (InstantiationException e) {
         throw new RuntimeException(e);
       } catch (IllegalAccessException e) {
         throw new RuntimeException(e);
       }
     }
   } else if (currentHandler != null)
     currentHandler.beginElement(uri, localName, qName, attributes);
 }