diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java
index 3c55bae060baf96845d189eb5106dfa468976234..ad7838c4fbeef26b6dd1f9f1d7f21a6a376d1d14 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java
@@ -161,5 +161,5 @@ public abstract interface GroupPersistence<T extends Principal>
                                                 String groupID)
         throws UserNotFoundException, GroupNotFoundException,
                TransientException, AccessControlException;
-
+    
 }
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java
index 8db06efab2dc59e6f990b921b89c5fdd34157368..703a3d62a170221b4a4ef875e4596c4ffc8880f9 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java
@@ -68,10 +68,10 @@
  */
 package ca.nrc.cadc.ac.server;
 
-import ca.nrc.cadc.ac.Group;
 import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.UserNotFoundException;
 import ca.nrc.cadc.net.TransientException;
+import com.unboundid.ldap.sdk.DN;
 import java.security.AccessControlException;
 import java.security.Principal;
 import java.util.Collection;
@@ -90,21 +90,25 @@ public abstract interface UserPersistence<T extends Principal>
      * @throws AccessControlException If the operation is not permitted.
      */
     public abstract User<T> getUser(T userID)
-        throws UserNotFoundException, TransientException, AccessControlException;
-
+        throws UserNotFoundException, TransientException, 
+               AccessControlException;
+    
     /**
      * Get all groups the user specified by userID belongs to.
      * 
      * @param userID The userID.
+     * @param isAdmin return only admin Groups when true, else return non-admin
+     *                Groups.
      * 
-     * @return Collection of Group instances.
+     * @return Collection of group DN.
      * 
      * @throws UserNotFoundException  when the user is not found.
      * @throws TransientException If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
-    public abstract Collection<Group> getUserGroups(T userID)
-        throws UserNotFoundException, TransientException, AccessControlException;
+    public abstract Collection<DN> getUserGroups(T userID, boolean isAdmin)
+        throws UserNotFoundException, TransientException,
+               AccessControlException;
     
     /**
      * Check whether the user is a member of the group.
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java
index 970da4800abe2fff9ece0803fa6503ce3576eb50..d418cc36f9e6a9db5f7e7652839a744f78c5e296 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java
@@ -162,10 +162,14 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                             "Support for groups properties not available");
                 }
                 
-                Group inactiveGroup = getInactiveGroup(group);
-                if (inactiveGroup != null)
+                try
+                {
+                    getInactiveGroup(group);
+                    return reactivateGroup(group);
+                }
+                catch (GroupNotFoundException e)
                 {
-                    return reactiveGroup(group, inactiveGroup);
+                    // ignore
                 }
                 
                 DN ownerDN = userPersist.getUserDN(group.getOwner());
@@ -197,7 +201,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
             {
                 e.printStackTrace();
                 throw new RuntimeException(e);
-            }
+            } 
         }
     }
     
@@ -247,43 +251,52 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     }
     
     private Group getInactiveGroup(final Group group)
-        throws AccessControlException, UserNotFoundException, LDAPException
+        throws AccessControlException, UserNotFoundException,
+        GroupNotFoundException
     {
-        Group inactiveGroup = 
-                getInactiveGroup(getGroupDN(group.getID()), group.getID());
-
-        if (inactiveGroup == null)
-        {
-            return null;
-        }
-        
-        if (!group.getOwner().equals(inactiveGroup.getOwner()))
-        {
-            throw new AccessControlException(
-                    "Inactive group not owned be requestor");
-        }
-        
-        Group inactiveAdminGroup = 
-                getInactiveGroup(getAdminGroupDN(group.getID()), group.getID());
-        
-        if (inactiveAdminGroup == null)
+        Group inactiveGroup;
+        try
         {
-            throw new RuntimeException("BUG: adminGroup not found for group " +
-                                       group.getID());
-        }
-        
-        if (!group.getOwner().equals(inactiveAdminGroup.getOwner()))
+            inactiveGroup = getInactiveGroup(
+                    getGroupDN(group.getID()), group.getID());
+
+            if (inactiveGroup == null)
+            {
+                return null;
+            }
+
+            if (!group.getOwner().equals(inactiveGroup.getOwner()))
+            {
+                throw new AccessControlException(
+                        "Inactive group not owned be requestor");
+            }
+
+            Group inactiveAdminGroup = getInactiveGroup(
+                    getAdminGroupDN(group.getID()), group.getID());
+
+            if (inactiveAdminGroup == null)
+            {
+                throw new RuntimeException(
+                        "BUG: adminGroup not found for group " + group.getID());
+            }
+
+            if (!group.getOwner().equals(inactiveAdminGroup.getOwner()))
+            {
+                throw new RuntimeException(
+                        "Bug: adminGroup owner doesn't match "
+                                + "group owner for group " + group.getID());
+            }
+            return inactiveGroup;
+        } 
+        catch (LDAPException e)
         {
-            throw new RuntimeException("Bug: adminGroup owner doesn't match " +
-                                       "group owner for group " + 
-                                       group.getID());
+            // TODO Auto-generated catch block
+            throw new RuntimeException("BUG: LDAP Exception: ", e);
         }
-        
-        return inactiveGroup;
     }
     
     private Group getInactiveGroup(final DN groupDN, final String groupID)
-        throws UserNotFoundException, LDAPException
+        throws UserNotFoundException, LDAPException, GroupNotFoundException
     {
         Filter filter = Filter.createANDFilter(
                 Filter.createEqualityFilter("cn", groupID),
@@ -304,7 +317,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
         {
             String msg = "Inactive Group not found " + groupID;
             logger.debug(msg);
-            return null;
+            throw new GroupNotFoundException(msg);
         }
 
         String groupCN = searchResult.getAttributeValue("cn");
@@ -315,34 +328,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
         return new Group(groupCN, owner);
     }
     
-    private Group reactiveGroup(final Group newGroup, final Group inactiveGroup)
-        throws UserNotFoundException, LDAPException, TransientException
+    private Group reactivateGroup(final Group group)
+        throws UserNotFoundException, LDAPException, TransientException, 
+               AccessControlException, GroupNotFoundException
     {
-        Group group = reactiveGroup(getGroupDN(newGroup.getID()), newGroup, 
-                                    inactiveGroup);
-        Group adminGroup = reactiveGroup(getGroupDN(newGroup.getID()), newGroup, 
-                                         inactiveGroup);
-        return group;
-    }
-    
-    private Group reactiveGroup(final DN groupDN, final Group newGroup, 
-                                final Group inactiveGroup)
-        throws UserNotFoundException, LDAPException, TransientException
-    {
-        List<Modification> mods = new ArrayList<Modification>();
-        mods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
-
-        Group modifiedGroup = modifyGroup(groupDN, newGroup, inactiveGroup, 
-                                          mods);
-        Group activatedGroup = new ActivatedGroup(modifiedGroup.getID(),
-                                                  modifiedGroup.getOwner());
-        activatedGroup.description = modifiedGroup.description;
-        activatedGroup.getProperties().addAll(modifiedGroup.getProperties());
-        activatedGroup.getGroupMembers().addAll(modifiedGroup.getGroupMembers());
-        activatedGroup.getUserMembers().addAll(modifiedGroup.getUserMembers());
-        activatedGroup.getGroupAdmins().addAll(modifiedGroup.getGroupAdmins());
-        activatedGroup.getUserAdmins().addAll(modifiedGroup.getUserAdmins());
-        return activatedGroup;
+        return modifyGroup(group, true);
     }
 
     /**
@@ -503,7 +493,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     /**
      * Modify the given group.
      *
-     * @param group The group to update.
+     * @param group The group to update. It must be an existing group
      * 
      * @return The newly updated group.
      * 
@@ -516,171 +506,107 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
         throws GroupNotFoundException, TransientException,
                AccessControlException, UserNotFoundException
     {
-        DN groupDN = getGroupDN(group.getID());
-        Group oldGroup = getGroup(groupDN, group.getID(), true);
-        Group newGroup = modifyGroup(groupDN, group, oldGroup, null);
-        
-        DN adminGroupDN = getAdminGroupDN(group.getID());
-        Group oldAdminGroup = getGroup(adminGroupDN, group.getID(), true);
-        Group newAdminGroup = modifyGroup(adminGroupDN, group, oldAdminGroup, 
-                                          null);
-        
-        newGroup.getGroupAdmins().addAll(newAdminGroup.getGroupAdmins());
-        newGroup.getUserAdmins().addAll(newAdminGroup.getUserAdmins());
-        
-        return newGroup;
+        return modifyGroup(group, false); 
     }
     
-    private Group modifyGroup(final DN groupDN, final Group newGroup, 
-                              final Group oldGroup,
-                              final List<Modification> modifications)
+    private Group modifyGroup(final Group group, boolean withActivate)
         throws UserNotFoundException, TransientException,
-               AccessControlException
+               AccessControlException, GroupNotFoundException
     {
-        if (!newGroup.getProperties().isEmpty())
+        if (!group.getProperties().isEmpty())
         {
             throw new UnsupportedOperationException(
                     "Support for groups properties not available");
         }
-
-        List<Modification> mods = new ArrayList<Modification>();
-        if (modifications != null)
-        {
-            mods.addAll(modifications);
-        }
-
-        if (newGroup.description == null && oldGroup.description != null)
-        {
-            mods.add(new Modification(ModificationType.DELETE, "description"));
-        }
-        else if (newGroup.description != null && oldGroup.description == null)
+        
+        // check if group exists
+        if (withActivate)
         {
-            mods.add(new Modification(ModificationType.ADD, "description", 
-                                        newGroup.description));
+            getInactiveGroup(group);
         }
-        else if (newGroup.description != null && oldGroup.description != null)
+        else
         {
-            mods.add(new Modification(ModificationType.REPLACE, "description", 
-                                        newGroup.description));
+            getGroup(group.getID());
         }
 
-        List<String> newMembers = new ArrayList<String>();
-        for (User<?> member : newGroup.getUserMembers())
+        List<Modification> mods = new ArrayList<Modification>();
+        List<Modification> adminMods = new ArrayList<Modification>();
+        if (withActivate)
         {
-            if (!oldGroup.getUserMembers().remove(member))
-            {
-                DN memberDN;
-                try
-                {
-                    memberDN = userPersist.getUserDN(member);
-                }
-                catch (LDAPException e)
-                {
-                    throw new UserNotFoundException(
-                            "User not found " + member.getUserID());
-                }
-                newMembers.add(memberDN.toNormalizedString());
-            }
+            mods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
+            adminMods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
         }
-        for (Group gr : newGroup.getGroupMembers())
-        {
-            if (gr.equals(newGroup))
-            {
-                throw new IllegalArgumentException(
-                        "cyclical reference from group member to group");
-            }
 
-            if (!oldGroup.getGroupMembers().remove(gr))
-            {
-                DN grDN = getGroupDN(gr.getID());
-                newMembers.add(grDN.toNormalizedString());
-            }
-        }
-        for (User<?> member : newGroup.getUserAdmins())
-        {
-            if (!oldGroup.getUserAdmins().remove(member))
-            {
-                DN memberDN;
-                try
-                {
-                    memberDN = userPersist.getUserDN(member);
-                }
-                catch (LDAPException e)
-                {
-                    throw new UserNotFoundException(
-                            "User not found " + member.getUserID());
-                }
-                newMembers.add(memberDN.toNormalizedString());
-            }
-        }
-        for (Group gr : newGroup.getGroupAdmins())
+        if (group.description == null)
         {
-            if (gr.equals(newGroup))
-            {
-                throw new IllegalArgumentException(
-                        "cyclical reference from group member to group");
-            }
-
-            if (!oldGroup.getGroupAdmins().remove(gr))
-            {
-                DN grDN = getGroupDN(gr.getID());
-                newMembers.add(grDN.toNormalizedString());
-            }
+            mods.add(new Modification(ModificationType.REPLACE, "description"));
         }
-        
-        if (!newMembers.isEmpty())
+        else
         {
-            mods.add(new Modification(ModificationType.ADD, "uniquemember", 
-                (String[]) newMembers.toArray(new String[newMembers.size()])));
+            mods.add(new Modification(ModificationType.REPLACE, "description", group.description));
         }
 
-        List<String> delMembers = new ArrayList<String>();
-        for (User<?> member : oldGroup.getUserMembers())
+        List<String> newMembers = new ArrayList<String>();
+        for (User<?> member : group.getUserMembers())
         {
             DN memberDN;
             try
             {
-                memberDN = this.userPersist.getUserDN(member);
-            }
+                memberDN = userPersist.getUserDN(member);
+            } 
             catch (LDAPException e)
             {
-                throw new UserNotFoundException(
-                        "User not found " + member.getUserID());
+                throw new UserNotFoundException("User not found "
+                        + member.getUserID());
             }
-            delMembers.add(memberDN.toNormalizedString());
+            newMembers.add(memberDN.toNormalizedString());
         }
-        for (Group gr : oldGroup.getGroupMembers())
+        for (Group gr : group.getGroupMembers())
         {
-            DN grDN = getGroupDN(gr.getID());
-            delMembers.add(grDN.toNormalizedString());
+                DN grDN = getGroupDN(gr.getID());
+                newMembers.add(grDN.toNormalizedString());
         }
-        for (User<?> member : oldGroup.getUserAdmins())
+        List<String> newAdmins = new ArrayList<String>();
+        for (User<?> member : group.getUserAdmins())
         {
             DN memberDN;
             try
             {
-                memberDN = this.userPersist.getUserDN(member);
+                memberDN = userPersist.getUserDN(member);
             }
             catch (LDAPException e)
             {
                 throw new UserNotFoundException(
                         "User not found " + member.getUserID());
             }
-            delMembers.add(memberDN.toNormalizedString());
+            newAdmins.add(memberDN.toNormalizedString());
         }
-        for (Group gr : oldGroup.getGroupAdmins())
+        for (Group gr : group.getGroupAdmins())
         {
             DN grDN = getGroupDN(gr.getID());
-            delMembers.add(grDN.toNormalizedString());
+            newMembers.add(grDN.toNormalizedString());
         }
+
+        mods.add(new Modification(ModificationType.REPLACE, "uniquemember", 
+                (String[]) newMembers.toArray(new String[newMembers.size()])));
+        adminMods.add(new Modification(ModificationType.REPLACE, "uniquemember", 
+                (String[]) newAdmins.toArray(new String[newAdmins.size()])));
         
-        if (!delMembers.isEmpty())
+        // modify admin group first
+        ModifyRequest modifyRequest = new ModifyRequest(getAdminGroupDN(group.getID()), adminMods);
+        try
         {
-            mods.add(new Modification(ModificationType.DELETE, "uniquemember",
-                (String[]) delMembers.toArray(new String[delMembers.size()])));
+            modifyRequest.addControl(
+                    new ProxiedAuthorizationV2RequestControl(
+                            "dn:" + getSubjectDN().toNormalizedString()));
+            LDAPResult result = getConnection().modify(modifyRequest);
         }
-
-        ModifyRequest modifyRequest = new ModifyRequest(groupDN, mods);
+        catch (LDAPException e1)
+        {
+            throw new RuntimeException("LDAP problem", e1);
+        }
+        // modify the group itself now
+        modifyRequest = new ModifyRequest(getGroupDN(group.getID()), mods);
         try
         {
             modifyRequest.addControl(
@@ -694,12 +620,19 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
         }
         try
         {
-            return getGroup(newGroup.getID());
+            if (withActivate)
+            {
+                return new ActivatedGroup(getGroup(group.getID()));
+            }
+            else
+            {
+                return getGroup(group.getID());
+            }
         }
         catch (GroupNotFoundException e)
         {
             throw new RuntimeException(
-                    "BUG: modified group not found (" + groupDN + ")");
+                    "BUG: modified group not found (" + group.getID() + ")");
         }
     }
 
@@ -801,24 +734,38 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
             throw new TransientException("Error getting user", e);
         }
         
+        Collection<DN> groupDNs = new HashSet<DN>();
         if (role == Role.OWNER)
         {
-            return getOwnerGroups(user, userDN, groupID);
+            groupDNs.addAll(getOwnerGroups(user, userDN, groupID));
         }
         else if (role == Role.MEMBER)
         {
-            return getMemberGroups(user, userDN, groupID);
+            groupDNs.addAll(getMemberGroups(user, userDN, groupID, false));
         }
         else if (role == Role.ADMIN)
         {
-            return getAdminGroups(user, userDN, groupID);
+            groupDNs.addAll(getMemberGroups(user, userDN, groupID, true));
+        }
+        
+        Collection<Group> groups = new HashSet<Group>();
+        try
+        {
+            for (DN groupDN : groupDNs)
+            {
+                groups.add(getGroup(groupDN));
+            }
+        }
+        catch (LDAPException e)
+        {
+            throw new TransientException("Error getting group", e);
         }
-        throw new IllegalArgumentException("Unknown role " + role);
+        return groups;
     }
     
-    protected Collection<Group> getOwnerGroups(final User<T> user, 
-                                               final DN userDN,
-                                               final String groupID)
+    protected Collection<DN> getOwnerGroups(final User<T> user, 
+                                            final DN userDN,
+                                            final String groupID)
         throws TransientException, AccessControlException,
                GroupNotFoundException, UserNotFoundException
     {
@@ -834,31 +781,20 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
             }
             
             SearchRequest searchRequest =  new SearchRequest(
-                    config.getGroupsDN(), SearchScope.SUB, filter, 
-                    new String[] {"cn", "description", "modifytimestamp"});
+                    config.getGroupsDN(), SearchScope.SUB, filter, "entrydn");
             
             searchRequest.addControl(
                     new ProxiedAuthorizationV2RequestControl("dn:" + 
                             getSubjectDN().toNormalizedString()));
             
-            Collection<Group> groups = new ArrayList<Group>();
+            Collection<DN> groupDNs = new HashSet<DN>();
             SearchResult results = getConnection().search(searchRequest);
             for (SearchResultEntry result : results.getSearchEntries())
             {
-                String groupName = result.getAttributeValue("cn");
-                // Ignore existing illegal group names.
-                try
-                {
-                    Group group = new Group(groupName, user);
-                    group.description = result.getAttributeValue("description");
-                    group.lastModified = 
-                        result.getAttributeValueAsDate("modifytimestamp");
-                    groups.add(group);
-                }
-                catch (IllegalArgumentException ignore) { }   
+                String entryDN = result.getAttributeValue("entrydn");
+                groupDNs.add(new DN(entryDN));
             }
-            
-            return groups; 
+            return groupDNs; 
         }
         catch (LDAPException e1)
         {
@@ -869,111 +805,39 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
         }
     }
     
-    protected Collection<Group> getMemberGroups(final User<T> user, 
-                                                final DN userDN, 
-                                                final String groupID)
+    protected Collection<DN> getMemberGroups(final User<T> user, 
+                                             final DN userDN, 
+                                             final String groupID,
+                                             final boolean isAdmin)
         throws TransientException, AccessControlException,
                GroupNotFoundException, UserNotFoundException
     {
+        Collection<DN> groups = new HashSet<DN>();
         if (groupID != null)
         {
-            String groupDN = getGroupDN(groupID).toNormalizedString();
-            Collection<Group> groups = new ArrayList<Group>();
-            if (userPersist.isMember(user.getUserID(), groupDN))
+            DN groupDN;
+            if (isAdmin)
             {
-                groups.add(getGroup(groupID, false));
+                groupDN = getAdminGroupDN(groupID);
             }
-            return groups;
-        }
-        else
-        {
-            try
+            else
             {
-                Collection<Group> memberGroups = 
-                        userPersist.getUserGroups(user.getUserID());
-
-                List<Filter> filters = new ArrayList<Filter>();
-                for (Group group : memberGroups)
-                {
-                    filters.add(Filter.createEqualityFilter("cn", 
-                                                            group.getID()));
-                }
-
-                Filter filter = Filter.createORFilter(filters);
-                SearchRequest searchRequest =
-                        new SearchRequest(config.getAdminGroupsDN(), 
-                                          SearchScope.SUB, filter, "cn");
-                
-                SearchResult results = getConnection().search(searchRequest);
-                for (SearchResultEntry result : results.getSearchEntries())
-                {
-                    String groupName = result.getAttributeValue("cn");
-                    for (Group group : memberGroups)
-                    {
-                        if (group.getID().equals(groupName))
-                        {
-                            memberGroups.remove(group);
-                        }
-                    }
-                }
-                return memberGroups;
-            }
-            catch (LDAPException e)
-            {
-                throw new TransientException(e.getDiagnosticMessage());
+                groupDN = getGroupDN(groupID);
             }
-        }
-    }
-    
-    protected Collection<Group> getAdminGroups(final User<T> user,
-                                               final DN userDN, 
-                                               final String groupID)
-        throws TransientException, AccessControlException,
-               GroupNotFoundException, UserNotFoundException
-    {
-        if (groupID != null)
-        {
-            String adminGroupDN = getAdminGroupDN(groupID).toNormalizedString();
-            Collection<Group> groups = new ArrayList<Group>();
-            if (userPersist.isMember(user.getUserID(), adminGroupDN))
+            if (userPersist.isMember(user.getUserID(),
+                                     groupDN.toNormalizedString()))
             {
-                groups.add(getGroup(groupID, false));
+                groups.add(groupDN);
             }
-            return groups;
         }
         else
         {
-            try
-            {
-                Collection<Group> memberGroups = 
-                        userPersist.getUserGroups(user.getUserID());
-
-                List<Filter> filters = new ArrayList<Filter>();
-                for (Group group : memberGroups)
-                {
-                    filters.add(Filter.createEqualityFilter("cn", 
-                                                            group.getID()));
-                }
-
-                Filter filter = Filter.createORFilter(filters);
-                SearchRequest searchRequest =
-                        new SearchRequest(config.getAdminGroupsDN(), 
-                                          SearchScope.SUB, filter, "cn");
-                
-                SearchResult results = getConnection().search(searchRequest);
-                Collection<Group> adminGroups = new HashSet<Group>();
-                for (SearchResultEntry result : results.getSearchEntries())
-                {
-                    String groupName = result.getAttributeValue("cn");
-                    adminGroups.add(getGroup(groupName, false));
-                }
-                return adminGroups;
-            }
-            catch (LDAPException e)
-            {
-                throw new TransientException(e.getDiagnosticMessage());
-            }
+            Collection<DN> memberGroupDNs = 
+                    userPersist.getUserGroups(user.getUserID(), isAdmin);
+            groups.addAll(memberGroupDNs);
+            logger.debug("# groups found: " + memberGroupDNs.size());
         }
+        return groups;
     }
     
     /**
@@ -984,26 +848,25 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
      * @return
      * @throws com.unboundid.ldap.sdk.LDAPException
      * @throws ca.nrc.cadc.ac.GroupNotFoundException
-     * @throws ca.nrc.cadc.ac.UserNotFoundException
      */
