# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: D:\Coding\External\jenkins-redmine-plugin\trunk # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: pom.xml --- pom.xml Base (BASE) +++ pom.xml Locally Modified (Based On LOCAL) @@ -5,7 +5,7 @@ org.jenkins-ci.plugins plugin - 1.466 + 1.568 redmine @@ -43,6 +43,24 @@ 0.14 + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-surefire-plugin + + + InjectedTest.java + + + @@ -61,7 +79,8 @@ com.taskadapter redmine-java-api - 1.15 + 1.23 + jar com.googlecode.jmockit @@ -79,6 +98,18 @@ postgresql 9.1-901-1.jdbc4 + + org.apache.httpcomponents + httpclient + 4.2 + jar + + + commons-lang + commons-lang + 2.6 + jar + Index: src/main/java/com/taskadapter/redmineapi/internal/Transport.java --- src/main/java/com/taskadapter/redmineapi/internal/Transport.java Base (BASE) +++ src/main/java/com/taskadapter/redmineapi/internal/Transport.java Locally Deleted @@ -1,529 +0,0 @@ -package com.taskadapter.redmineapi.internal; - -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.httpclient.protocol.Protocol; -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.InputStreamEntity; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicNameValuePair; -import org.json.JSONException; -import org.json.JSONObject; -import com.taskadapter.redmineapi.RedmineOptions; -import com.taskadapter.redmineapi.NotFoundException; -import com.taskadapter.redmineapi.RedmineAuthenticationException; -import com.taskadapter.redmineapi.RedmineException; -import com.taskadapter.redmineapi.RedmineFormatException; -import com.taskadapter.redmineapi.RedmineInternalError; -import com.taskadapter.redmineapi.RedmineManager; -import com.taskadapter.redmineapi.bean.Identifiable; -import com.taskadapter.redmineapi.bean.Issue; -import com.taskadapter.redmineapi.bean.IssueCategory; -import com.taskadapter.redmineapi.bean.IssueRelation; -import com.taskadapter.redmineapi.bean.IssueStatus; -import com.taskadapter.redmineapi.bean.Membership; -import com.taskadapter.redmineapi.bean.News; -import com.taskadapter.redmineapi.bean.Project; -import com.taskadapter.redmineapi.bean.Role; -import com.taskadapter.redmineapi.bean.SavedQuery; -import com.taskadapter.redmineapi.bean.TimeEntry; -import com.taskadapter.redmineapi.bean.Tracker; -import com.taskadapter.redmineapi.bean.User; -import com.taskadapter.redmineapi.bean.Version; -import com.taskadapter.redmineapi.internal.comm.BaseCommunicator; -import com.taskadapter.redmineapi.internal.comm.BasicHttpResponse; -import com.taskadapter.redmineapi.internal.comm.Communicator; -import com.taskadapter.redmineapi.internal.comm.Communicators; -import com.taskadapter.redmineapi.internal.comm.ContentHandler; -import com.taskadapter.redmineapi.internal.comm.SimpleCommunicator; -import com.taskadapter.redmineapi.internal.comm.redmine.RedmineAuthenticator; -import com.taskadapter.redmineapi.internal.comm.redmine.RedmineErrorHandler; -import com.taskadapter.redmineapi.internal.json.JsonInput; -import com.taskadapter.redmineapi.internal.json.JsonObjectParser; -import com.taskadapter.redmineapi.internal.json.JsonObjectWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Redmine transport utilities. - */ -public final class Transport { - private static final Map, EntityConfig> OBJECT_CONFIGS = new HashMap, EntityConfig>(); - private static final String CONTENT_TYPE = "application/json; charset=utf-8"; - private static final int DEFAULT_OBJECTS_PER_PAGE = 25; - private static final String KEY_TOTAL_COUNT = "total_count"; - private final Logger logger = LoggerFactory.getLogger(RedmineManager.class); - private SimpleCommunicator communicator; - private final Communicator errorCheckingCommunicator; - private final BaseCommunicator baseCommunicator; - private final RedmineAuthenticator authenticator; - private final Communicator coreCommunicator; - - static { - OBJECT_CONFIGS.put( - Project.class, - config("project", "projects", - RedmineJSONBuilder.PROJECT_WRITER, - RedmineJSONParser.PROJECT_PARSER)); - OBJECT_CONFIGS.put( - Issue.class, - config("issue", "issues", RedmineJSONBuilder.ISSUE_WRITER, - RedmineJSONParser.ISSUE_PARSER)); - OBJECT_CONFIGS.put( - User.class, - config("user", "users", RedmineJSONBuilder.USER_WRITER, - RedmineJSONParser.USER_PARSER)); - OBJECT_CONFIGS.put( - IssueCategory.class, - config("issue_category", "issue_categories", - RedmineJSONBuilder.CATEGORY_WRITER, - RedmineJSONParser.CATEGORY_PARSER)); - OBJECT_CONFIGS.put( - Version.class, - config("version", "versions", - RedmineJSONBuilder.VERSION_WRITER, - RedmineJSONParser.VERSION_PARSER)); - OBJECT_CONFIGS.put( - TimeEntry.class, - config("time_entry", "time_entries", - RedmineJSONBuilder.TIME_ENTRY_WRITER, - RedmineJSONParser.TIME_ENTRY_PARSER)); - OBJECT_CONFIGS.put(News.class, - config("news", "news", null, RedmineJSONParser.NEWS_PARSER)); - OBJECT_CONFIGS.put( - IssueRelation.class, - config("relation", "relations", - RedmineJSONBuilder.RELATION_WRITER, - RedmineJSONParser.RELATION_PARSER)); - OBJECT_CONFIGS.put( - Tracker.class, - config("tracker", "trackers", null, - RedmineJSONParser.TRACKER_PARSER)); - OBJECT_CONFIGS.put( - IssueStatus.class, - config("status", "issue_statuses", null, - RedmineJSONParser.STATUS_PARSER)); - OBJECT_CONFIGS - .put(SavedQuery.class, - config("query", "queries", null, - RedmineJSONParser.QUERY_PARSER)); - OBJECT_CONFIGS.put(Role.class, - config("role", "roles", null, RedmineJSONParser.ROLE_PARSER)); - OBJECT_CONFIGS.put( - Membership.class, - config("membership", "memberships", - RedmineJSONBuilder.MEMBERSHIP_WRITER, - RedmineJSONParser.MEMBERSHIP_PARSER)); - } - - private final URIConfigurator configurator; - private String login; - private String password; - private int objectsPerPage = DEFAULT_OBJECTS_PER_PAGE; - private static final String CHARSET = "UTF-8"; - - public Transport(URIConfigurator configurator, RedmineOptions options) { - this.configurator = configurator; - this.baseCommunicator = new BaseCommunicator(options); - this.authenticator = new RedmineAuthenticator( - baseCommunicator, CHARSET); - final ContentHandler errorProcessor = new RedmineErrorHandler(); - errorCheckingCommunicator = Communicators.fmap( - authenticator, - Communicators.compose(errorProcessor, - Communicators.transportDecoder())); - coreCommunicator = Communicators.fmap(errorCheckingCommunicator, - Communicators.contentReader()); - this.communicator = Communicators.simplify(coreCommunicator, - Communicators.identityHandler()); - } - - public User getCurrentUser(NameValuePair... params) throws RedmineException { - URI uri = getURIConfigurator().createURI("users/current.json", params); - HttpGet http = new HttpGet(uri); - String response = getCommunicator().sendRequest(http); - return parseResponse(response, "user", RedmineJSONParser.USER_PARSER); - } - - /** - * Performs an "add object" request. - * - * @param object - * object to use. - * @param params - * name params. - * @return object to use. - * @throws RedmineException - * if something goes wrong. - */ - public T addObject(T object, NameValuePair... params) - throws RedmineException { - final EntityConfig config = getConfig(object.getClass()); - URI uri = getURIConfigurator().getObjectsURI(object.getClass(), params); - HttpPost httpPost = new HttpPost(uri); - String body = RedmineJSONBuilder.toSimpleJSON(config.singleObjectName, - object, config.writer); - setEntity(httpPost, body); - String response = getCommunicator().sendRequest(httpPost); - logger.debug(response); - return parseResponse(response, config.singleObjectName, config.parser); - } - - /** - * Performs an "add child object" request. - * - * @param parentClass - * parent object id. - * @param object - * object to use. - * @param params - * name params. - * @return object to use. - * @throws RedmineException - * if something goes wrong. - */ - public T addChildEntry(Class parentClass, String parentId, T object, - NameValuePair... params) throws RedmineException { - final EntityConfig config = getConfig(object.getClass()); - URI uri = getURIConfigurator().getChildObjectsURI(parentClass, - parentId, object.getClass(), params); - HttpPost httpPost = new HttpPost(uri); - String body = RedmineJSONBuilder.toSimpleJSON(config.singleObjectName, - object, config.writer); - setEntity(httpPost, body); - String response = getCommunicator().sendRequest(httpPost); - logger.debug(response); - return parseResponse(response, config.singleObjectName, config.parser); - } - - /* - * note: This method cannot return the updated object from Redmine because - * the server does not provide any XML in response. - * - * @since 1.8.0 - */ - public void updateObject(T obj, - NameValuePair... params) throws RedmineException { - final EntityConfig config = getConfig(obj.getClass()); - final URI uri = getURIConfigurator().getObjectURI(obj.getClass(), - Integer.toString(obj.getId())); - final HttpPut http = new HttpPut(uri); - - final String body = RedmineJSONBuilder.toSimpleJSON( - config.singleObjectName, obj, config.writer); - setEntity(http, body); - - getCommunicator().sendRequest(http); - } - - /** - * Deletes an object. - * - * @param classs - * object class. - * @param id - * object id. - * @throws RedmineException - * if something goes wrong. - */ - public void deleteObject(Class classs, String id) - throws RedmineException { - final URI uri = getURIConfigurator().getObjectURI(classs, id); - final HttpDelete http = new HttpDelete(uri); - getCommunicator().sendRequest(http); - } - - /** - * @param classs - * target class - * @param key - * item key - * @param args - * extra arguments. - * @throws RedmineAuthenticationException - * invalid or no API access key is used with the server, which - * requires authorization. Check the constructor arguments. - * @throws NotFoundException - * the object with the given key is not found - * @throws RedmineException - */ - public T getObject(Class classs, String key, NameValuePair... args) - throws RedmineException { - final EntityConfig config = getConfig(classs); - final URI uri = getURIConfigurator().getObjectURI(classs, key, args); - final HttpGet http = new HttpGet(uri); - String response = getCommunicator().sendRequest(http); - logger.debug(response); - return parseResponse(response, config.singleObjectName, config.parser); - } - - /** - * Downloads a redmine content. - * - * @param uri - * target uri. - * @param handler - * content handler. - * @return handler result. - * @throws RedmineException - * if something goes wrong. - */ - public R download(String uri, - ContentHandler handler) - throws RedmineException { - final HttpGet request = new HttpGet(uri); - return errorCheckingCommunicator.sendRequest(request, handler); - } - - /** - * UPloads content on a server. - * - * @param content - * content stream. - * @return uploaded item token. - * @throws RedmineException - * if something goes wrong. - */ - public String upload(InputStream content) throws RedmineException { - final URI uploadURI = getURIConfigurator().getUploadURI(); - final HttpPost request = new HttpPost(uploadURI); - final AbstractHttpEntity entity = new InputStreamEntity(content, -1); - /* Content type required by a Redmine */ - entity.setContentType("application/octet-stream"); - request.setEntity(entity); - - final String result = getCommunicator().sendRequest(request); - return parseResponse(result, "upload", - RedmineJSONParser.UPLOAD_TOKEN_PARSER); - } - - /** - * @param classs - * target class - * @param key - * item key - * @param args - * extra arguments. - * @throws RedmineAuthenticationException - * invalid or no API access key is used with the server, which - * requires authorization. Check the constructor arguments. - * @throws NotFoundException - * the object with the given key is not found - * @throws RedmineException - */ - public T getObject(Class classs, Integer key, NameValuePair... args) - throws RedmineException { - return getObject(classs, key.toString(), args); - } - - public List getObjectsList(Class objectClass, - NameValuePair... params) throws RedmineException { - return getObjectsList(objectClass, Arrays.asList(params)); - } - - /** - * Returns an object list. - * - * @return objects list, never NULL - */ - public List getObjectsList(Class objectClass, - Collection params) throws RedmineException { - final EntityConfig config = getConfig(objectClass); - final List result = new ArrayList(); - - final List newParams = new ArrayList( - params); - - newParams.add(new BasicNameValuePair("limit", String - .valueOf(objectsPerPage))); - int offset = 0; - - int totalObjectsFoundOnServer; - do { - List paramsList = new ArrayList( - newParams); - paramsList.add(new BasicNameValuePair("offset", String - .valueOf(offset))); - - final URI uri = getURIConfigurator().getObjectsURI(objectClass, - paramsList); - - logger.debug(uri.toString()); - final HttpGet http = new HttpGet(uri); - - final String response = getCommunicator().sendRequest(http); - logger.debug("received: " + response); - - final List foundItems; - try { - final JSONObject responseObject = RedmineJSONParser - .getResponse(response); - foundItems = JsonInput.getListOrNull(responseObject, - config.multiObjectName, config.parser); - result.addAll(foundItems); - - /* Necessary for trackers */ - if (!responseObject.has(KEY_TOTAL_COUNT)) { - break; - } - totalObjectsFoundOnServer = JsonInput.getInt(responseObject, - KEY_TOTAL_COUNT); - } catch (JSONException e) { - throw new RedmineFormatException(e); - } - - if (foundItems.size() == 0) { - break; - } - - offset += foundItems.size(); - } while (offset < totalObjectsFoundOnServer); - - return result; - } - - /** - * This number of objects (tasks, projects, users) will be requested from - * Redmine server in 1 request. - */ - public int getObjectsPerPage() { - return objectsPerPage; - } - - /** - * Delivers a list of a child entries. - * - * @param classs - * target class. - */ - public List getChildEntries(Class parentClass, String parentId, - Class classs) throws RedmineException { - final EntityConfig config = getConfig(classs); - final URI uri = getURIConfigurator().getChildObjectsURI(parentClass, - parentId, classs); - - HttpGet http = new HttpGet(uri); - String response = getCommunicator().sendRequest(http); - final JSONObject responseObject; - try { - responseObject = RedmineJSONParser.getResponse(response); - return JsonInput.getListNotNull(responseObject, - config.multiObjectName, config.parser); - } catch (JSONException e) { - throw new RedmineFormatException("Bad categories response " + response, e); - } - } - - /** - * This number of objects (tasks, projects, users) will be requested from - * Redmine server in 1 request. - */ - public void setObjectsPerPage(int pageSize) { - if (pageSize <= 0) { - throw new IllegalArgumentException( - "Page size must be >= 0. You provided: " + pageSize); - } - this.objectsPerPage = pageSize; - } - - private SimpleCommunicator getCommunicator() - throws RedmineException { - return communicator; - } - - private static T parseResponse(String response, String tag, - JsonObjectParser parser) throws RedmineFormatException { - try { - return parser.parse(RedmineJSONParser.getResponseSingleObject(response, tag)); - } catch (JSONException e) { - throw new RedmineFormatException(e); - } - } - - private void setEntity(HttpEntityEnclosingRequest request, String body) { - StringEntity entity; - try { - entity = new StringEntity(body, CHARSET); - } catch (UnsupportedEncodingException e) { - throw new RedmineInternalError("Required charset " + CHARSET - + " is not supported", e); - } - entity.setContentType(CONTENT_TYPE); - request.setEntity(entity); - } - - @SuppressWarnings("unchecked") - private EntityConfig getConfig(Class class1) { - final EntityConfig guess = OBJECT_CONFIGS.get(class1); - if (guess == null) - throw new RedmineInternalError("Unsupported class " + class1); - return (EntityConfig) guess; - } - - private URIConfigurator getURIConfigurator() { - return configurator; - } - - private static EntityConfig config(String objectField, - String urlPrefix, JsonObjectWriter writer, - JsonObjectParser parser) { - return new EntityConfig(objectField, urlPrefix, writer, parser); - } - - public void setCredentials(String login, String password) { - this.login = login; - this.password = password; - authenticator.setCredentials(login, password); - } - - public void shutdown() { - baseCommunicator.shutdown(); - } - - public void setPassword(String password) { - setCredentials(login, password); - } - - public void setLogin(String login) { - setCredentials(login, password); - } - - /** - * Entity config. - */ - static class EntityConfig { - final String singleObjectName; - final String multiObjectName; - final JsonObjectWriter writer; - final JsonObjectParser parser; - - public EntityConfig(String objectField, String urlPrefix, - JsonObjectWriter writer, JsonObjectParser parser) { - super(); - this.singleObjectName = objectField; - this.multiObjectName = urlPrefix; - this.writer = writer; - this.parser = parser; - } - } - - public void addProtocol(Protocol protocol) { - Protocol.registerProtocol("https", protocol); - } - -} Index: src/main/java/com/taskadapter/redmineapi/RedmineManager.java --- src/main/java/com/taskadapter/redmineapi/RedmineManager.java Base (BASE) +++ src/main/java/com/taskadapter/redmineapi/RedmineManager.java Locally Deleted @@ -1,835 +0,0 @@ -/* - Copyright 2010-2012 Alexey Skorokhodov. - - 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.taskadapter.redmineapi; - -import com.taskadapter.redmineapi.bean.*; -import com.taskadapter.redmineapi.internal.Transport; -import com.taskadapter.redmineapi.internal.URIConfigurator; -import org.apache.http.NameValuePair; -import org.apache.http.message.BasicNameValuePair; -import com.taskadapter.redmineapi.internal.io.MarkedIOException; -import com.taskadapter.redmineapi.internal.io.MarkedInputStream; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.*; -import java.util.Map.Entry; - -/** - * Entry point for the API: use this class to communicate with Redmine servers. - * - * @author Alexey Skorokhodov - */ -public class RedmineManager { - - // TODO add tests for "relations" to RedmineManagerTest class - public static enum INCLUDE { - // these values MUST BE exactly as they are written here, - // can't use capital letters or rename. - // they are provided in "?include=..." HTTP request - journals, relations, attachments, changesets - } - - private final Transport transport; - - public RedmineManager(String uri) { - this(uri, RedmineOptions.simpleOptions()); - } - - public RedmineManager(String uri, String login, String password) { - this(uri, login, password, RedmineOptions.simpleOptions()); - } - - /** - * Creates an instance of RedmineManager class. Host and apiAccessKey are - * not checked at this moment. - * - * @param host - * complete Redmine server web URI, including protocol and port - * number. Example: http://demo.redmine.org:8080 - * @param apiAccessKey - * Redmine API access key. It is shown on "My Account" / - * "API access key" webpage (check - * http://redmine_server_url/my/account URL). This - * parameter is optional (can be set to NULL) for Redmine - * projects, which are "public". - */ - public RedmineManager(String host, String apiAccessKey) { - this(host, apiAccessKey, RedmineOptions.simpleOptions()); - } - - /** - * Creates an instance of RedmineManager class. Host and apiAccessKey are - * not checked at this moment. - * - * @param host - * complete Redmine server web URI, including protocol and port - * number. Example: http://demo.redmine.org:8080 - * @param apiAccessKey - * Redmine API access key. It is shown on "My Account" / - * "API access key" webpage (check - * http://redmine_server_url/my/account URL). This - * parameter is optional (can be set to NULL) for Redmine - * projects, which are "public". - */ - public RedmineManager(String host, String apiAccessKey, - RedmineOptions options) { - this.transport = new Transport(new URIConfigurator(host, apiAccessKey), - options); - } - - public RedmineManager(String uri, RedmineOptions options) { - this(uri, null, null, options); - } - - public RedmineManager(String uri, String login, String password, - RedmineOptions options) { - this.transport = new Transport(new URIConfigurator(uri, null), options); - transport.setCredentials(login, password); - } - - /** - * Sample usage: - *

