| /******************************************************************************* |
| * Copyright (c) 2004, 2007 Mylyn project committers and others. |
| * 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 |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.bugzilla.core; |
| |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.eclipse.mylyn.monitor.core.StatusHandler; |
| import org.eclipse.mylyn.tasks.core.AbstractAttributeFactory; |
| import org.eclipse.mylyn.tasks.core.RepositoryAttachment; |
| import org.eclipse.mylyn.tasks.core.RepositoryTaskAttribute; |
| import org.eclipse.mylyn.tasks.core.RepositoryTaskData; |
| import org.eclipse.mylyn.tasks.core.TaskComment; |
| import org.eclipse.mylyn.web.core.HtmlStreamTokenizer; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Parser for xml bugzilla reports. |
| * |
| * @author Rob Elves |
| */ |
| public class SaxBugReportContentHandler extends DefaultHandler { |
| |
| private static final String COMMENT_ATTACHMENT_STRING = "Created an attachment (id="; |
| |
| private StringBuffer characters; |
| |
| private TaskComment taskComment; |
| |
| private final Map<String, TaskComment> attachIdToComment = new HashMap<String, TaskComment>(); |
| |
| private int commentNum = 0; |
| |
| private RepositoryAttachment attachment; |
| |
| private RepositoryTaskData repositoryTaskData; |
| |
| private String errorMessage = null; |
| |
| private AbstractAttributeFactory attributeFactory; |
| |
| public SaxBugReportContentHandler(AbstractAttributeFactory factory, RepositoryTaskData taskData) { |
| this.attributeFactory = factory; |
| this.repositoryTaskData = taskData; |
| } |
| |
| public boolean errorOccurred() { |
| return errorMessage != null; |
| } |
| |
| public String getErrorMessage() { |
| return errorMessage; |
| } |
| |
| public RepositoryTaskData getReport() { |
| return repositoryTaskData; |
| } |
| |
| @Override |
| public void characters(char[] ch, int start, int length) throws SAXException { |
| characters.append(ch, start, length); |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| } |
| |
| @Override |
| public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { |
| characters = new StringBuffer(); |
| BugzillaReportElement tag = BugzillaReportElement.UNKNOWN; |
| try { |
| tag = BugzillaReportElement.valueOf(localName.trim().toUpperCase(Locale.ENGLISH)); |
| } catch (RuntimeException e) { |
| if (e instanceof IllegalArgumentException) { |
| // ignore unrecognized tags |
| return; |
| } |
| throw e; |
| } |
| switch (tag) { |
| case BUGZILLA: |
| // Note: here we can get the bugzilla version if necessary |
| break; |
| case BUG: |
| if (attributes != null && (attributes.getValue("error") != null)) { |
| errorMessage = attributes.getValue("error"); |
| } |
| break; |
| case LONG_DESC: |
| taskComment = new TaskComment(attributeFactory, commentNum++); |
| break; |
| case ATTACHMENT: |
| attachment = new RepositoryAttachment(attributeFactory); |
| if (attributes != null) { |
| if ("1".equals(attributes.getValue(BugzillaReportElement.IS_OBSOLETE.getKeyString()))) { |
| attachment.addAttribute(BugzillaReportElement.IS_OBSOLETE.getKeyString(), |
| attributeFactory.createAttribute(BugzillaReportElement.IS_OBSOLETE.getKeyString())); |
| attachment.setObsolete(true); |
| } |
| if ("1".equals(attributes.getValue(BugzillaReportElement.IS_PATCH.getKeyString()))) { |
| attachment.setPatch(true); |
| } |
| } |
| break; |
| } |
| |
| } |
| |
| @Override |
| public void endElement(String uri, String localName, String qName) throws SAXException { |
| |
| String parsedText = HtmlStreamTokenizer.unescape(characters.toString()); |
| |
| BugzillaReportElement tag = BugzillaReportElement.UNKNOWN; |
| try { |
| tag = BugzillaReportElement.valueOf(localName.trim().toUpperCase(Locale.ENGLISH)); |
| } catch (RuntimeException e) { |
| if (e instanceof IllegalArgumentException) { |
| // ignore unrecognized tags |
| return; |
| } |
| throw e; |
| } |
| switch (tag) { |
| case BUG_ID: { |
| try { |
| if (!repositoryTaskData.getId().equals(parsedText)) { |
| errorMessage = "Requested report number does not match returned report number."; |
| } |
| } catch (Exception e) { |
| errorMessage = "Bug id from server did not match requested id."; |
| } |
| |
| RepositoryTaskAttribute attr = repositoryTaskData.getAttribute(tag.getKeyString()); |
| if (attr == null) { |
| attr = attributeFactory.createAttribute(tag.getKeyString()); |
| repositoryTaskData.addAttribute(tag.getKeyString(), attr); |
| } |
| attr.setValue(parsedText); |
| break; |
| } |
| |
| // Comment attributes |
| case WHO: |
| case BUG_WHEN: |
| if (taskComment != null) { |
| RepositoryTaskAttribute attr = attributeFactory.createAttribute(tag.getKeyString()); |
| attr.setValue(parsedText); |
| taskComment.addAttribute(tag.getKeyString(), attr); |
| } |
| break; |
| case THETEXT: |
| if (taskComment != null) { |
| RepositoryTaskAttribute attr = attributeFactory.createAttribute(tag.getKeyString()); |
| attr.setValue(parsedText); |
| taskComment.addAttribute(tag.getKeyString(), attr); |
| |
| // Check for attachment |
| parseAttachment(taskComment, parsedText); |
| } |
| break; |
| case LONG_DESC: |
| if (taskComment != null) { |
| if (taskComment.getNumber() == 0) { |
| repositoryTaskData.setAttributeValue(RepositoryTaskAttribute.DESCRIPTION, taskComment.getText()); |
| break; |
| } |
| repositoryTaskData.addComment(taskComment); |
| } |
| break; |
| |
| // Attachment attributes |
| case ATTACHID: |
| case DATE: |
| case DESC: |
| case FILENAME: |
| case CTYPE: |
| case TYPE: |
| if (attachment != null) { |
| RepositoryTaskAttribute attr = attributeFactory.createAttribute(tag.getKeyString()); |
| attr.setValue(parsedText); |
| attachment.addAttribute(tag.getKeyString(), attr); |
| } |
| break; |
| case DATA: |
| break; |
| case ATTACHMENT: |
| if (attachment != null) { |
| repositoryTaskData.addAttachment(attachment); |
| } |
| break; |
| |
| // IGNORED ELEMENTS |
| // case REPORTER_ACCESSIBLE: |
| // case CLASSIFICATION_ID: |
| // case CLASSIFICATION: |
| // case CCLIST_ACCESSIBLE: |
| // case EVERCONFIRMED: |
| case BUGZILLA: |
| break; |
| case BUG: |
| // Reached end of bug. Need to set LONGDESCLENGTH to number of |
| // comments |
| RepositoryTaskAttribute numCommentsAttribute = repositoryTaskData.getAttribute(BugzillaReportElement.LONGDESCLENGTH.getKeyString()); |
| if (numCommentsAttribute == null) { |
| numCommentsAttribute = attributeFactory.createAttribute(BugzillaReportElement.LONGDESCLENGTH.getKeyString()); |
| numCommentsAttribute.setValue("" + repositoryTaskData.getComments().size()); |
| repositoryTaskData.addAttribute(BugzillaReportElement.LONGDESCLENGTH.getKeyString(), |
| numCommentsAttribute); |
| } else { |
| numCommentsAttribute.setValue("" + repositoryTaskData.getComments().size()); |
| } |
| |
| // Set the creator name on all attachments |
| for (RepositoryAttachment attachment : repositoryTaskData.getAttachments()) { |
| TaskComment taskComment = attachIdToComment.get(attachment.getId()); |
| if (taskComment != null) { |
| attachment.setCreator(taskComment.getAuthor()); |
| } |
| attachment.setAttributeValue(RepositoryTaskAttribute.ATTACHMENT_URL, |
| repositoryTaskData.getRepositoryUrl() + IBugzillaConstants.URL_GET_ATTACHMENT_SUFFIX |
| + attachment.getId()); |
| attachment.setRepositoryKind(repositoryTaskData.getRepositoryKind()); |
| attachment.setRepositoryUrl(repositoryTaskData.getRepositoryUrl()); |
| attachment.setTaskId(repositoryTaskData.getId()); |
| } |
| break; |
| |
| case BLOCKED: |
| case DEPENDSON: |
| RepositoryTaskAttribute dependancyAttribute = repositoryTaskData.getAttribute(tag.getKeyString()); |
| if (dependancyAttribute == null) { |
| dependancyAttribute = attributeFactory.createAttribute(tag.getKeyString()); |
| dependancyAttribute.setValue(parsedText); |
| repositoryTaskData.addAttribute(tag.getKeyString(), dependancyAttribute); |
| } else { |
| if (dependancyAttribute.getValue().equals("")) { |
| dependancyAttribute.setValue(parsedText); |
| } else { |
| dependancyAttribute.setValue(dependancyAttribute.getValue() + ", " + parsedText); |
| } |
| } |
| break; |
| case DELTA_TS: |
| RepositoryTaskAttribute delta_ts_attribute = repositoryTaskData.getAttribute(tag.getKeyString()); |
| if (delta_ts_attribute == null) { |
| delta_ts_attribute = attributeFactory.createAttribute(tag.getKeyString()); |
| repositoryTaskData.addAttribute(tag.getKeyString(), delta_ts_attribute); |
| } |
| delta_ts_attribute.setValue(BugzillaClient.stripTimeZone(parsedText)); |
| break; |
| default: |
| RepositoryTaskAttribute attribute = repositoryTaskData.getAttribute(tag.getKeyString()); |
| if (attribute == null) { |
| attribute = attributeFactory.createAttribute(tag.getKeyString()); |
| repositoryTaskData.addAttribute(tag.getKeyString(), attribute); |
| } |
| attribute.addValue(parsedText); |
| break; |
| } |
| |
| } |
| |
| /** determines attachment id from comment */ |
| private void parseAttachment(TaskComment taskComment, String commentText) { |
| |
| String attachmentID = ""; |
| |
| if (commentText.startsWith(COMMENT_ATTACHMENT_STRING)) { |
| int endIndex = commentText.indexOf(")"); |
| if (endIndex > 0 && endIndex < commentText.length()) { |
| attachmentID = commentText.substring(COMMENT_ATTACHMENT_STRING.length(), endIndex); |
| if (!attachmentID.equals("")) { |
| taskComment.setHasAttachment(true); |
| taskComment.setAttachmentId(attachmentID); |
| attachIdToComment.put(attachmentID, taskComment); |
| } |
| } |
| } |
| } |
| |
| } |