You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by lh...@apache.org on 2014/01/05 01:01:21 UTC

svn commit: r1555436 - in /shiro/branches/1.x: ./ support/hazelcast/ support/hazelcast/src/main/java/org/apache/shiro/hazelcast/ support/hazelcast/src/main/java/org/apache/shiro/hazelcast/cache/ support/hazelcast/src/test/groovy/org/apache/shiro/hazelc...

Author: lhazlewood
Date: Sun Jan  5 00:01:21 2014
New Revision: 1555436

URL: http://svn.apache.org/r1555436
Log:
SHIRO-412: updated Hazelcast support to reflect client vs server/embedded configuration.  Class/line test coverage at 100%

Added:
    shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactory.java
    shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactory.java
    shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/HazelcastInstanceFactory.java
    shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactoryTest.groovy
    shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactoryTest.groovy
    shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/HazelcastInstanceFactoryTest.groovy
Modified:
    shiro/branches/1.x/pom.xml
    shiro/branches/1.x/support/hazelcast/pom.xml
    shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/cache/HazelcastCacheManager.java
    shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/cache/HazelcastCacheManagerTest.groovy

Modified: shiro/branches/1.x/pom.xml
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/pom.xml?rev=1555436&r1=1555435&r2=1555436&view=diff
==============================================================================
--- shiro/branches/1.x/pom.xml (original)
+++ shiro/branches/1.x/pom.xml Sun Jan  5 00:01:21 2014
@@ -81,7 +81,7 @@
              modules' OSGi metadata: -->
         <ehcache.version>2.5.3</ehcache.version>
         <!-- Don't change this version without also changing the shiro-hazelcast and shiro-features OSGi metadata: -->
-        <hazelcast.version>2.4.1</hazelcast.version>
+        <hazelcast.version>3.1.3</hazelcast.version>
         <hsqldb.version>1.8.0.7</hsqldb.version>
         <jdk.version>1.5</jdk.version>
         <jetty.version>6.1.26</jetty.version>
@@ -710,8 +710,8 @@
             </dependency>
             <dependency>
                 <groupId>com.hazelcast</groupId>
-                <artifactId>hazelcast</artifactId>
-                <version>2.4.1</version>
+                <artifactId>hazelcast-client</artifactId>
+                <version>${hazelcast.version}</version>
             </dependency>
             <dependency>
                 <!-- Used for sample applications only - not required for the framework: -->

Modified: shiro/branches/1.x/support/hazelcast/pom.xml
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/pom.xml?rev=1555436&r1=1555435&r2=1555436&view=diff
==============================================================================
--- shiro/branches/1.x/support/hazelcast/pom.xml (original)
+++ shiro/branches/1.x/support/hazelcast/pom.xml Sun Jan  5 00:01:21 2014
@@ -42,7 +42,7 @@
         </dependency>
         <dependency>
             <groupId>com.hazelcast</groupId>
-            <artifactId>hazelcast</artifactId>
+            <artifactId>hazelcast-client</artifactId>
         </dependency>
         <!-- Test dependencies -->
         <dependency>