- *

- *

-     * {@code
-     *   Issue issueToCreate = new Issue();
-     *   issueToCreate.setSubject("This is the summary line 123");
-     *   Issue newIssue = mgr.createIssue(PROJECT_KEY, issueToCreate);
-     * }
-     *
-     * @param projectKey The project "identifier". This is a string key like "project-ABC", NOT a database numeric ID.
-     * @param issue      the Issue object to create on the server.
-     * @return the newly created Issue.
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws NotFoundException       the project with the given projectKey is not found
-     * @throws RedmineException
-     */
-    public Issue createIssue(String projectKey, Issue issue) throws RedmineException {
-		final Project oldProject = issue.getProject();
-		final Project newProject = new Project();
-		newProject.setIdentifier(projectKey);
-		issue.setProject(newProject);
-		try {
-			return transport.addObject(issue, new BasicNameValuePair("include",
-					INCLUDE.attachments.toString()));
-		} finally {
-			issue.setProject(oldProject);
-		}
-    }
-
-
-    /**
-     * Load the list of projects available to the user, which is represented by the API access key.
-     *
-     * @return list of Project objects
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws RedmineException
-     */
-    public List getProjects() throws RedmineException {
-        try {
-			return transport.getObjectsList(Project.class,
-					new BasicNameValuePair("include", "trackers"));
-        } catch (NotFoundException e) {
-            throw new RedmineInternalError("NotFoundException received, which should never happen in this request");
-        }
-    }
-
-    /**
-     * There could be several issues with the same summary, so the method returns List.
-     *
-     * @return empty list if not issues with this summary field exist, never NULL
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws NotFoundException
-     * @throws RedmineException
-     */
-    public List getIssuesBySummary(String projectKey, String summaryField) throws RedmineException {
-        if ((projectKey != null) && (projectKey.length() > 0)) {
-			return transport.getObjectsList(Issue.class,
-					new BasicNameValuePair("subject", summaryField),
-					new BasicNameValuePair("project_id", projectKey));
-		} else {
-			return transport.getObjectsList(Issue.class,
-					new BasicNameValuePair("subject", summaryField));
-        }
-    }
-
-    /**
-     * Generic method to search for issues.
-     *
-     * @param pParameters the http parameters key/value pairs to append to the rest api request
-     * @return empty list if not issues with this summary field exist, never NULL
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws NotFoundException
-     * @throws RedmineException
-     */
-    public List getIssues(Map pParameters) throws RedmineException {
-        Set params = new HashSet();
-
-        for (final Entry param : pParameters.entrySet()) {
-            params.add(new BasicNameValuePair(param.getKey(), param.getValue()));
-        }
-
-		return transport.getObjectsList(Issue.class, params);
-    }
-
-    /**
-     * @param id      the Redmine issue ID
-     * @param include list of "includes". e.g. "relations", "journals", ...
-     * @return Issue object
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws NotFoundException       the issue with the given id is not found on the server
-     * @throws RedmineException
-     */
-    public Issue getIssueById(Integer id, INCLUDE... include) throws RedmineException {
-        String value = join(",", include);
-		return transport.getObject(Issue.class, id, new BasicNameValuePair(
-				"include", value));
-    }
-
-    // TODO move to a separate utility class or find a replacement in Google Guava
-    // TODO add unit tests
-    private static String join(String delimToUse, INCLUDE... include) {
-        String delim = "";
-        StringBuilder sb = new StringBuilder();
-        for (INCLUDE i : include) {
-            sb.append(delim).append(i);
-            delim = delimToUse;
-        }
-        return sb.toString();
-    }
-
-    /**
-     * @param projectKey string key like "project-ABC", NOT a database numeric ID
-     * @return Redmine's project
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws NotFoundException       the project with the given key is not found
-     * @throws RedmineException
-     */
-    public Project getProjectByKey(String projectKey) throws RedmineException {
-		return transport.getObject(Project.class, projectKey,
-				new BasicNameValuePair("include", "trackers"));
-    }
-
-    /**
-     * @param projectKey string key like "project-ABC", NOT a database numeric ID
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws NotFoundException       if the project with the given key is not found
-     * @throws RedmineException
-     */
-    public void deleteProject(String projectKey) throws RedmineException {
-		transport.deleteObject(Project.class, projectKey);
-    }
-
-    public void deleteIssue(Integer id) throws RedmineException {
-		transport.deleteObject(Issue.class, Integer.toString(id));
-    }
-
-    /**
-     * @param projectKey ignored if NULL
-     * @param queryId    id of the saved query in Redmine. the query must be accessible to the user
-     *                   represented by the API access key (if the Redmine project requires authorization).
-     *                   This parameter is optional, NULL can be provided to get all available issues.
-     * @return list of Issue objects
-     * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which
-     *                                 requires authorization. Check the constructor arguments.
-     * @throws RedmineException
-     * @see Issue
-     */
-    public List getIssues(String projectKey, Integer queryId, INCLUDE... include) throws RedmineException {
-		List params = new ArrayList();
-        if (queryId != null) {
-            params.add(new BasicNameValuePair("query_id", String.valueOf(queryId)));
-        }
-
-        if ((projectKey != null) && (projectKey.length() > 0)) {
-            params.add(new BasicNameValuePair("project_id", projectKey));
-        }
-        String includeStr = join(",", include);
-        params.add(new BasicNameValuePair("include", includeStr));
-
-		return transport.getObjectsList(Issue.class, params);
-    }
-
-    /*
-      * note: This method cannot return the updated object from Redmine
-      * because the server does not provide any XML in response.
-      *
-      * @since 1.8.0
-      */
-    public void update(Identifiable obj) throws RedmineException {
-        validate(obj);
-		transport.updateObject(obj);
-    }
-
-    private void validate(Identifiable obj) {
-        // TODO this is a temporary step during refactoring. remove this class check, make it generic.
-        // maybe add validate() method to the objects themselves, although need to remember that
-        // there could be several "valid" states - e.g. "Valid to create"m "valid to update".
-        if (obj instanceof TimeEntry && !((TimeEntry) obj).isValid()) {
-            throw createIllegalTimeEntryException();
-        }
-    }
-
-    /**
-     * Sample usage:
-     * 

- *

- *

-     * {@code
-     * 	Project project = new Project();
-     * 	Long timeStamp = Calendar.getInstance().getTimeInMillis();
-     * 	String key = "projkey" + timeStamp;
-     * 	String name = "project number " + timeStamp;
-     * 	String description = "some description for the project";
-     * 	project.setIdentifier(key);
-     * 	project.setName(name);
-     * 	project.setDescription(description);
-     *
-     * 	Project createdProject = mgr.createProject(project);
-     * }
-     * 
- * - * @param project project to create on the server - * @return the newly created Project object. - * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which - * requires authorization. Check the constructor arguments. - * @throws RedmineException - */ - public Project createProject(Project project) throws RedmineException { - return transport.addObject(project, new BasicNameValuePair("include", - "trackers")); - } - - /** - * This number of objects (tasks, projects, users) will be requested from Redmine server in 1 request. - */ - public int getObjectsPerPage() { - return transport.getObjectsPerPage(); - } - - // TODO add test - - /** - * This number of objects (tasks, projects, users) will be requested from Redmine server in 1 request. - */ - public void setObjectsPerPage(int pageSize) { - transport.setObjectsPerPage(pageSize); - } - - /** - * Load the list of users on the server. - *

