Permalink
Browse files

Closes GH-22, see class notes in DefaultIDMgmtProxy

  • Loading branch information...
1 parent 258f514 commit 63281b66976a3c596b953bc894e39b8f6486e243 @timf timf committed Dec 28, 2010
@@ -70,10 +70,12 @@
</bean>
<bean id="nimbus-elastic.rm.idmappings"
- class="org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultIDMgmt">
+ class="org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultIDMgmtProxy" />
+ <!-- Don't reference this bean directly. See DefaultIDMgmtProxy class notes. -->
+ <bean id="nimbus-elastic.rm.realidmappings"
+ class="org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultIDMgmt">
<constructor-arg value="$COMMON{caches.dir}" />
-
</bean>
@@ -158,6 +158,12 @@ public synchronized ServiceImage findImage() throws Exception {
return (ServiceImage) this.appCtx.getBean(this.idIMAGE);
}
+ public synchronized Object findBeanByID(String id) throws Exception {
+ if (this.appCtx == null) {
+ throw new Exception("No " + this.contextName + " was instantiated");
+ }
+ return this.appCtx.getBean(id);
+ }
// -------------------------------------------------------------------------
// CONF FILE
@@ -0,0 +1,207 @@
+/*
+ * Copyright 1999-2010 University of Chicago
+ *
+ * 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.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults;
+
+import net.sf.ehcache.Cache;
+import org.nimbustools.messaging.gt4_0_elastic.context.ElasticContext;
+import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.IDMappings;
+import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.security.defaults.KeyCacheProvider;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * The purpose of this is to ensure that the same instance of the IDMappings/KeyCacheProvider
+ * impl class is being used across *all* Spring contexts in the same JVM. Because of the
+ * multiple messaging containers in use, it's currently a reality that multiple Spring
+ * contexts exist. And thus, breaking the IoC abstraction is necessary if anything is
+ * going to share resources that need to be consistent with each other.
+ *
+ * (It's not quite per-JVM. Just like with the protocol layers, if you're really after
+ * multiple Nimbus service stacks in the same JVM, you need to adjust the lookups in the
+ * JNDI config in your alternate installation. That will also then mean you'll get multiple
+ * DefaultIDMgmt instances, one per service stack).
+ */
+public class DefaultIDMgmtProxy implements IDMappings, KeyCacheProvider,
+ ApplicationContextAware {
+
+ public static final String ID_MAPPING_BEAN_NAME = "nimbus-elastic.rm.realidmappings";
+
+ private ApplicationContext thisAppCtx;
+ private IDMappings correctIDMappings;
+
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.thisAppCtx = applicationContext;
+ }
+
+ /**
+ * See class notes.
+ * @return the proper IDMappings instance, never null
+ * @throws Exception cannot find it
+ */
+ private IDMappings getReal() throws RuntimeException {
+ if (this.correctIDMappings != null) {
+ return this.correctIDMappings;
+ }
+
+ Object idMappings = null;
+ try {
+ if (this.thisAppCtx == null) {
+ ElasticContext thatAppCtx = ElasticContext.discoverElasticContext();
+ idMappings = thatAppCtx.findBeanByID(ID_MAPPING_BEAN_NAME);
+ } else {
+
+ try {
+ idMappings = this.thisAppCtx.getBean(ID_MAPPING_BEAN_NAME);
+ } catch (NoSuchBeanDefinitionException e) {
+ ElasticContext thatAppCtx = ElasticContext.discoverElasticContext();
+ idMappings = thatAppCtx.findBeanByID(ID_MAPPING_BEAN_NAME);
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Problem manually retrieving bean '" +
+ ID_MAPPING_BEAN_NAME + "': " + e.getMessage(), e);
+ }
+
+ // future developer error catch:
+ if (idMappings == null) {
+ throw new RuntimeException("no bean? '" + ID_MAPPING_BEAN_NAME + "'");
+ }
+ if (idMappings instanceof IDMappings) {
+ this.correctIDMappings = (IDMappings)idMappings;
+ } else {
+ throw new RuntimeException("bean does not implement" +
+ " IDMappings? '" + ID_MAPPING_BEAN_NAME + "'");
+ }
+ if (!(idMappings instanceof KeyCacheProvider)) {
+ throw new RuntimeException("bean does not implement" +
+ " KeyCacheProvider? '" + ID_MAPPING_BEAN_NAME + "'");
+ }
+
+ return this.correctIDMappings;
+ }
+
+ /**
+ * See class notes.
+ * @return the proper KeyCacheProvider instance, never null
+ * @throws Exception cannot find it
+ */
+ private KeyCacheProvider getRealKeyCacheProvider() throws RuntimeException {
+ return (KeyCacheProvider) this.getReal();
+ }
+
+
+ // **************************************************************************************
+
+ public String newInstanceID(String managerInstanceID, String elasticReservationID,
+ String sshkeyUsed) throws Exception {
+ return this.getReal().newInstanceID(managerInstanceID, elasticReservationID, sshkeyUsed);
+ }
+
+ public String newGrouplessInstanceID(String managerInstanceID, String sshkeyUsed)
+ throws Exception {
+ return this.getReal().newGrouplessInstanceID(managerInstanceID, sshkeyUsed);
+ }
+
+ public String newGroupReservationID(String managerGroupID) throws Exception {
+ return this.getReal().newGroupReservationID(managerGroupID);
+ }
+
+ public String newCoschedReservationID(String managerCoschedID) throws Exception {
+ return this.getReal().newCoschedReservationID(managerCoschedID);
+ }
+
+ public String getOrNewInstanceReservationID(String managerInstanceID, String sshkeyUsed)
+ throws Exception {
+ return this.getReal().getOrNewInstanceReservationID(managerInstanceID, sshkeyUsed);
+ }
+
+ public String getOrNewGroupReservationID(String managerGroupID) throws Exception {
+ return this.getReal().getOrNewGroupReservationID(managerGroupID);
+ }
+
+ public String getOrNewCoschedReservationID(String managerCoschedID) throws Exception {
+ return this.getReal().getOrNewCoschedReservationID(managerCoschedID);
+ }
+
+ public String checkInstanceAndReservation(String managerInstanceID,
+ String elasticReservationID) throws Exception {
+ return this.getReal().checkInstanceAndReservation(managerInstanceID, elasticReservationID);
+ }
+
+ public boolean isInstanceID(String elasticKey) {
+ return this.getReal().isInstanceID(elasticKey);
+ }
+
+ public String instanceToManager(String elasticInstanceID) {
+ return this.getReal().instanceToManager(elasticInstanceID);
+ }
+
+ public boolean isManagerGroupID(String elasticKey) {
+ return this.getReal().isManagerGroupID(elasticKey);
+ }
+
+ public String reservationToManagerGroup(String elasticReservationID) {
+ return this.getReal().reservationToManagerGroup(elasticReservationID);
+ }
+
+ public boolean isCoschedReservationID(String elasticKey) {
+ return this.getReal().isCoschedReservationID(elasticKey);
+ }
+
+ public String reservationToManagerCosched(String elasticReservationID) {
+ return this.getReal().reservationToManagerCosched(elasticReservationID);
+ }
+
+ public boolean isElasticInstanceID(String managerKey) {
+ return this.getReal().isElasticInstanceID(managerKey);
+ }
+
+ public String managerInstanceToElasticInstance(String managerInstanceID) {
+ return this.getReal().managerInstanceToElasticInstance(managerInstanceID);
+ }
+
+ public String managerInstanceToElasticReservation(String managerInstanceID) {
+ return this.getReal().managerInstanceToElasticReservation(managerInstanceID);
+ }
+
+ public boolean isElasticReservationIDGroup(String managerKey) {
+ return this.getReal().isElasticReservationIDGroup(managerKey);
+ }
+
+ public String managerGroupToElasticReservation(String managerGroupID) {
+ return this.getReal().managerGroupToElasticReservation(managerGroupID);
+ }
+
+ public boolean isElasticReservationIDCosched(String managerKey) {
+ return this.getReal().isElasticReservationIDCosched(managerKey);
+ }
+
+ public String managerCoschedToElasticReservation(String managerCoschedID) {
+ return this.getReal().managerCoschedToElasticReservation(managerCoschedID);
+ }
+
+ public String getKeyName(String elasticID) {
+ return this.getReal().getKeyName(elasticID);
+ }
+
+ public Cache getKeyCache() {
+ return this.getRealKeyCacheProvider().getKeyCache();
+ }
+}
@@ -40,7 +40,8 @@
// -------------------------------------------------------------------------
// key: 'ownerID', value: List of SSHKey objects
- private final Cache sshKeyCache;
+ private Cache sshKeyCache;
+ private final KeyCacheProvider keyCacheProvider;
protected boolean pubkeyOnly;
protected String splitToken;
@@ -55,8 +56,15 @@ public DefaultSSHKeys(KeyCacheProvider cacheLocator) {
if (cacheLocator == null) {
throw new IllegalArgumentException("cacheLocator may not be null");
}
+ this.keyCacheProvider = cacheLocator;
+ }
- this.sshKeyCache = cacheLocator.getKeyCache();
+ // avoids a circular dependency with Spring context instantiation
+ private void ensureCache() {
+ if (this.sshKeyCache != null) {
+ return;
+ }
+ this.sshKeyCache = this.keyCacheProvider.getKeyCache();
if (this.sshKeyCache == null) {
throw new IllegalArgumentException(
"cacheLocator failed to provide key cache");
@@ -121,6 +129,8 @@ public String getSplitToken() throws DisabledException {
* @return key object or null if one cannot be found
*/
public synchronized SSHKey findKey(String ownerID, String keyName) {
+
+ this.ensureCache();
if (ownerID == null) {
throw new IllegalArgumentException("ownerID may not be null");
@@ -159,6 +169,8 @@ public synchronized SSHKey findKey(String ownerID, String keyName) {
* @return all owner's key objects or zero-length array if zero are found
*/
public synchronized SSHKey[] getOwnerKeys(String ownerID) {
+
+ this.ensureCache();
if (ownerID == null) {
throw new IllegalArgumentException("ownerID may not be null");
@@ -196,6 +208,8 @@ public synchronized boolean newKey(String ownerID,
String pubKeyContent,
String fingerprint) {
+ this.ensureCache();
+
if (ownerID == null) {
throw new IllegalArgumentException("ownerID may not be null");
}
@@ -247,6 +261,8 @@ public synchronized boolean newKey(String ownerID,
* @return true if this deleted a key
*/
public boolean removeKey(String ownerID, String keyName) {
+
+ this.ensureCache();
if (ownerID == null) {
throw new IllegalArgumentException("ownerID may not be null");
@@ -3,14 +3,11 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
- xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-http://www.springframework.org/schema/aop
-http://www.springframework.org/schema/aop/spring-aop.xsd
-http://www.springframework.org/schema/security
+http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
@@ -162,11 +159,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd">
<bean id="nimbus-query.rm.idmappings"
- class="org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultIDMgmt">
-
- <constructor-arg value="$COMMON{caches.dir}" />
-
- </bean>
+ class="org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultIDMgmtProxy" />
<!-- ************ ServiceGeneral *********** -->
@@ -294,4 +287,4 @@ http://cxf.apache.org/schemas/jaxrs.xsd">
-->
<import resource="main.conflocator.xml"/>
-</beans>
+</beans>

0 comments on commit 63281b6

Please sign in to comment.