From 34b7567d8f886f79b812ad17ab403491088f0a89 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Thu, 4 Sep 2008 13:23:16 +0000
Subject: [PATCH] LMS-445 TokenGenerator with tests moved from project lims to
 common.

SVN: 8208
---
 .../cisd/common/utilities/TokenGenerator.java | 60 ++++++++++++++++
 .../common/utilities/TokenGeneratorTest.java  | 72 +++++++++++++++++++
 2 files changed, 132 insertions(+)
 create mode 100644 common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java
 create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java

diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java b/common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java
new file mode 100644
index 00000000000..15118d7356c
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.common.utilities;
+
+import java.security.SecureRandom;
+import java.util.Formatter;
+
+import ch.rinn.restrictions.Private;
+
+/**
+ * A generator for (pseudo-)random session tokens. It uses the lower half of a time stamp and adds a
+ * 128 bit pseudo-random number. Tokens are returned in hexadecimal format.
+ * 
+ * @author Bernd Rinn
+ */
+public final class TokenGenerator
+{
+    @Private
+    static final String TIMESTAMP_FORMAT = "%1$ty%1$tm%1$td%1$tH%1$tM%1$tS%1$tL-";
+
+    private final SecureRandom pseudoRandomNumberGenerator = new SecureRandom();
+
+    /**
+     * @param timeStamp The time stamp (in milli-seconds since start of the epoch) to base token
+     *            generation on.
+     * @return A new (pseudo-)random session token in hex format.
+     */
+    public synchronized String getNewToken(final long timeStamp)
+    {
+        final Formatter formatter = new Formatter();
+        final byte[] bytes = new byte[16];
+        formatter.format(TIMESTAMP_FORMAT, timeStamp);
+        pseudoRandomNumberGenerator.nextBytes(bytes);
+        hexify(formatter, bytes);
+        return formatter.toString();
+    }
+
+    private static void hexify(final Formatter formatter, final byte[] bytes)
+    {
+        for (final byte b : bytes)
+        {
+            formatter.format("%02X", b);
+        }
+    }
+
+}
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java
new file mode 100644
index 00000000000..b270fca9667
--- /dev/null
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.common.utilities;
+
+import org.apache.commons.lang.StringUtils;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.common.utilities.TokenGenerator;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ * Test cases for the {@link TokenGenerator}.
+ * 
+ * @author Bernd Rinn
+ */
+public class TokenGeneratorTest
+{
+
+    private static final String TIMESTAMP_FORMAT =
+            TokenGenerator.TIMESTAMP_FORMAT.substring(0,
+                    TokenGenerator.TIMESTAMP_FORMAT.length() - 1);
+
+    private static boolean isHexString(String s)
+    {
+        for (int i = 0; i < s.length(); ++i)
+        {
+            if (Character.isLetterOrDigit(s.charAt(i)) == false)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Test
+    public void testTokenIsWellformed()
+    {
+        final TokenGenerator generator = new TokenGenerator();
+        final long now = System.currentTimeMillis();
+        final String nowFormatted = String.format(TIMESTAMP_FORMAT, now);
+        final String[] token = StringUtils.split(generator.getNewToken(now), '-');
+        assertEquals(2, token.length);
+        assertEquals(nowFormatted, token[0]);
+        assert isHexString(token[1]) : token[1];
+    }
+
+    @Test
+    public void testTokensAreDifferent()
+    {
+        final TokenGenerator generator = new TokenGenerator();
+        final long now = System.currentTimeMillis();
+        final String[] token1 = StringUtils.split(generator.getNewToken(now), '-');
+        final String[] token2 = StringUtils.split(generator.getNewToken(now), '-');
+        assert token1[0].equals(token2[0]) : "'" + token1[0] + "' != '" + token2[0] + "'";
+        assert token1[1].equals(token2[1]) == false : "'" + token1[1] + "' == '" + token2[1] + "'";
+    }
+}
-- 
GitLab