Commit ec18994d authored by Greg Messner's avatar Greg Messner
Browse files

Mods for Java 8 and for new getOptionalXyz() methods (#127).

parent 8d0ddc1c
......@@ -5,7 +5,7 @@
<groupId>org.gitlab4j</groupId>
<artifactId>gitlab4j-api</artifactId>
<packaging>jar</packaging>
<version>4.7.18-SNAPSHOT</version>
<version>4.8.0-SNAPSHOT</version>
<name>GitLab API Java Client</name>
<description>GitLab API for Java (gitlab4j-api) provides a full featured Java API for working with GitLab repositories via the GitLab REST API.</description>
<url>https://github.com/gmessner/gitlab4j-api</url>
......@@ -38,7 +38,8 @@
</developers>
<properties>
<jdk.version>1.7</jdk.version>
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
<jersey.version>2.26</jersey.version>
<jackson.version>2.9.3</jackson.version>
<javaServlet.version>3.1.0</javaServlet.version>
......@@ -60,7 +61,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<version>2.5.3</version>
<configuration>
<goals>deploy</goals>
</configuration>
......@@ -68,7 +69,7 @@
<plugin>
<artifactId>maven-scm-plugin</artifactId>
<version>1.9.2</version>
<version>1.9.5</version>
<configuration>
<tag>${project.artifactId}-${project.version}</tag>
</configuration>
......@@ -77,17 +78,27 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.7.0</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<source>${java.source.version}</source>
<target>${java.target.version}</target>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<excludes>
<exclude>**/module-info.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
......@@ -102,7 +113,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-sources</id>
......@@ -116,7 +127,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.1</version>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
......@@ -130,7 +141,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<version>0.8.0</version>
<executions>
<execution>
<id>default-prepare-agent</id>
......@@ -173,7 +184,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.2</version>
<version>2.19.1</version>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
......@@ -184,6 +195,7 @@
</build>
<dependencies>
<!-- jaxb-api and javax.activation added for Java 9 compatibility -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
......@@ -194,6 +206,7 @@
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
......
package org.gitlab4j.api;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.WeakHashMap;
import javax.ws.rs.core.Response;
......@@ -28,6 +31,10 @@ public class GitLabApi {
}
}
// Used to keep track of GitLabApiExceptions on calls that return Optionsl<?>
private static final Map<Optional<?>, GitLabApiException> optionalExceptionMap =
Collections.synchronizedMap(new WeakHashMap<Optional<?>, GitLabApiException>());
GitLabApiClient apiClient;
private ApiVersion apiVersion;
private String gitLabServerUrl;
......@@ -55,7 +62,6 @@ public class GitLabApi {
private NotesApi notesApi;
private EventsApi eventsApi;
/**
* Create a new GitLabApi instance that is logically a duplicate of this instance, with the exception off sudo state.
*
......@@ -993,4 +999,46 @@ public class GitLabApi {
return (userApi);
}
/**
* Create and return an Optional instance associated with a GitLabApiException.
*
* @param optional the Optional instance to use as the key for the exception
* @param glae the GitLabApiException that was the result of a call to the GitLab API
*/
protected static final <T> Optional<T> createOptionalFromException(GitLabApiException glae) {
Optional<T> optional = Optional.empty();
optionalExceptionMap.put(optional, glae);
return (optional);
}
/**
* Get the exception associated with the provided Optional instance, or null if no exception is
* associated with the Optional instance.
*
* @param optional the Optional instance to get the exception for
* @return the exception associated with the provided Optional instance, or null if no exception is
* associated with the Optional instance
*/
public static final GitLabApiException getOptionalException(Optional<?> optional) {
return (optionalExceptionMap.get(optional));
}
/**
* Return the Optional instances contained value, if present, otherwise throw the exception that is
* associated with the Optional instance.
*
* @param optional the Optional instance to get the value for
* @return the value of the Optional instance if no exception is associated with it
* @throws GitLabApiException if there was an exception associated with the Optional instance
*/
public static final <T> T orElseThrow(Optional<T> optional) throws GitLabApiException {
GitLabApiException glea = getOptionalException(optional);
if (glea != null) {
throw (glea);
}
return (optional.get());
}
}
......@@ -2,6 +2,7 @@ package org.gitlab4j.api;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
......@@ -12,7 +13,6 @@ import org.gitlab4j.api.models.AccessLevel;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Member;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.User;
import org.gitlab4j.api.models.Visibility;
/**
......@@ -281,6 +281,18 @@ public class GroupApi extends AbstractApi {
return getGroup(groupId.toString());
}
/**
* Get all details of a group as an Optional instance.
*
* GET /groups/:id
*
* @param groupId the group ID to get
* @return the Group for the specified group ID as an Optional instance
*/
public Optional<Group> getOptionalGroup(Integer groupId) {
return (getOptionalGroup(groupId.toString()));
}
/**
* Get all details of a group.
*
......@@ -295,6 +307,22 @@ public class GroupApi extends AbstractApi {
return (response.readEntity(Group.class));
}
/**
* Get all details of a group as an Optional instance.
*
* GET /groups/:id
*
* @param groupPath the path of the group to get details for
* @return the Group for the specified group path as an Optional instance
*/
public Optional<Group> getOptionalGroup(String groupPath) {
try {
return (Optional.ofNullable(getGroup(groupPath)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Creates a new project group. Available only for users who can create groups.
*
......@@ -543,6 +571,23 @@ public class GroupApi extends AbstractApi {
return (response.readEntity(new GenericType<Member>() {}));
}
/**
* Get a group member viewable by the authenticated user as an Optional instance.
*
* GET /groups/:id/members/:id
*
* @param groupId the group ID to get the member for
* @param userId the member ID of the member to get
* @return a member viewable by the authenticated user as an Optional instance
*/
public Optional<Member> getOptionalMember(int groupId, int userId) throws GitLabApiException {
try {
return (Optional.ofNullable(getMember(groupId, userId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Adds a user to the list of group members.
*
......
......@@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
......@@ -473,6 +474,22 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(Project.class));
}
/**
* Get an Optional instance with the value for the specific project, which is owned by the authentication user.
*
* GET /projects/:id
*
* @param projectId the ID of the project to get
* @return an Optional instance with the specified project as a value
*/
public Optional<Project> getOptionalProject(Integer projectId) {
try {
return (Optional.ofNullable(getProject(projectId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Get a specific project, which is owned by the authentication user.
*
......@@ -504,6 +521,23 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(Project.class));
}
/**
* Get an Optional instance with the value for the specific project, which is owned by the authentication user.
*
* GET /projects/:id
*
* @param namespace the name of the project namespace or group
* @param project the name of the project
* @return an Optional instance with the specified project as a value
*/
public Optional<Project> getOptionalProject(String namespace, String project) {
try {
return (Optional.ofNullable(getProject(namespace, project)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Create a new project in the specified group.
*
......@@ -513,7 +547,6 @@ public class ProjectApi extends AbstractApi implements Constants {
* @throws GitLabApiException if any exception occurs
*/
public Project createProject(Integer groupId, String projectName) throws GitLabApiException {
GitLabApiForm formData = new GitLabApiForm().withParam("namespace_id", groupId).withParam("name", projectName, true);
Response response = post(Response.Status.CREATED, formData, "projects");
return (response.readEntity(Project.class));
......@@ -1013,6 +1046,24 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(Member.class));
}
/**
* Gets a project team member.
*
* GET /projects/:id/members/:user_id
*
* @param projectId the project ID to get team member for
* @param userId the user ID of the member
* @return the member specified by the project ID/user ID pair
* @throws GitLabApiException if any exception occurs
*/
public Optional<Member> getOptionalMember(Integer projectId, Integer userId) throws GitLabApiException {
try {
return (Optional.ofNullable(getMember(projectId, userId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Adds a user to a project team. This is an idempotent method and can be called multiple times
* with the same parameters. Adding team membership to a user that is already a member does not
......@@ -1303,6 +1354,23 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(ProjectHook.class));
}
/**
* Get a specific hook for project as an Optional instance.
*
* GET /projects/:id/hooks/:hook_id
*
* @param projectId the project ID to get the hook for
* @param hookId the ID of the hook to get
* @return the project hook for the specified project ID/hook ID pair as an Optional instance
*/
public Optional<ProjectHook> getOptionalHook(Integer projectId, Integer hookId) {
try {
return (Optional.ofNullable(getHook(projectId, hookId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Adds a hook to project.
*
......@@ -1632,6 +1700,23 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(Snippet.class));
}
/**
* Get a single of project snippet as an Optional instance.
*
* GET /projects/:id/snippets/:snippet_id
*
* @param projectId the project ID to get the snippet for
* @param snippetId the ID of the project's snippet
* @return the specified project Snippet as an Optional instance
*/
public Optional<Snippet> getOptionalSnippet(Integer projectId, Integer snippetId) {
try {
return (Optional.ofNullable(getSnippet(projectId, snippetId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Creates a new project snippet. The user must have permission to create new snippets.
*
......@@ -1710,6 +1795,7 @@ public class ProjectApi extends AbstractApi implements Constants {
*
* @param projectId the project ID of the snippet
* @param snippetId the ID of the project's snippet
* @return the raw project snippet plain text as an Optional instance
* @throws GitLabApiException if any exception occurs
*/
public String getRawSnippetContent(Integer projectId, Integer snippetId) throws GitLabApiException {
......@@ -1717,6 +1803,23 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(String.class));
}
/*
* Get the raw project snippet plain text as an Optional instance.
*
* GET /projects/:id/snippets/:snippet_id/raw
*
* @param projectId the project ID of the snippet
* @param snippetId the ID of the project's snippet
* @return the raw project snippet plain text as an Optional instance
*/
public Optional<String> getOptionalRawSnippetContent(Integer projectId, Integer snippetId) {
try {
return (Optional.ofNullable(getRawSnippetContent(projectId, snippetId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Share a project with the specified group.
*
......
......@@ -2,6 +2,7 @@ package org.gitlab4j.api;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
......@@ -213,6 +214,22 @@ public class UserApi extends AbstractApi {
return (response.readEntity(User.class));
}
/**
* Get a single user as an Optional instance.
*
* GET /users/:id
*
* @param userId the ID of the user to get
* @return the User for the specified user ID as an Optional instance
*/
public Optional<User> getOptionalUser(int userId) {
try {
return (Optional.ofNullable(getUser(userId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Lookup a user by username.
*
......@@ -231,6 +248,24 @@ public class UserApi extends AbstractApi {
return (users.isEmpty() ? null : users.get(0));
}
/**
* Lookup a user by username and return an Optional instance.
*
* NOTE: This is for admin users only.
*
* GET /users?username=:username
*
* @param username the username of the user to get
* @return the User for the specified username as an Optional instance
*/
public Optional<User> getOptionalUser(String username) {
try {
return (Optional.ofNullable(getUser(username)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Search users by Email or username
*
......@@ -469,6 +504,22 @@ public class UserApi extends AbstractApi {
return (response.readEntity(SshKey.class));
}
/**
* Get a single SSH Key as an Optional instance.
*
* GET /user/keys/:key_id
*
* @param keyId the ID of the SSH key
* @return an SshKey as an Optional instance holding the info on the SSH key specified by keyId
*/
public Optional<SshKey> getOptionalSshKey(Integer keyId) {
try {
return (Optional.ofNullable(getSshKey(keyId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Creates a new key owned by the currently authenticated user.
*
......@@ -614,6 +665,23 @@ public class UserApi extends AbstractApi {
return (response.readEntity(ImpersonationToken.class));
}
/**
* Get an impersonation token of a user as an Optional instance. Available only for admin users.
*
* GET /users/:user_id/impersonation_tokens/:impersonation_token_id
*
* @param userId the ID of the user to get SSH keys for
* @param tokenId the impersonation token ID to get
* @return the specified impersonation token as an Optional instance
*/
public Optional<ImpersonationToken> getOptionalImpersonationToken(Integer userId, Integer tokenId) {
try {
return (Optional.ofNullable(getImpersonationToken(userId, tokenId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Create an impersonation token. Available only for admin users.
*
......
......@@ -88,6 +88,7 @@ public class TestGitLabLogin {
assumeTrue(problems != null && problems.isEmpty());
}
@SuppressWarnings("deprecation")
@Test
public void testSession() throws GitLabApiException {
......@@ -98,6 +99,7 @@ public class TestGitLabLogin {
assertEquals(TEST_PRIVATE_TOKEN, gitLabApi.getSession().getPrivateToken());
}
@SuppressWarnings("deprecation")
@Test
public void testSessionV3() throws GitLabApiException {
......
package org.gitlab4j.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.Response;
import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.models.AccessLevel;
......@@ -127,4 +132,22 @@ public class TestGroupApi {
gitLabApi.getGroupApi().removeMember(testGroup.getId(), testUser.getId());
}
@Test
public void getGroup() throws GitLabApiException {
Group group = gitLabApi.getGroupApi().getGroup(TEST_GROUP);
assertNotNull(group);
}
@Test
public void getOptionalGroup() {
Optional<Group> optional = gitLabApi.getGroupApi().getOptionalGroup(TEST_GROUP);
assertTrue(optional.isPresent());
assertEquals(testGroup.getId(), optional.get().getId());
optional = gitLabApi.getGroupApi().getOptionalGroup(12345);
assertNotNull(optional);
assertFalse(optional.isPresent());
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), GitLabApi.getOptionalException(optional).getHttpStatus());
}
}
......@@ -24,16 +24,21 @@
package org.gitlab4j.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.Response;
import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.models.AccessLevel;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.User;
import org.gitlab4j.api.models.Visibility;
import org.junit.AfterClass;
import org.junit.Before;
......@@ -435,4 +440,29 @@ public class TestProjectApi {
gitLabApi.getProjectApi().shareProject(project.getId(), shareGroup.getId(), AccessLevel.DEVELOPER, null);
gitLabApi.getProjectApi().unshareProject(project.getId(), shareGroup.getId());
}
@Test
public void testGetOptionalProject() throws GitLabApiException {
Optional<Project> optional = gitLabApi.getProjectApi().getOptionalProject(TEST_NAMESPACE, TEST_PROJECT_NAME);
assertNotNull(optional);
assertTrue(optional.isPresent());
assertEquals(TEST_PROJECT_NAME, optional.get().getName());
Integer projectId = optional.get().getId();
optional = gitLabApi.getProjectApi().getOptionalProject(projectId);
assertNotNull(optional);
assertTrue(optional.isPresent());
assertEquals(projectId, optional.get().getId());
optional = gitLabApi.getProjectApi().getOptionalProject(TEST_NAMESPACE, "this-project-does-not-exist");
assertNotNull(optional);
assertFalse(optional.isPresent());
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), GitLabApi.getOptionalException(optional).getHttpStatus());
optional = gitLabApi.getProjectApi().getOptionalProject(1234567);
assertNotNull(optional);
assertFalse(optional.isPresent());
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), GitLabApi.getOptionalException(optional).getHttpStatus());
}
}
......@@ -10,8 +10,12 @@ import static org.junit.Assume.assumeTrue;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.Response;
import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.ImpersonationToken;
import org.gitlab4j.api.models.ImpersonationToken.Scope;
import org.gitlab4j.api.models.SshKey;
......@@ -129,6 +133,20 @@ public class TestUserApi {
assertEquals(TEST_USERNAME, user.getUsername());
}
@Test
public void testGetOptionalUser() throws GitLabApiException {
Optional<User> optional = gitLabApi.getUserApi().getOptionalUser(TEST_USERNAME);
assertNotNull(optional);
assertTrue(optional.isPresent());
assertEquals(TEST_USERNAME, optional.get().getUsername());
optional = gitLabApi.getUserApi().getOptionalUser("this-username-does-not-exist");
assertNotNull(optional);
assertFalse(optional.isPresent());
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), GitLabApi.getOptionalException(optional).getHttpStatus());
}
@Test
public void testSudoAsUser() throws GitLabApiException {
......@@ -176,6 +194,25 @@ public class TestUserApi {
gitLabApi.getUserApi().revokeImpersonationToken(user.getId(), token.getId());
}
@Test
public void testGetOptionalImpersonationToken() throws GitLabApiException, ParseException {
User user = gitLabApi.getUserApi().getCurrentUser();
Scope[] scopes = {Scope.API, Scope.READ_USER};
Date expiresAt = ISO8601.toDate("2018-01-01T00:00:00Z");
ImpersonationToken token = gitLabApi.getUserApi().createImpersonationToken(user.getId(), TEST_IMPERSONATION_TOKEN_NAME, expiresAt, scopes);
assertNotNull(token);
Optional<ImpersonationToken> optional = gitLabApi.getUserApi().getOptionalImpersonationToken(user.getId(), token.getId());
assertTrue(optional.isPresent());
assertEquals(token.getId(), optional.get().getId());
gitLabApi.getUserApi().revokeImpersonationToken(user.getId(), token.getId());
optional = gitLabApi.getUserApi().getOptionalImpersonationToken(user.getId(), 123456);
assertNotNull(optional);
assertFalse(optional.isPresent());
}
@Test
public void testGetImpersonationTokens() throws GitLabApiException, ParseException {
......@@ -232,4 +269,23 @@ public class TestUserApi {
assertEquals(user.getId(), sshKey.getUserId());
gitLabApi.getUserApi().deleteSshKey(sshKey.getId());
}
@Test
public void testGetOptionalSshKey() throws GitLabApiException {
assumeTrue(TEST_SSH_KEY != null);
User user = gitLabApi.getUserApi().getCurrentUser();
SshKey sshKey = gitLabApi.getUserApi().addSshKey(user.getId(), "Test-Key1", TEST_SSH_KEY);
assertNotNull(sshKey);
Optional<SshKey> optional = gitLabApi.getUserApi().getOptionalSshKey(sshKey.getId());
assertNotNull(optional.isPresent());
assertEquals(sshKey.getId(), optional.get().getId());
gitLabApi.getUserApi().deleteSshKey(sshKey.getId());
optional = gitLabApi.getUserApi().getOptionalSshKey(12345);
assertNotNull(optional);
assertFalse(optional.isPresent());
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), GitLabApi.getOptionalException(optional).getHttpStatus());
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment