Author: [email protected]
Date: Mon Sep 26 14:28:29 2011
New Revision: 1415

Log:
[AMDATUCASSANDRA-93] Fixed multi tenancy of Cassandra nonce store

Added:
   
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/NonceStoreTest.java
Modified:
   
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/osgi/Activator.java
   
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/CassandraNonceStorageProviderImpl.java
   
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/NonceColumnFamilyProvider.java
   
trunk/amdatu-cassandra/test-integration/base/src/main/java/org/amdatu/cassandra/test/integration/base/CassandraFixture.java
   trunk/amdatu-cassandra/test-integration/pom.xml
   trunk/amdatu-cassandra/test-integration/tests/pom.xml
   
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/OAuthServiceConsumerRESTTest.java
   
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTest.java
   
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTestBase.java

Modified: 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/osgi/Activator.java
==============================================================================
--- 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/osgi/Activator.java
     (original)
+++ 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/osgi/Activator.java
     Mon Sep 26 14:28:29 2011
@@ -16,14 +16,14 @@
 package org.amdatu.cassandra.store.nonce.osgi;
 
 import org.amdatu.auth.oauth.server.OAuthNonceStorageProvider;
-import org.amdatu.cassandra.listener.ColumnFamilyAvailable;
 import org.amdatu.cassandra.listener.ColumnFamilyProvider;
-import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
 import 
org.amdatu.cassandra.store.nonce.service.CassandraNonceStorageProviderImpl;
 import org.amdatu.cassandra.store.nonce.service.NonceColumnFamilyProvider;
