package eu.dnetlib.enabling.aas.service;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.bouncycastle.util.encoders.Base64;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;

import eu.dnetlib.enabling.aas.ctx.ISecurityContextContainer;
import eu.dnetlib.enabling.aas.ctx.SecurityContext;
import eu.dnetlib.enabling.aas.ctx.SecurityContextContainerException;
import eu.dnetlib.enabling.aas.ctx.tools.CodingContext;
import eu.dnetlib.enabling.aas.ctx.tools.SimpleContextRecoder;
import eu.dnetlib.enabling.aas.rmi.A2Error;
import eu.dnetlib.enabling.aas.rmi.A2Service;
import eu.dnetlib.enabling.aas.rmi.Attribute;
import eu.dnetlib.enabling.aas.rmi.AuthenticateRequest;
import eu.dnetlib.enabling.aas.rmi.AuthenticateResp;
import eu.dnetlib.enabling.aas.rmi.AuthorizeRequest;
import eu.dnetlib.enabling.aas.rmi.AuthorizeResp;
import eu.dnetlib.enabling.aas.rmi.InvalidateRequest;
import eu.dnetlib.enabling.aas.rmi.InvalidateResp;
import eu.dnetlib.enabling.aas.rmi.Obligation;
import eu.dnetlib.enabling.aas.rmi.TypedString;
import eu.dnetlib.enabling.aas.service.A2Constants;
import eu.dnetlib.enabling.aas.service.A2ServiceImpl;
import eu.dnetlib.enabling.aas.utils.ResourcesGenerator;
import eu.dnetlib.enabling.aas.utils.SpringUtils;
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
import eu.dnetlib.enabling.is.store.rmi.ISStoreException;
import eu.dnetlib.enabling.is.store.rmi.ISStoreService;

/**
 * For testing driver policies:
 * junit/new_policies/authenticate-all.xml
 * junit/new_policies/common-user-authorization.xml
 * junit/new_policies/collection-man-authorization.xml
 * junit/new_policies/community-man-authorization.xml								
 * Currently this tests are realized also by driver-tests project.
 * 
 * @author mhorst
 *
 */
public class SimpleDriverPoliciesTest {

	A2Service a2Service = null;
	ISStoreService storeService = null;
	ISRegistryService registryService = null;
	
	protected ApplicationContext context;
	public static String ATTRIBUTE_STRING_TYPE = "http://www.w3.org/2001/XMLSchema#string";
	
	void initContext() {
		context = SpringUtils.getSpringContext(SpringUtils.DEFAULT_INTEGRATION_RESOURCE);
	}
	
	@Before
	public void setUp() throws Exception {
		initContext();
		a2Service = (A2Service) context.getBean("A2Service");
		storeService = (ISStoreService) context.getBean("MockISStoreService");
		registryService = (ISRegistryService) context.getBean("MockISRegistryService");
		prepareUserResourceType();
	}

	@After
	public void tearDown() throws Exception {
		a2Service = null;
	}

	public void prepareUserResourceType() throws ISStoreException {
		List<String> colNames = storeService.getFileColls(); 
		
		if (!isNameAmongNames(colNames, ResourcesGenerator.IS_COLLECTION_DRIVER_USER_RESOURCE_PATH.substring("db/".length()))) {
			System.out.println("UserProf collection not found! Initializing UserProf collection...");
			boolean res = storeService.createFileColl(ResourcesGenerator.IS_COLLECTION_DRIVER_USER_RESOURCE_PATH);
			if (res)
				System.out.println("UserProf collection initialized successfully.");
			else
				System.err.println("UserProf collection NOT initialized! Unknown error occured!");
		} else {
			System.out.println("No need for creating UserProf collection.");
		}
	}

