/******************************************************************************* * 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.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.ebayopensource.turmeric.runtime.binding.utils.CollectionUtils; import org.ebayopensource.turmeric.runtime.common.binding.DataBindingDesc; import org.ebayopensource.turmeric.runtime.common.binding.DeserializerFactory; import org.ebayopensource.turmeric.runtime.common.binding.SerializerFactory; import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory; import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceException; import org.ebayopensource.turmeric.runtime.common.impl.attachment.BaseMessageAttachments; import org.ebayopensource.turmeric.runtime.common.impl.attachment.OutboundMessageAttachments; 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.internal.pipeline.InboundMessageImpl; import org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline.OutboundMessageImpl; import org.ebayopensource.turmeric.runtime.common.impl.internal.service.BaseServiceDescFactory; import org.ebayopensource.turmeric.runtime.common.impl.internal.service.DeserializerFactoryInitContextImpl; import org.ebayopensource.turmeric.runtime.common.impl.internal.service.ProtocolProcessorDesc; import org.ebayopensource.turmeric.runtime.common.impl.internal.service.SerializerFactoryInitContextImpl; import org.ebayopensource.turmeric.runtime.common.impl.utils.HTTPCommonUtils; import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager; import org.ebayopensource.turmeric.runtime.common.pipeline.InboundMessage; import org.ebayopensource.turmeric.runtime.common.pipeline.Transport; 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.types.Cookie; import org.ebayopensource.turmeric.runtime.common.types.G11nOptions; import org.ebayopensource.turmeric.runtime.common.types.SOAConstants; import org.ebayopensource.turmeric.runtime.common.types.SOAHeaders; import org.ebayopensource.turmeric.runtime.common.types.ServiceAddress; import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants; import org.ebayopensource.turmeric.runtime.spf.impl.internal.markdown.SOAServerMarkdownStateId; import org.ebayopensource.turmeric.runtime.spf.impl.internal.markdown.SOAServerMarkdownStateManager; import org.ebayopensource.turmeric.runtime.spf.impl.internal.pipeline.ServerMessageContextImpl; import org.ebayopensource.turmeric.runtime.spf.impl.internal.pipeline.ServerMessageProcessor; 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.service.ServerServiceId; import com.ebay.kernel.context.AppBuildConfig; import com.ebay.kernel.context.ServerContext; import com.ebay.kernel.markdown.MarkdownStateSnapshot; import com.ebay.kernel.util.StringUtils; /** * Helps creating ServerMessageContext in a safe way * * @author ichernyshev */ public final class ServerMessageContextBuilder { private static String s_poolName = null; private final String m_requestUri; private final String m_requestTransport; private final Transport m_responseTransport; private final Map<String,String> m_transportHeaders; private final Cookie[] m_cookies; private final ServiceAddress m_clientAddress; private final ServiceAddress m_serviceAddress; private final String m_targetServerName; private final int m_targetServerPort; private final Map<String, String> m_queryParams; private final Map<String, String> m_rawQueryParams; private ServerServiceDesc m_serviceDesc; private ServiceOperationDesc m_operationDesc; private ProtocolProcessorDesc m_protocolProcessor; private DataBindingDesc m_requestDataBinding; private DataBindingDesc m_responseDataBinding; private G11nOptions m_g11nOptions; private String m_requestId; private String m_requestGuid; private List<Throwable> m_errors; private String m_requestVersion; private Map<String,Object> m_contextProperties; private BaseMessageAttachments m_requestAttachments; private BaseMessageAttachments m_responseAttachments; private ServerMessageContextImpl m_context; private boolean m_hasInput; public ServerMessageContextBuilder(ServiceResolver resolver, String requestUri, String requestTransport, Transport responseTransport, Map<String, String> transportHeaders, Cookie[] cookies, ServiceAddress clientAddress, ServiceAddress serviceAddress, Collection<Throwable> errors, String targetServerName, int targetServerPort, Map<String, String> queryParams) throws ServiceException { this(resolver, requestUri, requestTransport, responseTransport, transportHeaders, cookies, clientAddress, serviceAddress, errors, targetServerName, targetServerPort, queryParams, queryParams); } public ServerMessageContextBuilder(ServiceResolver resolver, String requestUri, String requestTransport, Transport responseTransport, Map<String,String> transportHeaders, Cookie[] cookies, ServiceAddress clientAddress, ServiceAddress serviceAddress, Collection<Throwable> errors, String targetServerName, int targetServerPort, Map<String, String> queryParams, Map<String, String> rawQueryParams) throws ServiceException { m_requestUri = requestUri; m_requestTransport = requestTransport; m_responseTransport = responseTransport; m_transportHeaders = normalizeTransportHeaders(transportHeaders); m_cookies = normalizeCookies(cookies); m_clientAddress = clientAddress; m_serviceAddress = serviceAddress; m_targetServerName = targetServerName; m_targetServerPort = targetServerPort; m_queryParams = queryParams; // can be null; can be modified at this level m_rawQueryParams = rawQueryParams; m_serviceDesc = resolver.lookupServiceDesc(); Collection<Throwable> resolverErrors = resolver.getErrors(); if (resolverErrors != null) { addErrors(resolverErrors); } if (errors != null) { addErrors(errors); } lookupOperationDesc(); lookupRequestBindingDesc(); lookupResponseBindingDesc(); loadRequestG11nOptions(); loadRequestVersion(); if (!m_serviceDesc.isFallback() && m_operationDesc.isExisting()) { MarkdownStateSnapshot<SOAServerMarkdownStateId> markdownState = SOAServerMarkdownStateManager.getInstance().getMarkdownState( m_serviceDesc, m_operationDesc.getName(), true); if (markdownState != null) { getLogger().log(Level.FINE, "Service " + markdownState.getId().getStringId() + " has been marked down due to " + markdownState.getReason() + " in request " + getRequestUriForLog()); addError(new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_SERVICE_MARKDOWN, ErrorConstants.ERRORDOMAIN, new Object[] { markdownState.getId().getStringId(), markdownState.getReason()}))); } } // If the GUID id exists, use it to create request id String requestGuid = m_transportHeaders.get(SOAHeaders.REQUEST_GUID); if (requestGuid != null) { m_requestGuid = requestGuid; m_requestId = completeRequestId(m_requestGuid); } else { // If GUID id doesn't exist, String requestId = m_transportHeaders.get(SOAHeaders.REQUEST_ID); if (requestId != null) { m_requestId = completeRequestId(requestId); } else { m_requestGuid = HTTPCommonUtils.generateRequestGuid(); m_requestId = completeRequestId(m_requestGuid); setContextProperty(SOAConstants.CTX_PROP_GUID_CREATED, Boolean.valueOf(true)); } } m_transportHeaders.put(SOAHeaders.REQUEST_ID, m_requestId); } public String getRequestUri() { return m_requestUri; } public String getTransportHeader(String name) { name = SOAHeaders.normalizeName(name, true); return m_transportHeaders.get(name); } public ServerServiceId getServiceId() { return m_serviceDesc.getServiceId(); } public ServiceOperationDesc getOperationDesc() { return m_operationDesc; } public DataBindingDesc getRequestDataBinding() { return m_requestDataBinding; } public DataBindingDesc getResponseDataBinding() { return m_responseDataBinding; } public G11nOptions getG11nOptions() { return m_g11nOptions; } private String getServiceVersion() { return m_serviceDesc.getVersionCheckHandler().getVersion(); } public Charset getEffectiveCharset() { if (m_serviceDesc.getServiceCharset() != null) { // Service has configured a default-encoding; use that. return m_serviceDesc.getServiceCharset(); } // use the encoding of the request data. Never null. return m_g11nOptions.getCharset(); } private String getRequestUriForLog() { return "'" + m_requestUri + "'"; } public void addError(Throwable th) { if (m_errors == null) { m_errors = new ArrayList<Throwable>(); } m_errors.add(th); } public void addErrors(Collection<Throwable> errors) { if (m_errors == null) { m_errors = new ArrayList<Throwable>(); } m_errors.addAll(errors); } public boolean hasErrors() { return (m_errors != null && !m_errors.isEmpty()); } public void setContextProperty(String name, Object value) { if (name == null) { throw new NullPointerException(); } if (m_contextProperties == null) { m_contextProperties = new HashMap<String,Object>(); } m_contextProperties.put(name, value); } public void setRequestAttachments(BaseMessageAttachments value) { m_requestAttachments = value; } public void setResponseAttachments(BaseMessageAttachments value) { m_responseAttachments = value; } public void setContextValues(ServerMessageContextImpl ctx) throws ServiceException { ctx.setRequestId(m_requestId, m_requestGuid); if (m_contextProperties != null) { for (Map.Entry<String,Object> e: m_contextProperties.entrySet()) { String name = e.getKey(); Object value = e.getValue(); if (name.startsWith(SOAConstants.CTX_PROP_PREFIX)) { ctx.setSystemProperty(name, value); } else { ctx.setProperty(name, value); } } } if (hasErrors()) { for (Throwable e: m_errors) { ctx.addError(e); } } } private static Map<String,String> normalizeTransportHeaders(Map<String,String> headers) { Map<String,String> result = new HashMap<String,String>(); if (headers == null || headers.isEmpty()) { return result; } for (Iterator<Map.Entry<String,String>> it=headers.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String,String> e = it.next(); String name = e.getKey(); String value = e.getValue(); if (name == null) { continue; } // make all system headers names uppercase name = SOAHeaders.normalizeName(name, true); value = SOAHeaders.normalizeValue(name, value); result.put(name, value); } return result; } private static Cookie[] normalizeCookies(Cookie[] cookies) { if (cookies == null) { return new Cookie[0]; } return cookies; } private void lookupOperationDesc() throws ServiceException { // HOT FIX: For Porlet call, there's a compatibility issue regarding Upper case vs lower case operation. // Here, we want to make the first letter of the operation name lower case for Porlet, // to handle 587 client talking to 589 server scenario // RECEIVING SIDE LOGIC String opName = m_transportHeaders.get(SOAHeaders.SERVICE_OPERATION_NAME); if (opName != null && opName.equals("Portlet")) { StringBuffer sb = new StringBuffer(); sb.append(Character.toLowerCase(opName.charAt(0))); sb.append(opName.substring(1)); opName = sb.toString(); m_transportHeaders.put(SOAHeaders.SERVICE_OPERATION_NAME, opName); } m_operationDesc = m_serviceDesc.lookupOperation(m_requestUri, m_transportHeaders); if (m_operationDesc != null) { if (!m_operationDesc.isSupported()) { getLogger().log(Level.FINE, "Operation name not supported in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + "." + m_operationDesc.getName()); addError(new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_OPERATION_UNSUPPORTED, ErrorConstants.ERRORDOMAIN, new Object[] {m_operationDesc.getName()}))); } return; } String operationName = m_transportHeaders.get(SOAHeaders.SERVICE_OPERATION_NAME); if (operationName == null) { operationName = "***null***"; getLogger().log(Level.FINE, "Unknown operation name in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + "." + operationName); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_MISSING_OPERATION_NAME, ErrorConstants.ERRORDOMAIN, new Object[] {}))); } else if (!m_serviceDesc.isFallback()) { getLogger().log(Level.FINE, "Unknown operation name in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + "." + operationName); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_UNKNOWN_OPERATION, ErrorConstants.ERRORDOMAIN, new Object[] {operationName}))); } // create fallback operation m_operationDesc = ServerServiceDescFactory.getInstance().createFallbackOperationDesc( m_serviceDesc, operationName); } private void lookupProtocolProcessor() { if (m_serviceDesc.isFallback()) { m_protocolProcessor = m_serviceDesc.getNullProtocolProcessor(); return; } m_protocolProcessor = m_serviceDesc.lookupProtocolProcessor(m_requestUri, m_transportHeaders); if (m_protocolProcessor != null) { String requestPayload = m_requestDataBinding.getPayloadType(); if (!m_protocolProcessor.isPayloadSupported(requestPayload)) { getLogger().log(Level.FINE, "Protocol '" + m_protocolProcessor.getName() + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + " does not support request payload " + requestPayload); addError(new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_PROTOCOLPROCESSOR_UNSUPPORTED_REQUEST_FORMAT, ErrorConstants.ERRORDOMAIN, new Object[] {m_protocolProcessor.getName(), m_serviceDesc.getAdminName(), requestPayload}))); } String responsePayload = m_responseDataBinding.getPayloadType(); if (!m_protocolProcessor.isPayloadSupported(requestPayload)) { getLogger().log(Level.FINE, "Protocol '" + m_protocolProcessor.getName() + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + " does not support response payload " + responsePayload); addError(new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_PROTOCOLPROCESSOR_UNSUPPORTED_RESPONSE_FORMAT, ErrorConstants.ERRORDOMAIN, new Object[] {m_protocolProcessor.getName(), m_serviceDesc.getAdminName(), responsePayload}))); } return; } String protocolName = m_transportHeaders.get(SOAHeaders.MESSAGE_PROTOCOL); if (protocolName == null) { m_protocolProcessor = m_serviceDesc.getNullProtocolProcessor(); return; } // protocol is passed, but not recognized getLogger().log(Level.FINE, "Unknown protocol name '" + protocolName + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName()); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_UNKNOWN_PROTOCOL, ErrorConstants.ERRORDOMAIN, new Object[] {protocolName}))); m_protocolProcessor = m_serviceDesc.getNullProtocolProcessor(); } private void lookupProtocolProcessor(InboundMessage msg) throws ServiceException { if (m_serviceDesc.isFallback()) { m_protocolProcessor = m_serviceDesc.getNullProtocolProcessor(); return; } // First check the headers m_protocolProcessor = m_serviceDesc.lookupProtocolProcessor(m_requestUri, m_transportHeaders); if (m_protocolProcessor == null) { String protocolName = m_transportHeaders.get(SOAHeaders.MESSAGE_PROTOCOL); if (protocolName != null) { // Protocol name is passed, but not recognized getLogger().log(Level.FINE, "Unknown protocol name '" + protocolName + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName()); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_UNKNOWN_PROTOCOL, ErrorConstants.ERRORDOMAIN, new Object[] {protocolName}))); } // Then ask each processor whether it's the right one for the message Collection<ProtocolProcessorDesc> protocolProcessors = m_serviceDesc.getAllProtocolProcessors(); for (ProtocolProcessorDesc ppdesc : protocolProcessors) { if (ppdesc.getProcessor().isExpectedMessageProtocol(msg)) { m_protocolProcessor = ppdesc; break; } } } if (m_protocolProcessor != null) { String requestPayload = m_requestDataBinding.getPayloadType(); if (!m_protocolProcessor.isPayloadSupported(requestPayload)) { getLogger().log(Level.FINE, "Protocol '" + m_protocolProcessor.getName() + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + " does not support request payload " + requestPayload); addError(new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_PROTOCOLPROCESSOR_UNSUPPORTED_REQUEST_FORMAT, ErrorConstants.ERRORDOMAIN, new Object[] {m_protocolProcessor.getName(), m_serviceDesc.getAdminName(), requestPayload}))); } String responsePayload = m_responseDataBinding.getPayloadType(); if (!m_protocolProcessor.isPayloadSupported(requestPayload)) { getLogger().log(Level.FINE, "Protocol '" + m_protocolProcessor.getName() + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName() + " does not support response payload " + responsePayload); addError(new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_PROTOCOLPROCESSOR_UNSUPPORTED_RESPONSE_FORMAT, ErrorConstants.ERRORDOMAIN, new Object[] {m_protocolProcessor.getName(), m_serviceDesc.getAdminName(), responsePayload}))); } return; } m_protocolProcessor = m_serviceDesc.getNullProtocolProcessor(); } private void lookupRequestBindingDesc() throws ServiceException { m_requestDataBinding = m_serviceDesc.lookupDataBindingForRequest(m_requestUri, m_transportHeaders); if (m_requestDataBinding != null) { return; } String payloadType = m_transportHeaders.get(SOAHeaders.REQUEST_DATA_FORMAT); if (payloadType == null) { payloadType = "***null***"; } if (!m_serviceDesc.isFallback()) { getLogger().log(Level.FINE, "Unknown request data format '" + payloadType + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName()); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_UNKNOWN_REQUEST_PAYLOAD, ErrorConstants.ERRORDOMAIN, new Object[] {payloadType}))); } // create fallback request binding m_requestDataBinding = createFallbackDataBinding("request", payloadType); } private void lookupResponseBindingDesc() throws ServiceException { m_responseDataBinding = m_serviceDesc.lookupDataBindingForResponse(m_requestUri, m_transportHeaders); if (m_responseDataBinding != null) { return; } String payloadType = m_transportHeaders.get(SOAHeaders.RESPONSE_DATA_FORMAT); if (payloadType == null) { // TODO: move this logic to matcher? m_responseDataBinding = m_requestDataBinding; return; } if (!m_serviceDesc.isFallback()) { getLogger().log(Level.FINE, "Unknown response data format '" + payloadType + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName()); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_UNKNOWN_RESPONSE_PAYLOAD, ErrorConstants.ERRORDOMAIN, new Object[] {payloadType}))); } // create fallback response binding m_responseDataBinding = createFallbackDataBinding("request", payloadType); } 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) throws ServiceException { DeserializerFactoryInitContextImpl initCtx = new DeserializerFactoryInitContextImpl(svcId, options, rootClasses, null); factory.init(initCtx); initCtx.kill(); } private DataBindingDesc createFallbackDataBinding(String name, String payloadType) throws ServiceException { // There are 2 scenarios why we're here: // 1. it is a totally custom payload type (not JSON, NV or XML), // which is not supported by this real or fallback ServiceDesc // 2. it is a real service, but this well-known payload type (NV, JSON or XML) // is not in the list of supported bindings // In both cases, fallback binding for sending error response should be XML DeserializerFactory deser = new JAXBXMLDeserializerFactory(); SerializerFactory ser = new JAXBXMLSerializerFactory(); ServerServiceId serverServiceId = null; Collection<ServiceOperationDesc> opDescs = null; if (m_serviceDesc != null) { opDescs = m_serviceDesc.getAllOperations(); serverServiceId = m_serviceDesc.getServiceId(); } Set<Class> rootClasses = BaseServiceDescFactory.getRootClassesFromOperations(opDescs); Class[] rootClzes = BaseServiceDescFactory.addDataBindingSpecificTypes(rootClasses, null); initSerializerFactory(ser, serverServiceId, null, rootClzes); initDeserializerFactory(deser, serverServiceId, null, rootClzes); return new DataBindingDesc( "***fallback_" + name + "_data_binding_" + ser.getPayloadType() + "***", SOAConstants.MIME_XML, ser, deser, null, null, null, null); } private void loadRequestG11nOptions() throws ServiceException { String globalIdStr = m_transportHeaders.get(SOAHeaders.GLOBAL_ID); String localeStr = m_transportHeaders.get(SOAHeaders.LOCALE_LIST); String encoding = m_transportHeaders.get(SOAHeaders.MESSAGE_ENCODING); Charset charset = G11nOptions.DEFAULT_CHARSET; if (encoding != null) { try { charset = Charset.forName(encoding); } catch (Exception e) { getLogger().log(Level.FINE, "Unknown encoding name '" + encoding + "' in request " + getRequestUriForLog() + " to " + m_serviceDesc.getAdminName()); addError(new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_UNSUPPORTED_CHARSET, ErrorConstants.ERRORDOMAIN, new Object[] {encoding}), e)); } } List<String> locales; if (localeStr != null) { locales = StringUtils.splitStr(localeStr, ',', true); } else { locales = null; } m_g11nOptions = new G11nOptions(charset, locales, globalIdStr); } private void loadRequestVersion() { m_requestVersion = m_transportHeaders.get(SOAHeaders.VERSION); } /** * Request ID could be just "guid", or a combination of guid+svcName+IP+poolName. * We will always append our current svcName+IP+poolName with "!" as delimiter. * * @param requestId * @return */ private String completeRequestId(String requestId) { String serviceName = m_serviceDesc.getAdminName(); String ipAddr = ServerContext.getHostAddress(); return requestId + "!" + serviceName + "!" + ipAddr + "!" + getPoolName() + "["; } /** * Get pool name from build info */ private static String getPoolName() { if (s_poolName != null) { return s_poolName; } try { s_poolName = AppBuildConfig.getInstance().getCalPoolName(); } catch (Throwable e) { s_poolName = ""; getLogger().log(Level.WARNING, "Unable to get pool name", e); } return s_poolName; } private void createMessageContext(InputStream is) throws ServiceException { if (m_context != null) { return; } boolean bufferingMode = m_transportHeaders.containsKey(SOAHeaders.NON_STREAMING_MODE); // NOTE: no message header will be available at this stage, thus NULL is being passed into the outbound message impl InboundMessageImpl requestMsg = new InboundMessageImpl(true, m_requestTransport, getRequestDataBinding(), getG11nOptions(), m_transportHeaders, m_cookies, null, m_requestAttachments, getOperationDesc(), bufferingMode); if (is != null) requestMsg.setInputStream(is); ServiceOperationDesc opDesc = getOperationDesc(); ServiceOperationParamDesc respParam = opDesc.getResponseType(); boolean respHasAttachment = respParam.hasAttachment(); if (respHasAttachment) { String protocolName = m_transportHeaders.get(SOAHeaders.MESSAGE_PROTOCOL); setResponseAttachments(new OutboundMessageAttachments(protocolName)); } OutboundMessageImpl responseMsg = new OutboundMessageImpl(false, m_requestTransport, getResponseDataBinding(), getG11nOptions(), null, null, null, m_responseAttachments, getOperationDesc(), false, 0, bufferingMode); ServerMessageContextImpl ctx = new ServerMessageContextImpl( m_serviceDesc, getOperationDesc(), null, m_responseTransport, requestMsg, responseMsg, m_serviceAddress, null, m_clientAddress, m_requestVersion, getServiceVersion(), getEffectiveCharset(), m_requestUri, m_targetServerName, m_targetServerPort, m_queryParams, m_rawQueryParams); lookupProtocolProcessor(requestMsg); ctx.setProtocolProcessor(m_protocolProcessor); setContextValues(ctx); m_context = ctx; } public final List<Throwable> getContextErrorList() { if (m_context != null) { return m_context.getErrorList(); } return CollectionUtils.EMPTY_THROWABLE_LIST; } public void setInputStream(InputStream is) throws ServiceException { createMessageContext(is); m_hasInput = true; } public void setParamReferences(Object[] params) throws ServiceException { createMessageContext(null); InboundMessage msg = (InboundMessage)m_context.getRequestMessage(); msg.setParamReferences(params); m_hasInput = true; } public void processCall() throws ServiceException { if (!m_hasInput) { throw new IllegalStateException("No input was provided for the request message"); } ServerMessageProcessor processor = ServerMessageProcessor.getInstance(); processor.processMessage(m_context); } private static Logger getLogger() { return LogManager.getInstance(ServerMessageContextBuilder.class); } public static void validateServiceName(String adminName) throws ServiceException { ServerServiceDescFactory.getInstance().getServiceDesc(adminName); } public static void init() throws ServiceException { ServerMessageProcessor.getInstance(); } }