/*******************************************************************************
* 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.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.ServiceException;
import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceExceptionInterface;
import org.ebayopensource.turmeric.runtime.common.g11n.LocaleId;
import org.ebayopensource.turmeric.runtime.common.pipeline.OutboundMessage;
import org.ebayopensource.turmeric.runtime.common.types.G11nOptions;
import org.ebayopensource.turmeric.runtime.common.types.SOAConstants;
import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants;
import org.ebayopensource.turmeric.runtime.spf.exceptions.AppErrorWrapperException;
import org.ebayopensource.turmeric.runtime.spf.exceptions.ServiceHttpException;
import org.ebayopensource.turmeric.runtime.spf.impl.internal.pipeline.ServerMessageContextImpl;
import org.ebayopensource.turmeric.runtime.spf.pipeline.ErrorMapper;
import org.ebayopensource.turmeric.runtime.spf.pipeline.HttpError;
import org.ebayopensource.turmeric.runtime.spf.pipeline.HttpErrorMapper;
import org.ebayopensource.turmeric.runtime.spf.pipeline.ServerMessageContext;
/**
* @author rmurphy
*/
public class DefaultErrorMapperImpl implements ErrorMapper {
private static final String DEFAULT_LOCALE_LANGUAGE = "en-US";
private static final String IS_INTERNAL_CLIENT = "IS_INTERNAL_CLIENT";
public void init(InitContext ctx) throws ServiceException {
// noop
}
public Object mapErrors(List<Throwable> errors, ServerMessageContext ctx) throws ServiceException
{
// Call error handler only for error flow (i.e. errors present in fatal list).
// In such a flow, there may be output params, but these would be from previous work by the request dispatcher.
// Since output flow is no longer occurring, these output params must be discarded.
// The error handler will write new output params reflecting the error message content.
ErrorMessage result = new ErrorMessage();
String localeLang = getLocaleLanguage(ctx);
for (Throwable error : errors) {
boolean isAppWrapper = false;
if (error instanceof AppErrorWrapperException) {
error = ((AppErrorWrapperException)error).getCause();
isAppWrapper = true;
}
if ((error instanceof ServiceHttpException || !(error instanceof ServiceExceptionInterface))
&& !(SOAConstants.MSG_PROTOCOL_SOAP_11
.equals(((ServerMessageContextImpl) ctx)
.getMessageProtocol()) || SOAConstants.MSG_PROTOCOL_SOAP_12
.equals(((ServerMessageContextImpl) ctx)
.getMessageProtocol()))) {
HttpErrorMapper httpErrorMapper = ((ServerMessageContextImpl) ctx)
.getServiceDesc().getHttpErrorMapper();
HttpError httpError = null;
if (httpErrorMapper != null
&& (httpError = httpErrorMapper.getHttpError(error)) != null) {
return httpError;
}
}
ServiceExceptionInterface exception;
if (error instanceof ServiceExceptionInterface) {
exception = (ServiceExceptionInterface)error;
} else {
if (isAppWrapper) {
exception = new ServiceException(ErrorDataFactory.createErrorData(
ErrorConstants.SVC_RT_APPLICATION_INTERNAL_ERROR,
ErrorConstants.ERRORDOMAIN, new Object[] {error.toString()}), error);
} else {
exception = new ServiceException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_INTERNAL_ERROR,
ErrorConstants.ERRORDOMAIN, new Object[] {error.toString()}), error);
}
}
exception.localizeMessage(localeLang);
ErrorMessage errorMessage2 = exception.getErrorMessage();
if (errorMessage2 != null) {
List<CommonErrorData> errorDataList = errorMessage2.getError();
for (int i=0; i<errorDataList.size(); i++) {
CommonErrorData errorData = errorDataList.get(i);
boolean islocalTransport = ctx.getResponseMessage().getTransportProtocol()
.equals(SOAConstants.TRANSPORT_LOCAL);
Boolean isInternalClient = (Boolean)ctx.getProperty(IS_INTERNAL_CLIENT);
boolean isInternalClientOrLocalTransport = (isInternalClient != null?
isInternalClient.booleanValue() || islocalTransport : islocalTransport);
if (isInternalClientOrLocalTransport) {
errorData.setExceptionId(error.getClass().getName());
}
result.getError().add(errorData);
}
}
}
return result;
}
private String getLocaleLanguage(ServerMessageContext ctx) throws ServiceException {
OutboundMessage responseMessage = (OutboundMessage)ctx.getResponseMessage();
G11nOptions g11nOptions = responseMessage.getG11nOptions();
if (g11nOptions == null) {
return DEFAULT_LOCALE_LANGUAGE;
}
List<String> locales = g11nOptions.getLocales();
if (locales == null || locales.isEmpty()) {
return DEFAULT_LOCALE_LANGUAGE;
}
// Normally server logic reduces the locale list to the first one in the client's list that is supported
// by the handling service. In early stages of the logic, we have all the client's requested locales,
// and we just try to use the first one specified. If this does not have a resource bundle, we'll fall
// back to the raw unlocalized form of the message (basically English with underscores).
//
String locale = locales.get(0);
LocaleId localeId = LocaleId.valueOf(locale);
return localeId.getLanguage();
}
}