	@Test
	public void testAuthenticateUIService() throws Exception {
		String serviceProfId = null;
		String serviceSecCtxId = null;
		try {
			String resourceId = "uiservice1";
			String serviceProfile = ResourcesGenerator.generateSecProf(resourceId, null);
			serviceProfId = registryService.registerProfile(serviceProfile);
			AuthenticateRequest request = new AuthenticateRequest();
			TypedString[] principals = new TypedString[1];
			principals[0] = new TypedString(resourceId,"certificate");
			request.setPrincipals(principals);
			AuthenticateResp response = a2Service.authenticate(request);
			assertNotNull(response);
			assertEquals(0, response.getErrors().length);
			assertNull(response.getObligations());
			assertNotNull(response.getIdentities());
			TypedString identity = response.getIdentities()[0];
			assertEquals("driver.security.identity.service", identity.getType());
			assertEquals("driver.security.identity.service#uiservice", identity.getText());
			
			TypedString privKey = response.getIdentities()[1];
			TypedString publKey = response.getIdentities()[2];
			byte[] decodedPrivKey = null;
			byte[] decodedPublKey = null;
			decodedPrivKey = Base64.decode(privKey.getText());
			decodedPublKey = Base64.decode(publKey.getText());
			ISecurityContextContainer container = (ISecurityContextContainer) context.getBean("SecurityContextContainer");
			assertNotNull(container);
			String[] secCtxIds = new String[1];
	//		secCtxIds[0] = response.getContextId();
	//		secCtx are passed to the tomcat filter using threadLocal
			serviceSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			secCtxIds[0] = serviceSecCtxId;
			SecurityContext[] secCtxs=null;
			try {
				secCtxs = container.queryContexts(secCtxIds);
			} catch (SecurityContextContainerException e) {
				e.printStackTrace();
			}
			assertNotNull(secCtxs);
			SecurityContext secCtx = secCtxs[0];
			assertNotNull(secCtx);
			
			//check keys encoding/decoding
			assertTrue(java.util.Arrays.equals(decodedPrivKey, secCtx.getPrivKey()));
			assertTrue(java.util.Arrays.equals(decodedPublKey, secCtx.getPubKey()));
			
			assertNull(secCtx.getObligations());
			assertNotNull(secCtx.getIdentities());
			assertEquals(1, secCtx.getIdentities().length);
			eu.dnetlib.enabling.aas.rmi.TypedString identSecCtx = secCtx.getIdentities()[0];
			assertEquals("driver.security.identity.service", identSecCtx.getType());
			assertEquals("driver.security.identity.service#uiservice", identSecCtx.getText());
		} finally {
			if (serviceSecCtxId!=null)
				registryService.deleteProfile(serviceSecCtxId);
			if (serviceProfId!=null)
				registryService.deleteProfile(serviceProfId);
		}
	}

