/*
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors.
*
* 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.switchyard.internal;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.namespace.QName;
import org.switchyard.BaseHandler;
import org.switchyard.Exchange;
import org.switchyard.ExchangeHandler;
import org.switchyard.ExchangePattern;
import org.switchyard.ServiceDomain;
import org.switchyard.ServiceReference;
import org.switchyard.handlers.AddressingHandler;
import org.switchyard.handlers.PolicyHandler;
import org.switchyard.handlers.ProviderHandler;
import org.switchyard.handlers.SecurityHandler;
import org.switchyard.handlers.SecurityHandler.SecurityAction;
import org.switchyard.handlers.TransactionHandler;
import org.switchyard.handlers.TransformHandler;
import org.switchyard.handlers.ValidateHandler;
import org.switchyard.runtime.RuntimeMessages;
import org.switchyard.spi.Dispatcher;
import org.switchyard.spi.ExchangeBus;
/**
* Default endpoint provider.
*/
public class LocalExchangeBus implements ExchangeBus {
private ConcurrentHashMap<QName, Dispatcher> _dispatchers =
new ConcurrentHashMap<QName, Dispatcher>();
private HandlerChain _requestChain;
private HandlerChain _replyChain;
private ServiceDomain _domain;
/**
* Create a new LocalExchangeBus.
*/
public LocalExchangeBus() {
}
@Override
public void init(ServiceDomain domain) {
_domain = domain;
TransactionHandler transactionHandler = new TransactionHandler();
TransformHandler transformHandler = new TransformHandler(domain.getTransformerRegistry());
ValidateHandler validateHandler = new ValidateHandler(domain.getValidatorRegistry());
// Build out the request and reply handler chains.
_requestChain = new DefaultHandlerChain();
_requestChain.addLast("addressing", new AddressingHandler(_domain));
_requestChain.addLast("transaction-pre-invoke", transactionHandler);
_requestChain.addLast("security-process", new SecurityHandler(_domain, SecurityAction.PROCESS));
_requestChain.addLast("generic-policy", new PolicyHandler());
_requestChain.addLast("validation-before-transform", validateHandler);
_requestChain.addLast("transformation", transformHandler);
_requestChain.addLast("validation-after-transform", validateHandler);
_requestChain.addLast("provider", new ProviderHandler(_domain));
_requestChain.addLast("security-cleanup", new SecurityHandler(_domain, SecurityAction.CLEANUP));
_requestChain.addLast("transaction-post-invoke", transactionHandler);
_replyChain = new DefaultHandlerChain();
_replyChain.addLast("validation-before-transform", validateHandler);
_replyChain.addLast("transformation", transformHandler);
_replyChain.addLast("validation-after-transform", validateHandler);
_replyChain.addLast(HandlerChain.CONSUMER_HANDLER, new BaseHandler());
}
@Override
public void start() {
// NOP
}
@Override
public void stop() {
_dispatchers.clear();
}
@Override
public synchronized Dispatcher createDispatcher(ServiceReference reference) {
HandlerChain requestChain = _requestChain.copy();
HandlerChain replyChain = _replyChain.copy();
Dispatcher dispatcher = new LocalDispatcher(_domain, reference, requestChain, replyChain);
_dispatchers.put(reference.getName(), dispatcher);
return dispatcher;
}
@Override
public Dispatcher getDispatcher(ServiceReference reference) {
return _dispatchers.get(reference.getName());
}
}
class LocalDispatcher implements Dispatcher {
private HandlerChain _requestChain;
private HandlerChain _replyChain;
private ServiceReference _reference;
private ServiceDomain _domain;
/**
* Constructor.
* @param _domain
* @param handlerChain handler chain
*/
LocalDispatcher(ServiceDomain domain, final ServiceReference reference, final HandlerChain requestChain, final HandlerChain replyChain) {
this._domain = domain;
_reference = reference;
_requestChain = requestChain;
_replyChain = replyChain;
}
@Override
public void dispatch(final Exchange exchange) {
switch (exchange.getPhase()) {
case IN:
_requestChain.handle(exchange);
break;
case OUT:
ExchangeHandler replyHandler = ((ExchangeImpl)exchange).getReplyHandler();
if (replyHandler != null) {
_replyChain.replace(HandlerChain.CONSUMER_HANDLER, replyHandler);
}
_replyChain.handle(exchange);
break;
default:
throw RuntimeMessages.MESSAGES.invalidPhaseForDispatch(exchange.getPhase().toString());
}
}
@Override
public ServiceReference getServiceReference() {
return _reference;
}
@Override
public Exchange createExchange(ExchangeHandler handler, ExchangePattern pattern) {
ExchangeImpl exchangeImpl = new ExchangeImpl(_domain, this, handler);
return exchangeImpl;
}
}