1 17 package org.alfresco.repo.policy; 18 19 import java.lang.reflect.Field ; 20 import java.lang.reflect.Method ; 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.Map ; 25 26 import org.alfresco.service.cmr.dictionary.AssociationDefinition; 27 import org.alfresco.service.cmr.dictionary.ClassDefinition; 28 import org.alfresco.service.cmr.dictionary.DictionaryService; 29 import org.alfresco.service.cmr.dictionary.PropertyDefinition; 30 import org.alfresco.service.namespace.NamespaceService; 31 import org.alfresco.service.namespace.QName; 32 import org.alfresco.util.ParameterCheck; 33 import org.apache.commons.logging.Log; 34 import org.apache.commons.logging.LogFactory; 35 36 37 43 public class PolicyComponentImpl implements PolicyComponent 44 { 45 private static final Log logger = LogFactory.getLog(PolicyComponentImpl.class); 47 48 private static String ANNOTATION_NAMESPACE = "NAMESPACE"; 50 51 private DictionaryService dictionary; 53 54 private BehaviourFilter behaviourFilter; 56 57 private Map <PolicyKey, PolicyDefinition> registeredPolicies;; 59 60 private Map <QName, ClassBehaviourIndex<ClassBehaviourBinding>> classBehaviours = new HashMap <QName, ClassBehaviourIndex<ClassBehaviourBinding>>(); 62 63 private Map <QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>> propertyBehaviours = new HashMap <QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>>(); 65 66 private Map <QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>> associationBehaviours = new HashMap <QName, ClassBehaviourIndex<ClassFeatureBehaviourBinding>>(); 68 69 private static final QName FEATURE_WILDCARD = QName.createQName(NamespaceService.DEFAULT_URI, "*"); 71 72 73 79 public PolicyComponentImpl(DictionaryService dictionary) 80 { 81 this.dictionary = dictionary; 82 this.registeredPolicies = new HashMap <PolicyKey, PolicyDefinition>(); 83 } 84 85 86 91 public void setBehaviourFilter(BehaviourFilter filter) 92 { 93 this.behaviourFilter = filter; 94 } 95 96 97 100 @SuppressWarnings ("unchecked") 101 public <P extends ClassPolicy> ClassPolicyDelegate<P> registerClassPolicy(Class <P> policy) 102 { 103 ParameterCheck.mandatory("Policy interface class", policy); 104 PolicyDefinition definition = createPolicyDefinition(policy); 105 registeredPolicies.put(new PolicyKey(definition.getType(), definition.getName()), definition); 106 ClassPolicyDelegate<P> delegate = new ClassPolicyDelegate<P>(dictionary, policy, getClassBehaviourIndex(definition.getName())); 107 108 if (logger.isInfoEnabled()) 109 logger.info("Registered class policy " + definition.getName() + " (" + definition.getPolicyInterface() + ")"); 110 111 return delegate; 112 } 113 114 115 118 @SuppressWarnings ("unchecked") 119 public <P extends PropertyPolicy> PropertyPolicyDelegate<P> registerPropertyPolicy(Class <P> policy) 120 { 121 ParameterCheck.mandatory("Policy interface class", policy); 122 PolicyDefinition definition = createPolicyDefinition(policy); 123 registeredPolicies.put(new PolicyKey(definition.getType(), definition.getName()), definition); 124 PropertyPolicyDelegate<P> delegate = new PropertyPolicyDelegate<P>(dictionary, policy, getPropertyBehaviourIndex(definition.getName())); 125 126 if (logger.isInfoEnabled()) 127 logger.info("Registered property policy " + definition.getName() + " (" + definition.getPolicyInterface() + ")"); 128 129 return delegate; 130 } 131 132 133 136 @SuppressWarnings ("unchecked") 137 public <P extends AssociationPolicy> AssociationPolicyDelegate<P> registerAssociationPolicy(Class <P> policy) 138 { 139 ParameterCheck.mandatory("Policy interface class", policy); 140 PolicyDefinition definition = createPolicyDefinition(policy); 141 registeredPolicies.put(new PolicyKey(definition.getType(), definition.getName()), definition); 142 AssociationPolicyDelegate<P> delegate = new AssociationPolicyDelegate<P>(dictionary, policy, getAssociationBehaviourIndex(definition.getName())); 143 144 if (logger.isInfoEnabled()) 145 logger.info("Registered association policy " + definition.getName() + " (" + definition.getPolicyInterface() + ")"); 146 147 return delegate; 148 } 149 150 151 154 public Collection <PolicyDefinition> getRegisteredPolicies() 155 { 156 return Collections.unmodifiableCollection(registeredPolicies.values()); 157 } 158 159 160 163 public PolicyDefinition getRegisteredPolicy(PolicyType policyType, QName policy) 164 { 165 return registeredPolicies.get(new PolicyKey(policyType, policy)); 166 } 167 168 169 172 public boolean isRegisteredPolicy(PolicyType policyType, QName policy) 173 { 174 return registeredPolicies.containsKey(new PolicyKey(policyType, policy)); 175 } 176 177 178 181 public BehaviourDefinition<ClassBehaviourBinding> bindClassBehaviour(QName policy, QName classRef, Behaviour behaviour) 182 { 183 ParameterCheck.mandatory("Policy", policy); 185 ParameterCheck.mandatory("Class Reference", classRef); 186 ParameterCheck.mandatory("Behaviour", behaviour); 187 188 ClassDefinition classDefinition = dictionary.getClass(classRef); 190 if (classDefinition == null) 191 { 192 throw new IllegalArgumentException ("Class " + classRef + " has not been defined in the data dictionary"); 193 } 194 195 ClassBehaviourBinding binding = new ClassBehaviourBinding(dictionary, classRef); 197 BehaviourDefinition<ClassBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Class, policy, binding, behaviour); 198 getClassBehaviourIndex(policy).putClassBehaviour(definition); 199 200 if (logger.isInfoEnabled()) 201 logger.info("Bound " + behaviour + " to policy " + policy + " for class " + classRef); 202 203 return definition; 204 } 205 206 207 210 public BehaviourDefinition<ServiceBehaviourBinding> bindClassBehaviour(QName policy, Object service, Behaviour behaviour) 211 { 212 ParameterCheck.mandatory("Policy", policy); 214 ParameterCheck.mandatory("Service", service); 215 ParameterCheck.mandatory("Behaviour", behaviour); 216 217 ServiceBehaviourBinding binding = new ServiceBehaviourBinding(service); 219 BehaviourDefinition<ServiceBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Class, policy, binding, behaviour); 220 getClassBehaviourIndex(policy).putServiceBehaviour(definition); 221 222 if (logger.isInfoEnabled()) 223 logger.info("Bound " + behaviour + " to policy " + policy + " for service " + service); 224 225 return definition; 226 } 227 228 229 232 public BehaviourDefinition<ClassFeatureBehaviourBinding> bindPropertyBehaviour(QName policy, QName className, QName propertyName, Behaviour behaviour) 233 { 234 ParameterCheck.mandatory("Policy", policy); 236 ParameterCheck.mandatory("Class Reference", className); 237 ParameterCheck.mandatory("Property Reference", propertyName); 238 ParameterCheck.mandatory("Behaviour", behaviour); 239 240 PropertyDefinition propertyDefinition = dictionary.getProperty(className, propertyName); 242 if (propertyDefinition == null) 243 { 244 throw new IllegalArgumentException ("Property " + propertyName + " of class " + className + " has not been defined in the data dictionary"); 245 } 246 247 ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, propertyName); 249 BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Property, policy, binding, behaviour); 250 getPropertyBehaviourIndex(policy).putClassBehaviour(definition); 251 252 if (logger.isInfoEnabled()) 253 logger.info("Bound " + behaviour + " to policy " + policy + " for property " + propertyName + " of class " + className); 254 255 return definition; 256 } 257 258 259 262 public BehaviourDefinition<ClassFeatureBehaviourBinding> bindPropertyBehaviour(QName policy, QName className, Behaviour behaviour) 263 { 264 ParameterCheck.mandatory("Policy", policy); 266 ParameterCheck.mandatory("Class Reference", className); 267 ParameterCheck.mandatory("Behaviour", behaviour); 268 269 ClassDefinition classDefinition = dictionary.getClass(className); 271 if (classDefinition == null) 272 { 273 throw new IllegalArgumentException ("Class " + className + " has not been defined in the data dictionary"); 274 } 275 276 ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, FEATURE_WILDCARD); 278 BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Property, policy, binding, behaviour); 279 getPropertyBehaviourIndex(policy).putClassBehaviour(definition); 280 281 if (logger.isInfoEnabled()) 282 logger.info("Bound " + behaviour + " to policy " + policy + " for property " + FEATURE_WILDCARD + " of class " + className); 283 284 return definition; 285 } 286 287 288 291 public BehaviourDefinition<ServiceBehaviourBinding> bindPropertyBehaviour(QName policy, Object service, Behaviour behaviour) 292 { 293 ParameterCheck.mandatory("Policy", policy); 295 ParameterCheck.mandatory("Service", service); 296 ParameterCheck.mandatory("Behaviour", behaviour); 297 298 ServiceBehaviourBinding binding = new ServiceBehaviourBinding(service); 300 BehaviourDefinition<ServiceBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Property, policy, binding, behaviour); 301 getPropertyBehaviourIndex(policy).putServiceBehaviour(definition); 302 303 if (logger.isInfoEnabled()) 304 logger.info("Bound " + behaviour + " to property policy " + policy + " for service " + service); 305 306 return definition; 307 } 308 309 310 313 public BehaviourDefinition<ClassFeatureBehaviourBinding> bindAssociationBehaviour(QName policy, QName className, QName assocName, Behaviour behaviour) 314 { 315 ParameterCheck.mandatory("Policy", policy); 317 ParameterCheck.mandatory("Class Reference", className); 318 ParameterCheck.mandatory("Association Reference", assocName); 319 ParameterCheck.mandatory("Behaviour", behaviour); 320 321 AssociationDefinition assocDefinition = dictionary.getAssociation(assocName); 323 if (assocDefinition == null) 324 { 325 throw new IllegalArgumentException ("Association " + assocName + " of class " + className + " has not been defined in the data dictionary"); 326 } 327 328 ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, assocName); 330 BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour); 331 getAssociationBehaviourIndex(policy).putClassBehaviour(definition); 332 333 if (logger.isInfoEnabled()) 334 logger.info("Bound " + behaviour + " to policy " + policy + " for association " + assocName + " of class " + className); 335 336 return definition; 337 } 338 339 340 343 public BehaviourDefinition<ClassFeatureBehaviourBinding> bindAssociationBehaviour(QName policy, QName className, Behaviour behaviour) 344 { 345 ParameterCheck.mandatory("Policy", policy); 347 ParameterCheck.mandatory("Class Reference", className); 348 ParameterCheck.mandatory("Behaviour", behaviour); 349 350 ClassDefinition classDefinition = dictionary.getClass(className); 352 if (classDefinition == null) 353 { 354 throw new IllegalArgumentException ("Class " + className + " has not been defined in the data dictionary"); 355 } 356 357 ClassFeatureBehaviourBinding binding = new ClassFeatureBehaviourBinding(dictionary, className, FEATURE_WILDCARD); 359 BehaviourDefinition<ClassFeatureBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour); 360 getAssociationBehaviourIndex(policy).putClassBehaviour(definition); 361 362 if (logger.isInfoEnabled()) 363 logger.info("Bound " + behaviour + " to policy " + policy + " for association " + FEATURE_WILDCARD + " of class " + className); 364 365 return definition; 366 } 367 368 369 372 public BehaviourDefinition<ServiceBehaviourBinding> bindAssociationBehaviour(QName policy, Object service, Behaviour behaviour) 373 { 374 ParameterCheck.mandatory("Policy", policy); 376 ParameterCheck.mandatory("Service", service); 377 ParameterCheck.mandatory("Behaviour", behaviour); 378 379 ServiceBehaviourBinding binding = new ServiceBehaviourBinding(service); 381 BehaviourDefinition<ServiceBehaviourBinding> definition = createBehaviourDefinition(PolicyType.Association, policy, binding, behaviour); 382 getAssociationBehaviourIndex(policy).putServiceBehaviour(definition); 383 384 if (logger.isInfoEnabled()) 385 logger.info("Bound " + behaviour + " to association policy " + policy + " for service " + service); 386 387 return definition; 388 } 389 390 391 397 private synchronized ClassBehaviourIndex<ClassBehaviourBinding> getClassBehaviourIndex(QName policy) 398 { 399 ClassBehaviourIndex<ClassBehaviourBinding> index = classBehaviours.get(policy); 400 if (index == null) 401 { 402 index = new ClassBehaviourIndex<ClassBehaviourBinding>(behaviourFilter); 403 classBehaviours.put(policy, index); 404 } 405 return index; 406 } 407 408 409 415 private synchronized ClassBehaviourIndex<ClassFeatureBehaviourBinding> getPropertyBehaviourIndex(QName policy) 416 { 417 ClassBehaviourIndex<ClassFeatureBehaviourBinding> index = propertyBehaviours.get(policy); 418 if (index == null) 419 { 420 index = new ClassBehaviourIndex<ClassFeatureBehaviourBinding>(behaviourFilter); 421 propertyBehaviours.put(policy, index); 422 } 423 return index; 424 } 425 426 427 433 private synchronized ClassBehaviourIndex<ClassFeatureBehaviourBinding> getAssociationBehaviourIndex(QName policy) 434 { 435 ClassBehaviourIndex<ClassFeatureBehaviourBinding> index = associationBehaviours.get(policy); 436 if (index == null) 437 { 438 index = new ClassBehaviourIndex<ClassFeatureBehaviourBinding>(behaviourFilter); 439 associationBehaviours.put(policy, index); 440 } 441 return index; 442 } 443 444 445 455 @SuppressWarnings ("unchecked") 456 private <B extends BehaviourBinding> BehaviourDefinition<B> createBehaviourDefinition(PolicyType type, QName policy, B binding, Behaviour behaviour) 457 { 458 PolicyDefinition policyDefinition = getRegisteredPolicy(type, policy); 460 if (policyDefinition != null) 461 { 462 behaviour.getInterface(policyDefinition.getPolicyInterface()); 464 } 465 else 466 { 467 if (logger.isInfoEnabled()) 468 logger.info("Behaviour " + behaviour + " is binding (" + binding + ") to policy " + policy + " before the policy is registered"); 469 } 470 471 return new BehaviourDefinitionImpl<B>(type, policy, binding, behaviour); 473 } 474 475 476 482 private PolicyDefinition createPolicyDefinition(Class policyIF) 483 { 484 String namespaceURI = NamespaceService.DEFAULT_URI; 486 try 487 { 488 Field metadata = policyIF.getField(ANNOTATION_NAMESPACE); 489 if (!String .class.isAssignableFrom(metadata.getType())) 490 { 491 throw new PolicyException("NAMESPACE metadata incorrectly specified in policy " + policyIF.getCanonicalName()); 492 } 493 namespaceURI = (String )metadata.get(null); 494 } 495 catch(NoSuchFieldException e) 496 { 497 } 499 catch(IllegalAccessException e) 500 { 501 } 503 504 Method [] methods = policyIF.getMethods(); 506 if (methods.length != 1) 507 { 508 throw new PolicyException("Policy " + policyIF.getCanonicalName() + " must declare only one method"); 509 } 510 String name = methods[0].getName(); 511 512 return new PolicyDefinitionImpl(QName.createQName(namespaceURI, name), policyIF); 514 } 515 516 517 523 private static class PolicyKey 524 { 525 private PolicyType type; 526 private QName policy; 527 528 private PolicyKey(PolicyType type, QName policy) 529 { 530 this.type = type; 531 this.policy = policy; 532 } 533 534 @Override 535 public boolean equals(Object obj) 536 { 537 if (obj == this) 538 { 539 return true; 540 } 541 else if (obj == null || !(obj instanceof PolicyKey)) 542 { 543 return false; 544 } 545 PolicyKey other = (PolicyKey)obj; 546 return type.equals(other.type) && policy.equals(other.policy); 547 } 548 549 @Override 550 public int hashCode() 551 { 552 return 37 * type.hashCode() + policy.hashCode(); 553 } 554 } 555 556 557 563 class PolicyDefinitionImpl implements PolicyDefinition 564 { 565 private QName policy; 566 private Class policyIF; 567 568 PolicyDefinitionImpl(QName policy, Class policyIF) 569 { 570 this.policy = policy; 571 this.policyIF = policyIF; 572 } 573 574 577 public QName getName() 578 { 579 return policy; 580 } 581 582 585 public Class getPolicyInterface() 586 { 587 return policyIF; 588 } 589 590 593 public PolicyType getType() 594 { 595 if (ClassPolicy.class.isAssignableFrom(policyIF)) 596 { 597 return PolicyType.Class; 598 } 599 else if (PropertyPolicy.class.isAssignableFrom(policyIF)) 600 { 601 return PolicyType.Property; 602 } 603 else 604 { 605 return PolicyType.Association; 606 } 607 } 608 } 609 610 611 618 class BehaviourDefinitionImpl<B extends BehaviourBinding> implements BehaviourDefinition<B> 619 { 620 private PolicyType type; 621 private QName policy; 622 private B binding; 623 private Behaviour behaviour; 624 625 BehaviourDefinitionImpl(PolicyType type, QName policy, B binding, Behaviour behaviour) 626 { 627 this.type = type; 628 this.policy = policy; 629 this.binding = binding; 630 this.behaviour = behaviour; 631 } 632 633 636 public QName getPolicy() 637 { 638 return policy; 639 } 640 641 644 public PolicyDefinition getPolicyDefinition() 645 { 646 return getRegisteredPolicy(type, policy); 647 } 648 649 652 public B getBinding() 653 { 654 return binding; 655 } 656 657 660 public Behaviour getBehaviour() 661 { 662 return behaviour; 663 } 664 } 665 666 } 667 | Popular Tags |