+import org.amdatu.core.tenant.Tenant;
 import org.apache.felix.dm.DependencyActivatorBase;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
 
 /**
  * This is the bundle activator for the Cassandra nonce store bundle.
@@ -36,17 +36,12 @@
             .setInterface(new String[]{ColumnFamilyProvider.class.getName()}, 
null)
             .setImplementation(NonceColumnFamilyProvider.class));
 
-        // Create and register the Cassandra Service consumer storage provider
-        String keyspaceFilter = "(" + 
CassandraPersistenceManager.KEYSPACE_AWARE_KEY + "="
-        + CassandraPersistenceManager.DEFAULT_KEYSPACE + ")";
-        String nonceCFFilter =  "(&" + keyspaceFilter + "(" + 
ColumnFamilyAvailable.FILTER_NAME
-        + "=" + NonceColumnFamilyProvider.CF_NONCE + "))";
+        // Create and register the Cassandra nonce storage provider
         manager.add(
-            createComponent()
+            createAdapterService(Tenant.class, null)
             .setImplementation(CassandraNonceStorageProviderImpl.class)
             .setInterface(OAuthNonceStorageProvider.class.getName(), null)
-            
.add(createServiceDependency().setService(CassandraPersistenceManager.class, 
keyspaceFilter).setRequired(true))
-            
.add(createServiceDependency().setService(ColumnFamilyAvailable.class, 
nonceCFFilter).setRequired(true)));
+            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
     }
 
     @Override

Modified: 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/CassandraNonceStorageProviderImpl.java
==============================================================================
--- 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/CassandraNonceStorageProviderImpl.java
  (original)
+++ 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/CassandraNonceStorageProviderImpl.java
  Mon Sep 26 14:28:29 2011
@@ -16,7 +16,12 @@
 package org.amdatu.cassandra.store.nonce.service;
 
 import org.amdatu.auth.oauth.server.OAuthNonceStorageProvider;
+import org.amdatu.cassandra.listener.ColumnFamilyAvailable;
 import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
+import org.amdatu.core.tenant.Tenant;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.service.log.LogService;
 
 /**
  * This class provides a Cassandra based implementation of a OAuth nonce store.
@@ -30,7 +35,13 @@
     // We use time to live of 5 minutes
     public static final int DEFAULT_NONCE_TTL = 5 * 60;
 
-    // Service dependencies, injected by the dependency manager
+    // Tenant unaware service dependencies, injected by the dependency manager
+    private volatile Component m_component;
+    private volatile DependencyManager m_dependencyManager;
+    private volatile Tenant m_tenant;
+    private volatile LogService m_logService;
+    
+    // Tenant aware service dependencies, injected by the dependency manager
     private volatile CassandraPersistenceManager m_pm;
 
     // The time to live of nonces
@@ -43,7 +54,7 @@
      * Default constructor.
      */
     public CassandraNonceStorageProviderImpl() {
-        m_ttl = DEFAULT_NONCE_TTL;
+        setTTL(DEFAULT_NONCE_TTL);
     }
 
     /**
@@ -56,6 +67,27 @@
         m_pm = pm;
         m_ttl = ttl;
     }
+    
+    public void init() {
+        // Add tenant specific service dependencies      
+        String ksFilter = "(" + CassandraPersistenceManager.KEYSPACE_AWARE_KEY 
+ "=" + m_tenant.getId() + ")";
+        m_component.add(m_dependencyManager.createServiceDependency()
+            .setService(CassandraPersistenceManager.class, ksFilter)
+            .setRequired(true)
+            .setInstanceBound(true));
+
+        String cfFilter = "(" + ColumnFamilyAvailable.FILTER_NAME + "=" + 
NonceColumnFamilyProvider.CF_NONCE + ")";
+        String cfAvailableFilter =  "(&" + ksFilter + cfFilter + ")";
+        m_component.add(m_dependencyManager.createServiceDependency()
+            .setService(ColumnFamilyAvailable.class, cfAvailableFilter)
+            .setRequired(true)
+            .setInstanceBound(true));        
+    }
+    
+    public void start() {
+        m_logService.log(LogService.LOG_INFO,
+            "Service '" + getClass().getName() + "' started for tenant '" + 
m_tenant.getId() + "'");
+    }
 
     public boolean addNonce(long timestamp, String nonce, String[] 
requestParams) {
         String rowKey = getRowKey(timestamp, nonce, requestParams);
@@ -86,4 +118,9 @@
         rowkey += timestamp;
         return rowkey;
     }
+    
+    // Sets the TTL
+    public void setTTL(int ttl) {
+        m_ttl = ttl;
+    }
 }

Modified: 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/NonceColumnFamilyProvider.java
==============================================================================
--- 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/NonceColumnFamilyProvider.java
  (original)
+++ 
trunk/amdatu-cassandra/cassandra-store-nonce/src/main/java/org/amdatu/cassandra/store/nonce/service/NonceColumnFamilyProvider.java
  Mon Sep 26 14:28:29 2011
@@ -19,7 +19,6 @@
 import org.amdatu.cassandra.listener.ColumnFamilyDefinition.ColumnType;
 import org.amdatu.cassandra.listener.ColumnFamilyDefinition.CompareType;
 import org.amdatu.cassandra.listener.ColumnFamilyProvider;
-import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
 
 public class NonceColumnFamilyProvider implements ColumnFamilyProvider {
     /**
@@ -32,7 +31,7 @@
         return new ColumnFamilyDefinition[] {
             new ColumnFamilyDefinition(
                 CF_NONCE,
-                    new String[] 
{CassandraPersistenceManager.DEFAULT_KEYSPACE},
+                    null,
                     ColumnType.STANDARD,
                     CompareType.BYTESTYPE,
                     null)};

Modified: 
trunk/amdatu-cassandra/test-integration/base/src/main/java/org/amdatu/cassandra/test/integration/base/CassandraFixture.java
==============================================================================
--- 
trunk/amdatu-cassandra/test-integration/base/src/main/java/org/amdatu/cassandra/test/integration/base/CassandraFixture.java
 (original)
+++ 
trunk/amdatu-cassandra/test-integration/base/src/main/java/org/amdatu/cassandra/test/integration/base/CassandraFixture.java
 Mon Sep 26 14:28:29 2011
@@ -42,6 +42,7 @@
             
mavenBundle().groupId("org.amdatu.cassandra").artifactId("org.amdatu.cassandra.store.tenant").versionAsInProject(),
             
mavenBundle().groupId("org.amdatu.cassandra").artifactId("org.amdatu.cassandra.store.consumer").versionAsInProject(),
             
mavenBundle().groupId("org.amdatu.cassandra").artifactId("org.amdatu.cassandra.store.token").versionAsInProject(),
+            
mavenBundle().groupId("org.amdatu.cassandra").artifactId("org.amdatu.cassandra.store.nonce").versionAsInProject(),
             
             // The following 2 artifacts are necessary for default tenant 
resolving
             
mavenBundle().groupId("org.amdatu.web").artifactId("org.amdatu.web.tenantresolver.hostname").versionAsInProject(),
@@ -49,6 +50,7 @@
             
             // Provision Auth bundles
             
mavenBundle().groupId("org.amdatu.auth").artifactId("org.amdatu.auth.oauth.api").versionAsInProject(),
+            
mavenBundle().groupId("org.amdatu.auth").artifactId("org.amdatu.auth.oauth.server").versionAsInProject(),
             
mavenBundle().groupId("org.amdatu.auth").artifactId("org.amdatu.auth.oauth.consumerregistry").versionAsInProject(),
             
mavenBundle().groupId("org.amdatu.auth").artifactId("org.amdatu.auth.tokenprovider").versionAsInProject(),
             

Modified: trunk/amdatu-cassandra/test-integration/pom.xml
==============================================================================
--- trunk/amdatu-cassandra/test-integration/pom.xml     (original)
+++ trunk/amdatu-cassandra/test-integration/pom.xml     Mon Sep 26 14:28:29 2011
@@ -133,6 +133,13 @@
       </dependency>
       <dependency>
         <groupId>org.amdatu.auth</groupId>
+        <artifactId>org.amdatu.auth.oauth.server</artifactId>
+        <version>${org.amdatu.auth.version}</version>
+        <scope>compile</scope>
+        <type>bundle</type>
+      </dependency>
+      <dependency>
+        <groupId>org.amdatu.auth</groupId>
         <artifactId>org.amdatu.auth.tokenprovider</artifactId>
         <version>${org.amdatu.auth.version}</version>
         <scope>compile</scope>

Modified: trunk/amdatu-cassandra/test-integration/tests/pom.xml
==============================================================================
--- trunk/amdatu-cassandra/test-integration/tests/pom.xml       (original)
+++ trunk/amdatu-cassandra/test-integration/tests/pom.xml       Mon Sep 26 
14:28:29 2011
@@ -97,6 +97,13 @@
         <scope>test</scope>
         <type>bundle</type>
       </dependency>
+      <dependency>
+        <groupId>org.amdatu.cassandra</groupId>
+        <artifactId>org.amdatu.cassandra.store.nonce</artifactId>
+        <version>${project.version}</version>
+        <scope>test</scope>
+        <type>bundle</type>
+      </dependency>
 
       <dependency>
         <groupId>commons-httpclient</groupId>
@@ -157,6 +164,11 @@
       <artifactId>org.amdatu.cassandra.store.tenant</artifactId>
       <type>bundle</type>
     </dependency>
+    <dependency>
+      <groupId>org.amdatu.cassandra</groupId>
+      <artifactId>org.amdatu.cassandra.store.nonce</artifactId>
+      <type>bundle</type>
+    </dependency>
 
     <dependency>
       <groupId>org.amdatu.auth</groupId>
@@ -170,6 +182,11 @@
     </dependency>
     <dependency>
       <groupId>org.amdatu.auth</groupId>
+      <artifactId>org.amdatu.auth.oauth.server</artifactId>
+      <type>bundle</type>
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.auth</groupId>
       <artifactId>org.amdatu.auth.tokenprovider</artifactId>
       <type>bundle</type>
     </dependency>

Added: 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/NonceStoreTest.java
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/NonceStoreTest.java
 Mon Sep 26 14:28:29 2011
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2011 The Amdatu Foundation
+ * 
+ * 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 org.amdatu.cassandra.test.integration.tests;
+
+import junit.framework.Assert;
+
+import 
org.amdatu.cassandra.store.nonce.service.CassandraNonceStorageProviderImpl;
+import org.amdatu.cassandra.test.integration.tests.framework.CassandraTestBase;
+
+public class NonceStoreTest extends CassandraTestBase {
+
+    public void execute() throws Exception {        
+        // Now with the Cassandra implementation, we should wait for 5 minutes 
to verify that the 
+        // nonces have been removed. But we can't just block the integration 
test for that long, so 
+        // we change the TTL to 1 second
+        int ttl = 1;
+        
+        if (m_OAuthNonceStore instanceof CassandraNonceStorageProviderImpl) {
+            ((CassandraNonceStorageProviderImpl) 
m_OAuthNonceStore).setTTL(ttl);
+        } else {
+            Assert.fail("Expected to retrieve the Cassandra nonce store, but 
received a different implementation.");
+        }
+       
+        String nonce = "A";
+        long timestamp1 = 10000; // second 10
+        long timestamp2 = 10001;
+        long timestamp3 = 10002;
+        long timestamp4 = 20000;
+        long timestamp5 = 2435436;
+        
+        // Validate that the same nonce can be added only once
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp1, nonce, null));
+        assertFalse(m_OAuthNonceStore.addNonce(timestamp1, nonce, null));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp2, nonce, null));
+        assertFalse(m_OAuthNonceStore.addNonce(timestamp2, nonce, null));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp3, nonce, new 
String[]{"arg1"}));
+        assertFalse(m_OAuthNonceStore.addNonce(timestamp3, nonce, new 
String[]{"arg1"}));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp4, nonce, new 
String[]{"arg2"}));
+        assertFalse(m_OAuthNonceStore.addNonce(timestamp4, nonce, new 
String[]{"arg2"}));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp5, nonce, new 
String[]{"arg1", "arg2"}));
+        assertFalse(m_OAuthNonceStore.addNonce(timestamp5, nonce, new 
String[]{"arg1", "arg2"}));
+
+        try {
+            // The TTL in Cassandra can be set in seconds, not milliseconds. 
So that means that columns 
+            // are removed for certain after TTL + 1 seconds (due to rounding 
errors)
+            Thread.sleep((ttl + 1)*1000);
+        }
+        catch (InterruptedException e) {
+        }
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp1, nonce, null));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp2, nonce, null));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp3, nonce, new 
String[]{"arg1"}));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp4, nonce, new 
String[]{"arg2"}));
+        assertTrue(m_OAuthNonceStore.addNonce(timestamp5, nonce, new 
String[]{"arg1", "arg2"}));
+    }
+}

Modified: 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/OAuthServiceConsumerRESTTest.java
==============================================================================
--- 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/OAuthServiceConsumerRESTTest.java
   (original)
+++ 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/OAuthServiceConsumerRESTTest.java
   Mon Sep 26 14:28:29 2011
@@ -1,6 +1,6 @@
 package org.amdatu.cassandra.test.integration.tests;
 
-import static junit.framework.Assert.assertTrue;
+import junit.framework.Assert;
 
 import org.amdatu.cassandra.test.integration.base.CassandraFixture;
 import org.amdatu.cassandra.test.integration.tests.framework.CassandraTestBase;
@@ -22,7 +22,7 @@
         try {
             // Execute the method, this should return a 200
             int statusCode = httpClient.executeMethod(method);
-            assertTrue("HTTP GET to '" + url + "' returned " + statusCode, 
statusCode == 200);
+            Assert.assertTrue("HTTP GET to '" + url + "' returned " + 
statusCode, statusCode == 200);
         }
         finally {
             // Release the connection.

Modified: 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTest.java
==============================================================================
--- 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTest.java
        (original)
+++ 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTest.java
        Mon Sep 26 14:28:29 2011
@@ -23,12 +23,14 @@
 import static org.ops4j.pax.exam.LibraryOptions.junitBundles;
 
 import org.amdatu.auth.oauth.consumerregistry.OAuthServiceConsumerRegistry;
+import org.amdatu.auth.oauth.server.OAuthNonceStorageProvider;
 import org.amdatu.cassandra.application.CassandraConfigurationService;
 import org.amdatu.cassandra.application.CassandraDaemonService;
 import 
org.amdatu.cassandra.persistencemanager.CassandraPersistenceManagerFactory;
 import org.amdatu.cassandra.test.integration.base.CassandraFixture;
 import org.amdatu.cassandra.test.integration.tests.CassandraDaemonTest;
 import 
org.amdatu.cassandra.test.integration.tests.CassandraPersistenceManagerTest;
+import org.amdatu.cassandra.test.integration.tests.NonceStoreTest;
 import 
org.amdatu.cassandra.test.integration.tests.OAuthServiceConsumerRESTTest;
 import org.amdatu.cassandra.test.integration.tests.OAuthServiceConsumerTest;
 import org.amdatu.cassandra.test.integration.tests.UserAdminStoreTest;
@@ -66,6 +68,7 @@
     private TestContext m_testContext;
     private UserAdmin m_userAdmin;
     private OAuthServiceConsumerRegistry m_consumerRegistry;
+    private OAuthNonceStorageProvider m_nonceStore;
    
     @Configuration
     public Option[] config() {
@@ -110,6 +113,7 @@
         m_pmFactory = assertAvailable(m_testContext, 
CassandraPersistenceManagerFactory.class);
         m_userAdmin = assertAvailable(m_testContext, UserAdmin.class);
         m_consumerRegistry = assertAvailable(m_testContext, 
OAuthServiceConsumerRegistry.class);
+        m_nonceStore = assertAvailable(m_testContext, 
OAuthNonceStorageProvider.class);
       
         // Create the dependency manager
         m_dependencyManager = new 
DependencyManager(m_testContext.getBundleContext());
@@ -120,15 +124,18 @@
         test(UserAdminStoreTest.class);
         test(OAuthServiceConsumerTest.class);
         test(OAuthServiceConsumerRESTTest.class);
+        test(NonceStoreTest.class);
         
         // And we are done
         m_testContext.tearDown();
     }
 
     private <T extends CassandraTestBase> void test(Class<T> testClass) throws 
Exception {
+        m_logService.log(LogService.LOG_INFO, "Starting test '" + testClass + 
"'...");
         T test = testClass.newInstance();
         init(test);
         test.execute();
+        m_logService.log(LogService.LOG_INFO, "Finished test '" + testClass + 
"'...");
     }
     
     private void init(CassandraTestBase test) {
@@ -140,5 +147,6 @@
         test.setTestContext(m_testContext);
         test.setUserAdmin(m_userAdmin);
         test.setOAuthConsumerRegistry(m_consumerRegistry);
+        test.setOAuthNonceStore(m_nonceStore);
     }
 }

Modified: 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTestBase.java
==============================================================================
--- 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTestBase.java
    (original)
+++ 
trunk/amdatu-cassandra/test-integration/tests/src/test/java/org/amdatu/cassandra/test/integration/tests/framework/CassandraTestBase.java
    Mon Sep 26 14:28:29 2011
@@ -15,7 +15,10 @@
  */
 package org.amdatu.cassandra.test.integration.tests.framework;
 
