IDEA-75975 Wrong coding in Open Task from
[idea/community.git] / plugins / tasks / tasks-core / src / com / intellij / tasks / trac / TracRepository.java
1 /*
2  * Copyright 2000-2011 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.tasks.trac;
17
18 import com.intellij.openapi.util.Comparing;
19 import com.intellij.tasks.Task;
20 import com.intellij.tasks.TaskType;
21 import com.intellij.tasks.impl.BaseRepository;
22 import com.intellij.tasks.impl.BaseRepositoryImpl;
23 import com.intellij.tasks.impl.LocalTaskImpl;
24 import com.intellij.util.containers.ContainerUtil;
25 import com.intellij.util.xmlb.annotations.Tag;
26 import org.apache.xmlrpc.*;
27 import org.jetbrains.annotations.Nullable;
28
29 import java.io.IOException;
30 import java.net.MalformedURLException;
31 import java.net.URL;
32 import java.util.*;
33
34 /**
35  * @author Dmitry Avdeev
36  */
37 @Tag("Trac")
38 @SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked"})
39 public class TracRepository extends BaseRepositoryImpl {
40
41   static {
42     XmlRpc.setDefaultInputEncoding("UTF-8");
43   }
44
45   private String myDefaultSearch = "status!=closed&owner={username}&summary~={query}";
46   private Boolean myMaxSupported;
47
48   @Override
49   public Task[] getIssues(@Nullable String query, int max, long since) throws Exception {
50     Transport transport = new Transport();
51     return getIssues(query, max, transport);
52   }
53
54   private Task[] getIssues(String query, int max, final Transport transport) throws Exception {
55     final XmlRpcClient client = getRpcClient();
56
57     Vector<Object> result = null;
58     String search = myDefaultSearch + "&max=" + max;
59     if (myMaxSupported == null) {
60       try {
61         myMaxSupported = true;
62         result = runQuery(query, transport, client, search);
63       }
64       catch (XmlRpcException e) {
65         if (e.getMessage().contains("t.max")) {
66           myMaxSupported = false;
67         }
68         else throw e;
69       }
70     }
71     if (!myMaxSupported) {
72       search = myDefaultSearch;
73     }
74     if (result == null) {
75       result = runQuery(query, transport, client, search);
76     }
77
78     if (result == null) throw new Exception("Cannot connect to " + getUrl());
79
80     ArrayList<Task> tasks = new ArrayList<Task>(max);
81     int min = Math.min(max, result.size());
82     for (int i = 0; i < min; i++) {
83       Task task = getTask((Integer)result.get(i), client, transport);
84       ContainerUtil.addIfNotNull(tasks, task);
85     }
86     return tasks.toArray(new Task[tasks.size()]);
87   }
88
89   private Vector<Object> runQuery(String query, Transport transport, XmlRpcClient client, String search)
90     throws XmlRpcException, IOException {
91     if (query != null) {
92       search = search.replace("{query}", query);
93     }
94     search = search.replace("{username}", getUsername());
95     XmlRpcRequest request = new XmlRpcRequest("ticket.query", new Vector<Object>(Arrays.asList(search)));
96     return (Vector<Object>)client.execute(request, transport);
97   }
98
99   private XmlRpcClient getRpcClient() throws MalformedURLException {
100     return new XmlRpcClient(getUrl());
101   }
102
103   @Override
104   public Task findTask(String id) throws Exception {
105     return getTask(Integer.parseInt(id), getRpcClient(), new Transport());
106   }
107
108   public String getDefaultSearch() {
109     return myDefaultSearch;
110   }
111
112   public void setDefaultSearch(String defaultSearch) {
113     myDefaultSearch = defaultSearch;
114   }
115
116   @Nullable
117   private static Task getTask(int id, XmlRpcClient client, Transport transport) throws IOException, XmlRpcException {
118     XmlRpcRequest request = new XmlRpcRequest("ticket.get", new Vector(Arrays.asList(id)));
119     Object response = client.execute(request, transport);
120     if (response == null) return null;
121     Vector<Object> vector = (Vector<Object>)response;
122     LocalTaskImpl task = new LocalTaskImpl();
123     task.setId(vector.get(0).toString());
124     task.setCreated(getDate(vector.get(1)));
125     task.setUpdated(getDate(vector.get(2)));
126
127     Hashtable<String, String> map = (Hashtable<String, String>)vector.get(3);
128     task.setSummary(map.get("summary"));
129
130     TaskType taskType = TaskType.OTHER;
131     String type = map.get("type");
132     if ("Feature".equals(type) || type.equals("enhancement")) taskType = TaskType.FEATURE;
133     else if ("Bug".equals(type) || type.equals("defect") || type.equals("error")) taskType = TaskType.BUG;
134     else if ("Exception".equals(type)) taskType = TaskType.EXCEPTION;
135     task.setType(taskType);
136
137     task.setIssue(true);
138     return task;
139   }
140
141   private static Date getDate(Object o) {
142     return o instanceof Date ? (Date)o : new Date((Integer)o * 1000l);
143   }
144
145   @Override
146   public CancellableConnection createCancellableConnection() {
147
148     return new CancellableConnection() {
149
150       Transport myTransport;
151
152       @Override
153       protected void doTest() throws Exception {
154         myTransport = new Transport();
155         getIssues("", 1, myTransport);
156       }
157
158       @Override
159       public void cancel() {
160         myTransport.cancel();
161       }
162     };
163   }
164
165   @Override
166   public BaseRepository clone() {
167     return new TracRepository(this);
168   }
169
170   @SuppressWarnings({"UnusedDeclaration"})
171   public TracRepository() {
172     // for serialization
173   }
174
175   public TracRepository(TracRepositoryType repositoryType) {
176     super(repositoryType);
177     setUrl("http://myserver.com/login/rpc");
178     myUseHttpAuthentication = true;
179   }
180
181   private TracRepository(TracRepository other) {
182     super(other);
183     myDefaultSearch = other.myDefaultSearch;
184   }
185
186   private class Transport extends CommonsXmlRpcTransport {
187     public Transport() throws MalformedURLException {
188       super(new URL(getUrl()), getHttpClient());
189     }
190
191     void cancel() {
192       method.abort();
193     }
194   }
195
196   @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
197   @Override
198   public boolean equals(Object o) {
199     return super.equals(o) && Comparing.equal(((TracRepository)o).getDefaultSearch(), getDefaultSearch());
200   }
201 }