/**
* 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.cxf.jaxws.support;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.activation.DataHandler;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.MessageContext.Scope;
import org.apache.cxf.attachment.AttachmentImpl;
import org.apache.cxf.attachment.LazyAttachmentCollection;
import org.apache.cxf.binding.soap.SoapBindingConstants;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.jaxws.context.WrappedMessageContext;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
// Do some context mapping work from rt-core to jaxws standard.
// NOTE if there are changes in cxf Message property names, this
// class should be updated.
public final class ContextPropertiesMapping {
private static Map<String, String> cxf2jaxwsMap = new HashMap<String, String>();
private static Map<String, String> jaxws2cxfMap = new HashMap<String, String>();
static {
cxf2jaxwsMap.put(Message.ENDPOINT_ADDRESS,
BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
cxf2jaxwsMap.put(Message.MAINTAIN_SESSION,
BindingProvider.SESSION_MAINTAIN_PROPERTY);
cxf2jaxwsMap.put(Message.HTTP_REQUEST_METHOD,
MessageContext.HTTP_REQUEST_METHOD);
cxf2jaxwsMap.put(Message.RESPONSE_CODE,
MessageContext.HTTP_RESPONSE_CODE);
cxf2jaxwsMap.put(Message.PATH_INFO,
MessageContext.PATH_INFO);
cxf2jaxwsMap.put(Message.QUERY_STRING,
MessageContext.QUERY_STRING);
cxf2jaxwsMap.put("HTTP.REQUEST",
MessageContext.SERVLET_REQUEST);
cxf2jaxwsMap.put("HTTP.RESPONSE",
MessageContext.SERVLET_RESPONSE);
cxf2jaxwsMap.put("HTTP.CONTEXT",
MessageContext.SERVLET_CONTEXT);
jaxws2cxfMap.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
Message.ENDPOINT_ADDRESS);
jaxws2cxfMap.put(BindingProvider.SESSION_MAINTAIN_PROPERTY,
Message.MAINTAIN_SESSION);
jaxws2cxfMap.put(MessageContext.HTTP_REQUEST_METHOD,
Message.HTTP_REQUEST_METHOD);
jaxws2cxfMap.put(MessageContext.HTTP_RESPONSE_CODE,
Message.RESPONSE_CODE);
jaxws2cxfMap.put(MessageContext.PATH_INFO,
Message.PATH_INFO);
jaxws2cxfMap.put(MessageContext.QUERY_STRING,
Message.QUERY_STRING);
jaxws2cxfMap.put(MessageContext.SERVLET_REQUEST,
"HTTP.REQUEST");
jaxws2cxfMap.put(MessageContext.SERVLET_RESPONSE,
"HTTP.RESPONSE");
jaxws2cxfMap.put(MessageContext.SERVLET_CONTEXT,
"HTTP.CONTEXT");
jaxws2cxfMap.put(BindingProvider.SOAPACTION_URI_PROPERTY, SoapBindingConstants.SOAP_ACTION);
}
private ContextPropertiesMapping() {
}
private static void mapContext(Map<String, Object> context, Map<String, String> map) {
for (Map.Entry<String, String> entry : map.entrySet()) {
Object o = context.get(entry.getKey());
if (o != null) {
context.put(entry.getValue(), o);
}
}
}
public static void mapRequestfromJaxws2Cxf(Map<String, Object> context) {
//deal with PROTOCOL_HEADERS mapping
Object requestHeaders =
context.get(MessageContext.HTTP_REQUEST_HEADERS);
if (null != requestHeaders) {
context.put(Message.PROTOCOL_HEADERS, requestHeaders);
}
mapJaxws2Cxf(context);
}
public static void mapResponsefromCxf2Jaxws(Map<String, Object> context) {
//deal with PROTOCOL_HEADERS mapping
Object responseHeaders =
context.get(Message.PROTOCOL_HEADERS);
if (null != responseHeaders) {
context.put(MessageContext.HTTP_RESPONSE_HEADERS, responseHeaders);
}
mapContext(context, cxf2jaxwsMap);
Collection<Attachment> attachments
= CastUtils.cast((Collection<?>)context.get(Message.ATTACHMENTS));
Map<String, DataHandler> dataHandlers = getDHMap(attachments);
context.put(MessageContext.INBOUND_MESSAGE_ATTACHMENTS, dataHandlers);
Map<String, Scope> scopes = CastUtils.cast((Map<?, ?>)context.get(WrappedMessageContext.SCOPES));
if (scopes != null) {
scopes.put(MessageContext.INBOUND_MESSAGE_ATTACHMENTS, Scope.APPLICATION);
}
}
private static void mapJaxws2Cxf(Map<String, Object> context) {
mapContext(context, jaxws2cxfMap);
if (context.containsKey(BindingProvider.USERNAME_PROPERTY)) {
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setUserName((String)context.get(BindingProvider.USERNAME_PROPERTY));
authPolicy.setPassword((String)context.get(BindingProvider.PASSWORD_PROPERTY));
context.put(AuthorizationPolicy.class.getName(), authPolicy);
}
}
private static void mapCxf2Jaxws(WrappedMessageContext context) {
for (Map.Entry<String, String> entry : cxf2jaxwsMap.entrySet()) {
Object o = context.get(entry.getKey());
if (o != null) {
context.put(entry.getValue(), o, Scope.APPLICATION);
} else if (context.containsKey(entry.getValue())) {
context.put(entry.getValue(),
context.get(entry.getValue()), Scope.APPLICATION);
}
}
if (context.containsKey(AuthorizationPolicy.class.getName())) {
AuthorizationPolicy authPolicy =
(AuthorizationPolicy)context.get(AuthorizationPolicy.class.getName());
context.put(BindingProvider.USERNAME_PROPERTY, authPolicy.getUserName(), Scope.APPLICATION);
context.put(BindingProvider.PASSWORD_PROPERTY, authPolicy.getPassword(), Scope.APPLICATION);
}
}
public static MessageContext createWebServiceContext(Exchange exchange) {
WrappedMessageContext ctx = new WrappedMessageContext(exchange.getInMessage(), Scope.APPLICATION);
mapCxf2Jaxws(exchange, ctx, false);
return ctx;
}
public static void mapCxf2Jaxws(Exchange exchange, WrappedMessageContext ctx, boolean requestor) {
ctx.put(Message.WSDL_DESCRIPTION, exchange.get(Message.WSDL_DESCRIPTION));
ctx.put(Message.WSDL_INTERFACE, exchange.get(Message.WSDL_INTERFACE));
ctx.put(Message.WSDL_OPERATION, exchange.get(Message.WSDL_OPERATION));
ctx.put(Message.WSDL_PORT, exchange.get(Message.WSDL_PORT));
ctx.put(Message.WSDL_SERVICE, exchange.get(Message.WSDL_SERVICE));
mapCxf2Jaxws(ctx);
Message inMessage = exchange.getInMessage();
Message outMessage = exchange.getOutMessage();
if (inMessage == null
&& Boolean.TRUE.equals(ctx.get(Message.INBOUND_MESSAGE))) {
//inbound partial responses and stuff are not set in the exchange
inMessage = ctx.getWrappedMessage();
}
if (inMessage != null) {
addMessageAttachments(ctx,
inMessage,
MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
Object inHeaders =
inMessage.get(Message.PROTOCOL_HEADERS);
if (null != inHeaders) {
if (requestor) {
ctx.put(MessageContext.HTTP_RESPONSE_HEADERS,
inHeaders,
Scope.APPLICATION);
} else {
ctx.put(MessageContext.HTTP_REQUEST_HEADERS,
inHeaders,
Scope.APPLICATION);
}
outMessage = exchange.getOutMessage();
if (outMessage == null) {
Endpoint ep = exchange.get(Endpoint.class);
outMessage = ep.getBinding().createMessage();
exchange.setOutMessage(outMessage);
}
}
}
if (outMessage != null) {
addMessageAttachments(ctx,
outMessage,
MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
Object outHeaders =
outMessage.get(Message.PROTOCOL_HEADERS);
if (outHeaders != null && !requestor) {
ctx.put(MessageContext.HTTP_REQUEST_HEADERS,
outHeaders,
Scope.APPLICATION);
}
}
}
private static Map<String, DataHandler> getDHMap(Collection<Attachment> attachments) {
Map<String, DataHandler> dataHandlers = null;
if (attachments != null) {
if (attachments instanceof LazyAttachmentCollection) {
dataHandlers = ((LazyAttachmentCollection)attachments).createDataHandlerMap();
} else {
//preserve the order of iteration
dataHandlers = new LinkedHashMap<String, DataHandler>();
for (Attachment attachment : attachments) {
dataHandlers.put(attachment.getId(), attachment.getDataHandler());
}
}
}
return dataHandlers;
}
private static void addMessageAttachments(WrappedMessageContext ctx,
Message message,
String propertyName) {
Collection<Attachment> attachments = message.getAttachments();
Map<String, DataHandler> dataHandlers = getDHMap(attachments);
ctx.put(propertyName,
dataHandlers == null ? new LinkedHashMap<String, DataHandler>()
: dataHandlers,
Scope.APPLICATION);
}
public static void updateWebServiceContext(Exchange exchange, MessageContext ctx) {
//get the context response code and setback to out message
if (ctx.containsKey(MessageContext.HTTP_RESPONSE_CODE)) {
exchange.getOutMessage().put(Message.RESPONSE_CODE, ctx.get(MessageContext.HTTP_RESPONSE_CODE));
}
// Guard against wrong type associated with header list.
// Need to copy header only if the message is going out.
if (ctx.containsKey(Header.HEADER_LIST)
&& ctx.get(Header.HEADER_LIST) instanceof List<?>
&& exchange.getOutMessage() instanceof SoapMessage) {
SoapMessage sm = (SoapMessage) exchange.getOutMessage();
Iterator iter = ((List) ctx.get(Header.HEADER_LIST)).iterator();
while (iter.hasNext()) {
sm.getHeaders().add((Header) iter.next());
}
}
if (ctx.containsKey(MessageContext.HTTP_RESPONSE_HEADERS)) {
Map<String, List<String>> other = CastUtils
.cast((Map<?, ?>)ctx.get(MessageContext.HTTP_RESPONSE_HEADERS));
Map<String, List<String>> heads = CastUtils
.cast((Map<?, ?>)exchange.getOutMessage().get(Message.PROTOCOL_HEADERS));
if (heads != null) {
heads.putAll(other);
} else if (!other.isEmpty()) {
exchange.getOutMessage().put(Message.PROTOCOL_HEADERS,
ctx.get(MessageContext.HTTP_RESPONSE_HEADERS));
heads = other;
}
if (heads.containsKey("Content-Type")) {
List<String> ct = heads.get("Content-Type");
exchange.getOutMessage().put(Message.CONTENT_TYPE, ct.get(0));
heads.remove("Content-Type");
}
}
Map<String, DataHandler> dataHandlers
= CastUtils.cast((Map<?, ?>)ctx.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS));
if (dataHandlers != null && !dataHandlers.isEmpty()) {
Collection<Attachment> attachments = exchange.getOutMessage().getAttachments();
if (attachments == null) {
attachments = new ArrayList<Attachment>();
exchange.getOutMessage().setAttachments(attachments);
}
for (Map.Entry<String, DataHandler> entry : dataHandlers.entrySet()) {
Attachment att = new AttachmentImpl(entry.getKey(), entry.getValue());
attachments.add(att);
}
}
}
}