	@Test
	public void testAuthenticateUser() throws Exception {
		String userProfId = null;
		String userSecProfId = null;
		String userSecCtxId = null;
		try {
			String userEmail = "billy@nohost.eu";
			userProfId = registryService.registerProfile(ResourcesGenerator.generateUserProf(userEmail));
			assertNotNull(userProfId);
			Set<String> roles = new HashSet<String>();
			roles.add("driver.security.identity.role#user");
			userSecProfId = registryService.registerProfile(ResourcesGenerator.generateSecProf(userProfId, roles));
			assertNotNull(userSecProfId);
			
			AuthenticateRequest request = new AuthenticateRequest();
			TypedString[] principals = new TypedString[1];
			principals[0] = new TypedString(userEmail,"login");
			request.setPrincipals(principals);
			TypedString[] credentials = new TypedString[1];
			credentials[0] = new TypedString("driver","password");
			request.setCredentials(credentials);
			AuthenticateResp response = a2Service.authenticate(request);
			assertNotNull(response);
			assertEquals(0, response.getErrors().length);
			assertNull(response.getObligations());
			assertNotNull(response.getIdentities());
	//		assertEquals(5+2,response.getIdentities().length);
			assertEquals(1+2,response.getIdentities().length);
			TypedString identity = response.getIdentities()[0];
			assertEquals("driver.security.identity.role", identity.getType());
	//		assertEquals("driver.security.identity.role#administrator", identity.getText());
			assertEquals("driver.security.identity.role#user", identity.getText());
			System.out.println("SecurityContext id: " + response.getContextId());
			
			TypedString privKey = findIdentity(A2Constants.IDENTITY_PRIVATE_KEY,response.getIdentities());
			TypedString publKey = findIdentity(A2Constants.IDENTITY_PUBLIC_KEY,response.getIdentities());
			byte[] decodedPrivKey = null;
			byte[] decodedPublKey = null;
			decodedPrivKey = Base64.decode(privKey.getText());
			decodedPublKey = Base64.decode(publKey.getText());
			ISecurityContextContainer container = (ISecurityContextContainer) context.getBean("SecurityContextContainer");
			assertNotNull(container);
			String[] secCtxIds = new String[1];
	//		secCtxIds[0] = response.getContextId();
	//		secCtx are passed to the tomcat filter using threadLocal
			userSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			secCtxIds[0] = userSecCtxId;
	
			SecurityContext[] secCtxs=null;
			try {
				secCtxs = container.queryContexts(secCtxIds);
			} catch (SecurityContextContainerException e) {
				e.printStackTrace();
			}
			assertNotNull(secCtxs);
			SecurityContext secCtx = secCtxs[0];
			assertNotNull(secCtx);
			
			//check keys encoding/decoding
			assertTrue(java.util.Arrays.equals(decodedPrivKey, secCtx.getPrivKey()));
			assertTrue(java.util.Arrays.equals(decodedPublKey, secCtx.getPubKey()));
			
			assertNull(secCtx.getObligations());
			assertNotNull(secCtx.getIdentities());
	//		assertEquals(5, secCtx.getIdentities().length);
			assertEquals(1, secCtx.getIdentities().length);
			eu.dnetlib.enabling.aas.rmi.TypedString identSecCtx = secCtx.getIdentities()[0];
			assertEquals("driver.security.identity.role", identSecCtx.getType());
	//		assertEquals("driver.security.identity.role#administrator", identSecCtx.getText());
			assertEquals("driver.security.identity.role#user", identSecCtx.getText());
		} finally {
			if (userSecCtxId!=null)
				registryService.deleteProfile(userSecCtxId);
			if (userSecProfId!=null)
				registryService.deleteProfile(userSecProfId);
			if (userProfId!=null)
				registryService.deleteProfile(userProfId);
		}
	}


