diff options
Diffstat (limited to 'org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java')
-rw-r--r-- | org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java | 1044 |
1 files changed, 0 insertions, 1044 deletions
diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java deleted file mode 100644 index 627462b79..000000000 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java +++ /dev/null @@ -1,1044 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2008 Steffen Pingel and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Tasktop Technologies - initial API and implementation - * Xiaoyang Guan - improvements - *******************************************************************************/ - -package org.eclipse.mylyn.internal.trac.core.client; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; - -import org.apache.commons.httpclient.Credentials; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HostConfiguration; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpState; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.UsernamePasswordCredentials; -import org.apache.commons.httpclient.auth.AuthScheme; -import org.apache.commons.httpclient.auth.AuthScope; -import org.apache.commons.httpclient.auth.BasicScheme; -import org.apache.commons.httpclient.auth.DigestScheme; -import org.apache.commons.httpclient.methods.HeadMethod; -import org.apache.xmlrpc.XmlRpcException; -import org.apache.xmlrpc.client.XmlRpcClient; -import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.Status; -import org.eclipse.mylyn.commons.core.StatusHandler; -import org.eclipse.mylyn.commons.net.AbstractWebLocation; -import org.eclipse.mylyn.commons.net.AuthenticationCredentials; -import org.eclipse.mylyn.commons.net.AuthenticationType; -import org.eclipse.mylyn.commons.net.Policy; -import org.eclipse.mylyn.commons.net.UnsupportedRequestException; -import org.eclipse.mylyn.commons.net.WebUtil; -import org.eclipse.mylyn.internal.trac.core.TracCorePlugin; -import org.eclipse.mylyn.internal.trac.core.model.TracAttachment; -import org.eclipse.mylyn.internal.trac.core.model.TracComment; -import org.eclipse.mylyn.internal.trac.core.model.TracComponent; -import org.eclipse.mylyn.internal.trac.core.model.TracMilestone; -import org.eclipse.mylyn.internal.trac.core.model.TracPriority; -import org.eclipse.mylyn.internal.trac.core.model.TracSearch; -import org.eclipse.mylyn.internal.trac.core.model.TracSeverity; -import org.eclipse.mylyn.internal.trac.core.model.TracTicket; -import org.eclipse.mylyn.internal.trac.core.model.TracTicketField; -import org.eclipse.mylyn.internal.trac.core.model.TracTicketResolution; -import org.eclipse.mylyn.internal.trac.core.model.TracTicketStatus; -import org.eclipse.mylyn.internal.trac.core.model.TracTicketType; -import org.eclipse.mylyn.internal.trac.core.model.TracVersion; -import org.eclipse.mylyn.internal.trac.core.model.TracWikiPage; -import org.eclipse.mylyn.internal.trac.core.model.TracWikiPageInfo; -import org.eclipse.mylyn.internal.trac.core.model.TracTicket.Key; -import org.eclipse.mylyn.internal.trac.core.util.HttpMethodInterceptor; -import org.eclipse.mylyn.internal.trac.core.util.TracHttpClientTransportFactory; -import org.eclipse.mylyn.internal.trac.core.util.TracUtil; -import org.eclipse.mylyn.internal.trac.core.util.TracXmlRpcClientRequest; -import org.eclipse.mylyn.internal.trac.core.util.TracHttpClientTransportFactory.TracHttpException; - -/** - * Represents a Trac repository that is accessed through the Trac XmlRpcPlugin. - * - * @author Steffen Pingel - * @author Xiaoyang Guan - */ -public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiClient { - - private class XmlRpcRequest { - - private final String method; - - private final Object[] parameters; - - public XmlRpcRequest(String method, Object[] parameters) { - this.method = method; - this.parameters = parameters; - } - - public Object execute(IProgressMonitor monitor) throws TracException { - try { - // first attempt - return executeCallInternal(monitor); - } catch (TracPermissionDeniedException e) { - if (accountMangerAuthenticationFailed) { - // do not try again if this has failed in the past since it - // is more likely that XML_RPC permissions have not been set - throw e; - } - - AuthenticationCredentials credentials = location.getCredentials(AuthenticationType.REPOSITORY); - if (!credentialsValid(credentials)) { - throw e; - } - - // try form-based authentication via AccountManagerPlugin as a - // fall-back - HostConfiguration hostConfiguration = WebUtil.createHostConfiguration(httpClient, location, monitor); - try { - authenticateAccountManager(httpClient, hostConfiguration, credentials, monitor); - } catch (TracLoginException loginException) { - // caused by wrong user name or password - throw loginException; - } catch (IOException ignore) { - accountMangerAuthenticationFailed = true; - throw e; - } - - try { - validateAuthenticationState(httpClient); - } catch (TracLoginException ignore) { - // most likely form based authentication is not supported by - // repository - accountMangerAuthenticationFailed = true; - throw e; - } - - // the authentication information is available through the shared state in httpClient - } - - // second attempt - return executeCallInternal(monitor); - } - - private Object executeCallInternal(IProgressMonitor monitor) throws TracException { - try { - if (isTracd && digestScheme != null) { - probeAuthenticationScheme(monitor); - } - - TracXmlRpcClientRequest request = new TracXmlRpcClientRequest(xmlrpc.getClientConfig(), method, - parameters, monitor); - return xmlrpc.execute(request); - } catch (TracHttpException e) { - if (e.code == HttpStatus.SC_UNAUTHORIZED) { - digestScheme = null; - throw new TracLoginException(); - } else if (e.code == HttpStatus.SC_FORBIDDEN) { - digestScheme = null; - throw new TracPermissionDeniedException(); - } else if (e.code == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) { - throw new TracProxyAuthenticationException(); - } else { - throw new TracException(e); - } - } catch (XmlRpcException e) { - if (e.code == NO_SUCH_METHOD_ERROR) { - throw new TracNoSuchMethodException(e); - } else { - throw new TracRemoteException(e); - } - } catch (OperationCanceledException e) { - throw e; - } catch (Exception e) { - throw new TracException(e); - } - } - - } - - public static final String XMLRPC_URL = "/xmlrpc"; //$NON-NLS-1$ - - public static final String REQUIRED_REVISION = "1950"; //$NON-NLS-1$ - - public static final int REQUIRED_EPOCH = 0; - - public static final int REQUIRED_MAJOR = 0; - - public static final int REQUIRED_MINOR = 1; - - private static final int NO_SUCH_METHOD_ERROR = 1; - - private static final int LATEST_VERSION = -1; - - public static final int REQUIRED_WIKI_RPC_VERSION = 2; - - private XmlRpcClient xmlrpc; - - private TracHttpClientTransportFactory factory; - - private int majorAPIVersion = -1; - - private int minorAPIVersion = -1; - - private int epochAPIVersion = -1; - - private boolean accountMangerAuthenticationFailed; - - private XmlRpcClientConfigImpl config; - - private final HttpClient httpClient; - - private boolean probed; - - private volatile DigestScheme digestScheme; - - private final AuthScope authScope; - - private boolean isTracd; - - public TracXmlRpcClient(AbstractWebLocation location, Version version) { - super(location, version); - this.httpClient = createHttpClient(); - this.authScope = new AuthScope(WebUtil.getHost(repositoryUrl), WebUtil.getPort(repositoryUrl), null, - AuthScope.ANY_SCHEME); - } - - public synchronized XmlRpcClient getClient() throws TracException { - if (xmlrpc == null) { - config = new XmlRpcClientConfigImpl(); - config.setEncoding(ITracClient.CHARSET); - config.setTimeZone(TimeZone.getTimeZone(ITracClient.TIME_ZONE)); - config.setContentLengthOptional(false); - config.setConnectionTimeout(WebUtil.getConnectionTimeout()); - config.setReplyTimeout(WebUtil.getSocketTimeout()); - - xmlrpc = new XmlRpcClient(); - xmlrpc.setConfig(config); - - factory = new TracHttpClientTransportFactory(xmlrpc, httpClient); - factory.setLocation(location); - factory.setInterceptor(new HttpMethodInterceptor() { - public void processRequest(HttpMethod method) { - DigestScheme scheme = digestScheme; - if (scheme != null) { - Credentials creds = httpClient.getState().getCredentials(authScope); - if (creds != null) { - method.getHostAuthState().setAuthScheme(digestScheme); - method.getHostAuthState().setAuthRequested(true); - } - } - } - - public void processResponse(HttpMethod method) { - AuthScheme authScheme = method.getHostAuthState().getAuthScheme(); - if (authScheme instanceof DigestScheme) { - digestScheme = (DigestScheme) authScheme; - } - } - }); - xmlrpc.setTransportFactory(factory); - } - - // update configuration with latest values - AuthenticationCredentials credentials = location.getCredentials(AuthenticationType.REPOSITORY); - config.setServerURL(getXmlRpcUrl(credentials)); - if (credentialsValid(credentials)) { - Credentials creds = new UsernamePasswordCredentials(credentials.getUserName(), credentials.getPassword()); - httpClient.getState().setCredentials(authScope, creds); - } else { - httpClient.getState().clearCredentials(); - } - - return xmlrpc; - } - - private URL getXmlRpcUrl(AuthenticationCredentials credentials) throws TracException { - try { - String location = repositoryUrl.toString(); - if (credentialsValid(credentials)) { - location += LOGIN_URL; - } - location += XMLRPC_URL; - - return new URL(location); - } catch (Exception e) { - throw new TracException(e); - } - } - - private void probeAuthenticationScheme(IProgressMonitor monitor) throws TracException { - AuthenticationCredentials credentials = location.getCredentials(AuthenticationType.REPOSITORY); - if (!credentialsValid(credentials)) { - return; - } - - HostConfiguration hostConfiguration = WebUtil.createHostConfiguration(httpClient, location, monitor); - HeadMethod method = new HeadMethod(getXmlRpcUrl(credentials).toString()); - try { - // execute without any credentials set - int result = WebUtil.execute(httpClient, hostConfiguration, method, new HttpState(), monitor); - if (result == HttpStatus.SC_UNAUTHORIZED || result == HttpStatus.SC_FORBIDDEN) { - AuthScheme authScheme = method.getHostAuthState().getAuthScheme(); - if (authScheme instanceof DigestScheme) { - this.digestScheme = (DigestScheme) authScheme; - } else if (authScheme instanceof BasicScheme) { - httpClient.getParams().setAuthenticationPreemptive(true); - } - - Header header = method.getResponseHeader("Server"); //$NON-NLS-1$ - isTracd = (header != null && header.getValue().startsWith("tracd")); //$NON-NLS-1$ - -// Header header = method.getResponseHeader("WWW-Authenticate"); -// if (header != null) { -// if (header.getValue().startsWith("Basic")) { -// httpClient.getParams().setAuthenticationPreemptive(true); -// } else if (header.getValue().startsWith("Digest")) { -// DigestScheme scheme = new DigestScheme(); -// try { -// scheme.processChallenge(header.getValue()); -// this.digestScheme = scheme; -// } catch (MalformedChallengeException e) { -// // ignore -// } -// } -// } - } - } catch (IOException e) { - // ignore - } finally { - method.releaseConnection(); - } - } - - private Object call(IProgressMonitor monitor, String method, Object... parameters) throws TracException { - monitor = Policy.monitorFor(monitor); - while (true) { - if (!probed) { - try { - probeAuthenticationScheme(monitor); - } finally { - probed = true; - } - } - - getClient(); - - try { - XmlRpcRequest request = new XmlRpcRequest(method, parameters); - return request.execute(monitor); - } catch (TracLoginException e) { - try { - location.requestCredentials(AuthenticationType.REPOSITORY, null, monitor); - } catch (UnsupportedRequestException ignored) { - throw e; - } - } catch (TracPermissionDeniedException e) { - try { - location.requestCredentials(AuthenticationType.REPOSITORY, null, monitor); - } catch (UnsupportedRequestException ignored) { - throw e; - } - } catch (TracProxyAuthenticationException e) { - try { - location.requestCredentials(AuthenticationType.PROXY, null, monitor); - } catch (UnsupportedRequestException ignored) { - throw e; - } - } - } - } - - private Object[] multicall(IProgressMonitor monitor, Map<String, Object>... calls) throws TracException { - Object[] result = (Object[]) call(monitor, "system.multicall", new Object[] { calls }); //$NON-NLS-1$ - for (Object item : result) { - try { - checkForException(item); - } catch (XmlRpcException e) { - throw new TracRemoteException(e); - } catch (Exception e) { - throw new TracException(e); - } - } - return result; - } - - private void checkForException(Object result) throws NumberFormatException, XmlRpcException { - if (result instanceof Map) { - Map<?, ?> exceptionData = (Map<?, ?>) result; - if (exceptionData.containsKey("faultCode") && exceptionData.containsKey("faultString")) { //$NON-NLS-1$ //$NON-NLS-2$ - throw new XmlRpcException(Integer.parseInt(exceptionData.get("faultCode").toString()), //$NON-NLS-1$ - (String) exceptionData.get("faultString")); //$NON-NLS-1$ - } - } - } - - private Map<String, Object> createMultiCall(String methodName, Object... parameters) throws TracException { - Map<String, Object> table = new HashMap<String, Object>(); - table.put("methodName", methodName); //$NON-NLS-1$ - table.put("params", parameters); //$NON-NLS-1$ - return table; - } - - private Object getMultiCallResult(Object item) { - return ((Object[]) item)[0]; - } - - public void validate(IProgressMonitor monitor) throws TracException { - try { - Object[] result = (Object[]) call(monitor, "system.getAPIVersion"); //$NON-NLS-1$ - if (result.length >= 3) { - epochAPIVersion = (Integer) result[0]; - majorAPIVersion = (Integer) result[1]; - minorAPIVersion = (Integer) result[2]; - } else if (result.length >= 2) { - epochAPIVersion = 0; - majorAPIVersion = (Integer) result[0]; - minorAPIVersion = (Integer) result[1]; - } else { - throw new TracException( - "The API version is unsupported, please update your Trac XML-RPC Plugin to revision " //$NON-NLS-1$ - + REQUIRED_REVISION + " or later"); //$NON-NLS-1$ - } - } catch (TracNoSuchMethodException e) { - throw new TracException( - "Required API calls are missing, please update your Trac XML-RPC Plugin to revision " //$NON-NLS-1$ - + REQUIRED_REVISION + " or later"); //$NON-NLS-1$ - } - - if (!isAPIVersionOrHigher(REQUIRED_EPOCH, REQUIRED_MAJOR, REQUIRED_MINOR, monitor)) { - throw new TracException("The API version " + majorAPIVersion + "." + minorAPIVersion //$NON-NLS-1$ //$NON-NLS-2$ - + " is unsupported, please update your Trac XML-RPC Plugin to revision " + REQUIRED_REVISION //$NON-NLS-1$ - + " or later"); //$NON-NLS-1$ - } - } - - private void updateAPIVersion(IProgressMonitor monitor) throws TracException { - if (epochAPIVersion == -1 || majorAPIVersion == -1 || minorAPIVersion == -1) { - validate(monitor); - } - } - - private boolean isAPIVersionOrHigher(int epoch, int major, int minor, IProgressMonitor monitor) - throws TracException { - updateAPIVersion(monitor); - return (epochAPIVersion > epoch || (epochAPIVersion == epoch && majorAPIVersion > major || (majorAPIVersion == major && minorAPIVersion >= minor))); - } - - public TracTicket getTicket(int id, IProgressMonitor monitor) throws TracException { - Object[] result = (Object[]) call(monitor, "ticket.get", id); //$NON-NLS-1$ - TracTicket ticket = parseTicket(result); - - result = (Object[]) call(monitor, "ticket.changeLog", id, 0); //$NON-NLS-1$ - for (Object item : result) { - ticket.addComment(parseChangeLogEntry((Object[]) item)); - } - - result = (Object[]) call(monitor, "ticket.listAttachments", id); //$NON-NLS-1$ - for (Object item : result) { - ticket.addAttachment(parseAttachment((Object[]) item)); - } - - String[] actions = getActions(id, monitor); - ticket.setActions(actions); - - updateAttributes(new NullProgressMonitor(), false); - TracTicketResolution[] resolutions = getTicketResolutions(); - if (resolutions != null) { - String[] resolutionStrings = new String[resolutions.length]; - for (int i = 0; i < resolutions.length; i++) { - resolutionStrings[i] = resolutions[i].getName(); - } - ticket.setResolutions(resolutionStrings); - } else { - ticket.setResolutions(getDefaultTicketResolutions()); - } - - return ticket; - } - - private TracAttachment parseAttachment(Object[] entry) { - TracAttachment attachment = new TracAttachment((String) entry[0]); - attachment.setDescription((String) entry[1]); - attachment.setSize((Integer) entry[2]); - attachment.setCreated(parseDate(entry[3])); - attachment.setAuthor((String) entry[4]); - return attachment; - } - - private TracComment parseChangeLogEntry(Object[] entry) { - TracComment comment = new TracComment(); - comment.setCreated(parseDate(entry[0])); - comment.setAuthor((String) entry[1]); - comment.setField((String) entry[2]); - comment.setOldValue((String) entry[3]); - comment.setNewValue((String) entry[4]); - return comment; - } - - /* public for testing */ - @SuppressWarnings("unchecked") - public List<TracTicket> getTickets(int[] ids, IProgressMonitor monitor) throws TracException { - Map<String, Object>[] calls = new Map[ids.length]; - for (int i = 0; i < calls.length; i++) { - calls[i] = createMultiCall("ticket.get", ids[i]); //$NON-NLS-1$ - } - - Object[] result = multicall(monitor, calls); - assert result.length == ids.length; - - List<TracTicket> tickets = new ArrayList<TracTicket>(result.length); - for (Object item : result) { - Object[] ticketResult = (Object[]) getMultiCallResult(item); - tickets.add(parseTicket(ticketResult)); - } - - return tickets; - } - - @SuppressWarnings("unchecked") - public void search(TracSearch query, List<TracTicket> tickets, IProgressMonitor monitor) throws TracException { - // an empty query string is not valid, therefore prepend order - Object[] result = (Object[]) call(monitor, "ticket.query", "order=id" + query.toQuery()); //$NON-NLS-1$ //$NON-NLS-2$ - - Map<String, Object>[] calls = new Map[result.length]; - for (int i = 0; i < calls.length; i++) { - calls[i] = createMultiCall("ticket.get", result[i]); //$NON-NLS-1$ - } - result = multicall(monitor, calls); - - for (Object item : result) { - Object[] ticketResult = (Object[]) getMultiCallResult(item); - tickets.add(parseTicket(ticketResult)); - } - } - - private TracTicket parseTicket(Object[] ticketResult) throws InvalidTicketException { - TracTicket ticket = new TracTicket((Integer) ticketResult[0]); - ticket.setCreated(parseDate(ticketResult[1])); - ticket.setLastChanged(parseDate(ticketResult[2])); - Map<?, ?> attributes = (Map<?, ?>) ticketResult[3]; - for (Object key : attributes.keySet()) { - ticket.putValue(key.toString(), attributes.get(key).toString()); - } - return ticket; - } - - private Date parseDate(Object object) { - if (object instanceof Date) { - return (Date) object; - } else if (object instanceof Integer) { - return TracUtil.parseDate((Integer) object); - } - throw new ClassCastException("Unexpected object type for date: " + object.getClass()); //$NON-NLS-1$ - } - - @Override - public synchronized void updateAttributes(IProgressMonitor monitor) throws TracException { - monitor.beginTask("Updating attributes", 9); //$NON-NLS-1$ - - Object[] result = getAttributes("ticket.component", monitor); //$NON-NLS-1$ - data.components = new ArrayList<TracComponent>(result.length); - for (Object item : result) { - data.components.add(parseComponent((Map<?, ?>) getMultiCallResult(item))); - } - advance(monitor, 1); - - result = getAttributes("ticket.milestone", monitor); //$NON-NLS-1$ - data.milestones = new ArrayList<TracMilestone>(result.length); - for (Object item : result) { - data.milestones.add(parseMilestone((Map<?, ?>) getMultiCallResult(item))); - } - advance(monitor, 1); - - List<TicketAttributeResult> attributes = getTicketAttributes("ticket.priority", monitor); //$NON-NLS-1$ - data.priorities = new ArrayList<TracPriority>(result.length); - for (TicketAttributeResult attribute : attributes) { - data.priorities.add(new TracPriority(attribute.name, attribute.value)); - } - Collections.sort(data.priorities); - advance(monitor, 1); - - attributes = getTicketAttributes("ticket.resolution", monitor); //$NON-NLS-1$ - data.ticketResolutions = new ArrayList<TracTicketResolution>(result.length); - for (TicketAttributeResult attribute : attributes) { - data.ticketResolutions.add(new TracTicketResolution(attribute.name, attribute.value)); - } - Collections.sort(data.ticketResolutions); - advance(monitor, 1); - - attributes = getTicketAttributes("ticket.severity", monitor); //$NON-NLS-1$ - data.severities = new ArrayList<TracSeverity>(result.length); - for (TicketAttributeResult attribute : attributes) { - data.severities.add(new TracSeverity(attribute.name, attribute.value)); - } - Collections.sort(data.severities); - advance(monitor, 1); - - boolean trac011 = isAPIVersionOrHigher(1, 0, 0, monitor); - attributes = getTicketAttributes("ticket.status", trac011, monitor); //$NON-NLS-1$ - data.ticketStatus = new ArrayList<TracTicketStatus>(result.length); - for (TicketAttributeResult attribute : attributes) { - data.ticketStatus.add(new TracTicketStatus(attribute.name, attribute.value)); - } - Collections.sort(data.ticketStatus); - advance(monitor, 1); - - attributes = getTicketAttributes("ticket.type", monitor); //$NON-NLS-1$ - data.ticketTypes = new ArrayList<TracTicketType>(result.length); - for (TicketAttributeResult attribute : attributes) { - data.ticketTypes.add(new TracTicketType(attribute.name, attribute.value)); - } - Collections.sort(data.ticketTypes); - advance(monitor, 1); - - result = getAttributes("ticket.version", monitor); //$NON-NLS-1$ - data.versions = new ArrayList<TracVersion>(result.length); - for (Object item : result) { - data.versions.add(parseVersion((Map<?, ?>) getMultiCallResult(item))); - } - advance(monitor, 1); - - result = (Object[]) call(monitor, "ticket.getTicketFields"); //$NON-NLS-1$ - data.ticketFields = new ArrayList<TracTicketField>(result.length); - for (Object item : result) { - data.ticketFields.add(parseTicketField((Map<?, ?>) item)); - } - advance(monitor, 1); - } - - private void advance(IProgressMonitor monitor, int worked) { - monitor.worked(worked); - if (monitor.isCanceled()) { - throw new OperationCanceledException(); - } - - } - - private TracComponent parseComponent(Map<?, ?> result) { - TracComponent component = new TracComponent((String) result.get("name")); //$NON-NLS-1$ - component.setOwner((String) result.get("owner")); //$NON-NLS-1$ - component.setDescription((String) result.get("description")); //$NON-NLS-1$ - return component; - } - - private TracMilestone parseMilestone(Map<?, ?> result) { - TracMilestone milestone = new TracMilestone((String) result.get("name")); //$NON-NLS-1$ - milestone.setCompleted(parseDate(result.get("completed"))); //$NON-NLS-1$ - milestone.setDue(parseDate(result.get("due"))); //$NON-NLS-1$ - milestone.setDescription((String) result.get("description")); //$NON-NLS-1$ - return milestone; - } - - private TracVersion parseVersion(Map<?, ?> result) { - TracVersion version = new TracVersion((String) result.get("name")); //$NON-NLS-1$ - version.setTime(parseDate(result.get("time"))); //$NON-NLS-1$ - version.setDescription((String) result.get("description")); //$NON-NLS-1$ - return version; - } - - private TracTicketField parseTicketField(Map<?, ?> result) { - TracTicketField field = new TracTicketField((String) result.get("name")); //$NON-NLS-1$ - field.setType(TracTicketField.Type.fromString((String) result.get("type"))); //$NON-NLS-1$ - field.setLabel((String) result.get("label")); //$NON-NLS-1$ - field.setDefaultValue((String) result.get("value")); //$NON-NLS-1$ - Object[] items = (Object[]) result.get("options"); //$NON-NLS-1$ - if (items != null) { - String[] options = new String[items.length]; - for (int i = 0; i < items.length; i++) { - options[i] = (String) items[i]; - } - field.setOptions(options); - } - if (result.get("custom") != null) { //$NON-NLS-1$ - field.setCustom((Boolean) result.get("custom")); //$NON-NLS-1$ - } - if (result.get("order") != null) { //$NON-NLS-1$ - field.setOrder((Integer) result.get("order")); //$NON-NLS-1$ - } - if (result.get("optional") != null) { //$NON-NLS-1$ - field.setOptional((Boolean) result.get("optional")); //$NON-NLS-1$ - } - if (result.get("width") != null) { //$NON-NLS-1$ - field.setWidth((Integer) result.get("width")); //$NON-NLS-1$ - } - if (result.get("height") != null) { //$NON-NLS-1$ - field.setHeight((Integer) result.get("height")); //$NON-NLS-1$ - } - return field; - } - - @SuppressWarnings("unchecked") - private Object[] getAttributes(String attributeType, IProgressMonitor monitor) throws TracException { - Object[] ids = (Object[]) call(monitor, attributeType + ".getAll"); //$NON-NLS-1$ - Map<String, Object>[] calls = new Map[ids.length]; - for (int i = 0; i < calls.length; i++) { - calls[i] = createMultiCall(attributeType + ".get", ids[i]); //$NON-NLS-1$ - } - - Object[] result = multicall(monitor, calls); - assert result.length == ids.length; - - return result; - } - - private List<TicketAttributeResult> getTicketAttributes(String attributeType, IProgressMonitor monitor) - throws TracException { - return getTicketAttributes(attributeType, false, monitor); - } - - @SuppressWarnings("unchecked") - private List<TicketAttributeResult> getTicketAttributes(String attributeType, boolean assignValues, - IProgressMonitor monitor) throws TracException { - // get list of attribute ids first - Object[] ids = (Object[]) call(monitor, attributeType + ".getAll"); //$NON-NLS-1$ - // fetch all attributes in a single call - Map<String, Object>[] calls = new Map[ids.length]; - for (int i = 0; i < calls.length; i++) { - calls[i] = createMultiCall(attributeType + ".get", ids[i]); //$NON-NLS-1$ - } - - Object[] result = multicall(monitor, calls); - assert result.length == ids.length; - - List<TicketAttributeResult> attributes = new ArrayList<TicketAttributeResult>(result.length); - for (int i = 0; i < calls.length; i++) { - try { - TicketAttributeResult attribute = new TicketAttributeResult(); - attribute.name = (String) ids[i]; - Object value = getMultiCallResult(result[i]); - if (assignValues) { - attribute.value = i; - } else { - attribute.value = (value instanceof Integer) ? (Integer) value : Integer.parseInt((String) value); - } - attributes.add(attribute); - } catch (ClassCastException e) { - StatusHandler.log(new Status(IStatus.WARNING, TracCorePlugin.ID_PLUGIN, - "Invalid response from Trac repository for attribute type: '" + attributeType + "'", e)); //$NON-NLS-1$ //$NON-NLS-2$ - } catch (NumberFormatException e) { - StatusHandler.log(new Status(IStatus.WARNING, TracCorePlugin.ID_PLUGIN, - "Invalid response from Trac repository for attribute type: '" + attributeType + "'", e)); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - return attributes; - } - - public InputStream getAttachmentData(int ticketId, String filename, IProgressMonitor monitor) throws TracException { - byte[] data = (byte[]) call(monitor, "ticket.getAttachment", ticketId, filename); //$NON-NLS-1$ - return new ByteArrayInputStream(data); - } - - public void putAttachmentData(int ticketId, String filename, String description, InputStream in, - IProgressMonitor monitor) throws TracException { - byte[] data; - try { - data = readData(in, new NullProgressMonitor()); - } catch (IOException e) { - throw new TracException(e); - } - call(monitor, "ticket.putAttachment", ticketId, filename, description, data, false); //$NON-NLS-1$ - } - - private byte[] readData(InputStream in, IProgressMonitor monitor) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - byte[] buffer = new byte[512]; - while (true) { - int count = in.read(buffer); - if (count == -1) { - return out.toByteArray(); - } - if (monitor.isCanceled()) { - throw new OperationCanceledException(); - } - out.write(buffer, 0, count); - if (monitor.isCanceled()) { - throw new OperationCanceledException(); - } - } - } finally { - try { - in.close(); - } catch (IOException e) { - StatusHandler.log(new Status(IStatus.ERROR, TracCorePlugin.ID_PLUGIN, - "Error closing attachment stream", e)); //$NON-NLS-1$ - } - } - } - - public void deleteAttachment(int ticketId, String filename, IProgressMonitor monitor) throws TracException { - call(monitor, "ticket.deleteAttachment", ticketId, filename); //$NON-NLS-1$ - } - - private class TicketAttributeResult { - - String name; - - int value; - - } - - public int createTicket(TracTicket ticket, IProgressMonitor monitor) throws TracException { - Map<String, String> attributes = ticket.getValues(); - String summary = attributes.remove(Key.SUMMARY.getKey()); - String description = attributes.remove(Key.DESCRIPTION.getKey()); - if (summary == null || description == null) { - throw new InvalidTicketException(); - } - if (isAPIVersionOrHigher(0, 0, 2, monitor)) { - return (Integer) call(monitor, "ticket.create", summary, description, attributes, true); //$NON-NLS-1$ - } else { - return (Integer) call(monitor, "ticket.create", summary, description, attributes); //$NON-NLS-1$ - } - } - - public void updateTicket(TracTicket ticket, String comment, IProgressMonitor monitor) throws TracException { - updateAPIVersion(monitor); - - Map<String, String> attributes = ticket.getValues(); - if (isAPIVersionOrHigher(0, 0, 2, monitor)) { - call(monitor, "ticket.update", ticket.getId(), comment, attributes, true); //$NON-NLS-1$ - } else { - call(monitor, "ticket.update", ticket.getId(), comment, attributes); //$NON-NLS-1$ - } - } - - public Set<Integer> getChangedTickets(Date since, IProgressMonitor monitor) throws TracException { - Object[] ids; - ids = (Object[]) call(monitor, "ticket.getRecentChanges", since); //$NON-NLS-1$ - Set<Integer> result = new HashSet<Integer>(); - for (Object id : ids) { - result.add((Integer) id); - } - return result; - } - - public String[] getActions(int id, IProgressMonitor monitor) throws TracException { - Object[] actions = (Object[]) call(monitor, "ticket.getAvailableActions", id); //$NON-NLS-1$ - String[] result = new String[actions.length]; - for (int i = 0; i < result.length; i++) { - result[i] = (String) actions[i]; - } - return result; - } - - public Date getTicketLastChanged(Integer id, IProgressMonitor monitor) throws TracException { - Object[] result = (Object[]) call(monitor, "ticket.get", id); //$NON-NLS-1$ - return parseDate(result[2]); - } - - public void validateWikiRpcApi(IProgressMonitor monitor) throws TracException { - if (((Integer) call(monitor, "wiki.getRPCVersionSupported")) < 2) { //$NON-NLS-1$ - validate(monitor); - } - } - - public String wikiToHtml(String sourceText, IProgressMonitor monitor) throws TracException { - return (String) call(monitor, "wiki.wikiToHtml", sourceText); //$NON-NLS-1$ - } - - public String[] getAllWikiPageNames(IProgressMonitor monitor) throws TracException { - Object[] result = (Object[]) call(monitor, "wiki.getAllPages"); //$NON-NLS-1$ - String[] wikiPageNames = new String[result.length]; - for (int i = 0; i < wikiPageNames.length; i++) { - wikiPageNames[i] = (String) result[i]; - } - return wikiPageNames; - } - - public TracWikiPageInfo getWikiPageInfo(String pageName, IProgressMonitor monitor) throws TracException { - return getWikiPageInfo(pageName, LATEST_VERSION, null); - } - - public TracWikiPageInfo getWikiPageInfo(String pageName, int version, IProgressMonitor monitor) - throws TracException { - // Note: if an unexpected null value is passed to XmlRpcPlugin, XmlRpcClient will throw a TracRemoteException. - // So, this null-parameter checking may be omitted if resorting to XmlRpcClient is more appropriate. - if (pageName == null) { - throw new IllegalArgumentException("Wiki page name cannot be null"); //$NON-NLS-1$ - } - - Object result = (version == LATEST_VERSION) ? call(monitor, "wiki.getPageInfo", pageName) // //$NON-NLS-1$ - : call(monitor, "wiki.getPageInfoVersion", pageName, version); //$NON-NLS-1$ - return parseWikiPageInfo(result); - } - - @SuppressWarnings("unchecked") - public TracWikiPageInfo[] getWikiPageInfoAllVersions(String pageName, IProgressMonitor monitor) - throws TracException { - TracWikiPageInfo latestVersion = getWikiPageInfo(pageName, null); - Map<String, Object>[] calls = new Map[latestVersion.getVersion() - 1]; - for (int i = 0; i < calls.length; i++) { - calls[i] = createMultiCall("wiki.getPageInfoVersion", pageName, i + 1); //$NON-NLS-1$ - } - - Object[] result = multicall(monitor, calls); - - TracWikiPageInfo[] versions = new TracWikiPageInfo[result.length + 1]; - for (int i = 0; i < result.length; i++) { - Object pageInfoResult = getMultiCallResult(result[i]); - versions[i] = parseWikiPageInfo(pageInfoResult); - } - versions[result.length] = latestVersion; - - return versions; - } - - private TracWikiPageInfo parseWikiPageInfo(Object pageInfoResult) throws InvalidWikiPageException { - // Note: Trac XML-RPC Plugin returns 0 (as Integer) if pageName or version doesn't exist, - // and XmlRpcClient doesn't throw an Exception in this case - if (pageInfoResult instanceof Map<?, ?>) { - TracWikiPageInfo pageInfo = new TracWikiPageInfo(); - Map<?, ?> infoMap = (Map<?, ?>) pageInfoResult; - pageInfo.setPageName((String) infoMap.get("name")); //$NON-NLS-1$ - pageInfo.setAuthor((String) infoMap.get("author")); //$NON-NLS-1$ - pageInfo.setLastModified(parseDate(infoMap.get("lastModified"))); //$NON-NLS-1$ - pageInfo.setVersion((Integer) infoMap.get("version")); //$NON-NLS-1$ - return pageInfo; - } else { - throw new InvalidWikiPageException("Wiki page name or version does not exist"); //$NON-NLS-1$ - } - } - - public String getWikiPageContent(String pageName, IProgressMonitor monitor) throws TracException { - return getWikiPageContent(pageName, LATEST_VERSION, null); - } - - public String getWikiPageContent(String pageName, int version, IProgressMonitor monitor) throws TracException { - // Note: if an unexpected null value is passed to XmlRpcPlugin, XmlRpcClient will throw a TracRemoteException. - // So, this null-parameter checking may be omitted if resorting to XmlRpcClient is more appropriate. - if (pageName == null) { - throw new IllegalArgumentException("Wiki page name cannot be null"); //$NON-NLS-1$ - } - if (version == LATEST_VERSION) { - // XmlRpcClient throws a TracRemoteException if pageName or version doesn't exist - return (String) call(monitor, "wiki.getPage", pageName); //$NON-NLS-1$ - } else { - return (String) call(monitor, "wiki.getPageVersion", pageName, version); //$NON-NLS-1$ - } - } - - public String getWikiPageHtml(String pageName, IProgressMonitor monitor) throws TracException { - return getWikiPageHtml(pageName, LATEST_VERSION, null); - } - - public String getWikiPageHtml(String pageName, int version, IProgressMonitor monitor) throws TracException { - if (pageName == null) { - throw new IllegalArgumentException("Wiki page name cannot be null"); //$NON-NLS-1$ - } - - if (version == LATEST_VERSION) { - // XmlRpcClient throws a TracRemoteException if pageName or version doesn't exist - return (String) call(monitor, "wiki.getPageHTML", pageName); //$NON-NLS-1$ - } else { - return (String) call(monitor, "wiki.getPageHTMLVersion", pageName, version); //$NON-NLS-1$ - } - } - - public TracWikiPageInfo[] getRecentWikiChanges(Date since, IProgressMonitor monitor) throws TracException { - if (since == null) { - throw new IllegalArgumentException("Date parameter cannot be null"); //$NON-NLS-1$ - } - - Object[] result = (Object[]) call(monitor, "wiki.getRecentChanges", since); //$NON-NLS-1$ - TracWikiPageInfo[] changes = new TracWikiPageInfo[result.length]; - for (int i = 0; i < result.length; i++) { - changes[i] = parseWikiPageInfo(result[i]); - } - return changes; - } - - public TracWikiPage getWikiPage(String pageName, IProgressMonitor monitor) throws TracException { - return getWikiPage(pageName, LATEST_VERSION, null); - } - - public TracWikiPage getWikiPage(String pageName, int version, IProgressMonitor monitor) throws TracException { - TracWikiPage page = new TracWikiPage(); - page.setPageInfo(getWikiPageInfo(pageName, version, null)); - page.setContent(getWikiPageContent(pageName, version, null)); - page.setPageHTML(getWikiPageHtml(pageName, version, null)); - return page; - } - - public boolean putWikipage(String pageName, String content, Map<String, Object> attributes, IProgressMonitor monitor) - throws TracException { - Boolean result = (Boolean) call(monitor, "wiki.putPage", pageName, content, attributes); //$NON-NLS-1$ - return result.booleanValue(); - } - - public String[] listWikiPageAttachments(String pageName, IProgressMonitor monitor) throws TracException { - Object[] result = (Object[]) call(monitor, "wiki.listAttachments", pageName); //$NON-NLS-1$ - String[] attachments = new String[result.length]; - for (int i = 0; i < attachments.length; i++) { - attachments[i] = (String) result[i]; - } - return attachments; - } - - public InputStream getWikiPageAttachmentData(String pageName, String fileName, IProgressMonitor monitor) - throws TracException { - String attachmentName = pageName + "/" + fileName; //$NON-NLS-1$ - byte[] data = (byte[]) call(monitor, "wiki.getAttachment", attachmentName); //$NON-NLS-1$ - return new ByteArrayInputStream(data); - } - - /** - * Attach a file to a Wiki page on the repository. - * <p> - * This implementation uses the wiki.putAttachmentEx() call, which provides a richer functionality specific to Trac. - * - * @param pageName - * the name of the Wiki page - * @param fileName - * the name of the file to be attached - * @param description - * the description of the attachment - * @param in - * An InputStream of the content of the attachment - * @param replace - * whether to overwrite an existing attachment with the same filename - * @return The (possibly transformed) filename of the attachment. If <code>replace</code> is <code>true</code>, the - * returned name is always the same as the argument <code>fileName</code>; if <code>replace</code> is - * <code>false</code> and an attachment with name <code>fileName</code> already exists, a number is appended - * to the file name (before suffix) and the generated filename of the attachment is returned. - * @throws TracException - */ - public String putWikiPageAttachmentData(String pageName, String fileName, String description, InputStream in, - boolean replace, IProgressMonitor monitor) throws TracException { - byte[] data; - try { - data = readData(in, new NullProgressMonitor()); - } catch (IOException e) { - throw new TracException(e); - } - return (String) call(monitor, "wiki.putAttachmentEx", pageName, fileName, description, data, replace); //$NON-NLS-1$ - } - - public void deleteTicket(int ticketId, IProgressMonitor monitor) throws TracException { - call(monitor, "ticket.delete", ticketId); //$NON-NLS-1$ - } - -}
\ No newline at end of file |