/******************************************************************************* * Copyright (c) 2008 Pierre-Antoine Grégoire. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Pierre-Antoine Grégoire - initial API and implementation *******************************************************************************/ package org.org.eclipse.dws.core.internal.xml; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.Characters; import javax.xml.stream.events.EndElement; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import org.org.eclipse.core.utils.platform.binding.BindingException; import org.org.eclipse.dws.core.internal.model.ParentPom; import org.org.eclipse.dws.core.internal.model.Pom; import org.org.eclipse.dws.core.internal.model.PomDependency; import org.org.eclipse.dws.core.internal.model.PomProperty; import org.org.eclipse.dws.core.internal.model.PomRepository; import org.org.eclipse.dws.core.internal.model.PomDependency.Scope; /** * The Class StaxPomFileBinder. */ public class StaxPomFileBinder implements IXmlPomFileBinder { /** * @see org.org.eclipse.dws.core.internal.xml.IXmlPomFileBinder#parsePomFile(java.io.InputStream) */ public Pom parsePomFile(InputStream inputStream) throws BindingException { Pom result = null; XMLInputFactory factory = XMLInputFactory.newInstance(); try { XMLEventReader parser = factory.createXMLEventReader(inputStream); eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndDocument()) { parser.close(); break eventloop; } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String elementNameLocalPart = startElement.getName().getLocalPart(); if (elementNameLocalPart.equals(PROJECT_TAG)) { result = new Pom(); parseProject(parser, result); continue; } } } } catch (XMLStreamException e) { throw new BindingException(e); } return result; } private void parseProject(XMLEventReader parser, Pom result) throws XMLStreamException { eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndElement()) { EndElement endElement = event.asEndElement(); String elementNameLocalPart = endElement.getName().getLocalPart(); if (elementNameLocalPart.equals(PROJECT_TAG)) { break eventloop; } } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String elementNameLocalPart = startElement.getName().getLocalPart(); if (elementNameLocalPart.equals(GROUPID_TAG)) { result.setGroupId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(ARTIFACTID_TAG)) { result.setArtifactId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(VERSION_TAG)) { result.setVersion(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(PACKAGING_TAG)) { result.setPackaging(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(DESCRIPTION_TAG)) { result.setDescription(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(NAME_TAG)) { result.setName(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(DEPENDENCIES_TAG)) { parseDependencies(parser, result); continue; } if (elementNameLocalPart.equals(PARENT_TAG)) { parseParent(parser, result); continue; } if (elementNameLocalPart.equals(REPOSITORY_TAG)) { parseRepository(REPOSITORY_TAG, parser, result); continue; } if (elementNameLocalPart.equals(SNAPSHOT_REPOSITORY_TAG)) { parseRepository(SNAPSHOT_REPOSITORY_TAG, parser, result); continue; } if (elementNameLocalPart.equals(PROPERTIES_TAG)) { parseProperties(parser, result); continue; } } } } private void parseProperties(XMLEventReader parser, Pom result) throws XMLStreamException { eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndElement()) { EndElement endElement = event.asEndElement(); String elementNameLocalPart = endElement.getName().getLocalPart(); if (elementNameLocalPart.equals(PROPERTIES_TAG)) { break eventloop; } } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String key = startElement.getName().getLocalPart(); String value = parseTagTextContent(parser); result.getProperties().addProperty(new PomProperty(key, value)); continue; } } } private void parseRepository(String tagName, XMLEventReader parser, Pom result) throws XMLStreamException { PomRepository pomRepository = new PomRepository(); eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndElement()) { EndElement endElement = event.asEndElement(); String elementNameLocalPart = endElement.getName().getLocalPart(); if (elementNameLocalPart.equals(tagName)) { result.getRepositories().addRepository(pomRepository); break eventloop; } } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String elementNameLocalPart = startElement.getName().getLocalPart(); if (elementNameLocalPart.equals(ID_TAG)) { pomRepository.setId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(NAME_TAG)) { pomRepository.setName(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(URL_TAG)) { pomRepository.setUrl(parseTagTextContent(parser)); continue; } } } } private void parseParent(XMLEventReader parser, Pom result) throws XMLStreamException { ParentPom parentPom = new ParentPom(); eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndElement()) { EndElement endElement = event.asEndElement(); String elementNameLocalPart = endElement.getName().getLocalPart(); if (elementNameLocalPart.equals(PARENT_TAG)) { result.setParentPom(parentPom); break eventloop; } } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String elementNameLocalPart = startElement.getName().getLocalPart(); if (elementNameLocalPart.equals(GROUPID_TAG)) { parentPom.setGroupId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(ARTIFACTID_TAG)) { parentPom.setArtifactId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(VERSION_TAG)) { parentPom.setVersion(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(RELATIVEPATH_TAG)) { parentPom.setRelativePath(parseTagTextContent(parser)); continue; } } } } private void parseDependencies(XMLEventReader parser, Pom result) throws XMLStreamException { eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndElement()) { EndElement endElement = event.asEndElement(); String elementNameLocalPart = endElement.getName().getLocalPart(); if (elementNameLocalPart.equals(DEPENDENCIES_TAG)) { break eventloop; } } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String elementNameLocalPart = startElement.getName().getLocalPart(); if (elementNameLocalPart.equals(DEPENDENCY_TAG)) { parseDependency(parser, result); } } } } private void parseDependency(XMLEventReader parser, Pom result) throws XMLStreamException { PomDependency pomDependency = new PomDependency(); eventloop: while (true) { XMLEvent event = parser.nextEvent(); if (event.isEndElement()) { EndElement endElement = event.asEndElement(); String elementNameLocalPart = endElement.getName().getLocalPart(); if (elementNameLocalPart.equals(DEPENDENCY_TAG)) { result.addChild(pomDependency); break eventloop; } } if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String elementNameLocalPart = startElement.getName().getLocalPart(); if (elementNameLocalPart.equals(GROUPID_TAG)) { pomDependency.setGroupId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(ARTIFACTID_TAG)) { pomDependency.setArtifactId(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(VERSION_TAG)) { pomDependency.setVersion(parseTagTextContent(parser)); continue; } if (elementNameLocalPart.equals(SCOPE_TAG)) { String tagContent = parseTagTextContent(parser); tagContent = tagContent == null ? "compile" : tagContent; pomDependency.setScope(Scope.valueOf(tagContent.toUpperCase())); continue; } if (elementNameLocalPart.equals(CLASSIFIER_TAG)) { pomDependency.setClassifier(parseTagTextContent(parser)); continue; } } } } private String parseTagTextContent(XMLEventReader parser) throws XMLStreamException { String result = null; XMLEvent event = parser.nextEvent(); if (event.isCharacters()) { Characters characters = event.asCharacters(); result = characters.getData(); } return result; } /** * @see org.org.eclipse.dws.core.internal.xml.IXmlPomFileBinder#parsePomFile(java.lang.String) */ public Pom parsePomFile(String input) throws BindingException { InputStream inputStream = new ByteArrayInputStream(input.getBytes()); return parsePomFile(inputStream); } public String updatePom(InputStream pomStream, Set<PomDependency> pomDependencies, String pomEncoding) throws BindingException { String result = null; ByteArrayOutputStream outputStream = null; XMLEventReader reader = null; XMLEventWriter writer = null; XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); XMLEventFactory eventFactory = XMLEventFactory.newInstance(); try { outputStream = new ByteArrayOutputStream(); reader = inputFactory.createXMLEventReader(pomStream); writer = outputFactory.createXMLEventWriter(outputStream); boolean containsDependenciesTag = false; while (true) { XMLEvent event = reader.nextEvent(); if (event.getEventType() == XMLStreamConstants.START_ELEMENT && event.asStartElement().getName().getLocalPart().equals(new QName(DEPENDENCIES_TAG).getLocalPart())) { containsDependenciesTag = true; writer.add(event); addPomDependenciesToExistingDependenciesTag(reader, writer, event, eventFactory, pomDependencies); } else { if (!containsDependenciesTag) { if (event.getEventType() == XMLStreamConstants.END_ELEMENT) { QName elementName = event.asEndElement().getName(); if (elementName.getLocalPart().equals(new QName(PROJECT_TAG).getLocalPart())) { createNewDependenciesTagAndAddPomDependencies(reader, writer, event, eventFactory, pomDependencies); } } } writer.add(event); writer.flush(); } if (!reader.hasNext()) break; } reader.close(); reader = null; writer.close(); writer = null; pomStream.close(); pomStream = null; outputStream.close(); result = outputStream.toString(pomEncoding); outputStream = null; } catch (Exception e) { throw new BindingException(); } finally { try { if (pomStream != null) { pomStream.close(); } if (outputStream != null) { outputStream.close(); } if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } } catch (Exception e) { // trapping exceptions there } finally { } } return result; } /** * @see org.org.eclipse.dws.core.internal.xml.IXmlPomFileBinder#updatePom(java.io.InputStream, java.util.Set, java.lang.String) */ public String updatePom(String input, Set<PomDependency> pomDependencies, String pomEncoding) throws BindingException { return null; } /** * Creates the new dependencies tag and add pom dependencies. * * @param reader * the reader * @param writer * the writer * @param event * the event * @param eventFactory * the event factory * @param pomDependencies * the pom dependencies * * @throws XMLStreamException * the XML stream exception */ private static void createNewDependenciesTagAndAddPomDependencies(XMLEventReader reader, XMLEventWriter writer, XMLEvent event, XMLEventFactory eventFactory, Set<PomDependency> pomDependencies) throws XMLStreamException { writer.add(eventFactory.createStartElement(new QName(DEPENDENCIES_TAG), null, null)); addPomDependenciesToExistingDependenciesTag(reader, writer, event, eventFactory, pomDependencies); writer.add(eventFactory.createIgnorableSpace("\n")); writer.add(eventFactory.createEndElement(new QName(DEPENDENCIES_TAG), null)); writer.add(eventFactory.createIgnorableSpace("\n")); } /** * Adds the pom dependencies to existing dependencies tag. * * @param reader * the reader * @param writer * the writer * @param event * the event * @param eventFactory * the event factory * @param pomDependencies * the pom dependencies * * @throws XMLStreamException * the XML stream exception */ private static void addPomDependenciesToExistingDependenciesTag(XMLEventReader reader, XMLEventWriter writer, XMLEvent event, XMLEventFactory eventFactory, Set<PomDependency> pomDependencies) throws XMLStreamException { for (PomDependency pomDependency : pomDependencies) { writer.add(eventFactory.createIgnorableSpace("\n\t")); writer.add(eventFactory.createStartElement(new QName(DEPENDENCY_TAG), null, null)); addTagWithContent(writer, eventFactory, "\n\t\t", new QName(GROUPID_TAG), pomDependency.getGroupId()); addTagWithContent(writer, eventFactory, "\n\t\t", new QName(ARTIFACTID_TAG), pomDependency.getArtifactId()); addTagWithContent(writer, eventFactory, "\n\t\t", new QName(VERSION_TAG), pomDependency.getVersion()); addTagWithContent(writer, eventFactory, "\n\t\t", new QName(CLASSIFIER_TAG), pomDependency.getClassifier()); addTagWithContent(writer, eventFactory, "\n\t\t", new QName(SCOPE_TAG), pomDependency.getScope().name().toLowerCase()); addTagWithContent(writer, eventFactory, "\n\t\t", new QName(OPTIONAL_TAG), pomDependency.isOptional().toString()); writer.add(eventFactory.createIgnorableSpace("\n\t")); writer.add(eventFactory.createEndElement(new QName(DEPENDENCY_TAG), null)); } } /** * Adds the tag with content. * * @param writer * the writer * @param eventFactory * the event factory * @param ignorableSpace * the ignorable space * @param qName * the q name * @param content * the content * * @throws XMLStreamException * the XML stream exception */ private static void addTagWithContent(XMLEventWriter writer, XMLEventFactory eventFactory, String ignorableSpace, QName qName, String content) throws XMLStreamException { if (content != null) { writer.add(eventFactory.createIgnorableSpace(ignorableSpace)); writer.add(eventFactory.createStartElement(qName, null, null)); writer.add(eventFactory.createCharacters(content)); writer.add(eventFactory.createEndElement(qName, null)); } } }