-//    protected Group getGroup(final DN groupDN)
-//        throws LDAPException, GroupNotFoundException, UserNotFoundException
-//    {
-//        SearchResultEntry searchResult = 
-//                getConnection().getEntry(groupDN.toNormalizedString(),
-//                                new String[] {"cn", "description"});
-//
-//        if (searchResult == null)
-//        {
-//            String msg = "Group not found " + groupDN;
-//            logger.debug(msg);
-//            throw new GroupNotFoundException(groupDN.toNormalizedString());
-//        }
-//
-//        Group group = new Group(searchResult.getAttributeValue("cn"));
-//        group.description = searchResult.getAttributeValue("description");
-//        return group;
-//    }
+    protected Group getGroup(final DN groupDN)
+        throws LDAPException, GroupNotFoundException
+    {
+        SearchResultEntry searchResult = 
+                getConnection().getEntry(groupDN.toNormalizedString(),
+                                new String[] {"cn", "description"});
+
+        if (searchResult == null)
+        {
+            String msg = "Group not found " + groupDN;
+            logger.debug(msg);
+            throw new GroupNotFoundException(groupDN.toNormalizedString());
+        }
+
+        Group group = new Group(searchResult.getAttributeValue("cn"));
+        group.description = searchResult.getAttributeValue("description");
+        return group;
+    }
 
     /**
      * 
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java
index 91c6372c9ad7786e18b16e544a8098969b0f7f22..8bdb18d2383a88625c172fb2f183df69410c6cff 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java
@@ -191,5 +191,5 @@ public class LdapGroupPersistence<T extends Principal>
             }
         }
     }
-
+    
 }
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
index 90caef285ecec87b1399708f7ed35a5c6ad6d58e..3c0a0e7392f5e5d86c7a40722d31620dd9d79e5d 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
@@ -192,6 +192,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
      * Get all groups the user specified by userID belongs to.
      * 
      * @param userID The userID.
+     * @param isAdmin
      * 
      * @return Collection of Group instances.
      * 
@@ -199,7 +200,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
      * @throws TransientException If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
-    public Collection<Group> getUserGroups(T userID)
+    public Collection<DN> getUserGroups(final T userID, final boolean isAdmin)
         throws UserNotFoundException, TransientException, AccessControlException
     {
         try
@@ -211,7 +212,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                         "Unsupported principal type " + userID.getClass());
             }
 
-            User<T> user = getUser(userID);
+            User<T> user = getUser(userID);            
             Filter filter = Filter.createANDFilter(
                         Filter.createEqualityFilter(searchField, 
                                                     user.getUserID().getName()),
@@ -219,7 +220,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
 
             SearchRequest searchRequest = 
                     new SearchRequest(config.getUsersDN(), SearchScope.SUB, 
-                                      filter, new String[] {"memberOf"});
+                                      filter, "memberOf");
 
             searchRequest.addControl(
                     new ProxiedAuthorizationV2RequestControl("dn:" + 
@@ -228,31 +229,37 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
             SearchResultEntry searchResult = 
                     getConnection().searchForEntry(searchRequest);
             
-            Collection<Group> groups = new HashSet<Group>();
+            DN parentDN;
+            if (isAdmin)
+            {
+                parentDN = new DN(config.getAdminGroupsDN());
+            }
+            else
+            {
+                parentDN = new DN(config.getGroupsDN());
+            }
+            
+            Collection<DN> groupDNs = new HashSet<DN>();
             if (searchResult != null)
             {
-                String[] members = 
-                        searchResult.getAttributeValues("memberOf");
+                String[] members = searchResult.getAttributeValues("memberOf");
                 if (members != null)
                 {
                     for (String member : members)
                     {
-                        String groupCN = DN.getRDNString(member);
-                        int index = groupCN.indexOf("=");
-                        String groupName = groupCN.substring(index + 1);
-                        // Ignore existing illegal group names.
-                        try
+                        DN groupDN = new DN(member);
+                        if (groupDN.isDescendantOf(parentDN, false))
                         {
-                            groups.add(new Group(groupName, user));
+                            groupDNs.add(groupDN);
                         }
-                        catch (IllegalArgumentException ignore) { }
                     }
                 }
             }
-            return groups;
+            return groupDNs;
         }
         catch (LDAPException e)
         {
+            e.printStackTrace();
             // TODO check which LDAP exceptions are transient and which
             // ones are
             // access control
@@ -272,7 +279,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
      * @throws TransientException If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
-    public boolean isMemberX(T userID, String groupID)
+    public boolean isMember(T userID, String groupID)
         throws UserNotFoundException, TransientException,
                AccessControlException
     {
@@ -317,43 +324,6 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
         }
     }
     
-    public boolean isMember(T userID, String groupDN)
-        throws UserNotFoundException, TransientException,
-               AccessControlException
-    {
-        try
-        {
-            String searchField = (String) userLdapAttrib.get(userID.getClass());
-            if (searchField == null)
-            {
-                throw new IllegalArgumentException(
-                        "Unsupported principal type " + userID.getClass());
-            }
-
-            User<T> user = getUser(userID);
-            DN userDN = getUserDN(user);
-
-            CompareRequest compareRequest = 
-                    new CompareRequest(userDN.toNormalizedString(), 
-                                      "memberOf", groupDN);
-            
-            compareRequest.addControl(
-                    new ProxiedAuthorizationV2RequestControl("dn:" + 
-                            getSubjectDN().toNormalizedString()));
-            
-            CompareResult compareResult = 
-                    getConnection().compare(compareRequest);
-            return compareResult.compareMatched();
-        }
-        catch (LDAPException e)
-        {
-            // TODO check which LDAP exceptions are transient and which
-            // ones are
-            // access control
-            throw new TransientException("Error getting the user", e);
-        }
-    }
-    
     /**
      * Returns a member user identified by the X500Principal only. The
      * returned object has the fields required by the GMS.
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java
index ae28f5c12315d393aa0b3a87cc329be79344f598..8511d254f2ab164ad4428e9ab929f9e782bf852b 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java
@@ -68,11 +68,11 @@
  */
 package ca.nrc.cadc.ac.server.ldap;
 
