blob: 9c4da518d7d1011f57ae3ec44fb2e6049c6834b3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tuscany.sca.builder.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import org.apache.tuscany.sca.assembly.Base;
import org.apache.tuscany.sca.assembly.Component;
import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.Composite;
import org.apache.tuscany.sca.assembly.Endpoint;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.assembly.Implementation;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilder;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
import org.apache.tuscany.sca.assembly.builder.PolicyBuilder;
import org.apache.tuscany.sca.assembly.xml.Constants;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.policy.Intent;
import org.apache.tuscany.sca.policy.PolicySet;
import org.apache.tuscany.sca.policy.PolicySubject;
import org.apache.tuscany.sca.policy.util.PolicyHelper;
/**
* A composite builder that computes policy sets based on attached intents and policy sets.
* Useful if you want to build the model without making any runtime decisions such as
* reference/services matching
*
* @version $Rev$ $Date$
*/
public class CompositePolicyBuilderImpl extends ComponentPolicyBuilderImpl implements CompositeBuilder {
private final static QName NOLISTENER_INTENT = new QName(Base.SCA11_NS, "noListener");
private CompositeBuilder policyAppliesToBuilder = null;
public CompositePolicyBuilderImpl(ExtensionPointRegistry registry) {
super(registry);
policyAppliesToBuilder = new PolicyAppliesToBuilderImpl(registry);
}
public String getID() {
return "org.apache.tuscany.sca.assembly.builder.CompositePolicyBuilder";
}
public Composite build(Composite composite, BuilderContext context) throws CompositeBuilderException {
computePolicies(composite, context);
checkPolicies(composite, context);
buildPolicies(composite, context);
return composite;
}
protected void computePolicies(Composite composite, BuilderContext context) {
Monitor monitor = context.getMonitor();
monitor.pushContext("Composite: " + composite.getName().toString());
try {
resolveAndCheck(composite, context);
// compute policies recursively
for (Component component : composite.getComponents()) {
monitor.pushContext("Component: " + component.getName());
//resolve component level
resolveAndCheck(component, context);
try {
Implementation implementation = component.getImplementation();
for (ComponentService componentService : component.getServices()) {
monitor.pushContext("Service: " + componentService.getName());
try {
resolveAndCheck(componentService, context);
if (componentService.getInterfaceContract() != null) {
resolveAndCheck(componentService.getInterfaceContract().getInterface(), context);
resolveAndCheck(componentService.getInterfaceContract().getCallbackInterface(), context);
}
for (Endpoint ep : componentService.getEndpoints()) {
// Inherit from binding
inherit(ep, null, true, ep.getBinding());
// Inherit from composite/component/service
inherit(ep, null, true, ep.getService(), ep.getComponent(), composite );
if (componentService.getInterfaceContract() != null) {
// Inherit from the component.service.interface
// Do not check mutual exclusion here.. interfaces do not follow normal rules
// of the structural hierarchy (Policy spec 4.10)
inherit(ep, null, false, componentService.getInterfaceContract().getInterface());
}
// Replace profile intents with their required intents
// Replace unqualified intents if there is a qualified intent in the list
// Replace qualifiable intents with the default qualied intent
resolveAndNormalize(ep, context);
// Replace qualifiable intents with their default qualifier
expandDefaultIntents(ep, context);
// Remove the intents whose @contraints do not include the current element
removeConstrainedIntents(ep, context);
// Remove any direct policy sets if an external one has been applied
removeDirectPolicySetsIfExternalExists(ep, context);
// Validate that noListener is not specified on a service endpoint
checkForNoListenerIntent(ep, context);
// check that all intents are resolved
checkIntentsResolved(ep, context);
// check that the resulting endpoint has no mutually exclusive intents
checkMutualExclusion(ep, context);
}
} finally {
monitor.popContext();
}
}
for (ComponentReference componentReference : component.getReferences()) {
monitor.pushContext("Reference: " + componentReference.getName().toString());
try {
if (componentReference.getInterfaceContract() != null) {
resolveAndCheck(componentReference.getInterfaceContract().getInterface(), context);
resolveAndCheck(componentReference.getInterfaceContract().getCallbackInterface(),
context);
}
for (EndpointReference epr : componentReference.getEndpointReferences()) {
// Inherit from binding
inherit(epr, null, true, epr.getBinding());
// Inherit from composite/component/reference
inherit(epr, null, true, epr.getReference(), epr.getComponent(), composite);
// Inherit from the component.reference.interface
if (componentReference.getInterfaceContract() != null) {
// Do not check mutual exclusion here.. interfaces do not follow normal rules
// of the structural hierarchy (Policy spec 4.10)
inherit(epr, null, true, componentReference.getInterfaceContract().getInterface());
}
// Replace profile intents with their required intents
// Replace unqualified intents if there is a qualified intent in the list
// Replace qualifiable intents with the default qualified intent
resolveAndNormalize(epr, context);
// Replace qualifiable intents with their default qualifier
expandDefaultIntents(epr, context);
// Remove the intents whose @contraints do not include the current element
removeConstrainedIntents(epr, context);
removeDirectPolicySetsIfExternalExists(epr, context);
// check that all intents are resolved
checkIntentsResolved(epr, context);
// check that the resulting endpoint reference has no mutually exclusive intents
checkMutualExclusion(epr, context);
}
} finally {
monitor.popContext();
}
}
if (implementation instanceof Composite) {
resolveAndCheck(implementation, context);
inherit(implementation, Intent.Type.implementation, true, component, composite);
computePolicies((Composite)implementation, context);
expandDefaultIntents(implementation,context);
checkIntentsResolved(implementation,context);
} else {
resolveAndCheck(implementation, context);
if (implementation != null) {
inherit(implementation, Intent.Type.implementation, true, component, composite);
// Remove the intents whose @contraints do not include the current element
removeConstrainedIntents(implementation, context);
removeDirectPolicySetsIfExternalExists(implementation, context);
// Replace qualifiable intents with their default qualifier
expandDefaultIntents(implementation, context);
// check that all intents are resolved
checkIntentsResolved(implementation, context);
}
}
} finally {
monitor.popContext();
}
}
removeConstrainedIntents(composite, context);
} finally {
monitor.popContext();
}
}
private void validateTransactionIntents(Composite composite, BuilderContext context) {
for ( Component component : composite.getComponents() ) {
if ( component.getImplementation() != null ) {
if ( component.getImplementation() instanceof Composite )
validateTransactionIntents((Composite) component.getImplementation(), context);
for ( Intent implIntent : component.getImplementation().getRequiredIntents() ) {
if ( Constants.MANAGED_TRANSACTION_LOCAL_INTENT.equals(implIntent.getName() ) ) {
for ( ComponentReference reference : component.getReferences() ) {
for ( EndpointReference epr : reference.getEndpointReferences() ) {
for ( Intent eprIntent : epr.getRequiredIntents() ) {
if ( Constants.TRANSACTED_ONE_WAY_INTENT.equals(eprIntent.getName())) {
error(context.getMonitor(),
"TransactedOneWayWithManagedTransactionLocal",
this,
"reference",
epr.getComponent().getName(),
epr.getReference().getName());
} else if ( Constants.PROPAGATES_TRANSACTION_INTENT.equals(eprIntent.getName())) {
error(context.getMonitor(),
"PropagatesTransactionWithLocalTran",
this,
"reference",
epr.getComponent().getName(),
epr.getReference().getName());
}
}
}
}
for ( ComponentService service : component.getServices() ) {
for ( Endpoint ep : service.getEndpoints() ) {
for ( Intent epIntent : ep.getRequiredIntents() ) {
if ( Constants.TRANSACTED_ONE_WAY_INTENT.equals(epIntent.getName())) {
error(context.getMonitor(),
"TransactedOneWayWithManagedTransactionLocal",
this,
"service",
ep.getComponent().getName(),
ep.getService().getName());
} else if ( Constants.PROPAGATES_TRANSACTION_INTENT.equals(epIntent.getName())) {
error(context.getMonitor(),
"PropagatesTransactionWithLocalTran",
this,
"service",
ep.getComponent().getName(),
ep.getService().getName());
}
}
}
}
} else if ( Constants.NO_MANAGED_TRANSACTION_INTENT.equals(implIntent.getName())) {
for ( ComponentService service : component.getServices() ) {
for ( Endpoint ep : service.getEndpoints() ) {
for ( Intent epIntent : ep.getRequiredIntents() ) {
if ( Constants.PROPAGATES_TRANSACTION_INTENT.equals(epIntent.getName())) {
error(context.getMonitor(),
"PropagatesTransactionWithNoManagedTran",
this,
"service",
ep.getComponent().getName(),
ep.getService().getName());
}
}
}
}
for ( ComponentReference reference : component.getReferences() ) {
for ( EndpointReference epr : reference.getEndpointReferences() ) {
for ( Intent eprIntent : epr.getRequiredIntents() ) {
if ( Constants.PROPAGATES_TRANSACTION_INTENT.equals(eprIntent.getName())) {
error(context.getMonitor(),
"PropagatesTransactionWithNoManagedTran",
this,
"reference",
epr.getComponent().getName(),
epr.getReference().getName());
}
}
}
}
}
}
for ( ComponentReference reference : component.getReferences()) {
for ( EndpointReference epr : reference.getEndpointReferences() ) {
for ( Intent eprIntent : epr.getRequiredIntents() ) {
if ( Constants.TRANSACTED_ONE_WAY_INTENT.equals(eprIntent.getName()) ) {
for ( Operation o : epr.getComponentReferenceInterfaceContract().getInterface().getOperations() ) {
if ( !o.isNonBlocking() ) {
error(context.getMonitor(),
"TransactedOneWayWithTwoWayOp",
this,
reference.getName(),
o.getName());
}
}
} else if ( Constants.IMMEDIATE_ONE_WAY_INTENT.equals(eprIntent.getName())) {
for ( Operation o : epr.getComponentReferenceInterfaceContract().getInterface().getOperations() ) {
if ( !o.isNonBlocking() ) {
error(context.getMonitor(),
"ImmediateOneWayWithTwoWayOp",
this,
reference.getName(),
o.getName());
}
}
}
}
}
}
}
}
}
private void checkForNoListenerIntent(Endpoint ep, BuilderContext context) {
PolicyHelper helper = new PolicyHelper();
if ( helper.getIntent(ep, NOLISTENER_INTENT) != null ) {
error(context.getMonitor(),
"NoListenerIntentSpecifiedOnService",
this,
ep.toString());
}
}
private void removeDirectPolicySetsIfExternalExists(PolicySubject subject,
BuilderContext context) {
boolean foundExternalPolicySet = false;
for (PolicySet ps : subject.getPolicySets() ) {
if ( ps.isExternalAttachment() ) {
foundExternalPolicySet = true;
break;
}
}
if ( foundExternalPolicySet ) {
List<PolicySet> copy = new ArrayList<PolicySet>(subject.getPolicySets());
for ( PolicySet ps : copy ) {
if ( !ps.isExternalAttachment() ) {
subject.getPolicySets().remove(ps);
}
}
}
}
/**
* This is mainly about removing policies that don't "applyTo" the element where
* they have ended up after all the attachment and inheritance processing
*
* @param composite
* @param context
*/
protected void checkPolicies(Composite composite, BuilderContext context) throws CompositeBuilderException{
policyAppliesToBuilder.build(composite, context);
validateTransactionIntents(composite, context);
}
protected void buildPolicies(Composite composite, BuilderContext context) {
// build policies recursively
for (Component component : composite.getComponents()) {
Implementation implementation = component.getImplementation();
if (implementation instanceof Composite) {
buildPolicies((Composite)implementation, context);
}
}
for (Component component : composite.getComponents()) {
for (ComponentService componentService : component.getServices()) {
for (Endpoint ep : componentService.getEndpoints()) {
Set<QName> policyNames = getPolicyNames(ep);
// check that only one policy language is present in the endpoint's policy sets
if (policyNames.size() > 1){
error(context.getMonitor(),
"MultiplePolicyLanguagesInEP",
this,
ep.toString(),
policyNames.toString());
} else {
for (QName policyType : policyNames) {
PolicyBuilder builder = builders.getPolicyBuilder(policyType);
if (builder != null) {
builder.build(ep, context);
}
}
}
}
}
for (ComponentReference componentReference : component.getReferences()) {
for (EndpointReference epr : componentReference.getEndpointReferences()) {
Set<QName> policyNames = getPolicyNames(epr);
// check that only one policy language is present in the endpoint references's policy sets
if (policyNames.size() > 1){
error(context.getMonitor(),
"MultiplePolicyLanguagesInEPR",
this,
epr.toString(),
policyNames.toString());
} else {
for (QName policyType : policyNames) {
PolicyBuilder builder = builders.getPolicyBuilder(policyType);
if (builder != null) {
builder.build(epr, context);
}
}
}
}
}
Implementation implementation = component.getImplementation();
if (implementation != null) {
Set<QName> policyNames = getPolicyNames(implementation);
// check that only one policy language is present in the implementations's policy sets
if (policyNames.size() > 1){
error(context.getMonitor(),
"MultiplePolicyLanguagesInImplementation",
this,
component.toString(),
policyNames.toString());
} else {
for (QName policyType : policyNames) {
PolicyBuilder builder = builders.getPolicyBuilder(policyType);
if (builder != null) {
builder.build(component, implementation, context);
}
}
}
}
}
}
}