mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	125606 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125515 slanglois: MNT-16155 Update source headers - add new Copyrights for Java and JSP source files + automatic check in the build
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125788 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			744 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			744 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * #%L
 | |
|  * Alfresco Repository
 | |
|  * %%
 | |
|  * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | |
|  * %%
 | |
|  * This file is part of the Alfresco software. 
 | |
|  * If the software was purchased under a paid Alfresco license, the terms of 
 | |
|  * the paid license agreement will prevail.  Otherwise, the software is 
 | |
|  * provided under the following open source license terms:
 | |
|  * 
 | |
|  * 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 <http://www.gnu.org/licenses/>.
 | |
|  * #L%
 | |
|  */
 | |
| package org.alfresco.repo.remotecredentials;
 | |
| 
 | |
| import java.io.Serializable;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Collections;
 | |
| import java.util.HashMap;
 | |
| import java.util.HashSet;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.Set;
 | |
| 
 | |
| import org.alfresco.query.EmptyPagingResults;
 | |
| import org.alfresco.query.ListBackedPagingResults;
 | |
| import org.alfresco.query.PagingRequest;
 | |
| import org.alfresco.query.PagingResults;
 | |
| import org.alfresco.repo.model.Repository;
 | |
| import org.alfresco.repo.node.SystemNodeUtils;
 | |
| import org.alfresco.repo.security.authentication.AuthenticationUtil;
 | |
| import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
 | |
| import org.alfresco.service.cmr.dictionary.DictionaryService;
 | |
| import org.alfresco.service.cmr.remotecredentials.BaseCredentialsInfo;
 | |
| import org.alfresco.service.cmr.remotecredentials.RemoteCredentialsService;
 | |
| import org.alfresco.service.cmr.repository.ChildAssociationRef;
 | |
| import org.alfresco.service.cmr.repository.NodeRef;
 | |
| import org.alfresco.service.cmr.repository.NodeService;
 | |
| import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
 | |
| import org.alfresco.service.cmr.security.PermissionService;
 | |
| import org.alfresco.service.namespace.NamespaceService;
 | |
| import org.alfresco.service.namespace.QName;
 | |
| import org.alfresco.service.namespace.RegexQNamePattern;
 | |
| import org.alfresco.util.GUID;
 | |
| import org.alfresco.util.Pair;
 | |
| import org.apache.commons.logging.Log;
 | |
| import org.apache.commons.logging.LogFactory;
 | |
| 
 | |
| /**
 | |
|  * An Implementation of the {@link RemoteCredentialsService}
 | |
|  * 
 | |
|  * @author Nick Burch
 | |
|  * @since Odin
 | |
|  */
 | |
| public class RemoteCredentialsServiceImpl implements RemoteCredentialsService
 | |
