mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	107541: Merged 5.0.N (5.0.3) to HEAD-BUG-FIX (5.1/Cloud) (PARTIAL MERGE)
      107413: Merged DEV to 5.0.N (5.0.3)
         106858 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Cleaning of Javadoc,
   107565: MNT-13545 Fix compilation after merge of Javadoc
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@107633 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			762 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			762 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2005-2014 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 <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
package org.alfresco.repo.policy;
 | 
						|
 | 
						|
import java.lang.reflect.Field;
 | 
						|
import java.lang.reflect.Method;
 | 
						|
import java.util.Collection;
 | 
						|
import java.util.Collections;
 | 
						|
import java.util.HashMap;
 | 
						|
import java.util.Map;
 | 
						|
 | 
						|
import org.alfresco.repo.policy.Policy.Arg;
 | 
						|
import org.alfresco.repo.tenant.TenantService;
 | 
						|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
 | 
						|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
 | 
						|
import org.alfresco.service.cmr.dictionary.DictionaryService;
 | 
						|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
 | 
						|
import org.alfresco.service.namespace.NamespaceService;
 | 
						|
import org.alfresco.service.namespace.QName;
 | 
						|
import org.springframework.extensions.surf.util.ParameterCheck;
 | 
						|
import org.apache.commons.logging.Log;
 | 
						|
import org.apache.commons.logging.LogFactory;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Policy Component Implementation.
 | 
						|
 * 
 | 
						|
 * @author David Caruana
 | 
						|
 *
 | 
						|
 */
 | 
						|
