/*******************************************************************************
* 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.common.impl.internal.service;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import javax.wsdl.Definition;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.ebayopensource.turmeric.common.v1.types.ErrorMessage;
import org.ebayopensource.turmeric.runtime.binding.BindingConstants;
import org.ebayopensource.turmeric.runtime.binding.impl.parser.json.JSONStreamWriter;
import org.ebayopensource.turmeric.runtime.binding.schema.DataElementSchema;
import org.ebayopensource.turmeric.runtime.binding.utils.BindingUtils;
import org.ebayopensource.turmeric.runtime.common.binding.DataBindingDesc;
import org.ebayopensource.turmeric.runtime.common.binding.Deserializer;
import org.ebayopensource.turmeric.runtime.common.binding.DeserializerFactory;
import org.ebayopensource.turmeric.runtime.common.binding.Serializer;
import org.ebayopensource.turmeric.runtime.common.binding.SerializerFactory;
import org.ebayopensource.turmeric.runtime.common.binding.TypeConverter;
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.exceptions.ServiceNotFoundException;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.fastinfoset.JAXBFastInfosetDeserializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.fastinfoset.JAXBFastInfosetSerializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.json.JAXBJSONDeserializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.json.JAXBJSONSerializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.nv.JAXBNVDeserializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.nv.JAXBNVSerializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.validation.SchemaBaseDetails;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.validation.SchemaExtractor;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.xml.JAXBXMLDeserializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.jaxb.xml.JAXBXMLSerializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.protobuf.ProtobufDeserializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.binding.protobuf.ProtobufSerializerFactory;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.CommonConfigHolder;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.CustomSerializerConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.FrameworkHandlerConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.HandlerConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.MessageHeaderConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.MessageProcessorConfigHolder;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.MessageTypeConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.NameValue;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.OperationConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.OperationPropertyConfigHolder;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.OptionList;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.ProtocolProcessorConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.SerializerConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.TypeConverterConfig;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.TypeMappingConfigHolder;
import org.ebayopensource.turmeric.runtime.common.impl.internal.monitoring.MetricsConfigManager;
import org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline.LoggingHandlerInitContextImpl;
import org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline.PipelineInitContextImpl;
import org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline.ProtocolProcessorInitContextImpl;
import org.ebayopensource.turmeric.runtime.common.impl.internal.schema.BaseTypeDefsBuilder;
import org.ebayopensource.turmeric.runtime.common.impl.internal.schema.DataElementSchemaLoader;
import org.ebayopensource.turmeric.runtime.common.impl.internal.utils.ServiceNameUtils;
import org.ebayopensource.turmeric.runtime.common.impl.pipeline.PipelineImpl;
import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager;
import org.ebayopensource.turmeric.runtime.common.impl.utils.ReflectionUtils;
import org.ebayopensource.turmeric.runtime.common.pipeline.HandlerOptions;
import org.ebayopensource.turmeric.runtime.common.pipeline.LoggingHandler;
import org.ebayopensource.turmeric.runtime.common.pipeline.Pipeline;
import org.ebayopensource.turmeric.runtime.common.pipeline.PipelineMode;
import org.ebayopensource.turmeric.runtime.common.pipeline.ProtocolProcessor;
import org.ebayopensource.turmeric.runtime.common.service.HeaderMappingsDesc;
import org.ebayopensource.turmeric.runtime.common.service.ServiceContext;
import org.ebayopensource.turmeric.runtime.common.service.ServiceId;
import org.ebayopensource.turmeric.runtime.common.service.ServiceOperationDesc;
import org.ebayopensource.turmeric.runtime.common.service.ServiceOperationParamDesc;
import org.ebayopensource.turmeric.runtime.common.service.ServiceTypeMappings;
import org.ebayopensource.turmeric.runtime.common.types.SOAConstants;
import org.ebayopensource.turmeric.runtime.common.types.SOAHeaders;
import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants;
import com.ebay.kernel.component.Registration;
/**
* Base class implementing common functions for both client and server ServiceDesc factories
*
* @author ichernyshev
*/
public abstract class BaseServiceDescFactory<T extends ServiceDesc> {
private final String m_factoryName;
private final boolean m_isClientSide;
private final Map<ServiceId,T> m_descs = new HashMap<ServiceId,T>();
private final Map<String,QName> m_adminToQName = new HashMap<String,QName>();
private final Map<QName,String> m_qNameToAdmin = new HashMap<QName,String>();
private final Map<ServiceId,Throwable> m_failedNames = new HashMap<ServiceId,Throwable>();
private final boolean m_requiresLoadAll;
private boolean m_hasInitStarted;
private boolean m_wasInitSuccessful;
private List<Throwable> m_initExceptions = new ArrayList<Throwable>();
protected final Map<String,Boolean> m_rawModes = new ConcurrentHashMap<String,Boolean>();
private static BaseServiceDescFactory s_clientInstance;
private static BaseServiceDescFactory s_serverInstance;
protected BaseServiceDescFactory(String factoryName, boolean isClientSide, boolean requiresLoadAll) {
m_factoryName = factoryName;
m_isClientSide = isClientSide;
m_requiresLoadAll = requiresLoadAll;
}
public static BaseServiceDescFactory getClientInstance() {
if (s_clientInstance == null) {
throw new IllegalStateException("Client instance for BaseServiceDescFactory is not set");
}
return s_clientInstance;
}
public static BaseServiceDescFactory getServerInstance() {
if (s_serverInstance == null) {
throw new IllegalStateException("Server instance for BaseServiceDescFactory is not set");
}
return s_serverInstance;
}
protected static synchronized void setClientInstance(BaseServiceDescFactory value) {
if (value == null) {
throw new NullPointerException();
}
if (s_clientInstance != null) {
throw new IllegalStateException("Client instance for BaseServiceDescFactory is already set");
}
s_clientInstance = value;
}
protected static synchronized void setServerInstance(BaseServiceDescFactory value) {
if (value == null) {
throw new NullPointerException();
}
if (s_serverInstance != null) {
throw new IllegalStateException("Server instance for BaseServiceDescFactory is already set");
}
s_serverInstance = value;
}
public boolean isInRawMode(String adminName) {
return m_rawModes.containsKey(adminName);
}
public abstract ServiceContext getServiceContext(T desc) throws ServiceException;
/**
* Returns a ServiceDesc, attempting to load if necessary
*/
protected final T getServiceDesc(ServiceId id) throws ServiceException {
return getServiceDesc(id, true, true, false);
}
protected final T getServiceDesc(ServiceId id, boolean rawMode) throws ServiceException {
return getServiceDesc(id, true, true, rawMode);
}
protected final T getServiceDesc(ServiceId id, boolean rawMode, int useDefaultClientConfig) throws ServiceException {
boolean isZeroCC = useDefaultClientConfig == 1? true: false;
return getServiceDesc(id, true, true, rawMode, isZeroCC);
}
protected final T getServiceDesc(T serviceDesc, ServiceId id,
QName srvName, Definition wsdlDefinition, boolean rawMode)
throws ServiceException {
return getServiceDesc(serviceDesc, id, true, srvName, wsdlDefinition,
rawMode);
}
public final String findKnownAdminNameByQName(QName serviceQName) {
String result;
synchronized (m_descs) {
result = m_qNameToAdmin.get(serviceQName);
}
return result;
}
public final QName findKnownQNameByAdminName(String adminName) {
QName result;
synchronized (m_descs) {
result = m_adminToQName.get(adminName);
}
return result;
}
public final Collection<T> getKnownServiceDescsByAdminName(String adminName) {
Collection<T> result;
synchronized (m_descs) {
result = new ArrayList<T>(m_descs.size());
for (T svcDesc: m_descs.values()) {
if (svcDesc.getAdminName().equals(adminName)) {
result.add(svcDesc);
}
}
}
return result;
}
public final Collection<T> getKnownServiceDescs() {
synchronized (m_descs) {
return Collections.unmodifiableCollection(new ArrayList<T>(m_descs.values()));
}
}
final Map<ServiceId,Throwable> getFailedIds() {
synchronized (m_descs) {
return Collections.unmodifiableMap(new HashMap<ServiceId,Throwable>(m_failedNames));
}
}
private final T getServiceDesc(ServiceId id, boolean loadAllFirst, boolean logErrors)
throws ServiceException
{
return getServiceDesc(id, loadAllFirst, logErrors, isInRawMode(id.getAdminName()));
}
protected final void clearFromFailedCache(ServiceId id) {
synchronized (m_descs) {
m_failedNames.remove(id);
}
}
private T getServiceDesc(T serviceDesc, ServiceId id, boolean logErrors,
QName srvName, Definition wsdlDefinition, boolean rawMode)
throws ServiceException {
T result;
QName oldQName;
synchronized (m_descs) {
Throwable th = m_failedNames.get(id);
if (th != null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_SERVICE_INIT_FAILED,
ErrorConstants.ERRORDOMAIN, new Object[] {id.toString(), m_factoryName, th.toString()}), th);
}
result = m_descs.get(id);
oldQName = m_adminToQName.get(id.getAdminName());
}
if (result != null) {
return result;
}
try {
validateServiceName(id.getAdminName());
result = createServiceDesc(serviceDesc, id, srvName,
wsdlDefinition, rawMode);
if (oldQName != null && !oldQName.equals(result.getServiceQName())) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INCONSISTENT_QNAME,
ErrorConstants.ERRORDOMAIN, new Object[] {id.toString(), result.getServiceQName(), oldQName }));
}
} catch (ExceptionInInitializerError e) {
Throwable t = e.getException();
handleServiceLoadError(id, t, logErrors);
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_CANNOT_CREATE_SVC,
ErrorConstants.ERRORDOMAIN, new Object[] {m_factoryName, id.toString(), t.toString()}), t);
} catch (Throwable t) {
handleServiceLoadError(id, t, logErrors);
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_CANNOT_CREATE_SVC,
ErrorConstants.ERRORDOMAIN, new Object[] {m_factoryName, id.toString(), t.toString()}), t);
}
boolean hasAdded = false;
synchronized (m_descs) {
T result2 = m_descs.get(id);
if (result2 != null) {
// someone else has created a ServiceDesc, use older one
result = result2;
} else {
m_descs.put(id, result);
if (oldQName == null) {
m_adminToQName.put(id.getAdminName(), result
.getServiceQName());
m_qNameToAdmin.put(result.getServiceQName(), id
.getAdminName());
}
hasAdded = true;
}
m_failedNames.remove(id);
}
if (hasAdded) {
updateMetrics(result);
postServiceDescLoad(result);
}
return result;
}
private final T getServiceDesc(ServiceId id, boolean loadAllFirst, boolean logErrors, boolean rawMode)
throws ServiceException
{
return getServiceDesc(id, loadAllFirst, logErrors, rawMode, false);
}
private final T getServiceDesc(ServiceId id, boolean loadAllFirst, boolean logErrors, boolean rawMode, boolean useDefaultConfig)
throws ServiceException
{
if (rawMode && !isInRawMode(id.getAdminName())) m_rawModes.put(id.getAdminName(), Boolean.TRUE);
boolean wasInitSuccessful;
if (loadAllFirst) {
wasInitSuccessful = loadAllServices();
} else {
wasInitSuccessful = true;
}
T result;
QName oldQName;
synchronized (m_descs) {
Throwable th = m_failedNames.get(id);
if (th != null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_SERVICE_INIT_FAILED,
ErrorConstants.ERRORDOMAIN, new Object[] {id.toString(), m_factoryName, th.toString()}), th);
}
result = m_descs.get(id);
oldQName = m_adminToQName.get(id.getAdminName());
}
if (result != null) {
return result;
}
if (!wasInitSuccessful) {
// we tried to load all services, but failed,
// do not try to load any more
List<Throwable> exceptions = m_initExceptions;
Throwable origException = null;
String exceptionText = "(See log for details)";
if (exceptions != null && !exceptions.isEmpty()) {
origException = exceptions.get(0);
exceptionText = origException.getMessage();
}
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INIT_FAILED,
ErrorConstants.ERRORDOMAIN, new Object[] {id.toString(), m_factoryName, exceptionText}), origException);
}
try {
validateServiceName(id.getAdminName());
id.setUseDefaultConfig(useDefaultConfig);
result = createServiceDesc(id, rawMode);
if (oldQName != null && !oldQName.equals(result.getServiceQName())) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INCONSISTENT_QNAME,
ErrorConstants.ERRORDOMAIN, new Object[] {id.toString(), result.getServiceQName(), oldQName}));
}
} catch (ExceptionInInitializerError e) {
Throwable t = e.getException();
handleServiceLoadError(id, t, logErrors);
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_CANNOT_CREATE_SVC,
ErrorConstants.ERRORDOMAIN, new Object[] {m_factoryName, id.toString(), t.toString()}), t);
} catch (Throwable t) {
handleServiceLoadError(id, t, logErrors);
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_CANNOT_CREATE_SVC,
ErrorConstants.ERRORDOMAIN, new Object[] {m_factoryName, id.toString(), t.toString()}), t);
}
boolean hasAdded = false;
synchronized (m_descs) {
T result2 = m_descs.get(id);
if (result2 != null) {
// someone else has created a ServiceDesc, use older one
result = result2;
} else {
m_descs.put(id, result);
if (oldQName == null) {
m_adminToQName.put(id.getAdminName(), result.getServiceQName());
m_qNameToAdmin.put(result.getServiceQName(), id.getAdminName());
}
hasAdded = true;
}
m_failedNames.remove(id);
}
if (hasAdded) {
updateMetrics(result);
postServiceDescLoad(result);
}
return result;
}
private void handleServiceLoadError(ServiceId id, Throwable e, boolean logErrors) {
synchronized (m_descs) {
m_initExceptions.add(e);
m_failedNames.put(id, e);
}
if (logErrors) {
Level logLevel;
if (e instanceof ServiceNotFoundException) {
logLevel = Level.INFO;
} else {
logLevel = Level.SEVERE;
}
LogManager.getInstance(BaseServiceDescFactory.class).log(logLevel,
"Service " + id + " could not be loaded due to exception: " + e.toString(), e);
}
}
protected abstract void postServiceDescLoad(T svcDesc);
/**
* Reloads ServiceDesc to reflect configuration change
*/
protected final void reloadServiceDesc(ServiceId id) throws ServiceException
{
validateServiceName(id.getAdminName());
T serviceDesc = createServiceDesc(id);
synchronized (m_descs) {
m_failedNames.remove(id);
m_descs.put(id, serviceDesc);
}
postServiceDescLoad(serviceDesc);
}
public final synchronized void resetFactoryForUnitTest() throws ServiceException {
m_hasInitStarted = false;
m_wasInitSuccessful = false;
synchronized (m_descs) {
m_failedNames.clear();
m_descs.clear();
m_initExceptions.clear();
m_adminToQName.clear();
m_qNameToAdmin.clear();
}
}
protected abstract Collection<ServiceId> loadAllServiceNames() throws ServiceException;
public final synchronized boolean loadAllServices() throws ServiceException {
if (m_hasInitStarted) {
return m_wasInitSuccessful;
}
m_hasInitStarted = true;
boolean allSuccess = true;
try {
Collection<ServiceId> serviceNames = loadAllServiceNames();
for (ServiceId id: serviceNames) {
try {
validateServiceName(id.getAdminName());
getServiceDesc(id, false, false);
} catch (ServiceException e) {
if (m_requiresLoadAll) {
throw e;
}
allSuccess = false;
LogManager.getInstance(this.getClass()).log(Level.SEVERE,
"Skipping service " + id + " due to error: " + e.toString(), e);
}
}
} catch (Throwable e) {
allSuccess = false;
LogManager.getInstance(this.getClass()).log(Level.SEVERE,
"Unable to initialize " + m_factoryName + ": " + e.toString(), e);
synchronized (m_descs) {
m_initExceptions.add(e);
}
}
m_wasInitSuccessful = allSuccess;
return m_wasInitSuccessful;
}
public Throwable getFirstInitException() {
if (!m_initExceptions.isEmpty()) {
return m_initExceptions.get(0);
}
return null;
}
protected abstract T createServiceDesc(ServiceId id) throws ServiceException;
protected abstract T createServiceDesc(ServiceId id, boolean rawMode) throws ServiceException;
protected abstract T createServiceDesc(ServiceDesc commonDesc,
ServiceId newServiceId, QName srvQName, Definition definition,
boolean rawMode) throws ServiceException;
protected void validateServiceName(String name) throws ServiceException {
if (name == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_SVC_NAME,
ErrorConstants.ERRORDOMAIN, new Object[] { "***null***" }));
}
}
private void validateOperationName(String name) throws ServiceException {
if (name == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_OPERATION_NAME,
ErrorConstants.ERRORDOMAIN, new Object[] { "***null***" }));
}
}
private void validateProtocolProcessorName(String name) throws ServiceException {
if (name == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_PROTOCOL_PROCESSOR_NAME,
ErrorConstants.ERRORDOMAIN, new Object[] { "***null***" }));
}
}
private void validateDataBindingNameAndType(String name, String mimeType) throws ServiceException {
if (name == null) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_DATA_BINDING_NAME,
ErrorConstants.ERRORDOMAIN, new Object[] { "***null***" }));
}
if (mimeType == null) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_DATA_BINDING_MIME_TYPE,
ErrorConstants.ERRORDOMAIN, new Object[] { "***null***" }));
}
}
protected final Pipeline createPipeline(ServiceId svcId, PipelineMode mode,
MessageProcessorConfigHolder processorConfig, ClassLoader cl)
throws ServiceException
{
String pipelineClassName;
List<HandlerConfig> handlerConfigs;
if (mode == PipelineMode.REQUEST) {
pipelineClassName = processorConfig.getRequestPipelineClassName();
handlerConfigs = processorConfig.getRequestHandlers();
} else {
pipelineClassName = processorConfig.getResponsePipelineClassName();
handlerConfigs = processorConfig.getResponseHandlers();
}
if (pipelineClassName == null) {
pipelineClassName = PipelineImpl.class.getName();
}
if (handlerConfigs == null) {
handlerConfigs = new ArrayList<HandlerConfig>();
}
List<HandlerOptions> handlerOptionsList = new ArrayList<HandlerOptions>(handlerConfigs.size());
for (HandlerConfig config: handlerConfigs) {
String handlerName = config.getName();
String handlerClassName = config.getClassName();
List<NameValue> options = null;
OptionList optionList = config.getOptions();
if (optionList != null) {
options = optionList.getOption();
}
Map<String,String> options2 = new HashMap<String,String>();
if (options != null && !options.isEmpty()) {
for (int j=0; j<options.size(); j++) {
NameValue nv = options.get(j);
options2.put(nv.getName(), nv.getValue());
}
}
Boolean continueOnError = config.isContinueOnError();
if (continueOnError == null) {
continueOnError = Boolean.FALSE;
}
Boolean runOnError = config.isRunOnError();
if (runOnError == null) {
runOnError = Boolean.FALSE;
}
HandlerOptions handlerOptions = new HandlerOptions(handlerName, handlerClassName,
options2, continueOnError.booleanValue(), runOnError.booleanValue());
handlerOptionsList.add(handlerOptions);
}
Pipeline result = ReflectionUtils.createInstance(pipelineClassName, Pipeline.class, cl);
PipelineInitContextImpl initCtx = new PipelineInitContextImpl(svcId, mode, cl, handlerOptionsList);
result.init(initCtx);
initCtx.kill();
return result;
}
protected final ServiceTypeMappings createFallbackTypeMappings()
throws ServiceException
{
Map<String,String> packageToNamespace = new HashMap<String,String>();
validateAndAddPkgNsMapping(BindingUtils.getPackageName(ErrorMessage.class),
BindingConstants.SOA_TYPES_NAMESPACE, packageToNamespace);
return new ServiceTypeMappingsImpl(packageToNamespace, null);
}
protected final ServiceTypeMappings createTypeMappings(ServiceId svcId,
TypeMappingConfigHolder mappings, Class intfClass, ClassLoader cl)
throws ServiceException
{
Map<String,String> packageToNamespace = new HashMap<String,String>();
Map<String,List<String>> pkgToNsCfg = (mappings != null ? mappings.getPackageToNsMap() : null);
if (pkgToNsCfg != null) {
for (Map.Entry<String,List<String>> e: pkgToNsCfg.entrySet()) {
String pkgName = e.getKey();
List<String> nsList = e.getValue();
if (pkgName == null) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_TYPEMAP_DEFINITION,
ErrorConstants.ERRORDOMAIN));
}
for (String ns: nsList) {
validateAndAddPkgNsMapping(pkgName, ns, packageToNamespace);
}
}
}
BaseTypeDefsBuilder typeDefsBuilder;
if (intfClass != null) {
String typeDefsBuilderClassName = ServiceNameUtils.getServiceTypeDefsBuilderClassName(
svcId.getAdminName(), intfClass.getName());
Class<BaseTypeDefsBuilder> typeDefsBuilderClass = ReflectionUtils.loadClass(
typeDefsBuilderClassName, BaseTypeDefsBuilder.class, true, cl);
if (typeDefsBuilderClass != null) {
typeDefsBuilder = ReflectionUtils.createInstance(typeDefsBuilderClass);
typeDefsBuilder.build();
} else {
typeDefsBuilder = null;
LogManager.getInstance(this.getClass()).log(Level.WARNING,
"Unable to find Type Defs Builder class '" + typeDefsBuilderClassName +
"' for '" + svcId.getAdminName() + "'. Will continue loading without " +
"XML Schema information");
}
} else {
// TODO: get TypeDefs builder class name from somewhere else
typeDefsBuilder = null;
}
return new ServiceTypeMappingsImpl(packageToNamespace, typeDefsBuilder, mappings.getEnableNamespaceFolding());
}
private void validateAndAddPkgNsMapping(String pkgName, String ns,
Map<String,String> packageToNamespace) throws ServiceException
{
if (ns == null) {
// use empty string when there is no namespace
ns = "";
}
boolean alreadyHasPkgName = false;
for (Map.Entry<String,String> e: packageToNamespace.entrySet()) {
String otherPkg = e.getKey();
String otherNs = e.getValue();
if (arePackagesOverlapping(pkgName, otherPkg) && !otherNs.equals(ns)) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_PACKAGE_NS_REDEFINITION,
ErrorConstants.ERRORDOMAIN, new Object[] {pkgName, otherPkg}));
}
if (pkgName.equals(otherPkg)) {
alreadyHasPkgName = true;
}
}
if (!alreadyHasPkgName) {
packageToNamespace.put(pkgName, ns);
}
}
private boolean arePackagesOverlapping(String pkg1, String pkg2) {
if (pkg1.length() == 0 || pkg2.length() == 0 || pkg1.equals(pkg2)) {
return true;
}
/* commnenting for TrackingAPI WSDL issue
if (pkg1.startsWith(pkg2 + ".") || pkg2.startsWith(pkg1 + ".")) {
return true;
}
*/
return false;
}
private void validateAndAddXmlNameMapping(List<DataElementSchema> rootElements,
List<Class> javaTypeList, Map<QName,Class> xmlToJavaMappings) throws ServiceException
{
if (rootElements == null) {
return;
}
for (int i=0; i<rootElements.size(); i++) {
DataElementSchema elementSchema = rootElements.get(i);
Class javaType = javaTypeList.get(i);
QName xmlName = elementSchema.getElementName();
validateAndAddXmlNameMapping(xmlName, javaType, xmlToJavaMappings);
}
}
private void validateAndAddXmlNameMapping(QName xmlName, Class javaType,
Map<QName,Class> xmlToJavaMappings)
throws ServiceException
{
if (xmlToJavaMappings.containsKey(xmlName)) {
Class oldJavaType = xmlToJavaMappings.get(xmlName);
if (oldJavaType != javaType) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_TYPEMAP_REDEFINITION,
ErrorConstants.ERRORDOMAIN, new Object[] { xmlName.toString() } ));
}
return;
}
// TODO - this seems wrong. Why wouldn't we be able to have more than one instance of the same
// Java type as a parameter to an operation?
/*
*
if (xmlToJavaMappings.containsValue(javaType)) {
QName oldKey = findMapKey(xmlToJavaMappings, javaType);
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_TYPEMAP_REDEFINITION,
ErrorConstants.ERRORDOMAIN, new Object[] { String.valueOf(oldKey) }));
}
*/
xmlToJavaMappings.put(xmlName, javaType);
}
@SuppressWarnings("unused")
private <K> K findMapKey(Map<K,?> map, Object value) {
for (Map.Entry<K,?> e: map.entrySet()) {
Object value2 = e.getValue();
if (BindingUtils.sameObject(value, value2)) {
return e.getKey();
}
}
return null;
}
protected final ServiceOperationParamDesc createOperationParamDesc(ServiceId svcId,
MessageTypeConfig cfg, String ns, ServiceTypeMappings typeMappings,
String opName, boolean isErrorType, ClassLoader cl)
throws ServiceException
{
List<Class> rootJavaTypes = new ArrayList<Class>();
List<DataElementSchema> rootElements = new ArrayList<DataElementSchema>();
Map<QName,Class> xmlToJavaMappings = new HashMap<QName,Class>();
if (cfg == null) {
if (isErrorType) {
DataElementSchema elementSchema = DataElementSchemaLoader.getErrorMessageSchema();
rootJavaTypes.add(ErrorMessage.class);
rootElements.add(elementSchema);
xmlToJavaMappings.put(SOAConstants.ERROR_MESSAGE_ELEMENT_NAME, ErrorMessage.class);
}
return new ServiceOperationParamDescImpl(rootJavaTypes, rootElements, xmlToJavaMappings, false);
}
Class clazz = loadClassForJavaType(opName, cfg.getJavaTypeName(), cl);
rootJavaTypes.add(clazz);
DataElementSchema elementSchema = loadElementSchema(svcId, opName, ns, typeMappings, clazz, cfg.getXmlElementName(), cfg.getXmlTypeName(), cl);
rootElements.add(elementSchema);
validateAndAddXmlNameMapping(rootElements, rootJavaTypes, xmlToJavaMappings);
boolean hasAttachments = cfg.hasAttachment();
return new ServiceOperationParamDescImpl(rootJavaTypes, rootElements, xmlToJavaMappings, hasAttachments);
}
protected final ServiceOperationParamDesc createOperationHeaders(ServiceId svcId,
List<MessageHeaderConfig> cfgList, QName svcQName, ServiceTypeMappings typeMappings,
String opName, ClassLoader cl,String ns)
throws ServiceException
{
List<Class> rootJavaTypes = new ArrayList<Class>();
List<DataElementSchema> rootElements = new ArrayList<DataElementSchema>();
Map<QName,Class> xmlToJavaMappings = new HashMap<QName,Class>();
if (cfgList == null) {
return new ServiceOperationParamDescImpl(rootJavaTypes, rootElements, xmlToJavaMappings, false);
}
for (MessageHeaderConfig cfg : cfgList) {
Class clazz = loadClassForJavaType(opName, cfg.getJavaTypeName(), cl);
rootJavaTypes.add(clazz);
// Raghu, added 1/12/2010
/*
* Bug fix: 650886. The pre SOA2.4 Typemappings did not have namespace
* associated with the element. The NS was defaulted to service namespace
* in the loadElementSchema() earlier. The defaulting code was removed as
* part of code changes for supporting root types from non service ns.
* The code here is to support the pre SOA2.4 Typemappings.
*/
QName xmlElementName = cfg.getXmlElementName();
if (XMLConstants.NULL_NS_URI.equals(xmlElementName.getNamespaceURI())) {
xmlElementName = new QName(ns, xmlElementName.getLocalPart());
}
DataElementSchema elementSchema = loadElementSchema(svcId, opName, ns, typeMappings, clazz, xmlElementName, cfg.getXmlTypeName(), cl);
rootElements.add(elementSchema);
}
validateAndAddXmlNameMapping(rootElements, rootJavaTypes, xmlToJavaMappings);
return new ServiceOperationParamDescImpl(rootJavaTypes, rootElements, xmlToJavaMappings, false);
}
private Class loadClassForJavaType(String opName, String className, ClassLoader cl) throws ServiceException {
// load the Java types
if (className == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_METHOD_PARAM_ARGS,
ErrorConstants.ERRORDOMAIN, new Object[] {opName}));
}
Class clazz = ReflectionUtils.loadClass(className, null, cl);
return clazz;
}
private DataElementSchema loadElementSchema(ServiceId svcId, String opName, String ns, ServiceTypeMappings typeMappings, Class clazz, QName xmlName, QName xmlType, ClassLoader cl) throws ServiceException {
String typeNS = typeMappings.getNsForJavaType(clazz);
if (typeNS == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_NO_NAMESPACE_FOR_CLASS,
ErrorConstants.ERRORDOMAIN, new Object[] {clazz.getName()}));
}
// load the XML element names
if (xmlName == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_METHOD_PARAM_ARGS,
ErrorConstants.ERRORDOMAIN, new Object[] {opName}));
}
//xmlName = new QName(ns, xmlName.getLocalPart());
// load the XML element names
if (xmlType == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_METHOD_PARAM_ARGS,
ErrorConstants.ERRORDOMAIN, new Object[] {opName}));
}
xmlType = new QName(typeNS, xmlType.getLocalPart());
ServiceTypeMappingsImpl typeMappingsImpl = (ServiceTypeMappingsImpl)typeMappings;
BaseTypeDefsBuilder typeDefsBuilder = typeMappingsImpl.getTypeDefsBuilder();
DataElementSchema elementSchema = DataElementSchemaLoader.getInstance().loadSchema(
svcId, xmlName, xmlType, typeDefsBuilder, cl);
return elementSchema;
}
protected final Map<String,ServiceOperationDesc> createOperations(ServiceId svcId,
TypeMappingConfigHolder mappings, Collection<String> unsupportedOpNames,
ServiceTypeMappings typeMappings, QName svcQName, ClassLoader cl,
OperationPropertyConfigHolder propertyConfig
)
throws ServiceException
{
Collection<OperationConfig> opConfigs = mappings.getOperations();
Map<String,ServiceOperationDesc> result = new HashMap<String,ServiceOperationDesc>();
for (OperationConfig opConfig: opConfigs) {
String name = opConfig.getName();
String methodName = opConfig.getMethodName();
validateOperationName(name);
String svcNamespace = svcQName.getNamespaceURI();
ServiceOperationParamDesc requestParamDesc = createOperationParamDesc(svcId,
opConfig.getRequestMessage(), svcNamespace, typeMappings, name, false, cl);
ServiceOperationParamDesc responseParamDesc = createOperationParamDesc(svcId,
opConfig.getResponseMessage(), svcNamespace, typeMappings, name, false, cl);
ServiceOperationParamDesc errorParamDesc = createOperationParamDesc(svcId,
//opConfig.getErrorMessage(), null, typeMappings, name, true, cl);
opConfig.getErrorMessage(), svcNamespace, typeMappings, name, true, cl);
ServiceOperationParamDesc requestHeaderParamDesc = createOperationHeaders(svcId,
opConfig.getRequestHeader(), svcQName, typeMappings, name, cl,svcNamespace);
ServiceOperationParamDesc responseHeaderParamDesc = createOperationHeaders(svcId,
opConfig.getResponseHeader(), svcQName, typeMappings, name, cl,svcNamespace);
boolean isSupported = true;
if (unsupportedOpNames != null && unsupportedOpNames.contains(name)) {
isSupported = false;
}
// operation property map from operation.properties file - currently server
// side only, and string values only.
Map<String,Object> propMap;
if (propertyConfig != null) {
Map<String,String> opMap = propertyConfig.getOperationPropertyMap(name);
if (opMap != null) {
propMap = new HashMap<String,Object>();
propMap.putAll(opMap);
} else {
propMap = null;
}
} else {
propMap = null;
}
ServiceOperationDesc operation = new ServiceOperationDescImpl(svcId, name, methodName,
requestParamDesc, responseParamDesc, errorParamDesc, requestHeaderParamDesc,
responseHeaderParamDesc, propMap, true, isSupported);
result.put(name, operation);
}
return result;
}
protected final Map<String,ProtocolProcessorDesc> createProtocolProcessors(
ServiceId svcId, List<ProtocolProcessorConfig> processorConfigs, ClassLoader cl)
throws ServiceException
{
Map<String,ProtocolProcessorDesc> result = new HashMap<String,ProtocolProcessorDesc>();
for (int i=0; i<processorConfigs.size(); i++) {
ProtocolProcessorConfig config = processorConfigs.get(i);
String name = config.getName();
validateProtocolProcessorName(name);
name = name.toUpperCase();
String className = config.getClassName();
String version = config.getVersion();
if (className == null) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_PROTOCOL_PROCESSOR_DEFINITION,
ErrorConstants.ERRORDOMAIN, new Object[] { name } ));
}
ProtocolProcessor processor = ReflectionUtils.createInstance(
className, ProtocolProcessor.class, cl);
ProtocolProcessorInitContextImpl initCtx =
new ProtocolProcessorInitContextImpl(svcId, name, version);
processor.init(initCtx);
initCtx.kill();
Set<String> formats2;
Collection<String> dataFormats = processor.getSupportedDataFormats();
if (dataFormats != null && !dataFormats.isEmpty()) {
formats2 = new HashSet<String>();
for (String format: dataFormats) {
formats2.add(format.toUpperCase());
}
} else {
formats2 = null;
}
result.put(name, new ProtocolProcessorDesc(name, processor, formats2));
}
return result;
}
protected final Map<String,DataBindingDesc> createDataBindings(ServiceId svcId,
MessageProcessorConfigHolder processorConfig,
Collection<String> supportedBindingsNames,
Set<Class> rootClasses,
boolean requireDifferentPayloads, ClassLoader cl, boolean schemaCheck)
throws ServiceException
{
Map<String,DataBindingDesc> result = new HashMap<String,DataBindingDesc>();
SchemaFactory upaAwareSchemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema upaAwareMasterSchema = null;
Set<String> payloadTypes = null;
if (requireDifferentPayloads) {
payloadTypes = new HashSet<String>();
}
Map<String,SerializerConfig> bindingConfigs = processorConfig.getDataBindings();
for (Map.Entry<String,SerializerConfig> e: bindingConfigs.entrySet()) {
SerializerConfig config = e.getValue();
String name = config.getName();
String mimeType = config.getMimeType();
validateDataBindingNameAndType(name, mimeType);
name = name.toUpperCase();
String serClassName = config.getSerializerFactoryClassName();
String deserClassName = config.getDeserializerFactoryClassName();
if (serClassName == null || deserClassName == null) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_DATA_BINDING_DEFINITION,
ErrorConstants.ERRORDOMAIN, new Object[] { name } ));
}
Map<String,String> options = config.getOptions();
if (schemaCheck) {
boolean validate = false;
String payLoadValidation = options.get(BindingConstants.VALIDATE_PAYLOAD);
if(payLoadValidation != null && (payLoadValidation.equalsIgnoreCase("true") ||
payLoadValidation.equalsIgnoreCase("false")))
validate = Boolean.TRUE;
if (validate){
SchemaExtractor schemaExtractor = new SchemaExtractor(svcId.getAdminName());
SchemaBaseDetails schemaDetails = schemaExtractor.getMasterSchemaFilesDetails();
if(upaAwareMasterSchema == null) {
try {
String masterSchemaLocation = schemaDetails.getFilePathForStrictValidation();
upaAwareSchemaFactory.setFeature("http://apache.org/xml/features/validation/schema-full-checking", false);
if(masterSchemaLocation != null){
File schemaFile = new File(masterSchemaLocation);
upaAwareMasterSchema = upaAwareSchemaFactory.newSchema(schemaFile);
}
} catch (Exception exception) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_UNABLE_TO_REGISTER_SCHEMA,
ErrorConstants.ERRORDOMAIN, new Object[] { svcId.getCanonicalServiceName() } ), exception);
}
}
}
}
Map<String,TypeConverter<?,?>> typeConvertersByBoundType = new HashMap<String,TypeConverter<?,?>>();
Map<String,TypeConverter<?,?>> typeConvertersByValueType = new HashMap<String,TypeConverter<?,?>>();
buildTypeConverters(name, processorConfig,
typeConvertersByBoundType, typeConvertersByValueType, cl);
Collection<TypeConverter<?,?>> converters = null;
if (null != typeConvertersByValueType) {
converters = typeConvertersByValueType.values();
}
Class[] rootClassArray = addDataBindingSpecificTypes(rootClasses, converters);
SerializerFactory serFactory = ReflectionUtils.createInstance(
serClassName, SerializerFactory.class, cl);
initSerializerFactory(serFactory, svcId, options, rootClassArray);
//String payloadType = serFactory.getPayloadType().toUpperCase();
String payloadType = serFactory.getPayloadType();
DeserializerFactory deserFactory = ReflectionUtils.createInstance(
deserClassName, DeserializerFactory.class, cl);
initDeserializerFactory(deserFactory, svcId, options, rootClassArray, upaAwareMasterSchema);
String otherPayloadType = deserFactory.getPayloadType().toUpperCase();
if (!payloadType.equals(otherPayloadType)) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_BINDING_PAYLOAD_MISMATCH,
ErrorConstants.ERRORDOMAIN, new Object[] {name, payloadType, otherPayloadType}));
}
if (payloadTypes != null) {
if (payloadTypes.contains(payloadType)) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_DATA_BINDING_PAYLOAD_COLLISION,
ErrorConstants.ERRORDOMAIN, new Object[] {payloadType, name}));
}
payloadTypes.add(payloadType);
}
Map<String,Serializer> customSerializers = new HashMap<String,Serializer>();
Map<String,Deserializer> customDeserializers = new HashMap<String,Deserializer>();
buildCustomSerializers(name, processorConfig,
customSerializers, customDeserializers, cl);
DataBindingDesc bindingDesc = new DataBindingDesc(name, mimeType,
serFactory, deserFactory,
customSerializers, customDeserializers,
typeConvertersByBoundType, typeConvertersByValueType);
result.put(name, bindingDesc);
}
addDefaultDataBindings(svcId, result, payloadTypes, rootClasses, null, false);
if (supportedBindingsNames != null && !supportedBindingsNames.isEmpty()) {
// copy only supported bindings
Map<String,DataBindingDesc> result2 = new HashMap<String,DataBindingDesc>();
for (String name: supportedBindingsNames) {
if (name != null) {
name = name.toUpperCase();
}
if (name == null || name.length() == 0) {
continue;
}
DataBindingDesc bindingDesc = result.get(name);
if (bindingDesc == null) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_UNKNOWN_DATA_BINDING,
ErrorConstants.ERRORDOMAIN, new Object[] { name } ));
}
result2.put(name, bindingDesc);
}
if (!result2.isEmpty()) {
result = result2;
}
}
return result;
}
public static Set<Class> getRootClassesFromOperations(Collection<ServiceOperationDesc> operations) {
Set<Class> rootClasses = new HashSet<Class>();
for (ServiceOperationDesc opDesc: operations) {
rootClasses.addAll(opDesc.getRequestType().getRootJavaTypes());
rootClasses.addAll(opDesc.getResponseType().getRootJavaTypes());
rootClasses.addAll(opDesc.getErrorType().getRootJavaTypes());
ServiceOperationParamDesc headerDesc = opDesc.getRequestHeaders();
if (null != headerDesc) {
rootClasses.addAll(headerDesc.getRootJavaTypes());
}
headerDesc = opDesc.getResponseHeaders();
if (null != headerDesc) {
rootClasses.addAll(headerDesc.getRootJavaTypes());
}
}
// this should cover error message transmission in all fallback cases
// e.g. invalid service config, unknown operation name
rootClasses.add(ErrorMessage.class);
return rootClasses;
}
public static Class[] addDataBindingSpecificTypes(
Set<Class> rootClasses,
Collection<TypeConverter<?,?>> converters) {
Class[] rootClzArray;
if (null == converters) {
rootClzArray = rootClasses.toArray(new Class[rootClasses.size()]);
// rootClzArray = rootClasses.toArray(new Class[rootClasses.size() + 1]);
} else {
Set<Class> rootClzes = new HashSet<Class>();
rootClzes.addAll(rootClasses);
for (Iterator<TypeConverter<?,?>> it = converters.iterator(); it.hasNext(); ) {
TypeConverter<?,?> converter = it.next();
rootClzes.add(converter.getValueType());
}
rootClzArray = rootClzes.toArray(new Class[rootClzes.size()]);
}
return rootClzArray;
}
private void initSerializerFactory(SerializerFactory factory,
ServiceId svcId, Map<String,String> options, Class[] rootClasses) throws ServiceException
{
SerializerFactoryInitContextImpl initCtx =
new SerializerFactoryInitContextImpl(svcId, options, rootClasses);
factory.init(initCtx);
initCtx.kill();
}
private void initDeserializerFactory(DeserializerFactory factory,
ServiceId svcId, Map<String,String> options, Class[] rootClasses, Schema upaAwaremasterSchema) throws ServiceException
{
DeserializerFactoryInitContextImpl initCtx =
new DeserializerFactoryInitContextImpl(svcId, options, rootClasses, upaAwaremasterSchema);
factory.init(initCtx);
initCtx.kill();
}
private boolean hasDefaultDataBinding(Map<String,DataBindingDesc> bindings,
Set<String> payloadTypes, String name)
{
// default data binding uses the same name for both binding name and payloadType
if (bindings.containsKey(name)) {
return true;
}
if (payloadTypes != null && payloadTypes.contains(name)) {
return true;
}
return false;
}
private final static Map<String, String> NV_DATA_BINDING_OPTIONS;
private final static Map<String, String> JSON_DATA_BINDING_OPTIONS;
static {
NV_DATA_BINDING_OPTIONS = new HashMap<String, String>();
NV_DATA_BINDING_OPTIONS.put(JSONStreamWriter.KEY_USE_SCHEMA_INFO, "false");
JSON_DATA_BINDING_OPTIONS = new HashMap<String, String>();
JSON_DATA_BINDING_OPTIONS.put(JSONStreamWriter.KEY_USE_SCHEMA_INFO, "false");
}
protected final void addDefaultDataBindings(ServiceId svcId,
Map<String,DataBindingDesc> bindings,
Set<String> payloadTypes, Set<Class> rootClasses, Schema upaAwareMasterSchema, boolean forFallback) throws ServiceException
{
Class[] rootClassArray = addDataBindingSpecificTypes(rootClasses, null);
if (!hasDefaultDataBinding(bindings, payloadTypes, BindingConstants.PAYLOAD_XML)) {
DataBindingDesc bindingDesc = new DataBindingDesc(BindingConstants.PAYLOAD_XML,
SOAConstants.MIME_XML,
new JAXBXMLSerializerFactory(),
new JAXBXMLDeserializerFactory(),
null, null, null, null);
initSerializerFactory(bindingDesc.getSerializerFactory(), svcId, null, rootClassArray);
initDeserializerFactory(bindingDesc.getDeserializerFactory(), svcId, null, rootClassArray,
upaAwareMasterSchema);
bindings.put(BindingConstants.PAYLOAD_XML, bindingDesc);
if (payloadTypes != null) {
payloadTypes.add(BindingConstants.PAYLOAD_XML);
}
}
if (!hasDefaultDataBinding(bindings, payloadTypes, BindingConstants.PAYLOAD_NV)) {
DataBindingDesc bindingDesc = new DataBindingDesc(BindingConstants.PAYLOAD_NV,
SOAConstants.MIME_NV,
new JAXBNVSerializerFactory(),
new JAXBNVDeserializerFactory(),
null, null, null, null);
initSerializerFactory(bindingDesc.getSerializerFactory(), svcId, (forFallback ? NV_DATA_BINDING_OPTIONS : null), rootClassArray);
initDeserializerFactory(bindingDesc.getDeserializerFactory(), svcId, null, rootClassArray,
upaAwareMasterSchema);
bindings.put(BindingConstants.PAYLOAD_NV, bindingDesc);
if (payloadTypes != null) {
payloadTypes.add(BindingConstants.PAYLOAD_NV);
}
}
if (!hasDefaultDataBinding(bindings, payloadTypes, BindingConstants.PAYLOAD_JSON)) {
DataBindingDesc bindingDesc = new DataBindingDesc(BindingConstants.PAYLOAD_JSON,
SOAConstants.MIME_JSON,
new JAXBJSONSerializerFactory(),
new JAXBJSONDeserializerFactory(),
null, null, null, null);
initSerializerFactory(bindingDesc.getSerializerFactory(), svcId, (forFallback ? JSON_DATA_BINDING_OPTIONS : null), rootClassArray);
initDeserializerFactory(bindingDesc.getDeserializerFactory(), svcId, null, rootClassArray,
upaAwareMasterSchema);
bindings.put(BindingConstants.PAYLOAD_JSON, bindingDesc);
if (payloadTypes != null) {
payloadTypes.add(BindingConstants.PAYLOAD_JSON);
}
}
if (!hasDefaultDataBinding(bindings, payloadTypes, BindingConstants.PAYLOAD_FAST_INFOSET)) {
DataBindingDesc bindingDesc = new DataBindingDesc(BindingConstants.PAYLOAD_FAST_INFOSET,
SOAConstants.MIME_FAST_INFOSET,
new JAXBFastInfosetSerializerFactory(),
new JAXBFastInfosetDeserializerFactory(),
null, null, null, null);
initSerializerFactory(bindingDesc.getSerializerFactory(), svcId, null, rootClassArray);
initDeserializerFactory(bindingDesc.getDeserializerFactory(), svcId, null, rootClassArray,
upaAwareMasterSchema);
bindings.put(BindingConstants.PAYLOAD_FAST_INFOSET, bindingDesc);
if (payloadTypes != null) {
payloadTypes.add(BindingConstants.PAYLOAD_FAST_INFOSET);
}
}
if (!hasDefaultDataBinding(bindings, payloadTypes, BindingConstants.PAYLOAD_PROTOBUF)) {
DataBindingDesc bindingDesc = new DataBindingDesc(BindingConstants.PAYLOAD_PROTOBUF,
SOAConstants.MIME_PROTOBUF,
new ProtobufSerializerFactory(),
new ProtobufDeserializerFactory(),
null, null, null, null);
bindings.put(BindingConstants.PAYLOAD_PROTOBUF, bindingDesc);
if (payloadTypes != null) {
payloadTypes.add(BindingConstants.PAYLOAD_PROTOBUF);
}
}
}
private void buildCustomSerializers(String name,
MessageProcessorConfigHolder processorConfig,
Map<String,Serializer> customSerializers,
Map<String,Deserializer> customDeserializers,
ClassLoader cl)
throws ServiceException
{
Map<String,CustomSerializerConfig> customSerializerConfigs = processorConfig.getCustomSerializerMap(name);
if (customSerializerConfigs == null || customSerializerConfigs.isEmpty()) {
return;
}
for (CustomSerializerConfig info: customSerializerConfigs.values()) {
String serClassName = info.getSerializerClassName();
if (serClassName != null) {
Serializer ser = ReflectionUtils.createInstance(serClassName, Serializer.class, cl);
Class javaType = ser.getBoundType();
if (javaType == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_CUSTOM_SER_NO_BOUND_TYPE,
ErrorConstants.ERRORDOMAIN, new Object[] {serClassName}));
}
customSerializers.put(javaType.getName(), ser);
}
String deserClassName = info.getDeserializerClassName();
if (deserClassName != null) {
Deserializer deser = ReflectionUtils.createInstance(deserClassName, Deserializer.class, cl);
Class javaType = deser.getBoundType();
if (javaType == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_CUSTOM_DESER_NO_BOUND_TYPE,
ErrorConstants.ERRORDOMAIN, new Object[] {deserClassName}));
}
customDeserializers.put(javaType.getName(), deser);
}
}
}
private void buildTypeConverters(String name,
MessageProcessorConfigHolder processorConfig,
Map<String,TypeConverter<?,?>> typeConvertersByBoundType,
Map<String,TypeConverter<?,?>> typeConvertersByValueType,
ClassLoader cl) throws ServiceException
{
Map<String,TypeConverterConfig> convMap = processorConfig.getTypeConverterMap(name);
if (convMap == null || convMap.isEmpty()) {
return;
}
for (TypeConverterConfig convConfig: convMap.values()) {
String boundType = convConfig.getBoundJavaTypeName();
String valueType = convConfig.getValueJavaTypeName();
String className = convConfig.getTypeConverterClassName();
if (className == null || boundType == null || valueType == null) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_DATA_BINDING_TYPE_CONV,
ErrorConstants.ERRORDOMAIN, new Object[] {name}));
}
TypeConverter<?,?> conv;
if (typeConvertersByBoundType.containsKey(boundType)) {
conv = typeConvertersByBoundType.get(boundType);
if (!conv.getClass().getName().equals(className)) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_DATA_BINDING_TYPE_CONV_COLLISION,
ErrorConstants.ERRORDOMAIN, new Object[] {name, boundType}));
}
// keep using old converter if class name matches
} else {
conv = ReflectionUtils.createInstance(className, TypeConverter.class, cl);
checkTypeConverter(conv, valueType, boundType);
typeConvertersByBoundType.put(boundType, conv);
}
if (typeConvertersByValueType.containsKey(valueType)) {
TypeConverter oldConv = typeConvertersByValueType.get(valueType);
if (!oldConv.getClass().getName().equals(className)) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_DATA_BINDING_TYPE_CONV_COLLISION,
ErrorConstants.ERRORDOMAIN, new Object[] {name, valueType}));
}
// keep using old converter if class name matches
} else {
// converter is either created or found in the previous operations, let's use it
typeConvertersByValueType.put(valueType, conv);
}
}
}
private void checkTypeConverter(TypeConverter conv, String valueType, String boundType)
throws ServiceException
{
Class valueTypeClass = conv.getValueType();
Class boundTypeClass = conv.getBoundType();
if (valueTypeClass == null || !valueTypeClass.getName().equals(valueType)) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_TYPE_CONV_CLASS_MISMATCH,
ErrorConstants.ERRORDOMAIN, new Object[] {conv.getClass().getName(), valueType}));
}
if (boundTypeClass == null || !boundTypeClass.getName().equals(boundType)) {
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_TYPE_CONV_CLASS_MISMATCH,
ErrorConstants.ERRORDOMAIN, new Object[] {conv.getClass().getName(), boundType}));
}
}
protected final List<LoggingHandler> createLoggingHandlers(
ServiceId svcId, MessageProcessorConfigHolder processorConfig, ClassLoader cl)
throws ServiceException
{
Set<String> handlerClasses = new HashSet<String>();
List<LoggingHandler> result = new ArrayList<LoggingHandler>();
List<FrameworkHandlerConfig> handlers = processorConfig.getLoggingHandlers();
if (handlers == null) {
handlers = new ArrayList<FrameworkHandlerConfig>();
}
boolean supportsErrorLogging = false;
for (FrameworkHandlerConfig logHandler: handlers) {
String className = logHandler.getClassName();
if (className == null || className.length() == 0) {
// Shouldn't happen - config checks for this
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_UNDEFINED_LOG_HANDLER_CLASS_NAME,
ErrorConstants.ERRORDOMAIN));
}
if (handlerClasses.contains(className)) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_DUPLICATE_LOG_HANDLER_CLASS_NAME,
ErrorConstants.ERRORDOMAIN, new Object[] {className}));
}
handlerClasses.add(className);
LoggingHandler handler = ReflectionUtils.createInstance(className, LoggingHandler.class, cl);
Map<String,String> options = logHandler.getOptions();
LoggingHandlerInitContextImpl initCtx = new LoggingHandlerInitContextImpl(svcId, options);
handler.init(initCtx);
initCtx.kill();
supportsErrorLogging |= initCtx.supportsErrorLogging();
result.add(handler);
}
if (result.isEmpty() || !supportsErrorLogging) {
addDefaultLoggingHandler(svcId, cl, result);
}
return result;
}
protected final void addDefaultLoggingHandler(ServiceId svcId,
ClassLoader cl, List<LoggingHandler> list) throws ServiceException
{
String className = getDefaultLoggingHandlerClassName();
LoggingHandler handler = ReflectionUtils.createInstance(className, LoggingHandler.class, cl);
LoggingHandlerInitContextImpl initCtx = new LoggingHandlerInitContextImpl(svcId, null);
handler.init(initCtx);
initCtx.kill();
list.add(handler);
}
protected abstract String getDefaultLoggingHandlerClassName();
protected final Class loadServiceInterfaceClass(CommonConfigHolder config,
boolean isRequired, ClassLoader cl) throws ServiceException
{
String className = config.getServiceInterfaceClassName();
if (className == null) {
if (!isRequired) {
return null;
}
throw new ServiceCreationException(
ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_UNDEFINED_INTF_CLASS_NAME,
ErrorConstants.ERRORDOMAIN));
}
return ReflectionUtils.loadClass(className, null, cl);
}
protected HeaderMappingsDesc loadHeaderMappings(String adminName, OptionList options, boolean inbound) throws ServiceCreationException {
if (options == null) {
return HeaderMappingsDesc.EMPTY_MAPPINGS;
}
List<NameValue> nameValueList = options.getOption();
Map<String,String> headerMap = new HashMap<String,String>();
Set<String> suppressHeaderSet = new HashSet<String>();
for (NameValue nv : nameValueList) {
String rawname = nv.getName();
String name = SOAHeaders.normalizeName(rawname, true);
if (inbound && !SOAHeaders.isSOAHeader(name)) { // only validate incoming header names
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_HEADER_NAME,
ErrorConstants.ERRORDOMAIN, new Object[] {adminName, name}));
}
String value = nv.getValue();
if (value.startsWith("header[")) {
if (!value.endsWith("]")) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_MAPPING_VALUE,
ErrorConstants.ERRORDOMAIN, new Object[] {adminName, value}));
}
String indexval = value.substring(7, value.length()-1);
if (inbound) {
if( headerMap.containsKey(indexval)) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_DUPLICATE_HEADER_KEY,
ErrorConstants.ERRORDOMAIN, new Object[] {adminName, indexval}));
}
headerMap.put(indexval, name);
} else {
if( headerMap.containsKey(indexval)) {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_DUPLICATE_HEADER_KEY,
ErrorConstants.ERRORDOMAIN, new Object[] {adminName, indexval}));
}
headerMap.put(name, indexval);
}
} else if (value.equals("suppress")) {
suppressHeaderSet.add(name);
} else {
throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_FACTORY_INVALID_MAPPING_VALUE,
ErrorConstants.ERRORDOMAIN, new Object[] {adminName, value}));
}
}
HeaderMappingsDesc result = new HeaderMappingsDesc(headerMap, suppressHeaderSet);
return result;
}
private void updateMetrics(ServiceDesc serviceDesc) {
MetricsConfigManager mgr;
if (m_isClientSide) {
mgr = MetricsConfigManager.getClientInstance();
} else {
mgr = MetricsConfigManager.getServerInstance();
}
// make sure matrics subsystem recalculates its levels
mgr.resetMonitoringLevel(serviceDesc.getAdminName());
}
protected final void initializeCompStatus(BaseServiceBrowserCompStatus comp) {
URL xslTemplate = BaseServiceBrowserCompStatus.class.getResource("ServiceBrowserCompStatus.xsl");
if (xslTemplate == null) {
throw new RuntimeException("Unable to find XSL template ServiceBrowserCompStatus.xsl" +
" for ServiceDesc browser " + comp.getClass().getName());
}
Registration.registerComponent(comp, xslTemplate);
}
static {
SOAVariableProvider.init();
}
}