-import ca.nrc.cadc.ac.Group;
 import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.UserNotFoundException;
 import ca.nrc.cadc.ac.server.UserPersistence;
 import ca.nrc.cadc.net.TransientException;
+import com.unboundid.ldap.sdk.DN;
 import java.security.AccessControlException;
 import java.security.Principal;
 import java.util.Collection;
@@ -130,21 +130,23 @@ public class LdapUserPersistence<T extends Principal>
      * Get all groups the user specified by userID belongs to.
      * 
      * @param userID The userID.
+     * @param isAdmin return only admin Groups when true, else return non-admin
+     *                Groups.
      * 
-     * @return Collection of Group instances.
+     * @return Collection of Group DN.
      * 
      * @throws UserNotFoundException  when the user is not found.
      * @throws TransientException If an temporary, unexpected problem occurred.
      * @throws AccessControlException If the operation is not permitted.
      */
-    public Collection<Group> getUserGroups(T userID)
+    public Collection<DN> getUserGroups(T userID, boolean isAdmin)
         throws UserNotFoundException, TransientException, AccessControlException
     {
         LdapUserDAO<T> userDAO = null;
         try
         {
             userDAO = new LdapUserDAO<T>(this.config);
-            Collection<Group> ret = userDAO.getUserGroups(userID);
+            Collection<DN> ret = userDAO.getUserGroups(userID, isAdmin);
             return ret;
         }
         finally
diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java
index 8a675ee56ae32f2a7d85f21df3c1dc2c66ffcb65..2c68a1e61958dac8d9dd2bb946d114eff633330b 100644
--- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java
+++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java
@@ -70,11 +70,11 @@ public class LdapGroupDAOTest
     static int port = 389;
     static String adminDN = "uid=webproxy,ou=webproxy,ou=topologymanagement,o=netscaperoot";
     static String adminPW = "go4it";
-    static String usersDN = "ou=Users,ou=ds,dc=canfartest,dc=net";
-    static String groupsDN = "ou=Groups,ou=ds,dc=canfartest,dc=net";
+//    static String usersDN = "ou=Users,ou=ds,dc=canfartest,dc=net";
+//    static String groupsDN = "ou=Groups,ou=ds,dc=canfartest,dc=net";
     static String adminGroupsDN = "ou=adminGroups,ou=ds,dc=canfartest,dc=net";
-    //static String usersDN = "ou=Users,ou=ds,dc=canfar,dc=net";
-    //static String groupsDN = "ou=Groups,ou=ds,dc=canfar,dc=net";
+    static String usersDN = "ou=Users,ou=ds,dc=canfar,dc=net";
+    static String groupsDN = "ou=Groups,ou=ds,dc=canfar,dc=net";
     
     static String daoTestDN1 = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca";
     static String daoTestDN2 = "cn=cadcdaotest2,ou=cadc,o=hia,c=ca";
@@ -275,15 +275,13 @@ public class LdapGroupDAOTest
         });
     }
     
