diff --git a/source/java/org/alfresco/repo/remoteconnector/LocalWebScriptConnectorServiceImpl.java b/source/java/org/alfresco/repo/remoteconnector/LocalWebScriptConnectorServiceImpl.java
new file mode 100644
index 0000000000..7ed460a5d9
--- /dev/null
+++ b/source/java/org/alfresco/repo/remoteconnector/LocalWebScriptConnectorServiceImpl.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.remoteconnector;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.acegisecurity.Authentication;
+
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorRequest;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorService;
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.security.authentication.AuthenticationException;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.web.scripts.BaseWebScriptTest;
+import org.alfresco.repo.web.scripts.servlet.BasicHttpAuthenticatorFactory;
+import org.alfresco.repo.web.scripts.servlet.BasicHttpAuthenticatorFactory.BasicHttpAuthenticator;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.ParseException;
+import org.springframework.extensions.webscripts.Authenticator;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.TestWebScriptServer;
+import org.springframework.extensions.webscripts.TestWebScriptServer.Request;
+import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
+import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory;
+import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
+import org.springframework.extensions.webscripts.servlet.WebScriptServletResponse;
+
+/**
+ * Testing implementation of {@link RemoteConnectorService} which talks to
+ * the local webscripts only
+ *
+ * @author Nick Burch
+ * @since 4.0.2
+ */
+public class LocalWebScriptConnectorServiceImpl implements RemoteConnectorService
+{
+ /**
+ * The logger
+ */
+ private static Log logger = LogFactory.getLog(LocalWebScriptConnectorServiceImpl.class);
+
+ private WebScriptHelper helper;
+ private LocalAndRemoteAuthenticator auth;
+
+ public LocalWebScriptConnectorServiceImpl(BaseWebScriptTest webScriptTest) throws Exception
+ {
+ this.helper = new WebScriptHelper(webScriptTest);
+ this.auth = new LocalAndRemoteAuthenticator(webScriptTest);
+ }
+
+ /**
+ * Builds a new Request object
+ */
+ public RemoteConnectorRequest buildRequest(String url, String method)
+ {
+ // Ensure we accept this URL
+ String local = "http://localhost:8080/alfresco/";
+ String service = "/service/";
+ if (url.startsWith(local))
+ {
+ // Good, that's probably us, make it a relative url
+ url = url.substring(local.length()-1);
+
+ // Make sure it's a service one
+ if (url.startsWith(service))
+ {
+ // Strip off and use
+ url = url.substring(service.length()-1);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Only /service/ local URLs are supported, can't handle " + url);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not a local URL: " + url);
+ }
+
+ // Build and return
+ return new RemoteConnectorRequestImpl(url, method);
+ }
+
+ /**
+ * Builds a new Request object, using HttpClient method descriptions
+ */
+ public RemoteConnectorRequest buildRequest(String url, Class extends HttpMethodBase> method)
+ {
+ // Get the method name
+ String methodName;
+ try
+ {
+ HttpMethodBase httpMethod = method.getConstructor(String.class).newInstance(url);
+ methodName = httpMethod.getName();
+ }
+ catch(Exception e)
+ {
+ throw new AlfrescoRuntimeException("Error identifying method name", e);
+ }
+
+ // Build and return
+ return buildRequest(url, methodName);
+ }
+
+ /**
+ * Executes the specified request, and return the response
+ */
+ public RemoteConnectorResponse executeRequest(RemoteConnectorRequest request) throws IOException, AuthenticationException
+ {
+ // Convert the request object
+ RemoteConnectorRequestImpl requestImpl = (RemoteConnectorRequestImpl)request;
+ Request req = new Request(request.getMethod(), request.getURL());
+ req.setType(request.getContentType());
+
+ if (request.getRequestBody() != null)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ requestImpl.getRequestBody().writeRequest(baos);
+ req.setBody(baos.toByteArray());
+ }
+
+ // Log
+ if (logger.isInfoEnabled())
+ logger.info("Performing local " + request.getMethod() + " request to " + request.getURL());
+
+ // Capture the user details, as they may be changed during the request processing
+ Authentication fullAuth = AuthenticationUtil.getFullAuthentication();
+ String runAsUser = AuthenticationUtil.getRunAsUser();
+
+ // If they've specified Authentication details in the request, clear our security context
+ // and switch to that user, to avoid our context confusing the real request
+ Header authHeader = null;
+ Map headers = new HashMap();
+ for (Header header : request.getRequestHeaders())
+ {
+ if (header.getName().equals("Authorization"))
+ {
+ authHeader = header;
+ }
+ headers.put(header.getName(), header.getValue());
+ }
+ if (authHeader != null)
+ {
+ AuthenticationUtil.clearCurrentSecurityContext();
+ if (logger.isDebugEnabled())
+ logger.debug("HTTP Authorization found for the request, clearing security context, Auth is " + authHeader);
+ }
+ req.setHeaders(headers);
+
+ // Execute the request against the WebScript Test Framework
+ Response resp;
+ try
+ {
+ resp = helper.sendRequest(req, -1);
+ }
+ catch (Exception e)
+ {
+ throw new AlfrescoRuntimeException("Problem requesting", e);
+ }
+
+ // Reset the user details, now we're done performing the request
+ AuthenticationUtil.setFullAuthentication(fullAuth);
+ if (runAsUser != null && !runAsUser.equals(fullAuth.getName()))
+ {
+ AuthenticationUtil.setRunAsUser(runAsUser);
+ }
+
+ // Log
+ if (logger.isInfoEnabled())
+ logger.info("Response to request was " + resp.getStatus() + " - " + resp);
+
+ // Check the status
+ if (resp.getStatus() == Status.STATUS_UNAUTHORIZED)
+ {
+ throw new AuthenticationException("Not Authorized to access this resource");
+ }
+ if (resp.getStatus() == Status.STATUS_FORBIDDEN)
+ {
+ throw new AuthenticationException("Forbidden to access this resource");
+ }
+ // TODO Handle others too
+
+ // Convert the response
+ String charset = null;
+ String contentType = resp.getContentType();
+ if (contentType != null && contentType.contains("charset="))
+ {
+ int splitAt = contentType.indexOf("charset=") + "charset=".length();
+ charset = contentType.substring(splitAt);
+ }
+
+ InputStream body = new ByteArrayInputStream(resp.getContentAsByteArray());
+ Header[] respHeaders = new Header[0]; // TODO Can't easily get the list...
+
+ RemoteConnectorResponse response = new RemoteConnectorResponseImpl(request, contentType, charset, respHeaders, body);
+ return response;
+ }
+
+ /**
+ * Executes the given request, requesting a JSON response, and
+ * returns the parsed JSON received back
+ *
+ * @throws ParseException If the response is not valid JSON
+ */
+ public JSONObject executeJSONRequest(RemoteConnectorRequest request) throws ParseException, IOException, AuthenticationException
+ {
+ return RemoteConnectorServiceImpl.doExecuteJSONRequest(request, this);
+ }
+
+ private static class WebScriptHelper
+ {
+ private BaseWebScriptTest test;
+ private Method sendRequest;
+
+ private WebScriptHelper(BaseWebScriptTest test) throws Exception
+ {
+ this.test = test;
+
+ sendRequest = BaseWebScriptTest.class.getDeclaredMethod("sendRequest", Request.class, Integer.TYPE);
+ sendRequest.setAccessible(true);
+ }
+
+ private Response sendRequest(Request request, int expectedStatus) throws Exception
+ {
+ return (Response)sendRequest.invoke(test, request, expectedStatus);
+ }
+ }
+
+ /**
+ * A wrapper around {@link BasicHttpAuthenticator}, which uses the
+ * Authentication Context if present, otherwise HTTP Auth
+ */
+ private static class LocalAndRemoteAuthenticator implements ServletAuthenticatorFactory
+ {
+ private BasicHttpAuthenticatorFactory httpAuthFactory;
+
+ private LocalAndRemoteAuthenticator(BaseWebScriptTest test) throws Exception
+ {
+ // Get the test server
+ Method getServer = BaseWebScriptTest.class.getDeclaredMethod("getServer");
+ getServer.setAccessible(true);
+ TestWebScriptServer server = (TestWebScriptServer)getServer.invoke(test);
+
+ // Grab the real auth factory from the context
+ httpAuthFactory = (BasicHttpAuthenticatorFactory)server.getApplicationContext().getBean("webscripts.authenticator.basic");
+
+ // Wire us into the test
+ server.setServletAuthenticatorFactory(this);
+ }
+
+ @Override
+ public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
+ {
+ // Do we have current details?
+ if (AuthenticationUtil.getFullyAuthenticatedUser() != null)
+ {
+ // There are already details existing
+ // Allow these to be kept and used
+ logger.debug("Existing Authentication found, remaining as " + AuthenticationUtil.getFullyAuthenticatedUser());
+ return null;
+ }
+
+ // Fall back to the http auth one
+ logger.debug("No existing Authentication found, using regular HTTP Auth");
+ return httpAuthFactory.create(req, res);
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/remoteticket/RemoteAlfrescoTicketServiceTest.java b/source/java/org/alfresco/repo/remoteticket/RemoteAlfrescoTicketServiceTest.java
new file mode 100644
index 0000000000..4ce134ba5f
--- /dev/null
+++ b/source/java/org/alfresco/repo/remoteticket/RemoteAlfrescoTicketServiceTest.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.remoteticket;
+
+import org.alfresco.service.cmr.remoteticket.NoCredentialsFoundException;
+import org.alfresco.service.cmr.remoteticket.NoSuchSystemException;
+import org.alfresco.service.cmr.remoteticket.RemoteAlfrescoTicketInfo;
+import org.alfresco.service.cmr.remoteticket.RemoteAlfrescoTicketService;
+import org.alfresco.repo.remoteconnector.LocalWebScriptConnectorServiceImpl;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.cache.EhCacheAdapter;
+import org.alfresco.repo.remotecredentials.PasswordCredentialsInfoImpl;
+import org.alfresco.repo.security.authentication.AuthenticationException;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.repo.web.scripts.BaseWebScriptTest;
+import org.alfresco.service.cmr.remotecredentials.BaseCredentialsInfo;
+import org.alfresco.service.cmr.remotecredentials.RemoteCredentialsService;
+import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.util.PropertyMap;
+
+/**
+ * Tests for {@link RemoteAlfrescoTicketServiceImpl}, which work by
+ * looping back to the local repo. Because this tests talks to local
+ * webscripts, it needs to be run in the Remote API package
+ *
+ * TODO Test OAuth support, once added
+ *
+ * @author Nick Burch
+ * @since 4.0.2
+ */
+public class RemoteAlfrescoTicketServiceTest extends BaseWebScriptTest
+{
+ private static final String TEST_REMOTE_SYSTEM_ID = "testingRemoteSystem";
+ private static final String INVALID_REMOTE_SYSTEM_ID = "testingInvalidRemoteSystem";
+
+ private MutableAuthenticationService authenticationService;
+ private RetryingTransactionHelper retryingTransactionHelper;
+ private PersonService personService;
+
+ private RemoteAlfrescoTicketService remoteAlfrescoTicketService;
+ private RemoteCredentialsService remoteCredentialsService;
+ private EhCacheAdapter ticketsCache;
+
+ private static final String USER_ONE = "UserOneSecondToo";
+ private static final String USER_TWO = "UserTwoSecondToo";
+ private static final String PASSWORD = "passwordTEST";
+
+ // General methods
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ this.retryingTransactionHelper = (RetryingTransactionHelper)getServer().getApplicationContext().getBean("retryingTransactionHelper");
+ this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService");
+ this.personService = (PersonService)getServer().getApplicationContext().getBean("PersonService");
+
+ this.remoteAlfrescoTicketService = (RemoteAlfrescoTicketService)getServer().getApplicationContext().getBean("remoteAlfrescoTicketService");
+ this.remoteCredentialsService = (RemoteCredentialsService)getServer().getApplicationContext().getBean("RemoteCredentialsService");
+ this.ticketsCache = (EhCacheAdapter)getServer().getApplicationContext().getBean("remoteAlfrescoTicketService.ticketsCache");
+
+ // Do the setup as admin
+ AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
+
+ // Add our local system as a remote service
+ remoteAlfrescoTicketService.registerRemoteSystem(TEST_REMOTE_SYSTEM_ID, "http://localhost:8080/alfresco/service/", null);
+
+ // Wire up the loop-back connector
+ ((RemoteAlfrescoTicketServiceImpl)remoteAlfrescoTicketService).setRemoteConnectorService(
+ new LocalWebScriptConnectorServiceImpl(this));
+
+ // Ensure the invalid one isn't registered
+ remoteAlfrescoTicketService.registerRemoteSystem(INVALID_REMOTE_SYSTEM_ID, null, null);
+
+ // Create users
+ createUser(USER_ONE);
+ createUser(USER_TWO);
+
+ // Do tests as first user
+ AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+
+ // Admin user required to delete user
+ AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
+
+ // Delete the users, which also zaps their credentials
+ if(personService.personExists(USER_ONE))
+ {
+ personService.deletePerson(USER_ONE);
+ }
+ if(this.authenticationService.authenticationExists(USER_ONE))
+ {
+ this.authenticationService.deleteAuthentication(USER_ONE);
+ }
+
+ if(personService.personExists(USER_TWO))
+ {
+ personService.deletePerson(USER_TWO);
+ }
+ if(this.authenticationService.authenticationExists(USER_TWO))
+ {
+ this.authenticationService.deleteAuthentication(USER_TWO);
+ }
+
+ // Unregister the system
+ remoteAlfrescoTicketService.registerRemoteSystem(TEST_REMOTE_SYSTEM_ID, null, null);
+ }
+
+ private void createUser(String userName)
+ {
+ // if user with given user name doesn't already exist then create user
+ if (this.authenticationService.authenticationExists(userName) == false)
+ {
+ // create user
+ this.authenticationService.createAuthentication(userName, PASSWORD.toCharArray());
+
+ // create person properties
+ PropertyMap personProps = new PropertyMap();
+ personProps.put(ContentModel.PROP_USERNAME, userName);
+ personProps.put(ContentModel.PROP_FIRSTNAME, "First");
+ personProps.put(ContentModel.PROP_LASTNAME, "Last");
+ personProps.put(ContentModel.PROP_EMAIL, "FirstName123.LastName123@email.com");
+ personProps.put(ContentModel.PROP_JOBTITLE, "JobTitle123");
+ personProps.put(ContentModel.PROP_JOBTITLE, "Organisation123");
+
+ // create person node for user
+ this.personService.createPerson(personProps);
+ }
+ }
+
+ /**
+ * Getting, storing and fetching credentials
+ */
+ public void testGetStoreGetCredentials() throws Exception
+ {
+ // Run this test initially as the first user
+ AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
+
+
+ // First, try an invalid system
+ try
+ {
+ remoteAlfrescoTicketService.getRemoteCredentials(INVALID_REMOTE_SYSTEM_ID);
+ fail("Shouldn't work for an invalid system");
+ }
+ catch(NoSuchSystemException e) {}
+ try
+ {
+ remoteAlfrescoTicketService.storeRemoteCredentials(INVALID_REMOTE_SYSTEM_ID, null, null);
+ fail("Shouldn't work for an invalid system");
+ }
+ catch(NoSuchSystemException e) {}
+
+
+ // Our user starts out without credentials
+ BaseCredentialsInfo credentials =
+ remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(null, credentials);
+
+
+ // Try to store some invalid credentials (real user, but password wrong)
+ try
+ {
+ remoteAlfrescoTicketService.storeRemoteCredentials(TEST_REMOTE_SYSTEM_ID, USER_ONE, "invalid");
+ fail("Credentials invalid, shouldn't be allowed");
+ }
+ catch (AuthenticationException e) {}
+
+ // And an invalid user
+ try
+ {
+ remoteAlfrescoTicketService.storeRemoteCredentials(TEST_REMOTE_SYSTEM_ID, "thisUSERdoesNOTexist", "invalid");
+ fail("Credentials invalid, shouldn't be allowed");
+ }
+ catch (AuthenticationException e) {}
+
+
+ // Still none there
+ credentials = remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(null, credentials);
+
+
+ // Store some valid ones
+ credentials = remoteAlfrescoTicketService.storeRemoteCredentials(TEST_REMOTE_SYSTEM_ID, USER_ONE, PASSWORD);
+ assertNotNull(credentials);
+ assertEquals(TEST_REMOTE_SYSTEM_ID, credentials.getRemoteSystemName());
+ assertEquals(USER_ONE, credentials.getRemoteUsername());
+
+ // Check we can find them
+ credentials = remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(credentials);
+ assertEquals(TEST_REMOTE_SYSTEM_ID, credentials.getRemoteSystemName());
+ assertEquals(USER_ONE, credentials.getRemoteUsername());
+
+
+ // Store some different, valid credentials for the user
+ credentials = remoteAlfrescoTicketService.storeRemoteCredentials(TEST_REMOTE_SYSTEM_ID, USER_TWO, PASSWORD);
+ assertNotNull(credentials);
+ assertEquals(TEST_REMOTE_SYSTEM_ID, credentials.getRemoteSystemName());
+ assertEquals(USER_TWO, credentials.getRemoteUsername());
+
+ // Check we see the change
+ credentials = remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(credentials);
+ assertEquals(TEST_REMOTE_SYSTEM_ID, credentials.getRemoteSystemName());
+ assertEquals(USER_TWO, credentials.getRemoteUsername());
+
+
+ // Switch to the other user, no credentials there
+ AuthenticationUtil.setFullyAuthenticatedUser(USER_TWO);
+ credentials = remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(null, credentials);
+
+
+ // Switch back, and delete
+ AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
+ credentials = remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(credentials);
+
+ boolean deleted = remoteAlfrescoTicketService.deleteRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(true, deleted);
+
+ // Will have gone
+ credentials = remoteAlfrescoTicketService.getRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(null, credentials);
+
+ // Double delete is reported
+ deleted = remoteAlfrescoTicketService.deleteRemoteCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(false, deleted);
+ }
+
+ /**
+ * Getting cached and non-cached credentials
+ */
+ public void testGetTicket() throws Exception
+ {
+ // Run this test initially as the first user
+ AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
+
+
+ // First, try an invalid system
+ try
+ {
+ remoteAlfrescoTicketService.getAlfrescoTicket(INVALID_REMOTE_SYSTEM_ID);
+ fail("Shouldn't work for an invalid system");
+ }
+ catch(NoSuchSystemException e) {}
+ try
+ {
+ remoteAlfrescoTicketService.refetchAlfrescoTicket(INVALID_REMOTE_SYSTEM_ID);
+ fail("Shouldn't work for an invalid system");
+ }
+ catch(NoSuchSystemException e) {}
+
+
+ // Can't get or refresh if no credentials exist
+ try
+ {
+ remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ fail("Shouldn't work when no credentials");
+ }
+ catch(NoCredentialsFoundException e) {}
+ try
+ {
+ remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ fail("Shouldn't work when no credentials");
+ }
+ catch(NoCredentialsFoundException e) {}
+
+
+ // Have some stored
+ remoteAlfrescoTicketService.storeRemoteCredentials(TEST_REMOTE_SYSTEM_ID, USER_ONE, PASSWORD);
+
+
+ // A ticket will now exist
+ RemoteAlfrescoTicketInfo ticket = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket);
+ assertNotNull(ticket.getAsUrlParameters());
+
+
+ // Ask again, will get the same one
+ RemoteAlfrescoTicketInfo ticket2 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket2);
+ assertEquals(ticket.getAsUrlParameters(), ticket2.getAsUrlParameters());
+
+
+ // Force a re-fetch, will get another
+ RemoteAlfrescoTicketInfo ticket3 = remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket3);
+ assertNotSame(ticket.getAsUrlParameters(), ticket3.getAsUrlParameters());
+
+ // Ask for the ticket again, get the 2nd one again
+ RemoteAlfrescoTicketInfo ticket4 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket4);
+ assertEquals(ticket3.getAsUrlParameters(), ticket4.getAsUrlParameters());
+
+
+ // Zap from the cache, will trigger another to be fetched
+ ticketsCache.clear();
+
+ RemoteAlfrescoTicketInfo ticket5 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket5);
+ assertNotSame(ticket.getAsUrlParameters(), ticket5.getAsUrlParameters());
+ assertNotSame(ticket3.getAsUrlParameters(), ticket5.getAsUrlParameters());
+
+
+ // Change the password so it's no longer valid
+ PasswordCredentialsInfoImpl creds = (PasswordCredentialsInfoImpl)remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(creds);
+ creds.setRemotePassword("INVALID");
+ remoteCredentialsService.updateCredentials(creds);
+
+ // Currently will be marked as still working
+ assertEquals(true, creds.getLastAuthenticationSucceeded());
+
+
+ // Get will work, as ticket was previously cached
+ RemoteAlfrescoTicketInfo ticket6 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket6);
+ assertEquals(ticket5.getAsUrlParameters(), ticket6.getAsUrlParameters());
+
+ // Re-fetch will fail with authentication error
+ try
+ {
+ remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ fail("Shouldn't be able to refetch with wrong details");
+ }
+ catch(AuthenticationException e) {}
+
+ // Now a get will fail too, as the cache will be invalidated
+ try
+ {
+ remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ fail("Shouldn't be able to get after refresh with wrong details");
+ }
+ catch(AuthenticationException e) {}
+
+
+ // If we check the credentials, will now be marked as failing
+ creds = (PasswordCredentialsInfoImpl)remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(false, creds.getLastAuthenticationSucceeded());
+
+
+ // Change the password back to what it should be, and re-get
+ creds.setRemotePassword(PASSWORD);
+ remoteCredentialsService.updateCredentials(creds);
+
+ RemoteAlfrescoTicketInfo ticket7 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ assertNotNull(ticket7);
+ assertNotSame(ticket.getAsUrlParameters(), ticket7.getAsUrlParameters());
+ assertNotSame(ticket3.getAsUrlParameters(), ticket7.getAsUrlParameters());
+ assertNotSame(ticket5.getAsUrlParameters(), ticket7.getAsUrlParameters());
+
+ // Should now be marked as working again
+ creds = (PasswordCredentialsInfoImpl)remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(true, creds.getLastAuthenticationSucceeded());
+
+
+ // Check that failure can be marked in a read only transaction
+ creds.setRemotePassword("INVALID");
+ remoteCredentialsService.updateCredentials(creds);
+
+ retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute()
+ {
+ try
+ {
+ remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
+ fail("Shouldn't be able to refetch with wrong details");
+ }
+ catch(AuthenticationException e) {}
+ return null;
+ }
+ }, true, true);
+
+ // Check it was still marked as invalid, despite a read only transaction
+ creds = (PasswordCredentialsInfoImpl)remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
+ assertEquals(false, creds.getLastAuthenticationSucceeded());
+ }
+}