View Javadoc

1   /**
2    * Copyright (C) 2008 Atlassian
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  
17  package com.atlassian.theplugin.jira.api.soap;
18  
19  import com.atlassian.theplugin.jira.JIRAServer;
20  import com.atlassian.theplugin.jira.api.*;
21  import com.atlassian.theplugin.jira.api.soap.axis.*;
22  import com.atlassian.theplugin.commons.remoteapi.RemoteApiException;
23  import com.atlassian.theplugin.commons.remoteapi.RemoteApiLoginException;
24  import com.atlassian.theplugin.commons.configuration.ConfigurationFactory;
25  import com.atlassian.theplugin.commons.util.HttpConfigurableAdapter;
26  import com.intellij.openapi.diagnostic.Logger;
27  
28  import javax.xml.rpc.ServiceException;
29  import java.net.MalformedURLException;
30  import java.net.URL;
31  import java.rmi.RemoteException;
32  import java.util.ArrayList;
33  import java.util.Calendar;
34  import java.util.List;
35  
36  import org.apache.axis.AxisProperties;
37  
38  public class JIRASessionImpl implements JIRASession {
39  
40  	private String token;
41  	private JiraSoapService service;
42  	private String serverUrl;
43  	private URL portAddress;
44  
45  	public static final int ONE_DAY_AGO = -24;
46  
47  	private boolean loggedIn = false;
48  
49  	//
50  	// AxisProperties are shit - if you try to set nonexistent property to null, NPE is thrown. Moreover, sometimes
51  	// setting apparently *existing* property to null also throws NPE (see bug PL-412)! Crap, crap, crap...
52  	//
53  	private void setAxisProperty(String name, String value) {
54  		if (value == null) {
55  			if (AxisProperties.getProperty(name) != null) {
56  				try {
57  					AxisProperties.setProperty(name, null);
58  				} catch (NullPointerException e) {
59  					Logger.getInstance(getClass().getName()).info("Setting property " + name + " to null", e);
60  				}
61  			}
62  		} else {
63  			AxisProperties.setProperty(name, value);
64  		}
65  	}
66  
67  	private void setProxy() {
68  		boolean useIdeaProxySettings =
69  				ConfigurationFactory.getConfiguration().getGeneralConfigurationData().getUseIdeaProxySettings();
70  		HttpConfigurableAdapter proxyInfo = ConfigurationFactory.getConfiguration().transientGetHttpConfigurable();
71  		String host = null;
72  		String port = null;
73  		String user = null;
74  		String password = null;
75  		if (useIdeaProxySettings && proxyInfo.isUseHttpProxy()) {
76  			host = proxyInfo.getProxyHost();
77  			port = String.valueOf(proxyInfo.getProxyPort());
78  			if (proxyInfo.isProxyAuthentication()) {
79  				user = proxyInfo.getProxyLogin();
80  				password = proxyInfo.getPlainProxyPassword();
81  			}
82  		}
83  
84  		//
85  		// well - re-setting proxy does not really work - Axis bug
86  		// see: http://issues.apache.org/jira/browse/AXIS-2295
87  		// So in order to apply new proxy settings, IDEA has to be restarted
88  		// all software sucks
89  		//
90  		setAxisProperty("http.proxyHost", host);
91  		setAxisProperty("http.proxyPort", port);
92  		setAxisProperty("https.proxyHost", host);
93  		setAxisProperty("https.proxyPort", port);
94  		setAxisProperty("http.proxyUser", user);
95  		setAxisProperty("https.proxyUser", user);
96  		setAxisProperty("http.proxyPassword", password);
97  		setAxisProperty("https.proxyPassword", password);
98  	}
99  
100 	public JIRASessionImpl(String serverUrl) throws ServiceException, MalformedURLException {
101 		portAddress = new URL(serverUrl + "/rpc/soap/jirasoapservice-v2");
102 		JiraSoapServiceServiceLocator loc = new JiraSoapServiceServiceLocator();
103 		service = loc.getJirasoapserviceV2(portAddress);
104 		setProxy();
105 
106 		this.serverUrl = serverUrl;
107 	}
108 
109 	public void login(String userName, String password) throws RemoteApiLoginException {
110 		try {
111 			token = service.login(userName, password);
112 		} catch (RemoteAuthenticationException e) {
113 			throw new RemoteApiLoginException("Authentication failed");
114 		} catch (RemoteException e) {
115 	   		throw new RemoteApiLoginException(e.toString());
116 		}
117 		loggedIn = true;
118 	}
119 
120 	public void logout() {
121 		try {
122 			if (service.logout(token)) {
123 				token = null;
124 				loggedIn = false;
125 			}
126 		} catch (java.rmi.RemoteException e) {
127 			// todo: log the exception
128 		}
129 	}
130 
131 	public void logWork(JIRAIssue issue, String timeSpent, Calendar startDate, String comment,
132 						boolean updateEstimate, String newEstimate)
133 			throws RemoteApiException {
134 		RemoteWorklog workLog = new RemoteWorklog();
135 		workLog.setStartDate(startDate);
136 		workLog.setTimeSpent(timeSpent);
137 		workLog.setComment(comment);
138 		try {
139 			if (updateEstimate) {
140 				if (newEstimate != null) {
141 					service.addWorklogWithNewRemainingEstimate(token, issue.getKey(), workLog, newEstimate);	
142 				} else {
143 					service.addWorklogAndAutoAdjustRemainingEstimate(token, issue.getKey(), workLog);
144 				}
145 			} else {
146 				service.addWorklogAndRetainRemainingEstimate(token, issue.getKey(), workLog);
147 			}
148 		} catch (RemoteException e) {
149 			throw new RemoteApiException(e.toString(), e);
150 		}
151 	}
152 
153 	public JIRAIssue createIssue(JIRAIssue issue) throws RemoteApiException {
154 		RemoteIssue remoteIssue = new RemoteIssue();
155 
156 		remoteIssue.setProject(issue.getProjectKey());
157 		remoteIssue.setType(String.valueOf(issue.getTypeConstant().getId()));
158 		remoteIssue.setSummary(issue.getSummary());
159 		if (issue.getPriorityConstant().getId() != JIRAServer.ANY_ID) {
160 			remoteIssue.setPriority(String.valueOf(issue.getPriorityConstant().getId()));
161 		}
162 
163 		if (issue.getDescription() != null) {
164 			remoteIssue.setDescription(issue.getDescription());
165 		}
166 		if (issue.getAssignee() != null) {
167 			remoteIssue.setAssignee(issue.getAssignee());
168 		}
169 
170 		try {
171 			remoteIssue = service.createIssue(token, remoteIssue);
172 		} catch (RemoteException e) {
173 			throw new RemoteApiException(e.toString(), e);
174 		}
175 
176 		// todo: fill in all other fields. For now only the issue key and URL is being displayed
177 		JIRAIssueBean retVal = new JIRAIssueBean(serverUrl);
178 		retVal.setKey(remoteIssue.getKey());
179 		return retVal;
180 	}
181 
182 	public JIRAIssue getIssueDetails(JIRAIssue issue) throws RemoteApiException {
183 		try {
184 			RemoteIssue rIssue = service.getIssue(token, issue.getKey());
185 			JIRAIssueBean issueBean = new JIRAIssueBean(issue);
186 
187 			RemoteVersion[] aVers = rIssue.getAffectsVersions();
188 			List<JIRAConstant> av = new ArrayList<JIRAConstant>();
189 			for (RemoteVersion v : aVers) {
190 				av.add(new JIRAVersionBean(Long.valueOf(v.getId()), v.getName()));
191 			}
192 			issueBean.setAffectsVersions(av);
193 
194 			RemoteVersion[] fVers = rIssue.getFixVersions();
195 			List<JIRAConstant> fv = new ArrayList<JIRAConstant>();
196 			for (RemoteVersion v : fVers) {
197 				fv.add(new JIRAVersionBean(Long.valueOf(v.getId()), v.getName()));
198 			}
199 			issueBean.setFixVersions(fv);
200 
201 			RemoteComponent[] comps = rIssue.getComponents();
202 			List<JIRAConstant> c = new ArrayList<JIRAConstant>();
203 			for (RemoteComponent rc : comps) {
204 				c.add(new JIRAComponentBean(Long.valueOf(rc.getId()), rc.getName()));
205 			}
206 			issueBean.setComponents(c);
207 
208 			return issueBean;
209 
210 		} catch (RemoteException e) {
211 			throw new RemoteApiException(e.toString(), e);
212 		}
213 
214 	}
215 
216 	public void addComment(JIRAIssue issue, String comment) throws RemoteApiException {
217 		try {
218 			RemoteComment rComment = new RemoteComment();
219 			rComment.setBody(comment);
220 			service.addComment(token, issue.getKey(), rComment);
221 		} catch (RemoteException e) {
222 			throw new RemoteApiException(e.toString(), e);
223 		}
224 	}
225 
226 	public List<JIRAProject> getProjects() throws RemoteApiException {
227 		try {
228 			RemoteProject[] projects = service.getProjectsNoSchemes(token);
229 			List<JIRAProject> projectList = new ArrayList<JIRAProject>(projects.length);
230 
231 			for (RemoteProject p : projects) {
232 				JIRAProjectBean project = new JIRAProjectBean();
233 
234 				project.setName(p.getName());
235 				project.setKey(p.getKey());
236 				project.setDescription(p.getDescription());
237 				project.setUrl(p.getUrl());
238 				project.setLead(p.getLead());
239 				project.setId(Long.valueOf(p.getId()));
240 
241 				projectList.add(project);
242 			}
243 
244 			return projectList;
245 		} catch (RemoteException e) {
246 			throw new RemoteApiException(e.toString(), e);
247 		}
248 	}
249 
250 	private List<JIRAConstant> issueTableToList(RemoteIssueType[] types) throws MalformedURLException {
251 		List<JIRAConstant> typesList = new ArrayList<JIRAConstant>();
252 		for (RemoteIssueType type : types) {
253 			typesList.add(new JIRAIssueTypeBean(Long.valueOf(type.getId()), type.getName(), new URL(type.getIcon())));
254 		}
255 		return typesList;
256 	}
257 
258 	public List<JIRAConstant> getIssueTypes() throws RemoteApiException {
259 		try {
260 			return issueTableToList(service.getIssueTypes(token));
261 		} catch (RemoteException e) {
262 			throw new RemoteApiException(e.toString(), e);
263 		} catch (MalformedURLException e) {
264 			throw new RemoteApiException(e.toString(), e);
265 		}
266 
267 	}
268 
269 	public List<JIRAConstant> getIssueTypesForProject(String project) throws RemoteApiException {
270 		try {
271 			return issueTableToList(service.getIssueTypesForProject(token, project));
272 		} catch (RemoteException e) {
273 			throw new RemoteApiException(e.toString(), e);
274 		} catch (MalformedURLException e) {
275 			throw new RemoteApiException(e.toString(), e);
276 		}
277 	}
278 
279 	public List<JIRAConstant> getStatuses() throws RemoteApiException {
280 		try {
281 			RemoteStatus[] statuses = service.getStatuses(token);
282 
283 			List<JIRAConstant> statusesList = new ArrayList<JIRAConstant>(statuses.length);
284 			for (RemoteStatus status : statuses) {
285 				statusesList.add(new JIRAStatusBean(
286 						Long.valueOf(status.getId()), status.getName(), new URL(status.getIcon())));
287 			}
288 			return statusesList;
289 		} catch (RemoteException e) {
290 			throw new RemoteApiException(e.toString(), e);
291 		} catch (MalformedURLException e) {
292 			throw new RemoteApiException(e.toString(), e);
293 		}
294 	}
295 
296 	public List<JIRAComponentBean> getComponents(String projectKey) throws RemoteApiException {
297 		try {
298 			RemoteComponent[] components = service.getComponents(token, projectKey);
299 
300 			List<JIRAComponentBean> componentsList = new ArrayList<JIRAComponentBean>(components.length);
301 			for (RemoteComponent c : components) {
302 				componentsList.add(new JIRAComponentBean(Long.valueOf(c.getId()), c.getName()));
303 			}
304 			return componentsList;
305 		} catch (RemoteException e) {
306 			throw new RemoteApiException(e.toString(), e);
307 		}
308 	}
309 
310 	public List<JIRAVersionBean> getVersions(String projectKey) throws RemoteApiException {
311 		try {
312 			RemoteVersion[] versions = service.getVersions(token, projectKey);
313 
314 			List<JIRAVersionBean> versionsList = new ArrayList<JIRAVersionBean>(versions.length);
315 			for (RemoteVersion v : versions) {
316 				versionsList.add(new JIRAVersionBean(Long.valueOf(v.getId()), v.getName()));
317 			}
318 			return versionsList;
319 		} catch (RemoteException e) {
320 			throw new RemoteApiException(e.toString(), e);
321 		}
322 	}
323 
324 	public List<JIRAConstant> getPriorities() throws RemoteApiException {
325 		try {
326 			RemotePriority[] priorities = service.getPriorities(token);
327 
328 			List<JIRAConstant> prioritiesList = new ArrayList<JIRAConstant>(priorities.length);
329 			for (RemotePriority p : priorities) {
330 				prioritiesList.add(new JIRAPriorityBean(Long.valueOf(p.getId()), p.getName(), new URL(p.getIcon())));
331 			}
332 			return prioritiesList;
333 		} catch (RemoteException e) {
334 			throw new RemoteApiException(e.toString(), e);
335 		} catch (MalformedURLException e) {
336 			throw new RemoteApiException(e.toString(), e);
337 		}
338 	}
339 
340 	public List<JIRAResolutionBean> getResolutions() throws RemoteApiException {
341 		try {
342 			RemoteResolution[] resolutions = service.getResolutions(token);
343 
344 			List<JIRAResolutionBean> resolutionsList = new ArrayList<JIRAResolutionBean>(resolutions.length);
345 			for (RemoteResolution p : resolutions) {
346 				resolutionsList.add(new JIRAResolutionBean(Long.valueOf(p.getId()), p.getName()));
347 			}
348 			return resolutionsList;
349 		} catch (RemoteException e) {
350 			throw new RemoteApiException(e.toString(), e);
351 		}
352 	}
353 
354 	public List<JIRAQueryFragment> getSavedFilters() throws RemoteApiException {
355 		try {
356 			RemoteFilter[] filters = service.getSavedFilters(token);
357 
358 			List<JIRAQueryFragment> filtersList = new ArrayList<JIRAQueryFragment>(filters.length);
359 			for (RemoteFilter f : filters) {
360 				filtersList.add(new JIRASavedFilterBean(f.getName(), Long.valueOf(f.getId())));
361 			}
362 			return filtersList;
363 		} catch (RemoteException e) {
364 			throw new RemoteApiException(e.toString(), e);
365 		}
366 
367 	}
368 
369 	public void setAssignee(JIRAIssue issue, String assignee) throws RemoteApiException {
370 		RemoteFieldValue v = new RemoteFieldValue();
371 		RemoteFieldValue[] vTable = {v};
372 		v.setId("assignee");
373 		v.setValues(new String[]{assignee});
374 		try {
375 			service.updateIssue(token, issue.getKey(), vTable);
376 		} catch (RemoteException e) {
377 			throw new RemoteApiException(e.toString(), e);
378 		}
379 	}
380 
381     public List<JIRAAction> getAvailableActions(JIRAIssue issue) throws RemoteApiException {
382         try {
383             RemoteNamedObject[] actions = service.getAvailableActions(token, issue.getKey());
384             List<JIRAAction> actionList = new ArrayList<JIRAAction>(actions.length);
385             for (RemoteNamedObject action : actions) {
386 				actionList.add(new JIRAActionBean(Long.valueOf(action.getId()), action.getName()));
387             }
388             return actionList;
389         } catch (RemoteException e) {
390             throw new RemoteApiException(e.toString(), e);
391         }
392     }
393 
394 	public List<JIRAActionField> getFieldsForAction(JIRAIssue issue, JIRAAction action) throws RemoteApiException {
395 		try {
396 			RemoteField[] fields = service.getFieldsForAction(
397 					token, issue.getKey(), Long.valueOf(action.getId()).toString());
398 			List<JIRAActionField> fieldList = new ArrayList<JIRAActionField>(fields.length);
399 			for (RemoteField f : fields) {
400 				fieldList.add(new JIRAActionFieldBean(f.getId(), f.getName()));
401 			}
402 			return fieldList;
403 		} catch (RemoteException e) {
404 			throw new RemoteApiException(e.toString(), e);
405 		}
406 	}
407 
408 	public void progressWorkflowAction(JIRAIssue issue, JIRAAction action) throws RemoteApiException {
409 		try {
410 			// todo: if you want to actually fill in some fields, you will have to wait
411 			// until we actually handle this properly in the UI
412 			RemoteFieldValue[] dummyValues = new RemoteFieldValue[0];
413 			service.progressWorkflowAction(token, issue.getKey(), String.valueOf(action.getId()), dummyValues);
414 		} catch (RemoteException e) {
415 			throw new RemoteApiException(e.toString(), e);
416 		}
417 	}
418 
419 	public List<JIRAComment> getComments(JIRAIssue issue) throws RemoteApiException {
420 		try {
421 			RemoteComment[] comments = service.getComments(token, issue.getKey());
422 
423 			List<JIRAComment> commentsList = new ArrayList<JIRAComment>(comments.length);
424 			for (RemoteComment c : comments) {
425 				commentsList.add(new JIRACommentBean(c.getId(), c.getAuthor(), c.getBody(), c.getCreated()));
426 			}
427 			return commentsList;
428 		} catch (RemoteException e) {
429 			throw new RemoteApiException(e.toString(), e);
430 		}
431 	}
432 	public boolean isLoggedIn() {
433 		return loggedIn;
434 	}
435 }