| {
 | |
|     /**
 | |
|      * The logger
 | |
|      */
 | |
|     private static Log logger = LogFactory.getLog(RemoteCredentialsServiceImpl.class);
 | |
|     
 | |
|     /**
 | |
|      * The name of the System Container used to hold Shared Credentials.
 | |
|      * This isn't final, as unit tests change it to avoid trampling on
 | |
|      *  the real credentials.
 | |
|      */
 | |
|     private static String SHARED_CREDENTIALS_CONTAINER_NAME = "remote_credentials";
 | |
| 
 | |
|     private Repository repositoryHelper;
 | |
|     private NodeService nodeService;
 | |
|     private NamespaceService namespaceService;
 | |
|     private PermissionService permissionService;
 | |
|     private DictionaryService dictionaryService;
 | |
|     
 | |
|     /**
 | |
|      * Controls which Factory will be used to create {@link BaseCredentialsInfo}
 | |
|      *  instances for a given node, based on the type.
 | |
|      * eg rc:passwordCredentials -> PasswordCredentialsFactory
 | |
|      */
 | |
|     private Map<QName,RemoteCredentialsInfoFactory> credentialsFactories = new HashMap<QName, RemoteCredentialsInfoFactory>();
 | |
| 
 | |
|     
 | |
|     public void setNodeService(NodeService nodeService)
 | |
|     {
 | |
|         this.nodeService = nodeService;
 | |
|     }
 | |
| 
 | |
|     public void setNamespaceService(NamespaceService namespaceService)
 | |
|     {
 | |
|         this.namespaceService = namespaceService;
 | |
|     }
 | |
| 
 | |
|     public void setPermissionService(PermissionService permissionService)
 | |
|     {
 | |
|         this.permissionService = permissionService;
 | |
|     }
 | |
| 
 | |
|     public void setDictionaryService(DictionaryService dictionaryService)
 | |
|     {
 | |
|         this.dictionaryService = dictionaryService;
 | |
|     }
 | |
|     
 | |
|     public void setRepositoryHelper(Repository repositoryHelper)
 | |
|     {
 | |
|         this.repositoryHelper = repositoryHelper;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Registers a number of new factories
 | |
|      */
 | |
|     public void setCredentialsFactories(Map<String,RemoteCredentialsInfoFactory> factories)
 | |
|     {
 | |
|         // Convert, eg rc:passwordCredentials -> qname version, then register
 | |
|         for (String type : factories.keySet())
 | |
|         {
 | |
|             RemoteCredentialsInfoFactory factory = factories.get(type);
 | |
|             QName typeQ = QName.createQName(type, namespaceService);
 | |
|             registerCredentialsFactory(typeQ, factory);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Registers a new Factory to produce {@link BaseCredentialsInfo} objects
 | |
|      *  for a given data type.
 | |
|      * This provides an alternative to {@link #setCredentialsFactories(Map)}
 | |
|      *  to allow the registering of a new type without overriding all of them.
 | |
|      *  
 | |
|      * @param credentialsType The object type
 | |
|      * @param factory The Factory to use to create this type with
 | |
|      */
 | |
|     public void registerCredentialsFactory(QName credentialsType, RemoteCredentialsInfoFactory factory)
 | |
|     {
 | |
|         // Check the hierarchy is valid
 | |
|         if (! dictionaryService.isSubClass(credentialsType, RemoteCredentialsModel.TYPE_CREDENTIALS_BASE))
 | |
|         {
 | |
|             logger.warn("Unable to register credentials factory for " + credentialsType + 
 | |
|                         " as that type doesn't inherit from " + RemoteCredentialsModel.TYPE_CREDENTIALS_BASE);
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         // Log the new type
 | |
|         if (logger.isDebugEnabled())
 | |
|             logger.debug("Registering credentials factory for " + credentialsType + " of " + factory);
 | |
| 
 | |
|         // Store it
 | |
|         credentialsFactories.put(credentialsType, factory);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Provides a read only copy of the credentials factories, useful in unit tests
 | |
|      */
 | |
|     protected Map<QName,RemoteCredentialsInfoFactory> getCredentialsFactories()
 | |
|     {
 | |
|         return Collections.unmodifiableMap(credentialsFactories);
 | |
|     }
 | |
|     
 | |
|     // --------------------------------------------------------
 | |
|     
 | |
|     private static QName SHARED_CREDENTIALS_CONTAINER_QNAME = 
 | |
|         QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, SHARED_CREDENTIALS_CONTAINER_NAME); 
 | |
|     /**
 | |
|      * Gets the NodeRef of the holder of shared credentials remote systems.
 | |
|      * 
 | |
|      * This is stored under system
 | |
|      * 
 | |
|      * Protected, so that unit tests can make use of it
 | |
|      */
 | |
|     protected NodeRef getSharedContainerNodeRef(boolean required)
 | |
|     {
 | |
|         // Get the container, if available
 | |
|         NodeRef container = SystemNodeUtils.getSystemChildContainer(SHARED_CREDENTIALS_CONTAINER_QNAME, nodeService, repositoryHelper);
 | |
|         
 | |
|         // If it's needed, have it created
 | |
|         if (container == null && required)
 | |
|         {
 | |
|             // Lock and create
 | |
|             Pair<NodeRef,Boolean> details = null;
 | |
|             synchronized (this)
 | |
|             {
 | |
|                 details = SystemNodeUtils.getOrCreateSystemChildContainer(SHARED_CREDENTIALS_CONTAINER_QNAME, nodeService, repositoryHelper);
 | |
|             }
 | |
|             container = details.getFirst();
 | |
|             
 | |
|             // If created, set permissions
 | |
|             // Note - these must be kept in sync with the bootstrap file
 | |
|             if (details.getSecond())
 | |
|             {
 | |
|                 final NodeRef containerF = container;
 | |
|                 AuthenticationUtil.runAsSystem(new RunAsWork<Void>() {
 | |
|                     @Override
 | |
|                     public Void doWork() throws Exception
 | |
|                     {
 | |
|                         // Add the aspect
 | |
|                         nodeService.addAspect(containerF, RemoteCredentialsModel.ASPECT_REMOTE_CREDENTIALS_SYSTEM_CONTAINER, null);
 | |
| 
 | |
|                         // Set up the default permissions on the container
 | |
|                         // By default, anyone can add children, and read, but not edit other's credentials
 | |
|                         // (These can be changed later if needed by an administrator)
 | |
|                         permissionService.setInheritParentPermissions(containerF, false);
 | |
|                         permissionService.setPermission(
 | |
|                                 containerF, PermissionService.ALL_AUTHORITIES,
 | |
|                                 PermissionService.ADD_CHILDREN, true);
 | |
|                         permissionService.setPermission(
 | |
|                                 containerF, PermissionService.ALL_AUTHORITIES,
 | |
|                                 PermissionService.READ, true);
 | |
| 
 | |
|                         permissionService.setPermission(
 | |
|                                 containerF, PermissionService.OWNER_AUTHORITY,
 | |
|                                 PermissionService.FULL_CONTROL, true);
 | |
|                         
 | |
|                         return null;
 | |
|                     }
 | |
|                 });
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (container == null)
 | |
|         {
 | |
|             if (logger.isInfoEnabled())
 | |
|                 logger.info("Required System Folder " + SHARED_CREDENTIALS_CONTAINER_QNAME + " not yet created, will be lazy created on write");
 | |
|             return null;
 | |
|         }
 | |
|         return container;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Gets, creating as needed, the person credentials container for the given system
 | |
|      */
 | |
|     private NodeRef getPersonContainer(String remoteSystem, boolean lazyCreate)
 | |
|     {
 | |
|         // Get the person node
 | |
|         NodeRef person = repositoryHelper.getPerson();
 | |
|         if (person == null)
 | |
|         {
 | |
|             // Something's rather broken, the service security ought to prevent this 
 | |
|             throw new IllegalStateException("Person details required but none found! Running as " + AuthenticationUtil.getRunAsUser());
 | |
|         }
 | |
|         
 | |
|         // If we're in edit mode, ensure the correct aspect is applied
 | |
|         if (lazyCreate)
 | |
|         {
 | |
|             ensureCredentialsSystemContainer(person);
 | |
|         }
 | |
|         
 | |
|         // Find the container
 | |
|         return findRemoteSystemContainer(person, remoteSystem, lazyCreate);
 | |
|     }
 | |
|     /**
 | |
|      * Gets, creating as needed, the shared credentials container for the given system
 | |
|      */
 | |
|     private NodeRef getSharedContainer(String remoteSystem, boolean lazyCreate)
 | |
|     {
 | |
|         // Find the shared credentials container, under system
 | |
|         NodeRef systemContainer = getSharedContainerNodeRef(lazyCreate);
 | |
|         if (systemContainer == null) return null;
 | |
|         
 | |
|         // If we're in edit mode, ensure the correct aspect is applied
 | |
|         if (lazyCreate)
 | |
|         {
 | |
|             ensureCredentialsSystemContainer(systemContainer);
 | |
|         }
 | |
|         
 | |
|         // Find the container
 | |
|         return findRemoteSystemContainer(systemContainer, remoteSystem, lazyCreate);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Ensure the appropriate aspect is applied to the node which
 | |
|      *  will hold the Remote Credentials System 
 | |
|      */
 | |
|     private void ensureCredentialsSystemContainer(final NodeRef nodeRef)
 | |
|     {
 | |
|         AuthenticationUtil.runAsSystem(new RunAsWork<Void>() {
 | |
|             @Override
 | |
|             public Void doWork() throws Exception
 | |
|             {
 | |
|                 if (!nodeService.hasAspect(nodeRef, RemoteCredentialsModel.ASPECT_REMOTE_CREDENTIALS_SYSTEM_CONTAINER))
 | |
|                 {
 | |
|                     // Add the aspect
 | |
|                     nodeService.addAspect(nodeRef, RemoteCredentialsModel.ASPECT_REMOTE_CREDENTIALS_SYSTEM_CONTAINER, null);
 | |
|                     
 | |
|                     if (logger.isDebugEnabled())
 | |
|                         logger.debug("Added the Credentials Container aspect to " + nodeRef);
 | |
|                 }
 | |
|                 return null;
 | |
|             }
 | |
|         });
 | |
|     }
 | |
|     private NodeRef findRemoteSystemContainer(NodeRef nodeRef, String remoteSystem, boolean lazyCreate)
 | |
|     {
 | |
|         QName remoteSystemQName = QName.createQName(remoteSystem);
 | |
|         List<ChildAssociationRef> systems = nodeService.getChildAssocs(
 | |
|                 nodeRef, RemoteCredentialsModel.ASSOC_CREDENTIALS_SYSTEM, remoteSystemQName);
 | |
|         
 | |
|         NodeRef system = null;
 | |
|         if (systems.size() > 0)
 | |
|         {
 | |
|             system = systems.get(0).getChildRef();
 | |
|             
 | |
|             if (logger.isDebugEnabled())
 | |
|                 logger.debug("Resolved Remote Credentials Container for " + remoteSystem + " of " + system + " in parent " + nodeRef);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (lazyCreate)
 | |
|             {
 | |
|                 // Create, as the current user
 | |
|                 system = nodeService.createNode(
 | |
|                         nodeRef, RemoteCredentialsModel.ASSOC_CREDENTIALS_SYSTEM,
 | |
|                         QName.createQName(remoteSystem), RemoteCredentialsModel.TYPE_REMOTE_CREDENTIALS_SYSTEM
 | |
|                 ).getChildRef();
 | |
|                 
 | |
|                 if (logger.isDebugEnabled())
 | |
|                     logger.debug("Lazy created Remote Credentials Container for " + remoteSystem + 
 | |
|                                  " in parent " + nodeRef + ", new container is " + system);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (logger.isDebugEnabled())
 | |
|                     logger.debug("No Remote Credentials Container for " + remoteSystem + " found in " +
 | |
|                                  nodeRef + ", will be lazy created on write");
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return system;
 | |
|     }
 | |
| 
 | |
|     // --------------------------------------------------------
 | |
| 
 | |
|     @Override
 | |
|     public void deleteCredentials(BaseCredentialsInfo credentialsInfo)
 | |
|     {
 | |
|         if (credentialsInfo.getNodeRef() == null)
 | |
|         {
 | |
|             throw new IllegalArgumentException("Cannot delete Credentials which haven't been persisted yet!");
 | |
|         }
 | |
|         nodeService.deleteNode(credentialsInfo.getNodeRef());
 | |
|         
 | |
|         if (logger.isDebugEnabled())
 | |
|             logger.debug("Deleted credentials " + credentialsInfo + " from " + credentialsInfo.getNodeRef() + 
 | |
|                          " from Remote System " + credentialsInfo.getRemoteSystemName());
 | |
|         
 | |
|         // Leave the Remote System Container, in case special permissions
 | |
|         //  were previously applied to it that should be retained
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public BaseCredentialsInfo createPersonCredentials(String remoteSystem, BaseCredentialsInfo credentials)
 | |
|     {
 | |
|         NodeRef personContainer = getPersonContainer(remoteSystem, true);
 | |
|         return createCredentials(remoteSystem, personContainer, credentials);
 | |
|     }
 | |
|     @Override
 | |
|     public BaseCredentialsInfo createSharedCredentials(String remoteSystem, BaseCredentialsInfo credentials)
 | |
|     {
 | |
|         NodeRef shared = getSharedContainer(remoteSystem, true);
 | |
|         return createCredentials(remoteSystem, shared, credentials);
 | |
|     }
 | |
|     private BaseCredentialsInfo createCredentials(String remoteSystem, NodeRef remoteSystemNodeRef, BaseCredentialsInfo credentials)
 | |
|     {
 | |
|         if (credentials.getNodeRef() != null)
 | |
|         {
 | |
|             throw new IllegalArgumentException("Cannot create Credentials which have already been persisted!");
 | |
|         }
 | |
|         
 | |
|         // Check we know about the type
 | |
|         RemoteCredentialsInfoFactory factory = credentialsFactories.get(credentials.getCredentialsType());
 | |
|         if (factory == null)
 | |
|         {
 | |
|             throw new TypeConversionException("No Factory registered for type " + credentials.getCredentialsType());
 | |
|         }
 | |
|         
 | |
|         // Build the properties
 | |
|         Map<QName,Serializable> properties = RemoteCredentialsInfoFactory.FactoryHelper.getCoreCredentials(credentials);
 | |
|         properties.putAll( factory.serializeCredentials(credentials) );
 | |
|         
 | |
|         // Generate a name for it, which will be unique and doesn't need updating
 | |
|         QName name = QName.createQName(GUID.generate()); 
 | |
|         
 | |
|         // Add the node
 | |
|         NodeRef nodeRef = nodeService.createNode(
 | |
|                 remoteSystemNodeRef, RemoteCredentialsModel.ASSOC_CREDENTIALS,
 | |
|                 name, credentials.getCredentialsType(), properties
 | |
|         ).getChildRef();
 | |
|         
 | |
|         if (logger.isDebugEnabled())
 | |
|             logger.debug("Created new credentials at " + nodeRef + " for " + remoteSystem + " in " + 
 | |
|                          remoteSystemNodeRef + " of " + credentials);
 | |
|         
 | |
|         // Return the new object
 | |
|         return factory.createCredentials(
 | |
|                 credentials.getCredentialsType(), nodeRef,
 | |
|                 remoteSystem, remoteSystemNodeRef,
 | |
|                 nodeService.getProperties(nodeRef)
 | |
|         );
 | |
|     }
 | |
| 
 | |
| 
 | |
|     @Override
 | |
|     public BaseCredentialsInfo getPersonCredentials(String remoteSystem)
 | |
|     {
 | |
|         NodeRef personContainer = getPersonContainer(remoteSystem, false);
 | |
|         if (personContainer == null) return null;
 | |
| 
 | |
|         // Grab the children
 | |
|         List<ChildAssociationRef> credentials = 
 | |
|             nodeService.getChildAssocs(personContainer, RemoteCredentialsModel.ASSOC_CREDENTIALS, RegexQNamePattern.MATCH_ALL);
 | |
|         if (credentials.size() > 0)
 | |
|         {
 | |
|             NodeRef nodeRef = credentials.get(0).getChildRef();
 | |
|             return loadCredentials(remoteSystem, personContainer, nodeRef);
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
|     private BaseCredentialsInfo loadCredentials(String remoteSystem, NodeRef remoteSystemNodeRef, NodeRef credentialsNodeRef)
 | |
|     {
 | |
|         QName type = nodeService.getType(credentialsNodeRef);
 | |
|         RemoteCredentialsInfoFactory factory = credentialsFactories.get(type);
 | |
|         if (factory == null)
 | |
|         {
 | |
|             throw new TypeConversionException("No Factory registered for type " + type);
 | |
|         }
 | |
|         
 | |
|         // Wrap as an object
 | |
|         return factory.createCredentials(
 | |
|                 type, credentialsNodeRef,
 | |
|                 remoteSystem, remoteSystemNodeRef,
 | |
|                 nodeService.getProperties(credentialsNodeRef)
 | |
|         );
 | |
|     }
 | |
| 
 | |
| 
 | |
|     @Override
 | |
|     public BaseCredentialsInfo updateCredentials(BaseCredentialsInfo credentials)
 | |
|     {
 | |
|         if (credentials.getNodeRef() == null)
 | |
|         {
 | |
|             throw new IllegalArgumentException("Cannot update Credentials which haven't been persisted yet!");
 | |
|         }
 | |
|         
 | |
|         RemoteCredentialsInfoFactory factory = credentialsFactories.get(credentials.getCredentialsType());
 | |
|         if (factory == null)
 | |
|         {
 | |
|             throw new TypeConversionException("No Factory registered for type " + credentials.getCredentialsType());
 | |
|         }
 | |
|         
 | |
|         // Grab the current set of properties
 | |
|         Map<QName,Serializable> oldProps = nodeService.getProperties(credentials.getNodeRef());
 | |
|         
 | |
|         // Overwrite them with the credentials ones
 | |
|         Map<QName,Serializable> props = new HashMap<QName,Serializable>(oldProps);
 | |
|         props.putAll( RemoteCredentialsInfoFactory.FactoryHelper.getCoreCredentials(credentials) );
 | |
|         props.putAll( factory.serializeCredentials(credentials) );
 | |
|         
 | |
|         // Store
 | |
|         nodeService.setProperties(credentials.getNodeRef(), props);
 | |
|         
 | |
|         // For now, return as-is
 | |
|         return credentials;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public BaseCredentialsInfo updateCredentialsAuthenticationSucceeded(boolean succeeded, BaseCredentialsInfo credentials)
 | |
|     {
 | |
|         // We can't help with credentials that have never been stored
 | |
|         if (credentials.getNodeRef() == null)
 | |
|         {
 | |
|             throw new IllegalArgumentException("Cannot update Credentials which haven't been persisted yet!");
 | |
|         }
 | |
|         
 | |
|         // Return quickly if the credentials are already in the correct state 
 | |
|         if (succeeded == credentials.getLastAuthenticationSucceeded())
 | |
|         {
 | |
|             return credentials;
 | |
|         }
 | |
| 
 | |
|         
 | |
|         // Do the update 
 | |
|         nodeService.setProperty(credentials.getNodeRef(), RemoteCredentialsModel.PROP_LAST_AUTHENTICATION_SUCCEEDED, succeeded);
 | |
|         
 | |
|         // Update the object if we can
 | |
|         if (credentials instanceof AbstractCredentialsImpl)
 | |
|         {
 | |
|             ((AbstractCredentialsImpl)credentials).setLastAuthenticationSucceeded(succeeded);
 | |
|             return credentials;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             // Need to re-load
 | |
|             return loadCredentials(credentials.getRemoteSystemName(),
 | |
|                     credentials.getRemoteSystemContainerNodeRef(), credentials.getNodeRef());
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     
 | |
|     @Override
 | |
|     public PagingResults<String> listAllRemoteSystems(PagingRequest paging)
 | |
|     {
 | |
|         return listRemoteSystems(true, true, paging);
 | |
|     }
 | |
|     @Override
 | |
|     public PagingResults<String> listPersonRemoteSystems(PagingRequest paging)
 | |
|     {
 | |
|         return listRemoteSystems(true, false, paging);
 | |
|     }
 | |
|     @Override
 | |
|     public PagingResults<String> listSharedRemoteSystems(PagingRequest paging)
 | |
|     {
 | |
|         return listRemoteSystems(false, true, paging);
 | |
|     }
 | |
|     private PagingResults<String> listRemoteSystems(boolean people, boolean shared, PagingRequest paging)
 | |
|     {
 | |
|         List<NodeRef> search = new ArrayList<NodeRef>();
 | |
| 
 | |
|         if (people)
 | |
|         {
 | |
|             // Only search if it has the marker aspect
 | |
|             NodeRef person = repositoryHelper.getPerson();
 | |
|             if (nodeService.hasAspect(person, RemoteCredentialsModel.ASPECT_REMOTE_CREDENTIALS_SYSTEM_CONTAINER))
 | |
|             {
 | |
|                 search.add(person);
 | |
|             }
 | |
|         }
 | |
|         if (shared)
 | |
|         {
 | |
|             NodeRef system = getSharedContainerNodeRef(false);
 | |
|             if (system != null)
 | |
|             {
 | |
|                 search.add(system);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // If no suitable nodes were given, bail out
 | |
|         if (search.isEmpty())
 | |
|         {
 | |
|             return new EmptyPagingResults<String>();
 | |
|         }
 | |
|         
 | |
|         // Look for nodes
 | |
|         // Because all the information we need is held on the association, we don't
 | |
|         //  really need to use a Canned Query for this
 | |
|         Set<String> systems = new HashSet<String>();
 | |
|         for (NodeRef nodeRef : search)
 | |
|         {
 | |
|             List<ChildAssociationRef> refs = 
 | |
|                 nodeService.getChildAssocs(nodeRef, RemoteCredentialsModel.ASSOC_CREDENTIALS_SYSTEM, RegexQNamePattern.MATCH_ALL);
 | |
|             for (ChildAssociationRef ref : refs)
 | |
|             {
 | |
|                 // System Name is the association name, no namespace
 | |
|                 systems.add( ref.getQName().getLocalName() );
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Sort, then wrap as paged results
 | |
|         List<String> sortedSystems = new ArrayList<String>(systems);
 | |
|         Collections.sort(sortedSystems);
 | |
|         return new ListBackedPagingResults<String>(sortedSystems, paging);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public PagingResults<? extends BaseCredentialsInfo> listSharedCredentials(String remoteSystem,
 | |
|             QName credentialsType, PagingRequest paging)
 | |
|     {
 | |
|         // Get the container for that system
 | |
|         NodeRef container = getSharedContainer(remoteSystem, false);
 | |
|         if (container == null)
 | |
|         {
 | |
|             return new EmptyPagingResults<BaseCredentialsInfo>();
 | |
|         }
 | |
|         return listCredentials(new NodeRef[] {container}, remoteSystem, credentialsType, paging);
 | |
|     }
 | |
|     @Override
 | |
|     public PagingResults<? extends BaseCredentialsInfo> listPersonCredentials(String remoteSystem,
 | |
|             QName credentialsType, PagingRequest paging)
 | |
|     {
 | |
|         // Get the container for that system
 | |
|         NodeRef container = getPersonContainer(remoteSystem, false);
 | |
|         if (container == null)
 | |
|         {
 | |
|             return new EmptyPagingResults<BaseCredentialsInfo>();
 | |
|         }
 | |
|         return listCredentials(new NodeRef[] {container}, remoteSystem, credentialsType, paging);
 | |
|     }
 | |
|     @Override
 | |
|     public PagingResults<? extends BaseCredentialsInfo> listAllCredentials(String remoteSystem, QName credentialsType,
 | |
|             PagingRequest paging)
 | |
|     {
 | |
|         NodeRef personContainer = getPersonContainer(remoteSystem, false);
 | |
|         NodeRef systemContainer = getSharedContainer(remoteSystem, false);
 | |
|         if (personContainer == null && systemContainer == null)
 | |
|         {
 | |
|             return new EmptyPagingResults<BaseCredentialsInfo>();
 | |
|         }
 | |
|         return listCredentials(new NodeRef[] {personContainer, systemContainer}, remoteSystem, credentialsType, paging);
 | |
|     }
 | |
|     /**
 | |
|      * TODO This would probably be better done as a dedicated Canned Query
 | |
|      * We want to filter by Assoc Type and Child Node Type, and the node service
 | |
|      *  currently only allows you to do one or the other 
 | |
|      */
 | |
|     private PagingResults<? extends BaseCredentialsInfo> listCredentials(NodeRef[] containers, String remoteSystem, 
 | |
|             QName credentialsType, PagingRequest paging)
 | |
|     {
 | |
|         // NodeService wants an exhaustive list of the types
 | |
|         // Expand our single Credentials Type to cover all subtypes of it too
 | |
|         Set<QName> types = null;
 | |
|         if (credentialsType != null)
 | |
|         {
 | |
|             types = new HashSet<QName>( dictionaryService.getSubTypes(credentialsType, true) );
 | |
|             
 | |
|             if (logger.isDebugEnabled())
 | |
|                 logger.debug("Searching for credentials of " + credentialsType + " as types " + types);
 | |
|         }
 | |
|         
 | |
|         // Find all the credentials
 | |
|         List<ChildAssociationRef> credentials = new ArrayList<ChildAssociationRef>();
 | |
|         for (NodeRef nodeRef : containers)
 | |
|         {
 | |
|             if (nodeRef != null)
 | |
|             {
 | |
|                 // Find the credentials in the node
 | |
|                 List<ChildAssociationRef> allCreds = nodeService.getChildAssocs(
 | |
|                         nodeRef, RemoteCredentialsModel.ASSOC_CREDENTIALS, RegexQNamePattern.MATCH_ALL);
 | |
|                 
 | |
|                 // Filter them by type, if needed
 | |
|                 if (types == null || types.isEmpty())
 | |
|                 {
 | |
|                     // No type filtering needed
 | |
|                     credentials.addAll(allCreds);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     // Check the type of each one, and add if it matches
 | |
|                     for (ChildAssociationRef ref : allCreds)
 | |
|                     {
 | |
|                         NodeRef credNodeRef = ref.getChildRef();
 | |
|                         QName credType = nodeService.getType(credNodeRef);
 | |
|                         if (types.contains(credType))
 | |
|                         {
 | |
|                             // Matching type, accept
 | |
|                             credentials.add(ref);
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Did we find any?
 | |
|         if (credentials.isEmpty())
 | |
|         {
 | |
|             return new EmptyPagingResults<BaseCredentialsInfo>();
 | |
|         }
 | |
|         
 | |
|         // Excerpt
 | |
|         int start = paging.getSkipCount();
 | |
|         int end = Math.min(credentials.size(), start + paging.getMaxItems());
 | |
|         if (paging.getMaxItems() == 0)
 | |
|         {
 | |
|             end = credentials.size();
 | |
|         }
 | |
|         boolean hasMore = (end < credentials.size());
 | |
|         
 | |
|         List<ChildAssociationRef> wanted = credentials.subList(start, end);
 | |
|         
 | |
|         // Wrap and return
 | |
|         return new CredentialsPagingResults(wanted, credentials.size(), hasMore, remoteSystem); 
 | |
|     }
 | |
|     
 | |
|     // --------------------------------------------------------
 | |
|     
 | |
|     private class CredentialsPagingResults implements PagingResults<BaseCredentialsInfo>
 | |
|     {
 | |
|         private List<BaseCredentialsInfo> results;
 | |
|         private boolean hasMore;
 | |
|         private int size;
 | |
|         
 | |
|         private CredentialsPagingResults(List<ChildAssociationRef> refs, int size, boolean hasMore, String remoteSystem)
 | |
|         {
 | |
|             this.size = size;
 | |
|             this.hasMore = hasMore; 
 | |
|             
 | |
|             this.results = new ArrayList<BaseCredentialsInfo>(refs.size());
 | |
|             for (ChildAssociationRef ref : refs)
 | |
|             {
 | |
|                 this.results.add( loadCredentials(remoteSystem, ref.getParentRef(), ref.getChildRef()) );
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public List<BaseCredentialsInfo> getPage()
 | |
|         {
 | |
|             return results; 
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public Pair<Integer, Integer> getTotalResultCount()
 | |
|         {
 | |
|             return new Pair<Integer,Integer>(size,size);
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public boolean hasMoreItems()
 | |
|         {
 | |
|             return hasMore; 
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public String getQueryExecutionId()
 | |
|         {
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     // --------------------------------------------------------
 | |
| 
 | |
|     /** Unit testing use only! */
 | |
|     protected static String getSharedCredentialsSystemContainerName()
 | |
|     {
 | |
|         return SHARED_CREDENTIALS_CONTAINER_NAME;
 | |
|     }
 | |
|     protected static QName getSharedCredentialsSystemContainerQName()
 | |
|     {
 | |
|         return SHARED_CREDENTIALS_CONTAINER_QNAME;
 | |
|     }
 | |
|     /** Unit testing use only! Used to avoid tests affecting the real system container */
 | |
|     protected static void setSharedCredentialsSystemContainerName(String container)
 | |
|     {
 | |
|         SHARED_CREDENTIALS_CONTAINER_NAME = container;
 | |
|         SHARED_CREDENTIALS_CONTAINER_QNAME = 
 | |
|             QName.createQName(RemoteCredentialsModel.REMOTE_CREDENTIALS_MODEL_URL, SHARED_CREDENTIALS_CONTAINER_NAME);
 | |
|     }
 | |
| } |