/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.runtime.spf.impl.internal.pipeline;
import java.util.List;
import org.ebayopensource.turmeric.common.v1.types.CommonErrorData;
import org.ebayopensource.turmeric.common.v1.types.ErrorMessage;
import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory;
import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceCreationException;
import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceException;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.GlobalConfigHolder;
import org.ebayopensource.turmeric.runtime.common.impl.internal.monitoring.MonitoringSystem;
import org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline.BaseMessageContextImpl;
import org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline.BaseMessageProcessorImpl;
import org.ebayopensource.turmeric.runtime.common.pipeline.Dispatcher;
import org.ebayopensource.turmeric.runtime.common.pipeline.OutboundMessage;
import org.ebayopensource.turmeric.runtime.common.types.SOAHeaders;
import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants;
import org.ebayopensource.turmeric.runtime.spf.impl.internal.config.ServiceConfigManager;
import org.ebayopensource.turmeric.runtime.spf.impl.internal.markdown.SOAServerMarkdownStateManager;
import org.ebayopensource.turmeric.runtime.spf.impl.internal.monitoring.ServerServiceMonitoringCompStatus;
import org.ebayopensource.turmeric.runtime.spf.impl.internal.service.ServerServiceDesc;
import org.ebayopensource.turmeric.runtime.spf.impl.internal.service.ServerServiceDescFactory;
import org.ebayopensource.turmeric.runtime.spf.pipeline.ErrorMapper;
import org.ebayopensource.turmeric.runtime.spf.pipeline.HttpError;
import org.ebayopensource.turmeric.runtime.spf.pipeline.ServerMessageContext;
import org.ebayopensource.turmeric.runtime.spf.pipeline.VersionCheckHandler;
/**
* Implements server-side processing of the MessageContext.
*
* MessageContext is created by the Servlet or other receiving subsystem,
* such as LocalTransport, POP3 poller, etc. This implementation runs
* appropriate handlers, protocol processor and dispatchers.
*
* @author ichernyshev, smalladi
*/
public class ServerMessageProcessor extends BaseMessageProcessorImpl {
private static ServerMessageProcessor s_instance;
private ServerMessageProcessor() {
// local instances
}
public static synchronized ServerMessageProcessor getInstance() throws ServiceException {
if (s_instance == null) {
s_instance = new ServerMessageProcessor();
s_instance.initialize();
}
return s_instance;
}
public void processMessage(ServerMessageContext ctx) {
ServerMessageContextImpl ctx2 = (ServerMessageContextImpl)ctx;
processMessageInternal(ctx2, false);
}
@Override
public void dispatchInternal(BaseMessageContextImpl ctx, boolean useAsync) throws Throwable {
Dispatcher requestDispatcher = ctx.getServiceDesc().getRequestDispatcher();
requestDispatcher.dispatchSynchronously(ctx);
}
@Override
protected void beforeRequestPipeline(BaseMessageContextImpl ctx) throws ServiceException {
super.beforeRequestPipeline(ctx);
ServerMessageContextImpl serverCtx = (ServerMessageContextImpl)ctx;
ServerServiceDesc serviceDesc = serverCtx.getServiceDesc();
VersionCheckHandler versionCheckHandler = serviceDesc.getVersionCheckHandler();
versionCheckHandler.checkRequestVersion(ctx);
}
@Override
protected void processPreResponseDispatchErrors(BaseMessageContextImpl ctx)
throws ServiceException
{
@SuppressWarnings("unchecked")
List<Throwable> errors = ctx.getErrorList();
if (errors == null || errors.isEmpty()) {
return;
}
OutboundMessage response = (OutboundMessage)ctx.getResponseMessage();
response.setTransportHeader(SOAHeaders.ERROR_RESPONSE, "true");
ServerMessageContextImpl serverCtx = (ServerMessageContextImpl)ctx;
Object errorMsg;
ServerServiceDesc serviceDesc = serverCtx.getServiceDesc();
ErrorMapper errorMapper = serviceDesc.getErrorMapper();
try {
errorMsg = errorMapper.mapErrors(errors, serverCtx);
if (errorMsg == null) {
throw new ServiceException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_ERROR_MAPPER_RETURNED_NULL,
ErrorConstants.ERRORDOMAIN,
new Object[] {errorMapper.getClass().getName()}));
}
if (errorMsg instanceof HttpError) {
response.setUnserializable(errorMsg.toString());
}
response.setErrorResponse(errorMsg);
} catch (Throwable e) {
Throwable t = new ServiceException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_ERROR_MAPPER_FAILURE,
ErrorConstants.ERRORDOMAIN,
new Object[] {errorMapper.getClass().getName(), e.toString()}), e);
// add error, so it gets logged
ctx.addError(t);
Class errorMessageClass = serverCtx.getOperation().getErrorType().
getRootJavaTypes().get(0);
if (ErrorMessage.class.equals(errorMessageClass)) {
errorMsg = buildDefaultErrorMessage(ctx, e);
response.setErrorResponse(errorMsg);
} else {
response.setUnserializable(t.toString());
}
}
}
private Object buildDefaultErrorMessage(BaseMessageContextImpl ctx, Throwable e) {
CommonErrorData errData = ErrorDataFactory.createErrorData(
ErrorConstants.SVC_RT_UNABLE_TO_MAP_ERRORS, ErrorConstants.ERRORDOMAIN);
errData.setMessage(e.toString());
ErrorMessage result = new ErrorMessage();
List<CommonErrorData> errors = result.getError();
errors.add(errData);
return result;
}
private void initialize() throws ServiceException {
BaseMessageProcessorImpl.initializeCommonSubsystems();
GlobalConfigHolder globalConfig = ServiceConfigManager.getInstance().getGlobalConfig();
initializeMonitoringSystem(globalConfig);
SOAServerMarkdownStateManager.getInstance();
ServerServiceDescFactory.getInstance().initializeCompStatus();
ServerServiceDescFactory serviceDescFactory = ServerServiceDescFactory.getInstance();
if (!serviceDescFactory.loadAllServices()) {
Throwable t = serviceDescFactory.getFirstInitException();
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_INCOMPLETE_INIT,
ErrorConstants.ERRORDOMAIN, new Object[] {
t==null? "See log for details" : t.toString()}), t);
}
}
private void initializeMonitoringSystem(GlobalConfigHolder globalConfig)
throws ServiceException {
MonitoringSystem.initializeServer(globalConfig);
ServerServiceMonitoringCompStatus.initializeCompStatus();
}
}