fix and extend tests and test configurations
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml b/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml
index 612e0a8..a24baad 100644
--- a/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml
@@ -51,9 +51,13 @@
     <modelManager/>
     <aclFactory/>
      
-   <userManager>
-     <className>${package}.om.TurbineUser</className>
+   <userManager class="${package}">
+        <className>${package}.om.TurbineUser</className>
         <peerClassName>${package}.om.TurbineUserPeerImpl</peerClassName>
+        <userGroupRoleManager>
+            <!--className${package}.om.TurbineUserGroupRole</className-->
+            <peerClassName>${package}.om.TurbineUserGroupRolePeerImpl</peerClassName>
+        </userGroupRoleManager>        
     </userManager>
     <groupManager>
         <className>${package}.om.TurbineGroup</className>
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties
index 4c213d3..b14974a 100644
--- a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties
@@ -637,3 +637,20 @@
 #
 # Default: none
 # -------------------------------------------------------------------
+
+# -------------------------------------------------------------------
+#
+#  U R L M A P P E R   S E R V I C E
+#
+# - the valve org.apache.turbine.services.urlmapper.URLMapperValve is activated in classic-pipeline.xml
+# - service, optional pull tool and read configuration  
+# - configure turbine-url-mapping in xml, json or yaml
+# -------------------------------------------------------------------
+
+#services.URLMapperService.classname=org.apache.turbine.services.urlmapper.TurbineURLMapperService
+
+# new mapper in pull tooll data service
+#tool.request.mlink=org.apache.turbine.services.urlmapper.MappedTemplateLink
+
+#services.URLMapperService.configFile =  /src/test/conf/turbine-url-mapping.xml
+
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml
index f8457b0..a670a1b 100644
--- a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml
@@ -25,6 +25,7 @@
     <valve>org.apache.turbine.pipeline.DefaultLoginValve</valve>
     <valve>org.apache.turbine.pipeline.DefaultSessionValidationValve</valve>
     <valve>org.apache.turbine.pipeline.DefaultACLCreationValve</valve>
+    <!--  <valve>org.apache.turbine.services.urlmapper.URLMapperValve</valve> -->
     <valve>org.apache.turbine.pipeline.ExecutePageValve</valve>
     <valve>org.apache.turbine.pipeline.CleanUpValve</valve>
     <valve>org.apache.turbine.pipeline.DetermineRedirectRequestedValve</valve>
diff --git a/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java b/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java
index 7a48dae..592d71a 100644
--- a/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java
+++ b/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java
@@ -20,7 +20,9 @@
  */
 import static org.junit.jupiter.api.Assertions.*;
 
+import org.apache.fulcrum.security.GroupManager;
 import org.apache.fulcrum.security.ModelManager;
+import org.apache.fulcrum.security.RoleManager;
 import org.apache.fulcrum.security.entity.ExtendedUser;
 import org.apache.fulcrum.security.entity.Group;
 import org.apache.fulcrum.security.entity.Permission;
@@ -31,8 +33,12 @@
 import org.apache.fulcrum.security.model.turbine.entity.TurbineUserGroupRole;
 import org.apache.fulcrum.security.util.DataBackendException;
 import org.apache.fulcrum.security.util.EntityExistsException;
+import org.apache.fulcrum.security.util.GroupSet;
+import org.apache.fulcrum.security.util.RoleSet;
 import org.apache.fulcrum.security.util.UnknownEntityException;
 import org.apache.fulcrum.testcontainer.BaseUnit5Test;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.torque.ConstraintViolationException;
 import org.apache.turbine.annotation.AnnotationProcessor;
 import org.apache.turbine.annotation.TurbineService;
@@ -47,14 +53,12 @@
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Test that the SecurityService works properly by comparing behaviour of Turbine and Fulcrum security services using
  * Torque and Turbine user manager. Requires MySQL
  *
- * @author gkallidis
+ * @author <a href="mailto:gk@apache.org">Georg Kallidis</a>
  * @version $Id$
  */
 
