Author: angelo.vandersijpt at luminis.eu
Date: Thu Oct 28 13:55:50 2010
New Revision: 214
Log:
AMDATU-121 Refactored the Tenant service to be a little cleaner, and separate
concerns of storage and interaction better. Also, updated the integration tests
for this.
Added:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantEntity.java
- copied, changed from r213,
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantStorageProvider.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantColumnFamilyProvider.java
- copied, changed from r213,
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantColumnFamilyProvider.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantStorageProviderCassandraImpl.java
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantStorageProvider.java
Removed:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/TenantDAOMock.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantAwareService.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantDAOCassandraImpl.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantColumnFamilyProvider.java
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantDAO.java
Modified:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
trunk/platform-bundles/profile-service/src/main/java/org/amdatu/platform/profile/PersonService.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/Tenant.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantException.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantManagementService.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
Modified:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
==============================================================================
---
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
(original)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
Thu Oct 28 13:55:50 2010
@@ -31,8 +31,11 @@
import org.junit.Before;
import org.ops4j.pax.exam.Inject;
import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.container.def.options.VMOption;
import org.ops4j.pax.exam.options.MavenArtifactProvisionOption;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
@@ -66,6 +69,7 @@
// Setting this system property unfortunately is necessary with
the current Cassandra implementation
systemProperty("org.osgi.framework.system.packages.extra").value("sun.misc,com.sun.management"),
+ new VMOption("-Xmx1g"),
// Enable this line to allow a remote debugger to attach to the VM
in which Pax Exam runs
// new
VMOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
@@ -96,10 +100,10 @@
amdatuCassandraPersistenceManager(),
amdatuTenantService(),
amdatuUserAdminCassandraStore(),
- amdatuWink()
+ amdatuWink(),
// And finally deploy ourselves
-// bundle(integrationTestJarFile().toURI().toString())
+ bundle(integrationTestJarFile().toURI().toString())
));
}
@@ -166,15 +170,23 @@
};
/**
- * Helper method to get a given service by class. Will wait for
SERVICE_TIMEOUT seconds for the service,
+ * Helper method to get a given service by class and filter. Will wait for
SERVICE_TIMEOUT seconds for the service,
* and fail if it does not become available.
*/
@SuppressWarnings("unchecked")
- public <T> T getService(Class<T> serviceClass) {
+ public <T> T getService(Class<T> serviceClass, String filterString) throws
InvalidSyntaxException {
T serviceInstance = null;
// First open a service tracker and wait let the service tracker wait
for the availability of our service
- ServiceTracker serviceTracker = new ServiceTracker(m_bundleContext,
serviceClass.getName(), null);
+ ServiceTracker serviceTracker;
+ if (filterString == null) {
+ serviceTracker = new ServiceTracker(m_bundleContext,
serviceClass.getName(), null);
+ }
+ else {
+ String classFilter = "(" + Constants.OBJECTCLASS + "=" +
serviceClass.getName() + ")";
+ filterString = "(&" + classFilter + filterString + ")";
+ serviceTracker = new ServiceTracker(m_bundleContext,
m_bundleContext.createFilter(filterString), null);
+ }
serviceTracker.open();
try {
serviceInstance = (T)
serviceTracker.waitForService(SERVICE_TIMEOUT * 1000);
@@ -196,6 +208,21 @@
return serviceInstance;
}
+ /**
+ * Helper method to get a given service by class. Will wait for
SERVICE_TIMEOUT seconds for the service,
+ * and fail if it does not become available.
+ */
+ public <T> T getService(Class<T> serviceClass) {
+ try {
+ return getService(serviceClass, null);
+ }
+ catch (InvalidSyntaxException e) {
+ return null;
+ // This will not happen
+ }
+ }
+
+
protected File integrationTestJarFile() {
FileFilter ff = new FileFilter() {
public boolean accept(File pathname) {
@@ -207,7 +234,7 @@
}
////////////////////////////////////////////////////////////
- // A load of Pax Exam definitions for easier provisioning
+ // A load of Pax Exam definitions for easier (typo-free) provisioning
protected static MavenArtifactProvisionOption amdatuWink() {
return
mavenBundle().groupId("org.amdatu.platform").artifactId("wink-application").versionAsInProject();
Modified:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
==============================================================================
---
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
(original)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
Thu Oct 28 13:55:50 2010
@@ -16,20 +16,17 @@
*/
package org.amdatu.test.integration.tests;
-import static org.ops4j.pax.exam.CoreOptions.*;
-import static org.ops4j.pax.exam.CoreOptions.provision;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Properties;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
-import org.amdatu.platform.tenant.Tenant;
-import org.amdatu.platform.tenant.TenantDAO;
-import org.amdatu.platform.tenant.TenantException;
-import org.amdatu.platform.tenant.TenantManagementService;
+import org.amdatu.platform.tenant.*;
import org.amdatu.test.integration.base.IntegrationTestBase;
-import org.amdatu.test.integration.mock.TenantDAOMock;
+import org.amdatu.test.integration.mock.InMemoryTenantStorageProvider;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.junit.Test;
@@ -38,11 +35,15 @@
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
/**
- * This class provides an integration test for testing the Tenant Management
Service.
+ * This class provides an integration test for testing the Tenant Management
Service. We
+ * make sure the right services are registered when they should.
*
- * @author ivol
+ * TODO When the Cassandra-based storaged is factored out of the main bundle,
we should
+ * add a test for basic interaction with this storage.
*/
@RunWith(JUnit4TestRunner.class)
public class TenantManagementServiceTest extends IntegrationTestBase {
@@ -51,111 +52,92 @@
@Configuration
public Option[] configure() {
- return options(
- mavenConfiguration(),
-
- // Run test in a Felix container
- frameworks(felix()),
-
- // Setting this system property unfortunately is necessary with
the current Cassandra implementation
-
systemProperty("org.osgi.framework.system.packages.extra").value("sun.misc,com.sun.management"),
-
- // Enable this line to allow a remote debugger to attach to the VM
in which Pax Exam runs
- // new
VMOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
-
- // Install bundles we need to execute our test
- provision(
- compendium(),
- dependencyManager(),
- configAdmin(),
- felixLog(),
-
- // Amdatu platform bundles
- // TODO: this works fine when running 'mvn install' since the
artifacts will then be deployed to the maven
- // repository prior to running this integration test. With
'mvn integration-test' however, artifacts will
- // not be deployed and so this will only work when artifacts
have been deployed to the maven repository
- // before, possibly using outdated artifacts.
- amdatuConfigTemplateManager(),
- amdatuCassandraApplication(),
- amdatuCassandraListener(),
- amdatuCassandraPersistenceManager(),
- amdatuTenantService()
-
- // And finally deploy ourselves
- // bundle(integrationTestJarFile().toURI().toString())
- ));
+ return super.configure();
}
public Component[] getDependencies(DependencyManager manager) {
- // TODO update this, so we can get notified of a new tenant service
becoming available. Yay!
Component testComponent = manager.createComponent()
.setImplementation(this)
.add(manager.createServiceDependency()
- .setService(TenantManagementService.class));
+ .setService(TenantManagementService.class)
+ .setRequired(true))
+ .add(manager.createServiceDependency()
+ .setService(Tenant.class)
+ .setCallbacks("tenantAdded", "tenantRemoved"));
Properties props = new Properties();
props.put(Constants.SERVICE_RANKING, 1);
- Component daoComponent = manager.createComponent()
- .setInterface(TenantDAO.class.getName(), props)
- .setImplementation(TenantDAOMock.class);
+ Component storageComponent = manager.createComponent()
+ .setInterface(TenantStorageProvider.class.getName(), props)
+ .setImplementation(InMemoryTenantStorageProvider.class);
+
+ return new Component[] {testComponent, storageComponent};
+ }
+
+ private final Semaphore m_tenant1Added = new Semaphore(0);
+ private final Semaphore m_tenant1Removed = new Semaphore(0);
+
+ public void tenantAdded(ServiceReference reference) {
+ if (reference.getProperty(Tenant.SERVICE_PREFIX +
"id").equals("tenant1")) {
+ m_tenant1Added.release();
+ }
+ }
+
+ public void tenantRemoved(ServiceReference reference) {
+ if (reference.getProperty(Tenant.SERVICE_PREFIX +
"id").equals("tenant1")) {
+ m_tenant1Removed.release();
+ }
+ }
- return new Component[] {testComponent, daoComponent};
+ private boolean waitForTenantServiceAdded() throws InterruptedException {
+ return m_tenant1Added.tryAcquire(20, TimeUnit.SECONDS);
+ }
+
+ private boolean waitForTenantServiceRemoved() throws InterruptedException {
+ return m_tenant1Removed.tryAcquire(20, TimeUnit.SECONDS);
}
- // TODO pull this test apart into multiple tests
@Test
- public void testTenantManagementService() throws Exception {
+ public void shouldCreateTenantService() throws TenantException,
InterruptedException {
+ m_tenantManagementService.createTenant("tenant1", "Tenant1");
+ Assert.assertTrue("Tenant service did not become available",
waitForTenantServiceAdded());
+ }
- Tenant[] allTenants = m_tenantManagementService.getAllTenants();
- Assert.assertTrue("There are already tenants present in the storage",
- m_tenantManagementService.getAllTenants().length == 0);
+ @Test
+ public void shouldRemoveTenantService() throws TenantException,
InterruptedException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("tenant1", "Tenant1");
+ waitForTenantServiceAdded();
+ m_tenantManagementService.deleteTenant(tenant);
+ Assert.assertTrue("Tenant service did not disappear",
waitForTenantServiceRemoved());
+ }
- int tenantCount = allTenants.length;
- Tenant tenant =
m_tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant",
"TEST");
+ @Test
+ public void shouldPublishTenantProperties() throws TenantException,
InterruptedException, InvalidSyntaxException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldPublishTenantProperties",
"shouldPublishTenantProperties");
+ tenant.putProperty("host", "shouldPublishTenantProperties.org");
m_tenantManagementService.updateTenant(tenant);
- Assert.assertTrue("Added and updated 1 tenant, but the Tenant service
now holds "
- + m_tenantManagementService.getAllTenants().length + " tenants,
expected: " + (tenantCount + 1), m_tenantManagementService
- .getAllTenants().length == tenantCount + 1);
-
- // Try to add a tenant with the same id, should throw an exception
- try {
-
m_tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant",
"sdfsdfd");
- Assert.assertTrue("Tenant with the same id could be created
twice", false);
- }
- catch (TenantException e) {}
+ assertNotNull("The service did not become available",
+ getService(Tenant.class, "(" + Tenant.SERVICE_PREFIX +
"host=shouldPublishTenantProperties.org)"));
+ }
- m_tenantManagementService.deleteTenant(tenant);
+ @Test
+ public void shouldUpdateTenantProperties() throws TenantException,
InterruptedException, InvalidSyntaxException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldUpdateTenantProperties",
"shouldUpdateTenantProperties");
+ tenant.putProperty("host", "shouldUpdateTenantProperties.org");
+ m_tenantManagementService.updateTenant(tenant);
- Assert.assertTrue(m_tenantManagementService.getAllTenants().length ==
tenantCount);
+ assertNotNull("The service did not become available",
+ getService(Tenant.class, "(" + Tenant.SERVICE_PREFIX +
"host=shouldPublishTenantProperties.org)"));
- Tenant tenant1 =
m_tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant.1",
"TEST 1");
- Tenant tenant2 =
m_tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant.2",
"TEST 2");
- Tenant tenant3 =
m_tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant.3",
"TEST 3");
- tenant1.getProperties().put("hostname", "localhost");
- tenant2.getProperties().put("hostname", "localhost");
- tenant3.getProperties().put("hostname", "amdatu.org");
- m_tenantManagementService.updateTenant(tenant1);
- m_tenantManagementService.updateTenant(tenant2);
- m_tenantManagementService.updateTenant(tenant3);
-
- Map<String, String> filter = new HashMap<String, String>();
- filter.put("hostname", "localhost");
- Assert.assertTrue(m_tenantManagementService.getTenants(filter).length
== 2);
-
- filter.put("hostname", "amdatu.org");
- Assert.assertTrue(m_tenantManagementService.getTenants(filter).length
== 1);
-
- m_tenantManagementService.deleteTenant(tenant1);
- m_tenantManagementService.deleteTenant(tenant2);
- m_tenantManagementService.deleteTenant(tenant3);
-
- // What happens if I remove a tenant that was already removed?
- try {
- m_tenantManagementService.deleteTenant(tenant);
- Assert.assertTrue("Tenant with the same id could be deleted
twice", false);
- }
- catch (TenantException e) {}
+ tenant.putProperty("host", "shouldUpdateTenantProperties.com");
+ m_tenantManagementService.updateTenant(tenant);
+
+ assertNotNull("The service did not become available with the new
properties",
+ getService(Tenant.class, "(" + Tenant.SERVICE_PREFIX +
"host=shouldPublishTenantProperties.com)"));
+ assertNull("The service with the old property still lies around",
+ m_bundleContext.getServiceReference("(" +
Tenant.SERVICE_PREFIX + "host=shouldPublishTenantProperties.org)"));
}
+
}
Modified:
trunk/platform-bundles/profile-service/src/main/java/org/amdatu/platform/profile/PersonService.java
==============================================================================
---
trunk/platform-bundles/profile-service/src/main/java/org/amdatu/platform/profile/PersonService.java
(original)
+++
trunk/platform-bundles/profile-service/src/main/java/org/amdatu/platform/profile/PersonService.java
Thu Oct 28 13:55:50 2010
@@ -18,7 +18,6 @@
import java.util.List;
-import org.amdatu.platform.tenant.TenantAwareService;
import org.apache.shindig.social.opensocial.model.Person;
import org.osgi.service.useradmin.User;
Modified:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/Tenant.java
==============================================================================
---
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/Tenant.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/Tenant.java
Thu Oct 28 13:55:50 2010
@@ -21,60 +21,49 @@
/**
* This interface represents a tenant. A tenant has an id, name and a map of
properties that
- * identify the tenant. Tenants can be managed (i.e. persisted) using the
TenantService.
- * @author ivol
+ * identify the tenant. Tenants can be managed (i.e. persisted) using the
{@link TenantManagementService}.
+ *
+ * Tenant objects are intended to be stand-alone value objects.
+ *
+ * A tenant is solely identified by its ID, any changes to the name are
inconsequential.
+ *
+ * For each tenant, an OSGi service is registered. The <code>id</code>,
<code>name</code> and other properties
+ * will be registered with the service as service properties; the keys will be
prefixed with {@link #SERVICE_PREFIX}
+ * If the properties contain keys 'name' or 'id', the Tenant's name or id will
prevail.
*/
public interface Tenant {
/**
- * The property key with which Tenant aware services should register their
tenant.
- * So a tenant aware service should add a property named TENANT_AWARE_KEY
- * with a value that equals the tenant id in its service properties.
- * For example:
- * <pre>
- * {@code
- * private volatile org.apache.felix.dm.Component m_component;
- * private volatile org.amdatu.platform.tenant.Tenant m_tenant;
- *
- * public void init() {
- * Dictionary<String, String> serviceProperties = new
Hashtable<String, String>();
- *
serviceProperties.put(org.amdatu.platform.tenant.Tenant.TENANT_AWARE_KEY,
m_tenant.getId());
- * m_component.setServiceProperties(serviceProperties);
- * }
- * }
- * </pre>
+ * All properties from the
*/
- static final String TENANT_AWARE_KEY = "tenantid";
-
+ final String SERVICE_PREFIX = "tenant_";
+
/**
- * Returns the id of the tenant.
- * @return the id of the tenant.
+ * The unique ID for this tenant.
*/
String getId();
/**
- * Returns the name of the tenant.
- * @return the name of the tenant.
+ * The name for this tenant; not necessarily unique.
*/
String getName();
-
- /**
- * Sets the name of the tenant.
- * @param name Name of the tenant
- */
- void setName(String name);
-
+
/**
* Map of properties that identify this tenant. Properties may be a
hostname or a cookie.
- * @return List of properties that identify this tenant. If no properties
are available
- * then an empty map is returned.
+ * @return A map of properties that identify this tenant. If no properties
are available
+ * then an empty map is returned. Note that the map is <em>not</em> backed
by the Tenant
+ * object, and changes made to this map will not result in changes to the
Tenant.
*/
Map<String, String> getProperties();
+
+ /**
+ * Sets a property in the tenant; this will be reflected by subsequent
calls to {@link @getProperties}
+ */
+ void putProperty(String key, String value);
/**
- * Returns if this tenant matches all specified properties.
- * @param properties The properties to compare with
- * @return true if this tenant has all properties of the specified map and
if all values
- * are the same (case is not ignored).
+ * Returns whether this tenant matches <em>all</em> specified properties.
+ * @return <code>true</code> if this tenant has all properties of the
specified map and if all values
+ * are the same, <code>false</code> otherwise.
*/
boolean matches(Map<String, String> properties);
}
Copied:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantEntity.java
(from r213,
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java)
==============================================================================
---
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantEntity.java
Thu Oct 28 13:55:50 2010
@@ -17,29 +17,29 @@
*/
package org.amdatu.platform.tenant;
+import java.util.HashMap;
import java.util.Map;
+/**
+ * Data-object representing a Tenant.
+ */
+public class TenantEntity implements Tenant {
+ private final String m_id;
+ private final Map<String, String> m_properties;
-
-public class TenantImpl implements Tenant {
- // The id of the tenant
- private String m_id;
-
- // The name of the tenant
private String m_name;
- // The properties of the tenant
- private Map<String, String> m_properties;
-
- /**
- * Constructor.
- * @param id The id of the tenant
- * @param name The name of the tenant
- */
- public TenantImpl(String id, String name, Map<String, String> properties) {
+ public TenantEntity(String id, String name, Map<String, String>
properties) {
+ if (id == null) {
+ throw new NullPointerException("id cannot be null");
+ }
m_id = id;
m_name = name;
- m_properties = properties;
+ m_properties = new HashMap<String, String>(properties);
+ }
+
+ public TenantEntity(String id, String name) {
+ this(id, name, new HashMap<String, String>());
}
public String getId() {
@@ -55,7 +55,11 @@
}
public Map<String, String> getProperties() {
- return m_properties;
+ return new HashMap<String, String>(m_properties);
+ }
+
+ public void putProperty(String key, String value) {
+ m_properties.put(key, value);
}
public String toString() {
@@ -64,11 +68,7 @@
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((m_id == null) ? 0 : m_id.hashCode());
- result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
- return result;
+ return m_id.hashCode() * 31;
}
@Override
@@ -79,18 +79,8 @@
return false;
if (getClass() != obj.getClass())
return false;
- TenantImpl other = (TenantImpl) obj;
- if (m_id == null) {
- if (other.m_id != null)
- return false;
- } else if (!m_id.equals(other.m_id))
- return false;
- if (m_name == null) {
- if (other.m_name != null)
- return false;
- } else if (!m_name.equals(other.m_name))
- return false;
- return true;
+ TenantEntity other = (TenantEntity) obj;
+ return m_id == other.getId();
}
public boolean matches(Map<String, String> properties) {
Modified:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantException.java
==============================================================================
---
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantException.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantException.java
Thu Oct 28 13:55:50 2010
@@ -17,24 +17,16 @@
*/
package org.amdatu.platform.tenant;
+/**
+ * This exception signifies a logical error, e.g. trying to create a tenant
with an ID that is already in use.
+ */
public class TenantException extends Exception {
- /**
- * The serial version UID of this class.
- */
private static final long serialVersionUID = -4161504676185611010L;
- /**
- * Constructor for the exception.
- * @param e the exception
- */
public TenantException(Exception e) {
super(e);
}
- /**
- * Constructor for the exception.
- * @param msg The error message
- */
public TenantException(String msg) {
super(msg);
}
Modified:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantManagementService.java
==============================================================================
---
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantManagementService.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantManagementService.java
Thu Oct 28 13:55:50 2010
@@ -17,6 +17,7 @@
*/
package org.amdatu.platform.tenant;
+import java.util.List;
import java.util.Map;
/**
@@ -24,52 +25,30 @@
* are used to create tenant aware services. The tenant service will provide
tenants
* and the Felix dependency manager will automatically invoke a service
instance for
* each tenant aware service in which the tenant is injected.
- * @author ivol
*/
public interface TenantManagementService {
/**
- * Returns all available tenants. If no tenants are available an empty
array is returned.
- * @return all available tenants.
+ * Gets all tenants, or an empty list if there are none.
*/
- Tenant[] getAllTenants();
+ List<TenantEntity> getTenants() throws TenantException;
/**
- * Returns the tenant with the specified id.
- * @param id The id of the tenant to retrieve
- * @return the tenant with the specified id.
+ * Gets the tenant with the given ID, or <code>null</code> if this doesn't
exist.
*/
- Tenant getTenantById(String id);
+ TenantEntity getTenantById(String id) throws TenantException;
/**
- * Returns a tenant based on a map of properties that identify one or more
tenants.
- * Such an identifier may for example be a hostname that is associated
with the tenant.
- * @return Array of all tenants that match the specified properties. Of no
tenant matches
- * the properties an empty array is returned
+ * Gets all tenants that match the given properties, or an empty list if
there are none.
*/
- Tenant[] getTenants(Map<String, String> properties);
+ List<TenantEntity> getTenants(Map<String, String> properties) throws
TenantException;
/**
- * Create a new tenant with the specified id and name. Throws an
TenantException
- * if the tenant with that id already exists.
- * @param id The identifier of the tenant
- * @param name The name of the tenant
- * @return the created tenant
- * @throws TenantException in case a tenant with the specified id already
exists
- * or the tenant could not be persisted for any other reason.
+ * Creates a new tenant with the specified id and name.
+ * @throws TenantException in case a tenant with the specified id already
exists.
*/
- Tenant createTentant(String id, String name) throws TenantException;
+ TenantEntity createTenant(String id, String name) throws TenantException;
- /**
- * Updates an existing tenant.
- * @param tenant The tenant to update
- * @throws TenantException if the tenant could not be persisted for any
reason.
- */
- void updateTenant(Tenant tenant) throws TenantException;
-
- /**
- * Deletes an existing tenant
- * @param tenant The tenant to delete
- * @throws TenantException if the tenant could not be deleted for any
reason.
- */
- void deleteTenant(Tenant tenant) throws TenantException;
+ void updateTenant(TenantEntity tenant) throws TenantException;
+
+ void deleteTenant(TenantEntity tenant) throws TenantException;
}
Added:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantStorageProvider.java
==============================================================================
--- (empty file)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantStorageProvider.java
Thu Oct 28 13:55:50 2010
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.platform.tenant;
+
+import java.util.List;
+
+/**
+ * Interface for the Tenant Storage.
+ *
+ * The {@link TenantStorageProvider} can assume that synchronization will be
handled externally.
+ *
+ * All methods are allowed to throw a {@link TenantStorageException} when
storage or retrieval fails.
+ */
+public interface TenantStorageProvider {
+ /**
+ * Stores a tenant. If a tenant with this ID already exists, update it.
+ */
+ void store(TenantEntity tenant) throws TenantStorageException;
+
+ /**
+ * Deletes the specified tenant. The tenant is identified by its ID.
+ */
+ void delete(TenantEntity tenant) throws TenantStorageException;
+
+ /**
+ * Retrieves a tenant with the given ID, or <code>null</code> if none
exists
+ */
+ TenantEntity getById(String id) throws TenantStorageException;
+
+ /**
+ * Reads all existing Tenants and returns them.
+ */
+ List<TenantEntity> getAll() throws TenantStorageException;
+}
Copied:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantColumnFamilyProvider.java
(from r213,
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantColumnFamilyProvider.java)
==============================================================================
---
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantColumnFamilyProvider.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantColumnFamilyProvider.java
Thu Oct 28 13:55:50 2010
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.amdatu.platform.tenant.service;
+package org.amdatu.platform.tenant.dao;
import org.amdatu.platform.cassandra.listener.ColumnFamilyAvailable;
import org.amdatu.platform.cassandra.listener.ColumnFamilyDefinition;
Added:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantStorageProviderCassandraImpl.java
==============================================================================
--- (empty file)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantStorageProviderCassandraImpl.java
Thu Oct 28 13:55:50 2010
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.platform.tenant.dao;
+
+import static
org.amdatu.platform.tenant.dao.TenantColumnFamilyProvider.CF_TENANT;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.amdatu.platform.cassandra.persistencemanager.CassandraException;
+import
org.amdatu.platform.cassandra.persistencemanager.CassandraPersistenceManager;
+import org.amdatu.platform.tenant.TenantEntity;
+import org.amdatu.platform.tenant.TenantStorageException;
+import org.amdatu.platform.tenant.TenantStorageProvider;
+
+public class TenantStorageProviderCassandraImpl implements
TenantStorageProvider {
+ // Name of the supercolumns
+ private static final String SC_BASIC = "Basic";
+ private static final String SC_PROPERTIES = "Properties";
+
+ // Name of the columns
+ private static final String C_NAME = "name";
+
+ // Services injected by the Felix dependency manager
+ private volatile CassandraPersistenceManager m_pm;
+
+ public List<TenantEntity> getAll() throws TenantStorageException {
+ try {
+ List<TenantEntity> tenants = new ArrayList<TenantEntity>();
+ List<String> rowKeys = m_pm.getRowKeys(CF_TENANT);
+ if (rowKeys != null) {
+ for (String rowKey : rowKeys) {
+ TenantEntity tenant = getById(rowKey);
+ tenants.add(tenant);
+ }
+ }
+ return tenants;
+ }
+ catch (CassandraException e) {
+ throw new TenantStorageException(e);
+ }
+ }
+
+ public TenantEntity getById(String rowKey) throws TenantStorageException {
+ try {
+ if (!m_pm.exists(CF_TENANT, rowKey)) {
+ return null;
+ }
+ Map<String, Map<String, String>> values =
m_pm.getSuperStringValues(CF_TENANT, rowKey);
+ Map<String, String> basic = values.get(SC_BASIC);
+ Map<String, String> properties = values.get(SC_PROPERTIES);
+ String name = basic.get(C_NAME);
+ return new TenantEntity(rowKey, name, properties);
+ }
+ catch (CassandraException e) {
+ throw new TenantStorageException(e);
+ }
+ }
+
+ public void store(TenantEntity tenant) throws TenantStorageException {
+ try {
+ String id = tenant.getId();
+ m_pm.setStringValue(CF_TENANT, id, SC_BASIC, C_NAME,
tenant.getName());
+ for (String key : tenant.getProperties().keySet()) {
+ m_pm.setStringValue(CF_TENANT, id, SC_PROPERTIES, key,
tenant.getProperties().get(key));
+ }
+ }
+ catch (CassandraException e) {
+ throw new TenantStorageException(e);
+ }
+ }
+
+ public void delete(TenantEntity tenant) throws TenantStorageException {
+ try {
+ m_pm.deleteRow(CF_TENANT, tenant.getId());
+ }
+ catch (CassandraException e) {
+ throw new TenantStorageException(e);
+ }
+ }
+}
Modified:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
==============================================================================
---
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
Thu Oct 28 13:55:50 2010
@@ -21,10 +21,10 @@
import org.amdatu.platform.cassandra.listener.ColumnFamilyAvailable;
import org.amdatu.platform.cassandra.listener.ColumnFamilyProvider;
import
org.amdatu.platform.cassandra.persistencemanager.CassandraPersistenceManager;
-import org.amdatu.platform.tenant.TenantDAO;
import org.amdatu.platform.tenant.TenantManagementService;
-import org.amdatu.platform.tenant.dao.TenantDAOCassandraImpl;
-import org.amdatu.platform.tenant.service.TenantColumnFamilyProvider;
+import org.amdatu.platform.tenant.TenantStorageProvider;
+import org.amdatu.platform.tenant.dao.TenantColumnFamilyProvider;
+import org.amdatu.platform.tenant.dao.TenantStorageProviderCassandraImpl;
import org.amdatu.platform.tenant.service.TenantManagementServiceImpl;
import org.apache.felix.dm.DependencyActivatorBase;
import org.apache.felix.dm.DependencyManager;
@@ -52,20 +52,21 @@
"(" + CassandraPersistenceManager.KEYSPACE_AWARE_KEY + "="
+ CassandraPersistenceManager.DEFAULT_KEYSPACE + ")";
- // Create and register the Cassandra Tenant DAO
+ // Create and register the Cassandra Tenant Storage
manager.add(
createComponent()
- .setImplementation(TenantDAOCassandraImpl.class)
- .setInterface(TenantDAO.class.getName(), null)
+ .setImplementation(TenantStorageProviderCassandraImpl.class)
+ .setInterface(TenantStorageProvider.class.getName(), null)
.add(createServiceDependency().setService(CassandraPersistenceManager.class,
keyspaceFilter).setRequired(true))
.add(createServiceDependency().setService(ColumnFamilyAvailable.class,
tenantFilter).setRequired(true)));
+
// Create and register the Tenant management service
manager.add(
createComponent()
.setImplementation(TenantManagementServiceImpl.class)
.setInterface(TenantManagementService.class.getName(), null)
-
.add(createServiceDependency().setService(TenantDAO.class).setRequired(true))
+
.add(createServiceDependency().setService(TenantStorageProvider.class).setRequired(true))
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
}
Modified:
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
==============================================================================
---
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
(original)
+++
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
Thu Oct 28 13:55:50 2010
@@ -16,97 +16,112 @@
*/
package org.amdatu.platform.tenant.service;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.amdatu.platform.tenant.Tenant;
-import org.amdatu.platform.tenant.TenantDAO;
-import org.amdatu.platform.tenant.TenantException;
-import org.amdatu.platform.tenant.TenantManagementService;
+import java.util.*;
+
+import org.amdatu.platform.tenant.*;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
-import org.osgi.service.log.LogService;
-/**
- * Implementation of the Tenant management service.
- * @author ivol
- */
public class TenantManagementServiceImpl implements TenantManagementService {
- // Injected by the Felix dependency manager
private volatile DependencyManager m_manager;
- private volatile TenantDAO m_tenantDAO;
- private volatile LogService m_logService;
+ private volatile TenantStorageProvider m_tenantStorageProvider;
- // Instance variables
- private List<Tenant> m_tenants = new ArrayList<Tenant>();
private Map<Tenant, Component> m_tenantComponents = new HashMap<Tenant,
Component>();
+ // We currently use all-exclusive access.
+ private Object m_lock = new Object();
+
/**
* Invoked by the Felix dependency manager.
*/
- public void start() {
- try {
- // Upon starting this bundle, we load the available tenants into
memory
- m_tenants = m_tenantDAO.readAll();
-
- // Register all tenants as service
- for (Tenant tenant : getAllTenants()) {
-
m_manager.add(m_manager.createComponent().setImplementation(tenant).setInterface(
- Tenant.class.getName(), null));
+ public void start() throws TenantException {
+ // TODO if we cannot get our tenants now, should we retry later?
+ synchronized (m_lock) {
+ for (TenantEntity tenant : getTenants()) {
+ createTenantService(tenant);
}
}
- catch (TenantException e) {
- m_logService.log(LogService.LOG_ERROR, "Could not load tenants",
e);
+ }
+
+ public List<TenantEntity> getTenants() throws TenantException {
+ synchronized (m_lock) {
+ return m_tenantStorageProvider.getAll();
}
}
- public Tenant[] getAllTenants() {
- return m_tenants.toArray(new Tenant[m_tenants.size()]);
+ public TenantEntity getTenantById(String id) throws TenantException {
+ synchronized (m_lock) {
+ return m_tenantStorageProvider.getById(id);
+ }
}
- public Tenant getTenantById(String id) {
- for (Tenant tenant : m_tenants) {
- if (tenant.getId().equals(id)) {
- return tenant;
+ public List<TenantEntity> getTenants(Map<String, String> properties)
throws TenantException {
+ synchronized (m_lock) {
+ List<TenantEntity> matchingTenants = new ArrayList<TenantEntity>();
+ for (TenantEntity tenant : getTenants()) {
+ if (tenant.matches(properties)) {
+ matchingTenants.add(tenant);
+ }
}
+ return matchingTenants;
}
- return null;
}
- public Tenant[] getTenants(Map<String, String> properties) {
- List<Tenant> matchingTenants = new ArrayList<Tenant>();
- for (Tenant tenant : m_tenants) {
- if (tenant.matches(properties)) {
- matchingTenants.add(tenant);
+ public TenantEntity createTenant(String id, String name) throws
TenantException {
+ synchronized (m_lock) {
+ if (getTenantById(id) != null) {
+ throw new TenantException("Tenant with id '" + id + "' already
exists");
}
+ TenantEntity tenant = new TenantEntity(id, name);
+ m_tenantStorageProvider.store(tenant);
+ createTenantService(tenant);
+ return tenant;
}
- return matchingTenants.toArray(new Tenant[matchingTenants.size()]);
}
- public Tenant createTentant(String id, String name) throws TenantException
{
- synchronized (this) {
- Tenant tenant = m_tenantDAO.create(id, name);
- Component tenantComponent =
-
m_manager.createComponent().setImplementation(tenant).setInterface(Tenant.class.getName(),
null);
- m_tenantComponents.put(tenant, tenantComponent);
- m_manager.add(tenantComponent);
- m_tenants.add(tenant);
- return tenant;
+ public void updateTenant(TenantEntity tenant) throws TenantException {
+ synchronized (m_lock) {
+ m_tenantStorageProvider.store(tenant);
+ updateTenantService(tenant);
}
}
- public void updateTenant(Tenant tenant) throws TenantException {
- m_tenantDAO.update(tenant);
+ public void deleteTenant(TenantEntity tenant) throws TenantException {
+ synchronized (m_lock) {
+ if (getTenantById(tenant.getId()) == null) {
+ throw new TenantException("Tenant with id '" + tenant.getId()
+ "' does not exist, thus cannot be deleted.");
+ }
+ m_tenantStorageProvider.delete(tenant);
+ removeTenantService(tenant);
+ }
+ }
+
+ private void createTenantService(TenantEntity tenant) {
+ Component component = m_manager.createComponent()
+ .setImplementation(tenant)
+ .setInterface(Tenant.class.getName(),
createServiceProperties(tenant));
+ m_manager.add(component);
+ m_tenantComponents.put(tenant, component);
+ }
+
+ private void updateTenantService(TenantEntity tenant) {
+ Component component = m_tenantComponents.get(tenant);
+ component.setServiceProperties(createServiceProperties(tenant));
+ }
+
+ private void removeTenantService(TenantEntity tenant) {
+ m_manager.remove(m_tenantComponents.remove(tenant));
}
- public void deleteTenant(Tenant tenant) throws TenantException {
- synchronized (this) {
- m_tenantDAO.delete(tenant);
- m_tenants.remove(tenant);
- m_manager.remove(m_tenantComponents.get(tenant));
- m_tenantComponents.remove(tenant);
+ private Properties createServiceProperties(TenantEntity tenant) {
+ Properties properties = new Properties();
+ Map<String, String> tenantProperties = tenant.getProperties();
+ for (Map.Entry<String, String> entry : tenantProperties.entrySet()) {
+ properties.put(Tenant.SERVICE_PREFIX + entry.getKey(),
entry.getValue());
}
+ properties.put(Tenant.SERVICE_PREFIX + "id", tenant.getId());
+ properties.put(Tenant.SERVICE_PREFIX + "name", tenant.getName());
+
+ return properties;
}
}
Added:
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantStorageProvider.java
==============================================================================
--- (empty file)
+++
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantStorageProvider.java
Thu Oct 28 13:55:50 2010
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.unit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.amdatu.platform.tenant.TenantEntity;
+import org.amdatu.platform.tenant.TenantStorageProvider;
+
+/**
+ * This service provides an in-memory implementation of the
TenantStorageProvider, used for unit testing.
+ */
+public class InMemoryTenantStorageProvider implements TenantStorageProvider {
+ private final Map<String, TenantEntity> m_tenants = new HashMap<String,
TenantEntity>();
+
+ public List<TenantEntity> getAll() {
+ return new ArrayList<TenantEntity>(m_tenants.values());
+ }
+
+ public TenantEntity getById(String id) {
+ return copy(m_tenants.get(id));
+ }
+
+ public void store(TenantEntity tenant) {
+ m_tenants.put(tenant.getId(), copy(tenant));
+ }
+
+ public void delete(TenantEntity tenant) {
+ m_tenants.remove(tenant.getId());
+ }
+
+ private TenantEntity copy(TenantEntity tenant) {
+ if (tenant == null) {
+ return null;
+ }
+ return new TenantEntity(tenant.getId(), tenant.getName(), new
HashMap<String, String>(tenant.getProperties()));
+ }
+}
Modified:
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
==============================================================================
---
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
(original)
+++
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
Thu Oct 28 13:55:50 2010
@@ -16,18 +16,21 @@
*/
package org.amdatu.test.unit;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
import java.util.HashMap;
import java.util.Map;
-import junit.framework.Assert;
-
import org.amdatu.libraries.utilities.TestUtil;
-import org.amdatu.platform.tenant.Tenant;
-import org.amdatu.platform.tenant.TenantDAO;
+import org.amdatu.platform.tenant.TenantEntity;
import org.amdatu.platform.tenant.TenantException;
import org.amdatu.platform.tenant.TenantManagementService;
+import org.amdatu.platform.tenant.TenantStorageProvider;
import org.amdatu.platform.tenant.service.TenantManagementServiceImpl;
+import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
+import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.service.log.LogService;
@@ -37,80 +40,100 @@
* @author ivol
*/
public class TenantManagementServiceTest {
- /**
- * Run the unit test.
- */
- @Test
- public void TenantManagementServiceUnitTest() {
- // Instantiate the Tenant management service to test
- TenantDAO tenantDAO = new InMemoryTenantDAO();
- TenantManagementService tenantService = new
TenantManagementServiceImpl();
- TestUtil.configureObject(tenantService, LogService.class,
TestUtil.createNullObject(LogService.class));
- TestUtil.configureObject(tenantService, TenantDAO.class, tenantDAO);
- TestUtil.configureObject(tenantService, DependencyManager.class, new
DependencyManager(TestUtil.createNullObject(BundleContext.class)));
-
+ private TenantManagementService m_tenantManagementService;
+
+ @Before
+ public void setUp() {
+ TenantStorageProvider tenantStorageProvider = new
InMemoryTenantStorageProvider();
+ m_tenantManagementService = new TenantManagementServiceImpl();
+ TestUtil.configureObject(m_tenantManagementService, LogService.class,
TestUtil.createNullObject(LogService.class));
+ TestUtil.configureObject(m_tenantManagementService,
TenantStorageProvider.class, tenantStorageProvider);
+ TestUtil.configureObject(m_tenantManagementService,
DependencyManager.class,
+ new
DependencyManager(TestUtil.createNullObject(BundleContext.class)) {
+ public void add(Component c) {
+ }
+ });
+ }
+
+ @Test
+ public void shouldCreateTenant() throws TenantException {
+ int tenantsBefore = m_tenantManagementService.getTenants().size();
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldCreateTenant",
"shouldCreateTenant");
+
assertEquals(m_tenantManagementService.getTenantById("shouldCreateTenant"),
tenant);
+ assertEquals(m_tenantManagementService.getTenants().size(),
tenantsBefore + 1);
+ }
+
+ @Test
+ public void shouldNotCreateTenantTwice() throws TenantException {
+ int tenantsBefore = m_tenantManagementService.getTenants().size();
+ m_tenantManagementService.createTenant("shouldNotCreateTenantTwice",
"shouldNotCreateTenantTwice");
+
+ try {
+
m_tenantManagementService.createTenant("shouldNotCreateTenantTwice",
"withsomeothername");
+ fail("We could create a tenant with the same id twice");
+ }
+ catch (TenantException e) {
+ // expected
+ }
+
+ assertEquals(m_tenantManagementService.getTenants().size(),
tenantsBefore + 1);
+ }
+
+ @Test
+ public void shouldRemoveTenant() throws TenantException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldRemoveTenant",
"shouldRemoveTenant");
+ int tenantsBefore = m_tenantManagementService.getTenants().size();
+ m_tenantManagementService.deleteTenant(tenant);
+ assertEquals(m_tenantManagementService.getTenants().size(),
tenantsBefore - 1);
+ }
+
+ @Test
+ public void shouldUpdateTenant() throws TenantException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldUpdateTenant",
"shouldUpdateTenant");
+ tenant.setName("updatedName");
+
+ assertEquals("It should not store the tenant before we called 'store'",
+ "shouldUpdateTenant",
m_tenantManagementService.getTenantById("shouldUpdateTenant").getName());
+
+ m_tenantManagementService.updateTenant(tenant);
+
+ assertEquals("updatedName",
m_tenantManagementService.getTenantById("shouldUpdateTenant").getName());
+ }
+
+ @Test
+ public void shouldNotRemoveTenantTwice() throws TenantException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldNotRemoveTenantTwice",
"shouldNotRemoveTenantTwice");
+ int tenantsBefore = m_tenantManagementService.getTenants().size();
+ m_tenantManagementService.deleteTenant(tenant);
+ assertEquals(m_tenantManagementService.getTenants().size(),
tenantsBefore - 1);
try {
- // Verify that there are no tenants available right now
- Tenant[] allTenants = tenantService.getAllTenants();
- Assert
- .assertTrue("There are already tenants present in the storage",
- tenantService.getAllTenants().length == 0);
-
- // Create and update a tenant and verify that it has been added
- int tenantCount = allTenants.length;
- Tenant tenant =
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant",
"TEST");
- tenantService.updateTenant(tenant);
- Assert.assertTrue("Added and updated 1 tenant, but the Tenant
service now holds "
- + tenantService.getAllTenants().length + " tenants, expected:
" + (tenantCount + 1), tenantService
- .getAllTenants().length == tenantCount + 1);
-
- // Try to add a tenant with the same id, this should throw an
exception
- try {
-
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant",
"sdfsdfd");
- Assert.assertTrue("Tenant with the same id could be created
twice", false);
- }
- catch (TenantException e) {
- }
-
- // Delete the tenant and check if it has been removed
- tenantService.deleteTenant(tenant);
- Assert.assertTrue(tenantService.getAllTenants().length ==
tenantCount);
-
- // Create and update three tenants
- Tenant tenant1 =
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant.1",
"TEST 1");
- Tenant tenant2 =
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant.2",
"TEST 2");
- Tenant tenant3 =
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant.3",
"TEST 3");
- tenant1.getProperties().put("hostname", "localhost");
- tenant2.getProperties().put("hostname", "localhost");
- tenant3.getProperties().put("hostname", "amdatu.org");
- tenantService.updateTenant(tenant1);
- tenantService.updateTenant(tenant2);
- tenantService.updateTenant(tenant3);
-
- // Check if the filter works correct
- Map<String, String> filter = new HashMap<String, String>();
- filter.put("hostname", "localhost");
- Assert.assertTrue(tenantService.getTenants(filter).length == 2);
- filter.put("hostname", "amdatu.org");
- Assert.assertTrue(tenantService.getTenants(filter).length == 1);
-
- // Delete the tenants, now all tenants should be removed
- tenantService.deleteTenant(tenant1);
- tenantService.deleteTenant(tenant2);
- tenantService.deleteTenant(tenant3);
- Assert.assertTrue(tenantService.getAllTenants().length == 0);
-
- // What happens if I remove a tenant that was already removed?
This should throw an exception
- try {
- tenantService.deleteTenant(tenant);
- Assert.fail("Tenant with the same id could be deleted twice");
- }
- catch (TenantException e) {
- }
+ m_tenantManagementService.deleteTenant(tenant);
+ fail("we could remove a tenant twice");
}
catch (TenantException e) {
- Assert.fail("An error has occurred: " + e.toString());
- e.printStackTrace();
+ //expected
+ }
+ }
+
+ @Test
+ public void shouldFilterTenants() throws TenantException {
+ TenantEntity tenant =
m_tenantManagementService.createTenant("shouldFilterTenants",
"shouldFilterTenants");
+ assertEquals(0, m_tenantManagementService.getTenants(map("host",
"amdatu.org")).size());
+ tenant.putProperty("host", "amdatu.org");
+
+ assertEquals("It should not store the tenant before we called 'store'",
+ 0, m_tenantManagementService.getTenants(map("host",
"amdatu.org")).size());
+
+ m_tenantManagementService.updateTenant(tenant);
+ assertEquals(1, m_tenantManagementService.getTenants(map("host",
"amdatu.org")).size());
+ }
+
+ private static <T> Map<T, T> map(T... elements) {
+ Map<T, T> result = new HashMap<T, T>();
+ for (int i = 0; i < elements.length; i += 2) {
+ result.put(elements[i], elements[i+1]);
}
- }
+ return result;
+ }
+
}