/*
* 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.component.http;
import java.util.Set;
import org.switchyard.Exchange;
import org.switchyard.ExchangePattern;
import org.switchyard.ExchangeState;
import org.switchyard.HandlerException;
import org.switchyard.Message;
import org.switchyard.Scope;
import org.switchyard.ServiceDomain;
import org.switchyard.ServiceReference;
import org.switchyard.component.common.Endpoint;
import org.switchyard.component.common.SynchronousInOutHandler;
import org.switchyard.component.common.composer.MessageComposer;
import org.switchyard.component.common.selector.OperationSelectorFactory;
import org.switchyard.component.http.composer.HttpBindingData;
import org.switchyard.component.http.composer.HttpComposition;
import org.switchyard.component.http.composer.HttpRequestBindingData;
import org.switchyard.component.http.composer.HttpResponseBindingData;
import org.switchyard.component.http.config.model.HttpBindingModel;
import org.switchyard.component.http.endpoint.EndpointPublisherFactory;
import org.switchyard.deploy.BaseServiceHandler;
import org.switchyard.label.BehaviorLabel;
import org.switchyard.metadata.ServiceOperation;
import org.switchyard.runtime.event.ExchangeCompletionEvent;
import org.switchyard.security.context.SecurityContextManager;
import org.switchyard.selector.OperationSelector;
/**
* Hanldes HTTP requests to invoke a SwitchYard service.
*
* @author Magesh Kumar B <mageshbk@jboss.com> (C) 2012 Red Hat Inc.
*/
public class InboundHandler extends BaseServiceHandler {
private final HttpBindingModel _config;
private final String _gatewayName;
private SecurityContextManager _securityContextManager;
private ServiceDomain _domain;
private ServiceReference _serviceRef;
private MessageComposer<HttpBindingData> _messageComposer;
private final OperationSelector<HttpBindingData> _operationSelector;
private Endpoint _endpoint;
/**
* Constructor.
* @param config the configuration settings
* @param domain the service domain
*/
public InboundHandler(final HttpBindingModel config, ServiceDomain domain) {
super(domain);
_config = config;
_gatewayName = config.getName();
_domain = domain;
_securityContextManager = new SecurityContextManager(_domain);
_operationSelector = OperationSelectorFactory
.getOperationSelectorFactory(HttpBindingData.class)
.newOperationSelector(config.getOperationSelector());
}
/**
* Start lifecycle.
*
* @throws HttpPublishException If unable to publish the service
*/
@Override
protected void doStart() throws HttpPublishException {
try {
_serviceRef = _domain.getServiceReference(_config.getServiceName());
String contextPath = _config.getContextPath();
if (contextPath == null) {
contextPath = "/";
}
_endpoint = EndpointPublisherFactory.getPublisher().publish(_domain, contextPath, this);
// Create and configure the HTTP message composer
_messageComposer = HttpComposition.getMessageComposer(_config);
} catch (Exception e) {
throw HttpMessages.MESSAGES.unableToPublish(e);
}
_endpoint.start();
}
/**
* Invokes the SwitchYard service.
*
* @param input the HTTP request message
* @return the HTTP response message from invocation
*/
public HttpResponseBindingData invoke(final HttpRequestBindingData input) {
HttpResponseBindingData response = null;
try {
SynchronousInOutHandler inOutHandler = new SynchronousInOutHandler();
Exchange exchange = _serviceRef.createExchange(getOperationName(input), inOutHandler);
// identify ourselves
exchange.getContext().setProperty(ExchangeCompletionEvent.GATEWAY_NAME, _gatewayName, Scope.EXCHANGE)
.addLabels(BehaviorLabel.TRANSIENT.label());
Message message = _messageComposer.compose(input, exchange);
_securityContextManager.addCredentials(exchange, input.extractCredentials());
if (exchange.getContract().getConsumerOperation().getExchangePattern() == ExchangePattern.IN_ONLY) {
exchange.send(message);
if (exchange.getState().equals(ExchangeState.FAULT)) {
response = (HttpResponseBindingData) _messageComposer.decompose(exchange, new HttpResponseBindingData());
} else {
response = new HttpResponseBindingData();
}
} else {
exchange.send(message);
exchange = inOutHandler.waitForOut();
response = (HttpResponseBindingData) _messageComposer.decompose(exchange, new HttpResponseBindingData());
}
} catch (Exception e) {
HttpLogger.ROOT_LOGGER.unexpectedExceptionInvokingSwitchyardServcie(e);
}
return response;
}
/**
* Stop lifecycle.
*/
@Override
protected void doStop() {
_endpoint.stop();
}
@Override
public void handleFault(Exchange exchange) {
throw HttpMessages.MESSAGES.unexpectedFault();
}
@Override
public void handleMessage(Exchange exchange) throws HandlerException {
throw HttpMessages.MESSAGES.unexpectedMessage();
}
private String getOperationName(HttpRequestBindingData message) throws Exception {
String operationName = null;
if (_operationSelector != null) {
operationName = _operationSelector.selectOperation(message).getLocalPart();
}
if (operationName == null) {
final Set<ServiceOperation> operations = _serviceRef.getInterface().getOperations();
if (operations.size() != 1) {
throw HttpMessages.MESSAGES.moreThanOneOperationSelector(operations);
}
final ServiceOperation serviceOperation = operations.iterator().next();
operationName = serviceOperation.getName();
}
return operationName;
}
}