Author: angela
Date: Tue Apr  8 15:43:26 2014
New Revision: 1585763

URL: http://svn.apache.org/r1585763
Log:
OAK-1697 : Unresolved conflicts in TokenProviderImpl#createToken()

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java?rev=1585763&r1=1585762&r2=1585763&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
 Tue Apr  8 15:43:26 2014
@@ -29,6 +29,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.AccessDeniedException;
@@ -210,11 +211,7 @@ class TokenProviderImpl implements Token
         if (tokenParent != null) {
             try {
                 long creationTime = new Date().getTime();
-                Calendar creation = GregorianCalendar.getInstance();
-                creation.setTimeInMillis(creationTime);
-                String tokenName = Text.replace(ISO8601.format(creation), ":", 
".");
-
-                NodeUtil tokenNode = tokenParent.addChild(tokenName, 
TOKEN_NT_NAME);
+                NodeUtil tokenNode = createTokenNode(tokenParent, 
creationTime);
                 tokenNode.setString(JcrConstants.JCR_UUID, 
IdentifierManager.generateUUID());
 
                 String key = 
generateKey(options.getConfigValue(PARAM_TOKEN_LENGTH, DEFAULT_KEY_SIZE));
@@ -397,6 +394,31 @@ class TokenProviderImpl implements Token
         return tokenParent;
     }
 
+    /**
+     * Create a new token node below the specified {@code parent}.
+     *
+     * @param parent The parent node.
+     * @param creationTime The creation time that is used as name hint.
+     * @return The new token node
+     * @throws AccessDeniedException
+     */
+    private NodeUtil createTokenNode(@Nonnull NodeUtil parent, @Nonnull long 
creationTime) throws AccessDeniedException {
+        Calendar creation = GregorianCalendar.getInstance();
+        creation.setTimeInMillis(creationTime);
+        String tokenName = Text.replace(ISO8601.format(creation), ":", ".");
+        NodeUtil tokenNode;
+        try {
+            tokenNode = parent.addChild(tokenName, TOKEN_NT_NAME);
+            root.commit();
+        } catch (CommitFailedException e) {
+            // conflict while creating token node -> retry
+            log.debug("Failed to create token node " + tokenName + ". Using 
random name as fallback.");
+            root.refresh();
+            tokenNode = parent.addChild(UUID.randomUUID().toString(), 
TOKEN_NT_NAME);
+        }
+        return tokenNode;
+    }
+
     
//--------------------------------------------------------------------------
 
     /**

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java?rev=1585763&r1=1585762&r2=1585763&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
 Tue Apr  8 15:43:26 2014
@@ -23,6 +23,10 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
 import javax.jcr.GuestCredentials;
@@ -30,11 +34,14 @@ import javax.jcr.SimpleCredentials;
 
 import org.apache.jackrabbit.JcrConstants;
 import 
org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
+import org.apache.jackrabbit.oak.api.ContentSession;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
 import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenProvider;
 import org.apache.jackrabbit.oak.util.NodeUtil;
@@ -308,6 +315,51 @@ public class TokenProviderImplTest exten
         }
     }
 
+    /**
+     *@see <a 
href="https://issues.apache.org/jira/browse/OAK-1697";>OAK-1697</a>
+     */
+    @Test
+    public void testValidTokenCredentialsWithConflict() throws Exception {
+        ExecutorService pool = Executors.newFixedThreadPool(10);
+        List<ContentSession> sessions = new ArrayList<ContentSession>();
+
+        try {
+            TokenConfiguration tc = getSecurityProvider().getConfiguration(
+                    TokenConfiguration.class);
+            SimpleCredentials sc = (SimpleCredentials) getAdminCredentials();
+
+            List<TokenProvider> tokenProviders = new 
ArrayList<TokenProvider>();
+
+            for (int i = 0; i < 10; i++) {
+                ContentSession session = login(getAdminCredentials());
+                Root r = session.getLatestRoot();
+                tokenProviders.add(tc.getTokenProvider(r));
+                sessions.add(session);
+            }
+
+            ArrayList<DataFuture> list = new ArrayList<DataFuture>();
+
+            for (TokenProvider tokenProvider : tokenProviders) {
+                list.add(createDataFuture(pool, tokenProvider, sc.getUserID(),
+                        Collections.<String, Object> emptyMap()));
+            }
+
+            for (DataFuture df : list) {
+                assertNotNull(df.future.get());
+            }
+        } finally {
+            for (ContentSession session : sessions) {
+                if (session != null) {
+                    session.close();
+                }
+            }
+
+            if (pool != null) {
+                pool.shutdown();
+            }
+        }
+    }
+
     
//--------------------------------------------------------------------------
     private static void assertTokenInfo(TokenInfo info, String userId) {
         assertNotNull(info);
@@ -330,4 +382,23 @@ public class TokenProviderImplTest exten
         tree.setProperty(tokenTree.getProperty("rep:token.key"));
         tree.setProperty(tokenTree.getProperty("rep:token.exp"));
     }
+    
+    private static class DataFuture {
+        public Future<TokenInfo> future;
+
+        public DataFuture(Future<TokenInfo> future) {
+            super();
+            this.future = future;
+        }
+    }
+    
+    private DataFuture createDataFuture(ExecutorService pool , final 
TokenProvider tp,final String userId, final Map<String, ?> attributes){
+        Future<TokenInfo> future = pool.submit(new Callable<TokenInfo>() {
+            @Override
+            public TokenInfo call() throws Exception {
+                return tp.createToken(userId, attributes);
+            }
+        });
+        return new DataFuture(future);
+    }
 }
\ No newline at end of file


Reply via email to