### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.bugzilla.core Index: src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaLanguageSettings.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaLanguageSettings.java,v retrieving revision 1.4 diff -u -r1.4 BugzillaLanguageSettings.java --- src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaLanguageSettings.java 5 Dec 2007 02:57:16 -0000 1.4 +++ src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaLanguageSettings.java 4 Jan 2008 20:55:41 -0000 @@ -38,6 +38,8 @@ public static final String COMMAND_CHANGES_SUBMITTED = "changes_submitted"; + public static final String COMMAND_ERROR_CONFIRM_MATCH = "error_confirm_match"; + private Map> languageAttributes = new LinkedHashMap>(); public BugzillaLanguageSettings(String languageName) { Index: src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java,v retrieving revision 1.35 diff -u -r1.35 BugzillaTaskDataHandler.java --- src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java 29 Nov 2007 19:29:40 -0000 1.35 +++ src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java 4 Jan 2008 20:55:41 -0000 @@ -22,6 +22,7 @@ import org.eclipse.mylyn.internal.bugzilla.core.IBugzillaConstants.BUGZILLA_RESOLUTION_3_0; import org.eclipse.mylyn.monitor.core.StatusHandler; import org.eclipse.mylyn.tasks.core.AbstractAttributeFactory; +import org.eclipse.mylyn.tasks.core.AbstractPostTaskDataResult; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.AbstractTaskDataHandler; import org.eclipse.mylyn.tasks.core.RepositoryOperation; @@ -359,4 +360,31 @@ return true; } + @Override + public boolean usePostTaskDataNewAPI() { + return true; + } + + public void postTaskData(TaskRepository repository, RepositoryTaskData taskData, IProgressMonitor monitor, AbstractPostTaskDataResult abstractPostTaskDataResult) + throws CoreException { +try { + BugzillaClient client = connector.getClientManager().getClient(repository); + try { + client.postTaskData(taskData, abstractPostTaskDataResult); + } catch (CoreException e) { + // TODO: Move retry handling into client + if (e.getStatus().getCode() == RepositoryStatus.ERROR_REPOSITORY_LOGIN) { + client.postTaskData(taskData, abstractPostTaskDataResult); + } else { + throw e; + } + + } + +} catch (IOException e) { + throw new CoreException(new BugzillaStatus(IStatus.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.ERROR_IO, repository.getUrl(), e)); +} +} + } Index: src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java,v retrieving revision 1.93 diff -u -r1.93 BugzillaRepositoryConnector.java --- src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java 11 Dec 2007 02:43:58 -0000 1.93 +++ src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java 4 Jan 2008 20:55:41 -0000 @@ -90,6 +90,7 @@ enSetting.addLanguageAttribute("bad_login", "error"); enSetting.addLanguageAttribute("processed", "processed"); enSetting.addLanguageAttribute("changes_submitted", "Changes submitted"); + enSetting.addLanguageAttribute("error_confirm_match", "confirm match"); languages.add(enSetting); } Index: src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java,v retrieving revision 1.107 diff -u -r1.107 BugzillaClient.java --- src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java 19 Dec 2007 18:45:59 -0000 1.107 +++ src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java 4 Jan 2008 20:55:40 -0000 @@ -42,11 +42,13 @@ import org.apache.commons.httpclient.methods.multipart.PartBase; import org.apache.commons.httpclient.methods.multipart.StringPart; import org.apache.commons.httpclient.params.HttpMethodParams; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.internal.bugzilla.core.history.BugzillaTaskHistoryParser; import org.eclipse.mylyn.internal.bugzilla.core.history.TaskHistory; +import org.eclipse.mylyn.tasks.core.AbstractPostTaskDataResult; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.ITaskAttachment; import org.eclipse.mylyn.tasks.core.ITaskCollector; @@ -1341,4 +1343,335 @@ + " failed. Please verify connection and authentication information.")); } + public void postTaskData(RepositoryTaskData taskData, AbstractPostTaskDataResult abstractPostTaskDataResult) throws IOException, CoreException { + Assert.isNotNull(abstractPostTaskDataResult); + NameValuePair[] formData = null; + String prefix = null; + String prefix2 = null; + String postfix = null; + String postfix2 = null; + + if (taskData == null) { + return; + } else if (taskData.isNew()) { + formData = getPairsForNew(taskData); + prefix = IBugzillaConstants.FORM_PREFIX_BUG_218; + prefix2 = IBugzillaConstants.FORM_PREFIX_BUG_220; + postfix = IBugzillaConstants.FORM_POSTFIX_216; + postfix2 = IBugzillaConstants.FORM_POSTFIX_218; + } else { + formData = getPairsForExisting(taskData); + } + + GzipPostMethod method = null; + try { + if (taskData.isNew()) { + method = postFormData(POST_BUG_CGI, formData); + } else { + method = postFormData(PROCESS_BUG_CGI, formData); + } + + if (method == null) { + throw new IOException("Could not post form, client returned null method."); + } + BufferedReader in = new BufferedReader(new InputStreamReader(method.getResponseBodyAsUnzippedStream(), + method.getRequestCharSet())); + in.mark(40960); + HtmlStreamTokenizer tokenizer = new HtmlStreamTokenizer(in, null); + + boolean existingBugPosted = false; + boolean isTitle = false; + String title = ""; + boolean isBodyDT = false; + boolean isBodyCode = false; + String divIDName = ""; + String dtName = ""; + String codeName = ""; + String bugzillaBody = ""; + + for (Token token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) { + + if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.TITLE + && !((HtmlTag) (token.getValue())).isEndTag()) { + isTitle = true; + continue; + } + + if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.DIV) { + divIDName = ((HtmlTag) (token.getValue())).getAttribute("id"); + } + + if (divIDName != null && divIDName.equals("bugzilla-body")) { + bugzillaBody += token.toString(); + if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.DT + && ((HtmlTag) (token.getValue())).isEndTag()) { + isBodyDT = false; + continue; + } + if (token.getType() == Token.TAG + && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.CODE + && ((HtmlTag) (token.getValue())).isEndTag()) { + isBodyCode = false; + abstractPostTaskDataResult.addResponseData(dtName, codeName); + continue; + } + if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.DT) { + isBodyDT = true; + dtName = ""; + codeName = ""; + } + if (token.getType() == Token.TAG + && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.CODE) { + isBodyCode = true; + codeName = ""; + } + + if (token.getType() != Token.TAG) { + if (isBodyDT) + dtName += ((StringBuffer) token.getValue()).toString().toLowerCase(Locale.ENGLISH) + " "; + if (isBodyCode) + codeName += ((StringBuffer) token.getValue()).toString().toLowerCase(Locale.ENGLISH) + " "; + continue; + } + } + + if (isTitle) { + // get all of the data in the title tag + if (token.getType() != Token.TAG) { + title += ((StringBuffer) token.getValue()).toString().toLowerCase(Locale.ENGLISH) + " "; + continue; + } else if (token.getType() == Token.TAG + && ((HtmlTag) token.getValue()).getTagType() == HtmlTag.Type.TITLE + && ((HtmlTag) token.getValue()).isEndTag()) { + + boolean found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_PROCESSED).iterator(); iterator.hasNext() && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (!taskData.isNew() && found) { + existingBugPosted = true; + } else if (taskData.isNew() && prefix != null && prefix2 != null && postfix != null + && postfix2 != null) { + int startIndex = -1; + int startIndexPrefix = title.toLowerCase(Locale.ENGLISH).indexOf( + prefix.toLowerCase(Locale.ENGLISH)); + int startIndexPrefix2 = title.toLowerCase(Locale.ENGLISH).indexOf( + prefix2.toLowerCase(Locale.ENGLISH)); + + if (startIndexPrefix != -1 || startIndexPrefix2 != -1) { + if (startIndexPrefix != -1) { + startIndex = startIndexPrefix + prefix.length(); + } else { + startIndex = startIndexPrefix2 + prefix2.length(); + } + int stopIndex = title.toLowerCase(Locale.ENGLISH).indexOf( + postfix.toLowerCase(Locale.ENGLISH), startIndex); + if (stopIndex == -1) + stopIndex = title.toLowerCase(Locale.ENGLISH).indexOf( + postfix2.toLowerCase(Locale.ENGLISH), startIndex); + if (stopIndex > -1) { + abstractPostTaskDataResult.setNewTaskID((title.substring(startIndex, stopIndex)).trim()); + } + } + } + isTitle = false; + } + } + } + + if ((!taskData.isNew() && existingBugPosted != true) || (taskData.isNew() && abstractPostTaskDataResult.getNewTaskID() == null)) { + try { + in.reset(); + } catch (IOException e) { + // ignore + } + parseHtmlError(in, abstractPostTaskDataResult); + } + + return; + } catch (ParseException e) { + authenticated = false; + throw new CoreException(new BugzillaStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.ERROR_INTERNAL, "Unable to parse response from " + repositoryUrl.toString() + ".")); + } finally { + if (method != null) { + method.releaseConnection(); + } + } + + } + + /** + * Utility method for determining what potential error has occurred from a bugzilla html reponse page + */ + public void parseHtmlError(BufferedReader in, AbstractPostTaskDataResult abstractPostTaskDataResult) throws IOException, CoreException { + Assert.isNotNull(abstractPostTaskDataResult); + HtmlStreamTokenizer tokenizer = new HtmlStreamTokenizer(in, null); + boolean isTitle = false; + String title = ""; + String body = ""; + + try { + for (Token token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) { + body += token.toString(); + if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.TITLE + && !((HtmlTag) (token.getValue())).isEndTag()) { + isTitle = true; + continue; + } + + if (isTitle) { + // get all of the data in the title tag + if (token.getType() != Token.TAG) { + title += ((StringBuffer) token.getValue()).toString().toLowerCase(Locale.ENGLISH) + " "; + continue; + } else if (token.getType() == Token.TAG + && ((HtmlTag) token.getValue()).getTagType() == HtmlTag.Type.TITLE + && ((HtmlTag) token.getValue()).isEndTag()) { + + boolean found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_ERROR_LOGIN).iterator(); iterator.hasNext() && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (found) { + authenticated = false; + abstractPostTaskDataResult.setErrorStatus("ERROR_REPOSITORY_LOGIN"); + throw new CoreException(new BugzillaStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.ERROR_REPOSITORY_LOGIN, repositoryUrl.toString(), title)); + } + found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_ERROR_COLLISION).iterator(); iterator.hasNext() + && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (found) { + abstractPostTaskDataResult.setErrorStatus("REPOSITORY_COLLISION"); + throw new CoreException(new BugzillaStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.REPOSITORY_COLLISION, repositoryUrl.toString())); + } + found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_ERROR_COMMENT_REQUIRED).iterator(); iterator.hasNext() + && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (found) { + abstractPostTaskDataResult.setErrorStatus("REPOSITORY_COMMENT_REQUIRED"); + throw new CoreException(new BugzillaStatus(Status.INFO, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.REPOSITORY_COMMENT_REQUIRED)); + } + found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_ERROR_LOGGED_OUT).iterator(); iterator.hasNext() + && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (found) { + authenticated = false; + // throw new + // BugzillaException(IBugzillaConstants.LOGGED_OUT); + abstractPostTaskDataResult.setErrorStatus("REPOSITORY_LOGGED_OUT"); + throw new CoreException(new BugzillaStatus(Status.INFO, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.REPOSITORY_LOGGED_OUT, + "You have been logged out. Please retry operation.")); + } + found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_ERROR_CONFIRM_MATCH).iterator(); iterator.hasNext() + && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (found) { + abstractPostTaskDataResult.setErrorStatus("COMMAND_ERROR_CONFIRM_MATCH"); + try { + in.reset(); + } catch (IOException e) { + // ignore + } + parseResultConfirmMatch(in, abstractPostTaskDataResult); + } + found = false; + for (Iterator iterator = bugzillaLanguageSettings.getResponseForCommand( + BugzillaLanguageSettings.COMMAND_CHANGES_SUBMITTED).iterator(); iterator.hasNext() + && !found;) { + String value = iterator.next().toLowerCase(Locale.ENGLISH); + found = found || title.indexOf(value) != -1; + } + if (found) { + return; + } + isTitle = false; + } + } + } + + abstractPostTaskDataResult.setErrorStatus("A repository error has occurred."); + throw new CoreException(RepositoryStatus.createHtmlStatus(repositoryUrl.toString(), IStatus.INFO, + BugzillaCorePlugin.PLUGIN_ID, RepositoryStatus.ERROR_REPOSITORY, + "A repository error has occurred.", body)); + + } catch (ParseException e) { + authenticated = false; + abstractPostTaskDataResult.setErrorStatus("ERROR_INTERNAL: Unable to parse response from " + repositoryUrl.toString() + "."); + throw new CoreException(new BugzillaStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.ERROR_INTERNAL, "Unable to parse response from " + repositoryUrl.toString() + ".")); + } finally { + in.close(); + } + } + + public void parseResultConfirmMatch(BufferedReader in, AbstractPostTaskDataResult postResult) throws IOException, + CoreException { + HtmlStreamTokenizer tokenizer = new HtmlStreamTokenizer(in, null); + + boolean isSelect = false; + String select = ""; + String body = ""; + String name = ""; + String value = ""; + try { + for (Token token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) { + body += token.toString(); + if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.SELECT + && !((HtmlTag) (token.getValue())).isEndTag()) { + isSelect = true; + select += token.toString().toLowerCase(Locale.ENGLISH); + name = ((HtmlTag) (token.getValue())).getAttribute("id"); + continue; + } + + if (isSelect) { + if (token.getType() == Token.TAG + && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.OPTION + && !((HtmlTag) (token.getValue())).isEndTag()) { + value = ((HtmlTag) (token.getValue())).getAttribute("value"); + postResult.addResponseData(name, value); + } + if (token.getType() == Token.TAG + && ((HtmlTag) token.getValue()).getTagType() == HtmlTag.Type.SELECT + && ((HtmlTag) token.getValue()).isEndTag()) { + isSelect = false; + } + } + } + postResult.setErrorStatus("ERROR_CONFIRM_MATCH"); + throw new CoreException(new BugzillaStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.ERROR_CONFIRM_MATCH, repositoryUrl.toString(), "confirm match")); + } catch (ParseException e) { + throw new CoreException(new BugzillaStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID, + RepositoryStatus.ERROR_INTERNAL, "Unable to parse response from " + repositoryUrl.toString() + ".")); + } finally { + in.close(); + } + } + } #P org.eclipse.mylyn.tasks.core Index: src/org/eclipse/mylyn/tasks/core/AbstractTaskDataHandler.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractTaskDataHandler.java,v retrieving revision 1.10 diff -u -r1.10 AbstractTaskDataHandler.java --- src/org/eclipse/mylyn/tasks/core/AbstractTaskDataHandler.java 21 Nov 2007 22:39:09 -0000 1.10 +++ src/org/eclipse/mylyn/tasks/core/AbstractTaskDataHandler.java 4 Jan 2008 20:55:43 -0000 @@ -52,6 +52,26 @@ throws CoreException; /** + * API-3.0 remove when API change is done + * + * @since 2.3 + */ + public boolean usePostTaskDataNewAPI() { + return false; + } + + /** + * API-3.0 make abstract if we can switch from postTaskData + * + * AbstractRepositoryTaskEditor submitToRepository use old or new style + * + * @since 2.3 + */ + public void postTaskData(TaskRepository repository, RepositoryTaskData taskData, IProgressMonitor monitor, + AbstractPostTaskDataResult abstractPostTaskDataResult) throws CoreException { + } + + /** * @param repositoryUrl * @param repositoryKind * @param taskKind Index: src/org/eclipse/mylyn/tasks/core/RepositoryStatus.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/RepositoryStatus.java,v retrieving revision 1.7 diff -u -r1.7 RepositoryStatus.java --- src/org/eclipse/mylyn/tasks/core/RepositoryStatus.java 26 Jun 2007 01:16:32 -0000 1.7 +++ src/org/eclipse/mylyn/tasks/core/RepositoryStatus.java 4 Jan 2008 20:55:43 -0000 @@ -46,6 +46,8 @@ public final static int ERROR_INTERNAL = 7; + public final static int ERROR_CONFIRM_MATCH = 13; + private String htmlMessage; protected String repositoryUrl; Index: src/org/eclipse/mylyn/tasks/core/AbstractPostTaskDataResult.java =================================================================== RCS file: src/org/eclipse/mylyn/tasks/core/AbstractPostTaskDataResult.java diff -N src/org/eclipse/mylyn/tasks/core/AbstractPostTaskDataResult.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/tasks/core/AbstractPostTaskDataResult.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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.tasks.core; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class AbstractPostTaskDataResult { + + private String newTaskID; + + private String errorStatus; + + private Map> responseData = new LinkedHashMap>(); + + public String getNewTaskID() { + return newTaskID; + } + + public void setNewTaskID(String newTaskID) { + this.newTaskID = newTaskID; + } + + public String getErrorStatus() { + return errorStatus; + } + + public void setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + } + + public Map> getResponseData() { + return responseData; + } + + public void setResponseData(Map> responseData) { + this.responseData = responseData; + } + + public void addResponseData(String name, String response) { + List responseList = responseData.get(name); + if (responseList == null) { + responseList = new LinkedList(); + responseData.put(name.toLowerCase(), responseList); + } + responseList.add(response); + } + + public void reset() { + newTaskID = null; + errorStatus = null; + responseData.clear(); + } + +} #P org.eclipse.mylyn.bugzilla.ui Index: src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditor.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditor.java,v retrieving revision 1.83 diff -u -r1.83 BugzillaTaskEditor.java --- src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditor.java 21 Nov 2007 22:14:56 -0000 1.83 +++ src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditor.java 4 Jan 2008 20:55:45 -0000 @@ -12,12 +12,18 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.fieldassist.ContentProposalAdapter; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaCorePlugin; @@ -29,6 +35,7 @@ import org.eclipse.mylyn.monitor.core.StatusHandler; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.RepositoryOperation; +import org.eclipse.mylyn.tasks.core.RepositoryStatus; import org.eclipse.mylyn.tasks.core.RepositoryTaskAttribute; import org.eclipse.mylyn.tasks.ui.DatePicker; import org.eclipse.mylyn.tasks.ui.TasksUiPlugin; @@ -310,7 +317,8 @@ @Override protected boolean hasContentAssist(RepositoryTaskAttribute attribute) { - return BugzillaReportElement.NEWCC.getKeyString().equals(attribute.getId()); + return BugzillaReportElement.NEWCC.getKeyString().equals(attribute.getId()) + || BugzillaReportElement.QA_CONTACT.getKeyString().equals(attribute.getId()); } @Override @@ -638,8 +646,12 @@ } } }); - ContentAssistCommandAdapter adapter = applyContentAssist(assignedTo, + ContentAssistObject contentAssistObject = applyContentAssistWithReturnObject(assignedTo, createContentProposalProvider(assignedAttribute)); + if (personProposalMap.get(assignedAttribute.getId()) == null) { + personProposalMap.put(assignedAttribute.getId(), contentAssistObject); + } + ContentAssistCommandAdapter adapter = contentAssistObject.getCommandAdapter(); ILabelProvider propsalLabelProvider = createProposalLabelProvider(assignedAttribute); if (propsalLabelProvider != null) { adapter.setLabelProvider(propsalLabelProvider); @@ -672,4 +684,63 @@ return super.attributeChanged(attribute); } + @Override + protected IStatus handleSubmitError(final CoreException exception) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + String confirmMatchMessage = "Confirm match for field"; + String confirmMatchMessageFields = " '"; + int confirmMatchCount = 0; + if ( form != null && !form.isDisposed()) { + if (exception.getStatus().getCode() == RepositoryStatus.ERROR_IO) { + parentEditor.setMessage(ERROR_NOCONNECTIVITY, IMessageProvider.ERROR); + StatusHandler.log(exception.getStatus()); + } else if (exception.getStatus().getCode() == RepositoryStatus.REPOSITORY_COMMENT_REQUIRED) { + StatusHandler.displayStatus("Comment required", exception.getStatus()); + if (!getManagedForm().getForm().isDisposed() && newCommentTextViewer != null + && !newCommentTextViewer.getControl().isDisposed()) { + newCommentTextViewer.getControl().setFocus(); + } + } else if (exception.getStatus().getCode() == RepositoryStatus.ERROR_REPOSITORY_LOGIN) { + if (TasksUiUtil.openEditRepositoryWizard(repository) == MessageDialog.OK) { + submitToRepository(); + return; + } + } else if (exception.getStatus().getCode() == RepositoryStatus.ERROR_CONFIRM_MATCH) { +// StatusHandler.displayStatus("Confirm Match", exception.getStatus()); + taskDataResult.getResponseData().keySet(); + FieldDecoration contentProposalImage = FieldDecorationRegistry.getDefault().getFieldDecoration( + FieldDecorationRegistry.DEC_ERROR); + Iterator iter = taskDataResult.getResponseData().keySet().iterator(); + while (iter.hasNext()) { + String key = iter.next(); + RepositoryTaskAttribute attribute = taskData.getAttribute(key); + + ContentAssistObject contentAssistObject = personProposalMap.get(key); + if (contentAssistObject != null) { + contentAssistObject.getCommandAdapter().getControl().setFocus(); + contentAssistObject.getControlDecoration().setImage(contentProposalImage.getImage()); + contentAssistObject.getControlDecoration().setShowOnlyOnFocus(false); + contentAssistObject.setNewContentProposalProvider(createUserMatchContentProposalProvider(taskDataResult.getResponseData() + .get(key))); + } + if (confirmMatchCount++ > 0) + confirmMatchMessageFields += " and '"; + confirmMatchMessageFields += attribute.getName() + "'"; + } + if (confirmMatchCount++ > 1) + confirmMatchMessage += "s"; + confirmMatchMessage += confirmMatchMessageFields; + parentEditor.setMessage(confirmMatchMessage, IMessageProvider.ERROR); + } else { + StatusHandler.displayStatus("Submit failed", exception.getStatus()); + } + setGlobalBusy(false); + } + } + + }); + return Status.OK_STATUS; + } + } Index: src/org/eclipse/mylyn/internal/bugzilla/ui/editor/NewBugzillaTaskEditor.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/NewBugzillaTaskEditor.java,v retrieving revision 1.46 diff -u -r1.46 NewBugzillaTaskEditor.java --- src/org/eclipse/mylyn/internal/bugzilla/ui/editor/NewBugzillaTaskEditor.java 18 Nov 2007 20:01:32 -0000 1.46 +++ src/org/eclipse/mylyn/internal/bugzilla/ui/editor/NewBugzillaTaskEditor.java 4 Jan 2008 20:55:45 -0000 @@ -192,8 +192,12 @@ } } }); - ContentAssistCommandAdapter adapter = applyContentAssist(assignedTo, + ContentAssistObject contentAssistObject = applyContentAssistWithReturnObject(assignedTo, createContentProposalProvider(assignedAttribute)); + if (personProposalMap.get(assignedAttribute.getId()) == null) { + personProposalMap.put(assignedAttribute.getId(), contentAssistObject); + } + ContentAssistCommandAdapter adapter = contentAssistObject.getCommandAdapter(); ILabelProvider propsalLabelProvider = createProposalLabelProvider(assignedAttribute); if (propsalLabelProvider != null) { adapter.setLabelProvider(propsalLabelProvider); Index: plugin.xml =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.ui/plugin.xml,v retrieving revision 1.94 diff -u -r1.94 plugin.xml --- plugin.xml 5 Dec 2007 02:57:17 -0000 1.94 +++ plugin.xml 4 Jan 2008 20:55:44 -0000 @@ -57,6 +57,7 @@ + #P org.eclipse.mylyn.tasks.ui Index: src/org/eclipse/mylyn/tasks/ui/editors/AbstractRepositoryTaskEditor.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractRepositoryTaskEditor.java,v retrieving revision 1.253 diff -u -r1.253 AbstractRepositoryTaskEditor.java --- src/org/eclipse/mylyn/tasks/ui/editors/AbstractRepositoryTaskEditor.java 15 Dec 2007 04:03:25 -0000 1.253 +++ src/org/eclipse/mylyn/tasks/ui/editors/AbstractRepositoryTaskEditor.java 4 Jan 2008 20:55:48 -0000 @@ -18,6 +18,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; @@ -73,6 +74,7 @@ import org.eclipse.mylyn.internal.tasks.ui.PersonProposalProvider; import org.eclipse.mylyn.internal.tasks.ui.TaskListColorsAndFonts; import org.eclipse.mylyn.internal.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.internal.tasks.ui.UserMatchPersonProposalProvider; import org.eclipse.mylyn.internal.tasks.ui.actions.AbstractTaskEditorAction; import org.eclipse.mylyn.internal.tasks.ui.actions.AttachAction; import org.eclipse.mylyn.internal.tasks.ui.actions.AttachScreenshotAction; @@ -94,6 +96,7 @@ import org.eclipse.mylyn.internal.tasks.ui.views.ResetRepositoryConfigurationAction; import org.eclipse.mylyn.monitor.core.DateUtil; import org.eclipse.mylyn.monitor.core.StatusHandler; +import org.eclipse.mylyn.tasks.core.AbstractPostTaskDataResult; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.AbstractTaskCategory; @@ -205,7 +208,7 @@ */ public abstract class AbstractRepositoryTaskEditor extends TaskFormPage { - private static final String ERROR_NOCONNECTIVITY = "Unable to submit at this time. Check connectivity and retry."; + protected static final String ERROR_NOCONNECTIVITY = "Unable to submit at this time. Check connectivity and retry."; private static final String LABEL_HISTORY = "History"; @@ -237,7 +240,7 @@ private FormToolkit toolkit; - private ScrolledForm form; + protected ScrolledForm form; protected TaskRepository repository; @@ -267,7 +270,7 @@ private RepositoryTaskEditorInput editorInput; - private TaskEditor parentEditor = null; + protected TaskEditor parentEditor = null; private RepositoryTaskOutlineNode taskOutlineModel = null; @@ -294,7 +297,7 @@ */ protected Text summaryText; - private TextViewer newCommentTextViewer; + protected TextViewer newCommentTextViewer; private org.eclipse.swt.widgets.List ccList; @@ -318,6 +321,40 @@ private TaskComment selectedComment = null; + protected AbstractPostTaskDataResult taskDataResult = new AbstractPostTaskDataResult(); + + public class ContentAssistObject { + private ContentAssistCommandAdapter commandAdapter; + + private ControlDecoration controlDecoration; + + private IContentProposalProvider savedContentProposalProvider; + + public ContentAssistCommandAdapter getCommandAdapter() { + return commandAdapter; + } + public void setCommandAdapter(ContentAssistCommandAdapter commandAdapter) { + this.commandAdapter = commandAdapter; + } + public ControlDecoration getControlDecoration() { + return controlDecoration; + } + public void setControlDecoration(ControlDecoration controlDecoration) { + this.controlDecoration = controlDecoration; + } + public void setNewContentProposalProvider(IContentProposalProvider contentProposalProvider) { + savedContentProposalProvider = getCommandAdapter().getContentProposalProvider(); + getCommandAdapter().setContentProposalProvider(contentProposalProvider); + } + public void resetContentProposalProvider() { + getCommandAdapter().setContentProposalProvider(savedContentProposalProvider); + savedContentProposalProvider = null; + } + + } + + protected Map personProposalMap = new HashMap(10); + /** * @author Raphael Ackermann (bug 195514) */ @@ -1057,9 +1094,13 @@ text.setData(attribute); if (hasContentAssist(attribute)) { - ContentAssistCommandAdapter adapter = applyContentAssist(text, + ContentAssistObject contentAssistObject = applyContentAssistWithReturnObject(text, createContentProposalProvider(attribute)); - + if (personProposalMap.get(attribute.getId()) == null) { + personProposalMap.put(attribute.getId(), contentAssistObject); + } + ContentAssistCommandAdapter adapter = contentAssistObject.getCommandAdapter(); + ILabelProvider propsalLabelProvider = createProposalLabelProvider(attribute); if (propsalLabelProvider != null) { adapter.setLabelProvider(propsalLabelProvider); @@ -1189,6 +1230,9 @@ * @param proposalProvider * instance providing content proposals * @return the ContentAssistCommandAdapter for the field. + * + * @deprecated use {@link #applyContentAssistWithReturnObject(Text text, IContentProposalProvider proposalProvider)} instead + * */ protected ContentAssistCommandAdapter applyContentAssist(Text text, IContentProposalProvider proposalProvider) { ControlDecoration controlDecoration = new ControlDecoration(text, (SWT.TOP | SWT.LEFT)); @@ -1213,6 +1257,42 @@ } /** + * Adds content assist to the given text field. + * + * @param text + * text field to decorate. + * @param proposalProvider + * instance providing content proposals + * @return the ContentAssistObject for the field. + * + * since 2.3 + */ + protected ContentAssistObject applyContentAssistWithReturnObject(Text text, IContentProposalProvider proposalProvider) { + ContentAssistObject result = new ContentAssistObject(); + ControlDecoration controlDecoration = new ControlDecoration(text, (SWT.TOP | SWT.LEFT)); + result.setControlDecoration(controlDecoration); + controlDecoration.setMarginWidth(0); + controlDecoration.setShowHover(true); + controlDecoration.setShowOnlyOnFocus(true); + + FieldDecoration contentProposalImage = FieldDecorationRegistry.getDefault().getFieldDecoration( + FieldDecorationRegistry.DEC_CONTENT_PROPOSAL); + controlDecoration.setImage(contentProposalImage.getImage()); + + TextContentAdapter textContentAdapter = new TextContentAdapter(); + + ContentAssistCommandAdapter adapter = new ContentAssistCommandAdapter(text, textContentAdapter, + proposalProvider, "org.eclipse.ui.edit.text.contentAssist.proposals", new char[0]); + result.setCommandAdapter(adapter); + + IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getService(IBindingService.class); + controlDecoration.setDescriptionText(NLS.bind("Content Assist Available ({0})", + bindingService.getBestActiveBindingFormattedFor(adapter.getCommandId()))); + + return result; + } + + /** * Creates an IContentProposalProvider to provide content assist proposals for the given attribute. * * @param attribute @@ -1935,8 +2015,12 @@ GridDataFactory.fillDefaults().hint(150, SWT.DEFAULT).applyTo(text); if (hasContentAssist(addCCattribute)) { - ContentAssistCommandAdapter adapter = applyContentAssist(text, + ContentAssistObject contentAssistObject = applyContentAssistWithReturnObject(text, createContentProposalProvider(addCCattribute)); + if (personProposalMap.get(addCCattribute.getId()) == null) { + personProposalMap.put(addCCattribute.getId(), contentAssistObject); + } + ContentAssistCommandAdapter adapter = contentAssistObject.getCommandAdapter(); ILabelProvider propsalLabelProvider = createProposalLabelProvider(addCCattribute); if (propsalLabelProvider != null) { adapter.setLabelProvider(propsalLabelProvider); @@ -3315,10 +3399,37 @@ @Override protected IStatus run(IProgressMonitor monitor) { AbstractTask modifiedTask = null; + String taskId; try { monitor.beginTask("Submitting task", 3); - String taskId = connector.getTaskDataHandler().postTaskData(repository, taskData, - new SubProgressMonitor(monitor, 1)); + if (connector.getTaskDataHandler().usePostTaskDataNewAPI()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + + FieldDecoration contentProposalImage = FieldDecorationRegistry.getDefault() + .getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL); + Iterator iter = taskDataResult.getResponseData().keySet().iterator(); + while (iter.hasNext()) { + String key = iter.next(); + ContentAssistObject contentAssistObject = personProposalMap.get(key); + if (contentAssistObject != null) { + contentAssistObject.getControlDecoration().setImage( + contentProposalImage.getImage()); + contentAssistObject.getControlDecoration().setShowOnlyOnFocus(true); + contentAssistObject.resetContentProposalProvider(); + } + } + taskDataResult.reset(); + } + }); + + connector.getTaskDataHandler().postTaskData(repository, taskData, + new SubProgressMonitor(monitor, 1), taskDataResult); + taskId = taskDataResult.getNewTaskID(); + } else { + taskId = connector.getTaskDataHandler().postTaskData(repository, taskData, + new SubProgressMonitor(monitor, 1)); + } final boolean isNew = taskData.isNew(); if (isNew) { if (taskId != null) { @@ -3697,8 +3808,12 @@ textField = createTextField(peopleComposite, assignedAttribute, SWT.FLAT | SWT.READ_ONLY); } else { textField = createTextField(peopleComposite, assignedAttribute, SWT.FLAT); - ContentAssistCommandAdapter adapter = applyContentAssist(textField, + ContentAssistObject contentAssistObject = applyContentAssistWithReturnObject(textField, createContentProposalProvider(assignedAttribute)); + if (personProposalMap.get(assignedAttribute.getId()) == null) { + personProposalMap.put(assignedAttribute.getId(), contentAssistObject); + } + ContentAssistCommandAdapter adapter = contentAssistObject.getCommandAdapter(); ILabelProvider propsalLabelProvider = createProposalLabelProvider(assignedAttribute); if (propsalLabelProvider != null) { adapter.setLabelProvider(propsalLabelProvider); @@ -3721,4 +3836,16 @@ form.layout(true, true); form.reflow(true); } + + /** + * Creates an IContentProposalProvider to provide content assist proposals for the given operation. + * + * @param operation + * operation for which to provide content assist. + * @return the IContentProposalProvider. + */ + protected IContentProposalProvider createUserMatchContentProposalProvider(ListuserList) { + + return new UserMatchPersonProposalProvider(userList); + } } Index: src/org/eclipse/mylyn/internal/tasks/ui/UserMatchPersonProposalProvider.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/UserMatchPersonProposalProvider.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/UserMatchPersonProposalProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/UserMatchPersonProposalProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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.tasks.ui; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jface.fieldassist.IContentProposal; +import org.eclipse.jface.fieldassist.IContentProposalProvider; + +public class UserMatchPersonProposalProvider implements IContentProposalProvider { + + List userMatchList; + + public UserMatchPersonProposalProvider(List userMatchList) { + this.userMatchList = userMatchList; + } + + public IContentProposal[] getProposals(String contents, int position) { + IContentProposal[] result = new IContentProposal[userMatchList.size()]; + int i = 0; + for (final String address : userMatchList) { + result[i++] = new PersonContentProposal(address, false); + } + Arrays.sort(result); + return result; + } + +}