/* * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway * Copyright (C) 2009 Mickael Guessant * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package davmail.exchange; import org.apache.log4j.Logger; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.util.HashMap; import java.util.Map; /** * XmlStreamReader utility methods */ @SuppressWarnings("Since15") public final class XMLStreamUtil { private static final Logger LOGGER = Logger.getLogger(XMLStreamUtil.class); private XMLStreamUtil() { } /** * Build a new XMLInputFactory. * * @return XML input factory */ public static XMLInputFactory getXmlInputFactory() { XMLInputFactory inputFactory = XMLInputFactory.newInstance(); inputFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE); return inputFactory; } /** * Convert the XML stream to a map of entries. * An entry is also a key/value map * * @param inputStream xml input stream * @param rowName xml tag name of entries * @param idName xml tag name of entry attribute used as key in the main map * @return map of entries * @throws IOException on error */ public static Map> getElementContentsAsMap(InputStream inputStream, String rowName, String idName) throws IOException { Map> results = new HashMap>(); Map item = null; String currentElement = null; XMLStreamReader reader = null; try { XMLInputFactory inputFactory = getXmlInputFactory(); reader = inputFactory.createXMLStreamReader(inputStream); while (reader.hasNext()) { int event = reader.next(); if (event == XMLStreamConstants.START_ELEMENT && rowName.equals(reader.getLocalName())) { item = new HashMap(); } else if (event == XMLStreamConstants.END_ELEMENT && rowName.equals(reader.getLocalName())) { if (item.containsKey(idName)) { results.put(item.get(idName).toLowerCase(), item); } item = null; } else if (event == XMLStreamConstants.START_ELEMENT && item != null) { currentElement = reader.getLocalName(); } else if (event == XMLStreamConstants.CHARACTERS && currentElement != null) { item.put(currentElement, reader.getText()); currentElement = null; } } } catch (XMLStreamException e) { throw new IOException(e.getMessage()); } finally { try { if (reader != null) { reader.close(); } } catch (XMLStreamException e) { ExchangeSession.LOGGER.error(e); } } return results; } /** * Test if reader is on a start tag named tagLocalName. * * @param reader xml stream reader * @param tagLocalName tag local name * @return true if reader is on a start tag named tagLocalName */ public static boolean isStartTag(XMLStreamReader reader, String tagLocalName) { return (reader.getEventType() == XMLStreamConstants.START_ELEMENT) && (reader.getLocalName().equals(tagLocalName)); } /** * Test if reader is on a start tag. * * @param reader xml stream reader * @return true if reader is on a start tag */ public static boolean isStartTag(XMLStreamReader reader) { return (reader.getEventType() == XMLStreamConstants.START_ELEMENT); } /** * Test if reader is on an end tag named tagLocalName. * * @param reader xml stream reader * @param tagLocalName tag local name * @return true if reader is on an end tag named tagLocalName */ public static boolean isEndTag(XMLStreamReader reader, String tagLocalName) { return (reader.getEventType() == XMLStreamConstants.END_ELEMENT) && (reader.getLocalName().equals(tagLocalName)); } /** * Create XML stream reader for byte array * * @param xmlContent xml content as byte array * @return XML stream reader * @throws XMLStreamException on error */ public static XMLStreamReader createXMLStreamReader(byte[] xmlContent) throws XMLStreamException { return createXMLStreamReader(new ByteArrayInputStream(xmlContent)); } /** * Create XML stream reader for string * * @param xmlContent xml content as string * @return XML stream reader * @throws XMLStreamException on error */ public static XMLStreamReader createXMLStreamReader(String xmlContent) throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLStreamUtil.getXmlInputFactory(); return xmlInputFactory.createXMLStreamReader(new StringReader(xmlContent)); } /** * Create XML stream reader for inputStream * * @param inputStream xml content inputStream * @return XML stream reader * @throws XMLStreamException on error */ public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLStreamUtil.getXmlInputFactory(); return xmlInputFactory.createXMLStreamReader(inputStream); } /** * Get element text. * * @param reader stream reader * @return element text */ public static String getElementText(XMLStreamReader reader) { String value = null; try { value = reader.getElementText(); } catch (XMLStreamException e) { LOGGER.warn(e.getMessage()); } catch (RuntimeException e) { // probably com.ctc.wstx.exc.WstxLazyException on invalid character sequence LOGGER.warn(e.getMessage()); } return value; } }