Author: [email protected]
Date: Mon Nov 7 17:20:25 2011
New Revision: 1714
Log:
Added:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantConfigUpdateListenerImpl.java
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantMutationColumnFamilyProviderImpl.java
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantMutationDAO.java
sandbox/ivol/tenant-management-gadget/src/main/resources/static/images/remove_disabled.gif
(contents, props changed)
Modified:
sandbox/ivol/tenant-management-gadget/pom.xml
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/osgi/Activator.java
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantBean.java
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantRESTServiceImpl.java
sandbox/ivol/tenant-management-gadget/src/main/resources/jsp/TenantGadget.jsp
sandbox/ivol/tenant-management-gadget/src/main/resources/static/css/tenant.css
sandbox/ivol/tenant-management-gadget/src/main/resources/static/js/tenant.js
Modified: sandbox/ivol/tenant-management-gadget/pom.xml
==============================================================================
--- sandbox/ivol/tenant-management-gadget/pom.xml (original)
+++ sandbox/ivol/tenant-management-gadget/pom.xml Mon Nov 7 17:20:25 2011
@@ -29,6 +29,7 @@
<properties>
<amdatu.opensocial.version>0.2.0</amdatu.opensocial.version>
+ <amdatu.cassandra.version>0.2.1-RC2</amdatu.cassandra.version>
</properties>
<dependencies>
@@ -92,6 +93,34 @@
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.amdatu.cassandra</groupId>
+ <artifactId>org.amdatu.cassandra.listener</artifactId>
+ <version>${amdatu.cassandra.version}</version>
+ <scope>provided</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.cassandra</groupId>
+ <artifactId>org.amdatu.cassandra.application</artifactId>
+ <version>${amdatu.cassandra.version}</version>
+ <scope>provided</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.cassandra</groupId>
+ <artifactId>org.amdatu.cassandra.persistencemanager</artifactId>
+ <version>${amdatu.cassandra.version}</version>
+ <scope>provided</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.cassandra</groupId>
+ <artifactId>org.amdatu.cassandra.persistencemanager.hector</artifactId>
+ <version>${amdatu.cassandra.version}</version>
+ <scope>provided</scope>
+ <type>bundle</type>
+ </dependency>
</dependencies>
<repositories>
Modified:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/osgi/Activator.java
==============================================================================
---
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/osgi/Activator.java
(original)
+++
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/osgi/Activator.java
Mon Nov 7 17:20:25 2011
@@ -13,17 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.amdatu.opensocial.tenant.gadget.osgi;
-
+package org.amdatu.opensocial.tenant.gadget.osgi;
+
import java.util.Dictionary;
import java.util.Hashtable;
+import org.amdatu.cassandra.listener.ColumnFamilyProvider;
+import
org.amdatu.cassandra.persistencemanager.hector.HectorCassandraPersistenceManager;
import org.amdatu.core.tenant.Tenant;
import org.amdatu.libraries.utilities.osgi.ServiceDependentActivator;
import org.amdatu.opensocial.gadgetmanagement.GadgetDefinitionProvider;
import org.amdatu.opensocial.tenant.gadget.service.TenantGadgetDefinition;
import org.amdatu.opensocial.tenant.gadget.service.TenantGadgetImpl;
import org.amdatu.opensocial.tenant.gadget.service.TenantRESTServiceImpl;
+import
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl;
import org.amdatu.web.dispatcher.DispatcherService;
import org.amdatu.web.httpcontext.ResourceProvider;
import org.amdatu.web.jsp.JspSupport;
@@ -35,65 +38,72 @@
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.log.LogService;
import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * This is the OSGi activator for this gadget bundle.
- *
- * @author ivol
- */
-public class Activator extends ServiceDependentActivator {
- /**
- * Context id of the Authorization HTTP Context.
- */
- public static final String CONTEXTID = "amdatu-opensocial-tenant";
-
- /**
- * URL alias hosting the login gadget.
- */
- public static final String ALIAS = "/tenant";
-
- /**
- * URL alias hosting the JSPs.
- */
- public static final String JSP_ALIAS = ALIAS + "/jsp";
-
- /**
- * URL alias hosting the statics.
- */
+
+/**
+ * This is the OSGi activator for this gadget bundle.
+ *
+ * @author ivol
+ */
+public class Activator extends ServiceDependentActivator {
+ /**
+ * Context id of the Authorization HTTP Context.
+ */
+ public static final String CONTEXTID = "amdatu-opensocial-tenant";
+
+ /**
+ * URL alias hosting the login gadget.
+ */
+ public static final String ALIAS = "/tenant";
+
+ /**
+ * URL alias hosting the JSPs.
+ */
+ public static final String JSP_ALIAS = ALIAS + "/jsp";
+
+ /**
+ * URL alias hosting the statics.
+ */
public static final String RES_ALIAS = ALIAS + "/static";
-
+
protected Class<?>[] getRequiredServices() {
- return new Class<?>[] {JaxRsSpi.class};
- }
-
- @Override
- public void initWithDependencies(final BundleContext context, final
DependencyManager manager) throws Exception {
-
- Dictionary<String, Object> properties = new Hashtable<String,
Object>();
- properties.put(DispatcherService.CONTEXT_ID_KEY, CONTEXTID);
- properties.put(JspSupport.JSP_ALIAS_KEY, JSP_ALIAS);
- properties.put(ResourceSupport.RESOURCE_ALIAS_KEY, RES_ALIAS);
-
-
manager.add(createComponent().setInterface(ResourceProvider.class.getName(),
properties)
- .setImplementation(TenantGadgetImpl.class)
-
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+ return new Class<?>[] { JaxRsSpi.class };
+ }
+
+ @Override
+ public void initWithDependencies(final BundleContext context, final
DependencyManager manager) throws Exception {
+
+ Dictionary<String, Object> properties = new Hashtable<String,
Object>();
+ properties.put(DispatcherService.CONTEXT_ID_KEY, CONTEXTID);
+ properties.put(JspSupport.JSP_ALIAS_KEY, JSP_ALIAS);
+ properties.put(ResourceSupport.RESOURCE_ALIAS_KEY, RES_ALIAS);
+
+
manager.add(createComponent().setInterface(ResourceProvider.class.getName(),
properties)
+ .setImplementation(TenantGadgetImpl.class)
+
.add(createServiceDependency().setService(LogService.class).setRequired(true))
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true)));
// Register a login gadget definition for each tenant
manager.add(createAdapterService(Tenant.class, null)
.setInterface(GadgetDefinitionProvider.class.getName(), null)
.setImplementation(TenantGadgetDefinition.class));
-
+
// Create and register the REST tenant service
manager.add(
- createAdapterService(Tenant.class, null)
- .setInterface(new String[] {RESTService.class.getName()},
null)
- .setImplementation(TenantRESTServiceImpl.class)
-
.add(createServiceDependency().setService(LogService.class).setRequired(true))
-
.add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true)));
- }
-
- @Override
- public void destroy(final BundleContext arg0, final DependencyManager
arg1) throws Exception {
- }
-}
+ createAdapterService(Tenant.class, null)
+ .setInterface(new String[] { RESTService.class.getName() },
null)
+ .setImplementation(TenantRESTServiceImpl.class)
+
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+
.add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+
.add(createServiceDependency().setService(HectorCassandraPersistenceManager.class).setRequired(true)));
+
+ // Define a service that provides the ColumnFamily we need
+ manager.add(
+ createComponent()
+ .setInterface(new String[] {
ColumnFamilyProvider.class.getName() }, null)
+
.setImplementation(TenantMutationColumnFamilyProviderImpl.class));
+ }
+
+ @Override
+ public void destroy(final BundleContext arg0, final DependencyManager
arg1) throws Exception {
+ }
+}
Modified:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantBean.java
==============================================================================
---
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantBean.java
(original)
+++
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantBean.java
Mon Nov 7 17:20:25 2011
@@ -5,18 +5,17 @@
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.amdatu.libraries.utilities.rest.AtomSyndicationLink;
@XmlRootElement(name = "tenant")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
-public class TenantBean {
+public class TenantBean implements Comparable<TenantBean>{
private String m_id;
private String m_name;
private String m_hostname;
- private AtomSyndicationLink m_link;
+ private List<AtomSyndicationLink> m_links;
public TenantBean() {
}
@@ -51,11 +50,22 @@
m_hostname = hostname;
}
- public AtomSyndicationLink getLink() {
- return m_link;
+ public List<AtomSyndicationLink> getLinks() {
+ return m_links;
}
- public void setLink(final AtomSyndicationLink link) {
- m_link = link;
+ public void setLinks(final List<AtomSyndicationLink> links) {
+ m_links = links;
+ }
+
+ public void addLink(AtomSyndicationLink link) {
+ if (m_links == null) {
+ m_links = new ArrayList<AtomSyndicationLink>();
+ }
+ m_links.add(link);
+ }
+
+ public int compareTo(TenantBean otherBean) {
+ return
getName().toLowerCase().compareTo(otherBean.getName().toLowerCase());
}
}
Added:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantConfigUpdateListenerImpl.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantConfigUpdateListenerImpl.java
Mon Nov 7 17:20:25 2011
@@ -0,0 +1,137 @@
+/*
+ * 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.opensocial.tenant.gadget.service;
+
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.CF;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.amdatu.core.tenant.TenantManagementService;
+import
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.MutationType;
+import org.amdatu.opensocial.tenant.gadget.service.TenantMutationDAO.Mutation;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+public class TenantConfigUpdateListenerImpl {
+ // The thread that inspects the Cassandra database for changes
+ private InspectTenantMutationsThread m_inspectThread;
+
+ // The interval for each individual inspect
+ private static int INSPECT_INTERVAL = 5000;
+
+ private volatile ConfigurationAdmin m_configAdmin;
+ private volatile LogService m_logService;
+ private volatile TenantMutationDAO m_tenantMutationDAO;
+
+ public void start() {
+ // Now start the inspect thread
+ m_inspectThread = new InspectTenantMutationsThread();
+ m_inspectThread.start();
+ }
+
+ public void stop() {
+ // Stop the inspect thread
+ m_inspectThread.interrupt();
+ }
+
+ /**
+ * This Thread inspects available Keyspaces and ColumnFamilies in
Cassandra and compares these to
+ * the registered CassandraPersistenceManager and ColumnFamilyAvailable
services. Since other nodes
+ * in the cluster may add, update or drop keyspaces and column families
and Cassandra does not support
+ * any event mechanism to act upon these events we will continuously
inspect this ourselves.
+ *
+ * @author ivol
+ *
+ */
+ class InspectTenantMutationsThread extends Thread {
+ public void run() {
+ try {
+ while (!isInterrupted()) {
+ // Inspect the tenant mutation ColumnFamily for new
mutations
+ try {
+ List<String> rowKeys = m_pm.getRowKeys(CF);
+ if (rowKeys != null && rowKeys.size() > 0) {
+ applyMutations(rowKeys);
+ }
+ }
+ catch (Exception e) {
+ m_logService.log(LogService.LOG_ERROR, "An error
occurred while applying tenant mutation. Cause: " + e.getMessage(), e);
+ }
+
+ Thread.sleep(INSPECT_INTERVAL);
+ }
+ }
+ catch (InterruptedException e) {
+ m_logService.log(LogService.LOG_INFO, "Tenant config update
listener thread interrupted.");
+ }
+ }
+
+ public void applyMutations(List<String> rowKeys) throws IOException {
+ for (String rowKey : rowKeys) {
+ Mutation mutation = m_tenantMutationDAO.getMutation(rowKey);
+ if (mutation.type == MutationType.UPDATE) {
+ Configuration config =
m_configAdmin.getConfiguration(TenantManagementService.PID);
+ Dictionary properties = config.getProperties();
+ String tenantKey = findTenantKey(mutation.id);
+ if (tenantKey == null) {
+ int newid = findLastTenantKey() + 1;
+ tenantKey = "tenant" + newid;
+ properties.put(tenantKey + ".id", mutation.id);
+ }
+ properties.put(tenantKey + ".name", mutation.name);
+ properties.put(tenantKey + ".properties.hostname",
mutation.hostname);
+ config.update(properties);
+ }
+ }
+ }
+
+ private String findTenantKey(String tenantId) throws IOException {
+ Configuration config =
m_configAdmin.getConfiguration(TenantManagementService.PID);
+ Dictionary properties = config.getProperties();
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement().toString();
+ if (key.endsWith(".id")) {
+ if (tenantId.equals(properties.get(key))) {
+ return key.substring(0, key.indexOf(".id"));
+ }
+ }
+ }
+ return null;
+ }
+
+ private int findLastTenantKey() throws IOException {
+ int maxid = 1;
+ Configuration config =
m_configAdmin.getConfiguration(TenantManagementService.PID);
+ Dictionary properties = config.getProperties();
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement().toString();
+ if (key.endsWith(".id")) {
+ String id = key.substring("tenant".length(),
key.indexOf("."));
+ if (Integer.parseInt(id) > maxid) {
+ maxid = Integer.parseInt(id);
+ }
+ }
+ }
+ return maxid;
+ }
+ }
+}
Added:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantMutationColumnFamilyProviderImpl.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantMutationColumnFamilyProviderImpl.java
Mon Nov 7 17:20:25 2011
@@ -0,0 +1,57 @@
+/*
+ * 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.opensocial.tenant.gadget.service;
+
+import org.amdatu.cassandra.listener.ColumnFamilyDefinition;
+import org.amdatu.cassandra.listener.ColumnFamilyProvider;
+import org.amdatu.cassandra.listener.ColumnFamilyDefinition.ColumnType;
+import org.amdatu.cassandra.listener.ColumnFamilyDefinition.CompareType;
+
+public class TenantMutationColumnFamilyProviderImpl implements
ColumnFamilyProvider {
+ final static String KEYSPACE = "Default"; // Hardcoded
+ final static String CF = "TenantMutations"; // Hardcoded
+
+ final static String C_ID = "id";
+ final static String C_NAME = "name";
+ final static String C_HOST = "host";
+ final static String C_TYPE = "type";
+
+ static enum MutationType {
+ UPDATE("update"),
+ DELETE("delete");
+
+ private String m_value;
+
+ MutationType(final String mutationType) {
+ m_value = mutationType;
+ }
+
+ public String getValue() {
+ return m_value;
+ }
+ };
+
+ public ColumnFamilyDefinition[] getColumnFamilies() {
+ return new ColumnFamilyDefinition[] {
+ new ColumnFamilyDefinition(
+ CF,
+ new String[] { KEYSPACE },
+ ColumnType.STANDARD,
+ CompareType.BYTESTYPE,
+ null) };
+ }
+
+}
Added:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantMutationDAO.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantMutationDAO.java
Mon Nov 7 17:20:25 2011
@@ -0,0 +1,63 @@
+package org.amdatu.opensocial.tenant.gadget.service;
+
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.CF;
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.C_HOST;
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.C_ID;
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.C_NAME;
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.C_TYPE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import
org.amdatu.cassandra.persistencemanager.hector.HectorCassandraPersistenceManager;
+import
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.MutationType;
+
+public class TenantMutationDAO {
+ private volatile HectorCassandraPersistenceManager m_pm;
+ private static int m_index = 0;
+
+ public void addUpdateMutation(String id, String name, String hostname) {
+ String rowKey = generateRowKey();
+ m_pm.setValue(CF, rowKey, null, C_ID, id);
+ m_pm.setValue(CF, rowKey, null, C_NAME, name);
+ m_pm.setValue(CF, rowKey, null, C_HOST, hostname);
+ m_pm.setValue(CF, rowKey, null, C_TYPE, MutationType.UPDATE);
+ }
+
+ public void addDeleteMutation(String id) {
+ String rowKey = generateRowKey();
+ m_pm.setValue(CF, rowKey, null, C_ID, id);
+ m_pm.setValue(CF, rowKey, null, C_TYPE, MutationType.DELETE);
+ }
+
+ public List<Mutation> getMutations() {
+ List<String> rowKeys = m_pm.getRowKeys(CF);
+ if (rowKeys != null && rowKeys.size() > 0) {
+ for (String rowKey : rowKeys) {
+ List<Mutation> mutations = new ArrayList<Mutation>();
+ mutations.add(getMutation(rowKey));
+ }
+ }
+ }
+
+ public Mutation getMutation(String rowKey) {
+ Mutation mutation = new Mutation();
+ mutation.id = m_pm.getValue(CF, rowKey, null, C_ID, String.class);
+ mutation.name = m_pm.getValue(CF, rowKey, null, C_NAME, String.class);
+ mutation.hostname = m_pm.getValue(CF, rowKey, null, C_HOST,
String.class);
+ mutation.type = MutationType.valueOf(m_pm.getValue(CF, rowKey, null,
C_TYPE, String.class));
+ return mutation;
+ }
+
+ class Mutation {
+ String id;
+ String name;
+ String hostname;
+ MutationType type;
+ }
+
+ private synchronized String generateRowKey() {
+ m_index++;
+ return "row_" + m_index;
+ }
+}
Modified:
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantRESTServiceImpl.java
==============================================================================
---
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantRESTServiceImpl.java
(original)
+++
sandbox/ivol/tenant-management-gadget/src/main/java/org/amdatu/opensocial/tenant/gadget/service/TenantRESTServiceImpl.java
Mon Nov 7 17:20:25 2011
@@ -15,8 +15,12 @@
*/
package org.amdatu.opensocial.tenant.gadget.service;
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.CF;
+import static
org.amdatu.opensocial.tenant.gadget.service.TenantMutationColumnFamilyProviderImpl.*;
+
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
@@ -24,6 +28,7 @@
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -37,6 +42,7 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import
org.amdatu.cassandra.persistencemanager.hector.HectorCassandraPersistenceManager;
import org.amdatu.core.tenant.Tenant;
import org.amdatu.core.tenant.TenantManagementService;
import org.amdatu.libraries.utilities.rest.AtomSyndicationLink;
@@ -55,8 +61,11 @@
NO_CACHE_CONTROL.setNoCache(true); // No cache
}
- private ConfigurationAdmin m_configAdmin;
- private LogService m_logService;
+ private volatile LogService m_logService;
+ private volatile Tenant m_tenant;
+ private volatile TenantMutationDAO m_tenantDAO;
+
+
public void start() {
m_logService.log(LogService.LOG_INFO, "Tenant management REST service
started");
@@ -69,9 +78,11 @@
try {
for (TenantBean tenant : getTenants()) {
String href = request.getContextPath() + "/rest/tenants/" +
tenant.getId();
- tenant.setLink(new
AtomSyndicationLink().setHref(href).setRel("Alternate")
- .setType("application/json"));
-
+ tenant.addLink(new
AtomSyndicationLink().setHref(href).setRel("edit").setType("application/json"));
+ if (!tenant.getId().equals(m_tenant.getId())) {
+ // Only provide delete link if the tenant is not the same
as the current tenant
+ tenant.addLink(new
AtomSyndicationLink().setHref(href).setRel("delete").setType("application/json"));
+ }
tenantsBean.addTenant(tenant);
}
}
@@ -123,6 +134,33 @@
properties.put(tenantKey + ".name", name);
properties.put(tenantKey + ".properties.hostname", hostname);
config.update(properties);
+
+ m_tenantDAO.addUpdateMutation(id, name, hostname);
+ }
+ catch (Exception e) {
+ throw new WebApplicationException(e,
Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ return Response.ok(tenant,
MediaType.APPLICATION_JSON_TYPE).cacheControl(NO_CACHE_CONTROL)
+ .build();
+ }
+
+ @DELETE
+ @Path("/{id}")
+ public Response deleteTenant(@PathParam("id") final String id) {
+ TenantBean tenant = null;
+ try {
+ Configuration config =
m_configAdmin.getConfiguration(TenantManagementService.PID);
+ Dictionary properties = config.getProperties();
+ String tenantKey = findTenantKey(id);
+ if (tenantKey != null) {
+ properties.remove(tenantKey + ".id");
+ properties.remove(tenantKey + ".name");
+ properties.remove(tenantKey + ".properties.hostname");
+ config.update(properties);
+ }
+
+ m_tenantDAO.addDeleteMutation(id);
}
catch (Exception e) {
throw new WebApplicationException(e,
Response.Status.INTERNAL_SERVER_ERROR);
@@ -145,6 +183,8 @@
key = "tenant" + keyId;
exists = properties.get(key + ".id") != null;
}
+
+ Collections.sort(tenants);
return tenants;
}
@@ -160,35 +200,7 @@
return new TenantBean(id, name, hostname);
}
- private String findTenantKey(String tenantId) throws IOException {
- Configuration config =
m_configAdmin.getConfiguration(TenantManagementService.PID);
- Dictionary properties = config.getProperties();
- Enumeration keys = properties.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement().toString();
- if (key.endsWith(".id")) {
- if (tenantId.equals(properties.get(key))) {
- return key.substring(0, key.indexOf(".id"));
- }
- }
- }
- return null;
- }
+
- private int findLastTenantKey() throws IOException {
- int maxid = 1;
- Configuration config =
m_configAdmin.getConfiguration(TenantManagementService.PID);
- Dictionary properties = config.getProperties();
- Enumeration keys = properties.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement().toString();
- if (key.endsWith(".id")) {
- String id = key.substring("tenant".length(), key.indexOf("."));
- if (Integer.parseInt(id) > maxid) {
- maxid = Integer.parseInt(id);
- }
- }
- }
- return maxid;
- }
+
}
Modified:
sandbox/ivol/tenant-management-gadget/src/main/resources/jsp/TenantGadget.jsp
==============================================================================
---
sandbox/ivol/tenant-management-gadget/src/main/resources/jsp/TenantGadget.jsp
(original)
+++
sandbox/ivol/tenant-management-gadget/src/main/resources/jsp/TenantGadget.jsp
Mon Nov 7 17:20:25 2011
@@ -46,24 +46,30 @@
<script type="text/javascript"
src="${gadgetBaseUrl}/static/js/tenant.js"></script>
<script type="text/javascript"
src="${gadgetBaseUrl}/static/js/util.js"></script>
- <fieldset id="tenants">
- <legend id="tenants_legend">__MSG_tenants__</legend>
- <div id="tenants"></div>
+ <p>
+ <fieldset id="tenants">
+ <legend id="tenants_legend">__MSG_tenants__</legend>
+ <div id="tenants"></div>
+ </fieldset>
+ </p>
+
+ <p>
+ <input type="button" id="new_tenant_button" value="__MSG_new_tenant__"
onclick="javascript:showAddTenant();"/>
+ </p>
+
+ <p>
+ <fieldset id="tenant_details" style="display:none;visibility:hidden">
+ <legend id="tenant_details_legend">__MSG_details__</legend>
+ <table width="95%">
+ <tr><td>__MSG_id__</td><td><input type="edit" id="tenant_id"
disabled="disabled"/></td></tr>
+ <tr><td>__MSG_name__</td><td><input type="edit" id="tenant_name"
value=""/></td></tr>
+ <tr><td>__MSG_hostname__</td><td><input type="edit"
id="tenant_hostname" value=""/></td></tr>
+ </table>
+ <input type="submit" id="tenant_save" value="__MSG_save__"
onclick="javascript:saveTenant();"/>
+ <input type="button" id="cancel" value="__MSG_cancel__"
onclick="javascript:cancelEdit();"/>
+ </fieldset>
<div id="infobox"></div>
- </fieldset>
-
- <input type="button" id="new_tenant_button" value="__MSG_new_tenant__"
onclick="javascript:addTenant();"/>
-
- <fieldset id="tenant_details" style="display:none;visibility:hidden">
- <legend id="tenant_details_legend">__MSG_details__</legend>
- <table width="95%">
- <tr><td>__MSG_id__</td><td><input type="edit" id="tenant_id"
disabled="disabled"/></td></tr>
- <tr><td>__MSG_name__</td><td><input type="edit" id="tenant_name"
value=""/></td></tr>
- <tr><td>__MSG_hostname__</td><td><input type="edit"
id="tenant_hostname" value=""/></td></tr>
- </table>
- <input type="submit" id="tenant_save" value="__MSG_save__"
onclick="javascript:saveTenant();"/>
- <input type="button" id="cancel" value="__MSG_cancel__"
onclick="javascript:cancelEdit();"/>
- </fieldset>
+ </p>
<script type="text/javascript">
var contextPath = "${contextPath}";
Modified:
sandbox/ivol/tenant-management-gadget/src/main/resources/static/css/tenant.css
==============================================================================
---
sandbox/ivol/tenant-management-gadget/src/main/resources/static/css/tenant.css
(original)
+++
sandbox/ivol/tenant-management-gadget/src/main/resources/static/css/tenant.css
Mon Nov 7 17:20:25 2011
@@ -20,7 +20,6 @@
}
table td {
-
max-width: 280px;
_width: 280px; /* IE */
white-space: pre; /* CSS 2.0 */
Added:
sandbox/ivol/tenant-management-gadget/src/main/resources/static/images/remove_disabled.gif
==============================================================================
Binary file. No diff available.
Modified:
sandbox/ivol/tenant-management-gadget/src/main/resources/static/js/tenant.js
==============================================================================
---
sandbox/ivol/tenant-management-gadget/src/main/resources/static/js/tenant.js
(original)
+++
sandbox/ivol/tenant-management-gadget/src/main/resources/static/js/tenant.js
Mon Nov 7 17:20:25 2011
@@ -30,6 +30,14 @@
gadgets.io.makeRequest(url, callback, params);
}
+function doDeleteTenant(url, callback) {
+ var params = {};
+ params[gadgets.io.RequestParameters.CONTENT_TYPE] =
gadgets.io.ContentType.JSON;
+ params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.DELETE;
+ url = getBaseUrl() + addNoCache(unescape(url));
+ gadgets.io.makeRequest(url, callback, params);
+}
+
function onTenantsLoaded(response) {
if (response.rc == 200) {
var html = "<p><center><table class='stripeMe'>";
@@ -42,13 +50,21 @@
var id = tenants[i]["id"];
var name = tenants[i]["name"];
var hostname = tenants[i]["hostname"];
- var link = tenants[i]["link"].href;
-
- var editTenant = " onclick=\"javascript:editTenant('" + escape(link) +
"');\"";
- var deleteTentant = " onclick=\"javascript:confirmDeleteTenant('" +
escape(link) + "', '" + escape(name) + "');\"";
+ // Create the edit link
+ var editLink = getLink(ensureArray(tenants[i]["links"]), "edit");
+ var editTenant = " onclick=\"javascript:showEditTenant('" +
escape(editLink) + "');\"";
html += "<tr><td><a href='#'" + editTenant + ">" + name + " (" +
hostname + ")</a></td>";
- html += "<td align='center'><a href='#'><img src='" + contextPath +
"/tenant/static/images/remove.gif'" + deleteTenant + "/></a></td></tr>";
+
+ // Create the delete link
+ var deleteLink = getLink(ensureArray(tenants[i]["links"]), "delete");
+ if (deleteLink) {
+ var deleteTenant = " onclick=\"javascript:showDeleteTenant('" +
escape(deleteLink) + "', '" + escape(name) + "');\"";
+ html += "<td align='center'><a href='#'><img src='" + contextPath +
"/tenant/static/images/remove.gif'" + deleteTenant + "/></a></td></tr>";
+ } else {
+ html += "<td align='center'><a class='tooltip' title='The current
Tenant you are working on cannot be removed.'>";
+ html += "<img src='" + contextPath +
"/tenant/static/images/remove_disabled.gif'/></a></td></tr>";
+ }
}
html += "</table></center></p>";
@@ -63,6 +79,14 @@
gadgets.window.adjustHeight();
}
+function getLink(tenants, linkType) {
+ for (j=0; j<tenants.length; j++) {
+ if(tenants[j].rel == linkType) {
+ return tenants[j].href;
+ }
+ }
+}
+
function onTenantLoaded(response) {
if (response.rc == 200) {
var tenant = response.data["tenant"];
@@ -79,15 +103,16 @@
}
}
-function editTenant(link) {
- loadTenant(escape(unescape(link)), onTenantLoaded);
- hide('new_tenant_button');
- document.getElementById('tenant_details_legend').innerHTML =
updateTenantLabel;
- show('tenant_details');
-}
-function deleteTenant() {
+function showDeleteTenant(link, name) {
+ if (confirm('Are you sure you want to delete the Tenant "' + name + '"?')) {
+ deleteTenant(link);
+ }
+}
+
+function deleteTenant(link) {
+ doDeleteTenant(escape(link), onTenantDeleted);
}
function saveTenant() {
@@ -96,23 +121,51 @@
}
function onTenantSaved() {
- document.getElementById('infobox').innerHTML = "Tenant updated
successfully.";
+ hide('tenant_details');
+ loadTenants();
+ showInfo("Tenant saved successfully.");
+}
+
+function onTenantDeleted() {
+ hide('tenant_details');
+ loadTenants();
+ showInfo("Tenant deleted successfully.");
+}
+
+function showInfo(message) {
+ document.getElementById('infobox').innerHTML = "<p><font color='#267F00'>" +
message + "</p>";
+ show('infobox');
+ gadgets.window.adjustHeight();
}
-function confirmDeleteTenant(tenant) {
- alert('confirm');
+function showError(message) {
+ document.getElementById('infobox').innerHTML = "<p><font color='#FF0000'>" +
message + "</p>";
+ show('infobox');
+ gadgets.window.adjustHeight();
+}
+
+function showEditTenant(link) {
+ loadTenant(escape(unescape(link)), onTenantLoaded);
+ hide('new_tenant_button');
+ hide('infobox');
+ document.getElementById('tenant_details_legend').innerHTML =
updateTenantLabel;
+ show('tenant_details');
}
function cancelEdit() {
hide('tenant_details');
show('new_tenant_button');
+ hide('infobox');
gadgets.window.adjustHeight();
}
-function addTenant() {
+function showAddTenant() {
hide('new_tenant_button');
document.getElementById('tenant_details_legend').innerHTML = newTenantLabel;
document.getElementById('tenant_id').disabled = "";
+ document.getElementById('tenant_id').value = "";
+ document.getElementById('tenant_name').value = "";
+ document.getElementById('tenant_hostname').value = "";
show('tenant_details');
gadgets.window.adjustHeight();
}
\ No newline at end of file
_______________________________________________
Amdatu-commits mailing list
[email protected]
http://lists.amdatu.org/mailman/listinfo/amdatu-commits