mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fogbugz support initial
This commit is contained in:
@@ -112,6 +112,7 @@
|
||||
<tasks.repositoryType implementation="com.intellij.tasks.github.GitHubRepositoryType"/>
|
||||
<tasks.repositoryType implementation="com.intellij.tasks.redmine.RedmineRepositoryType"/>
|
||||
<tasks.repositoryType implementation="com.intellij.tasks.trac.TracRepositoryType"/>
|
||||
<tasks.repositoryType implementation="com.intellij.tasks.fogbugz.FogBugzRepositoryType"/>
|
||||
|
||||
<checkinHandlerFactory implementation="com.intellij.tasks.impl.TaskCheckinHandlerFactory"/>
|
||||
<!--<tasks.repositoryType implementation="com.intellij.tasks.mantis.MantisRepositoryType"/>-->
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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 com.intellij.tasks.fogbugz;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.tasks.Comment;
|
||||
import com.intellij.tasks.Task;
|
||||
import com.intellij.tasks.TaskRepositoryType;
|
||||
import com.intellij.tasks.TaskType;
|
||||
import com.intellij.tasks.impl.BaseRepository;
|
||||
import com.intellij.tasks.impl.BaseRepositoryImpl;
|
||||
import com.intellij.tasks.impl.LocalTaskImpl;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.input.SAXBuilder;
|
||||
import org.jdom.xpath.XPath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
import javax.xml.datatype.DatatypeFactory;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mkennedy
|
||||
*/
|
||||
@Tag("FogBugz")
|
||||
public class FogBugzRepository extends BaseRepositoryImpl {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.fogbugz.FogBugzRepository");
|
||||
private transient String token;
|
||||
|
||||
public FogBugzRepository(TaskRepositoryType type) {
|
||||
super(type);
|
||||
setUrl("https://example.fogbugz.com");
|
||||
}
|
||||
|
||||
private FogBugzRepository(FogBugzRepository other) {
|
||||
super(other);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public FogBugzRepository() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task[] getIssues(@Nullable String query, int max, final long since) throws Exception {
|
||||
return getCases(StringUtil.notNullize(query));
|
||||
}
|
||||
|
||||
private Task[] getCases(String q) throws Exception {
|
||||
HttpClient client = login(getLoginMethod());
|
||||
PostMethod method = new PostMethod(getUrl() + "/api.asp");
|
||||
method.addParameter("token", token);
|
||||
method.addParameter("cmd", "search");
|
||||
method.addParameter("q", q);
|
||||
method.addParameter("cols", "sTitle,fOpen,dtOpened,dtLastUpdated,ixCategory");
|
||||
int status = client.executeMethod(method);
|
||||
if (status != 200) {
|
||||
throw new Exception("Error listing cases: " + method.getStatusLine());
|
||||
}
|
||||
Document document = new SAXBuilder(false).build(method.getResponseBodyAsStream()).getDocument();
|
||||
XPath path = XPath.newInstance("/response/cases/case");
|
||||
final XPath commentPath = XPath.newInstance("events/event");
|
||||
@SuppressWarnings("unchecked") final List<Element> nodes = (List<Element>)path.selectNodes(document);
|
||||
List<Task> tasks = ContainerUtil.mapNotNull(nodes, new NotNullFunction<Element, Task>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Task fun(Element element) {
|
||||
return createCase(element, commentPath);
|
||||
|
||||
}
|
||||
});
|
||||
return tasks.toArray(new Task[tasks.size()]);
|
||||
}
|
||||
|
||||
private static TaskType getType(Element element) {
|
||||
String category = element.getChildText("ixCategory");
|
||||
if ("1".equals(category)) {
|
||||
return TaskType.BUG;
|
||||
}
|
||||
else if ("2".equals(category)) {
|
||||
return TaskType.FEATURE;
|
||||
}
|
||||
return TaskType.OTHER;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Task createCase(final Element element, final XPath commentPath) {
|
||||
String id = element.getAttributeValue("ixBug");
|
||||
String title = element.getChildTextTrim("sTitle");
|
||||
TaskType type = getType(element);
|
||||
LocalTaskImpl task = new LocalTaskImpl(id, title) {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Comment[] getComments() {
|
||||
List<Element> nodes;
|
||||
try {
|
||||
nodes = commentPath.selectNodes(element);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Error selecting comment nodes", e);
|
||||
}
|
||||
List<Comment> comments = ContainerUtil.mapNotNull(nodes, new NotNullFunction<Element, Comment>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Comment fun(Element element) {
|
||||
return createComment(element);
|
||||
}
|
||||
|
||||
private Comment createComment(final Element element) {
|
||||
return new Comment() {
|
||||
@Override
|
||||
public String getText() {
|
||||
return element.getChildTextTrim("s");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return element.getChildTextTrim("sPerson");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Date getDate() {
|
||||
return parseDate(element.getChildTextTrim("dt"));
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
return comments.toArray(new Comment[comments.size()]);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Date getUpdated() {
|
||||
return parseDate(element.getChildText("dtLastUpdated"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Date getCreated() {
|
||||
return parseDate(element.getChildTextTrim("dtOpened"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return !Boolean.valueOf(element.getChildTextTrim("fOpen"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIssue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getIssueUrl() {
|
||||
return getUrl() + "/default.asp?" + getId();
|
||||
}
|
||||
};
|
||||
task.setType(type);
|
||||
return task;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Task findTask(String id) throws Exception {
|
||||
Task[] tasks = getCases(id);
|
||||
switch (tasks.length) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return tasks[0];
|
||||
default:
|
||||
LOG.warn("Expected unique case for case id: " + id + ", got " + tasks.length + " instead. Using the first one.");
|
||||
return tasks[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseRepository clone() {
|
||||
return new FogBugzRepository(this);
|
||||
}
|
||||
|
||||
private HttpClient login(PostMethod method) throws Exception {
|
||||
HttpClient client = getHttpClient();
|
||||
int status = client.executeMethod(method);
|
||||
if (status != 200) {
|
||||
throw new Exception("Error logging in: " + method.getStatusLine());
|
||||
}
|
||||
Document document = new SAXBuilder(false).build(method.getResponseBodyAsStream()).getDocument();
|
||||
XPath path = XPath.newInstance("/response/token");
|
||||
Element result = (Element)path.selectSingleNode(document);
|
||||
if (result == null) {
|
||||
Element error = (Element)XPath.newInstance("/response/error").selectSingleNode(document);
|
||||
throw new Exception(error == null ? "Error logging in" : error.getText());
|
||||
}
|
||||
token = result.getTextTrim();
|
||||
return client;
|
||||
}
|
||||
|
||||
private PostMethod getLoginMethod() {
|
||||
PostMethod method = new PostMethod(getUrl() + "/api.asp");
|
||||
method.addParameter("cmd", "logon");
|
||||
method.addParameter("email", getUsername());
|
||||
method.addParameter("password", getPassword());
|
||||
return method;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CancellableConnection createCancellableConnection() {
|
||||
return new HttpTestConnection<PostMethod>(getLoginMethod()) {
|
||||
@Override
|
||||
protected void doTest(PostMethod method) throws Exception {
|
||||
login(method);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Date parseDate(@NotNull String string) {
|
||||
try {
|
||||
return DatatypeFactory.newInstance().newXMLGregorianCalendar(string).toGregorianCalendar().getTime();
|
||||
}
|
||||
catch (DatatypeConfigurationException e) {
|
||||
throw new RuntimeException("Error configuring datatype factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return "{id} (e.g. 2344245), {summary}";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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 com.intellij.tasks.fogbugz;
|
||||
|
||||
import com.intellij.tasks.TaskRepository;
|
||||
import com.intellij.tasks.impl.BaseRepositoryType;
|
||||
import icons.TasksCoreIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author mkennedy
|
||||
*/
|
||||
public class FogBugzRepositoryType extends BaseRepositoryType<FogBugzRepository> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "FogBugz";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return TasksCoreIcons.Fogbugz;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TaskRepository createRepository() {
|
||||
return new FogBugzRepository(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<FogBugzRepository> getRepositoryClass() {
|
||||
return FogBugzRepository.class;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ public class TasksCoreIcons {
|
||||
public static final Icon Bug = load("/icons/bug.png"); // 16x16
|
||||
public static final Icon Exception = load("/icons/exception.png"); // 16x16
|
||||
public static final Icon Feature = load("/icons/feature.png"); // 16x16
|
||||
public static final Icon Fogbugz = load("/icons/fogbugz.png"); // 16x16
|
||||
public static final Icon Github = load("/icons/github.png"); // 16x16
|
||||
public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16
|
||||
public static final Icon Mantis = load("/icons/mantis.png"); // 16x16
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 853 B |
Reference in New Issue
Block a user