Added: shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactory.java
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactory.java?rev=1555436&view=auto
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactory.java (added)
+++ shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactory.java Sun Jan  5 00:01:21 2014
@@ -0,0 +1,105 @@
+package org.apache.shiro.hazelcast;
+
+import com.hazelcast.client.HazelcastClient;
+import com.hazelcast.client.config.ClientConfig;
+import com.hazelcast.core.HazelcastInstance;
+
+/**
+ * Constructs and returns a <a href="http://www.hazelcast.org/docs/3.0/manual/html-single/#JavaClient">Hazelcast client</a>
+ * that can be used to interact with Hazelcast cluster members.
+ * <p/>
+ * This implementation is likely the one that most Shiro-enabled applications will use: most applications are probably
+ * not suited to be full cache cluster members because of the additional memory and communication requirements that
+ * would impose on the application, and instead are likely to be only clients to the cache cluster.
+ * <p/>
+ * If you *do* however wish to have your application be a peer (full) cache cluster node - for example, maybe you are
+ * running an application in 'embedded' or 'standalone' mode and don't want to connect to external cache nodes - use the
+ * {@link EmbeddedHazelcastInstanceFactory} instead.
+ *
+ * @see EmbeddedHazelcastInstanceFactory
+ */
+public class ClientHazelcastInstanceFactory extends HazelcastInstanceFactory {
+
+    private ClientConfig config;
+
+    /**
+     * Instantiates the factory with a new {@link ClientConfig}, ready to be configured.
+     */
+    public ClientHazelcastInstanceFactory() {
+        this.config = new ClientConfig();
+    }
+
+    /**
+     * Returns the {@link ClientConfig} object that represents the configuration to be used when creating a new client
+     * {@link HazelcastInstance}.
+     * <p/>
+     * If using {@code shiro.ini}, you can reference this property by name and then chain config statements easily to
+     * reduce configuration.  For example:
+     * <pre>
+     * [main]
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory
+     * hazelcast.config.groupConfig.name = myClusterGroupName
+     * hazelcast.config.addresses = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * </pre>
+     * <p>or, you can configure the object separately and then inject it by reference. For example:</p>
+     * <pre>
+     * [main]
+     * hazelcastConfig = com.hazelcast.client.config.ClientConfig
+     * hazelcastConfig.groupConfig.name = myClusterGroupName
+     * hazelcastConfig.addresses = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory
+     * hazelcast.config = $hazelcastConfig
+     * </pre>
+     *
+     * @return the clientConfig to be used to customize configuration
+     */
+    public ClientConfig getConfig() {
+        return config;
+    }
+
+    /**
+     * Sets the {@link ClientConfig} object that represents the configuration to be used when creating a new client
+     * {@link HazelcastInstance}.
+     * <p/>
+     * If using {@code shiro.ini}, you can reference this property by name and then chain config statements easily to
+     * reduce configuration.  For example:
+     * <pre>
+     * [main]
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory
+     * hazelcast.config.groupConfig.name = myClusterGroupName
+     * hazelcast.config.addresses = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * </pre>
+     * <p>or, you can configure the object separately and then inject it by reference. For example:</p>
+     * <pre>
+     * [main]
+     * hazelcastConfig = com.hazelcast.client.config.ClientConfig
+     * hazelcastConfig.groupConfig.name = myClusterGroupName
+     * hazelcastConfig.addresses = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory
+     * hazelcast.config = $hazelcastConfig
+     * </pre>
+     *
+     * @param config the config object that represents the configuration to be used when creating a new client
+     *               {@link HazelcastInstance}.
+     */
+    public void setConfig(ClientConfig config) {
+        this.config = config;
+    }
+
+    /**
+     * Creates a new client {@code HazelcastInstance} via
+     * <pre>
+     * return HazelcastClient.newHazelcastClient(this.config);
+     * </pre>
+     *
+     * @return a new client {@code HazelcastInstance}
+     */
+    @Override
+    protected HazelcastInstance createInstance() {
+        return HazelcastClient.newHazelcastClient(this.config);
+    }
+}

Added: shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactory.java
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactory.java?rev=1555436&view=auto
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactory.java (added)
+++ shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactory.java Sun Jan  5 00:01:21 2014
@@ -0,0 +1,112 @@
+package org.apache.shiro.hazelcast;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+
+/**
+ * Constructs and returns an embedded Hazelcast cluster node that can be a peer to other Hazelcast cluster members.
+ * <p/>
+ * <b>Note:</b> this implementation should only be used if you want to start an embedded Hazelcast server node within
+ * the same JVM as your Shiro-enabled application.  If your application should be a standard client to a Hazelcast
+ * cluster, use the {@link ClientHazelcastInstanceFactory} instead.
+ * <p/>
+ * Most Shiro-enabled applications are likely to be clients to a Hazelcast cluster since being a full cache server node
+ * (cluster peer) imposes additional memory, threading and communication requirements that might not be suitable for
+ * apps with other dedicated workloads (e.g. handling requests).  In these cases, it is likely that
+ * the {@link ClientHazelcastInstanceFactory} should be used instead to connect to the cluster, instead of operating
+ * as a full server cluster node (peer).
+ * <p/>
+ * For more information on embedded/server node configuration, see the
+ * <a href="http://hazelcast.org/docs/3.0/manual/html-single/#Config">Hazelcast server configuration documentation</a>.
+ *
+ * @see ClientHazelcastInstanceFactory
+ */
+public class EmbeddedHazelcastInstanceFactory extends HazelcastInstanceFactory {
+
+    private Config config;
+
+    /**
+     * Instantiates the factory with a new {@link Config}, ready to be configured.
+     */
+    public EmbeddedHazelcastInstanceFactory() {
+        this.config = new Config();
+    }
+
+    /**
+     * Returns the {@link Config} object that represents the configuration to be used when creating a new embedded
+     * server node {@link HazelcastInstance}.
+     * <p/>
+     * If using {@code shiro.ini}, you can reference this property by name and then chain config statements easily to
+     * reduce configuration.  For example:
+     * <pre>
+     * [main]
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory
+     * hazelcast.config.groupConfig.name = myClusterGroupName
+     * hazelcast.config.networkConfig.joinConfig.multicastConfig.enabled = false
+     * hazelcast.config.networkConfig.joinConfig.tcpIpConfig.members = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * </pre>
+     * <p>or, you can configure the object separately and then inject it by reference. For example:</p>
+     * <pre>
+     * [main]
+     * hazelcastConfig = com.hazelcast.config.Config
+     * hazelcastConfig.groupConfig.name = myClusterGroupName
+     * hazelcastConfig.networkConfig.joinConfig.multicastConfig.enabled = false
+     * hazelcastConfig.networkConfig.joinConfig.tcpIpConfig.members = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory
+     * hazelcast.config = $hazelcastConfig
+     * </pre>
+     *
+     * @return the config to be used to customize configuration
+     */
+    public Config getConfig() {
+        return config;
+    }
+
+
+    /**
+     * Sets the {@link Config} object that represents the configuration to be used when creating a new embedded
+     * server node {@link HazelcastInstance}.
+     * <p/>
+     * If using {@code shiro.ini}, you can reference this property by name and then chain config statements easily to
+     * reduce configuration.  For example:
+     * <pre>
+     * [main]
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory
+     * hazelcast.config.groupConfig.name = myClusterGroupName
+     * hazelcast.config.networkConfig.joinConfig.multicastConfig.enabled = false
+     * hazelcast.config.networkConfig.joinConfig.tcpIpConfig.members = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * </pre>
+     * <p>or, you can configure the object separately and then inject it by reference. For example:</p>
+     * <pre>
+     * [main]
+     * hazelcastConfig = com.hazelcast.config.Config
+     * hazelcastConfig.groupConfig.name = myClusterGroupName
+     * hazelcastConfig.networkConfig.joinConfig.multicastConfig.enabled = false
+     * hazelcastConfig.networkConfig.joinConfig.tcpIpConfig.members = 192.168.1.1, 192.168.1.2, 192.168.1.3
+     * ...
+     * hazelcast = org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory
+     * hazelcast.config = $hazelcastConfig
+     * </pre>
+     * @param config the config to be used to customize configuration
+     */
+    public void setConfig(Config config) {
+        this.config = config;
+    }
+
+    /**
+     * Creates a new client {@code HazelcastInstance} via
+     * <pre>
+     * return Hazelcast.newHazelcastInstance(this.config);
+     * </pre>
+     *
+     * @return a new client {@code HazelcastInstance}
+     */
+    @Override
+    protected HazelcastInstance createInstance() {
+        return Hazelcast.newHazelcastInstance(this.config);
+    }
+}

