boolean isOneWayOperation = operation.isNonBlocking();
boolean operationHasCallback = contract.getCallbackName() != null;
if (isOneWayOperation && operationHasCallback) {
throw new ComponentRuntimeException("Operation cannot be marked one-way and have a callback");
}
TargetInvoker invoker = null;
if (target instanceof Component) {
Component component = (Component) target;
if (isOneWayOperation || operationHasCallback) {
invoker = component.createAsyncTargetInvoker(targetWire, inboundOperation);
} else {
String portName = sourceWire.getTargetName().getPortName();
invoker = component.createTargetInvoker(portName, inboundOperation);
}
} else if (target instanceof Reference) {
Reference reference = (Reference) target;
if (!(reference instanceof CompositeReference) && operationHasCallback) {
// Notice that for bound references we only use async target invokers for callback operations
invoker = reference.createAsyncTargetInvoker(sourceWire, inboundOperation);
} else {
ServiceContract targetContract = targetWire.getServiceContract();
invoker = reference.createTargetInvoker(targetContract, inboundOperation);
}
} else if (target instanceof CompositeService) {
CompositeService compServ = (CompositeService) target;
invoker = compServ.createTargetInvoker(targetWire.getServiceContract(), inboundChain.getOperation());
}
if (source instanceof Service && !(source instanceof CompositeService)) {
// services are a special case: invoker must go on the inbound chain
if (target instanceof Component && (isOneWayOperation || operationHasCallback)) {
// if the target is a component and the operation is non-blocking
connect(outboundChain, inboundChain, null, true);
} else {
connect(outboundChain, inboundChain, null, false);
}
Service service = (Service) source;
InboundInvocationChain chain = service.getInboundWire().getInvocationChains().get(operation);
chain.setTargetInvoker(invoker);
} else {
if (target instanceof Component && (isOneWayOperation || operationHasCallback)) {
// if the target is a component and the operation is non-blocking
connect(outboundChain, inboundChain, invoker, true);
} else {
connect(outboundChain, inboundChain, invoker, false);
}
}
}
// create source callback chains and connect them if target callback chains exist
Map<Operation<?>, OutboundInvocationChain> sourceCallbackChains =
targetWire.getSourceCallbackInvocationChains(source.getName());
for (InboundInvocationChain inboundChain : sourceWire.getTargetCallbackInvocationChains().values()) {
Operation<?> operation = inboundChain.getOperation();
if (sourceCallbackChains != null && sourceCallbackChains.get(operation) != null) {
String name = operation.getName();
BuilderConfigException e =
new BuilderConfigException("Source callback chain should not exist for operation [" + name + "]");
e.setIdentifier(sourceWire.getReferenceName());
throw e;
}
Operation targetOp =
(Operation)targetWire.getServiceContract().getCallbackOperations().get(operation.getName());
OutboundInvocationChain outboundChain = wireService.createOutboundChain(targetOp);
targetWire.addSourceCallbackInvocationChain(source.getName(), targetOp, outboundChain);
if (source instanceof Component) {
Component component = (Component) source;
TargetInvoker invoker = component.createTargetInvoker(null, operation);
connect(outboundChain, inboundChain, invoker, false);
} else if (source instanceof CompositeReference) {
CompositeReference compRef = (CompositeReference) source;
ServiceContract sourceContract = sourceWire.getServiceContract();
TargetInvoker invoker = compRef.createCallbackTargetInvoker(sourceContract, operation);
connect(outboundChain, inboundChain, invoker, false);
} else if (source instanceof Service) {
Service service = (Service) source;
ServiceContract sourceContract = sourceWire.getServiceContract();
TargetInvoker invoker = service.createCallbackTargetInvoker(sourceContract, operation);
connect(outboundChain, inboundChain, invoker, false);
}
}
if (postProcessorRegistry != null) {
// run wire post-processors