-    // TODO: add test passing in groupID
     @Test
     public void testSearchMemberGroups() throws Exception
     {
-        final String testGroup1ID = getGroupID();
-        
-        final String testGroup2ID = getGroupID();
+        final String groupID = getGroupID();
+        final String testGroup1ID = groupID + "-1";
+        final String testGroup2ID = groupID + "-2";
         
-                    
         Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>()
         {
             public Object run() throws Exception
@@ -293,11 +291,12 @@ public class LdapGroupDAOTest
                     Group testGroup1 = new Group(testGroup1ID, daoTestUser1);
                     testGroup1.getUserMembers().add(daoTestUser2);
                     testGroup1 = getGroupDAO().addGroup(testGroup1);
+                    log.debug("add group: " + testGroup1ID);
                     
                     Group testGroup2 = new Group(testGroup2ID, daoTestUser1);
                     testGroup2.getUserMembers().add(daoTestUser2);
                     testGroup2 = getGroupDAO().addGroup(testGroup2);
-                    
+                    log.debug("add group: " + testGroup2ID);
                 }
                 catch (Exception e)
                 {
@@ -325,6 +324,7 @@ public class LdapGroupDAOTest
                     boolean found2 = false;
                     for (Group group : groups)
                     {
+                        log.debug("member group: " + group.getID());
                         if (group.getID().equals(testGroup1ID))
                         {
                             found1 = true;
@@ -342,6 +342,12 @@ public class LdapGroupDAOTest
                     {
                         fail("Test group 2 not found");
                     }
+                    
+                    groups = getGroupDAO().getGroups(daoTestUser2.getUserID(), 
+                                                     Role.MEMBER, testGroup1ID);
+                    assertNotNull(groups);
+                    assertTrue(groups.size() == 1);
+                    assertTrue(groups.iterator().next().getID().equals(testGroup1ID));
                 }
                 catch (Exception e)
                 {
@@ -368,45 +374,97 @@ public class LdapGroupDAOTest
             }
         });
     }
