diff options
Diffstat (limited to 'sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java')
-rw-r--r-- | sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java new file mode 100644 index 0000000000..2c5e61a8a1 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java @@ -0,0 +1,279 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed 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.core.invocation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.core.invocation.impl.MessageChannelImpl; +import org.apache.tuscany.core.invocation.impl.MessageDispatcher; +import org.apache.tuscany.core.invocation.impl.RequestResponseInterceptor; + +/** + * Contains a source- or target-side invocation pipeline for a service operation. Source and target invocation pipelines + * are "bridged" together by a set of wire builders with the source-side holding references to the target. + * <p> + * A set of invocation configurations are used by a {@link org.apache.tuscany.core.invocation.spi.ProxyFactory} to + * create service proxies. + * <p> + * Invocation configurations must contain at least one interceptor and may have 0 to N handlers. Handlers process an + * invocation request or response in a one-way fashion. A typical invocation sequence where interceptors and handlers + * are configured for both the source and target-side will proceed as follows: + * <ol> + * <li>The first source interceptor will be called with a message, which will in turn invoke the next interceptor in + * the chain + * <li>The last source interceptor, which must be of type + * {@link org.apache.tuscany.core.invocation.impl.RequestResponseInterceptor} if there are handlers present, will be + * invoked. The RR interceptor will in turn pass the message to a + * {@link org.apache.tuscany.core.invocation.MessageChannel} which will invoke all source-side request handlers. + * <li> The RR interceptor will then invoke the target-side request <tt>MessageChannel</tt>. + * <li> The last source-side handler, an instance of + * {@link org.apache.tuscany.core.invocation.impl.MessageDispatcher}, will invoke the first source-side + * interceptor, which in turn will pass the message down the target-side interceptor chain. + * <li> If the target is a component instance the last target-side interceptor, an instance of + * {@link org.apache.tuscany.core.invocation.impl.InvokerInterceptor} will retrieve the + * {@link org.apache.tuscany.core.invocation.TargetInvoker} from the message and call it to invoke the operation on a + * target instance. <tt>TargetInvoker</tt>s are help by the source proxy to enable optimizations such as caching of + * target instances. + * <li> The response is returned up the invocation stack until it reaches the source-side + * <tt>RequestResponseInterceptor</tt>, which invokes the target and source-side response channels respectively. + * <li> The response is then passed back up the rest of the invocation stack. + * </ol> + * <p> + * The source-to-target bridge may be constructed in any of the following ways: + * <ul> + * <li>Source handler-to-target handler + * <li>Source handler-to-target interceptor + * <li>Source interceptor-to-target handler + * <li>Source interceptor-to-target interceptor + * </ul> + * <p> + * In some scenarios, a service proxy may only contain target-side invocaton chains, for example, when a service is + * resolved through a locate operation by a non-component client. In this case, there will be no source-side invocation + * chains and the target invoker will be held by the target-side and passed down the pipeline. + * + * @see org.apache.tuscany.core.builder.WireBuilder + * @see org.apache.tuscany.core.invocation.spi.ProxyFactory + * @see org.apache.tuscany.core.invocation.TargetInvoker + * @see org.apache.tuscany.core.invocation.impl.MessageDispatcher + * + * @version $Rev$ $Date$ + */ +public class InvocationConfiguration { + + // the operation on the target that will utlimately be invoked + private Method operation; + + // responsible for invoking a target instance + private TargetInvoker targetInvoker; + + private Interceptor sourceInterceptorChainHead; + + private Interceptor sourceInterceptorChainTail; + + private Interceptor targetInterceptorChainHead; + + private Interceptor targetInterceptorChainTail; + + private List<MessageHandler> requestHandlers; + + private List<MessageHandler> responseHandlers; + + // a source-side pointer to target request handlers, if the exist + private MessageChannel targetRequestChannel; + + // a source-side pointer to target response handlers, if the exist + private MessageChannel targetResponseChannel; + + /** + * Creates an new invocation configuration for the given target operation + */ + public InvocationConfiguration(Method operation) { + assert (operation != null) : "No operation type specified"; + this.operation = operation; + } + + /** + * Returns the target operation for the invocation configuration + */ + public Method getMethod() { + return operation; + } + + /** + * Used by source-side configurations, sets a pointer to the target-side request channel. This may be null when no + * target request handlers exist. + */ + public void setTargetRequestChannel(MessageChannel channel) { + targetRequestChannel = channel; + } + + /** + * Used by source-side configurations, sets a pointer to the target-side response channel. This may be null when no + * target response handlers exist. + */ + public void setTargetResponseChannel(MessageChannel channel) { + targetResponseChannel = channel; + } + + /** + * Adds an interceptor to the invocation chain for source-side configurations + */ + public void addSourceInterceptor(Interceptor interceptor) { + if (sourceInterceptorChainHead == null) { + sourceInterceptorChainHead = interceptor; + } else { + sourceInterceptorChainTail.setNext(interceptor); + } + sourceInterceptorChainTail = interceptor; + } + + /** + * Adds an interceptor to the invocation chain for target-side configurations + */ + public void addTargetInterceptor(Interceptor interceptor) { + if (targetInterceptorChainHead == null) { + targetInterceptorChainHead = interceptor; + } else { + targetInterceptorChainTail.setNext(interceptor); + } + targetInterceptorChainTail = interceptor; + } + + /** + * Adds an request handler to the invocation chain for either a source- or target-side configuration + */ + public void addRequestHandler(MessageHandler handler) { + if (requestHandlers == null) { + requestHandlers = new ArrayList<MessageHandler>(); + } + requestHandlers.add(handler); + } + + /** + * Adds an response handler to the invocation chain for either a source- or target-side configuration + */ + public void addResponseHandler(MessageHandler handler) { + if (responseHandlers == null) { + responseHandlers = new ArrayList<MessageHandler>(); + } + responseHandlers.add(handler); + } + + /** + * Returns the request handler chain for either a source- or target-side configuration + */ + public List<MessageHandler> getRequestHandlers() { + return requestHandlers; + } + + /** + * Returns the response handler chain for either a source- or target-side configuration + */ + public List<MessageHandler> getResponseHandlers() { + return responseHandlers; + } + + /** + * Returns the head source-side interceptor. This will be null for target-side configurations + */ + public Interceptor getSourceInterceptor() { + return sourceInterceptorChainHead; + } + + /** + * Returns the head target-side interceptor. On source-side configurations, this will be the head interceptor of the + * "bridged" target configuration. + */ + public Interceptor getTargetInterceptor() { + return targetInterceptorChainHead; + } + + + public Interceptor getLastTargetInterceptor() { + return targetInterceptorChainTail; + } + + /** + * Sets the target invoker to pass down the invocation pipeline. When a service proxy represents a wire, + * the target invoker is set on the source-side. + */ + public void setTargetInvoker(TargetInvoker invoker) { + this.targetInvoker = invoker; + } + + /** + * Returns the target invoker that is passed down the invocation pipeline. When a service proxy represents a wire, + * the target invoker is cached on the source-side. + */ + public TargetInvoker getTargetInvoker() { + return targetInvoker; + } + + /** + * Prepares the configuration by linking interceptors and handlers + */ + public void build() { + + if (requestHandlers != null && targetInterceptorChainHead != null) { + // on target-side, connect existing handlers and interceptors + MessageHandler messageDispatcher = new MessageDispatcher(targetInterceptorChainHead); + requestHandlers.add(messageDispatcher); + } + + if (requestHandlers != null) { + MessageChannel requestChannel = new MessageChannelImpl(requestHandlers); + MessageChannel responseChannel = new MessageChannelImpl(responseHandlers); + Interceptor channelInterceptor = new RequestResponseInterceptor(requestChannel, targetRequestChannel, + responseChannel, targetResponseChannel); + + if (sourceInterceptorChainHead != null) { + sourceInterceptorChainTail.setNext(channelInterceptor); + } else { + sourceInterceptorChainHead = channelInterceptor; + } + + } else { + // no request handlers + if (sourceInterceptorChainHead != null) { + if (targetInterceptorChainHead != null) { + // Connect source interceptor chain directly to target interceptor chain + sourceInterceptorChainTail.setNext(targetInterceptorChainHead); + // sourceInterceptorChainTail = targetInterceptorChainHead; + } else { + // Connect source interceptor chain to the target request channel + Interceptor channelInterceptor = new RequestResponseInterceptor(null, targetRequestChannel, null, + targetResponseChannel); + sourceInterceptorChainTail.setNext(channelInterceptor); + } + } else { + // no source interceptor chain or source handlers, conntect to target interceptor chain or channel + if (targetInterceptorChainHead != null) { + sourceInterceptorChainHead = targetInterceptorChainHead; + sourceInterceptorChainTail = targetInterceptorChainHead; + } else { + Interceptor channelInterceptor = new RequestResponseInterceptor(null, targetRequestChannel, null, + targetResponseChannel); + sourceInterceptorChainHead = channelInterceptor; + sourceInterceptorChainTail = channelInterceptor; + } + } + } + } + +} |