Added: shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/HazelcastInstanceFactory.java
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/HazelcastInstanceFactory.java?rev=1555436&view=auto
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/HazelcastInstanceFactory.java (added)
+++ shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/HazelcastInstanceFactory.java Sun Jan  5 00:01:21 2014
@@ -0,0 +1,52 @@
+package org.apache.shiro.hazelcast;
+
+import com.hazelcast.core.HazelcastInstance;
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.util.Destroyable;
+import org.apache.shiro.util.Factory;
+import org.apache.shiro.util.Initializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract base class for providing {@link HazelcastInstance}s.  Subclasses create either an embedded Hazelcast server
+ * node that will be a member of the Hazelcast cluster or a lightweight client that is not a server member, but only
+ * interacts with server members.
+ *
+ * @see ClientHazelcastInstanceFactory
+ * @see EmbeddedHazelcastInstanceFactory
+ */
+public abstract class HazelcastInstanceFactory implements Factory<HazelcastInstance>, Initializable, Destroyable {
+
+    private static final Logger log = LoggerFactory.getLogger(ClientHazelcastInstanceFactory.class);
+
+    private HazelcastInstance instance;
+
+    public synchronized HazelcastInstance getInstance() {
+        if (this.instance == null) {
+            this.instance = createInstance();
+        }
+        return this.instance;
+    }
+
+    protected abstract HazelcastInstance createInstance();
+
+    public void init() throws ShiroException {
+        getInstance(); //will auto-create the instance as necessary.
+    }
+
+    public void destroy() throws Exception {
+        if (this.instance == null) return;
+
+        try {
+            this.instance.getLifecycleService().shutdown();
+        } catch (Throwable t) {
+            if (log.isWarnEnabled()) {
+                log.warn("Unable to cleanly shutdown implicitly created HazelcastInstance.  " +
+                        "Ignoring (shutting down)...", t);
+            }
+        } finally {
+            this.instance = null;
+        }
+    }
+}

Modified: shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/cache/HazelcastCacheManager.java
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/cache/HazelcastCacheManager.java?rev=1555436&r1=1555435&r2=1555436&view=diff
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/cache/HazelcastCacheManager.java (original)
+++ shiro/branches/1.x/support/hazelcast/src/main/java/org/apache/shiro/hazelcast/cache/HazelcastCacheManager.java Sun Jan  5 00:01:21 2014
@@ -18,18 +18,13 @@
  */
 package org.apache.shiro.hazelcast.cache;
 
-import com.hazelcast.config.Config;
-import com.hazelcast.core.Hazelcast;
 import com.hazelcast.core.HazelcastInstance;
 import org.apache.shiro.ShiroException;
 import org.apache.shiro.cache.Cache;
 import org.apache.shiro.cache.CacheException;
 import org.apache.shiro.cache.CacheManager;
 import org.apache.shiro.cache.MapCache;
-import org.apache.shiro.util.Destroyable;
 import org.apache.shiro.util.Initializable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.Map;
 
