Author: matthieu
Date: Fri Dec 11 10:06:00 2015
New Revision: 1719308
URL: http://svn.apache.org/viewvc?rev=1719308&view=rev
Log:
JAMES-1644 Introduce ContinuationToken
Added:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MalformedContinuationTokenException.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationToken.java
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/ContinuationTokenTest.java
Modified:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenRequest.java
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationTokenResponse.java
Modified:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java?rev=1719308&r1=1719307&r2=1719308&view=diff
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
(original)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
Fri Dec 11 10:06:00 2015
@@ -19,6 +19,7 @@
package org.apache.james.jmap;
import java.io.IOException;
+import java.time.ZonedDateTime;
import javax.inject.Inject;
import javax.servlet.ServletException;
@@ -29,6 +30,7 @@ import javax.servlet.http.HttpServletRes
import org.apache.james.jmap.json.MultipleObjectMapperBuilder;
import org.apache.james.jmap.model.AccessTokenRequest;
import org.apache.james.jmap.model.AccessTokenResponse;
+import org.apache.james.jmap.model.ContinuationToken;
import org.apache.james.jmap.model.ContinuationTokenRequest;
import org.apache.james.jmap.model.ContinuationTokenResponse;
import org.apache.james.user.api.UsersRepository;
@@ -106,7 +108,7 @@ public class AuthenticationServlet exten
ContinuationTokenResponse continuationTokenResponse =
ContinuationTokenResponse
.builder()
// TODO Answer a real token
- .continuationToken("token")
+ .continuationToken(new ContinuationToken("fake",
ZonedDateTime.now(), "fake"))
.methods(ContinuationTokenResponse.AuthenticationMethod.PASSWORD)
.build();
@@ -149,4 +151,5 @@ public class AuthenticationServlet exten
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
+
}
Added:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MalformedContinuationTokenException.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MalformedContinuationTokenException.java?rev=1719308&view=auto
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MalformedContinuationTokenException.java
(added)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MalformedContinuationTokenException.java
Fri Dec 11 10:06:00 2015
@@ -0,0 +1,31 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.jmap.exceptions;
+
+public class MalformedContinuationTokenException extends Exception {
+
+ public MalformedContinuationTokenException(String s) {
+ super(s);
+ }
+
+ public MalformedContinuationTokenException(String s, Throwable throwable) {
+ super(s, throwable);
+ }
+}
Modified:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenRequest.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenRequest.java?rev=1719308&r1=1719307&r2=1719308&view=diff
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenRequest.java
(original)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenRequest.java
Fri Dec 11 10:06:00 2015
@@ -20,6 +20,9 @@ package org.apache.james.jmap.model;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import org.apache.james.jmap.exceptions.MalformedContinuationTokenException;
+
+import java.time.DateTimeException;
@JsonDeserialize(builder=AccessTokenRequest.Builder.class)
public class AccessTokenRequest {
@@ -33,14 +36,14 @@ public class AccessTokenRequest {
@JsonPOJOBuilder(withPrefix="")
public static class Builder {
- private String token;
+ private ContinuationToken token;
private String method;
private String password;
private Builder() {}
- public Builder token(String token) {
- this.token = token;
+ public Builder token(String token) throws
MalformedContinuationTokenException, DateTimeException {
+ this.token = ContinuationToken.fromString(token);
return this;
}
@@ -59,17 +62,17 @@ public class AccessTokenRequest {
}
}
- private final String token;
+ private final ContinuationToken token;
private final String method;
private final String password;
- private AccessTokenRequest(String token, String method, String password) {
+ private AccessTokenRequest(ContinuationToken token, String method, String
password) {
this.token = token;
this.method = method;
this.password = password;
}
- public String getToken() {
+ public ContinuationToken getToken() {
return token;
}
Added:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationToken.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationToken.java?rev=1719308&view=auto
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationToken.java
(added)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationToken.java
Fri Dec 11 10:06:00 2015
@@ -0,0 +1,122 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.jmap.model;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.apache.james.jmap.exceptions.MalformedContinuationTokenException;
+
+import java.time.DateTimeException;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+public class ContinuationToken {
+
+ public static final String SEPARATOR = "_";
+
+ private final String username;
+ private final ZonedDateTime expirationDate;
+ private final String signature;
+
+ public ContinuationToken(String username, ZonedDateTime expirationDate,
String signature) {
+ Preconditions.checkNotNull(username);
+ Preconditions.checkNotNull(expirationDate);
+ Preconditions.checkNotNull(signature);
+ this.username = username;
+ this.expirationDate = expirationDate;
+ this.signature = signature;
+ }
+
+ public static ContinuationToken fromString(String serializedToken) throws
MalformedContinuationTokenException {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(serializedToken),
"Serialized continuation token should not be null or empty");
+ ImmutableList<String> tokenParts =
ImmutableList.copyOf(Splitter.on(SEPARATOR).split(serializedToken));
+ if (tokenParts.size() < 3) {
+ throw new MalformedContinuationTokenException("Token " +
serializedToken + " does not have enough parts");
+ }
+ Iterator<String> tokenPartsReversedIterator =
tokenParts.reverse().iterator();
+ String signature = tokenPartsReversedIterator.next();
+ String expirationDateString = tokenPartsReversedIterator.next();
+ String username = retrieveUsername(tokenPartsReversedIterator);
+ try {
+ return new ContinuationToken(username,
+ ZonedDateTime.parse(expirationDateString,
DateTimeFormatter.ISO_OFFSET_DATE_TIME),
+ signature);
+ } catch(DateTimeException e) {
+ throw new MalformedContinuationTokenException("Token " +
serializedToken + " as an incorrect date", e);
+ }
+ }
+
+ private static String retrieveUsername(Iterator<String>
reversedIteratorOnUsernameParts) {
+ List<String> usernamePart =
ImmutableList.copyOf(Lists.newArrayList(reversedIteratorOnUsernameParts)).reverse();
+ return Joiner.on(SEPARATOR).join(usernamePart);
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public ZonedDateTime getExpirationDate() {
+ return expirationDate;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public String serialize() {
+ return username
+ + SEPARATOR
+ + DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(expirationDate)
+ + SEPARATOR
+ + signature;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+ ContinuationToken continuationToken = (ContinuationToken) other;
+ return Objects.equals(username, continuationToken.username)
+ && expirationDate.isEqual(continuationToken.expirationDate)
+ && Objects.equals(signature, continuationToken.signature);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(username, expirationDate, signature);
+ }
+
+ @Override
+ public String toString() {
+ return "ContinuationToken{" +
+ "username='" + username + '\'' +
+ ", expirationDate=" + expirationDate +
+ ", signature='" + signature + '\'' +
+ '}';
+ }
+}
Modified:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationTokenResponse.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationTokenResponse.java?rev=1719308&r1=1719307&r2=1719308&view=diff
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationTokenResponse.java
(original)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/ContinuationTokenResponse.java
Fri Dec 11 10:06:00 2015
@@ -53,8 +53,8 @@ public class ContinuationTokenResponse {
private Builder() {}
- public Builder continuationToken(String continuationToken) {
- this.continuationToken = continuationToken;
+ public Builder continuationToken(ContinuationToken continuationToken) {
+ this.continuationToken = continuationToken.serialize();
return this;
}
Added:
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/ContinuationTokenTest.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/ContinuationTokenTest.java?rev=1719308&view=auto
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/ContinuationTokenTest.java
(added)
+++
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/ContinuationTokenTest.java
Fri Dec 11 10:06:00 2015
@@ -0,0 +1,97 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.jmap.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.apache.james.jmap.exceptions.MalformedContinuationTokenException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ContinuationTokenTest {
+
+ private static final String USER = "user";
+ private static final String EXPIRATION_DATE_STRING =
"2011-12-03T10:15:30+01:00";
+ public static final String SIGNATURE = "signature";
+
+ private ZonedDateTime expirationDate;
+
+ @Before
+ public void setUp() {
+ expirationDate = ZonedDateTime.parse(EXPIRATION_DATE_STRING,
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ }
+
+ @Test
+ public void continuationTokenShouldBeRetrievedFromString() throws
Exception {
+ assertThat(ContinuationToken.fromString(USER +
ContinuationToken.SEPARATOR + EXPIRATION_DATE_STRING +
ContinuationToken.SEPARATOR + SIGNATURE))
+ .isEqualTo(new ContinuationToken(USER, expirationDate, SIGNATURE));
+ }
+
+ @Test
+ public void usernameShouldBeAllowedToContainSeparator() throws Exception {
+ String username = "user" + ContinuationToken.SEPARATOR + "using" +
ContinuationToken.SEPARATOR + "separator";
+ assertThat(ContinuationToken.fromString(username +
ContinuationToken.SEPARATOR + EXPIRATION_DATE_STRING +
ContinuationToken.SEPARATOR + SIGNATURE))
+ .isEqualTo(new ContinuationToken(username, expirationDate,
SIGNATURE));
+ }
+
+ @Test(expected = MalformedContinuationTokenException.class)
+ public void continuationTokenThatMissPartsShouldThrow() throws Exception {
+ ContinuationToken.fromString(EXPIRATION_DATE_STRING +
ContinuationToken.SEPARATOR + SIGNATURE);
+ }
+
+ @Test(expected = MalformedContinuationTokenException.class)
+ public void continuationTokenWithMalformedDatesShouldThrow() throws
Exception {
+ ContinuationToken.fromString(USER + ContinuationToken.SEPARATOR +
"2011-25-03T10:15:30+01:00" + ContinuationToken.SEPARATOR + SIGNATURE);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void nullContinuationTokenShouldThrow() throws Exception {
+ ContinuationToken.fromString(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void emptyContinuationTokenShouldThrow() throws Exception {
+ ContinuationToken.fromString("");
+ }
+
+ @Test
+ public void getAsStringShouldReturnACorrectResult() throws Exception {
+ assertThat(new ContinuationToken(USER, expirationDate,
SIGNATURE).serialize())
+ .isEqualTo(USER + ContinuationToken.SEPARATOR +
EXPIRATION_DATE_STRING + ContinuationToken.SEPARATOR + SIGNATURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void newContinuationTokenWithNullUsernameShouldThrow() {
+ new ContinuationToken(null, expirationDate, SIGNATURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void newContinuationTokenWithNullExpirationDateShouldThrow() {
+ new ContinuationToken(USER, null, SIGNATURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void newContinuationTokenWithNullSignatureShouldThrow() {
+ new ContinuationToken(USER, expirationDate, null);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]