* @param endpointReference
* @param endpoints
*/
private void selectForwardEndpoint(EndpointReference endpointReference, List<Endpoint> endpoints, Audit matchAudit, BuilderContext builderContext, boolean runtime) {
Endpoint matchedEndpoint = null;
if (endpointReference.getReference().getName().startsWith("$self$.")){
// just select the first one and don't do any policy matching
if (endpointReference.getTargetEndpoint() != null && !endpointReference.getTargetEndpoint().isUnresolved()) {
matchedEndpoint = endpointReference.getTargetEndpoint();
} else {
matchedEndpoint = endpoints.get(0);
}
} else {
// find the endpoints that match this endpoint reference
List<Endpoint> matchedEndpoints = new ArrayList<Endpoint>();
for (Endpoint endpoint : endpoints){
if (haveMatchingPolicy(endpointReference, endpoint, matchAudit, builderContext) &&
haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){
matchedEndpoints.add(endpoint);
}
}
// TUSCANY-4005 - raise an error if a reference target that only specifies the
// component name matches more than one component service
if (endpointReference.getTargetEndpoint().getService() == null &&
endpointReference.getTargetEndpoint().getBinding() == null &&
matchedEndpoints.size() > 1 ) {
String serviceName = null;
for (Endpoint endpoint : matchedEndpoints){
// ignore service names called "default" as these indicate dynamic services
// created for the likes of implementation.python
if (serviceName == null &&
!endpoint.getService().getName().equals("default")){
serviceName = endpoint.getService().getName();
}
if (serviceName != null &&
!endpoint.getService().getName().equals("default") &&
!endpoint.getService().getName().equals(serviceName)){
if (runtime){
Monitor.error(monitor,
this,
"endpoint-validation-messages",
"TooManyTargetServices",
endpointReference.toString(),
endpointReference.getTargetEndpoint().toString(),
matchAudit);
throw new ServiceRuntimeException("Unable to bind " +
monitor.getLastProblem().toString());
} else {
Monitor.warning(monitor,
this,
"endpoint-validation-messages",
"TooManyTargetServices",
endpointReference.toString(),
endpointReference.getTargetEndpoint().toString());
return;
}
}
}
}
// TUSCANY-3941 check for the case where the user has provided a
// binding.sca at the reference and make sure we pick
// a binding.sca at the service regardless of how many
// other bindings are provided
if (endpointReference.getBinding() != null &&
endpointReference.getBinding() instanceof SCABinding ){
for (Endpoint endpoint : matchedEndpoints){
if (endpoint.getBinding() instanceof SCABinding){
matchedEndpoint = endpoint;
break;
}
}
}
if (matchedEndpoint == null) {
// just take the first matched endpoint from the list
if (matchedEndpoints.size() > 0){
matchedEndpoint = matchedEndpoints.get(0);
}
}
}
if (matchedEndpoint == null){
return;
} else {
endpointReference.setTargetEndpoint(matchedEndpoint);
Binding binding = matchedEndpoint.getBinding();
try {
endpointReference.setBinding((Binding)binding.clone());
} catch (CloneNotSupportedException e) {
// shouldn't happen
throw new RuntimeException(e);
}
// TUSCANY-3873 - add policy from the service
// we don't care about intents at this stage
endpointReference.getPolicySets().addAll(matchedEndpoint.getPolicySets());
// TODO - we need to re-run the appliesTo processing here but there is some question about what
// appliesTo means. It's also difficult to get to the PolicyAppliesToBuilder from here and
// need a new EntensionInterface to support access. So for now I'm just cheating and looking to
// see if the XPath expression contains the binding type as a string while we discuss appliesTo