diff --git a/commons/src/main/java/com/microsoft/azure/cosmosdb/HashIndex.java b/commons/src/main/java/com/microsoft/azure/cosmosdb/HashIndex.java index 2c351733d..e4aa804ea 100644 --- a/commons/src/main/java/com/microsoft/azure/cosmosdb/HashIndex.java +++ b/commons/src/main/java/com/microsoft/azure/cosmosdb/HashIndex.java @@ -84,31 +84,6 @@ public HashIndex(String jsonString) { } } - /** - * Gets data type. - * - * @return the data type. - */ - public DataType getDataType() { - DataType result = null; - try { - result = DataType.valueOf(WordUtils.capitalize(super.getString(Constants.Properties.DATA_TYPE))); - } catch (IllegalArgumentException e) { - // Ignore exception and let the caller handle null value. - this.getLogger().warn("Invalid index dataType value {}.", super.getString(Constants.Properties.DATA_TYPE)); - } - return result; - } - - /** - * Sets data type. - * - * @param dataType the data type. - */ - public void setDataType(DataType dataType) { - super.set(Constants.Properties.DATA_TYPE, dataType.name()); - } - /** * Gets precision. * diff --git a/commons/src/main/java/com/microsoft/azure/cosmosdb/Index.java b/commons/src/main/java/com/microsoft/azure/cosmosdb/Index.java index 7a3b00a6d..e5f132dae 100644 --- a/commons/src/main/java/com/microsoft/azure/cosmosdb/Index.java +++ b/commons/src/main/java/com/microsoft/azure/cosmosdb/Index.java @@ -163,4 +163,28 @@ public IndexKind getKind() { private void setKind(IndexKind indexKind) { super.set(Constants.Properties.INDEX_KIND, indexKind.name()); } + + /** + * Gets data type. + * + * @return the data type. + */ + public DataType getDataType() { + DataType result = null; + try { + result = DataType.valueOf(WordUtils.capitalize(super.getString(Constants.Properties.DATA_TYPE))); + } catch (IllegalArgumentException e) { + this.getLogger().warn("Invalid index dataType value {}.", super.getString(Constants.Properties.DATA_TYPE)); + } + return result; + } + + /** + * Sets data type. + * + * @param dataType the data type. + */ + public void setDataType(DataType dataType) { + super.set(Constants.Properties.DATA_TYPE, dataType.name()); + } } diff --git a/commons/src/main/java/com/microsoft/azure/cosmosdb/RangeIndex.java b/commons/src/main/java/com/microsoft/azure/cosmosdb/RangeIndex.java index 27ef781fe..4b92093eb 100644 --- a/commons/src/main/java/com/microsoft/azure/cosmosdb/RangeIndex.java +++ b/commons/src/main/java/com/microsoft/azure/cosmosdb/RangeIndex.java @@ -81,30 +81,6 @@ public RangeIndex(String jsonString) { } } - /** - * Gets data type. - * - * @return the data type. - */ - public DataType getDataType() { - DataType result = null; - try { - result = DataType.valueOf(WordUtils.capitalize(super.getString(Constants.Properties.DATA_TYPE))); - } catch (IllegalArgumentException e) { - this.getLogger().warn("Invalid index dataType value {}.", super.getString(Constants.Properties.DATA_TYPE)); - } - return result; - } - - /** - * Sets data type. - * - * @param dataType the data type. - */ - public void setDataType(DataType dataType) { - super.set(Constants.Properties.DATA_TYPE, dataType.name()); - } - /** * Gets precision. * diff --git a/commons/src/main/java/com/microsoft/azure/cosmosdb/SpatialIndex.java b/commons/src/main/java/com/microsoft/azure/cosmosdb/SpatialIndex.java index a263640bc..ec3856ca9 100644 --- a/commons/src/main/java/com/microsoft/azure/cosmosdb/SpatialIndex.java +++ b/commons/src/main/java/com/microsoft/azure/cosmosdb/SpatialIndex.java @@ -63,27 +63,4 @@ public SpatialIndex(String jsonString) { } } - /** - * Gets data type. - * - * @return the data type. - */ - public DataType getDataType() { - DataType result = null; - try { - result = DataType.valueOf(WordUtils.capitalize(super.getString(Constants.Properties.DATA_TYPE))); - } catch (IllegalArgumentException e) { - this.getLogger().warn("Invalid index dataType value {}.", super.getString(Constants.Properties.DATA_TYPE)); - } - return result; - } - - /** - * Sets data type. - * - * @param dataType the data type. - */ - public void setDataType(DataType dataType) { - super.set(Constants.Properties.DATA_TYPE, dataType.name()); - } } diff --git a/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/ResourceTokenAuthorizationHelper.java b/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/ResourceTokenAuthorizationHelper.java index 9e0577917..61f9efcd5 100644 --- a/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/ResourceTokenAuthorizationHelper.java +++ b/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/ResourceTokenAuthorizationHelper.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -211,4 +212,34 @@ public static String getAuthorizationTokenUsingResourceTokens( return resourceToken; } } + + /** + * Checks whether the specified path segment is a resource type + * + * @param resourcePathSegment the path segment to analyze. + * @return true or false + */ + public static boolean IsResourceType(String resourcePathSegment) { + if (StringUtils.isEmpty(resourcePathSegment)) { + return false; + } + + switch (resourcePathSegment.toLowerCase()) { + case Paths.ATTACHMENTS_PATH_SEGMENT: + case Paths.COLLECTIONS_PATH_SEGMENT: + case Paths.DATABASES_PATH_SEGMENT: + case Paths.PERMISSIONS_PATH_SEGMENT: + case Paths.USERS_PATH_SEGMENT: + case Paths.DOCUMENTS_PATH_SEGMENT: + case Paths.STORED_PROCEDURES_PATH_SEGMENT: + case Paths.TRIGGERS_PATH_SEGMENT: + case Paths.USER_DEFINED_FUNCTIONS_PATH_SEGMENT: + case Paths.CONFLICTS_PATH_SEGMENT: + case Paths.PARTITION_KEY_RANGES_PATH_SEGMENT: + return true; + + default: + return false; + } + } } diff --git a/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/Utils.java b/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/Utils.java index 84405cedd..b1ab81f9d 100644 --- a/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/Utils.java +++ b/commons/src/main/java/com/microsoft/azure/cosmosdb/internal/Utils.java @@ -175,35 +175,7 @@ public static boolean isDatabaseLink(String link) { return true; } - /** - * Checks whether the specified path segment is a resource type - * - * @param resourcePathSegment the path segment to analyze. - * @return true or false - */ - public static boolean IsResourceType(String resourcePathSegment) { - if (StringUtils.isEmpty(resourcePathSegment)) { - return false; - } - switch (resourcePathSegment.toLowerCase()) { - case Paths.ATTACHMENTS_PATH_SEGMENT: - case Paths.COLLECTIONS_PATH_SEGMENT: - case Paths.DATABASES_PATH_SEGMENT: - case Paths.PERMISSIONS_PATH_SEGMENT: - case Paths.USERS_PATH_SEGMENT: - case Paths.DOCUMENTS_PATH_SEGMENT: - case Paths.STORED_PROCEDURES_PATH_SEGMENT: - case Paths.TRIGGERS_PATH_SEGMENT: - case Paths.USER_DEFINED_FUNCTIONS_PATH_SEGMENT: - case Paths.CONFLICTS_PATH_SEGMENT: - case Paths.PARTITION_KEY_RANGES_PATH_SEGMENT: - return true; - - default: - return false; - } - } /** * Joins the specified paths by appropriately padding them with '/' diff --git a/direct-impl/src/main/java/com/microsoft/azure/cosmosdb/internal/directconnectivity/StoreClient.java b/direct-impl/src/main/java/com/microsoft/azure/cosmosdb/internal/directconnectivity/StoreClient.java index f51634e9a..455e6e237 100644 --- a/direct-impl/src/main/java/com/microsoft/azure/cosmosdb/internal/directconnectivity/StoreClient.java +++ b/direct-impl/src/main/java/com/microsoft/azure/cosmosdb/internal/directconnectivity/StoreClient.java @@ -25,13 +25,7 @@ import com.microsoft.azure.cosmosdb.ConsistencyLevel; import com.microsoft.azure.cosmosdb.DocumentClientException; -import com.microsoft.azure.cosmosdb.internal.HttpConstants; -import com.microsoft.azure.cosmosdb.internal.ISessionToken; -import com.microsoft.azure.cosmosdb.internal.InternalServerErrorException; -import com.microsoft.azure.cosmosdb.internal.OperationType; -import com.microsoft.azure.cosmosdb.internal.ResourceType; -import com.microsoft.azure.cosmosdb.internal.SessionContainer; -import com.microsoft.azure.cosmosdb.internal.SessionTokenHelper; +import com.microsoft.azure.cosmosdb.internal.*; import com.microsoft.azure.cosmosdb.rx.internal.BackoffRetryUtility; import com.microsoft.azure.cosmosdb.rx.internal.Configs; import com.microsoft.azure.cosmosdb.rx.internal.Exceptions; @@ -199,7 +193,7 @@ private void updateResponseHeader(RxDocumentServiceRequest request, Map partitionKeyRangeSessionToken = ValueHolder.initialize(null); - - if (SessionTokenHelper.tryParse(sessionToken, partitionKeyRangeSessionToken)) { - return partitionKeyRangeSessionToken.v; - } else { - throw new RuntimeException(new BadRequestException(String.format(RMResources.InvalidSessionToken, sessionToken))); - } - } - - static boolean tryParse(String sessionToken, ValueHolder parsedSessionToken) { - parsedSessionToken.v = null; - if (!Strings.isNullOrEmpty(sessionToken)) { - String[] sessionTokenSegments = StringUtils.split(sessionToken,":"); - return VectorSessionToken.tryCreate(sessionTokenSegments[sessionTokenSegments.length - 1], parsedSessionToken); - } else { - return false; - } - } - public static void validateAndRemoveSessionToken(RxDocumentServiceRequest request) throws DocumentClientException { String sessionToken = request.getHeaders().get(HttpConstants.HttpHeaders.SESSION_TOKEN); if (!Strings.isNullOrEmpty(sessionToken)) { diff --git a/gateway/src/main/java/com/microsoft/azure/cosmosdb/internal/SessionTokenParser.java b/gateway/src/main/java/com/microsoft/azure/cosmosdb/internal/SessionTokenParser.java new file mode 100644 index 000000000..3896c05b8 --- /dev/null +++ b/gateway/src/main/java/com/microsoft/azure/cosmosdb/internal/SessionTokenParser.java @@ -0,0 +1,32 @@ +package com.microsoft.azure.cosmosdb.internal; + +import com.microsoft.azure.cosmosdb.rx.internal.BadRequestException; +import com.microsoft.azure.cosmosdb.rx.internal.RMResources; +import com.microsoft.azure.cosmosdb.rx.internal.Strings; +import com.microsoft.azure.cosmosdb.rx.internal.Utils; +import org.apache.commons.lang3.StringUtils; + +public class SessionTokenParser { + + public static ISessionToken parse(String sessionToken) { + Utils.ValueHolder partitionKeyRangeSessionToken = Utils.ValueHolder.initialize(null); + + if (SessionTokenParser.tryParse(sessionToken, partitionKeyRangeSessionToken)) { + return partitionKeyRangeSessionToken.v; + } else { + throw new RuntimeException(new BadRequestException(String.format(RMResources.InvalidSessionToken, sessionToken))); + } + } + + static boolean tryParse(String sessionToken, Utils.ValueHolder parsedSessionToken) { + parsedSessionToken.v = null; + if (!Strings.isNullOrEmpty(sessionToken)) { + String[] sessionTokenSegments = StringUtils.split(sessionToken,":"); + return VectorSessionToken.tryCreate(sessionTokenSegments[sessionTokenSegments.length - 1], parsedSessionToken); + } else { + return false; + } + } + + +} diff --git a/sdk/src/main/java/com/microsoft/azure/cosmosdb/rx/internal/ChangeFeedQueryImpl.java b/sdk/src/main/java/com/microsoft/azure/cosmosdb/rx/internal/ChangeFeedQueryImpl.java index 4b988cd84..d08fc3993 100644 --- a/sdk/src/main/java/com/microsoft/azure/cosmosdb/rx/internal/ChangeFeedQueryImpl.java +++ b/sdk/src/main/java/com/microsoft/azure/cosmosdb/rx/internal/ChangeFeedQueryImpl.java @@ -1,17 +1,17 @@ /* * The MIT License (MIT) * Copyright (c) 2018 Microsoft Corporation - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -52,48 +52,51 @@ class ChangeFeedQueryImpl { private final String documentsLink; private final ChangeFeedOptions options; - public ChangeFeedQueryImpl(RxDocumentClientImpl client, - ResourceType resourceType, - Class klass, - String collectionLink, - ChangeFeedOptions changeFeedOptions) { + public ChangeFeedQueryImpl(RxDocumentClientImpl client, + ResourceType resourceType, + Class klass, + String collectionLink, + ChangeFeedOptions changeFeedOptions) { this.client = client; this.resourceType = resourceType; this.klass = klass; this.documentsLink = Utils.joinPath(collectionLink, Paths.DOCUMENTS_PATH_SEGMENT); - changeFeedOptions = changeFeedOptions != null ? changeFeedOptions: new ChangeFeedOptions(); - + changeFeedOptions = changeFeedOptions != null ? changeFeedOptions : new ChangeFeedOptions(); - if (resourceType.isPartitioned() && changeFeedOptions.getPartitionKeyRangeId() == null && changeFeedOptions.getPartitionKey() == null) { - throw new IllegalArgumentException(RMResources.PartitionKeyRangeIdOrPartitionKeyMustBeSpecified); - } + validateChangeFeedQuery(resourceType, changeFeedOptions); - if (changeFeedOptions.getPartitionKey() != null && - !Strings.isNullOrEmpty(changeFeedOptions.getPartitionKeyRangeId())) { + String requestContinuation = null; - throw new IllegalArgumentException(String.format( - RMResources.PartitionKeyAndParitionKeyRangeIdBothSpecified - , "feedOptions")); - } - - String initialNextIfNoneMatch = null; - boolean canUseStartFromBeginning = true; if (changeFeedOptions.getRequestContinuation() != null) { - initialNextIfNoneMatch = changeFeedOptions.getRequestContinuation(); + requestContinuation = changeFeedOptions.getRequestContinuation(); canUseStartFromBeginning = false; } - if(changeFeedOptions.getStartDateTime() != null){ + if (changeFeedOptions.getStartDateTime() != null) { canUseStartFromBeginning = false; } if (canUseStartFromBeginning && !changeFeedOptions.isStartFromBeginning()) { - initialNextIfNoneMatch = IfNonMatchAllHeaderValue; + requestContinuation = IfNonMatchAllHeaderValue; + } + + this.options = getChangeFeedOptions(changeFeedOptions, requestContinuation); + } + + private void validateChangeFeedQuery(ResourceType resourceType, ChangeFeedOptions changeFeedOptions) { + if (resourceType.isPartitioned() && changeFeedOptions.getPartitionKeyRangeId() == null && changeFeedOptions.getPartitionKey() == null) { + throw new IllegalArgumentException(RMResources.PartitionKeyRangeIdOrPartitionKeyMustBeSpecified); } - this.options = getChangeFeedOptions(changeFeedOptions, initialNextIfNoneMatch); + if (changeFeedOptions.getPartitionKey() != null && + !Strings.isNullOrEmpty(changeFeedOptions.getPartitionKeyRangeId())) { + + throw new IllegalArgumentException(String.format( + RMResources.PartitionKeyAndParitionKeyRangeIdBothSpecified + , "feedOptions")); + } } private RxDocumentServiceRequest createDocumentServiceRequest(String continuationToken, int pageSize) { @@ -104,7 +107,7 @@ private RxDocumentServiceRequest createDocumentServiceRequest(String continuatio } // On REST level, change feed is using IfNoneMatch/ETag instead of continuation. - if(continuationToken != null) { + if (continuationToken != null) { headers.put(HttpConstants.HttpHeaders.IF_NONE_MATCH, continuationToken); } @@ -115,7 +118,7 @@ private RxDocumentServiceRequest createDocumentServiceRequest(String continuatio headers.put(HttpConstants.HttpHeaders.PARTITION_KEY, partitionKey.toJson()); } - if(options.getStartDateTime() != null){ + if (options.getStartDateTime() != null) { String dateTimeInHttpFormat = Utils.zonedDateTimeAsUTCRFC1123(options.getStartDateTime()); headers.put(HttpConstants.HttpHeaders.IF_MODIFIED_SINCE, dateTimeInHttpFormat); } @@ -139,7 +142,7 @@ private ChangeFeedOptions getChangeFeedOptions(ChangeFeedOptions options, String newOps.setRequestContinuation(continuationToken); return newOps; } - + public Observable> executeAsync() { Func2 createRequestFunc = (continuationToken, pageSize) -> this.createDocumentServiceRequest(continuationToken, pageSize); @@ -147,11 +150,11 @@ public Observable> executeAsync() { // TODO: clean up if we want to use single vs observable. Func1>> executeFunc = request -> this.executeRequestAsync(request).toObservable(); - return Paginator.getPaginatedChangeFeedQueryResultAsObservable(options, createRequestFunc, executeFunc, klass, options.getMaxItemCount() != null ? options.getMaxItemCount(): -1); + return Paginator.getPaginatedChangeFeedQueryResultAsObservable(options, createRequestFunc, executeFunc, klass, options.getMaxItemCount() != null ? options.getMaxItemCount() : -1); } private Single> executeRequestAsync(RxDocumentServiceRequest request) { return client.readFeed(request).toSingle() - .map( rsp -> BridgeInternal.toChaneFeedResponsePage(rsp, klass)); + .map(rsp -> BridgeInternal.toChaneFeedResponsePage(rsp, klass)); } } diff --git a/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTests2.java b/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTests2.java index 308bcba4b..87a3943d0 100644 --- a/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTests2.java +++ b/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTests2.java @@ -36,6 +36,7 @@ import com.microsoft.azure.cosmosdb.internal.HttpConstants; import com.microsoft.azure.cosmosdb.internal.ISessionToken; import com.microsoft.azure.cosmosdb.internal.SessionTokenHelper; +import com.microsoft.azure.cosmosdb.internal.SessionTokenParser; import com.microsoft.azure.cosmosdb.internal.directconnectivity.WFConstants; import com.microsoft.azure.cosmosdb.internal.routing.PartitionKeyInternal; import com.microsoft.azure.cosmosdb.rx.AsyncDocumentClient; @@ -206,7 +207,7 @@ public void validateNoChargeOnFailedSessionRead() throws Exception { ResourceResponse childResource = writeClient.createDocument(parentResource.getSelfLink(), documentDefinition, null, true).toBlocking().first(); logger.info("Created {} child resource", childResource.getResource().getResourceId()); - String token = childResource.getSessionToken().split(":")[0] + ":" + this.createSessionToken(SessionTokenHelper.parse(childResource.getSessionToken()), 100000000).convertToString(); + String token = childResource.getSessionToken().split(":")[0] + ":" + this.createSessionToken(SessionTokenParser.parse(childResource.getSessionToken()), 100000000).convertToString(); FeedOptions feedOptions = new FeedOptions(); feedOptions.setPartitionKey(new PartitionKey(PartitionKeyInternal.Empty.toJson())); @@ -270,7 +271,7 @@ public void call(Integer index) { String lsnHeaderValue = queryResponse.getResponseHeaders().get(WFConstants.BackendHeaders.LSN); long lsn = Long.valueOf(lsnHeaderValue); String sessionTokenHeaderValue = queryResponse.getResponseHeaders().get(HttpConstants.HttpHeaders.SESSION_TOKEN); - ISessionToken sessionToken = SessionTokenHelper.parse(sessionTokenHeaderValue); + ISessionToken sessionToken = SessionTokenParser.parse(sessionTokenHeaderValue); logger.info("Session Token = {}, LSN = {}", sessionToken.convertToString(), lsn); assertThat(lsn).isEqualTo(sessionToken.getLSN()); } catch (Exception ex) { @@ -282,7 +283,7 @@ public void call(Integer index) { String lsnHeaderValue = clientException.getResponseHeaders().get(WFConstants.BackendHeaders.LSN); long lsn = Long.valueOf(lsnHeaderValue); String sessionTokenHeaderValue = clientException.getResponseHeaders().get(HttpConstants.HttpHeaders.SESSION_TOKEN); - ISessionToken sessionToken = SessionTokenHelper.parse(sessionTokenHeaderValue); + ISessionToken sessionToken = SessionTokenParser.parse(sessionTokenHeaderValue); logger.info("Session Token = {}, LSN = {}", sessionToken.convertToString(), lsn); assertThat(lsn).isEqualTo(sessionToken.getLSN()); diff --git a/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTestsBase.java b/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTestsBase.java index c26246436..7857f8b18 100644 --- a/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTestsBase.java +++ b/sdk/src/test/java/com/microsoft/azure/cosmosdb/rx/internal/ConsistencyTestsBase.java @@ -40,12 +40,7 @@ import com.microsoft.azure.cosmosdb.Resource; import com.microsoft.azure.cosmosdb.ResourceResponse; import com.microsoft.azure.cosmosdb.User; -import com.microsoft.azure.cosmosdb.internal.HttpConstants; -import com.microsoft.azure.cosmosdb.internal.ISessionToken; -import com.microsoft.azure.cosmosdb.internal.ResourceType; -import com.microsoft.azure.cosmosdb.internal.SessionContainer; -import com.microsoft.azure.cosmosdb.internal.SessionTokenHelper; -import com.microsoft.azure.cosmosdb.internal.VectorSessionToken; +import com.microsoft.azure.cosmosdb.internal.*; import com.microsoft.azure.cosmosdb.internal.directconnectivity.WFConstants; import com.microsoft.azure.cosmosdb.internal.routing.PartitionKeyInternalHelper; import com.microsoft.azure.cosmosdb.internal.routing.Range; @@ -692,7 +687,7 @@ void validateSessionTokenMultiPartitionCollection(boolean useGateway) throws Exc // this token can read childresource2 but not childresource1 String sessionToken = - StringUtils.split(childResource1.getSessionToken(), ':')[0] + ":" + createSessionToken(SessionTokenHelper.parse(childResource1.getSessionToken()), 100000000).convertToString() + "," + childResource2.getSessionToken(); + StringUtils.split(childResource1.getSessionToken(), ':')[0] + ":" + createSessionToken(SessionTokenParser.parse(childResource1.getSessionToken()), 100000000).convertToString() + "," + childResource2.getSessionToken(); RequestOptions option = new RequestOptions(); option.setSessionToken(sessionToken); @@ -771,7 +766,7 @@ public void afterClass() { private String getDifferentLSNToken(String token, long lsnDifferent) throws Exception { String[] tokenParts = StringUtils.split(token, ':'); - ISessionToken sessionToken = SessionTokenHelper.parse(tokenParts[1]); + ISessionToken sessionToken = SessionTokenParser.parse(tokenParts[1]); ISessionToken differentSessionToken = createSessionToken(sessionToken, sessionToken.getLSN() + lsnDifferent); return String.format("%s:%s", tokenParts[0], differentSessionToken.convertToString()); }