	@SuppressWarnings("unchecked")
	@Test
	public void testAuthorizeCollectionAccess() throws Exception {
		String serviceProfId = null;
		String serviceSecCtxId = null;
		String userProfId = null;
		String userSecProfId = null;
		String userSecCtxId = null;
		try {
//			uiservice authentication
			String uiserviceId = "uiservice1";
			String serviceProfile = ResourcesGenerator.generateSecProf(uiserviceId, null);
			serviceProfId = registryService.registerProfile(serviceProfile);
			assertNotNull(serviceProfId);
			AuthenticateRequest serviceRequest = new AuthenticateRequest();
			TypedString[] serviceRrincipals = new TypedString[1];
			serviceRrincipals[0] = new TypedString(uiserviceId,"certificate");
			serviceRequest.setPrincipals(serviceRrincipals);
			AuthenticateResp serviceResponse = a2Service.authenticate(serviceRequest);
			assertNotNull(serviceResponse);
			serviceSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
//			user authentication
			String userEmail = "colman@nohost.eu";
			userProfId = registryService.registerProfile(ResourcesGenerator.generateUserProf(userEmail));
			assertNotNull(userProfId);
			Set<String> roles = new HashSet<String>();
			roles.add("driver.security.identity.role#collection_manager");
			userSecProfId = registryService.registerProfile(ResourcesGenerator.generateSecProf(userProfId, roles));
			assertNotNull(userSecProfId);
			
			AuthenticateRequest userRequest = new AuthenticateRequest();
			TypedString[] userPrincipals = new TypedString[1];
			userPrincipals[0] = new TypedString(userEmail,"login");
			userRequest.setPrincipals(userPrincipals);
			TypedString[] userCredentials = new TypedString[1];
			userCredentials[0] = new TypedString("driver","password");
			userRequest.setCredentials(userCredentials);
			AuthenticateResp userResponse = a2Service.authenticate(userRequest);
			assertNotNull(userResponse);
			userSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
			String secCtxIdChain = null;
			SimpleContextRecoder recoder = new SimpleContextRecoder();
			CodingContext ctx = new CodingContext();
	//		ctx.secCtxId = serviceResponse.getContextId();
			ctx.secCtxId = serviceSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
	//		ctx.secCtxId = userResponse.getContextId();
			ctx.secCtxId = userSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
			
			AuthorizeRequest authorizeRequest = new AuthorizeRequest();
	//		authorizeRequest.setContextId(secCtxIdChain);
	//		secCtx are passed to the tomcat filter using threadLocal
			A2ServiceImpl.threadLocal.set(secCtxIdChain);
	
			authorizeRequest.setResource(new TypedString("collection"));
			authorizeRequest.setAction(new TypedString("edit"));
			AuthorizeResp authorizeResponse = a2Service.authorize(authorizeRequest);
			
			assertNotNull(authorizeResponse);
			assertTrue(authorizeResponse.isAuthorized());
			
			assertFalse(authorizeResponse.hasErrors());
			assertTrue(authorizeResponse.hasObligations());
			assertEquals(1, authorizeResponse.getObligations().length);
			Obligation oblig = authorizeResponse.getObligations()[0];
			assertEquals(2, oblig.getAttributes().length);
			Attribute attrResource = oblig.getAttributes()[0];
			assertEquals("resource", attrResource.getKey());
			assertEquals("http://www.w3.org/2001/XMLSchema#string", attrResource.getType());
			assertEquals("collection", attrResource.getValue());
			
			authorizeRequest.setAction(new TypedString("unsupported action"));
			authorizeResponse = a2Service.authorize(authorizeRequest);
			assertNotNull(authorizeResponse);
			assertFalse(authorizeResponse.isAuthorized());
			assertTrue(authorizeResponse.hasErrors());
			assertFalse(authorizeResponse.hasObligations());
			Iterator itErr = Arrays.asList(authorizeResponse.getErrors()).iterator();
			assertTrue(itErr.hasNext());
			if (itErr.hasNext()) {
				A2Error error = (A2Error) itErr.next();
				assertEquals(A2Error.DECISION_NOT_APPLICABLE , error.getErrorId());
			}
		} finally {
			if (serviceSecCtxId!=null)
				registryService.deleteProfile(serviceSecCtxId);
			if (serviceProfId!=null)
				registryService.deleteProfile(serviceProfId);
			if (userSecCtxId!=null)
				registryService.deleteProfile(userSecCtxId);
			if (userSecProfId!=null)
				registryService.deleteProfile(userSecProfId);
			if (userProfId!=null)
				registryService.deleteProfile(userProfId);
		}

	}