@@ -41,45 +36,49 @@ import java.util.Map;
  * {@link HazelcastInstance#getMap(String) acquire} named {@link java.util.concurrent.ConcurrentMap ConcurrentMap}
  * instances.  Those clustered/distributed Map instances are then wrapped and made available to {@code CacheManager}
  * callers as {@link MapCache} instances via {@link #getCache(String)}.
- * <h2>Configuration</h2>
- * This implementation's backing {@code HazelcastInstance} can be configured in one of three ways:
- * <ol>
- * <li>Doing nothing and leveraging default Hazelcast configuration mechanisms</li>
- * <li>Supplying an already-existing {@code HazelcastInstance}</li>
- * <li>Supplying a {@link Config} instance and using that to create a new {@code HazelcastInstance}</li>
- * </ol>
- * <h3>Default Configuration</h3>
- * If you simply instantiate a {@code HazelcastCacheManager} and do nothing further, its backing
- * {@link HazelcastInstance} instance will be created automatically by calling
- * {@link Hazelcast#newHazelcastInstance(com.hazelcast.config.Config) Hazelcast.newHazelcastInstance(null)}.
+ * <h3>Configuration</h3>
+ * This implementation's backing {@code HazelcastInstance} must be specified by calling
+ * {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) setHazelcastInstance}, either directly or via
+ * Dependency Injection (shiro.ini, Spring, Guice, etc).
  * <p/>
- * The null argument instructs Hazelcast to use whatever default configuration mechanism it has at its disposal,
- * usually a {@code hazelcast.xml} file at the root of the classpath, or if that is not present, the
- * {@code hazelcast-default.xml} file contained in the Hazelcast {@code .jar} file itself.
- * <p/>
- * <h3>An existing {@code HazelcastInstance}</h3>
- * If you have created a {@code HazelcastInstance} outside of Shiro's knowledge/control, you can simply configure it
- * to be used by calling {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) setHazelcastInstance}.
- * <p/>
- * <h3>A {@link Config} instance</h3>
- * If you do not want to use the above two options, you can have programmatic control over all of Hazelcast's
- * configuration by <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">creating and configuring a
- * Config instance</a>.
- * <p/>
- * Once constructed, you can set it via {@link #setConfig(com.hazelcast.config.Config) setConfig(config)}. This config
- * instance will be used to acquire a new Hazelcast instance by calling
- * {@link Hazelcast#newHazelcastInstance(Config) Hazelcast.newHazelcastInstance(config)}
+ * DependencyInjection environments will likely find using either the
+ * {@link org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory} or the {@link org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory} factory implementations
+ * convenient for specifying Hazelcast configuration that will be used to create the {@link HazelcastInstance}.
+ * <h4>As a Hazelcast Client</h4>
+ * <p>If your Shiro-enabled application is a client to a Hazelcast cluster, you will likely want to use the
+ * {@link org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory} to create a client hazelcast instance.  For example, if using
+ * {@code shiro.ini}:<p/>
+ * <pre>
+ * hazelcast = org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory
+ * hazelcast.config.groupConfig.name = myClusterGroupName
+ * hazelcast.config.addresses = 192.168.1.1, 192.168.1.2, 192.168.1.3
+ *
+ * cacheManager = org.apache.shiro.hazelcast.cache.HazelcastCacheManager
+ * cacheManager.hazelcastInstance = $hazelcast
+ * </pre>
+ * <h4>As an Embedded Hazelcast Node</h4>
+ * <p>If, instead of being a client to a Hazelcast cluster, you want your application to run with an embedded Hazelcast
+ * server node (or be a server node peer to other server nodes), use the
+ * {@link org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory} instead.  For example:<p/>
+ * <pre>
+ * [main]
+ * hazelcast = org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory
+ * hazelcast.config.groupConfig.name = myClusterGroupName
+ * hazelcast.config.networkConfig.joinConfig.multicastConfig.enabled = false
+ * hazelcast.config.networkConfig.joinConfig.tcpIpConfig.members = 192.168.1.1, 192.168.1.2, 192.168.1.3
+ *
+ * cacheManager = org.apache.shiro.hazelcast.cache.HazelcastCacheManager
+ * cacheManager.hazelcastInstance = $hazelcast
+ * </pre>
+ *
+ * @see org.apache.shiro.hazelcast.ClientHazelcastInstanceFactory
+ * @see org.apache.shiro.hazelcast.EmbeddedHazelcastInstanceFactory
  *
- * @see <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">Hazelcast Configuration Documentation</a>
  * @since 1.3
  */
-public class HazelcastCacheManager implements CacheManager, Initializable, Destroyable {
+public class HazelcastCacheManager implements CacheManager, Initializable {
 
-    public static final Logger log = LoggerFactory.getLogger(HazelcastCacheManager.class);
-
-    private boolean implicitlyCreated = false;
     private HazelcastInstance hazelcastInstance;
-    private Config config;
 
     /**
      * Returns a {@link MapCache} instance representing the named Hazelcast-managed
@@ -92,101 +91,36 @@ public class HazelcastCacheManager imple
      * @return a {@link MapCache} instance representing the named Hazelcast-managed {@link com.hazelcast.core.IMap IMap}.
      * @throws CacheException
      * @see HazelcastInstance#getMap(String)
-     * @see #ensureHazelcastInstance()
+     * @see #assertHazlecastInstance() ()
      *
      */
     public <K, V> Cache<K, V> getCache(String name) throws CacheException {
-        Map<K, V> map = ensureHazelcastInstance().getMap(name); //returned map is a ConcurrentMap
+        HazelcastInstance instance = assertHazlecastInstance();
+        Map<K, V> map = instance.getMap(name); //returned map is a ConcurrentMap
         return new MapCache<K, V>(name, map);
     }
 
     /**
-     * Ensures that this implementation has a backing {@link HazelcastInstance}, and if not, implicitly creates one
-     * via {@link #createHazelcastInstance()}.
+     * Asserts that this implementation has a backing {@link HazelcastInstance}, and if not, throws a
+     * {@link CacheException}.
      *
-     * @return the backing (potentially newly created) {@code HazelcastInstance}.
-     * @see #createHazelcastInstance()
      * @see HazelcastInstance
      */
-    protected HazelcastInstance ensureHazelcastInstance() {
+    protected final HazelcastInstance assertHazlecastInstance() throws CacheException {
         if (this.hazelcastInstance == null) {
-            this.hazelcastInstance = createHazelcastInstance();
-            this.implicitlyCreated = true;
+            throw new CacheException("The " + getClass().getName() + " instance must be configured with a HazelcastInstance instance before it can be used.");
         }
         return this.hazelcastInstance;
     }
 
     /**
-     * Initializes this instance by {@link #ensureHazelcastInstance() ensuring} there is a backing
-     * {@link HazelcastInstance}.
+     * Asserts that a {@link #getHazelcastInstance() hazelcastInstance} has been specified.
      *
-     * @throws ShiroException
-     * @see #ensureHazelcastInstance()
+     * @throws ShiroException if the {@code hazelcastInstance} has not been specified.
      * @see HazelcastInstance
      */
     public void init() throws ShiroException {
-        ensureHazelcastInstance();
-    }
-
-    /**
-     * Implicitly creates and returns a new {@link HazelcastInstance} that will be used to back this implementation.
-     * This implementation calls:
-     * <pre>
-     * return Hazelcast.newHazelcastInstance(this.config);
-     * </pre>
-     * using any {@link #setConfig(com.hazelcast.config.Config) configured} {@code Config} object.  If no config
-     * object has been specified, {@code this.config} will be {@code null}, thereby using Hazelcast's
-     * <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">default configuration mechanism</a>.
-     * <p/>
-     * Can be overridden by subclasses for custom creation behavior.
-     *
-     * @return a new {@link HazelcastInstance} that will be used to back this implementation
-     * @see Hazelcast#newHazelcastInstance(com.hazelcast.config.Config)
-     * @see Config
-     */
-    protected HazelcastInstance createHazelcastInstance() {
-        return Hazelcast.newHazelcastInstance(this.config);
-    }
-
-    //needed for unit tests only - not part of Shiro's public API
-
-    /**
-     * NOT PART OF SHIRO'S ACCESSIBLE API.  DO NOT DEPEND ON THIS.  This method was added for testing purposes only.
-     * <p/>
-     * Returns {@code true} if this {@code HazelcastCacheManager} instance implicitly created the backing
-     * {@code HazelcastInstance}, or {@code false} if one was externally provided via
-     * {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) setHazelcastInstance}.
-     *
-     * @return {@code true} if this {@code HazelcastCacheManager} instance implicitly created the backing
-     *         {@code HazelcastInstance}, or {@code false} if one was externally provided via
-     *         {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) setHazelcastInstance}.
-     */
-    protected final boolean isImplicitlyCreated() {
-        return this.implicitlyCreated;
-    }
-
-    /**
-     * Destroys any {@link #ensureHazelcastInstance() implicitly created} backing {@code HazelcastInstance}.  If the
-     * backing Hazelcast was not implicitly created (i.e. because it was configured externally and supplied via
-     * {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) setHazelcastInstance}), this method does
-     * nothing.
-     *
-     * @throws Exception if there is a problem shutting down
-     */
-    public void destroy() throws Exception {
-        if (this.implicitlyCreated) {
-            try {
-                this.hazelcastInstance.getLifecycleService().shutdown();
-            } catch (Throwable t) {
-                if (log.isWarnEnabled()) {
-                    log.warn("Unable to cleanly shutdown implicitly created HazelcastInstance.  " +
-                            "Ignoring (shutting down)...", t);
-                }
-            } finally {
-                this.hazelcastInstance = null;
-                this.implicitlyCreated = false;
-            }
-        }
+        assertHazlecastInstance();
     }
 
     /**
@@ -211,35 +145,4 @@ public class HazelcastCacheManager imple
     public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
         this.hazelcastInstance = hazelcastInstance;
     }
-
-    /**
-     * Returns the Hazelcast {@code Config} object to use to create a backing {@code HazelcastInstance} if one is not
-     * {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) supplied}, or {@code null} if the
-     * default <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">Hazelcast configuration
-     * mechanisms</a> will be used.
-     *
-     * @return the Hazelcast {@code Config} object to use to create a backing {@code HazelcastInstance} if one is not
-     *         {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) supplied}, or {@code null} if the
-     *         default <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">Hazelcast configuration
-     *         mechanisms</a> will be used.
-     * @see Hazelcast#newHazelcastInstance(com.hazelcast.config.Config)
-     */
-    public Config getConfig() {
-        return config;
-    }
-
-    /**
-     * Sets the Hazelcast {@code Config} object to use to create a backing {@code HazelcastInstance} if one is not
-     * {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) supplied}.  {@code null} can be set if the
-     * default <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">Hazelcast configuration
-     * mechanisms</a> will be used.
-     *
-     * @param config the Hazelcast {@code Config} object to use to create a backing {@code HazelcastInstance} if one is not
-     *               {@link #setHazelcastInstance(com.hazelcast.core.HazelcastInstance) supplied}, or {@code null} if the
-     *               default <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch12.html">Hazelcast configuration
-     *               mechanisms</a> will be used.
-     */
-    public void setConfig(Config config) {
-        this.config = config;
-    }
 }

Added: shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactoryTest.groovy
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactoryTest.groovy?rev=1555436&view=auto
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactoryTest.groovy (added)
+++ shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/ClientHazelcastInstanceFactoryTest.groovy Sun Jan  5 00:01:21 2014
@@ -0,0 +1,60 @@
+package org.apache.shiro.hazelcast
+
+import com.hazelcast.client.HazelcastClient
+import com.hazelcast.client.config.ClientConfig
+import com.hazelcast.core.HazelcastInstance
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.powermock.core.classloader.annotations.PrepareForTest
+import org.powermock.modules.junit4.PowerMockRunner
+
+import static org.easymock.EasyMock.expect
+import static org.easymock.EasyMock.same
+import static org.junit.Assert.*
+import static org.powermock.api.easymock.PowerMock.*
+
+@RunWith(PowerMockRunner)
+@PrepareForTest(HazelcastClient)
+class ClientHazelcastInstanceFactoryTest {
+
+    ClientHazelcastInstanceFactory factory
+
+    @Before
+    void setUp() {
+        factory = new ClientHazelcastInstanceFactory()
+    }
+
+    @Test
+    void testNew() {
+        assertNotNull factory.config
+        assertTrue factory.config instanceof ClientConfig
+        factory.destroy()
+    }
+
+    @Test
+    void testGetInstance() {
+
+        mockStatic(HazelcastClient)
+
+        def hc = createStrictMock(HazelcastInstance)
+        def config = createStrictMock(ClientConfig)
+
+        factory.config = config
+
+        //create a mock instead of starting a networked node:
+        expect(HazelcastClient.newHazelcastClient(same(config))).andReturn(hc)
+
+        replay HazelcastClient, hc, config
+
+        try {
+            def instance = factory.getInstance()
+
+            assertNotNull instance
+            assertSame instance, hc
+
+        } finally {
+            verify HazelcastClient, hc, config
+        }
+    }
+}

Added: shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactoryTest.groovy
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactoryTest.groovy?rev=1555436&view=auto
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactoryTest.groovy (added)
+++ shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/EmbeddedHazelcastInstanceFactoryTest.groovy Sun Jan  5 00:01:21 2014
@@ -0,0 +1,60 @@
+package org.apache.shiro.hazelcast
+
+import com.hazelcast.config.Config
+import com.hazelcast.core.Hazelcast
+import com.hazelcast.core.HazelcastInstance
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.powermock.core.classloader.annotations.PrepareForTest
+import org.powermock.modules.junit4.PowerMockRunner
+
+import static org.easymock.EasyMock.expect
+import static org.easymock.EasyMock.same
+import static org.junit.Assert.*
+import static org.powermock.api.easymock.PowerMock.*
+
+@RunWith(PowerMockRunner)
+@PrepareForTest(Hazelcast)
+class EmbeddedHazelcastInstanceFactoryTest {
+
+    EmbeddedHazelcastInstanceFactory factory
+
+    @Before
+    void setUp() {
+        factory = new EmbeddedHazelcastInstanceFactory()
+    }
+
+    @Test
+    void testNew() {
+        assertNotNull factory.config
+        assertTrue factory.config instanceof Config
+        factory.destroy()
+    }
+
+    @Test
+    void testGetInstance() {
+
+        mockStatic(Hazelcast)
+
+        def hc = createStrictMock(HazelcastInstance)
+        def config = createStrictMock(Config)
+
+        factory.config = config
+
+        //create a mock instead of starting a networked node:
+        expect(Hazelcast.newHazelcastInstance(same(config))).andReturn(hc)
+
+        replay Hazelcast, hc, config
+
+        try {
+            def instance = factory.getInstance()
+
+            assertNotNull instance
+            assertSame instance, hc
+
+        } finally {
+            verify Hazelcast, hc, config
+        }
+    }
+}

Added: shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/HazelcastInstanceFactoryTest.groovy
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/HazelcastInstanceFactoryTest.groovy?rev=1555436&view=auto
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/HazelcastInstanceFactoryTest.groovy (added)
+++ shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/HazelcastInstanceFactoryTest.groovy Sun Jan  5 00:01:21 2014
@@ -0,0 +1,125 @@
+package org.apache.shiro.hazelcast
+
+import com.hazelcast.core.HazelcastInstance
+import com.hazelcast.core.LifecycleService
+import org.junit.Test
+
+import static org.easymock.EasyMock.*
+import static org.junit.Assert.assertEquals
+import static org.junit.Assert.assertSame
+
+class HazelcastInstanceFactoryTest {
+
+    HazelcastInstanceFactory factory
+
+    @Test
+    void testInit() {
+
+        def hc = createStrictMock(HazelcastInstance)
+
+        factory = new HazelcastInstanceFactory() {
+            @Override
+            protected HazelcastInstance createInstance() {
+                return hc;
+            }
+        }
+
+        replay hc
+
+        factory.init();
+
+        def instance = factory.getInstance()
+
+        assertSame instance, hc
+
+        verify hc
+    }
+
+    @Test
+    void testGetInstance() {
+
+        def hc = createStrictMock(HazelcastInstance)
+        int callCount = 0
+
+        factory = new HazelcastInstanceFactory() {
+            @Override
+            protected HazelcastInstance createInstance() {
+                callCount++
+                return hc;
+            }
+        }
+
+        replay hc
+
+        def instance = factory.getInstance();
+
+        assertSame instance, hc
+        assertEquals 1, callCount
+
+        //check that it does not create a new instance:
+        instance = factory.getInstance()
+        assertSame instance, hc
+        assertEquals 1, callCount
+
+        verify hc
+    }
+
+    @Test
+    void testDestroy() {
+
+        def hc = createStrictMock(HazelcastInstance)
+
+        factory = new HazelcastInstanceFactory() {
+            @Override
+            protected HazelcastInstance createInstance() {
+                return hc;
+            }
+        }
+
+        def ls = createStrictMock(LifecycleService)
+
+        expect(hc.getLifecycleService()).andStubReturn(ls)
+        ls.shutdown()
+
+        replay hc, ls
+
+        def instance = factory.getInstance();
+
+        assertSame instance, hc
+
+        factory.destroy()
+
+        verify hc, ls
+
+    }
+
+    @Test
+    void testDestroyWithException() {
+
+        def hc = createStrictMock(HazelcastInstance)
+
+        factory = new HazelcastInstanceFactory() {
+            @Override
+            protected HazelcastInstance createInstance() {
+                return hc;
+            }
+        }
+
+        def ls = createStrictMock(LifecycleService)
+
+        expect(hc.getLifecycleService()).andStubReturn(ls)
+        ls.shutdown()
+        expectLastCall().andThrow(new IllegalStateException("foo"))
+
+        replay hc, ls
+
+        def instance = factory.getInstance();
+
+        assertSame instance, hc
+
+        factory.destroy()
+
+        verify hc, ls
+    }
+
+}

Modified: shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/cache/HazelcastCacheManagerTest.groovy
URL: http://svn.apache.org/viewvc/shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/cache/HazelcastCacheManagerTest.groovy?rev=1555436&r1=1555435&r2=1555436&view=diff
==============================================================================
--- shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/cache/HazelcastCacheManagerTest.groovy (original)
+++ shiro/branches/1.x/support/hazelcast/src/test/groovy/org/apache/shiro/hazelcast/cache/HazelcastCacheManagerTest.groovy Sun Jan  5 00:01:21 2014
@@ -18,165 +18,106 @@
  */
 package org.apache.shiro.hazelcast.cache
 
-import com.hazelcast.config.Config
-import com.hazelcast.core.Hazelcast
 import com.hazelcast.core.HazelcastInstance
 import com.hazelcast.core.IMap
-import com.hazelcast.core.LifecycleService
+import org.apache.shiro.cache.CacheException
 import org.apache.shiro.cache.MapCache
+import org.junit.Before
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.powermock.core.classloader.annotations.PrepareForTest
-import org.powermock.modules.junit4.PowerMockRunner
 
-import static org.easymock.EasyMock.expect
-import static org.easymock.EasyMock.same
+import static org.easymock.EasyMock.*
 import static org.junit.Assert.*
-import static org.powermock.api.easymock.PowerMock.*
 
 /**
  * Unit tests for {@link HazelcastCacheManager}.  Uses PowerMock to mock Hazelcast's static method calls.
  *
  * @since 1.3
  */
-@RunWith(PowerMockRunner)
-@PrepareForTest(Hazelcast)
 class HazelcastCacheManagerTest {
 
-    @Test
-    void testGetSetHazelcastInstance() {
-        def hc = createStrictMock(HazelcastInstance)
-        def manager = new HazelcastCacheManager();
-        manager.hazelcastInstance = hc
-
-        replay hc
-
-        assertSame hc, manager.hazelcastInstance
+    HazelcastCacheManager manager
 
-        verify hc
+    @Before
+    void setUp() {
+        manager = new HazelcastCacheManager()
     }
 
     @Test
-    void testInit() {
-
-        mockStatic(Hazelcast)
-        //create a mock instead of starting a networked node:
-        def hc = createStrictMock(HazelcastInstance)
-
-        expect(Hazelcast.newHazelcastInstance(null)).andReturn(hc)
-
-        replay Hazelcast, hc
-
-        def manager = new HazelcastCacheManager()
-
+    void testInitWithoutHazelcastInstance() {
         try {
             manager.init()
-
-            assertNull manager.config
-            assertSame hc, manager.hazelcastInstance
-            assertTrue manager.implicitlyCreated
-        } finally {
-            verify Hazelcast, hc
+            fail("CacheException expected.")
+        } catch (CacheException ce) {
+            assertEquals("The " + HazelcastCacheManager.class.getName() + " instance must be configured with a HazelcastInstance instance before it can be used.", ce.getMessage())
         }
     }
 
     @Test
-    void testDestroy() {
-
-        mockStatic Hazelcast
+    void testInit() {
         def hc = createStrictMock(HazelcastInstance)
-        def lcService = createStrictMock(LifecycleService)
 
-        expect(Hazelcast.newHazelcastInstance(null)).andReturn(hc)
-        expect(hc.getLifecycleService()).andReturn(lcService)
-        lcService.shutdown()
+        replay hc
+
+        manager.hazelcastInstance = hc
 
-        replay Hazelcast, hc, lcService
+        verify hc
+    }
 
-        def manager = new HazelcastCacheManager()
-        manager.init() //force implicit creation
+    @Test
+    void testSetHazelcastInstance() {
+        def hc = createStrictMock(HazelcastInstance)
 
-        manager.destroy()
+        replay hc
 
-        assertNull manager.hazelcastInstance
-        assertFalse manager.implicitlyCreated
+        manager.hazelcastInstance = hc
+        assertSame hc, manager.hazelcastInstance
 
-        verify Hazelcast, hc, lcService
+        verify hc
     }
 
     @Test
-    void testDestroyWithThrowable() {
-
-        mockStatic Hazelcast
+    void testGetSetHazelcastInstance() {
         def hc = createStrictMock(HazelcastInstance)
-        def lcService = createStrictMock(LifecycleService)
 
-        expect(Hazelcast.newHazelcastInstance(null)).andReturn(hc)
-        expect(hc.getLifecycleService()).andReturn(lcService)
-        lcService.shutdown()
-        expectLastCall().andThrow(new IllegalStateException())
-
-        replay Hazelcast, hc, lcService
-
-        def manager = new HazelcastCacheManager()
-        manager.init() //force implicit creation
+        manager.hazelcastInstance = hc
 
-        manager.destroy()
+        replay hc
 
-        assertNull manager.hazelcastInstance
-        assertFalse manager.implicitlyCreated
+        assertSame hc, manager.hazelcastInstance
 
-        verify Hazelcast, hc, lcService
+        verify hc
     }
 
+    @Test
+    void testGetCacheWithoutHazelcastInstance() {
+        try {
+            manager.getCache('foo')
+            fail("CacheException expected.")
+        } catch (CacheException ce) {
+            assertEquals("The " + HazelcastCacheManager.class.getName() + " instance must be configured with a HazelcastInstance instance before it can be used.", ce.getMessage())
+        }
+    }
 
     @Test
     void testGetCache() {
 
-        mockStatic Hazelcast
         def hc = createStrictMock(HazelcastInstance)
         def hcMap = createStrictMock(IMap)
 
-        expect(Hazelcast.newHazelcastInstance(null)).andReturn(hc)
-        expect(hc.getMap("foo")).andReturn(hcMap)
+        expect(hc.getMap(eq('foo'))).andReturn(hcMap)
 
-        replay Hazelcast, hc, hcMap
+        replay hc, hcMap
 
         try {
-            def manager = new HazelcastCacheManager()
-            def cache = manager.getCache("foo")
+            manager.hazelcastInstance = hc
+            def cache = manager.getCache('foo')
 
             assertNotNull cache
             assertTrue cache instanceof MapCache
             assertNotNull cache.map
-            assertTrue cache.map instanceof IMap
+            assertSame hcMap, cache.map
         } finally {
-            verify Hazelcast, hc, hcMap
+            verify hc, hcMap
         }
     }
-
-    @Test
-    void testCustomConfig() {
-
-        mockStatic Hazelcast
-
-        def hc = createStrictMock(HazelcastInstance)
-        def config = createStrictMock(Config)
-
-        expect(Hazelcast.newHazelcastInstance(same(config))).andReturn(hc)
-
-        replay Hazelcast, config
-
-        def manager = new HazelcastCacheManager()
-        manager.config = config
-
-        manager.init()
-
-        assertSame config, manager.config
-        assertSame hc, manager.hazelcastInstance
-
-        verify Hazelcast, config
-    }
-
-
 }