directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dran...@apache.org
Subject [1/2] directory-kerby git commit: DIRKRB-347 Extract cache facility from abstract class into a separate backend; Also refactored backend related codes
Date Wed, 08 Jul 2015 07:33:53 GMT
Repository: directory-kerby
Updated Branches:
  refs/heads/master 9af3d5884 -> f82e49764


DIRKRB-347 Extract cache facility from abstract class into a separate backend; Also refactored backend related codes


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/688fedff
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/688fedff
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/688fedff

Branch: refs/heads/master
Commit: 688fedfff5fc86232f8ff2998afe32a2a9126dd9
Parents: 6404ce5
Author: drankye <kai.zheng@intel.com>
Authored: Wed Jul 8 15:27:08 2015 +0800
Committer: Drankye <drankye@gmail.com>
Committed: Wed Jul 8 15:27:08 2015 +0800

----------------------------------------------------------------------
 .../identitybackend/JsonIdentityBackend.java    |  13 +-
 .../kerb/identity/backend/JsonBackendTest.java  |  33 +----
 .../identitybackend/LdapIdentityBackend.java    |  92 +++++++------
 .../AbstractLdapIdentityBackendTest.java        |  53 ++++++--
 .../DirectoryLdapIdentityBackendTest.java       |  39 +-----
 .../backend/LdapIdentityBackendTest.java        |  40 +-----
 .../java/org/apache/kerby/MavibotBackend.java   |  85 +++++-------
 .../org/apache/kerby/MavibotBackendTest.java    |  31 ++---
 .../ZookeeperIdentityBackend.java               |  74 +++++------
 .../identity/backend/ZookeeperBackendTest.java  |  43 +-----
 .../kerberos/kdc/impl/NettyKdcServerImpl.java   |   2 +-
 .../kerb/identity/backend/BackendTest.java      |  25 +---
 .../kerb/identity/backend/BackendTestBase.java  |  73 ++++++++++
 .../kerb/identity/CacheableIdentityService.java | 128 ++++++++++++++++++
 .../kerberos/kerb/identity/IdentityService.java |  12 +-
 .../backend/AbstractIdentityBackend.java        | 133 ++++++++++++-------
 .../kerb/identity/backend/IdentityBackend.java  |   5 +-
 .../identity/backend/MemoryIdentityBackend.java |  39 ++++--
 .../server/impl/AbstractInternalKdcServer.java  |  16 ++-
 .../impl/DefaultInternalKdcServerImpl.java      |   2 +-
 20 files changed, 525 insertions(+), 413 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
index 7c28d6c..291756b 100644
--- a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/JsonIdentityBackend.java
@@ -26,6 +26,7 @@ import org.apache.kerby.config.Config;
 import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.EncryptionKeyAdapter;
 import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.KerberosTimeAdapter;
 import org.apache.kerby.kerberos.kdc.identitybackend.typeAdapter.PrincipalNameAdapter;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
 import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
@@ -52,6 +53,7 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
     private long kdbFileTimeStamp;
 
     public JsonIdentityBackend() {
+
     }
 
     /**
@@ -67,8 +69,7 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public void initialize() {
-        super.initialize();
+    protected void doInitialize() throws KrbException {
         createGson();
         load();
     }
@@ -76,10 +77,10 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
     /**
      * Load identities from file
      */
