View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2006 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  package ch.elca.el4j.services.remoting.protocol.jaxws;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  import java.util.Set;
22  import java.util.TreeSet;
23  
24  import javax.xml.bind.JAXBContext;
25  import javax.xml.bind.JAXBElement;
26  import javax.xml.bind.JAXBException;
27  import javax.xml.bind.Marshaller;
28  import javax.xml.bind.PropertyException;
29  import javax.xml.bind.Unmarshaller;
30  import javax.xml.namespace.QName;
31  import javax.xml.soap.SOAPHeaderElement;
32  import javax.xml.soap.SOAPMessage;
33  import javax.xml.ws.handler.MessageContext;
34  import javax.xml.ws.handler.soap.SOAPMessageContext;
35  
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  import org.w3c.dom.Node;
39  import org.w3c.dom.NodeList;
40  
41  import com.sun.xml.ws.util.xml.NodeListIterator;
42  
43  import ch.elca.el4j.core.contextpassing.ImplicitContextPassingRegistry;
44  
45  /**
46   * This class is a JAX-WS Handler that injects the implicit context while
47   * sending a SOAP message and extract it while retrieving one.
48   *
49   * @svnLink $Revision: 4077 $;$Date: 2010-01-06 16:18:36 +0100 (Mi, 06. Jan 2010) $;$Author: swisswheel $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/remoting_jaxws/src/main/java/ch/elca/el4j/services/remoting/protocol/jaxws/JaxwsContextHandler.java $
50   *
51   * @author Stefan Wismer (SWI)
52   */
53  public class JaxwsContextHandler extends AbstractJaxwsJaxbContextHandler {
54  	/**
55  	 * Private logger.
56  	 */
57  	private static Logger s_logger = LoggerFactory.getLogger(JaxwsContextHandler.class);
58  	
59  	/**
60  	 * The registry to get the context from.
61  	 */
62  	private ImplicitContextPassingRegistry m_contextPassingRegistry;
63  	
64  	
65  	/**
66  	 * Create a new JAX-WS Handler to modify a soap message.
67  	 *
68  	 * @param registry The registry to take the context from
69  	 * @param jaxbContext The context to serialize the implicit context with
70  	 */
71  	public JaxwsContextHandler(ImplicitContextPassingRegistry registry,
72  		JAXBContext jaxbContext) {
73  		super(jaxbContext);
74  		m_contextPassingRegistry = registry;
75  	}
76  
77  	/** {@inheritDoc} */
78  	public boolean handleMessage(SOAPMessageContext context) {
79  		Boolean outboundProperty = (Boolean) context
80  			.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
81  
82  		if (m_contextPassingRegistry != null) {
83  			SOAPMessage msg = context.getMessage();
84  			if (outboundProperty.booleanValue()) {
85  				handleOutgoingMessage(msg);
86  			} else {
87  				handleIncomingMessage(msg);
88  			}
89  		}
90  		return true;
91  	}
92  
93  	/**
94  	 * Handles an incoming SOAP message.
95  	 * Adds the implicit context to the SOAP header.
96  	 *
97  	 * @param msg    the SOAP message
98  	 */
99  	@SuppressWarnings("unchecked")
100 	protected void handleIncomingMessage(SOAPMessage msg) {
101 		Node contextElement = null;
102 		try {
103 			if (msg.getSOAPHeader() != null) {
104 				NodeList list = msg.getSOAPHeader()
105 					.getElementsByTagNameNS(CONTEXT_NAMESPACE.getURI(),
106 						CONTEXT_ELEMENT_NAME);
107 				if (list.getLength() > 0) {
108 					contextElement = (Node) list.item(0);
109 				}
110 			}
111 		} catch (Exception e) {
112 			s_logger.error("Error getting SOAP header.");
113 			return;
114 		}
115 
116 		if (contextElement != null) {
117 			Unmarshaller unmarshaller = getUnmarshaller();
118 
119 			Map<String, Object> map = new HashMap<String, Object>();
120 			NodeList nodeList = contextElement.getChildNodes();
121 			NodeListIterator it = new NodeListIterator(nodeList);
122 
123 			while (it.hasNext()) {
124 				Node soapNode = (Node) it.next();
125 
126 				try {
127 					// Try to get the passed Object out of the xml
128 					JAXBElement element = (JAXBElement) unmarshaller
129 						.unmarshal(soapNode);
130 
131 					map.put(soapNode.getNodeName(), element.getValue());
132 				} catch (JAXBException e) {
133 					s_logger.error("Unable to unmarshall context element "
134 						+ soapNode.getNodeName());
135 				}
136 			}
137 			m_contextPassingRegistry.pushAssembledImplicitContext(map);
138 		}
139 	}
140 
141 	/**
142 	 * Handles an outgoing SOAP message.
143 	 * Extracts the implicit context from the SOAP header.
144 	 *
145 	 * @param msg    the SOAP message
146 	 */
147 	@SuppressWarnings("unchecked")
148 	protected void handleOutgoingMessage(SOAPMessage msg) {
149 		SOAPHeaderElement newElement = null;
150 
151 		try {
152 			if (msg.getSOAPHeader() == null) {
153 				// create header
154 				msg.getSOAPPart().getEnvelope().addHeader();
155 			}
156 			newElement = msg.getSOAPHeader().addHeaderElement(
157 				new QName(CONTEXT_NAMESPACE.getURI(),
158 					CONTEXT_ELEMENT_NAME));
159 		} catch (Exception e) {
160 			s_logger.error("Error creating SOAP header.");
161 			return;
162 		}
163 
164 		Marshaller marshaller = getMarshaller();
165 		try {
166 			marshaller.setProperty(Marshaller.JAXB_FRAGMENT,
167 				Boolean.TRUE);
168 		} catch (PropertyException e) {
169 			s_logger.error("Error setting marshaller properties.");
170 			return;
171 		}
172 
173 		Map assembledContext = m_contextPassingRegistry
174 			.getAssembledImplicitContext();
175 		Set<String> keys = (Set<String>) assembledContext.keySet();
176 		for (String key : keys) {
177 			try {
178 				Object value = assembledContext.get(key);
179 				marshaller.marshal(new JAXBElement(new QName("", key),
180 					Object.class, value), newElement);
181 			} catch (JAXBException e) {
182 				s_logger.error("Unable to marshal context for " + key);
183 			}
184 		}
185 	}
186 
187 	/** {@inheritDoc} */
188 	public boolean handleFault(SOAPMessageContext context) {
189 		return true;
190 	}
191 
192 	/** {@inheritDoc} */
193 	@SuppressWarnings("unchecked")
194 	public Set getHeaders() {
195 		return new TreeSet();
196 	}
197 
198 	/** {@inheritDoc} */
199 	public void close(MessageContext context) { }
200 
201 
202 	/** {@inheritDoc} */
203 	@Override
204 	protected Logger getLogger() {
205 		return s_logger;
206 	}
207 }