blob: 0f831e8412427c1a5ef43b512b017bdb8b7e7f31 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.util;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.builder.Builder;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.transport.MessageFormatter;
import org.apache.axis2.transport.http.ApplicationXMLFormatter;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.SOAPMessageFormatter;
import org.apache.axis2.transport.http.XFormURLEncodedFormatter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.Map;
/**
* MessageProcessorSelector is utility class which encapsulate MessageBuilder and
* MessageFormatter selection logic.
*
* @since 1.7.0
*/
public class MessageProcessorSelector {
private static final Log log = LogFactory.getLog(MessageProcessorSelector.class);
/**
* Initial work for a builder selector which selects the builder for a given message format
* based on the the content type of the recieved message. content-type to builder mapping can be
* specified through the Axis2.xml.
*
* @param type content-type
* @param msgContext the active MessageContext
* @return the builder registered against the given content-type
* @throws org.apache.axis2.AxisFault
*/
public static Builder getMessageBuilder(String type, MessageContext msgContext)
throws AxisFault {
boolean useFallbackBuilder = false;
AxisConfiguration configuration =
msgContext.getConfigurationContext().getAxisConfiguration();
Parameter useFallbackParameter = configuration.getParameter(Constants.Configuration.USE_DEFAULT_FALLBACK_BUILDER);
if (useFallbackParameter != null) {
useFallbackBuilder = JavaUtils.isTrueExplicitly(useFallbackParameter.getValue(), useFallbackBuilder);
}
String cType = getContentTypeForBuilderSelection(type, msgContext);
Builder builder = configuration.getMessageBuilder(cType, useFallbackBuilder);
if (builder != null) {
// Check whether the request has a Accept header if so use that as the response
// message type.
// If thats not present,
// Setting the received content-type as the messageType to make
// sure that we respond using the received message serialization format.
Object contentNegotiation = configuration
.getParameterValue(Constants.Configuration.ENABLE_HTTP_CONTENT_NEGOTIATION);
if (JavaUtils.isTrueExplicitly(contentNegotiation)) {
Map transportHeaders =
(Map) msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
if (transportHeaders != null) {
String acceptHeader = (String) transportHeaders.get(HTTPConstants.HEADER_ACCEPT);
if (acceptHeader != null) {
int index = acceptHeader.indexOf(";");
if (index > 0) {
acceptHeader = acceptHeader.substring(0, index);
}
String[] strings = acceptHeader.split(",");
for (String string : strings) {
String accept = string.trim();
// We dont want dynamic content negotoatin to work on text.xml as its
// ambiguos as to whether the user requests SOAP 1.1 or POX response
if (!HTTPConstants.MEDIA_TYPE_TEXT_XML.equals(accept) &&
configuration.getMessageFormatter(accept) != null) {
type = string;
break;
}
}
}
}
}
msgContext.setProperty(Constants.Configuration.MESSAGE_TYPE, type);
}
return builder;
}
/**
* Initial work for a builder selector which selects the builder for a given message format based on the the content type of the recieved message.
* content-type to builder mapping can be specified through the Axis2.xml.
*
* @param msgContext
* @return the builder registered against the given content-type
* @throws AxisFault
*/
public static MessageFormatter getMessageFormatter(MessageContext msgContext)
throws AxisFault {
MessageFormatter messageFormatter = null;
String messageFormatString = getMessageFormatterProperty(msgContext);
messageFormatString = getContentTypeForFormatterSelection(messageFormatString, msgContext);
if (messageFormatString != null) {
messageFormatter = msgContext.getConfigurationContext()
.getAxisConfiguration().getMessageFormatter(messageFormatString);
if (log.isDebugEnabled()) {
log.debug("Message format is: " + messageFormatString
+ "; message formatter returned by AxisConfiguration: " + messageFormatter);
}
}
if (messageFormatter == null) {
messageFormatter = (MessageFormatter) msgContext.getProperty(Constants.Configuration.MESSAGE_FORMATTER);
if (messageFormatter != null) {
return messageFormatter;
}
}
if (messageFormatter == null) {
// If we are doing rest better default to Application/xml formatter
if (msgContext.isDoingREST()) {
String httpMethod = (String) msgContext.getProperty(Constants.Configuration.HTTP_METHOD);
if (Constants.Configuration.HTTP_METHOD_GET.equals(httpMethod) ||
Constants.Configuration.HTTP_METHOD_DELETE.equals(httpMethod)) {
return new XFormURLEncodedFormatter();
}
return new ApplicationXMLFormatter();
} else {
// Lets default to SOAP formatter
//TODO need to improve this to use the stateless nature
messageFormatter = new SOAPMessageFormatter();
}
}
return messageFormatter;
}
private static String getMessageFormatterProperty(MessageContext msgContext) {
String messageFormatterProperty = null;
Object property = msgContext
.getProperty(Constants.Configuration.MESSAGE_TYPE);
if (property != null) {
messageFormatterProperty = (String) property;
}
if (messageFormatterProperty == null) {
Parameter parameter = msgContext
.getParameter(Constants.Configuration.MESSAGE_TYPE);
if (parameter != null) {
messageFormatterProperty = (String) parameter.getValue();
}
}
return messageFormatterProperty;
}
private static String getContentTypeForBuilderSelection(String type, MessageContext msgContext) {
/**
* Handle special case where content-type : text/xml and SOAPAction = null consider as
* POX (REST) message not SOAP 1.1.
*
* it's required use the Builder associate with "application/xml" here but should not
* change content type of current message.
*
*/
String cType = type;
if (msgContext.getSoapAction() == null && HTTPConstants.MEDIA_TYPE_TEXT_XML.equals(type) && msgContext.isDoingREST()) {
cType = HTTPConstants.MEDIA_TYPE_APPLICATION_XML;
}
return cType;
}
private static String getContentTypeForFormatterSelection(String type, MessageContext msgContext) {
/**
* Handle special case where content-type : text/xml and SOAPAction = null consider as
* POX (REST) message not SOAP 1.1.
*
* 1.) it's required use the Builder associate with "application/xml" here but should not
* change content type of current message.
*/
String cType = type;
if (msgContext.isDoingREST() && HTTPConstants.MEDIA_TYPE_TEXT_XML.equals(type)) {
cType = HTTPConstants.MEDIA_TYPE_APPLICATION_XML;
msgContext.setProperty(Constants.Configuration.CONTENT_TYPE, HTTPConstants.MEDIA_TYPE_TEXT_XML);
}
return cType;
}
}