-    
-    // TODO: add test passing in groupID
+
 //    @Test
     public void testSearchAdminGroups() throws Exception
     {
-        // do everything as owner
+        final String groupID = getGroupID();
+        final String testGroup1ID = groupID + ".1";
+        final String testGroup2ID = groupID + ".2";
+        
         Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>()
         {
             public Object run() throws Exception
             {
                 try
-                {             
-                    Group expectedGroup = new Group("CadcDaoTestGroup1");
+                {   
+                    Group testGroup1 = new Group(testGroup1ID, daoTestUser1);
+                    testGroup1.getUserAdmins().add(daoTestUser2);
+                    testGroup1 = getGroupDAO().addGroup(testGroup1);
+                    log.debug("add group: " + testGroup1ID);
                     
+                    Group testGroup2 = new Group(testGroup2ID, daoTestUser1);
+                    testGroup2.getUserAdmins().add(daoTestUser2);
+                    testGroup2 = getGroupDAO().addGroup(testGroup2);
+                    log.debug("add group: " + testGroup2ID);
+                }
+                catch (Exception e)
+                {
+                    throw new Exception("Problems", e);
+                }
+                return null;
+            }
+        });
+        
+        Subject.doAs(daoTestUser2Subject, new PrivilegedExceptionAction<Object>()
+        {
+            public Object run() throws Exception
+            {
+                try
+                {   
                     Collection<Group> groups = 
-                        getGroupDAO().getGroups(daoTestUser2.getUserID(), 
-                                                Role.ADMIN, null);
-                    System.out.println("# groups found: " + groups.size());
+                            getGroupDAO().getGroups(daoTestUser2.getUserID(), 
+                                                    Role.ADMIN, null);
                     
-                    boolean found = false;
+                    log.debug("# groups found: " + groups.size());
+                    assertNotNull(groups);
+                    assertTrue(groups.size() >= 2);
+                    
+                    boolean found1 = false;
+                    boolean found2 = false;
                     for (Group group : groups)
                     {
-                        System.out.println("found group: " + group.getID());
-                        // get the group to get the owner 
-                        // (not returned for RW groups)
-                        group = getGroupDAO().getGroup(group.getID());
-                        if (!group.getOwner().equals(daoTestUser2))
+                        log.debug("admin group: " + group.getID());
+                        if (group.getID().equals(testGroup1ID))
                         {
-                            fail("returned group with wrong owner");
+                            found1 = true;
                         }
-                        if (group.equals(expectedGroup))
+                        if (group.getID().equals(testGroup2ID))
                         {
-                            found = true;
+                            found2 = true;
                         }
                     }
-                    if (!found)
+                    if (!found1)
                     {
-                        fail("");
+                        fail("Test group 1 not found");
                     }
+                    if (!found2)
+                    {
+                        fail("Test group 2 not found");
+                    }
+                    
+                    groups = getGroupDAO().getGroups(daoTestUser2.getUserID(), 
+                                                     Role.ADMIN, testGroup1ID);
+                    assertNotNull(groups);
+                    assertTrue(groups.size() == 1);
+                    assertTrue(groups.iterator().next().getID().equals(testGroup1ID));
+                }
+                catch (Exception e)
+                {
+                    throw new Exception("Problems", e);
+                }
+                return null;
+            }
+        });
+        
+        Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>()
+        {
+            public Object run() throws Exception
+            {
+                try
+                {   
+                    getGroupDAO().deleteGroup(testGroup1ID);
+                    getGroupDAO().deleteGroup(testGroup2ID);                    
                 }
                 catch (Exception e)
                 {
@@ -521,15 +579,6 @@ public class LdapGroupDAOTest
             public Object run() throws Exception
             {
                 getGroupDAO().addGroup(new Group(groupID, daoTestUser1));
-                
-//                try
-//                {
-//                    getGroupDAO().modifyGroup(new Group(groupID, unknownUser));
-//                    fail("modifyGroup with unknown user should throw " + 
-//                         "UserNotFoundException");
-//                }
-//                catch (UserNotFoundException ignore) {}
-                
                 try
                 {
                     getGroupDAO().modifyGroup(new Group("foo", daoTestUser1));
diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java
index f02c0f12c21689c61b6625bac768e3fd91efe835..6bda5b89871e4aaa8bbd6ffe71f3dc56cfa6e809 100644
--- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java
+++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java
@@ -172,7 +172,7 @@ public class LdapUserDAOTest
     /**
      * Test of getUserGroups method, of class LdapUserDAO.
      */
-//    @Test
+    @Test
     public void testGetUserGroups() throws Exception
     {
         Subject subject = new Subject();
@@ -185,11 +185,17 @@ public class LdapUserDAOTest
             {
                 try
                 {            
-                    Collection<Group> groups = getUserDAO().getUserGroups(testUser.getUserID());
+                    Collection<DN> groups = getUserDAO().getUserGroups(testUser.getUserID(), false);
+                    assertNotNull(groups);
+                    assertTrue(!groups.isEmpty());
+                    for (DN groupDN : groups)
+                        log.debug(groupDN);
+                    
+                    groups = getUserDAO().getUserGroups(testUser.getUserID(), true);
                     assertNotNull(groups);
                     assertTrue(!groups.isEmpty());
-                    for (Group group : groups)
-                        log.debug(group);
+                    for (DN groupDN : groups)
+                        log.debug(groupDN);
                     
                     return null;
                 }
@@ -204,7 +210,7 @@ public class LdapUserDAOTest
     /**
      * Test of getUserGroups method, of class LdapUserDAO.
      */
-//    @Test
+    @Test
     public void testIsMember() throws Exception
     {
         Subject subject = new Subject();
@@ -220,8 +226,8 @@ public class LdapUserDAOTest
                     boolean isMember = getUserDAO().isMember(testUser.getUserID(), "foo");
                     assertFalse(isMember);
                     
-                    String groupID = "cn=cadcdaotestgroup,cn=groups,ou=ds,dc=canfartest,dc=net";
-                    isMember = getUserDAO().isMember(testUser.getUserID(), groupID);
+                    String groupDN = "cn=cadcdaotestgroup1,ou=groups,ou=ds,dc=canfartest,dc=net";
+                    isMember = getUserDAO().isMember(testUser.getUserID(), groupDN);
                     assertTrue(isMember);
                     
                     return null;
@@ -234,7 +240,6 @@ public class LdapUserDAOTest
         });
     }
     
-    
     /**
      * Test of getMember.
      */
@@ -262,7 +267,6 @@ public class LdapUserDAOTest
             }
         });
         
-        
         // should also work as a different user
         subject = new Subject();
         subject.getPrincipals().add(new HttpPrincipal("CadcDaoTest2"));
@@ -286,7 +290,6 @@ public class LdapUserDAOTest
         });
     }
     
-    
     private static void check(final User<? extends Principal> user1, final User<? extends Principal> user2)
     {
         assertEquals(user1, user2);
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java
index 189088c9de5af0f082e88032c846ae859c18c4ba..22e445ede8750b77db6dd5f0bc07db03420531db 100644
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java
@@ -68,19 +68,18 @@
  */
 package ca.nrc.cadc.ac;
 
-import java.security.Principal;
 
 public class ActivatedGroup extends Group
 {
-
-    public ActivatedGroup(String groupID)
-    {
-        super(groupID);
-    }
-    
-    public ActivatedGroup(String groupID, User<? extends Principal> owner)
+    public ActivatedGroup(Group group)
     {
-        super(groupID, owner);
+        super(group.getID(), group.getOwner());
+        this.description = group.description;
+        this.properties = group.getProperties();
+        this.lastModified = group.lastModified;
+        this.getUserMembers().addAll(group.getUserMembers());
+        this.getGroupMembers().addAll(group.getGroupMembers());
+        this.getUserAdmins().addAll(group.getUserAdmins());
+        this.getGroupAdmins().addAll(group.getGroupAdmins());
     }
-
 }