	@SuppressWarnings("unchecked")
	@Test
	public void testAuthorizeCommunityAccess() throws Exception {
		String serviceProfId = null;
		String serviceSecCtxId = null;
		String userProfId = null;
		String userSecProfId = null;
		String userSecCtxId = null;
		try {
//			uiservice authentication
			String uiserviceId = "uiservice1";
			String serviceProfile = ResourcesGenerator.generateSecProf(uiserviceId, null);
			serviceProfId = registryService.registerProfile(serviceProfile);
			assertNotNull(serviceProfId);
			AuthenticateRequest serviceRequest = new AuthenticateRequest();
			TypedString[] serviceRrincipals = new TypedString[1];
			serviceRrincipals[0] = new TypedString(uiserviceId,"certificate");
			serviceRequest.setPrincipals(serviceRrincipals);
			AuthenticateResp serviceResponse = a2Service.authenticate(serviceRequest);
			assertNotNull(serviceResponse);
			serviceSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
//			user authentication
			String userEmail = "comman@nohost.eu";
			userProfId = registryService.registerProfile(ResourcesGenerator.generateUserProf(userEmail));
			assertNotNull(userProfId);
			Set<String> roles = new HashSet<String>();
			roles.add("driver.security.identity.role#community_manager");
			userSecProfId = registryService.registerProfile(ResourcesGenerator.generateSecProf(userProfId, roles));
			assertNotNull(userSecProfId);
			
			AuthenticateRequest userRequest = new AuthenticateRequest();
			TypedString[] userPrincipals = new TypedString[1];
			userPrincipals[0] = new TypedString(userEmail,"login");
			userRequest.setPrincipals(userPrincipals);
			TypedString[] userCredentials = new TypedString[1];
			userCredentials[0] = new TypedString("driver","password");
			userRequest.setCredentials(userCredentials);
			AuthenticateResp userResponse = a2Service.authenticate(userRequest);
			assertNotNull(userResponse);
			userSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
			String secCtxIdChain = null;
			SimpleContextRecoder recoder = new SimpleContextRecoder();
			CodingContext ctx = new CodingContext();
	//		ctx.secCtxId = serviceResponse.getContextId();
			ctx.secCtxId = serviceSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
	//		ctx.secCtxId = userResponse.getContextId();
			ctx.secCtxId = userSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
			
			AuthorizeRequest authorizeRequest = new AuthorizeRequest();
	//		authorizeRequest.setContextId(secCtxIdChain);
	//		secCtx are passed to the tomcat filter using threadLocal
			A2ServiceImpl.threadLocal.set(secCtxIdChain);
	
			authorizeRequest.setResource(new TypedString("community"));
			authorizeRequest.setAction(new TypedString("delete"));
			AuthorizeResp authorizeResponse = a2Service.authorize(authorizeRequest);
			
			assertNotNull(authorizeResponse);
			assertTrue(authorizeResponse.isAuthorized());
			
			assertFalse(authorizeResponse.hasErrors());
			assertTrue(authorizeResponse.hasObligations());
			assertEquals(1, authorizeResponse.getObligations().length);
			Obligation oblig = authorizeResponse.getObligations()[0];
			assertEquals(2, oblig.getAttributes().length);
			Attribute attrResource = oblig.getAttributes()[0];
			assertEquals("resource", attrResource.getKey());
			assertEquals("http://www.w3.org/2001/XMLSchema#string", attrResource.getType());
			assertEquals("community", attrResource.getValue());

		} finally {
			if (serviceSecCtxId!=null)
				registryService.deleteProfile(serviceSecCtxId);
			if (serviceProfId!=null)
				registryService.deleteProfile(serviceProfId);
			if (userSecCtxId!=null)
				registryService.deleteProfile(userSecCtxId);
			if (userSecProfId!=null)
				registryService.deleteProfile(userSecProfId);
			if (userProfId!=null)
				registryService.deleteProfile(userProfId);
		}
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testAuthorizeProfileAccess() throws Exception {
		String serviceProfId = null;
		String serviceSecCtxId = null;
		String userProfId = null;
		String userSecProfId = null;
		String userSecCtxId = null;
		try {
//			uiservice authentication
			String uiserviceId = "uiservice1";
			String serviceProfile = ResourcesGenerator.generateSecProf(uiserviceId, null);
			serviceProfId = registryService.registerProfile(serviceProfile);
			assertNotNull(serviceProfId);
			AuthenticateRequest serviceRequest = new AuthenticateRequest();
			TypedString[] serviceRrincipals = new TypedString[1];
			serviceRrincipals[0] = new TypedString(uiserviceId,"certificate");
			serviceRequest.setPrincipals(serviceRrincipals);
			AuthenticateResp serviceResponse = a2Service.authenticate(serviceRequest);
			assertNotNull(serviceResponse);
			serviceSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
//			user authentication
			String userEmail = "somebode@nohost.eu";
			userProfId = registryService.registerProfile(ResourcesGenerator.generateUserProf(userEmail));
			assertNotNull(userProfId);
			Set<String> roles = new HashSet<String>();
			roles.add("driver.security.identity.role#user");
			userSecProfId = registryService.registerProfile(ResourcesGenerator.generateSecProf(userProfId, roles));
			assertNotNull(userSecProfId);
			
			AuthenticateRequest userRequest = new AuthenticateRequest();
			TypedString[] userPrincipals = new TypedString[1];
			userPrincipals[0] = new TypedString(userEmail,"login");
			userRequest.setPrincipals(userPrincipals);
			TypedString[] userCredentials = new TypedString[1];
			userCredentials[0] = new TypedString("driver","password");
			userRequest.setCredentials(userCredentials);
			AuthenticateResp userResponse = a2Service.authenticate(userRequest);
			assertNotNull(userResponse);
			userSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
			String secCtxIdChain = null;
			SimpleContextRecoder recoder = new SimpleContextRecoder();
			CodingContext ctx = new CodingContext();
	//		ctx.secCtxId = serviceResponse.getContextId();
			ctx.secCtxId = serviceSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
	//		ctx.secCtxId = userResponse.getContextId();
			ctx.secCtxId = userSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
			
			AuthorizeRequest authorizeRequest = new AuthorizeRequest();
	//		authorizeRequest.setContextId(secCtxIdChain);
	//		secCtx are passed to the tomcat filter using threadLocal
			A2ServiceImpl.threadLocal.set(secCtxIdChain);
	
			authorizeRequest.setResource(new TypedString("profile"));
			authorizeRequest.setAction(new TypedString("view"));
			AuthorizeResp authorizeResponse = a2Service.authorize(authorizeRequest);
			
			assertNotNull(authorizeResponse);
			assertTrue(authorizeResponse.isAuthorized());
			
			assertFalse(authorizeResponse.hasErrors());
			assertTrue(authorizeResponse.hasObligations());
			assertEquals(1, authorizeResponse.getObligations().length);
			Obligation oblig = authorizeResponse.getObligations()[0];
			assertEquals(2, oblig.getAttributes().length);
			Attribute attrResource = oblig.getAttributes()[0];
			assertEquals("resource", attrResource.getKey());
			assertEquals("http://www.w3.org/2001/XMLSchema#string", attrResource.getType());
			assertEquals("profile", attrResource.getValue());

		} finally {
			if (serviceSecCtxId!=null)
				registryService.deleteProfile(serviceSecCtxId);
			if (serviceProfId!=null)
				registryService.deleteProfile(serviceProfId);
			if (userSecCtxId!=null)
				registryService.deleteProfile(userSecCtxId);
			if (userSecProfId!=null)
				registryService.deleteProfile(userSecProfId);
			if (userProfId!=null)
				registryService.deleteProfile(userProfId);
		}

	}

	@SuppressWarnings("unchecked")
	public void testInvalidate() throws Exception {
		String serviceProfId = null;
		String serviceSecCtxId = null;
		String userProfId = null;
		String userSecProfId = null;
		String userSecCtxId = null;
		try {
//			uiservice authentication
			String uiserviceId = "uiservice1";
			String serviceProfile = ResourcesGenerator.generateSecProf(uiserviceId, null);
			serviceProfId = registryService.registerProfile(serviceProfile);
			assertNotNull(serviceProfId);
			AuthenticateRequest serviceRequest = new AuthenticateRequest();
			TypedString[] serviceRrincipals = new TypedString[1];
			serviceRrincipals[0] = new TypedString(uiserviceId,"certificate");
			serviceRequest.setPrincipals(serviceRrincipals);
			AuthenticateResp serviceResponse = a2Service.authenticate(serviceRequest);
			assertNotNull(serviceResponse);
			serviceSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
//			user authentication
			String userEmail = "somebode@nohost.eu";
			userProfId = registryService.registerProfile(ResourcesGenerator.generateUserProf(userEmail));
			assertNotNull(userProfId);
			Set<String> roles = new HashSet<String>();
			roles.add("driver.security.identity.role#user");
			userSecProfId = registryService.registerProfile(ResourcesGenerator.generateSecProf(userProfId, roles));
			assertNotNull(userSecProfId);
			
			AuthenticateRequest userRequest = new AuthenticateRequest();
			TypedString[] userPrincipals = new TypedString[1];
			userPrincipals[0] = new TypedString(userEmail,"login");
			userRequest.setPrincipals(userPrincipals);
			TypedString[] userCredentials = new TypedString[1];
			userCredentials[0] = new TypedString("driver","password");
			userRequest.setCredentials(userCredentials);
			AuthenticateResp userResponse = a2Service.authenticate(userRequest);
			assertNotNull(userResponse);
			userSecCtxId = (String) A2ServiceImpl.threadLocal.get();
			
			String secCtxIdChain = null;
			SimpleContextRecoder recoder = new SimpleContextRecoder();
			CodingContext ctx = new CodingContext();
	//		ctx.secCtxId = serviceResponse.getContextId();
			ctx.secCtxId = serviceSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
	//		ctx.secCtxId = userResponse.getContextId();
			ctx.secCtxId = userSecCtxId;
			secCtxIdChain = recoder.encode(ctx, secCtxIdChain, null);
			
			AuthorizeRequest authorizeRequest = new AuthorizeRequest();
	//		authorizeRequest.setContextId(secCtxIdChain);
	//		secCtx are passed to the tomcat filter using threadLocal
			A2ServiceImpl.threadLocal.set(secCtxIdChain);
	
			authorizeRequest.setResource(new TypedString("profile"));
			authorizeRequest.setAction(new TypedString("view"));
			AuthorizeResp authorizeResponse = a2Service.authorize(authorizeRequest);
			
			assertNotNull(authorizeResponse);
			assertTrue(authorizeResponse.isAuthorized());
			assertFalse(authorizeResponse.hasErrors());

			InvalidateRequest invRequest = new InvalidateRequest();
			invRequest.setInvalidContextId(userSecCtxId);
			InvalidateResp invResponse = a2Service.invalidate(invRequest);
			assertNotNull(invResponse);
			assertTrue(invResponse.getErrors().length==0);
//			System.out.println("Trying to authorize once again, but without SecCtx...");
			authorizeResponse = a2Service.authorize(authorizeRequest);
			assertFalse(authorizeResponse.isAuthorized());
//			trying to delete SecCtx which is already deleted
			invResponse = a2Service.invalidate(invRequest);
			assertNotNull(invResponse);
			assertFalse(invResponse.getErrors().length==0);
			
		} finally {
			if (serviceSecCtxId!=null)
				registryService.deleteProfile(serviceSecCtxId);
			if (serviceProfId!=null)
				registryService.deleteProfile(serviceProfId);
			if (userSecCtxId!=null)
				registryService.deleteProfile(userSecCtxId);
			if (userSecProfId!=null)
				registryService.deleteProfile(userSecProfId);
			if (userProfId!=null)
				registryService.deleteProfile(userProfId);
		}

	}
	
	
	TypedString findIdentity(String identityType, TypedString[] identities) {
		if (identityType==null || identities==null)
			return null;
		for (int i = 0; i < identities.length; i++) {
			if (identityType.equals(identities[i].getType()))
				return identities[i];
		}
		return null;
	}

	static boolean isNameAmongNames(List<String> names, String name) {
		if (names==null || name==null)
			return false;
		for (String currentName : names) {
			if (name.equals(currentName))
				return true;
		}
		return false;
	}
	
}
