1 package org.objectweb.celtix.bus.bindings.xml; 2 3 import java.io.*; 4 import java.util.*; 5 import java.util.logging.Level ; 6 import java.util.logging.Logger ; 7 8 import javax.jws.WebParam; 9 import javax.jws.soap.SOAPBinding.ParameterStyle; 10 import javax.jws.soap.SOAPBinding.Style; 11 import javax.wsdl.BindingInput; 12 import javax.wsdl.BindingOperation; 13 import javax.wsdl.BindingOutput; 14 import javax.wsdl.Port; 15 import javax.wsdl.WSDLException; 16 import javax.xml.namespace.QName ; 17 import javax.xml.ws.Holder; 18 import javax.xml.ws.WebFault; 19 import javax.xml.ws.WebServiceException; 20 import javax.xml.ws.handler.MessageContext; 21 22 import org.w3c.dom.*; 23 24 import org.objectweb.celtix.Bus; 25 import org.objectweb.celtix.bindings.AbstractBindingImpl; 26 import org.objectweb.celtix.bindings.DataBindingCallback; 27 import org.objectweb.celtix.bindings.DataReader; 28 import org.objectweb.celtix.bindings.DataWriter; 29 import org.objectweb.celtix.bindings.xmlformat.TBody; 30 import org.objectweb.celtix.bus.handlers.HandlerChainInvoker; 31 import org.objectweb.celtix.common.logging.LogUtils; 32 import org.objectweb.celtix.context.InputStreamMessageContext; 33 import org.objectweb.celtix.context.ObjectMessageContext; 34 import org.objectweb.celtix.context.OutputStreamMessageContext; 35 import org.objectweb.celtix.handlers.HandlerInvoker; 36 import org.objectweb.celtix.helpers.NodeUtils; 37 import org.objectweb.celtix.helpers.WSDLHelper; 38 import org.objectweb.celtix.helpers.XMLUtils; 39 import org.objectweb.celtix.ws.addressing.EndpointReferenceType; 40 import org.objectweb.celtix.wsdl.EndpointReferenceUtils; 41 42 public class XMLBindingImpl extends AbstractBindingImpl { 43 private static final Logger LOG = LogUtils.getL7dLogger(XMLBindingImpl.class); 44 protected final XMLMessageFactory msgFactory; 45 protected final boolean isServer; 46 private final XMLUtils xmlUtils = new XMLUtils(); 47 48 private Bus bus; 49 private EndpointReferenceType endpointRef; 50 51 public XMLBindingImpl(boolean server) { 52 isServer = server; 53 msgFactory = XMLMessageFactory.newInstance(); 54 } 55 56 public XMLBindingImpl(Bus b, EndpointReferenceType ert, boolean server) { 57 this(server); 58 this.bus = b; 59 this.endpointRef = ert; 60 } 61 62 public Bus getBus() { 63 return this.bus; 64 } 65 66 public EndpointReferenceType getEndpointReference() { 67 return this.endpointRef; 68 } 69 70 72 public MessageContext createBindingMessageContext(MessageContext srcCtx) { 73 return new XMLMessageContextImpl(srcCtx); 74 } 75 76 public HandlerInvoker createHandlerInvoker() { 77 return new HandlerChainInvoker(getHandlerChain(true)); 78 } 79 80 public XMLMessageFactory getMessageFactory() { 81 return this.msgFactory; 82 } 83 84 private XMLMessage initXMLMessage() { 85 return msgFactory.createMessage(); 86 } 87 88 public void marshal(ObjectMessageContext objContext, MessageContext mc, DataBindingCallback callback) { 89 try { 90 LOG.entering(getClass().getName(), "marshal"); 91 boolean isInputMsg = (Boolean )mc.get(ObjectMessageContext.MESSAGE_INPUT); 92 XMLMessage msg = initXMLMessage(); 93 LOG.log(Level.INFO, "XML_MARSHALLING_START", xmlUtils.toString(msg.getRoot())); 94 if (callback.getMode() == DataBindingCallback.Mode.PARTS) { 95 if (callback.getSOAPStyle() == Style.DOCUMENT 96 && callback.getSOAPParameterStyle() == ParameterStyle.BARE) { 97 if (isInputMsg) { 98 addReturnWrapperRoot(msg, callback); 99 LOG.log(Level.INFO, "XML_MARSHALLING_BARE_OUT", xmlUtils.toString(msg.getRoot())); 100 } else { 101 addWrapperRoot(msg, callback); 102 LOG.log(Level.INFO, "XML_MARSHALLING_BARE_IN", xmlUtils.toString(msg.getRoot())); 103 104 } 105 } 106 addParts(msg.getRoot(), objContext, isInputMsg, callback); 107 } else if (callback.getMode() == DataBindingCallback.Mode.MESSAGE) { 108 throw new XMLBindingException("Could not figure out how to marshal data"); 109 } else if (callback.getMode() == DataBindingCallback.Mode.PAYLOAD) { 110 throw new XMLBindingException("Could not figure out how to marshal data"); 111 } 112 LOG.log(Level.INFO, "XML_MARSHALLING_END", xmlUtils.toString(msg.getRoot())); 113 ((XMLMessageContext)mc).setMessage(msg); 114 LOG.exiting(getClass().getName(), "marshal", "XML binding Mashal OK"); 115 } catch (Exception e) { 116 LOG.log(Level.SEVERE, "XML_MARSHALLING_FAILURE_MSG", e); 117 throw new XMLBindingException("XML binding marshal exception ", e); 118 } 119 } 120 121 public void marshalFault(ObjectMessageContext objContext, 122 MessageContext mc, 123 DataBindingCallback callback) { 124 XMLMessage msg = null; 125 126 try { 127 msg = XMLMessageContext.class.isInstance(mc) && ((XMLMessageContext)mc).getMessage() != null 128 ? ((XMLMessageContext)mc).getMessage() : initXMLMessage(); 129 if (msg.hasChildNodes()) { 130 msg.removeContents(); 131 } 132 133 Throwable t = objContext.getException(); 134 135 XMLFault fault = msg.addFault(); 136 StringBuffer str = new StringBuffer (t.toString()); 138 if (!t.getClass().isAnnotationPresent(WebFault.class)) { 139 str.append("\n"); 140 for (StackTraceElement s : t.getStackTrace()) { 141 str.append(s.toString()); 142 str.append("\n"); 143 } 144 } 145 fault.addFaultString(str.toString()); 146 147 DataWriter<XMLFault> writer = callback.createWriter(XMLFault.class); 148 if (writer != null) { 149 writer.write(t, fault); 150 if (fault.getFaultDetail() != null && !fault.getFaultDetail().hasChildNodes()) { 151 fault.removeChild(fault.getFaultDetail()); 152 } 153 } 154 } catch (XMLBindingException se) { 155 LOG.log(Level.SEVERE, "FAULT_MARSHALLING_FAILURE_MSG", se); 156 } 158 ((XMLMessageContext)mc).setMessage(msg); 159 } 160 161 public void unmarshal(MessageContext mc, ObjectMessageContext objContext, DataBindingCallback callback) { 162 try { 163 LOG.entering(getClass().getName(), "unmarshal"); 164 165 boolean isOutputMsg = (Boolean )mc.get(ObjectMessageContext.MESSAGE_INPUT); 166 if (!XMLMessageContext.class.isInstance(mc)) { 167 throw new XMLBindingException("XMLMessageContext not available"); 168 } 169 170 XMLMessageContext xmlContext = XMLMessageContext.class.cast(mc); 171 XMLMessage xmlMessage = xmlContext.getMessage(); 172 173 if (callback.getMode() == DataBindingCallback.Mode.PARTS) { 174 Node root = xmlMessage.getRoot(); 175 LOG.log(Level.INFO, "XML_UNMARSHALLING_START", xmlUtils.toString(root)); 176 getParts(root, callback, objContext, isOutputMsg); 177 LOG.log(Level.INFO, "XML_UNMARSHALLING_END", xmlUtils.toString(root)); 178 } else if (callback.getMode() == DataBindingCallback.Mode.MESSAGE) { 179 throw new XMLBindingException("Could not figure out how to marshal data"); 180 } else if (callback.getMode() == DataBindingCallback.Mode.PAYLOAD) { 181 throw new XMLBindingException("Could not figure out how to marshal data"); 182 } 183 LOG.exiting(getClass().getName(), "unmarshal", "XML binding Unmashal OK"); 184 } catch (Exception e) { 185 LOG.log(Level.SEVERE, "XML_UNMARSHALLING_FAILURE_MSG", e); 186 throw new XMLBindingException("XML binding unmarshal exception", e); 187 } 188 } 189 190 public void unmarshalFault(MessageContext context, ObjectMessageContext objContext, 191 DataBindingCallback callback) { 192 try { 193 if (!XMLMessageContext.class.isInstance(context)) { 194 throw new XMLBindingException("XMLMessageContext not available"); 195 } 196 197 XMLMessageContext xmlContext = XMLMessageContext.class.cast(context); 198 XMLMessage xmlMessage = xmlContext.getMessage(); 199 200 XMLFault fault = xmlMessage.getFault(); 201 if (fault == null) { 202 fault = xmlMessage.addFault(); 203 fault.addFaultString("Unknow fault raised, the fault is null"); 204 } 205 DataReader<XMLFault> reader = callback.createReader(XMLFault.class); 206 207 if (reader == null) { 208 throw new WebServiceException("Could not unmarshal fault"); 209 } 210 Object faultObj = reader.read(null, 0, fault); 211 212 objContext.setException((Throwable )faultObj); 213 } catch (Exception se) { 214 LOG.log(Level.SEVERE, "XML_UNMARSHALLING_FAILURE_MSG", se); 215 throw new XMLBindingException("XML binding unmarshal fault exception", se); 216 } 217 } 218 219 public void write(MessageContext msgContext, OutputStreamMessageContext outContext) throws IOException { 220 XMLMessageContext xmlContext = (XMLMessageContext)msgContext; 221 try { 222 xmlContext.getMessage().writeTo(outContext.getOutputStream()); 223 224 if (LOG.isLoggable(Level.FINE)) { 225 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 226 xmlContext.getMessage().writeTo(baos); 227 LOG.log(Level.FINE, baos.toString()); 228 } 229 } catch (Exception e) { 230 LOG.log(Level.SEVERE, "XML_WRITE_FAILURE_MSG", e); 231 throw new XMLBindingException("XML binding write exception ", e); 232 } 233 } 234 235 public void read(InputStreamMessageContext inContext, MessageContext context) throws IOException { 236 if (!XMLMessageContext.class.isInstance(context)) { 237 throw new XMLBindingException("XMLMessageContext not available"); 238 } 239 try { 240 XMLMessageContext xmlContext = XMLMessageContext.class.cast(context); 241 xmlContext.setMessage(msgFactory.createMessage(inContext.getInputStream())); 242 } catch (Exception e) { 243 LOG.log(Level.SEVERE, "XML_READ_FAILURE_MSG", e); 244 throw new XMLBindingException("XML binding read exception ", e); 245 } 246 } 247 248 public boolean hasFault(MessageContext msgContext) { 249 XMLMessage msg = ((XMLMessageContext)msgContext).getMessage(); 250 assert msg != null; 251 return msg.hasFault(); 252 } 253 254 public void updateMessageContext(MessageContext msgContext) { 255 } 257 258 private void getParts(Node xmlNode, DataBindingCallback callback, ObjectMessageContext objCtx, 259 boolean isOutBound) throws XMLBindingException { 260 DataReader<Node> reader = null; 261 for (Class <?> cls : callback.getSupportedFormats()) { 262 if (cls == Node.class) { 263 reader = callback.createReader(Node.class); 264 break; 265 } 266 } 267 268 if (reader == null) { 269 throw new XMLBindingException("Could not figure out how to marshal data"); 270 } 271 if (callback.getSOAPStyle() == Style.DOCUMENT 272 && callback.getSOAPParameterStyle() == ParameterStyle.WRAPPED) { 273 reader.readWrapper(objCtx, isOutBound, xmlNode); 274 return; 275 } 276 277 Node childNode = NodeUtils.getChildElementNode(xmlNode); 278 279 if (isOutBound && callback.getWebResult() != null) { 280 Object retVal = reader.read(callback.getWebResultQName(), -1, childNode); 281 objCtx.setReturn(retVal); 282 childNode = childNode.getNextSibling(); 283 } 284 285 WebParam.Mode ignoreParamMode = isOutBound ? WebParam.Mode.IN : WebParam.Mode.OUT; 286 int noArgs = callback.getParamsLength(); 287 Object [] methodArgs = objCtx.getMessageObjects(); 288 289 for (int idx = 0; idx < noArgs; idx++) { 290 WebParam param = callback.getWebParam(idx); 291 if (param.mode() != ignoreParamMode) { 292 QName elName = (callback.getSOAPStyle() == Style.DOCUMENT) 293 ? new QName (param.targetNamespace(), param.name()) 294 : new QName ("", param.partName()); 295 296 Object obj = reader.read(elName, idx, childNode); 297 if (param.mode() != WebParam.Mode.IN) { 298 try { 299 methodArgs[idx].getClass().getField("value").set(methodArgs[idx], obj); 302 } catch (Exception ex) { 303 throw new XMLBindingException("Can not set the part value into the Holder field.", 304 ex); 305 } 306 } else { 307 methodArgs[idx] = obj; 308 } 309 childNode = childNode.getNextSibling(); 310 } 311 } 312 } 313 314 private void addWrapperRoot(XMLMessage xmlMessage, DataBindingCallback callback) throws WSDLException { 315 BindingOperation operation = getBindingOperation(callback.getOperationName()); 316 317 BindingInput input = operation.getBindingInput(); 318 319 TBody xmlBinding = null; 320 Iterator ite = input.getExtensibilityElements().iterator(); 321 while (ite.hasNext()) { 322 Object obj = ite.next(); 323 if (obj instanceof TBody) { 324 xmlBinding = (TBody)obj; 325 } 326 } 327 328 if (needRootNode(operation, false)) { 329 if (xmlBinding == null || xmlBinding.getRootNode() == null) { 330 throw new XMLBindingException("Bare style must define the rootNode in this case!"); 331 } 332 QName rootNode = xmlBinding.getRootNode(); 333 Document doc = xmlMessage.getRoot(); 334 String targetNamespace = rootNode.getNamespaceURI() == null 335 ? callback.getTargetNamespace() : rootNode.getNamespaceURI(); 336 Element operationNode = doc.createElementNS(targetNamespace, rootNode.getLocalPart()); 337 xmlMessage.appendChild(operationNode); 338 } 339 } 340 341 private void addReturnWrapperRoot(XMLMessage xmlMessage, 342 DataBindingCallback callback) throws WSDLException { 343 BindingOperation operation = getBindingOperation(callback.getOperationName()); 344 345 BindingOutput output = operation.getBindingOutput(); 346 TBody xmlBinding = null; 347 Iterator ite = output.getExtensibilityElements().iterator(); 348 while (ite.hasNext()) { 349 Object obj = ite.next(); 350 if (obj instanceof TBody) { 351 xmlBinding = (TBody)obj; 352 } 353 } 354 if (needRootNode(operation, true)) { 355 if (xmlBinding == null || xmlBinding.getRootNode() == null) { 356 throw new XMLBindingException("Bare style must define the rootNode in this case!"); 357 } 358 QName rootNode = xmlBinding.getRootNode(); 359 Document doc = xmlMessage.getRoot(); 360 String targetNamespace = rootNode.getNamespaceURI() == null 361 ? callback.getTargetNamespace() : rootNode.getNamespaceURI(); 362 Element operationNode = doc.createElementNS(targetNamespace, rootNode.getLocalPart()); 363 xmlMessage.appendChild(operationNode); 364 } 365 } 366 367 private BindingOperation getBindingOperation(String operationName) throws WSDLException { 368 WSDLHelper helper = new WSDLHelper(); 369 Port port = EndpointReferenceUtils.getPort(this.bus.getWSDLManager(), this.endpointRef); 370 return helper.getBindingOperation(port.getBinding(), 371 operationName); 372 } 373 374 private boolean needRootNode(BindingOperation operation, boolean out) { 375 WSDLHelper helper = new WSDLHelper(); 376 Map parts = helper.getParts(operation.getOperation(), out); 377 return parts.size() != 1; 378 } 379 380 private void addParts(Node xmlNode, 381 ObjectMessageContext objCtx, 382 boolean isOutBound, 383 DataBindingCallback callback) { 384 DataWriter<Node> writer = callback.createWriter(Node.class); 385 if (writer == null) { 386 throw new XMLBindingException("Could not figure out how to marshal data"); 387 } 388 389 if (callback.getSOAPStyle() == Style.DOCUMENT 390 && callback.getSOAPParameterStyle() == ParameterStyle.WRAPPED) { 391 writer.writeWrapper(objCtx, isOutBound, xmlNode); 392 return; 393 } 394 395 if (isOutBound && callback.getWebResult() != null) { 397 writer.write(objCtx.getReturn(), callback.getWebResultQName(), xmlNode); 398 } 399 WebParam.Mode ignoreParamMode = isOutBound ? WebParam.Mode.IN : WebParam.Mode.OUT; 401 int noArgs = callback.getParamsLength(); 402 Object [] args = objCtx.getMessageObjects(); 403 for (int idx = 0; idx < noArgs; idx++) { 404 WebParam param = callback.getWebParam(idx); 405 if (param.mode() != ignoreParamMode) { 406 Object partValue = args[idx]; 407 if (param.mode() != WebParam.Mode.IN) { 408 partValue = ((Holder)args[idx]).value; 409 } 410 411 QName elName = (callback.getSOAPStyle() == Style.DOCUMENT) 412 ? new QName (param.targetNamespace(), param.name()) 413 : new QName ("", param.partName()); 414 writer.write(partValue, elName, xmlNode); 415 } 416 } 417 } 418 } 419 | Popular Tags |