From c34aaa50b5bf539607410faa15892c90b12415ba Mon Sep 17 00:00:00 2001 From: Andrei Savu Date: Tue, 31 Jan 2012 15:04:42 +0200 Subject: [PATCH] Include the JSESSIONID as part of the LoginResponse --- .../cloudstack/domain/LoginResponse.java | 36 +++++++++++++++- .../features/SessionAsyncClient.java | 10 ++--- .../cloudstack/features/SessionClient.java | 4 +- .../ParseLoginResponseFromHttpResponse.java | 41 +++++++++++++++++++ .../features/SessionClientLiveTest.java | 29 ++++++------- 5 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoginResponse.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoginResponse.java index ad3dfb117f..351b9f7f4d 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoginResponse.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoginResponse.java @@ -46,7 +46,25 @@ public class LoginResponse implements Comparable { private String timezone; private String timezoneOffset; private String sessionKey; + private String jSessionId; + public Builder copyOf(LoginResponse r) { + this.userName = r.userName; + this.userId = r.userId; + this.password = r.password; + this.domainId = r.domainId; + this.timeout = r.timeout; + this.accountName = r.accountName; + this.firstName = r.firstName; + this.lastName = r.lastName; + this.accountType = r.accountType; + this.timezone = r.timezone; + this.timezoneOffset = r.timezoneOffset; + this.sessionKey = r.sessionKey; + this.jSessionId = r.jSessionId; + return this; + } + public Builder userName(String userName) { this.userName = userName; return this; @@ -106,10 +124,15 @@ public class LoginResponse implements Comparable { this.sessionKey = sessionKey; return this; } + + public Builder jSessionId(String jSessionId) { + this.jSessionId = jSessionId; + return this; + } public LoginResponse build() { return new LoginResponse(userName, userId, password, domainId, timeout, accountName, - firstName, lastName, accountType, timezone, timezoneOffset, sessionKey); + firstName, lastName, accountType, timezone, timezoneOffset, sessionKey, jSessionId); } } @@ -137,10 +160,11 @@ public class LoginResponse implements Comparable { private String timezoneOffset; @SerializedName("sessionkey") private String sessionKey; + private String jSessionId; public LoginResponse(String userName, long userId, String password, long domainId, long timeout, String accountName, String firstName, String lastName, Account.Type accountType, - String timezone, String timezoneOffset, String sessionKey) { + String timezone, String timezoneOffset, String sessionKey, String jSessionId) { this.userName = userName; this.userId = userId; this.password = password; @@ -153,6 +177,7 @@ public class LoginResponse implements Comparable { this.timezone = timezone; this.timezoneOffset = timezoneOffset; this.sessionKey = sessionKey; + this.jSessionId = jSessionId; } public String getUserName() { @@ -202,6 +227,10 @@ public class LoginResponse implements Comparable { public String getSessionKey() { return sessionKey; } + + public String getJSessionId() { + return jSessionId; + } @Override public boolean equals(Object o) { @@ -223,6 +252,7 @@ public class LoginResponse implements Comparable { if (timezoneOffset != null ? !timezoneOffset.equals(loginResponse.timezoneOffset) : loginResponse.timezoneOffset != null) return false; if (userName != null ? !userName.equals(loginResponse.userName) : loginResponse.userName != null) return false; + if (jSessionId != null ? !jSessionId.equals(loginResponse.jSessionId) : loginResponse.jSessionId != null) return false; return true; } @@ -241,6 +271,7 @@ public class LoginResponse implements Comparable { result = 31 * result + (timezone != null ? timezone.hashCode() : 0); result = 31 * result + (timezoneOffset != null ? timezoneOffset.hashCode() : 0); result = 31 * result + (sessionKey != null ? sessionKey.hashCode() : 0); + result = 31 * result + (jSessionId != null ? jSessionId.hashCode() : 0); return result; } @@ -259,6 +290,7 @@ public class LoginResponse implements Comparable { ", timezone='" + timezone + '\'' + ", timezoneOffset='" + timezoneOffset + '\'' + ", sessionKey='" + sessionKey + '\'' + + ", jSessionId='" + jSessionId + '\'' + '}'; } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java index 2c7a147346..452e6a3a76 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java @@ -21,17 +21,18 @@ package org.jclouds.cloudstack.features; import com.google.common.util.concurrent.ListenableFuture; import org.jclouds.cloudstack.domain.Account; import org.jclouds.cloudstack.domain.LoginResponse; +import org.jclouds.cloudstack.functions.ParseLoginResponseFromHttpResponse; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import javax.ws.rs.Consumes; +import javax.ws.rs.CookieParam; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.QueryParam; -import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; /** @@ -50,7 +51,7 @@ public interface SessionAsyncClient { */ @GET @QueryParams(keys = "command", values = "login") - @SelectJson("loginresponse") + @ResponseParser(ParseLoginResponseFromHttpResponse.class) @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) ListenableFuture loginUserInDomainWithHashOfPassword(@QueryParam("username") String userName, @@ -64,9 +65,8 @@ public interface SessionAsyncClient { @SelectJson("account") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @HeaderParam(HttpHeaders.COOKIE) ListenableFuture getAccountByNameUsingSession(@QueryParam("name") String accountName, - @QueryParam("sessionkey") String sessionKey); + @QueryParam("sessionkey") String sessionKey, @CookieParam("JSESSIONID") String jSessionId); /** * @see SessionClient#logoutUser diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java index 853d7cddf6..f21239873e 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java @@ -59,10 +59,12 @@ public interface SessionClient { * account name * @param sessionKey * a valid session key + * @param jSessionId + * the JSESSIONID cookie returned by the server * @return * account instance or null */ - Account getAccountByNameUsingSession(String accountName, String sessionKey); + Account getAccountByNameUsingSession(String accountName, String sessionKey, String jSessionId); /** * Logs out the user by invalidating the session key diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java new file mode 100644 index 0000000000..557a2764ad --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java @@ -0,0 +1,41 @@ +package org.jclouds.cloudstack.functions; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.inject.Inject; +import com.google.inject.TypeLiteral; +import org.jclouds.cloudstack.domain.LoginResponse; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseFirstJsonValueNamed; +import org.jclouds.json.internal.GsonWrapper; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.get; +import static com.google.common.collect.Iterables.getOnlyElement; + +/** + * @author Andrei Savu + */ +public class ParseLoginResponseFromHttpResponse implements Function { + + private ParseFirstJsonValueNamed parser; + + @Inject + ParseLoginResponseFromHttpResponse(GsonWrapper gson) { + this.parser = new ParseFirstJsonValueNamed(checkNotNull(gson, "gsonWrapper"), + new TypeLiteral(){}, "loginresponse"); + } + + @Override + public LoginResponse apply(HttpResponse response) { + checkNotNull(response, "response"); + + LoginResponse login = parser.apply(response); + checkNotNull(login, "loginResponse"); + + String jSessionId = get(Splitter.on("=").split(get(Splitter.on(";").trimResults().split( + getOnlyElement(response.getHeaders().get("Set-Cookie"))), 0)), 1); + + return LoginResponse.builder().copyOf(login).jSessionId(jSessionId).build(); + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientLiveTest.java index 30172aec16..1b44bf5edf 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientLiveTest.java @@ -41,38 +41,39 @@ public class SessionClientLiveTest extends BaseCloudStackClientLiveTest { private final String PLAIN_TEXT_PASSWORD = "jcl0ud"; private final String DOMAIN = "Partners/jCloud"; - private LoginResponse loginResponse; + private LoginResponse login; @Test(enabled = true) - public void testLoginWithHashedPassword() throws Exception { - loginResponse = client.getSessionClient() + public void testLoginWithHashOfPassword() throws Exception { + login = client.getSessionClient() .loginUserInDomainWithHashOfPassword(USER, DOMAIN, md5Hex(PLAIN_TEXT_PASSWORD)); - assertNotNull(loginResponse); - assertNotNull(loginResponse.getSessionKey()); + assertNotNull(login); + assertNotNull(login.getSessionKey()); + assertNotNull(login.getJSessionId()); } - @Test(dependsOnMethods = "testLoginWithHashedPassword") + @Test(dependsOnMethods = "testLoginWithHashOfPassword") public void testRetrieveUserInfoWithSessionKey() throws Exception { - Account account = client.getSessionClient() - .getAccountByNameUsingSession(loginResponse.getAccountName(), loginResponse.getSessionKey()); + Account account = client.getSessionClient().getAccountByNameUsingSession( + login.getAccountName(), login.getSessionKey(), login.getJSessionId()); assertNotNull(account); - assertEquals(account.getName(), loginResponse.getAccountName()); + assertEquals(account.getName(), login.getAccountName()); User currentUser = find(account.getUsers(), new Predicate() { @Override public boolean apply(User user) { - return user.getId() == loginResponse.getUserId(); + return user.getId() == login.getUserId(); } }); assertNotNull(currentUser); - assertEquals(currentUser.getName(), loginResponse.getUserName()); - assertEquals(currentUser.getDomainId(), loginResponse.getDomainId()); + assertEquals(currentUser.getName(), login.getUserName()); + assertEquals(currentUser.getDomainId(), login.getDomainId()); } - + @Test(dependsOnMethods = "testRetrieveUserInfoWithSessionKey") public void testLogout() throws Exception { - client.getSessionClient().logoutUser(loginResponse.getSessionKey()); + client.getSessionClient().logoutUser(login.getSessionKey()); } }