blob: cea101f57d41c21eeb2629e41258eec2e81cd814 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.plugins.jira;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.issues.Issue;
import org.codehaus.plexus.util.IOUtil;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
/**
* XML parser that extracts <code>Issue</code>s from JIRA. This works on an XML file downloaded from JIRA and creates a
* <code>List</code> of issues that is exposed to the user of the class.
*
* @version $Id$
*/
public class JiraXML extends DefaultHandler {
private final List<Issue> issueList;
private final StringBuilder currentElement = new StringBuilder(1024);
private String currentParent = "";
private final String datePattern;
private Issue issue;
private String jiraVersion = null;
private final Log log;
private SimpleDateFormat sdf;
/**
* @param log not null.
* @param datePattern may be null.
* @since 2.4
*/
public JiraXML(Log log, String datePattern) {
this.log = log;
this.datePattern = datePattern;
if (datePattern == null) {
sdf = null;
} else {
// @todo Do we need to be able to configure the locale of the JIRA server as well?
sdf = new SimpleDateFormat(datePattern, Locale.ENGLISH);
}
this.issueList = new ArrayList<>(16);
}
/**
* Parse the given xml file. The list of issues can then be retrieved with {@link #getIssueList()}.
*
* @param xmlPath the file to pares.
* @throws MojoExecutionException in case of errors.
* @since 2.4
*/
public void parseXML(File xmlPath) throws MojoExecutionException {
InputStream xmlStream = null;
try {
xmlStream = new FileInputStream(xmlPath);
InputSource inputSource = new InputSource(xmlStream);
parse(inputSource);
} catch (FileNotFoundException e) {
throw new MojoExecutionException("Failed to open JIRA XML file " + xmlPath, e);
} finally {
IOUtil.close(xmlStream);
}
}
void parse(InputSource xmlSource) throws MojoExecutionException {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
saxParser.parse(xmlSource, this);
} catch (Throwable t) {
throw new MojoExecutionException("Failed to parse JIRA XML.", t);
}
}
public void startElement(String namespaceURI, String sName, String qName, Attributes attrs) {
switch (qName) {
case "item":
issue = new Issue();
currentParent = "item";
break;
case "key":
String id = attrs.getValue("id");
if (id != null) {
issue.setId(id.trim());
}
break;
case "build-info":
currentParent = "build-info";
break;
default:
// none
}
}
public void endElement(String namespaceURI, String sName, String qName) {
if (qName.equals("item")) {
issueList.add(issue);
currentParent = "";
} else if (qName.equals("key")) {
issue.setKey(currentElement.toString().trim());
} else if (qName.equals("summary")) {
issue.setSummary(currentElement.toString().trim());
} else if (qName.equals("type")) {
issue.setType(currentElement.toString().trim());
} else if (qName.equals("link") && currentParent.equals("item")) {
issue.setLink(currentElement.toString().trim());
} else if (qName.equals("priority")) {
issue.setPriority(currentElement.toString().trim());
} else if (qName.equals("status")) {
issue.setStatus(currentElement.toString().trim());
} else if (qName.equals("resolution")) {
issue.setResolution(currentElement.toString().trim());
} else if (qName.equals("assignee")) {
issue.setAssignee(currentElement.toString().trim());
} else if (qName.equals("reporter")) {
issue.setReporter(currentElement.toString().trim());
} else if (qName.equals("version") && currentParent.equals("item")) {
issue.setVersion(currentElement.toString().trim());
} else if (qName.equals("version") && currentParent.equals("build-info")) {
jiraVersion = currentElement.toString().trim();
} else if (qName.equals("fixVersion")) {
issue.addFixVersion(currentElement.toString().trim());
} else if (qName.equals("component")) {
issue.addComponent(currentElement.toString().trim());
} else if (qName.equals("comment")) {
issue.addComment(currentElement.toString().trim());
} else if (qName.equals("title") && currentParent.equals("item")) {
issue.setTitle(currentElement.toString().trim());
} else if (qName.equals("created") && currentParent.equals("item") && sdf != null) {
try {
issue.setCreated(sdf.parse(currentElement.toString().trim()));
} catch (ParseException e) {
log.warn("Element \"Created\". " + e.getMessage() + ". Using the pattern \"" + datePattern + "\"");
}
} else if (qName.equals("updated") && currentParent.equals("item") && sdf != null) {
try {
issue.setUpdated(sdf.parse(currentElement.toString().trim()));
} catch (ParseException e) {
log.warn("Element \"Updated\". " + e.getMessage() + ". Using the pattern \"" + datePattern + "\"");
}
}
currentElement.setLength(0);
}
public void characters(char[] buf, int offset, int len) {
currentElement.append(buf, offset, len);
}
public List<Issue> getIssueList() {
return Collections.unmodifiableList(this.issueList);
}
public String getJiraVersion() {
return jiraVersion;
}
}