/*******************************************************************************
* 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.sif.impl.internal.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.ebayopensource.turmeric.runtime.common.errors.ErrorDataProvider;
import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory;
import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceException;
import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceRuntimeException;
import org.ebayopensource.turmeric.runtime.common.impl.internal.monitoring.MetricsRegistrationHelper;
import org.ebayopensource.turmeric.runtime.common.pipeline.MessageContext;
import org.ebayopensource.turmeric.runtime.common.types.G11nOptions;
import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants;
import org.ebayopensource.turmeric.common.v1.types.CommonErrorData;
import org.ebayopensource.turmeric.common.v1.types.ErrorData;
import com.ebay.kernel.logger.LogLevel;
import com.ebay.kernel.logger.Logger;
public class ErrorHelper {
private static Logger LOGGER = Logger.getInstance(ErrorHelper.class);
private static final Locale DEFAULT_LOCALE = Locale.US;
/**
* Retrieve a SOA error as a CommonErrorData. CommonErrorData is the preferred ErrorData format.
* The locale of the CommonErrorData is implied within MessageContext.
*
* @param key specifies the bundle and errorname to retrieve
* @param args placeholder arguments to pass onto the localizable message and resolution
* @param ctx MessageContext
* @return a CommonErrorData that corresponds to the bundle and errorname specified.
* @throws NullPointerException if a validation error occurred -- if key is null, key.getBundle() is null, or key.getErrorName is null
* @throws ServiceRuntimeException if no error could be found or no error data provider was configured
* @throws ServiceException if was a problem finding the locale
*/
public static CommonErrorData getCommonErrorData( ErrorDataProvider.ErrorDataKey key, Object[] args, MessageContext ctx ) throws ServiceException {
Locale locale = getLocale( ctx.getResponseMessage().getG11nOptions() );
ErrorDataProvider errorDataProvider = ctx.getErrorDataProvider();
CommonErrorData errorData = getCommonErrorData( errorDataProvider, key, args, locale );
processErrorGroups( errorData, ctx );
return errorData;
}
/**
* Retrieve a SOA error as a CommonErrorData. CommonErrorData is the preferred ErrorData format.
* This API differs from
* {@link #getCommonErrorData(org.ebayopensource.turmeric.runtime.common.errors.ErrorDataProvider.ErrorDataKey, Object[], MessageContext)}
* in that it allows specification of a locale other than the one associated with the MessageContext.
*
* @param key specifies the bundle and errorname to retrieve
* @param args placeholder arguments to pass onto the localizable message and resolution
* @param ctx MessageContext
* @param locale desired Locale
* @return a CommonErrorData that corresponds to the bundle and errorname specified.
* @throws NullPointerException if a validation error occurred -- if key is null, key.getBundle() is null, or key.getErrorName is null
* @throws ServiceRuntimeException if no error could be found or no error data provider was configured
*/
public static CommonErrorData getCommonErrorData( ErrorDataProvider.ErrorDataKey key, Object[] args, Locale locale, MessageContext ctx ){
try {
ErrorDataProvider errorDataProvider = ctx.getErrorDataProvider();
CommonErrorData errorData = getCommonErrorData( errorDataProvider, key, args, locale );
processErrorGroups( errorData, ctx );
return errorData;
} catch ( ServiceException e ) {
throw ServiceRuntimeException.wrap( e );
}
}
private static CommonErrorData getCommonErrorData( ErrorDataProvider errorDataProvider, ErrorDataProvider.ErrorDataKey key, Object[] args, Locale locale ) {
if ( errorDataProvider == null )
throw new ServiceRuntimeException( ErrorDataFactory.createErrorData(ErrorConstants.CFG_NO_ERROR_DATA_PROVIDER,
ErrorConstants.ERRORDOMAIN));
return errorDataProvider.getCommonErrorData( key, args, locale );
}
/**
* Retrieve a SOA error as an ErrorData. This API was written for backwards compatibility for those legacy clients
* who only understand the original ErrorData format. The locale of the ErrorData is implied within the MessageContext.
*
* @param key specifies the bundle and errorname to retrieve
* @param args placeholder arguments to pass onto the localizable message and resolution
* @param ctx MessageContext
* @return an ErrorData that corresponds to the bundle and errorname specified.
* @throws NullPointerException if a validation error occurred -- if key is null, key.getBundle() is null, or key.getErrorName is null
* @throws ServiceRuntimeException if no error could be found or no error data provider was configured
* @throws ServiceException if was a problem finding the locale
*/
public static CommonErrorData getErrorData( ErrorDataProvider.ErrorDataKey key, Object[] args, MessageContext ctx ) throws ServiceException {
Locale locale = getLocale( ctx.getResponseMessage().getG11nOptions() );
ErrorDataProvider errorDataProvider = ctx.getErrorDataProvider();
return getErrorData( errorDataProvider, key, args, locale );
}
/**
* Retrieve a SOA error as an ErrorData. This API was written for backwards compatibility for those legacy clients
* who only understand the original ErrorData format. This API differs from
* {@link #getErrorData(org.ebayopensource.turmeric.runtime.common.errors.ErrorDataProvider.ErrorDataKey, Object[], MessageContext)}
* by allowing specification of a locale other than the one associated with the MessageContext.
*
* @param key specifies the bundle and errorname to retrieve
* @param args placeholder arguments to pass onto the localizable message and resolution
* @param ctx MessageContext
* @param locale desired Locale
* @return an ErrorData that corresponds to the bundle and errorname specified.
* @throws NullPointerException if a validation error occurred -- if key is null, key.getBundle() is null, or key.getErrorName is null
* @throws ServiceRuntimeException if no error could be found or no error data provider was configured
*/
public static CommonErrorData getErrorData( ErrorDataProvider.ErrorDataKey key, Object[] args, Locale locale, MessageContext ctx ) {
try {
ErrorDataProvider errorDataProvider = ctx.getErrorDataProvider();
return getErrorData( errorDataProvider, key, args, locale );
} catch ( ServiceException e ) {
throw ServiceRuntimeException.wrap( e );
}
}
private static CommonErrorData getErrorData( ErrorDataProvider errorDataProvider, ErrorDataProvider.ErrorDataKey key, Object[] args, Locale locale ) {
if ( errorDataProvider == null )
throw new ServiceRuntimeException( ErrorDataFactory.createErrorData(ErrorConstants.CFG_NO_ERROR_DATA_PROVIDER,
ErrorConstants.ERRORDOMAIN));
return errorDataProvider.getCommonErrorData( key, args, locale );
}
/**
* Retrieve a SOA error as "Custom" ErrorData. "Custom" ErrorData are subclasses of CommonErrorData. Use of a "Custom" ErrorData may
* be necessary if an application requires error state beyond what is provided by CommonErrorData.
* The locale of the "Custom" ErrorData is implied within MessageContext.
*
* @param key specifies the bundle and errorname to retrieve
* @param args placeholder arguments to pass onto the localizable message and resolution
* @param clazz Class reference to the "Custom" ErrorData
* @param ctx MessageContext
* @return a "Custom" ErrorData that corresponds to the bundle and errorname specified.
* @throws NullPointerException if a validation error occurred -- if key is null, key.getBundle() is null, or key.getErrorName is null
* @throws ServiceRuntimeException if no error could be found or no error data provider was configured
* @throws ServiceException if was a problem finding the locale
*/
public static <T extends CommonErrorData> T getCustomErrorData( ErrorDataProvider.ErrorDataKey key, Object[] args, Class<T> clazz, MessageContext ctx )
throws ServiceException {
Locale locale = getLocale( ctx.getResponseMessage().getG11nOptions() );
ErrorDataProvider errorDataProvider = ctx.getErrorDataProvider();
T errorData = getCustomErrorData( errorDataProvider, key, args, clazz, locale );
processErrorGroups( errorData, ctx );
return errorData;
}
/**
* Retrieve a SOA error as "Custom" ErrorData. "Custom" ErrorData are subclasses of CommonErrorData. Use of a "Custom" ErrorData may
* be necessary if an application requires error state beyond what is provided by CommonErrorData.
* This API differs from
* {@link #getCustomErrorData(org.ebayopensource.turmeric.runtime.common.errors.ErrorDataProvider.ErrorDataKey, Object[], Class, MessageContext)}
* by allowing specification of a locale other than the one associated with the MessageContext.
*
* @param key specifies the bundle and errorname to retrieve
* @param args placeholder arguments to pass onto the localizable message and resolution
* @param clazz Class reference to the "Custom" ErrorData
* @param ctx MessageContext
* @param locale desired Locale
* @return a "Custom" ErrorData that corresponds to the bundle and errorname specified.
* @throws NullPointerException if a validation error occurred -- if key is null, key.getBundle() is null, or key.getErrorName is null
* @throws ServiceRuntimeException if no error could be found or no error data provider was configured
*/
public static <T extends CommonErrorData> T getCustomErrorData( ErrorDataProvider.ErrorDataKey key, Object[] args, Class<T> clazz, Locale locale, MessageContext ctx ) {
try {
ErrorDataProvider errorDataProvider = ctx.getErrorDataProvider();
T errorData = getCustomErrorData( errorDataProvider, key, args, clazz, locale );
processErrorGroups( errorData, ctx );
return errorData;
} catch ( ServiceException e ) {
throw ServiceRuntimeException.wrap( e );
}
}
private static <T extends CommonErrorData> T getCustomErrorData( ErrorDataProvider errorDataProvider, ErrorDataProvider.ErrorDataKey key, Object[] args, Class<T> clazz, Locale locale ) {
if ( errorDataProvider == null )
throw new ServiceRuntimeException( ErrorDataFactory.createErrorData(ErrorConstants.CFG_NO_ERROR_DATA_PROVIDER,
ErrorConstants.ERRORDOMAIN));
return errorDataProvider.getCustomErrorData( key, args, clazz, locale );
}
private static Locale getLocale( G11nOptions g11nOptions ) {
if (g11nOptions == null) {
return DEFAULT_LOCALE;
}
List<String> locales = g11nOptions.getLocales();
if (locales == null || locales.isEmpty()) {
return DEFAULT_LOCALE;
}
// 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).
//
Locale locale;
String localeString = locales.get(0);
int offset = localeString.indexOf( '-' );
if ( offset > 0 ) {
String language = localeString.substring( 0, offset );
String country = localeString.substring( offset+1 );
locale = new Locale( language, country );
} else {
/**
* This condition would be unexpected. Just take the locale string as-is then.
*/
locale = new Locale( localeString );
}
return locale;
}
public static void processErrorGroups( CommonErrorData errorData, MessageContext ctx ) {
if ( errorData.getErrorGroups() != null && errorData.getErrorGroups().trim().length() > 0 ) {
MetricsRegistrationHelper.registerMetricsForErrorDataGrps
( errorData, errorData.getOrganization(), errorData.getErrorGroups(), ctx );
}
/**
* Error groups will not be sent out on the wire
*/
errorData.setErrorGroups( null );
}
public static void main( String[] args ) {
List<String> localeStrings = new ArrayList<String>();
localeStrings.add( "fr-CA" );
localeStrings.add( "fr-FR" );
localeStrings.add( "en-US" );
localeStrings.add( "es-US" );
localeStrings.add( "zh-Hans" );
G11nOptions g11nOptions = new G11nOptions( G11nOptions.DEFAULT_CHARSET, localeStrings );
Locale locale = getLocale( g11nOptions );
if ( Locale.CANADA_FRENCH.equals( locale ) )
if ( LOGGER.isLogEnabled( LogLevel.INFO ) && LOGGER.isInfoEnabled() )
LOGGER.log( LogLevel.INFO, locale.toString() );
// CommonErrorData errorData = new CommonErrorData();
// errorData.getErrorGroup().add( "foo" );
// new ErrorDataGroupEliminator().eliminateErrorGroup( errorData );
// System.out.println( errorData.getErrorGroup() );
}
}