public class PolicyComponentImpl implements PolicyComponent
 | 
						|
{
 | 
						|
    // Logger
 | 
						|
    private static final Log logger = LogFactory.getLog(PolicyComponentImpl.class);
 | 
						|
    
 | 
						|
    // Policy interface annotations
 | 
						|
    private static String ANNOTATION_NAMESPACE = "NAMESPACE";
 | 
						|
    private static String ANNOTATION_ARG ="ARG_";
 | 
						|
 | 
						|
    // Dictionary Service
 | 
						|
    private DictionaryService dictionary;
 | 
						|
    
 | 
						|
    // Behaviour Filter
 | 
						|
    private BehaviourFilter behaviourFilter;
 | 
						|
    
 | 
						|
    // Map of registered Policies
 | 
						|
    private Map<PolicyKey, PolicyDefinition> registeredPolicies;; 
 | 
						|
 | 
						|
    // Map of Class Behaviours (by policy name)
 | 
						|
    private Map<QName, ClassBehaviourIndex<ClassBehaviourBinding>> classBehaviours = new HashMap<QName, ClassBehaviourIndex<ClassBehaviourBinding>>();
 | 
						|
    
 | 
						|
    // Map of Property Behaviours (by policy name)
 | 
						|
    private Map<QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>> propertyBehaviours = new HashMap<QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>>();
 | 
						|
 | 
						|
    // Map of Association Behaviours (by policy name)
 | 
						|
    private Map<QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>> associationBehaviours = new HashMap<QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>>();
 | 
						|
 | 
						|
    // Wild Card Feature
 | 
						|
    private static final QName FEATURE_WILDCARD = QName.createQName(NamespaceService.DEFAULT_URI, "*"); 
 | 
						|
 | 
						|
    // Try lock timeout (MNT-11371)
 | 
						|
    private long tryLockTimeout;
 | 
						|
 | 
						|
 | 
						|
    public void setTryLockTimeout(long tryLockTimeout)
 | 
						|
    {
 | 
						|
        this.tryLockTimeout = tryLockTimeout;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Construct
 | 
						|
     * 
 | 
						|
     * @param dictionary  dictionary service
 | 
						|
     */
 | 
						|
    public PolicyComponentImpl(DictionaryService dictionary)
 | 
						|
    {
 | 
						|
        this.dictionary = dictionary;
 | 
						|
        this.registeredPolicies = new HashMap<PolicyKey, PolicyDefinition>();
 | 
						|
    }
 | 
						|
    
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the behaviour filter
 | 
						|
     * 
 | 
						|
     * @param filter BehaviourFilter
 | 
						|
     */
 | 
						|
    public void setBehaviourFilter(BehaviourFilter filter)
 | 
						|
    {
 | 
						|
        this.behaviourFilter = filter;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Sets the tenant service
 | 
						|
     * 
 | 
						|
     * @param tenantService TenantService
 | 
						|
     */
 | 
						|
    public void setTenantService(TenantService tenantService)
 | 
						|
    {
 | 
						|
        PolicyFactory.setTenantService(tenantService);
 | 
						|
    }
 | 
						|
    
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Sets the transaction-based policy invocation handler
 | 
						|
     * 
 | 
						|
     * @param factory TransactionInvocationHandlerFactory
 | 
						|
     */
 | 
						|
    public void setTransactionInvocationHandlerFactory(TransactionInvocationHandlerFactory factory)
 | 
						|
    {
 | 
						|
        PolicyFactory.setTransactionInvocationHandlerFactory(factory);
 | 
						|
    }
 | 
						|
    
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#registerClassPolicy()
 | 
						|
     */
 | 
						|
    @SuppressWarnings("unchecked")
 | 
						|
    public <P extends ClassPolicy> ClassPolicyDelegate<P> registerClassPolicy(Class<P> policy)
 | 
						|
    {
 | 
						|
        ParameterCheck.mandatory("Policy interface class", policy);
 | 
						|
        PolicyDefinition definition = createPolicyDefinition(policy);
 | 
						|
        registeredPolicies.put(new PolicyKey(definition.getType(), definition.getName()), definition);
 | 
						|
        ClassPolicyDelegate<P> delegate = new ClassPolicyDelegate<P>(dictionary, policy, getClassBehaviourIndex(definition.getName()), tryLockTimeout);
 | 
						|
        
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Registered class policy " + definition.getName() + " (" + definition.getPolicyInterface() + ")");
 | 
						|
        
 | 
						|
        return delegate;
 | 
						|
    }
 | 
						|
 | 
						|
    @Override
 | 
						|
    public void removeClassDefinition(BehaviourDefinition<ClassBehaviourBinding> definition)
 | 
						|
    {
 | 
						|
        getClassBehaviourIndex(definition.getPolicy()).removeClassBehaviour(definition);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#registerPropertyPolicy(java.lang.Class)
 | 
						|
     */
 | 
						|
    @SuppressWarnings("unchecked")
 | 
						|
    public <P extends PropertyPolicy> PropertyPolicyDelegate<P> registerPropertyPolicy(Class<P> policy)
 | 
						|
    {
 | 
						|
        ParameterCheck.mandatory("Policy interface class", policy);
 | 
						|
        PolicyDefinition definition = createPolicyDefinition(policy);
 | 
						|
        registeredPolicies.put(new PolicyKey(definition.getType(), definition.getName()), definition);
 | 
						|
        PropertyPolicyDelegate<P> delegate = new PropertyPolicyDelegate<P>(dictionary, policy, getPropertyBehaviourIndex(definition.getName()), tryLockTimeout);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Registered property policy " + definition.getName() + " (" + definition.getPolicyInterface() + ")");
 | 
						|
        
 | 
						|
        return delegate;
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#registerAssociationPolicy(java.lang.Class)
 | 
						|
     */
 | 
						|
    @SuppressWarnings("unchecked")
 | 
						|
    public <P extends AssociationPolicy> AssociationPolicyDelegate<P> registerAssociationPolicy(Class<P> policy)
 | 
						|
    {
 | 
						|
        ParameterCheck.mandatory("Policy interface class", policy);
 | 
						|
        PolicyDefinition definition = createPolicyDefinition(policy);
 | 
						|
        registeredPolicies.put(new PolicyKey(definition.getType(), definition.getName()), definition);
 | 
						|
        AssociationPolicyDelegate<P> delegate = new AssociationPolicyDelegate<P>(dictionary, policy, getAssociationBehaviourIndex(definition.getName()), tryLockTimeout);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Registered association policy " + definition.getName() + " (" + definition.getPolicyInterface() + ")");
 | 
						|
        
 | 
						|
        return delegate;
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#getRegisteredPolicies()
 | 
						|
     */
 | 
						|
    public Collection<PolicyDefinition> getRegisteredPolicies()
 | 
						|
    {
 | 
						|
        return Collections.unmodifiableCollection(registeredPolicies.values());
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#getRegisteredPolicy(org.alfresco.repo.policy.PolicyType, org.alfresco.repo.ref.QName)
 | 
						|
     */
 | 
						|
    public PolicyDefinition getRegisteredPolicy(PolicyType policyType, QName policy)
 | 
						|
    {
 | 
						|
        return registeredPolicies.get(new PolicyKey(policyType, policy));
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#isRegisteredPolicy(org.alfresco.repo.policy.PolicyType, org.alfresco.repo.ref.QName)
 | 
						|
     */
 | 
						|
    public boolean isRegisteredPolicy(PolicyType policyType, QName policy)
 | 
						|
    {
 | 
						|
        return registeredPolicies.containsKey(new PolicyKey(policyType, policy));
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindClassBehaviour(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ClassBehaviourBinding> bindClassBehaviour(QName policy, QName classRef, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Class Reference", classRef);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
 | 
						|
        // Validate Binding
 | 
						|
        ClassDefinition classDefinition = dictionary.getClass(classRef);
 | 
						|
        if (classDefinition == null)
 | 
						|
        {
 | 
						|
            throw new IllegalArgumentException("Class " + classRef + " has not been defined in the data dictionary");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ClassBehaviourBinding binding = new ClassBehaviourBinding(dictionary, classRef);
 | 
						|
        BehaviourDefinition<ClassBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Class, policy, binding, behaviour);
 | 
						|
        getClassBehaviourIndex(policy).putClassBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to policy " + policy + " for class " + classRef);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
    
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindClassBehaviour(org.alfresco.repo.ref.QName, java.lang.Object, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ServiceBehaviourBinding> bindClassBehaviour(QName policy, Object service, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Service", service);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ServiceBehaviourBinding binding = new ServiceBehaviourBinding(service);
 | 
						|
        BehaviourDefinition<ServiceBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Class, policy, binding, behaviour);
 | 
						|
        getClassBehaviourIndex(policy).putServiceBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to policy " + policy + " for service " + service);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }    
 | 
						|
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindPropertyBehaviour(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ClassFeatureBehaviourBinding> bindPropertyBehaviour(QName policy, QName className, QName propertyName, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Class Reference", className);
 | 
						|
        ParameterCheck.mandatory("Property Reference", propertyName);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
 | 
						|
        // Validate Binding
 | 
						|
        PropertyDefinition propertyDefinition = dictionary.getProperty(className, propertyName);
 | 
						|
        if (propertyDefinition == null)
 | 
						|
        {
 | 
						|
            throw new IllegalArgumentException("Property " + propertyName + " of class " + className + " has not been defined in the data dictionary");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, propertyName);
 | 
						|
        BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Property, policy, binding, behaviour);
 | 
						|
        getPropertyBehaviourIndex(policy).putClassBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to policy " + policy + " for property " + propertyName + " of class " + className);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
    
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindPropertyBehaviour(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ClassFeatureBehaviourBinding> bindPropertyBehaviour(QName policy, QName className, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Class Reference", className);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
 | 
						|
        // Validate Binding
 | 
						|
        ClassDefinition classDefinition = dictionary.getClass(className);
 | 
						|
        if (classDefinition == null)
 | 
						|
        {
 | 
						|
            throw new IllegalArgumentException("Class " + className + " has not been defined in the data dictionary");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, FEATURE_WILDCARD);
 | 
						|
        BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Property, policy, binding, behaviour);
 | 
						|
        getPropertyBehaviourIndex(policy).putClassBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to policy " + policy + " for property " + FEATURE_WILDCARD + " of class " + className);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindPropertyBehaviour(org.alfresco.repo.ref.QName, java.lang.Object, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ServiceBehaviourBinding> bindPropertyBehaviour(QName policy, Object service, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Service", service);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ServiceBehaviourBinding binding = new ServiceBehaviourBinding(service);
 | 
						|
        BehaviourDefinition<ServiceBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Property, policy, binding, behaviour);
 | 
						|
        getPropertyBehaviourIndex(policy).putServiceBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to property policy " + policy + " for service " + service);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindAssociationBehaviour(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ClassFeatureBehaviourBinding> bindAssociationBehaviour(QName policy, QName className, QName assocName, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Class Reference", className);
 | 
						|
        ParameterCheck.mandatory("Association Reference", assocName);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
 | 
						|
        // Validate Binding
 | 
						|
        AssociationDefinition assocDefinition = dictionary.getAssociation(assocName);
 | 
						|
        if (assocDefinition == null)
 | 
						|
        {
 | 
						|
            throw new IllegalArgumentException("Association " + assocName + " of class " + className + " has not been defined in the data dictionary");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, assocName);
 | 
						|
        BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour);
 | 
						|
        getAssociationBehaviourIndex(policy).putClassBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to policy " + policy + " for association " + assocName + " of class " + className);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindAssociationBehaviour(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ClassFeatureBehaviourBinding> bindAssociationBehaviour(QName policy, QName className, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Class Reference", className);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
 | 
						|
        // Validate Binding
 | 
						|
        ClassDefinition classDefinition = dictionary.getClass(className);
 | 
						|
        if (classDefinition == null)
 | 
						|
        {
 | 
						|
            throw new IllegalArgumentException("Class " + className + " has not been defined in the data dictionary");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, FEATURE_WILDCARD);
 | 
						|
        BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour);
 | 
						|
        getAssociationBehaviourIndex(policy).putClassBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to policy " + policy + " for association " + FEATURE_WILDCARD + " of class " + className);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.repo.policy.PolicyComponent#bindAssociationBehaviour(org.alfresco.repo.ref.QName, java.lang.Object, org.alfresco.repo.policy.Behaviour)
 | 
						|
     */
 | 
						|
    public BehaviourDefinition<ServiceBehaviourBinding> bindAssociationBehaviour(QName policy, Object service, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Validate arguments
 | 
						|
        ParameterCheck.mandatory("Policy", policy);
 | 
						|
        ParameterCheck.mandatory("Service", service);
 | 
						|
        ParameterCheck.mandatory("Behaviour", behaviour);
 | 
						|
        
 | 
						|
        // Create behaviour definition and bind to policy
 | 
						|
        ServiceBehaviourBinding binding = new ServiceBehaviourBinding(service);
 | 
						|
        BehaviourDefinition<ServiceBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour);
 | 
						|
        getAssociationBehaviourIndex(policy).putServiceBehaviour(definition);
 | 
						|
        
 | 
						|
        if (logger.isInfoEnabled())
 | 
						|
            logger.info("Bound " + behaviour + " to association policy " + policy + " for service " + service);
 | 
						|
 | 
						|
        return definition;
 | 
						|
    }
 | 
						|
    
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Gets the Class behaviour index for the specified Policy
 | 
						|
     * 
 | 
						|
     * @param policy  the policy
 | 
						|
     * @return  the class behaviour index
 | 
						|
     */
 | 
						|
    private synchronized ClassBehaviourIndex<ClassBehaviourBinding> getClassBehaviourIndex(QName policy)
 | 
						|
    {
 | 
						|
        ClassBehaviourIndex<ClassBehaviourBinding> index = classBehaviours.get(policy);
 | 
						|
        if (index == null)
 | 
						|
        {
 | 
						|
            index = new ClassBehaviourIndex<ClassBehaviourBinding>(behaviourFilter);
 | 
						|
            index.setTryLockTimeout(tryLockTimeout);
 | 
						|
            classBehaviours.put(policy, index);
 | 
						|
        }
 | 
						|
        return index;
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Gets the Property behaviour index for the specified Policy
 | 
						|
     * 
 | 
						|
     * @param policy  the policy
 | 
						|
     * @return  the property behaviour index
 | 
						|
     */
 | 
						|
    private synchronized ClassBehaviourIndex<ClassFeatureBehaviourBinding> getPropertyBehaviourIndex(QName policy)
 | 
						|
    {
 | 
						|
        ClassBehaviourIndex<ClassFeatureBehaviourBinding> index = propertyBehaviours.get(policy);
 | 
						|
        if (index == null)
 | 
						|
        {
 | 
						|
            index = new ClassBehaviourIndex<ClassFeatureBehaviourBinding>(behaviourFilter);
 | 
						|
            index.setTryLockTimeout(tryLockTimeout);
 | 
						|
            propertyBehaviours.put(policy, index);
 | 
						|
        }
 | 
						|
        return index;
 | 
						|
    }
 | 
						|
    
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets the Association behaviour index for the specified Policy
 | 
						|
     * 
 | 
						|
     * @param policy  the policy
 | 
						|
     * @return  the association behaviour index
 | 
						|
     */
 | 
						|
    private synchronized ClassBehaviourIndex<ClassFeatureBehaviourBinding> getAssociationBehaviourIndex(QName policy)
 | 
						|
    {
 | 
						|
        ClassBehaviourIndex<ClassFeatureBehaviourBinding> index = associationBehaviours.get(policy);
 | 
						|
        if (index == null)
 | 
						|
        {
 | 
						|
            index = new ClassBehaviourIndex<ClassFeatureBehaviourBinding>(behaviourFilter);
 | 
						|
            index.setTryLockTimeout(tryLockTimeout);
 | 
						|
            associationBehaviours.put(policy, index);
 | 
						|
        }
 | 
						|
        return index;
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Create a Behaviour Definition
 | 
						|
     * 
 | 
						|
     * @param <B>  the type of binding
 | 
						|
     * @param type  policy type
 | 
						|
     * @param policy  policy name
 | 
						|
     * @param binding  the binding
 | 
						|
     * @param behaviour  the behaviour
 | 
						|
     * @return  the behaviour definition
 | 
						|
     */
 | 
						|
    @SuppressWarnings("unchecked")
 | 
						|
    private <B extends BehaviourBinding> BehaviourDefinition<B> createBehaviourDefinition(PolicyType type, QName policy, B binding, Behaviour behaviour)
 | 
						|
    {
 | 
						|
        // Determine if policy has already been registered
 | 
						|
        PolicyDefinition policyDefinition = getRegisteredPolicy(type, policy);
 | 
						|
        if (policyDefinition != null)
 | 
						|
        {
 | 
						|
            // Policy has already been registered, force validation of behaviour now
 | 
						|
            behaviour.getInterface(policyDefinition.getPolicyInterface());
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            if (logger.isInfoEnabled())
 | 
						|
                logger.info("Behaviour " + behaviour + " is binding (" + binding + ") to policy " + policy + " before the policy is registered");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Construct the definition
 | 
						|
        return new BehaviourDefinitionImpl<B>(type, policy, binding, behaviour);
 | 
						|
    }
 | 
						|
    
 | 
						|
 | 
						|
    /**
 | 
						|
     * Create a Policy Definition
 | 
						|
     * 
 | 
						|
     * @param policyIF  the policy interface
 | 
						|
     * @return  the policy definition
 | 
						|
     */
 | 
						|
    private PolicyDefinition createPolicyDefinition(Class policyIF)
 | 
						|
    {
 | 
						|
        // Extract Policy Namespace
 | 
						|
        String namespaceURI = NamespaceService.DEFAULT_URI;
 | 
						|
        try
 | 
						|
        {
 | 
						|
            Field metadata = policyIF.getField(ANNOTATION_NAMESPACE);
 | 
						|
            if (!String.class.isAssignableFrom(metadata.getType()))
 | 
						|
            {
 | 
						|
                throw new PolicyException("NAMESPACE metadata incorrectly specified in policy " + policyIF.getCanonicalName());
 | 
						|
            }
 | 
						|
            namespaceURI = (String)metadata.get(null);
 | 
						|
        }
 | 
						|
        catch(NoSuchFieldException e)
 | 
						|
        {
 | 
						|
            // Assume default namespace
 | 
						|
        }
 | 
						|
        catch(IllegalAccessException e)
 | 
						|
        {
 | 
						|
            // Shouldn't get here (interface definitions must be accessible)
 | 
						|
        }
 | 
						|
 | 
						|
        // Extract Policy Name
 | 
						|
        Method[] methods = policyIF.getMethods();
 | 
						|
        if (methods.length != 1)
 | 
						|
        {
 | 
						|
            throw new PolicyException("Policy " + policyIF.getCanonicalName() + " must declare only one method");
 | 
						|
        }
 | 
						|
        String name = methods[0].getName();
 | 
						|
 | 
						|
        // Extract Policy Arguments
 | 
						|
        Class[] paramTypes = methods[0].getParameterTypes();
 | 
						|
        Arg[] args = new Arg[paramTypes.length];
 | 
						|
        for (int i = 0; i < paramTypes.length; i++)
 | 
						|
        {
 | 
						|
            // Extract Policy Arg
 | 
						|
            args[i] = (i == 0) ? Arg.KEY : Arg.START_VALUE; 
 | 
						|
            try
 | 
						|
            {
 | 
						|
                Field argMetadata = policyIF.getField(ANNOTATION_ARG + i);
 | 
						|
                if (!Arg.class.isAssignableFrom(argMetadata.getType()))
 | 
						|
                {
 | 
						|
                    throw new PolicyException("ARG_" + i + " metadata incorrectly specified in policy " + policyIF.getCanonicalName());
 | 
						|
                }
 | 
						|
                args[i] = (Arg)argMetadata.get(null);
 | 
						|
                if (i == 0 && (!args[i].equals(Arg.KEY)))
 | 
						|
                {
 | 
						|
                    throw new PolicyException("ARG_" + i + " specified in policy " + policyIF.getCanonicalName() + " must be a key");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            catch(NoSuchFieldException e)
 | 
						|
            {
 | 
						|
                // Assume default ARG configuration
 | 
						|
            }
 | 
						|
            catch(IllegalAccessException e)
 | 
						|
            {
 | 
						|
                // Shouldn't get here (interface definitions must be accessible)
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Create Policy Definition
 | 
						|
        return new PolicyDefinitionImpl(QName.createQName(namespaceURI, name), policyIF, args);
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Policy Key (composite of policy type and name)
 | 
						|
     * 
 | 
						|
     * @author David Caruana
 | 
						|
     *
 | 
						|
     */
 | 
						|
    private static class PolicyKey
 | 
						|
    {
 | 
						|
        private PolicyType type;
 | 
						|
        private QName policy;
 | 
						|
        
 | 
						|
        private PolicyKey(PolicyType type, QName policy)
 | 
						|
        {
 | 
						|
            this.type = type;
 | 
						|
            this.policy = policy;
 | 
						|
        }
 | 
						|
 | 
						|
        @Override
 | 
						|
        public boolean equals(Object obj)
 | 
						|
        {
 | 
						|
            if (obj == this)
 | 
						|
            {
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
            else if (obj == null || !(obj instanceof PolicyKey))
 | 
						|
            {
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
            PolicyKey other = (PolicyKey)obj;
 | 
						|
            return type.equals(other.type) && policy.equals(other.policy);
 | 
						|
        }
 | 
						|
 | 
						|
        @Override
 | 
						|
        public int hashCode()
 | 
						|
        {
 | 
						|
            return 37 * type.hashCode() + policy.hashCode();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Policy Definition implementation.
 | 
						|
     * 
 | 
						|
     * @author David Caruana
 | 
						|
     *
 | 
						|
     */
 | 
						|
    /*package*/ class PolicyDefinitionImpl implements PolicyDefinition
 | 
						|
    {
 | 
						|
        private QName policy;
 | 
						|
        private Class policyIF;
 | 
						|
        private Arg[] args;
 | 
						|
 | 
						|
        /*package*/ PolicyDefinitionImpl(QName policy, Class policyIF, Arg[] args)
 | 
						|
        {
 | 
						|
            this.policy = policy;
 | 
						|
            this.policyIF = policyIF;
 | 
						|
            this.args = args;
 | 
						|
        }
 | 
						|
        
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.PolicyDefinition#getName()
 | 
						|
         */
 | 
						|
        public QName getName()
 | 
						|
        {
 | 
						|
            return policy;
 | 
						|
        }
 | 
						|
        
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.PolicyDefinition#getPolicyInterface()
 | 
						|
         */
 | 
						|
        public Class getPolicyInterface()
 | 
						|
        {
 | 
						|
            return policyIF;
 | 
						|
        }
 | 
						|
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.PolicyDefinition#getType()
 | 
						|
         */
 | 
						|
        public PolicyType getType()
 | 
						|
        {
 | 
						|
            if (ClassPolicy.class.isAssignableFrom(policyIF))
 | 
						|
            {
 | 
						|
                return PolicyType.Class;
 | 
						|
            }
 | 
						|
            else if (PropertyPolicy.class.isAssignableFrom(policyIF))
 | 
						|
            {
 | 
						|
                return PolicyType.Property;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                return PolicyType.Association; 
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.PolicyDefinition#getArgument(int)
 | 
						|
         */
 | 
						|
        public Arg getArgument(int index)
 | 
						|
        {
 | 
						|
            if (index < 0 || index > args.length -1)
 | 
						|
            {
 | 
						|
                throw new IllegalArgumentException("Argument index " + index + " is invalid");
 | 
						|
            }
 | 
						|
            return args[index];
 | 
						|
        }
 | 
						|
        
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.PolicyDefinition#getArguments()
 | 
						|
         */
 | 
						|
        public Arg[] getArguments()
 | 
						|
        {
 | 
						|
            return args;
 | 
						|
        }
 | 
						|
        
 | 
						|
    }
 | 
						|
    
 | 
						|
 | 
						|
    /**
 | 
						|
     * Behaviour Definition implementation.
 | 
						|
     * 
 | 
						|
     * @author David Caruana
 | 
						|
     *
 | 
						|
     * @param <B>  the type of binding
 | 
						|
     */
 | 
						|
    /*package*/ class BehaviourDefinitionImpl<B extends BehaviourBinding> implements BehaviourDefinition<B>
 | 
						|
    {
 | 
						|
        private PolicyType type;
 | 
						|
        private QName policy;
 | 
						|
        private B binding;
 | 
						|
        private Behaviour behaviour;
 | 
						|
        
 | 
						|
        /*package*/ BehaviourDefinitionImpl(PolicyType type, QName policy, B binding, Behaviour behaviour)
 | 
						|
        {
 | 
						|
            this.type = type;
 | 
						|
            this.policy = policy;
 | 
						|
            this.binding = binding;
 | 
						|
            this.behaviour = behaviour;
 | 
						|
        }
 | 
						|
        
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.BehaviourDefinition#getPolicy()
 | 
						|
         */
 | 
						|
        public QName getPolicy()
 | 
						|
        {
 | 
						|
            return policy;
 | 
						|
        }
 | 
						|
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.BehaviourDefinition#getPolicyDefinition()
 | 
						|
         */
 | 
						|
        public PolicyDefinition getPolicyDefinition()
 | 
						|
        {
 | 
						|
            return getRegisteredPolicy(type, policy);
 | 
						|
        }
 | 
						|
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.BehaviourDefinition#getBinding()
 | 
						|
         */
 | 
						|
        public B getBinding()
 | 
						|
        {
 | 
						|
            return binding;
 | 
						|
        }
 | 
						|
        
 | 
						|
        /* (non-Javadoc)
 | 
						|
         * @see org.alfresco.repo.policy.BehaviourDefinition#getBehaviour()
 | 
						|
         */
 | 
						|
        public Behaviour getBehaviour()
 | 
						|
        {
 | 
						|
            return behaviour;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
}
 |