@@ -62,6 +66,10 @@
     extends BaseUnit5Test
 {
 
+    private static final String TEST_GROUP = "TEST_GROUP";
+
+    private static final String TEST_ROLE = "TEST_Role";
+
     org.apache.fulcrum.security.SecurityService fulcrumSecurityService;
     
     @TurbineService
@@ -73,12 +81,10 @@
 
     boolean onDeleteCascade = true;
 
-    // By default org.slf4j.LoggerFactory is optional in 4.0, but included in webapp
-    Logger log = LoggerFactory.getLogger( getClass().getName() );
+    Logger log = LogManager.getLogger( getClass().getName() );
 
     @BeforeAll
     public static void init()
-        throws Exception
     {
         tc = new TurbineConfig( ".", "src/test/conf/torque/turbine/CompleteTurbineResources.properties" );
         tc.initialize();
@@ -169,62 +175,165 @@
     }
 
     /**
-     * Tests Turbine and Fulcrum.
+     * Tests Turbine Security Manager User / Group / Role
      * 
      * @throws Exception
      */
     @Test
-    // @Ignore(value="Turbine security service supported requires Turbine 4.0.1")
     public void testGrantUserGroupRole()
-        throws Exception
     {
         Group group = null;
         Role role = null;
         User user = null;
-        TurbineUser fulcrumUser = null;
         try
-        {
-            group = turbineSecurityService.getGroupInstance( "TEST_GROUP" );
-            group = turbineSecurityService.addGroup( group ); // assign here to delete later as
-            role = turbineSecurityService.getRoleInstance( "TEST_Role" );
-            role = turbineSecurityService.addRole( role );
+        {            
             // Turbine security service returns a wrapped instance: org.apache.turbine.om.security.DefaultUserImpl
             // which implements org.apache.turbine.om.security.User
             user = turbineSecurityService.getUserInstance( "Clint" );
-            // required not null constraint
-            ( (ExtendedUser) user ).setFirstName( user.getName() );
-            ( (ExtendedUser) user ).setLastName( user.getName() );
+           
+            if (turbineSecurityService.accountExists( user ) ) {
+                // only now the user object is updated with id
+                user = turbineSecurityService.getUser( "Clint" );
+                turbineSecurityService.revokeAll( user );
+            } else {          
+                // required not null constraint;
+                ( (ExtendedUser) user ).setFirstName( user.getName() );
+                ( (ExtendedUser) user ).setLastName( user.getName() );
+                turbineSecurityService.addUser( user, "clint" );
+                user = turbineSecurityService.getUser( "Clint" );
+            }
+             
+            role = addNewTestRole(turbineSecurityService); 
+            group = addNewTestGroup(turbineSecurityService); 
 
-            turbineSecurityService.addUser( user, "clint" );
             turbineSecurityService.grant( user, group, role );
-
-            // existing role
-            Group existingGroup = turbineSecurityService.getGroupByName( "global" );
-            Role existingRole = turbineSecurityService.getRoleByName( "turbineuser" );
-            turbineSecurityService.grant( user, existingGroup, existingRole );
-            assertTrue( user.getUserGroupRoleSet().size() == 2 );
-            // get fresh db user
-            user = turbineSecurityService.getUser( "Clint" );
-            existingGroup = turbineSecurityService.getGroupByName( "turbine" );
-            existingRole = turbineSecurityService.getRoleByName( "turbineadmin" );
-            turbineSecurityService.grant( user, existingGroup, existingRole );
-            assertTrue( user.getUserGroupRoleSet().size() == 3 );
-
+            
             TurbineAccessControlList tacl = turbineSecurityService.<TurbineAccessControlList>getACL( user );
             
-            assertTrue(tacl.hasRole( existingRole, existingGroup ) );
-            assertTrue(tacl.hasRole( "turbineuser" ));
+            for (Group aclgroup : tacl.getAllGroups())
+            {
+                log.info(  "acl group class:" + aclgroup.getClass() );
+                log.info(  "acl group class:" + aclgroup );
+            }
+            
+            for (TurbineUserGroupRole userGroupRoleSet : user.getUserGroupRoleSet())
+            {
+                log.info(  "First Group class:" + userGroupRoleSet.getGroup().getClass() );
+                log.info(  "First UserGroupRoleSet:" + userGroupRoleSet );
+            }
+            assertTrue(tacl.hasRole( role, group ) );
+            
+            // existing role
+            // special global group
+            Group globalGroup = turbineSecurityService.getGlobalGroup();
+            Role turbineuserRole = turbineSecurityService.getRoleByName( "turbineuser" );
+            turbineSecurityService.grant( user, globalGroup, turbineuserRole );
+            assertEquals(2, user.getUserGroupRoleSet().size());
+            turbineSecurityService.saveUser( user );
+            
+            // get fresh db user
+            user = turbineSecurityService.getUser( "Clint" );
+            for (TurbineUserGroupRole userGroupRoleSet : user.getUserGroupRoleSet())
+            {
+                log.info(  "Second (with turbineuser Group class:" + userGroupRoleSet.getGroup().getClass() );
+                log.info(  "UserGroupRoleSet:" + userGroupRoleSet );
+            }
+            
+            Group existingGroup = turbineSecurityService.getGroupByName( "turbine" );
+            Role existingRole = turbineSecurityService.getRoleByName( "turbineadmin" );
+            turbineSecurityService.grant( user, existingGroup, existingRole );
+            
+            for (TurbineUserGroupRole userGroupRoleSet : user.getUserGroupRoleSet())
+            {
+                log.info(  "Third with turbineadmin Group class:" + userGroupRoleSet.getGroup().getClass() );
+                log.info(  "UserGroupRoleSet:" + userGroupRoleSet );
+            }
+            assertEquals(3, user.getUserGroupRoleSet().size());
+
+            user = turbineSecurityService.getUser( "Clint" );
+            tacl = turbineSecurityService.<TurbineAccessControlList>getACL( user );
+            
+            GroupSet aclgroupset = tacl.getGroupSet();
+            for (Group aclgroup : aclgroupset )
+            {
+                log.info(  "last acl group class:" + aclgroup.getClass() );
+                log.info(  "acl group class:" + aclgroup );
+                RoleSet roles = tacl.getRoles( aclgroup );
+                if (roles == null) {
+                    log.info( "No roles for group " + aclgroup );
+                } else {
+                    for (Role aclrole : roles ) {
+                        log.info(  "last acl aclrole class:" + aclrole.getClass() );
+                        log.info(  "acl aclrole class:" + aclrole );
+                    }
+                } 
+            }
+           
+            assertTrue(tacl.hasRole( role, group ), 
+                    "acl has not role " + role + ", group: " + group );
+            assertTrue(tacl.hasRole( existingRole, existingGroup ),  
+                    "acl has not role " + existingRole + ", group: " + existingGroup );
+            
+            log.info( "tacl.hasRole( \"turbineuser\" ):" + tacl.hasRole( "turbineuser" ) );
+            //assertTrue(tacl.hasRole( "turbineuser" ), "acl " + tacl + " of user " + user + " has not expected role turbineuser: " + tacl.getRoles() + " in default group global");
+            //assertTrue(tacl.hasRole( "turbineuser" ), "acl " + tacl + " of user " + user + " has not expected role turbineuser: " + tacl.getRoles());
             
             turbineSecurityService.revoke( user, existingGroup, existingRole );
 
             //user = turbineSecurityService.getUser( "Clint" );
             assertTrue( user.getUserGroupRoleSet().size() == 2 );
             userGroupRoleCheck( group, role, user.getUserDelegate() );
+            
+            tacl = turbineSecurityService.getACL( user );
+            // revoked
+            assertFalse(tacl.hasRole( existingRole, existingGroup ) );
+            
+            
+        } catch (EntityExistsException e) {
+          // cft. finally
+            fail(e);
+        } catch (Exception e) {
+            log.error( "error" , e);
+            fail(e);
+        }
+        finally
+        {
+            if ( user != null )
+                deleteUser( user );
+            // not needed as user remove revokes all :
+            // if (group != null && role != null && user != null) turbineSecurityService.revoke(user, group, role);
+            if ( group != null )
+                deleteGroup( group );
+            if ( role != null )
+                deleteRole( role );
+        }
+    }
+
+    /**
+     * Test Fulcrum Turbine Security Manager User / Group / Role
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testGrantUserGroupRoleAlternative()
+    {
+        Group group = null;
+        Role role = null;
+        TurbineUser fulcrumUser = null;
+        try
+        {          
+            role = addNewTestRole(fulcrumSecurityService.getRoleManager()); 
+            group = addNewTestGroup(fulcrumSecurityService.getGroupManager());
+            
             // compare
             // Fulcrum security service returns a raw
             // org.apache.fulcrum.security.model.turbine.entity.impl.TurbineUserImpl,
             org.apache.fulcrum.security.UserManager userManager = fulcrumSecurityService.getUserManager();
             fulcrumUser = userManager.getUserInstance( "Clint2" );
+            // clean up
+            if (userManager.checkExists( fulcrumUser )) {
+                ( (TurbineModelManager) fulcrumSecurityService.getModelManager() ).revokeAll( fulcrumUser );   
+            }
             // required not null constraint
             ( (ExtendedUser) fulcrumUser ).setFirstName( fulcrumUser.getName() );
             ( (ExtendedUser) fulcrumUser ).setLastName( fulcrumUser.getName() );
@@ -232,27 +341,38 @@
             ( (TurbineModelManager) fulcrumSecurityService.getModelManager() ).grant( fulcrumUser, group, role );
             userGroupRoleCheck( group, role, fulcrumUser );
             
-            tacl = turbineSecurityService.getACL( user );
-            // revoked
-            assertFalse(tacl.hasRole( existingRole, existingGroup ) );
-;
+            TurbineAccessControlList tacl = fulcrumSecurityService.getUserManager().getACL( fulcrumUser );
             
+            Group existingGroup = fulcrumSecurityService.getGroupManager().getGroupByName( "turbine" );
+            Role existingRole = fulcrumSecurityService.getRoleManager().getRoleByName( "turbineadmin" );
+            
+            assertFalse(tacl.hasRole( existingRole, existingGroup ) );
+            
+            fulcrumSecurityService.<TurbineModelManager> getModelManager().grant( fulcrumUser, existingGroup, existingRole );
+            
+            tacl = fulcrumSecurityService.getUserManager().getACL( fulcrumUser );
+            assertTrue(tacl.hasRole( existingRole, existingGroup ) );
+            
+            Role turbineuserRole = fulcrumSecurityService.getRoleManager().getRoleByName( "turbineuser" );
+            Group globalGroup = fulcrumSecurityService.<TurbineModelManager> getModelManager().getGlobalGroup();
+            fulcrumSecurityService.<TurbineModelManager> getModelManager().grant( fulcrumUser, globalGroup, turbineuserRole );
+
+            tacl = fulcrumSecurityService.getUserManager().getACL( fulcrumUser );
+            assertTrue(tacl.hasRole( turbineuserRole, globalGroup ) );
+            // global role
+            assertTrue(tacl.hasRole( turbineuserRole ) );
             
         } catch (EntityExistsException e) {
           // cft. finally
-            fail();
+            fail(e);
         } catch (Exception e) {
             log.error( "error" , e);
-            fail();
+            fail(e);
         }
         finally
         {
             if ( fulcrumUser != null )
                 deleteUser( new DefaultUserImpl( fulcrumUser ) );
-            if ( user != null )
-                deleteUser( user );
-            // not needed as user remove revokes all :
-            // if (group != null && role != null && user != null) turbineSecurityService.revoke(user, group, role);
             if ( group != null )
                 deleteGroup( group );
             if ( role != null )
@@ -264,7 +384,87 @@
     {
 
     }
+    
+    /**
+     * 
+     * @param securityService
+     * @return
+     * @throws UnknownEntityException
+     * @throws DataBackendException
+     * @throws EntityExistsException
+     */
+    private Group addNewTestGroup(SecurityService securityService) throws UnknownEntityException, DataBackendException, EntityExistsException
+    {
+        Group group = null;
+        group = securityService.getGroupInstance( TEST_GROUP );
+        
+        GroupSet groups =  securityService.getAllGroups();
+        for (Group delGroup : groups)
+        {               
+            if (delGroup.getName().toLowerCase().contains( "test" )) {
+                log.warn( "deleting all group: "+ delGroup );
+                securityService.removeGroup( delGroup );
+            }
+        }
+       // assign here to delete later as
+        group = securityService.addGroup( group );
+        return group;
+    }
 
+    private Role addNewTestRole(SecurityService securityService) throws DataBackendException, UnknownEntityException, EntityExistsException
+    {
+        Role role = null;
+        RoleSet roles =  securityService.getAllRoles();
+        for (Role delRole : roles)
+        {               
+            if (delRole.getName().toLowerCase().contains( "test" )) {
+                log.warn( "deleting all user,groups for role: "+ delRole );
+                securityService.revokeAll( delRole, true );
+                securityService.removeRole( delRole );
+            }
+        }
+        role = securityService.getRoleInstance( TEST_ROLE );
+       // assign here to delete later as
+        role = securityService.addRole( role );
+        return role;
+    }
+    
+    
+    private Group addNewTestGroup(GroupManager groupManager) throws UnknownEntityException, DataBackendException, EntityExistsException
+    {
+        Group group = null;
+        group = groupManager.getGroupInstance( TEST_GROUP );
+        
+        GroupSet groups =  groupManager.getAllGroups();
+        for (Group delGroup : groups)
+        {               
+            if (delGroup.getName().toLowerCase().contains( "test" )) {
+                log.warn( "deleting all group: "+ delGroup );
+                groupManager.removeGroup( delGroup );
+            }
+        }
+       // assign here to delete later as
+        group = groupManager.addGroup( group );
+        return group;
+    }
+
+    private Role addNewTestRole(RoleManager roleManager) throws DataBackendException, UnknownEntityException, EntityExistsException
+    {
+        Role role = null;
+        RoleSet roles =  roleManager.getAllRoles();
+        for (Role delRole : roles)
+        {               
+            if (delRole.getName().toLowerCase().contains( "test" )) {
+                log.warn( "deleting all user,groups for role could not be done with fulcrum security service! " );
+                roleManager.removeRole( delRole );
+            }
+        }
+        role = roleManager.getRoleInstance( TEST_ROLE );
+       // assign here to delete later as
+        role = roleManager.addRole( role );
+        return role;
+    }
+    
 
     /**
      * Fulcrum contract check
@@ -290,7 +490,7 @@
                 break;
             }
         }
-        assertTrue( ugrFound );
+        assertTrue( ugrFound, "Not found user" + user + " with role " + role + " in group " + group);
         assertTrue( ugrTest.getGroup().equals( group ) );
         assertTrue( ugrTest.getUser().equals( user ) );
     }