package hudson.plugins.bugzilla;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.httpclient.HttpClient;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
public class BugzillaSession {
String url;
String username;
String password;
// should only access from execute()/initClient()
transient XmlRpcClient client;
public BugzillaSession(String u) throws XmlRpcException, MalformedURLException {
this(u, null, null);
}
public BugzillaSession(String u, String username, String password) throws XmlRpcException, MalformedURLException {
this.url = u;
this.username = username;
this.password = password;
initClient();
}
public void checkVersion() throws XmlRpcException {
HashMap<String, Object> result = this.execute("Bugzilla.version", null);
String version = (String)result.get("version");
LOGGER.log(Level.INFO, "Bugzilla server version is " + version);
}
private void initClient() throws MalformedURLException {
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
URL urlobj = new URL(this.url + "/xmlrpc.cgi");
if(urlobj.getHost() == null) throw new MalformedURLException();
config.setServerURL(urlobj);
client = new XmlRpcClient();
XmlRpcCommonsTransportFactory transportFactory = new XmlRpcCommonsTransportFactory(client);
// set the HttpClient so that we retain cookies
transportFactory.setHttpClient(new HttpClient());
client.setTransportFactory(transportFactory);
client.setConfig(config);
}
public boolean login() {
if(username == null || password == null) {
LOGGER.fine("Username or password missing, assuming not necessary");
return true;
}
try {
HashMap<String, Object> args = new HashMap<String, Object>();
args.put("login", username);
args.put("password", password);
HashMap<String, Object> result = this.execute("User.login", args);
if(result.containsKey("id")) {
LOGGER.fine("Successful bugzilla login - ID " + result.get("id"));
return true;
} else {
LOGGER.log(Level.WARNING, "No 'id' after XMLRPC Bugzilla login");
return false;
}
} catch (XmlRpcException e) {
LOGGER.log(Level.WARNING, "XMLRPC cannot log in to bugzilla: " + e.getMessage());
return false;
}
}
public HashMap<Integer, String> getBugSummaryMap(HashSet<Integer> bugIds) {
if(bugIds.size() == 0) return null;
HashMap<Integer, String> ret = new HashMap<Integer, String>();
try {
ArrayList<Integer> argIds = new ArrayList<Integer>(bugIds);
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("ids", argIds);
HashMap<String, Object> result = this.execute("Bug.get_bugs", params);
Object[] bugs = (Object[])result.get("bugs");
LOGGER.fine("get_bugs result has " + bugs.length);
for(Object bug : bugs) {
HashMap<String, Object> bugMap = (HashMap<String, Object>)bug;
Integer id = (Integer)bugMap.get("id");
String summary = (String)bugMap.get("summary");
ret.put(id, summary);
}
} catch (XmlRpcException e) {
LOGGER.log(Level.WARNING, "XMLRPC problem getting bug summaries: " + e.getMessage());
return null;
}
return ret;
}
private HashMap<String, Object> execute(String method, HashMap<String, Object> args) throws XmlRpcException {
if(client == null) {
try {
initClient();
} catch (MalformedURLException e) {
// should be impossible
throw new Error(e);
}
}
boolean exit = false;
HashMap<String, Object> ret = null;
while(ret == null) {
try {
ret = (HashMap<String, Object>)client.execute(
method,
args == null ? new Object[0] : new Object[]{args}
);
} catch (XmlRpcException e) {
if(exit || e.code != LOGIN_REQUIRED) {
LOGGER.log(Level.FINE, "XmlRpcException for \""+method+"\" error code '"+e.code+"'", e);
throw e;
}
LOGGER.log(Level.FINE, "Login required for \""+method+"\". Attempting.");
exit = true;
login();
}
}
return ret;
}
private static final Logger LOGGER = Logger.getLogger(BugzillaSession.class.getName());
private static final int LOGIN_REQUIRED = 410;
public String getUrl() {
return url;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}