This operation requires "Redmine Administrator" permission. - * - * @return list of User objects - * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which - * requires authorization. Check the constructor arguments. - * @throws NotFoundException - * @throws RedmineException - */ - public List getUsers() throws RedmineException { - return transport.getObjectsList(User.class, new BasicNameValuePair( - "include", "memberships")); - } - - public User getUserById(Integer userId) throws RedmineException { - return transport.getObject(User.class, userId, new BasicNameValuePair( - "include", "memberships")); - } - - /** - * @return the current user logged into Redmine - */ - public User getCurrentUser() throws RedmineException { - return transport.getCurrentUser(); - } - - public User createUser(User user) throws RedmineException { - return transport.addObject(user); - } - - /** - * @param userId user identifier (numeric ID) - * @throws RedmineAuthenticationException invalid or no API access key is used with the server, which - * requires authorization. Check the constructor arguments. - * @throws NotFoundException if the user with the given id is not found - * @throws RedmineException - */ - public void deleteUser(Integer userId) throws RedmineException { - transport.deleteObject(User.class, Integer.toString(userId)); - } - - public List getTimeEntries() throws RedmineException { - return transport.getObjectsList(TimeEntry.class); - } - - /** - * @param id the database Id of the TimeEntry record - */ - public TimeEntry getTimeEntry(Integer id) throws RedmineException { - return transport.getObject(TimeEntry.class, id); - } - - public List getTimeEntriesForIssue(Integer issueId) throws RedmineException { - return transport.getObjectsList(TimeEntry.class, - new BasicNameValuePair("issue_id", Integer.toString(issueId))); - } - - public TimeEntry createTimeEntry(TimeEntry obj) throws RedmineException { - validate(obj); - return transport.addObject(obj); - } - - public void deleteTimeEntry(Integer id) throws RedmineException { - transport.deleteObject(TimeEntry.class, Integer.toString(id)); - } - - private IllegalArgumentException createIllegalTimeEntryException() { - return new IllegalArgumentException("You have to either define a Project or Issue ID for a Time Entry. " - + "The given Time Entry object has neither defined."); - } - - /** - * Get "saved queries" for the given project available to the current user. - *

- *

This REST API feature was added in Redmine 1.3.0. See http://www.redmine.org/issues/5737 - */ - public List getSavedQueries(String projectKey) throws RedmineException { - Set params = new HashSet(); - - if ((projectKey != null) && (projectKey.length() > 0)) { - params.add(new BasicNameValuePair("project_id", projectKey)); - } - - return transport.getObjectsList(SavedQuery.class, params); - } - - /** - * Get all "saved queries" available to the current user. - *

- *

This REST API feature was added in Redmine 1.3.0. See http://www.redmine.org/issues/5737 - */ - public List getSavedQueries() throws RedmineException { - return transport.getObjectsList(SavedQuery.class); - } - - public IssueRelation createRelation(Integer issueId, Integer issueToId, String type) throws RedmineException { - IssueRelation toCreate = new IssueRelation(); - toCreate.setIssueId(issueId); - toCreate.setIssueToId(issueToId); - toCreate.setType(type); - return transport.addChildEntry(Issue.class, issueId.toString(), - toCreate); - } - - /** - * Delete Issue Relation with the given ID. - */ - public void deleteRelation(Integer id) throws RedmineException { - transport.deleteObject(IssueRelation.class, Integer.toString(id)); - } - - /** - * Delete all issue's relations - */ - public void deleteIssueRelations(Issue redmineIssue) throws RedmineException { - for (IssueRelation relation : redmineIssue.getRelations()) { - deleteRelation(relation.getId()); - } - } - - /** - * Delete relations for the given issue ID. - * - * @param id issue ID - */ - public void deleteIssueRelationsByIssueId(Integer id) throws RedmineException { - Issue issue = getIssueById(id, INCLUDE.relations); - deleteIssueRelations(issue); - } - - /** - * Delivers a list of existing {@link com.taskadapter.redmineapi.bean.IssueStatus}es. - * - * @return a list of existing {@link com.taskadapter.redmineapi.bean.IssueStatus}es. - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public List getStatuses() throws RedmineException { - return transport.getObjectsList(IssueStatus.class); - } - - /** - * creates a new {@link Version} for the {@link Project} contained.
- * Pre-condition: the attribute {@link Project} for the {@link Version} must - * not be null! - * - * @param version the {@link Version}. Must contain a {@link Project}. - * @return the new {@link Version} created by Redmine - * @throws IllegalArgumentException thrown in case the version does not contain a project. - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public Version createVersion(Version version) throws RedmineException { - // check project - if (version.getProject() == null - || version.getProject().getId() == null) { - throw new IllegalArgumentException( - "Version must contain an existing project"); - } - return transport.addChildEntry(Project.class, version.getProject() - .getId().toString(), version); - } - - /** - * deletes a new {@link Version} from the {@link Project} contained.
- * - * @param version the {@link Version}. - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public void deleteVersion(Version version) throws RedmineException { - transport - .deleteObject(Version.class, Integer.toString(version.getId())); - } - - /** - * delivers a list of {@link Version}s of a {@link Project} - * - * @param projectID the ID of the {@link Project} - * @return the list of {@link Version}s of the {@link Project} - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public List getVersions(int projectID) throws RedmineException { - return transport.getChildEntries(Project.class, - Integer.toString(projectID), Version.class); - } - - // TODO add test - public Version getVersionById(int versionId) throws RedmineException { - return transport.getObject(Version.class, versionId); - } - - /** - * delivers a list of {@link com.taskadapter.redmineapi.bean.IssueCategory}s of a {@link Project} - * - * @param projectID the ID of the {@link Project} - * @return the list of {@link com.taskadapter.redmineapi.bean.IssueCategory}s of the {@link Project} - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public List getCategories(int projectID) throws RedmineException { - return transport.getChildEntries(Project.class, - Integer.toString(projectID), IssueCategory.class); - } - - /** - * creates a new {@link IssueCategory} for the {@link Project} contained.
- * Pre-condition: the attribute {@link Project} for the {@link IssueCategory} must - * not be null! - * - * @param category the {@link IssueCategory}. Must contain a {@link Project}. - * @return the new {@link IssueCategory} created by Redmine - * @throws IllegalArgumentException thrown in case the category does not contain a project. - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public IssueCategory createCategory(IssueCategory category) throws RedmineException { - if (category.getProject() == null - || category.getProject().getId() == null) { - throw new IllegalArgumentException( - "IssueCategory must contain an existing project"); - } - - return transport.addChildEntry(Project.class, category.getProject() - .getId().toString(), category); - } - - /** - * deletes an {@link IssueCategory}.
- * - * @param category the {@link IssueCategory}. - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public void deleteCategory(IssueCategory category) throws RedmineException { - transport.deleteObject(IssueCategory.class, - Integer.toString(category.getId())); - } - - /** - * @return a list of all {@link com.taskadapter.redmineapi.bean.Tracker}s available - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public List getTrackers() throws RedmineException { - return transport.getObjectsList(Tracker.class); - } - - /** - * Delivers an {@link com.taskadapter.redmineapi.bean.Attachment} by its ID. - * - * @param attachmentID the ID - * @return the {@link com.taskadapter.redmineapi.bean.Attachment} - * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login - * @throws RedmineException thrown in case something went wrong in Redmine - * @throws NotFoundException thrown in case an object can not be found - */ - public Attachment getAttachmentById(int attachmentID) throws RedmineException { - return transport.getObject(Attachment.class, attachmentID); - } - - public void downloadAttachmentContent(Attachment issueAttachment, - OutputStream stream) throws RedmineException { - transport.download(issueAttachment.getContentURL(), - new CopyBytesHandler(stream)); - } - - /** - * Downloads the content of an {@link com.taskadapter.redmineapi.bean.Attachment} from the Redmine server. - * - * @param issueAttachment the {@link com.taskadapter.redmineapi.bean.Attachment} - * @return the content of the attachment as a byte[] array - * @throws RedmineCommunicationException thrown in case the download fails - */ - public byte[] downloadAttachmentContent(Attachment issueAttachment) - throws RedmineException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - downloadAttachmentContent(issueAttachment, baos); - try { - baos.close(); - } catch (IOException e) { - throw new RedmineInternalError(); - } - return baos.toByteArray(); - } - - public void setLogin(String login) { - transport.setLogin(login); - } - - public void setPassword(String password) { - transport.setPassword(password); - } - - /** - * @param projectKey ignored if NULL - * @return list of news objects - * @see News - */ - public List getNews(String projectKey) throws RedmineException { - Set params = new HashSet(); - if ((projectKey != null) && (projectKey.length() > 0)) { - params.add(new BasicNameValuePair("project_id", projectKey)); - } - return transport.getObjectsList(News.class, params); - } - - /** - * Shutdowns a communicator. - */ - public void shutdown() { - transport.shutdown(); - } - - /** - * Uploads an attachement. - * - * @param fileName - * file name of the attachement. - * @param contentType - * content type of the attachement. - * @param content - * attachement content stream. - * @return attachement content. - * @throws RedmineException - * if something goes wrong. - * @throws IOException - * if input cannot be read. This exception cannot be thrown yet - * (I am not sure if http client can distinguish "network" - * errors and local errors) but is will be good to distinguish - * reading errors and transport errors. - */ - public Attachment uploadAttachment(String fileName, String contentType, - InputStream content) throws RedmineException, IOException { - final InputStream wrapper = new MarkedInputStream(content, - "uploadStream"); - final String token; - try { - token = transport.upload(wrapper); - final Attachment result = new Attachment(); - result.setToken(token); - result.setContentType(contentType); - result.setFileName(fileName); - return result; - } catch (RedmineException e) { - unwrapIO(e, "uploadStream"); - throw e; - } - } - - /** - * Unwraps an IO. - * - * @param e - * exception to unwrap. - * @param tag - * target tag. - * @throws IOException - * @throws RedmineException - */ - private void unwrapIO(RedmineException orig, String tag) throws IOException { - Throwable e = orig; - while (e != null) { - if (e instanceof MarkedIOException) { - final MarkedIOException marked = (MarkedIOException) e; - if (tag.equals(marked.getTag())) - throw marked.getIOException(); - } - e = e.getCause(); - } - } - - /** - * Uploads an attachement. - * - * @param fileName - * file name of the attachement. - * @param contentType - * content type of the attachement. - * @param content - * attachement content stream. - * @return attachement content. - * @throws RedmineException - * if something goes wrong. - * @throws IOException - * if input cannot be read. - */ - public Attachment uploadAttachment(String fileName, String contentType, - byte[] content) throws RedmineException, IOException { - final InputStream is = new ByteArrayInputStream(content); - try { - return uploadAttachment(fileName, contentType, is); - } finally { - try { - is.close(); - } catch (IOException e) { - throw new RedmineInternalError("Unexpected exception", e); - } - } - } - - /** - * Uploads an attachement. - * - * @param contentType - * content type of the attachement. - * @param content - * attachement content stream. - * @return attachement content. - * @throws RedmineException - * if something goes wrong. - * @throws IOException - * if input cannot be read. - */ - public Attachment uploadAttachment(String contentType, File content) - throws RedmineException, IOException { - final InputStream is = new FileInputStream(content); - try { - return uploadAttachment(content.getName(), contentType, is); - } finally { - is.close(); - } - } - - public List getRoles() throws RedmineException { - return transport.getObjectsList(Role.class); - } - - public List getMemberships(String project) - throws RedmineException { - return transport.getChildEntries(Project.class, project, - Membership.class); - } - - public List getMemberships(Project project) - throws RedmineException { - return getMemberships(getProjectKey(project)); - } - - /** - * Add a membership. - * - * @param membership - * membership. - * @throws RedmineException - */ - public void addMembership(Membership membership) throws RedmineException { - final Project project = membership.getProject(); - if (project == null) - throw new IllegalArgumentException("Project must be set"); - if (membership.getUser() == null) - throw new IllegalArgumentException("User must be set"); - transport.addChildEntry(Project.class, getProjectKey(project), - membership); - } - - public Membership getMembership(int id) throws RedmineException { - return transport.getObject(Membership.class, id); - } - - public void deleteMembership(int id) throws RedmineException { - transport.deleteObject(Membership.class, Integer.toString(id)); - } - - public void delete(Membership membership) throws RedmineException { - transport.deleteObject(Membership.class, membership.getId().toString()); - } - - private String getProjectKey(Project project) { - return project.getId() != null ? project.getId().toString() : project - .getIdentifier(); - } - - public Transport getTransport() { - return this.transport; - - } - -} Index: src/main/java/hudson/plugins/redmine/RedmineMetricsCalculator.java --- src/main/java/hudson/plugins/redmine/RedmineMetricsCalculator.java Base (BASE) +++ src/main/java/hudson/plugins/redmine/RedmineMetricsCalculator.java Locally Modified (Based On LOCAL) @@ -1,19 +1,16 @@ package hudson.plugins.redmine; +import com.taskadapter.redmineapi.RedmineException; +import com.taskadapter.redmineapi.RedmineManager; +import com.taskadapter.redmineapi.bean.Issue; +import com.taskadapter.redmineapi.bean.Project; +import com.taskadapter.redmineapi.bean.Version; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; - -import org.apache.commons.httpclient.protocol.Protocol; -import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory; import org.apache.commons.lang.ArrayUtils; -import com.taskadapter.redmineapi.RedmineException; -import com.taskadapter.redmineapi.RedmineManager; -import com.taskadapter.redmineapi.bean.Issue; -import com.taskadapter.redmineapi.bean.Project; -import com.taskadapter.redmineapi.bean.Version; public class RedmineMetricsCalculator { @@ -39,9 +36,6 @@ List result = new ArrayList(); try { RedmineManager manager = new RedmineManager(url, apiKey); - if(url.startsWith("https://")) { - manager.getTransport().addProtocol(new Protocol("https", new SSLProtocolSocketFactory(), 443)); - } Project proj = getProject(manager); @@ -97,7 +91,7 @@ private Project getProject(RedmineManager manager) throws RedmineException { for (Project proj : manager.getProjects()) { - if (!projectName.equals(proj.getName())) { + if (!(projectName.equals(proj.getName()) || projectName.equals(proj.getIdentifier()))) { continue; } return proj;