-    public void load() {
+    private void load() throws KrbException {
         String jsonFile = getConfig().getString(JSON_IDENTITY_BACKEND_FILE);
         if (jsonFile == null || jsonFile.isEmpty()) {
-            throw new RuntimeException("No json kdb file is found");
+            throw new KrbException("No json kdb file is found");
         }
 
         jsonKdbFile = new File(jsonFile);
@@ -180,8 +181,8 @@ public class JsonIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public List<String> getIdentities(int start, int limit) {
-        List<String> principals =getIdentities();
+    protected List<String> doGetIdentities(int start, int limit) throws KrbException {
+        List<String> principals = getIdentities();
 
         if (limit == -1) {
             return principals;

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java b/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
index 777d8bc..5981d51 100644
--- a/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
+++ b/kerby-backend/json-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/JsonBackendTest.java
@@ -22,6 +22,7 @@ package org.apache.kerby.kerberos.kerb.identity.backend;
 import org.apache.kerby.config.Conf;
 import org.apache.kerby.config.Config;
 import org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -31,12 +32,11 @@ import java.io.File;
 /**
  * Json backend test
  */
-public class JsonBackendTest extends BackendTest {
-    private static IdentityBackend backend;
+public class JsonBackendTest extends BackendTestBase {
     private static File jsonBackendFile;
 
     @BeforeClass
-    public static void setup() {
+    public static void setup() throws KrbException {
         File testDir = new File(System.getProperty("test.dir", "target"));
         jsonBackendFile = new File(testDir, "json-identity-backend-file");
         String jsonBackendFileString = jsonBackendFile.getAbsolutePath();
@@ -48,33 +48,8 @@ public class JsonBackendTest extends BackendTest {
         backend.initialize();
     }
 
-    @Test
-    public void testGet() {
-        super.testGet(backend);
-    }
-
-    @Test
-    public void testStore() {
-        super.testStore(backend);
-    }
-
-    @Test
-    public void testUpdate() {
-        super.testUpdate(backend);
-    }
-
-    @Test
-    public void testDelete() {
-        super.testDelete(backend);
-    }
-
-    @Test
-    public void testGetIdentities() {
-        super.testGetIdentities(backend);
-    }
-
     @AfterClass
-    public static void rmJsonBackendFile() {
+    public static void cleanJsonBackendFile() {
         if (jsonBackendFile.exists()) {
             jsonBackendFile.delete();
         }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java b/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
index 360aeaa..0c55080 100644
--- a/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
+++ b/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
@@ -35,6 +35,7 @@ import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.shared.kerberos.KerberosAttribute;
 import org.apache.kerby.config.Config;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
 import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
@@ -50,12 +51,12 @@ import java.util.Map;
 
 /**
  * An LDAP based backend implementation.
- *
  */
 public class LdapIdentityBackend extends AbstractIdentityBackend {
     //The LdapConnection, may be LdapNetworkConnection or LdapCoreSessionConnection
     private LdapConnection connection;
-    //This is used as a flag to represent the connection whether is LdapNetworkConnection object or not
+    //This is used as a flag to represent the connection whether is
+    // LdapNetworkConnection object or not
     private boolean isLdapNetworkConnection;
 
     public LdapIdentityBackend() {
@@ -73,13 +74,14 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
     }
 
     /**
-     * Constructing an instance using a LdapConnection and a specified config that contains anything
-     * to be used to initialize a necessary baseDn.
-     * @param config,connection .The config is used to config the backend, and the connection is used to
-     *                          to handle add/delete/update/get operations, may be a LdapNetworkConnection
-     *                          or a LdapCoreSessionConnection.
+     * Constructing an instance using a LdapConnection and a specified config
+     * that contains anything to be used to initialize a necessary baseDn.
+     * @param config The config is used to config the backend
+     * @param connection The connection to be used to handle the operations,
+     *                   may be a LdapNetworkConnection or a LdapCoreSessionConnection.
      */
-    public LdapIdentityBackend(Config config, LdapConnection connection) throws LdapException {
+    public LdapIdentityBackend(Config config,
+                               LdapConnection connection) {
         setConfig(config);
         this.connection = connection;
     }
@@ -87,7 +89,7 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
     /**
      * Start the connection for the initialize()
      */
-    public void startConnection() throws LdapException {
+    private void startConnection() throws LdapException {
         if (isLdapNetworkConnection == true) {
             this.connection = new LdapNetworkConnection(getConfig().getString("host"),
                     getConfig().getInt("port"));
@@ -100,12 +102,11 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public void initialize() {
-        super.initialize();
+    protected void doInitialize() throws KrbException {
         try {
             startConnection();
         } catch (LdapException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to start connection with LDAP", e);
         }
     }
 
@@ -113,22 +114,20 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public void stop() {
+    protected void doStop() throws KrbException {
         try {
             closeConnection();
-        } catch (LdapException e) {
-            e.printStackTrace();
         } catch (IOException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to close connection with LDAP", e);
         }
     }
 
     /**
      * Close the connection for stop()
      */
-    public void closeConnection() throws LdapException, IOException {
-        if (this.connection.isConnected()) {
-            this.connection.close();
+    private void closeConnection() throws IOException {
+        if (connection.isConnected()) {
+            connection.close();
         }
     }
 
@@ -180,7 +179,7 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doAddIdentity(KrbIdentity identity) {
+    protected KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException {
         String principalName = identity.getPrincipalName();
         String[] names = principalName.split("@");
         Entry entry = new DefaultEntry();
@@ -188,27 +187,29 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
         try {
             Dn dn = toDn(principalName);
             entry.setDn(dn);
-            entry.add("objectClass", "top", "person", "inetOrgPerson", "krb5principal", "krb5kdcentry");
+            entry.add("objectClass", "top", "person", "inetOrgPerson",
+                    "krb5principal", "krb5kdcentry");
             entry.add("cn", names[0]);
             entry.add( "sn", names[0]);
             entry.add(KerberosAttribute.KRB5_KEY_AT, keysInfo.getKeys());
             entry.add( "krb5EncryptionType", keysInfo.getEtypes());
             entry.add( KerberosAttribute.KRB5_PRINCIPAL_NAME_AT, principalName);
-            entry.add( KerberosAttribute.KRB5_KEY_VERSION_NUMBER_AT, identity.getKeyVersion() + "");
+            entry.add( KerberosAttribute.KRB5_KEY_VERSION_NUMBER_AT,
+                    identity.getKeyVersion() + "");
             entry.add( "krb5KDCFlags", "" + identity.getKdcFlags());
-            entry.add( KerberosAttribute.KRB5_ACCOUNT_DISABLED_AT, "" + identity.isDisabled());
+            entry.add( KerberosAttribute.KRB5_ACCOUNT_DISABLED_AT, "" +
+                    identity.isDisabled());
             entry.add( "createTimestamp",
                     toGeneralizedTime(identity.getCreatedTime()));
-            entry.add(KerberosAttribute.KRB5_ACCOUNT_LOCKEDOUT_AT, "" + identity.isLocked());
+            entry.add(KerberosAttribute.KRB5_ACCOUNT_LOCKEDOUT_AT, "" +
+                    identity.isLocked());
             entry.add( KerberosAttribute.KRB5_ACCOUNT_EXPIRATION_TIME_AT,
                     toGeneralizedTime(identity.getExpireTime()));
             connection.add(entry);
         } catch (LdapInvalidDnException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to add identity", e);
         } catch (LdapException e) {
-            e.printStackTrace();
-        } catch (Exception e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to add identity", e);
         }
         return identity;
     }
@@ -217,7 +218,7 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doGetIdentity(String principalName) {
+    protected KrbIdentity doGetIdentity(String principalName) throws KrbException {
         KrbIdentity krbIdentity = new KrbIdentity(principalName);
         try {
             Dn dn = toDn(principalName);
@@ -235,12 +236,13 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
             krbIdentity.setKdcFlags(getHelper.getKdcFlags());
             krbIdentity.setLocked(getHelper.getLocked());
         } catch (LdapException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to retrieve identity", e);
         } catch (ParseException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to retrieve identity", e);
         } catch (IOException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to retrieve identity", e);
         }
+
         return krbIdentity;
     }
 
@@ -248,25 +250,31 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) {
+    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException {
         String principalName = identity.getPrincipalName();
         KeysInfo keysInfo = new KeysInfo(identity);
         try {
             Dn dn = toDn(principalName);
             ModifyRequest modifyRequest = new ModifyRequestImpl();
             modifyRequest.setName(dn);
-            modifyRequest.replace(KerberosAttribute.KRB5_KEY_VERSION_NUMBER_AT, "" + identity.getKeyVersion());
+            modifyRequest.replace(KerberosAttribute.KRB5_KEY_VERSION_NUMBER_AT,
+                    "" + identity.getKeyVersion());
             modifyRequest.replace(KerberosAttribute.KRB5_KEY_AT, keysInfo.getKeys());
             modifyRequest.replace("krb5EncryptionType", keysInfo.getEtypes());
-            modifyRequest.replace(KerberosAttribute.KRB5_PRINCIPAL_NAME_AT, identity.getPrincipalName());
-            modifyRequest.replace(KerberosAttribute.KRB5_ACCOUNT_EXPIRATION_TIME_AT, toGeneralizedTime(identity.getExpireTime()));
-            modifyRequest.replace(KerberosAttribute.KRB5_ACCOUNT_DISABLED_AT, "" + identity.isDisabled());
+            modifyRequest.replace(KerberosAttribute.KRB5_PRINCIPAL_NAME_AT,
+                    identity.getPrincipalName());
+            modifyRequest.replace(KerberosAttribute.KRB5_ACCOUNT_EXPIRATION_TIME_AT,
+                    toGeneralizedTime(identity.getExpireTime()));
+            modifyRequest.replace(KerberosAttribute.KRB5_ACCOUNT_DISABLED_AT, "" +
+                    identity.isDisabled());
             modifyRequest.replace("krb5KDCFlags", "" + identity.getKdcFlags());
-            modifyRequest.replace(KerberosAttribute.KRB5_ACCOUNT_LOCKEDOUT_AT, "" + identity.isLocked());
+            modifyRequest.replace(KerberosAttribute.KRB5_ACCOUNT_LOCKEDOUT_AT, "" +
+                    identity.isLocked());
             connection.modify(modifyRequest);
         } catch (LdapException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to update identity", e);
         }
+
         return identity;
     }
 
@@ -274,12 +282,12 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected void doDeleteIdentity(String principalName) {
+    protected void doDeleteIdentity(String principalName) throws KrbException {
         try {
             Dn dn = toDn(principalName);
             connection.delete(dn);
         } catch (LdapException e) {
-            e.printStackTrace();
+            throw new KrbException("Failed to remove identity", e);
         }
     }
 
@@ -300,7 +308,7 @@ public class LdapIdentityBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public List<String> getIdentities(int start, int limit) {
+    protected List<String> doGetIdentities(int start, int limit) {
         List<String> identities = getIdentities();
 
         if (limit == -1) {

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractLdapIdentityBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractLdapIdentityBackendTest.java b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractLdapIdentityBackendTest.java
index 924dea2..0ceb963 100644
--- a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractLdapIdentityBackendTest.java
+++ b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractLdapIdentityBackendTest.java
@@ -21,35 +21,64 @@ package org.apache.kerby.kerberos.kerb.identity.backend;
 
 import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.ldap.LdapServer;
+import org.apache.kerby.kerberos.kdc.identitybackend.LdapIdentityBackend;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.junit.After;
+import org.junit.Test;
+
+public abstract class AbstractLdapIdentityBackendTest extends  BackendTest {
+    protected LdapIdentityBackend backend;
 
-public abstract class AbstractLdapIdentityBackendTest extends  BackendTest
-{
     /** The used DirectoryService instance */
     private static DirectoryService service;
 
     /** The used LdapServer instance */
     private static LdapServer ldapServer;
 
-    public static DirectoryService getService()
-    {
+    public static DirectoryService getService() {
         return service;
     }
 
-
-    public static void setService( DirectoryService service )
-    {
+    public static void setService( DirectoryService service ) {
         AbstractLdapIdentityBackendTest.service = service;
     }
 
-
-    public static LdapServer getLdapServer()
-    {
+    public static LdapServer getLdapServer() {
         return ldapServer;
     }
 
-    public static void setLdapServer( LdapServer ldapServer )
-    {
+    public static void setLdapServer( LdapServer ldapServer ) {
         AbstractLdapIdentityBackendTest.ldapServer = ldapServer;
     }
 
+    @After
+    public void tearDown() throws Exception {
+        backend.stop();
+        backend.release();
+    }
+
+    @Test
+    public void testGet() throws KrbException {
+        testGet(backend);
+    }
+
+    @Test
+    public void testStore() throws KrbException {
+        testStore(backend);
+    }
+
+    @Test
+    public void testUpdate() throws KrbException {
+        testUpdate(backend);
+    }
+
+    @Test
+    public void testDelete() throws KrbException {
+        testDelete(backend);
+    }
+
+    @Test
+    public void testGetIdentities() throws KrbException {
+        testGetIdentities(backend);
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/DirectoryLdapIdentityBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/DirectoryLdapIdentityBackendTest.java b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/DirectoryLdapIdentityBackendTest.java
index 786ad27..e667db9 100644
--- a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/DirectoryLdapIdentityBackendTest.java
+++ b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/DirectoryLdapIdentityBackendTest.java
@@ -29,9 +29,7 @@ import org.apache.directory.server.core.api.LdapCoreSessionConnection;
 import org.apache.directory.server.core.integ.FrameworkRunner;
 import org.apache.kerby.config.Conf;
 import org.apache.kerby.kerberos.kdc.identitybackend.LdapIdentityBackend;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(FrameworkRunner.class)
@@ -59,9 +57,7 @@ import org.junit.runner.RunWith;
                 "ou: users"
         }
 )
-public class DirectoryLdapIdentityBackendTest extends AbstractLdapIdentityBackendTest
-{
-    private LdapIdentityBackend backend;
+public class DirectoryLdapIdentityBackendTest extends AbstractLdapIdentityBackendTest {
     private static final String BASE_DN = "ou=users,dc=example,dc=com";
     private static final String ADMIN_DN = "uid=admin,ou=system";
     private static final String ADMIN_PW = "secret";
@@ -74,39 +70,8 @@ public class DirectoryLdapIdentityBackendTest extends AbstractLdapIdentityBacken
         config.setString("admin_pw", ADMIN_PW);
         config.setString("base_dn", BASE_DN);
         LdapConnection connection = new LdapCoreSessionConnection(getService());
-        this.backend = new LdapIdentityBackend(config, connection);
+        backend = new LdapIdentityBackend(config, connection);
         backend.initialize();
         backend.start();
     }
-
-    @After
-    public void tearDown() throws Exception {
-        backend.stop();
-        backend.release();
-    }
-
-    @Test
-    public void testGet() {
-        super.testGet(backend);
-    }
-
-    @Test
-    public void testStore() {
-        super.testStore(backend);
-    }
-
-    @Test
-    public void testUpdate() {
-        super.testUpdate(backend);
-    }
-
-    @Test
-    public void testDelete() {
-        super.testDelete(backend);
-    }
-
-    @Test
-    public void testGetIdentities() {
-        super.testGetIdentities(backend);
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapIdentityBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapIdentityBackendTest.java b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapIdentityBackendTest.java
index 5761845..83ca85a 100644
--- a/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapIdentityBackendTest.java
+++ b/kerby-backend/ldap-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/LdapIdentityBackendTest.java
@@ -27,9 +27,7 @@ import org.apache.directory.server.core.annotations.CreatePartition;
 import org.apache.directory.server.core.integ.FrameworkRunner;
 import org.apache.kerby.config.Conf;
 import org.apache.kerby.kerberos.kdc.identitybackend.LdapIdentityBackend;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(FrameworkRunner.class)
@@ -57,14 +55,11 @@ import org.junit.runner.RunWith;
                 "ou: users"
         }
 )
-public class LdapIdentityBackendTest extends AbstractLdapIdentityBackendTest
-{
+public class LdapIdentityBackendTest extends AbstractLdapIdentityBackendTest {
     private static final String BASE_DN = "ou=users,dc=example,dc=com";
     private static final String ADMIN_DN = "uid=admin,ou=system";
     private static final String ADMIN_PW = "secret";
 
-    private LdapIdentityBackend backend;
-
     @Before
     public void setUp() throws Exception {
         Conf config = new Conf();
@@ -73,39 +68,8 @@ public class LdapIdentityBackendTest extends AbstractLdapIdentityBackendTest
         config.setString("admin_dn", ADMIN_DN);
         config.setString("admin_pw", ADMIN_PW);
         config.setString("base_dn", BASE_DN);
-        this.backend = new LdapIdentityBackend(config);
+        backend = new LdapIdentityBackend(config);
         backend.initialize();
         backend.start();
     }
-
-    @After
-    public void tearDown() throws Exception {
-        backend.stop();
-        backend.release();
-    }
-
-    @Test
-    public void testGet() {
-        super.testGet(backend);
-    }
-
-    @Test
-    public void testStore() {
-        super.testStore(backend);
-    }
-
-    @Test
-    public void testUpdate() {
-        super.testUpdate(backend);
-    }
-
-    @Test
-    public void testDelete() {
-        super.testDelete(backend);
-    }
-
-    @Test
-    public void testGetIdentities() {
-        super.testGetIdentities(backend);
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/mavibot/src/main/java/org/apache/kerby/MavibotBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/mavibot/src/main/java/org/apache/kerby/MavibotBackend.java b/kerby-backend/mavibot/src/main/java/org/apache/kerby/MavibotBackend.java
index 27068c2..f78f75a 100644
--- a/kerby-backend/mavibot/src/main/java/org/apache/kerby/MavibotBackend.java
+++ b/kerby-backend/mavibot/src/main/java/org/apache/kerby/MavibotBackend.java
@@ -22,6 +22,7 @@ package org.apache.kerby;
 import org.apache.directory.mavibot.btree.*;
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
 import org.slf4j.Logger;
@@ -78,7 +79,8 @@ public class MavibotBackend extends AbstractIdentityBackend {
         if (rm.getManagedTrees().contains(DATA_TREE)) {
             database = rm.getManagedTree(DATA_TREE);
         } else {
-            PersistedBTreeConfiguration<String, KrbIdentity> config = new PersistedBTreeConfiguration<String, KrbIdentity>();
+            PersistedBTreeConfiguration<String, KrbIdentity> config = 
+                    new PersistedBTreeConfiguration<String, KrbIdentity>();
             // _no_ duplicates
             config.setAllowDuplicates(false);
             config.setBtreeType(BTreeTypeEnum.PERSISTED);
@@ -96,27 +98,23 @@ public class MavibotBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public List<String> getIdentities(int start, int limit) {
-        
+    protected List<String> doGetIdentities(int start, int limit) throws KrbException {
         List<String> keys = new ArrayList<String>();
-        
         KeyCursor<String> cursor = null;
-        
+
         try {
             cursor = database.browseKeys();
             while(cursor.hasNext()) {
                 keys.add(cursor.next());
             }
-        }
-        catch(Exception e) {
-            LOG.debug("Errors occurred while fetching the principals", e);
-        }
-        finally {
+        } catch(Exception e) {
+            throw new KrbException("Errors occurred while fetching the principals", e);
+        } finally {
             if(cursor != null) {
                 cursor.close();
             }
         }
-        
+
         return keys;
     }
 
@@ -124,45 +122,33 @@ public class MavibotBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doGetIdentity(String principalName) {
-        
+    protected KrbIdentity doGetIdentity(String principalName) throws KrbException {
         try {
             return database.get(principalName);
-        }
-        catch(KeyNotFoundException e) {
+        } catch(KeyNotFoundException e) {
             LOG.debug("Identity {} doesn't exist", principalName);
+            return null;
+        } catch(IOException e) {
+            throw new KrbException("Failed to get the identity " + principalName);
         }
-        catch(IOException e) {
-            LOG.warn("Failed to get the identity {}", principalName);
-            throw new RuntimeException(e);
-        }
-        
-        return null;
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    protected synchronized KrbIdentity doAddIdentity(KrbIdentity identity) {
-        
+    protected synchronized KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException {
         String p = identity.getPrincipalName();
         try {
             if(database.hasKey(p)) {
-                LOG.debug("Identity {} already exists", p);
-                return null;
+                throw new KrbException("Identity already exists " + p);
             }
             
             return database.insert(p, identity);
-        }
-        catch(KeyNotFoundException e) {
-            LOG.debug("No such identity {} exists", p);
-            LOG.debug("", e);
-            return null;
-        }
-        catch(IOException e) {
-            LOG.warn("Failed to add the identity {}", p);
-            throw new RuntimeException(e);
+        } catch(KeyNotFoundException e) {
+            throw new KrbException("No such identity exists " + p);
+        } catch(IOException e) {
+            throw new KrbException("Failed to add the identity " + p);
         }
     }
 
@@ -170,22 +156,18 @@ public class MavibotBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected synchronized KrbIdentity doUpdateIdentity(KrbIdentity identity) {
-        
+    protected synchronized KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException {
         String p = identity.getPrincipalName();
         try {
             if(!database.hasKey(p)) {
-                LOG.debug("No identity found with the principal {}", p);
-                return null;
+                throw new KrbException("No identity found with the principal " + p);
             }
             
             database.delete(p);
             
             return database.insert(p, identity);
-        }
-        catch(Exception e) {
-            LOG.warn("Failed to update the identity {}", p);
-            throw new RuntimeException(e);
+        } catch(Exception e) {
+            throw new KrbException("Failed to update the identity " + p);
         }
     }
 
@@ -193,17 +175,14 @@ public class MavibotBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    protected void doDeleteIdentity(String principalName) {
-
+    protected void doDeleteIdentity(String principalName) throws KrbException {
         try {
             Tuple<String, KrbIdentity> t = database.delete(principalName);
             if (t == null) {
-                LOG.debug("Identity {} doesn't exist", principalName);
+                throw new KrbException("Not existing, identity = " + principalName);
             }
-        }
-        catch(IOException e) {
-            LOG.warn("Failed to delete the identity {}", principalName);
-            throw new RuntimeException(e);
+        } catch(IOException e) {
+            throw new KrbException("Failed to delete the identity " + principalName);
         }
     }
 
@@ -211,13 +190,11 @@ public class MavibotBackend extends AbstractIdentityBackend {
      * {@inheritDoc}
      */
     @Override
-    public void stop() {
+    protected void doStop() throws KrbException {
         try {
-            LOG.debug("Closing the database");
             rm.close();
-        }
-        catch(Exception e) {
-            LOG.warn("Failed to close the database", e);
+        } catch(IOException e) {
+            throw new KrbException("Failed to close the database", e);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/mavibot/src/test/java/org/apache/kerby/MavibotBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/mavibot/src/test/java/org/apache/kerby/MavibotBackendTest.java b/kerby-backend/mavibot/src/test/java/org/apache/kerby/MavibotBackendTest.java
index f21600c..8cd041c 100644
--- a/kerby-backend/mavibot/src/test/java/org/apache/kerby/MavibotBackendTest.java
+++ b/kerby-backend/mavibot/src/test/java/org/apache/kerby/MavibotBackendTest.java
@@ -23,14 +23,15 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.List;
 
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.identity.backend.BackendTest;
+import org.apache.kerby.kerberos.kerb.identity.backend.BackendTestBase;
 import org.apache.kerby.kerberos.kerb.identity.backend.IdentityBackend;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.*;
 import org.junit.rules.TemporaryFolder;
 
 /**
@@ -38,14 +39,11 @@ import org.junit.rules.TemporaryFolder;
  *
  * @author <a href="mailto:kerby@directory.apache.org">Apache Kerby Project</a>
  */
-public class MavibotBackendTest extends BackendTest {
+public class MavibotBackendTest extends BackendTestBase {
+    private static TemporaryFolder tmpFolder = new TemporaryFolder();
 
-    private MavibotBackend backend;
-    
-    private TemporaryFolder tmpFolder = new TemporaryFolder();
-    
-    @Before
-    public void setup() throws Exception {
+    @BeforeClass
+    public static void setup() throws Exception {
         tmpFolder.create();
         
         File dbFile = tmpFolder.newFile();
@@ -53,19 +51,14 @@ public class MavibotBackendTest extends BackendTest {
         backend.initialize();
     }
     
-    @After
-    public void clean() {
-        backend.stop();
+    @AfterClass
+    public static void tearDown() throws KrbException {
         tmpFolder.delete();
     }
-    
-    @Test
-    public void testBackend() {
-        super.testAll(backend);
-    }
 
     // overriding this cause MavibotBackend doesn't support range search
-    public void testGetIdentities(IdentityBackend backend) {
+    @Override
+    protected void testGetIdentities(IdentityBackend backend) throws KrbException {
         KrbIdentity[] identities = createManyIdentities();
 
         for (KrbIdentity identity : identities) {

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
index de9281b..69fadf9 100644
--- a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
+++ b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kdc.identitybackend;
 
 import org.apache.kerby.config.Config;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.identity.backend.AbstractIdentityBackend;
 import org.apache.zookeeper.KeeperException;
@@ -29,8 +30,6 @@ import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.server.ServerConfig;
 import org.apache.zookeeper.server.ZooKeeperServerMain;
 import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
@@ -43,11 +42,8 @@ import java.util.Properties;
  * A Zookeeper based backend implementation. Currently it uses an embedded
  * Zookeeper. In follow up it will be enhanced to support standalone Zookeeper
  * cluster for replication and reliability.
- *
  */
-public class ZookeeperIdentityBackend extends AbstractIdentityBackend
-        implements Watcher {
-    private static final Logger LOG = LoggerFactory.getLogger(ZookeeperIdentityBackend.class);
+public class ZookeeperIdentityBackend extends AbstractIdentityBackend {
     private String zkHost;
     private int zkPort;
     private File dataFile;
@@ -60,6 +56,13 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
 
     }
 
+    class MyWatcher implements Watcher {
+        @Override
+        public void process(WatchedEvent event) {
+            ZookeeperIdentityBackend.this.process(event);
+        }
+    }
+
     /**
      * Constructing an instance using specified config that contains anything
      * to be used to init the Zookeeper backend.
@@ -73,15 +76,14 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * {@inheritDoc}
      */
     @Override
-    public void initialize() {
-        super.initialize();
+    protected void doInitialize() throws KrbException {
         init();
     }
 
     /**
      * Init Zookeeper Server and connection service, used to initialize the backend.
      */
-    private void init() {
+    private void init() throws KrbException {
         zkHost = getConfig().getString(ZKConfKey.ZK_HOST);
         zkPort = getConfig().getInt(ZKConfKey.ZK_PORT);
 
@@ -112,7 +114,7 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
     /**
      * Prepare connection to Zookeeper server.
      */
-    private void connectZK() {
+    private void connectZK() throws KrbException {
         try {
             zooKeeper = new ZooKeeper(zkHost, 10000, null);
             while (true) {
@@ -128,25 +130,14 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
             }
 
         } catch (IOException e) {
-            throw new RuntimeException("Failed to prepare Zookeeper connection");
+            throw new KrbException("Failed to prepare Zookeeper connection");
         }
     }
 
     /**
-     * Load identities from file
-     */
-    public void load() throws IOException {
-        // TODO: prepare zookeeper connection to the server.
-        // ZooKeeper zooKeeper = null;
-
-        // TODO: load the kdb file from zookeeper
-    }
-
-    /**
      * Start the Zookeeper server
      */
-    private void startEmbeddedZookeeper() {
-
+    private void startEmbeddedZookeeper() throws KrbException {
         Properties startupProperties = new Properties();
         startupProperties.put("dataDir", dataFile.getAbsolutePath());
         startupProperties.put("dataLogDir", dataLogFile.getAbsolutePath());
@@ -156,7 +147,7 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
         try {
             quorumConfiguration.parseProperties(startupProperties);
         } catch(Exception e) {
-            throw new RuntimeException(e);
+            throw new KrbException("Loading quorum configuraiton failed", e);
         }
 
         final ServerConfig configuration = new ServerConfig();
@@ -168,7 +159,7 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
                     try {
                         zooKeeperServer.runFromConfig(configuration);
                     } catch (IOException e) {
-                        LOG.error("ZooKeeper Failed", e);
+                        throw new RuntimeException("ZooKeeper Failed", e);
                     }
                 }
             };
@@ -180,8 +171,7 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * This will watch all the kdb update event so that it's timely synced.
      * @param event The kdb update event ot watch.
      */
-    @Override
-    public void process(WatchedEvent event) {
+    private void process(WatchedEvent event) {
         System.out.print("I got an event: " + event);
     }
 
@@ -189,7 +179,7 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doGetIdentity(String principalName) {
+    protected KrbIdentity doGetIdentity(String principalName) throws KrbException {
         principalName = replaceSlash(principalName);
         IdentityZNode identityZNode = new IdentityZNode(zooKeeper, principalName);
         KrbIdentity krb = new KrbIdentity(principalName);
@@ -206,9 +196,9 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
             krb.setKeyVersion(identityZNode.getKeyVersion());
             krb.setLocked(identityZNode.getLocked());
         } catch (KeeperException e) {
-            LOG.error("Fail to get identity from zookeeper", e);
-            return null;
+            throw new KrbException("Fail to get identity from zookeeper", e);
         }
+        
         return krb;
     }
 
@@ -216,15 +206,14 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doAddIdentity(KrbIdentity identity) {
+    protected KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException {
         if (doGetIdentity(identity.getPrincipalName()) != null) {
             throw new RuntimeException("Principal already exists.");
         }
         try {
             setIdentity(identity);
         } catch (KeeperException e) {
-            LOG.error("Fail to add identity to zookeeper", e);
-            return null;
+            throw new KrbException("Fail to add identity to zookeeper", e);
         }
         return identity;
     }
@@ -233,15 +222,14 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * {@inheritDoc}
      */
     @Override
-    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) {
+    protected KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException {
         if (doGetIdentity(identity.getPrincipalName()) == null) {
             throw new RuntimeException("Principal does not exist.");
         }
         try {
             setIdentity(identity);
         } catch (KeeperException e) {
-            LOG.error("Fail to update identity in zookeeper", e);
-            return null;
+            throw new KrbException("Fail to update identity in zookeeper", e);
         }
         return identity;
     }
@@ -250,16 +238,16 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * {@inheritDoc}
      */
     @Override
-    protected void doDeleteIdentity(String principalName) {
+    protected void doDeleteIdentity(String principalName) throws KrbException {
         principalName = replaceSlash(principalName);
         if (doGetIdentity(principalName) == null) {
-            throw new RuntimeException("Principal does not exist.");
+            throw new KrbException("Principal does not exist.");
         }
         IdentityZNode identityZNode = new IdentityZNode(zooKeeper, principalName);
         try {
             identityZNode.deleteIdentity();
         } catch (KeeperException e) {
-            LOG.error("Fail to delete identity in zookeeper", e);
+            throw new KrbException("Fail to delete identity in zookeeper", e);
         }
     }
 
@@ -267,7 +255,7 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
      * {@inheritDoc}
      */
     @Override
-    public List<String> getIdentities(int start, int limit) {
+    protected List<String> doGetIdentities(int start, int limit) throws KrbException {
         if (limit == -1) {
             return getIdentities();
         }
@@ -277,16 +265,14 @@ public class ZookeeperIdentityBackend extends AbstractIdentityBackend
 
     /**
      * Get all of the identity names
-     * @return
      */
-    public List<String> getIdentities() {
-
+    private List<String> getIdentities() throws KrbException {
         List<String> identityNames = null;
         try {
             // The identities getting from zookeeper is unordered
             identityNames = IdentityZNodeHelper.getIdentityNames(zooKeeper);
         } catch (KeeperException e) {
-            LOG.error("Fail to get identities from zookeeper", e);
+            throw new KrbException("Fail to get identities from zookeeper", e);
         }
         if(identityNames == null || identityNames.isEmpty()) {
             return null;

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java b/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
index 220d152..81b2955 100644
--- a/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
+++ b/kerby-backend/zookeeper-backend/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/ZookeeperBackendTest.java
@@ -22,6 +22,7 @@ package org.apache.kerby.kerberos.kerb.identity.backend;
 import org.apache.kerby.config.Conf;
 import org.apache.kerby.kerberos.kdc.identitybackend.ZKConfKey;
 import org.apache.kerby.kerberos.kdc.identitybackend.ZookeeperIdentityBackend;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -32,11 +33,9 @@ import java.io.File;
 /**
  * Zookeeper backend test
  */
-public class ZookeeperBackendTest extends BackendTest {
-    private static IdentityBackend backend;
-
+public class ZookeeperBackendTest extends BackendTestBase {
     @BeforeClass
-    public static void setup() {
+    public static void setup() throws KrbException {
         Conf config = new Conf();
 
         File testdir = new File(System.getProperty("test.dir", "target"));
@@ -53,40 +52,4 @@ public class ZookeeperBackendTest extends BackendTest {
         backend.initialize();
         backend.start();
     }
-
-    @AfterClass
-    public static void tearDown() {
-        backend.stop();
-        backend.release();
-    }
-
-    @Before
-    public void delete() {
-        super.cleanIdentities(backend);
-    }
-
-    @Test
-    public void testGet() {
-        super.testGet(backend);
-    }
-
-    @Test
-    public void testStore() {
-        super.testStore(backend);
-    }
-
-    @Test
-    public void testUpdate() {
-        super.testUpdate(backend);
-    }
-
-    @Test
-    public void testDelete() {
-        super.testDelete(backend);
-    }
-
-    @Test
-    public void testGetIdentities() {
-        super.testGetIdentities(backend);
-    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/impl/NettyKdcServerImpl.java
----------------------------------------------------------------------
diff --git a/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/impl/NettyKdcServerImpl.java b/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/impl/NettyKdcServerImpl.java
index 491adc1..3368adc 100644
--- a/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/impl/NettyKdcServerImpl.java
+++ b/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/impl/NettyKdcServerImpl.java
@@ -65,7 +65,7 @@ public class NettyKdcServerImpl extends AbstractInternalKdcServer {
 
     private void prepareHandler() {
         kdcContext = new KdcContext(getSetting());
-        kdcContext.setIdentityService(getBackend());
+        kdcContext.setIdentityService(getIdentityService());
         PreauthHandler preauthHandler = new PreauthHandler();
         preauthHandler.init();
         kdcContext.setPreauthHandler(preauthHandler);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTest.java b/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTest.java
index 0dc6035..a1e385f 100644
--- a/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTest.java
+++ b/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTest.java
@@ -25,6 +25,7 @@ import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
 import org.apache.kerby.kerberos.kerb.spec.base.EncryptionKey;
 import org.apache.kerby.kerberos.kerb.spec.base.EncryptionType;
+import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.List;
@@ -44,19 +45,7 @@ public abstract class BackendTest {
             EncryptionType.DES3_CBC_SHA1_KD
     };
 
-    /**
-     * A convenient method to run all tests on the given backend 
-     * @param backend an instance of the backend to be tested
-     */
-    public void testAll(IdentityBackend backend) {
-        testStore(backend);
-        testGet(backend);
-        testUpdate(backend);
-        testDelete(backend);
-        testGetIdentities(backend);
-    }
-    
-    protected void testGet(IdentityBackend backend) {
+    protected void testGet(IdentityBackend backend) throws KrbException {
         KrbIdentity kid = createOneIdentity(TEST_PRINCIPAL);
         backend.addIdentity(kid);
         // clear the identity cache.
@@ -79,7 +68,7 @@ public abstract class BackendTest {
         backend.deleteIdentity(TEST_PRINCIPAL);
     }
 
-    protected void testStore(IdentityBackend backend) {
+    protected void testStore(IdentityBackend backend) throws KrbException {
         KrbIdentity kid = createOneIdentity(TEST_PRINCIPAL);
         backend.addIdentity(kid);
         // clear the identity cache.
@@ -92,7 +81,7 @@ public abstract class BackendTest {
         backend.deleteIdentity(TEST_PRINCIPAL);
     }
 
-    protected void testUpdate(IdentityBackend backend) {
+    protected void testUpdate(IdentityBackend backend) throws KrbException {
         KrbIdentity kid = createOneIdentity(TEST_PRINCIPAL);
         backend.addIdentity(kid);
 
@@ -107,7 +96,7 @@ public abstract class BackendTest {
         backend.deleteIdentity(TEST_PRINCIPAL);
     }
 
-    protected void testDelete(IdentityBackend backend) {
+    protected void testDelete(IdentityBackend backend) throws KrbException {
         KrbIdentity kid = createOneIdentity(TEST_PRINCIPAL);
         backend.addIdentity(kid);
         // clear the identity cache.
@@ -119,7 +108,7 @@ public abstract class BackendTest {
         assertThat(backend.getIdentity(TEST_PRINCIPAL)).isNull();
     }
 
-    protected void testGetIdentities(IdentityBackend backend) {
+    protected void testGetIdentities(IdentityBackend backend) throws KrbException {
         KrbIdentity[] identities = createManyIdentities();
 
         for (KrbIdentity identity : identities) {
@@ -176,7 +165,7 @@ public abstract class BackendTest {
         return Arrays.asList(ENC_TYPES);
     }
 
-    protected void cleanIdentities(IdentityBackend backend) {
+    protected void cleanIdentities(IdentityBackend backend) throws KrbException {
         List<String> identities = backend.getIdentities(0, -1);
         if (identities != null) {
             for (String identity : identities) {

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTestBase.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTestBase.java b/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTestBase.java
new file mode 100644
index 0000000..bb542a0
--- /dev/null
+++ b/kerby-kerb/kerb-identity-test/src/test/java/org/apache/kerby/kerberos/kerb/identity/backend/BackendTestBase.java
@@ -0,0 +1,73 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.kerby.kerberos.kerb.identity.backend;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Json backend test
+ */
+public abstract class BackendTestBase extends BackendTest {
+    protected static IdentityBackend backend;
+
+    /**
+     * Create and prepare an identity backend for the tests. Must override.
+     */
+    @BeforeClass
+    public static void setup() throws Exception {
+        //backend = prepareBackend();
+    }
+
+    @Test
+    public void testGet() throws KrbException {
+        super.testGet(backend);
+    }
+
+    @Test
+    public void testStore() throws KrbException {
+        super.testStore(backend);
+    }
+
+    @Test
+    public void testUpdate() throws KrbException {
+        testUpdate(backend);
+    }
+
+    @Test
+    public void testDelete() throws KrbException {
+        testDelete(backend);
+    }
+
+    @Test
+    public void testGetIdentities() throws KrbException {
+        testGetIdentities(backend);
+    }
+
+    @AfterClass
+    public static void tearDown() throws KrbException {
+        if (backend != null) {
+            backend.stop();
+            backend.release();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/CacheableIdentityService.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/CacheableIdentityService.java b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/CacheableIdentityService.java
new file mode 100644
index 0000000..01f1c21
--- /dev/null
+++ b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/CacheableIdentityService.java
@@ -0,0 +1,128 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.kerby.kerberos.kerb.identity;
+
+import org.apache.kerby.config.Config;
+import org.apache.kerby.config.Configured;
+import org.apache.kerby.kerberos.kerb.KrbException;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * A cacheable identity backend that provides a cache with FIFO and size limit.
+ * Note only limited recently active identities are kept in the cache, and other
+ * identities are meant to be loaded from the underlying backend like memory,
+ * file, SQL DB, LDAP, and etc.
+ */
+public class CacheableIdentityService
+        extends Configured implements IdentityService {
+
+    private static final int DEFAULT_CACHE_SIZE = 1000;
+
+    private Map<String, KrbIdentity> idCache;
+    private int cacheSize = DEFAULT_CACHE_SIZE;
+
+    private IdentityService underlying;
+
+    public CacheableIdentityService(Config config, IdentityService underlying) {
+        super(config);
+        this.underlying = underlying;
+
+        init();
+    }
+
+    private void init() {
+        Map<String, KrbIdentity> tmpMap =
+                new LinkedHashMap<String, KrbIdentity>(cacheSize) {
+            @Override
+            protected boolean removeEldestEntry(Map.Entry eldest) {
+                return size() > cacheSize;
+            }
+        };
+
+        idCache = new ConcurrentHashMap<>(tmpMap);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<String> getIdentities(int start, int limit) throws KrbException {
+        return underlying.getIdentities(start, limit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public KrbIdentity getIdentity(String principalName) throws KrbException {
+        if (idCache.containsKey(principalName)) {
+            return idCache.get(principalName);
+        }
+
+        KrbIdentity identity = underlying.getIdentity(principalName);
+        if (identity != null) {
+            idCache.put(principalName, identity);
+        }
+
+        return identity;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public KrbIdentity addIdentity(KrbIdentity identity) throws KrbException {
+        KrbIdentity added = underlying.addIdentity(identity);
+        if (added != null) {
+            idCache.put(added.getPrincipalName(), added);
+        }
+
+        return added;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public KrbIdentity updateIdentity(KrbIdentity identity) throws KrbException {
+        KrbIdentity updated = underlying.updateIdentity(identity);
+        if (updated != null) {
+            idCache.put(updated.getPrincipalName(), updated);
+        }
+
+        return updated;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void deleteIdentity(String principalName) throws KrbException {
+        if (idCache.containsKey(principalName)) {
+            idCache.remove(principalName);
+        }
+
+        underlying.deleteIdentity(principalName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/IdentityService.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/IdentityService.java b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/IdentityService.java
index 6083cf0..1b3ee0f 100644
--- a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/IdentityService.java
+++ b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/IdentityService.java
@@ -19,6 +19,8 @@
  */
 package org.apache.kerby.kerberos.kerb.identity;
 
+import org.apache.kerby.kerberos.kerb.KrbException;
+
 import java.util.List;
 
 /**
@@ -31,33 +33,33 @@ public interface IdentityService {
      * Note it's ordered by principal name.
      * @return principal names
      */
-    List<String> getIdentities(int start, int limit);
+    List<String> getIdentities(int start, int limit) throws KrbException;
 
     /**
      * Get the identity account specified by name.
      * @param principalName
      * @return identity
      */
-    KrbIdentity getIdentity(String principalName);
+    KrbIdentity getIdentity(String principalName) throws KrbException;
 
     /**
      * Add an identity, and return the newly created result.
      * @param identity
      * @return identity
      */
-    KrbIdentity addIdentity(KrbIdentity identity);
+    KrbIdentity addIdentity(KrbIdentity identity) throws KrbException;
 
     /**
      * Update an identity, and return the updated result.
      * @param identity
      * @return identity
      */
-    KrbIdentity updateIdentity(KrbIdentity identity);
+    KrbIdentity updateIdentity(KrbIdentity identity) throws KrbException;
 
     /**
      * Delete the identity specified by principal name
      * @param principalName
      *
      */
-    void deleteIdentity(String principalName);
+    void deleteIdentity(String principalName) throws KrbException;
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
index 07c96f6..4c1e817 100644
--- a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
+++ b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.identity.backend;
 
 import org.apache.kerby.config.Configured;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.List;
 
 /**
  * An abstract identity backend that provides default behaviors and a cache
@@ -35,73 +37,93 @@ import java.util.Map;
 public abstract class AbstractIdentityBackend
         extends Configured implements IdentityBackend {
 
-    private static final int DEFAULT_CACHE_SIZE = 1000;
-
-    private Map<String, KrbIdentity> idCache;
-    private int cacheSize = DEFAULT_CACHE_SIZE;
-
-    protected void setCacheSize(int cacheSize) {
-        this.cacheSize = cacheSize;
-    }
+    private final static Logger logger =
+            LoggerFactory.getLogger(AbstractIdentityBackend.class);
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void initialize() {
-        idCache = new LinkedHashMap<String, KrbIdentity>(cacheSize) {
-            @Override
-            protected boolean removeEldestEntry(Map.Entry eldest) {
-                return size() > cacheSize;
-            }
-        };
+    public void initialize() throws KrbException {
+        logger.debug("initialize called");
+        doInitialize();
     }
 
     /**
+     * Perform the real initialization work for the backend.
+     */
+    protected void doInitialize() throws KrbException {}
+
+    /**
      * {@inheritDoc}
      */
     @Override
     public void start() {
-
+        doStart();
+        logger.debug("start called");
     }
 
     /**
+     * Perform the real start work for the backend.
+     */
+    protected void doStart() {}
+
+    /**
      * {@inheritDoc}
      */
     @Override
-    public void stop() {
-
+    public void stop() throws KrbException {
+        doStop();
+        logger.debug("stop called");
     }
 
     /**
+     * Perform the real stop work for the backend.
+     */
+    protected void doStop() throws KrbException {}
+
+    /**
      * {@inheritDoc}
      */
     @Override
     public void release() {
-        idCache.clear();
+        doRelease();
+        logger.debug("release called");
     }
 
     /**
-     * Get (principal, KrbIdentity) pairs from the cache.
-     * @return
+     * Perform the real release work for the backend.
+     */
+    protected void doRelease() {}
+
+    /**
+     * {@inheritDoc}
      */
-    protected Map<String, KrbIdentity> getCache() {
-        return idCache;
+    @Override
+    public List<String> getIdentities(int start, int limit) throws KrbException {
+        logger.debug("getIdentities called");
+        return doGetIdentities(start, limit);
     }
 
     /**
+     * Perform the real work to get identities.
+     */
+    protected abstract List<String> doGetIdentities(int start, int limit) throws KrbException;
+
+    /**
      * {@inheritDoc}
      */
     @Override
-    public KrbIdentity getIdentity(String principalName) {
-        if (idCache.containsKey(principalName)) {
-            return idCache.get(principalName);
+    public KrbIdentity getIdentity(String principalName) throws KrbException {
+        if (principalName == null || principalName.isEmpty()) {
+            throw new IllegalArgumentException("Invalid principal name");
         }
 
+        logger.debug("getIdentity called, principalName = {}", principalName);
+
         KrbIdentity identity = doGetIdentity(principalName);
-        if (identity != null) {
-            idCache.put(principalName, identity);
-        }
+        logger.debug("getIdentity {}, principalName = {}",
+                (identity != null ? "successful" : "failed"), principalName);
 
         return identity;
     }
@@ -110,53 +132,67 @@ public abstract class AbstractIdentityBackend
      * Add an identity, invoked by addIdentity.
      * @param principalName
      */
-    protected abstract KrbIdentity doGetIdentity(String principalName);
+    protected abstract KrbIdentity doGetIdentity(String principalName) throws KrbException;
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public KrbIdentity addIdentity(KrbIdentity identity) {
-        KrbIdentity added = doAddIdentity(identity);
-        if (added != null) {
-            idCache.put(added.getPrincipalName(), added);
+    public KrbIdentity addIdentity(KrbIdentity identity) throws KrbException {
+        logger.debug("addIdentity called, principalName = {}",
+                identity.getPrincipalName());
+
+        if (identity == null) {
+            throw new IllegalArgumentException("null identity to add");
         }
 
+        KrbIdentity added = doAddIdentity(identity);
+        logger.debug("addIdentity {}, principalName = {}",
+                (added != null ? "successful" : "failed"), identity.getPrincipalName());
+
         return added;
     }
 
     /**
-     * Add an identity, invoked by addIdentity.
+     * Add an identity, invoked by addIdentity, and return added identity.
      * @param identity
      */
-    protected abstract KrbIdentity doAddIdentity(KrbIdentity identity);
+    protected abstract KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException;
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public KrbIdentity updateIdentity(KrbIdentity identity) {
-        KrbIdentity updated = doUpdateIdentity(identity);
-        if (updated != null) {
-            idCache.put(updated.getPrincipalName(), updated);
+    public KrbIdentity updateIdentity(KrbIdentity identity) throws KrbException {
+        logger.debug("updateIdentity called, principalName = {}",
+                identity.getPrincipalName());
+
+        if (identity == null) {
+            throw new IllegalArgumentException("null identity to update");
         }
 
+        KrbIdentity updated = doUpdateIdentity(identity);
+        logger.debug("addIdentity {}, principalName = {}",
+                (updated != null ? "successful" : "failed"), identity.getPrincipalName());
+
         return updated;
     }
 
     /**
-     * Update an identity, invoked by updateIdentity.
+     * Update an identity, invoked by updateIdentity, and return updated identity.
      * @param identity
      */
-    protected abstract KrbIdentity doUpdateIdentity(KrbIdentity identity);
+    protected abstract KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException;
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void deleteIdentity(String principalName) {
-        if (idCache.containsKey(principalName)) {
-            idCache.remove(principalName);
+    public void deleteIdentity(String principalName) throws KrbException {
+        logger.debug("deleteIdentity called, principalName = {}", principalName);
+
+        if (principalName == null) {
+            throw new IllegalArgumentException("null identity to remove");
         }
 
         doDeleteIdentity(principalName);
@@ -166,6 +202,5 @@ public abstract class AbstractIdentityBackend
      * Delete an identity, invoked by deleteIndentity.
      * @param principalName
      */
-    protected abstract void doDeleteIdentity(String principalName);
-
+    protected abstract void doDeleteIdentity(String principalName) throws KrbException;
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/IdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/IdentityBackend.java b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/IdentityBackend.java
index d705534..3a8126c 100644
--- a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/IdentityBackend.java
+++ b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/IdentityBackend.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.identity.backend;
 
 import org.apache.kerby.config.Configurable;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.IdentityService;
 
 /**
@@ -30,7 +31,7 @@ public interface IdentityBackend extends IdentityService, Configurable {
     /**
      * Init work for the backend can be done here.
      */
-    void initialize();
+    void initialize() throws KrbException;
 
     /**
      * Start the backend and return soon after the backend or the connection to
@@ -45,7 +46,7 @@ public interface IdentityBackend extends IdentityService, Configurable {
      *
      * Will be called during KDC stop.
      */
-    void stop();
+    void stop() throws KrbException;
 
     /**
      * Release the backend associated resources like connection.

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/MemoryIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/MemoryIdentityBackend.java b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/MemoryIdentityBackend.java
index 5ac58bd..21fae7e 100644
--- a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/MemoryIdentityBackend.java
+++ b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/MemoryIdentityBackend.java
@@ -19,20 +19,32 @@
  */
 package org.apache.kerby.kerberos.kerb.identity.backend;
 
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * A memory map based identity backend, which is purely relying on the
- * underlying cache as the storage.
+ * A memory map based identity backend.
  */
 public class MemoryIdentityBackend extends AbstractIdentityBackend {
+    // TODO: configurable
+    private static final int DEFAULT_STORAGE_SIZE = 10000000;
 
-    public MemoryIdentityBackend() {
-        setCacheSize(10000000); // Just no idea, configurable ?
+    private Map<String, KrbIdentity> storage;
+    private int storageSize = DEFAULT_STORAGE_SIZE;
+
+    protected void doInitialize() {
+        Map<String, KrbIdentity> tmpMap =
+                new LinkedHashMap<String, KrbIdentity>(storageSize) {
+                    @Override
+                    protected boolean removeEldestEntry(Map.Entry eldest) {
+                        return size() > storageSize;
+                    }
+                };
+
+        storage = new ConcurrentHashMap<>(tmpMap);
     }
 
     /**
@@ -40,7 +52,7 @@ public class MemoryIdentityBackend extends AbstractIdentityBackend {
      */
     @Override
     protected KrbIdentity doGetIdentity(String principalName) {
-        return null;
+        return storage.get(principalName);
     }
 
     /**
@@ -48,7 +60,7 @@ public class MemoryIdentityBackend extends AbstractIdentityBackend {
      */
     @Override
     protected KrbIdentity doAddIdentity(KrbIdentity identity) {
-        return identity;
+        return storage.put(identity.getPrincipalName(), identity);
     }
 
     /**
@@ -56,7 +68,7 @@ public class MemoryIdentityBackend extends AbstractIdentityBackend {
      */
     @Override
     protected KrbIdentity doUpdateIdentity(KrbIdentity identity) {
-        return identity;
+        return storage.put(identity.getPrincipalName(), identity);
     }
 
     /**
@@ -64,14 +76,14 @@ public class MemoryIdentityBackend extends AbstractIdentityBackend {
      */
     @Override
     protected void doDeleteIdentity(String principalName) {
-
+        storage.remove(principalName);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public List<String> getIdentities(int start, int limit) {
+    protected List<String> doGetIdentities(int start, int limit) throws KrbException{
         List<String> identities = getIdentities();
         if (limit == -1 || start + limit > identities.size()) {
             return identities;
@@ -81,10 +93,9 @@ public class MemoryIdentityBackend extends AbstractIdentityBackend {
 
     /**
      * Get all of the identity names
-     * @return
      */
     private List<String> getIdentities() {
-        List<String> identities = new ArrayList<>(getCache().keySet());
+        List<String> identities = new ArrayList<>(storage.keySet());
         Collections.sort(identities);
         return identities;
     }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
index 52ec4d7..785e399 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
@@ -20,7 +20,10 @@
 package org.apache.kerby.kerberos.kerb.server.impl;
 
 import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.identity.CacheableIdentityService;
+import org.apache.kerby.kerberos.kerb.identity.IdentityService;
 import org.apache.kerby.kerberos.kerb.identity.backend.IdentityBackend;
+import org.apache.kerby.kerberos.kerb.identity.backend.MemoryIdentityBackend;
 import org.apache.kerby.kerberos.kerb.server.BackendConfig;
 import org.apache.kerby.kerberos.kerb.server.KdcConfig;
 import org.apache.kerby.kerberos.kerb.server.KdcSetting;
@@ -35,6 +38,7 @@ public class AbstractInternalKdcServer implements InternalKdcServer {
     private final BackendConfig backendConfig;
     private final KdcSetting kdcSetting;
     private IdentityBackend backend;
+    private IdentityService identityService;
 
     public AbstractInternalKdcServer(KdcSetting kdcSetting) {
         this.kdcSetting = kdcSetting;
@@ -55,8 +59,16 @@ public class AbstractInternalKdcServer implements InternalKdcServer {
         return kdcConfig.getKdcServiceName();
     }
 
-    protected IdentityBackend getBackend() {
-        return backend;
+    protected IdentityService getIdentityService() {
+        if (identityService == null) {
+            if (backend instanceof MemoryIdentityBackend) { // Already in memory
+                identityService = backend;
+            } else {
+                identityService = new CacheableIdentityService(
+                        backendConfig, backend);
+            }
+        }
+        return identityService;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/688fedff/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultInternalKdcServerImpl.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultInternalKdcServerImpl.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultInternalKdcServerImpl.java
index 8b61d8e..dec1221 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultInternalKdcServerImpl.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/DefaultInternalKdcServerImpl.java
@@ -66,7 +66,7 @@ public class DefaultInternalKdcServerImpl extends AbstractInternalKdcServer {
 
     private void prepareHandler() {
         kdcContext = new KdcContext(getSetting());
-        kdcContext.setIdentityService(getBackend());
+        kdcContext.setIdentityService(getIdentityService());
         PreauthHandler preauthHandler = new PreauthHandler();
         preauthHandler.init();
         kdcContext.setPreauthHandler(preauthHandler);


Mime
View raw message