+import junit.framework.Assert;
+
 import org.amdatu.auth.oauth.consumerregistry.OAuthServiceConsumerRegistry;
+import org.amdatu.auth.oauth.server.OAuthNonceStorageProvider;
 import org.amdatu.cassandra.application.CassandraDaemonService;
 import 
org.amdatu.cassandra.persistencemanager.CassandraPersistenceManagerFactory;
 import org.amdatu.core.itest.base.TestContext;
@@ -33,6 +36,7 @@
     protected volatile TestContext m_testContext;
     protected volatile UserAdmin m_userAdmin;
     protected volatile OAuthServiceConsumerRegistry m_OAuthConsumerRegistry;
+    protected volatile OAuthNonceStorageProvider m_OAuthNonceStore;
     
     public abstract void execute() throws Exception;
     
@@ -66,5 +70,32 @@
     
     public void setOAuthConsumerRegistry(OAuthServiceConsumerRegistry 
registry) {
         m_OAuthConsumerRegistry = registry;
+    }
+    
+    public void setOAuthNonceStore(OAuthNonceStorageProvider store) {
+        m_OAuthNonceStore = store;
+    }
+    
+    protected void assertFalse(boolean check) {
+        Assert.assertFalse(getStackTrace(), check);
+    }
+    protected void assertTrue(boolean check) {
+        Assert.assertTrue(getStackTrace(), check);
+    }
+    
+    protected String getStackTrace() {
+        String eol = System.getProperty("line.separator");
+        String stackTrace = "Assertion failed." + eol + "Stacktrace:" + eol;
+        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
+        int lineCount = 0;
+        for (StackTraceElement element : elements) {
+            if (lineCount < 10) {
+                stackTrace += element.toString() + eol;
+            } else if (lineCount == 10) {
+                stackTrace += "..." + eol;
+            }
+            lineCount++;
+        }
+        return stackTrace;
     }
 }
_______________________________________________
Amdatu-commits mailing list
[email protected]
http://lists.amdatu.org/mailman/listinfo/amdatu-commits

Reply via email to