summaryrefslogtreecommitdiff
path: root/plugins/tasks/tasks-core
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/tasks/tasks-core')
-rw-r--r--plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java8
-rw-r--r--plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java57
-rw-r--r--plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepositoryEditor.java16
-rw-r--r--plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java (renamed from plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraSoapApi.java)10
-rw-r--r--plugins/tasks/tasks-core/src/META-INF/plugin.xml2
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java30
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/trello/model/TrelloCard.java3
7 files changed, 94 insertions, 32 deletions
diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java
index 22e93a9d26ee..8ee9c97512a1 100644
--- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java
+++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java
@@ -5,7 +5,7 @@ import com.intellij.tasks.Task;
import com.intellij.tasks.TaskState;
import com.intellij.tasks.jira.rest.api2.JiraRestApi2;
import com.intellij.tasks.jira.rest.api20alpha1.JiraRestApi20Alpha1;
-import com.intellij.tasks.jira.soap.JiraSoapApi;
+import com.intellij.tasks.jira.soap.JiraLegacyApi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,11 +47,11 @@ public abstract class JiraRemoteApi {
public abstract ApiType getType();
public enum ApiType {
- SOAP("SOAP") {
+ LEGACY("XML-RPC + RSS") {
@NotNull
@Override
- public JiraSoapApi createApi(@NotNull JiraRepository repository) {
- return new JiraSoapApi(repository);
+ public JiraLegacyApi createApi(@NotNull JiraRepository repository) {
+ return new JiraLegacyApi(repository);
}
},
REST_2_0("REST 2.0") {
diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java
index c5a469a40c33..b8004ca70023 100644
--- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java
+++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java
@@ -15,23 +15,31 @@ import com.intellij.tasks.impl.BaseRepositoryImpl;
import com.intellij.tasks.impl.TaskUtil;
import com.intellij.tasks.impl.gson.GsonUtil;
import com.intellij.tasks.jira.rest.JiraRestApi;
-import com.intellij.tasks.jira.soap.JiraSoapApi;
+import com.intellij.tasks.jira.soap.JiraLegacyApi;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.annotations.Tag;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.xmlrpc.CommonsXmlRpcTransport;
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcRequest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Hashtable;
import java.util.List;
+import java.util.Vector;
import java.util.regex.Pattern;
/**
* @author Dmitry Avdeev
*/
+@SuppressWarnings("UseOfObsoleteCollectionType")
@Tag("JIRA")
public class JiraRepository extends BaseRepositoryImpl {
@@ -51,6 +59,7 @@ public class JiraRepository extends BaseRepositoryImpl {
private String mySearchQuery = TaskBundle.message("jira.default.query");
private JiraRemoteApi myApiVersion;
+ private String myJiraVersion;
/**
* Serialization constructor
@@ -69,6 +78,7 @@ public class JiraRepository extends BaseRepositoryImpl {
private JiraRepository(JiraRepository other) {
super(other);
mySearchQuery = other.mySearchQuery;
+ myJiraVersion = other.myJiraVersion;
if (other.myApiVersion != null) {
myApiVersion = other.myApiVersion.getType().createApi(this);
}
@@ -77,8 +87,13 @@ public class JiraRepository extends BaseRepositoryImpl {
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
- if (o.getClass() != getClass()) return false;
- return Comparing.equal(mySearchQuery, ((JiraRepository)o).mySearchQuery);
+ if (!(o instanceof JiraRepository)) return false;
+
+ JiraRepository repository = (JiraRepository)o;
+
+ if (!Comparing.equal(mySearchQuery, repository.getSearchQuery())) return false;
+ if (!Comparing.equal(myJiraVersion, repository.getJiraVersion())) return false;
+ return true;
}
@@ -149,7 +164,7 @@ public class JiraRepository extends BaseRepositoryImpl {
public JiraRemoteApi discoverApiVersion() throws Exception {
if (LEGACY_API_ONLY) {
LOG.info("Intentionally using only legacy JIRA API");
- return new JiraSoapApi(this);
+ return createLegacyApi();
}
String responseBody;
@@ -164,7 +179,7 @@ public class JiraRepository extends BaseRepositoryImpl {
// not the way to check it safely.
StatusLine status = method.getStatusLine();
if (status != null && status.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
- return new JiraSoapApi(this);
+ return createLegacyApi();
}
else {
throw e;
@@ -173,13 +188,31 @@ public class JiraRepository extends BaseRepositoryImpl {
JsonObject object = GSON.fromJson(responseBody, JsonObject.class);
// when JIRA 4.x support will be dropped 'versionNumber' array in response
// may be used instead version string parsing
- JiraRestApi restApi = JiraRestApi.fromJiraVersion(object.get("version").getAsString(), this);
+ myJiraVersion = object.get("version").getAsString();
+ JiraRestApi restApi = JiraRestApi.fromJiraVersion(myJiraVersion, this);
if (restApi == null) {
throw new Exception(TaskBundle.message("jira.failure.no.REST"));
}
return restApi;
}
+ private JiraLegacyApi createLegacyApi() {
+ try {
+ XmlRpcClient client = new XmlRpcClient(getUrl());
+ Vector<String> parameters = new Vector<String>(Collections.singletonList(""));
+ XmlRpcRequest request = new XmlRpcRequest("jira1.getServerInfo", parameters);
+ @SuppressWarnings("unchecked") Hashtable<String, Object> response =
+ (Hashtable<String, Object>)client.execute(request, new CommonsXmlRpcTransport(new URL(getUrl()), getHttpClient()));
+ if (response != null) {
+ myJiraVersion = (String)response.get("version");
+ }
+ }
+ catch (Exception e) {
+ LOG.error("Cannot find out JIRA version via XML-RPC", e);
+ }
+ return new JiraLegacyApi(this);
+ }
+
private void ensureApiVersionDiscovered() throws Exception {
if (myApiVersion == null || LEGACY_API_ONLY || REDISCOVER_API) {
myApiVersion = discoverApiVersion();
@@ -275,7 +308,7 @@ public class JiraRepository extends BaseRepositoryImpl {
}
private boolean isRestApiSupported() {
- return myApiVersion != null && myApiVersion.getType() != JiraRemoteApi.ApiType.SOAP;
+ return myApiVersion != null && myApiVersion.getType() != JiraRemoteApi.ApiType.LEGACY;
}
public boolean isJqlSupported() {
@@ -322,6 +355,16 @@ public class JiraRepository extends BaseRepositoryImpl {
}
}
+ @Nullable
+ public String getJiraVersion() {
+ return myJiraVersion;
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void setJiraVersion(@Nullable String jiraVersion) {
+ myJiraVersion = jiraVersion;
+ }
+
public String getRestUrl(String... parts) {
return getUrl() + REST_API_PATH + "/" + StringUtil.join(parts, "/");
}
diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepositoryEditor.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepositoryEditor.java
index 3299ac427432..a8ed1f880bf7 100644
--- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepositoryEditor.java
+++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepositoryEditor.java
@@ -16,7 +16,7 @@
package com.intellij.tasks.jira;
import com.intellij.openapi.project.Project;
-import com.intellij.tasks.TaskBundle;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.tasks.config.BaseRepositoryEditor;
import com.intellij.tasks.jira.jql.JqlLanguage;
import com.intellij.ui.EditorTextField;
@@ -35,6 +35,7 @@ import javax.swing.*;
public class JiraRepositoryEditor extends BaseRepositoryEditor<JiraRepository> {
private EditorTextField mySearchQueryField;
private JBLabel mySearchLabel;
+ private JBLabel myNoteLabel;
public JiraRepositoryEditor(Project project, JiraRepository repository, Consumer<JiraRepository> changeListener) {
super(project, repository, changeListener);
@@ -53,6 +54,7 @@ public class JiraRepositoryEditor extends BaseRepositoryEditor<JiraRepository> {
if (connectionSuccessful) {
enableJqlSearchIfSupported();
}
+ updateNote();
}
@Nullable
@@ -62,14 +64,20 @@ public class JiraRepositoryEditor extends BaseRepositoryEditor<JiraRepository> {
enableJqlSearchIfSupported();
installListener(mySearchQueryField);
mySearchLabel = new JBLabel("Search:", SwingConstants.RIGHT);
- JBLabel note = new JBLabel(TaskBundle.message("jira.failure.no.JQL"));
- note.setComponentStyle(UIUtil.ComponentStyle.SMALL);
+ myNoteLabel = new JBLabel();
+ myNoteLabel.setComponentStyle(UIUtil.ComponentStyle.SMALL);
+ updateNote();
return FormBuilder.createFormBuilder()
.addLabeledComponent(mySearchLabel, mySearchQueryField)
- .addComponentToRightColumn(note)
+ .addComponentToRightColumn(myNoteLabel)
.getPanel();
}
+ private void updateNote() {
+ myNoteLabel.setText("JQL search cannot be used in JIRA versions prior 4.2. " +
+ String.format("Your version: %s.", StringUtil.notNullize(myRepository.getJiraVersion(), "unknown")));
+ }
+
@Override
public void setAnchor(@Nullable final JComponent anchor) {
super.setAnchor(anchor);
diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraSoapApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java
index 148432902a86..e8cbee842cda 100644
--- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraSoapApi.java
+++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java
@@ -22,18 +22,18 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
- * Legacy SOAP connector restored due to IDEA-120595.
+ * Legacy integration restored due to IDEA-120595.
*
* @author Mikhail Golubev
*/
-public class JiraSoapApi extends JiraRemoteApi {
+public class JiraLegacyApi extends JiraRemoteApi {
- private static final Logger LOG = Logger.getInstance(JiraSoapApi.class);
+ private static final Logger LOG = Logger.getInstance(JiraLegacyApi.class);
@NonNls private static final String RSS_SEARCH_PATH = "/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml";
public static final String RSS_ISSUE_PATH = "/si/jira.issueviews:issue-xml/";
- public JiraSoapApi(@NotNull JiraRepository repository) {
+ public JiraLegacyApi(@NotNull JiraRepository repository) {
super(repository);
}
@@ -99,7 +99,7 @@ public class JiraSoapApi extends JiraRemoteApi {
@NotNull
@Override
public final ApiType getType() {
- return ApiType.SOAP;
+ return ApiType.LEGACY;
}
@Override
diff --git a/plugins/tasks/tasks-core/src/META-INF/plugin.xml b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
index 36268b408073..6f3ac82f463a 100644
--- a/plugins/tasks/tasks-core/src/META-INF/plugin.xml
+++ b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
@@ -103,7 +103,7 @@
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
- <projectConfigurable instance="com.intellij.tasks.config.TaskConfigurable" id="tasks" displayName="Tasks" nonDefaultProject="true">
+ <projectConfigurable groupId="tools" instance="com.intellij.tasks.config.TaskConfigurable" id="tasks" displayName="Tasks" nonDefaultProject="true">
<configurable instance="com.intellij.tasks.config.TaskRepositoriesConfigurable" displayName="Servers" id="tasks.servers"/>
</projectConfigurable>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java
index f7723a9f96fa..eafe341d3989 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java
@@ -107,8 +107,8 @@ public final class TrelloRepository extends BaseRepositoryImpl {
}
@Override
- public Task[] getIssues(@Nullable String query, int max, long since) throws Exception {
- List<TrelloCard> cards = fetchCards();
+ public Task[] getIssues(@Nullable String query, int offset, int limit, boolean withClosed) throws Exception {
+ List<TrelloCard> cards = fetchCards(offset + limit, withClosed);
return ContainerUtil.map2Array(cards, Task.class, new Function<TrelloCard, Task>() {
@Override
public Task fun(TrelloCard card) {
@@ -120,17 +120,24 @@ public final class TrelloRepository extends BaseRepositoryImpl {
@Nullable
@Override
public Task findTask(@NotNull String id) throws Exception {
- String url = TRELLO_API_BASE_URL + "/cards/" + id + "?actions=commentCard&fields=" + encodeUrl(TrelloCard.REQUIRED_FIELDS) ;
+ TrelloCard card = fetchCardById(id);
+ return card != null ? new TrelloTask(card, this) : null;
+ }
+
+ @Nullable
+ public TrelloCard fetchCardById(@NotNull String id) throws Exception {
+ String url = TRELLO_API_BASE_URL + "/cards/" + id + "?actions=commentCard&fields=" + encodeUrl(TrelloCard.REQUIRED_FIELDS);
try {
- return new TrelloTask(makeRequestAndDeserializeJsonResponse(url, TrelloCard.class), this);
+ return makeRequestAndDeserializeJsonResponse(url, TrelloCard.class);
}
// Trello returns string "The requested resource was not found." or "invalid id"
- // if card can't be found
+ // if card can't be found, which not only cannot be deserialized, but also not valid JSON at all.
catch (JsonParseException e) {
return null;
}
}
+
@Nullable
public TrelloUser getCurrentUser() {
return myCurrentUser;
@@ -241,7 +248,7 @@ public final class TrelloRepository extends BaseRepositoryImpl {
}
@NotNull
- private List<TrelloCard> fetchCards() throws Exception {
+ public List<TrelloCard> fetchCards(int limit, boolean withClosed) throws Exception {
boolean fromList = false;
// choose most appropriate card provider
String baseUrl;
@@ -258,8 +265,10 @@ public final class TrelloRepository extends BaseRepositoryImpl {
else {
throw new IllegalStateException("Not configured");
}
- String allCardsUrl = baseUrl + "?filter=all&fields=" + encodeUrl(TrelloCard.REQUIRED_FIELDS);
- List<TrelloCard> cards = makeRequestAndDeserializeJsonResponse(allCardsUrl, TrelloUtil.LIST_OF_CARDS_TYPE);
+ String fetchCardsUrl = baseUrl + "?fields=" + encodeUrl(TrelloCard.REQUIRED_FIELDS) + "&limit" + limit;
+ // 'visible' filter for some reason is not supported for lists
+ fetchCardsUrl += withClosed || fromList ? "&filter=all" : "&filter=visible";
+ List<TrelloCard> cards = makeRequestAndDeserializeJsonResponse(fetchCardsUrl, TrelloUtil.LIST_OF_CARDS_TYPE);
LOG.debug("Total " + cards.size() + " cards downloaded");
if (!myIncludeAllCards) {
cards = ContainerUtil.filter(cards, new Condition<TrelloCard>() {
@@ -270,7 +279,10 @@ public final class TrelloRepository extends BaseRepositoryImpl {
});
LOG.debug("Total " + cards.size() + " cards after filtering");
}
- if (!fromList) {
+ if (!cards.isEmpty()) {
+ if (fromList) {
+ baseUrl = TRELLO_API_BASE_URL + "/boards/" + cards.get(0).getIdBoard() + "/cards";
+ }
// fix for IDEA-111470 and IDEA-111475
// Select IDs of visible cards, e.d. cards that either archived explicitly, belong to archived list or closed board.
// This information can't be extracted from single card description, because its 'closed' field
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/model/TrelloCard.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/model/TrelloCard.java
index f4fc18d42500..4aebd6a67385 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/model/TrelloCard.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/model/TrelloCard.java
@@ -44,7 +44,6 @@ public class TrelloCard extends TrelloModel {
@SerializedName("desc")
private String description;
private String url;
- @SerializedName("due")
private boolean closed;
private Date dateLastActivity;
private List<TrelloLabel> labels;
@@ -91,7 +90,7 @@ public class TrelloCard extends TrelloModel {
}
@Override
- public void setName(String name) {
+ public void setName(@NotNull String name) {
this.name = name;
}