// Find the set of policy sets from this reference. This includes
// the policy sets that are specific to the service binding and
// any policy sets that are not binding specific
for (PolicySet policySet : endpointReference.getPolicySets()){
PolicyBuilder policyBuilder = null;
if (policySet.getPolicies().size() > 0){
QName policyType = policySet.getPolicies().get(0).getName();
policyBuilder = builders.getPolicyBuilder(policyType);
}
if ((policyBuilder == null) ||
(policyBuilder != null && policyBuilder.getSupportedBindings() == null) ||
(policyBuilder != null && policyBuilder.getSupportedBindings().contains(binding.getType()))){
referencePolicySets.add(policySet);
}
}
// if there are no policy sets on the reference take the policy sets from the
// service binding we are matching against
if (referencePolicySets.isEmpty()) {
for (PolicySet policySet : endpoint.getPolicySets()){
PolicyBuilder policyBuilder = null;
if (policySet.getPolicies().size() > 0){
QName policyType = policySet.getPolicies().get(0).getName();
policyBuilder = builders.getPolicyBuilder(policyType);
}
if ((policyBuilder == null) ||
(policyBuilder != null && policyBuilder.getSupportedBindings() == null) ||
(policyBuilder != null && policyBuilder.getSupportedBindings().contains(binding.getType()))){
referencePolicySets.add(policySet);
}
}
}
// the "appliesTo" algorithm to remove any policy sets that
// don't apply to the service binding will already have been
// run during the build phase
// Determine if there are any reference policies
boolean noEndpointReferencePolicies = true;
for (PolicySet policySet : referencePolicySets){
if (policySet.getPolicies().size() > 0){
noEndpointReferencePolicies = false;
break;
}
}
// Determine of there are any service policies
boolean noEndpointPolicies = true;
for (PolicySet policySet : endpoint.getPolicySets()){
if (policySet.getPolicies().size() > 0){
noEndpointPolicies = false;
break;
}
}
// if no policy sets or intents are present then they match
if ((endpointReference.getRequiredIntents().size() == 0) &&
(endpoint.getRequiredIntents().size() == 0) &&
(noEndpointReferencePolicies) &&
(noEndpointPolicies)) {
matchAudit.append("Match because there are no intents or policies ");
matchAudit.appendSeperator();
return true;
}
// check that the intents on the reference side are resolved
// can't do this until this point as the service binding
// may come into play. Intents may be satisfied by the default
// or optional intents that the binding type provides. Failing
// this they must be satisfied by reference policy sets
// Failing this the intent is unresolved and the reference and
// service don't match
// TODO - seems that we should do this loop on a binding by binding basis
// rather than each time we do matching
BindingType bindingType = null;
Definitions systemDefinitions = null;
if (builderContext != null){
systemDefinitions = builderContext.getDefinitions();
} else {
systemDefinitions = ((RuntimeEndpoint)endpoint).getCompositeContext().getSystemDefinitions();
}
bindingType = systemDefinitions.getBindingType(binding.getType());
// Before we start examining intents, remove any whose constrained
// types don't include the binding type
removeConstrainedIntents(endpointReference, bindingType);
List<Intent> eprIntents = new ArrayList<Intent>();
List<Intent> eprMayProvideInterationIntents = new ArrayList<Intent>();
eprIntents.addAll(endpointReference.getRequiredIntents());
// first check the binding type
for (Intent intent : endpointReference.getRequiredIntents()){
if (bindingType != null &&
bindingType.getAlwaysProvidedIntents().contains(intent)){
eprIntents.remove(intent);
} else if (bindingType != null &&
bindingType.getMayProvidedIntents().contains(intent)){
eprIntents.remove(intent);
if (intent.getType().equals(Intent.Type.interaction)){
eprMayProvideInterationIntents.add(intent);
}
} else {
// TODO - this code also appears in the ComponentPolicyBuilder
// so should rationalize
loop: for (PolicySet policySet : referencePolicySets){
if (policySet.getProvidedIntents().contains(intent)){
eprIntents.remove(intent);
break;
}
for (Intent psProvidedIntent : policySet.getProvidedIntents()){
if (isQualifiedBy(psProvidedIntent, intent)){
eprIntents.remove(intent);
break loop;
}
}
for (IntentMap map : policySet.getIntentMaps()) {
for (Qualifier q : map.getQualifiers()) {
if (intent.equals(q.getIntent())) {
eprIntents.remove(intent);
break loop;
}
}
}
}
}
}
// if there are unresolved intents the service and reference don't match
if (eprIntents.size() > 0){
matchAudit.append("No match because there are unresolved intents " + eprIntents.toString() + " ");
matchAudit.appendSeperator();
return false;
}
// TUSCANY-3959 - something that's not explicitly stated in the spec. mayProvides intents don't
// lead to policy sets as the binding natively implements the intent. So
// we need to check that these intents match explicitly between reference and service
// sides
if (eprMayProvideInterationIntents.size() > 0){
for (Intent eprIntent : eprMayProvideInterationIntents){
boolean match = false;
for (Intent epIntent : endpoint.getRequiredIntents()){
if (epIntent.equals(eprIntent)){
match = true;
break;
}
}
if (!match){
matchAudit.append("No match because the reference has a mayProvide intent that the service doesn't have " + eprIntent.getName());
matchAudit.appendSeperator();
return false;
}
}
}
// if there are no policies on epr or ep side then
// they match
if (noEndpointPolicies && noEndpointReferencePolicies){
matchAudit.append("Match because the intents are resolved and there are no policy sets ");
matchAudit.appendSeperator();
return true;
}
// if there are some policies on one side and not the other then
// the don't match
if (noEndpointPolicies && !noEndpointReferencePolicies) {
matchAudit.append("No match because there are policy sets at the endpoint reference but not at the endpoint ");
matchAudit.appendSeperator();
return false;
}
if (!noEndpointPolicies && noEndpointReferencePolicies){
matchAudit.append("No match because there are policy sets at the endpoint but not at the endpoint reference ");
matchAudit.appendSeperator();
return false;
}
// If policy set QNames from epr and er match exactly then the reference and
// service policies are compatible
Set<PolicySet> referencePolicySet = new HashSet<PolicySet>(referencePolicySets);
Set<PolicySet> servicePolicySet = new HashSet<PolicySet>(endpoint.getPolicySets());
if(referencePolicySet.equals(servicePolicySet)){
matchAudit.append("Match because the policy sets on both sides are eactly the same ");
matchAudit.appendSeperator();
return true;
}
// if policy set language at ep and epr are not the same then there is no
// match. We get the policy language by looking at the first expression
// of the first policy set. By this stage we know that all the policy sets
// in an endpoint or endpoint reference will use a single language and we know
// that there is at least one policy set with at least one policy
QName eprLanguage = null;
for (PolicySet policySet : referencePolicySets){
if (policySet.getPolicies().size() > 0){
eprLanguage = policySet.getPolicies().get(0).getName();
break;
}
}
QName epLanguage = null;
for (PolicySet policySet : endpoint.getPolicySets()){
if (policySet.getPolicies().size() > 0){
epLanguage = policySet.getPolicies().get(0).getName();
break;
}
}
if(!eprLanguage.getNamespaceURI().equals(epLanguage.getNamespaceURI())){
matchAudit.append("No match because the policy sets on either side have policies in differnt languages " +
eprLanguage +
" and " +
epLanguage +
" ");
matchAudit.appendSeperator();
return false;
}
// now do a policy specific language match
PolicyBuilder builder = builders.getPolicyBuilder(eprLanguage);
boolean match = false;
// switch the derived list of policy sets into the reference
// it will be left there if there is a match
List<PolicySet> originalPolicySets = endpointReference.getPolicySets();
endpointReference.getPolicySets().clear();
endpointReference.getPolicySets().addAll(referencePolicySets);
if (builder != null) {
if (builderContext == null){
builderContext = new BuilderContext(monitor);
}
match = builder.build(endpointReference, endpoint, builderContext);
}
if (!match){
matchAudit.append("No match because the language specific matching failed ");
matchAudit.appendSeperator();