1 4 5 9 10 package org.openlaszlo.remote.soap; 11 12 import org.openlaszlo.iv.flash.api.action.Program; 13 import org.openlaszlo.remote.soap.encoding.SWFSimpleDeserializerFactory; 14 import org.openlaszlo.remote.soap.encoding.SWFObjectDeserializerFactory; 15 import org.openlaszlo.remote.soap.encoding.LZObjectSerializerFactory; 16 import org.openlaszlo.server.LPS; 17 import java.io.IOException ; 18 import java.net.URLDecoder ; 19 import java.rmi.RemoteException ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.ArrayList ; 23 import java.util.Hashtable ; 24 import java.util.Map ; 25 import javax.xml.namespace.QName ; 26 import javax.xml.rpc.JAXRPCException ; 27 import javax.xml.soap.SOAPHeader ; 28 import org.apache.axis.AxisFault; 29 import org.apache.axis.client.Service; 30 import org.apache.axis.client.Call; 31 import javax.xml.rpc.ServiceException ; 32 import javax.xml.rpc.encoding.DeserializerFactory ; 33 import javax.xml.rpc.encoding.SerializerFactory ; 34 import javax.xml.rpc.encoding.TypeMappingRegistry ; 35 import javax.xml.rpc.encoding.TypeMapping ; 36 import javax.xml.rpc.handler.HandlerInfo ; 37 import javax.xml.rpc.handler.HandlerRegistry ; 38 import javax.xml.soap.SOAPException ; 39 import org.apache.axis.Constants; 40 import org.apache.axis.message.SOAPBodyElement; 41 import org.apache.axis.message.SOAPHeaderElement; 42 import org.apache.log4j.Logger; 43 import org.w3c.dom.DOMException ; 44 import org.w3c.dom.Element ; 45 import org.w3c.dom.Node ; 46 import org.w3c.dom.NodeList ; 47 import org.w3c.dom.Text ; 48 import org.xml.sax.SAXException ; 49 50 public class LZSOAPService 51 { 52 private static Logger mLogger = Logger.getLogger(LZSOAPService.class); 53 54 String mServiceName; 55 String mPort; 56 String mEndpointAddress; 57 String mTransport; 58 String mTargetNS; 59 String mXMLSchemaNS; 60 String mSOAPEncodingNS; 61 Service mService; 62 TypeMappingRegistry mTypeMappingRegistry; 63 HandlerRegistry mHandlerRegistry; 64 TypeMapping mDefaultTypeMapping; 65 TypeMapping mDefaultSOAPEncodingTypeMapping; 66 67 68 String mWSDL; 69 70 72 Hashtable mClientSOAPServiceMap = new Hashtable (); 73 74 75 Map mOperations = null; 76 77 78 Map mSchemaComplexTypes = null; 79 80 81 82 83 DeserializerFactory mSWFObjectDeserializerFactory = 84 new SWFObjectDeserializerFactory(); 85 SerializerFactory mObjectSerializerFactory = new LZObjectSerializerFactory(); 86 87 public LZSOAPService(String wsdl, String serviceName, String port, 88 String endpointAddress, String transport, 89 String targetNS, String xmlSchemaNS, 90 String soapEncodingNS) 91 throws ServiceException { 92 93 mWSDL = wsdl; 94 mServiceName = serviceName; 95 mPort = port; 96 mEndpointAddress = endpointAddress; 97 mTransport = transport; 98 mTargetNS = targetNS; 99 mXMLSchemaNS = xmlSchemaNS; 100 mSOAPEncodingNS = soapEncodingNS; 101 102 mService = new Service(new QName (mTargetNS, mServiceName)); 103 104 mTypeMappingRegistry = mService.getTypeMappingRegistry(); 105 mHandlerRegistry = mService.getHandlerRegistry(); 106 107 getHandlerChain().add(new HandlerInfo (LZSOAPHandler.class, null, null)); 108 109 mDefaultTypeMapping = LZDefaultTypeMapping.getSingleton(); 111 mDefaultSOAPEncodingTypeMapping = new LZDefaultSOAPEncodingTypeMapping(); 112 mTypeMappingRegistry.registerDefault(mDefaultTypeMapping); 113 mTypeMappingRegistry.register(Constants.URI_SOAP11_ENC, mDefaultSOAPEncodingTypeMapping); 114 } 115 116 117 public synchronized byte[] createClientSOAPService(String swfversion, int swfnum) 118 throws ServiceException { 119 byte[] swfobj = (byte[])mClientSOAPServiceMap.get(swfversion); 120 if (swfobj == null) { 121 try { 122 swfobj = ClientSOAPService.createObject(this, swfnum); 123 mClientSOAPServiceMap.put(swfversion, swfobj); 124 } catch (IOException e) { 125 throw new ServiceException ("could not create client SOAP service object"); 126 } 127 } 128 return swfobj; 129 } 130 131 134 public byte[] getClientSOAPService(int swfnum) 135 throws ServiceException { 136 String swfversion = LPS.getSWFVersion(swfnum); 137 byte[] swfobj = (byte[])mClientSOAPServiceMap.get(swfversion); 138 if (swfobj == null) swfobj = createClientSOAPService(swfversion, swfnum); 139 return swfobj; 140 } 141 142 183 public Object [] invoke(String operation, String xml) 184 throws AxisFault, ServiceException , RemoteException { 185 186 mLogger.debug("invoke()"); 187 188 try { 189 Element envelope = LZSOAPUtils.xmlStringToElement(xml); 190 191 Element body = LZSOAPUtils.getFirstElementByTagName(envelope, "b"); 192 Element paramsEl = LZSOAPUtils.getFirstElementByTagName(body, "params"); 193 194 Object [] callArr = createCall(operation, paramsEl); 195 Call call = (Call)callArr[0]; 196 Object [] params = (Object [])callArr[1]; 197 198 Element header = LZSOAPUtils.getFirstElementByTagName(envelope, "h"); 199 NodeList headerNodes = header.getChildNodes(); 200 for (int i=0; i < headerNodes.getLength(); i++) { 201 Node headerNode = (Node )headerNodes.item(i); 202 if (headerNode.getNodeType() != Node.ELEMENT_NODE) continue; 203 call.addHeader(new SOAPHeaderElement((Element)headerNode)); 204 } 205 206 Object returnValue = call.invoke(params); 208 209 SOAPHeader responseHeader = 211 call.getResponseMessage().getSOAPEnvelope().getHeader(); 212 213 LZSOAPOperation op = (LZSOAPOperation)mOperations.get(operation); 214 return new Object []{ op.getStyle(), returnValue, responseHeader }; 215 216 } catch (AxisFault e) { 217 mLogger.error("AxisFault"); 218 throw e; 219 } catch (IOException e) { 220 mLogger.error("IOException", e); 221 throw new ServiceException (e.getMessage()); 222 } catch (org.xml.sax.SAXException e) { 223 mLogger.error("SAXException:", e); 224 throw new ServiceException (e.getMessage()); 225 } catch (SOAPException e) { 226 mLogger.error("SOAPException", e); 227 throw new ServiceException (e.getMessage()); 228 } 229 230 } 231 232 Node getParamValue(Element param) { 233 NodeList list = param.getChildNodes(); 234 int len = list.getLength(); 235 if (len == 0) { 236 return null; 237 } 238 239 for (int i=0; i < list.getLength(); i++) { 241 Node node = list.item(i); 242 if (node.getNodeType() == Node.ELEMENT_NODE) { 243 return param; 244 } 245 } 246 247 return list.item(0); 248 } 249 250 251 254 public boolean isTextNode(Node paramNode) { 255 return (paramNode == null || paramNode.getNodeType() == Node.TEXT_NODE); 256 } 257 258 261 public boolean isElementNode(Node paramNode) { 262 return (paramNode.getNodeType() == Node.ELEMENT_NODE); 263 } 264 265 268 public List setRPCParams(Call call, NodeList paramsList, List parts, 269 LZSOAPOperation op) 270 throws ServiceException , IOException , SAXException , DOMException { 271 272 if (mLogger.isDebugEnabled()) { 273 mLogger.debug("setRPCParams"); 274 } 275 276 int pos = 0; List params = new ArrayList (); 278 for (int i=0; i < paramsList.getLength(); i++) { 279 280 Node node = (Node )paramsList.item(i); 281 if (node.getNodeType() != Node.ELEMENT_NODE) continue; 282 283 Element p = (Element)node; 284 Node paramNode = getParamValue(p); 285 286 LZSOAPPart part = (LZSOAPPart)parts.get(pos); 287 ComplexType type = part.getType(); 288 289 if (type.isArray()) { 290 291 if (! isElementNode(paramNode)) { 292 throw new ServiceException ("parameter " + (pos+1) + 293 " should an array"); 294 } 295 296 call.addParameter(part.getName(), type.getBase().getName(), 297 ArrayList .class, part.getParameterMode()); 298 299 ArrayWrapper aw = new ArrayWrapper((Element)paramNode, type); 300 ArrayList list = new ArrayList (); 301 list.add(aw); 302 params.add(list); 303 if (mLogger.isDebugEnabled()) { 304 mLogger.debug("array param: " + aw); 305 } 306 307 } else { 308 309 call.addParameter(part.getName(), type.getName(), 310 part.getParameterMode()); 311 312 if (isTextNode(paramNode)) { Text text = (Text )paramNode; 314 String strValue = (text != null ? text.getData() : ""); 315 params.add(((LZSOAPPart)parts.get(pos)).valueOf(strValue)); 316 if (mLogger.isDebugEnabled()) { 317 mLogger.debug("primitive param: " + strValue); 318 } 319 320 } else if (isElementNode(paramNode)) { ObjectWrapper ow = new ObjectWrapper((Element)paramNode); 322 params.add(ow); 323 if (mLogger.isDebugEnabled()) { 324 mLogger.debug("object param: " + ow); 325 } 326 327 } else { 328 throw new ServiceException ("bad parameter " + (pos+1) + 329 ": " + paramNode); 330 } 331 332 } 333 334 ++pos; 335 } 336 337 if (params.size() != parts.size()) { 338 throw new ServiceException ("wrong number of params"); 339 } 340 341 parts = op.getOutputMessage().getParts(); 343 if (parts.size() != 1) { 344 throw new ServiceException ("no support more than one return value"); 345 } 346 347 LZSOAPPart part = (LZSOAPPart)parts.get(0); 348 ComplexType type = part.getType(); 349 if (type != null) { 350 call.setReturnType(type.getName()); 351 } else { 352 mLogger.warn("type of return unspecified"); 353 } 354 355 return params; 356 } 357 358 361 public List setDocumentParams(Call call, NodeList paramsList, List parts, 362 LZSOAPOperation op) 363 throws ServiceException , IOException , SAXException , DOMException { 364 365 if (mLogger.isDebugEnabled()) { 366 mLogger.debug("setDocumentParams"); 367 } 368 369 call.setProperty(Call.OPERATION_STYLE_PROPERTY, "document"); 370 call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean (true)); 371 call.setProperty(Call.SOAPACTION_URI_PROPERTY, op.getSoapAction()); 372 373 List params = new ArrayList (); 374 for (int i=0; i < paramsList.getLength(); i++) { 375 376 Node node = (Node )paramsList.item(i); 377 if (node.getNodeType() != Node.ELEMENT_NODE) continue; 378 379 Element p = (Element)node; 380 381 Text text = (Text )p.getFirstChild(); 383 String data = URLDecoder.decode(text.getData()); 384 Element docElement = LZSOAPUtils.xmlStringToElement(data); 385 params.add(new SOAPBodyElement(docElement)); 386 387 } 388 389 return params; 390 } 391 392 397 public Object [] createCall(String operation, Element paramsEl) throws ServiceException { 398 LZSOAPOperation op = (LZSOAPOperation)mOperations.get(operation); 399 if (op == null) { 400 throw new ServiceException ("could not find operation named " + 401 operation); 402 } 403 404 try { 405 Call call = (org.apache.axis.client.Call) 406 mService.createCall(new QName (mTargetNS, mPort)); 407 call.setOperationName(new QName (mTargetNS, op.getName())); 408 call.setTargetEndpointAddress(mEndpointAddress); 409 410 NodeList paramsList = paramsEl.getChildNodes(); 411 List parts = op.getInputMessage().getParts(); 412 413 List params = null; 414 if (op.getStyle().equals("document")) 415 params = setDocumentParams(call, paramsList, parts, op); 416 else 417 params = setRPCParams(call, paramsList, parts, op); 418 419 return new Object []{ call, params.toArray() }; 420 } catch (IOException e) { 421 mLogger.error("IOException", e); 422 throw new ServiceException ("IOException: " + e.getMessage()); 423 } catch (SAXException e) { 424 mLogger.error("SAXException", e); 425 throw new ServiceException ("SAXException: " + e.getMessage()); 426 } catch (DOMException e) { 427 mLogger.error("DOMException", e); 428 throw new ServiceException ("DOMException: " + e.getMessage()); 429 } 430 } 431 432 public TypeMappingRegistry getTypeMappingRegistry() { 433 return mTypeMappingRegistry; 434 } 435 436 public HandlerRegistry getHandlerRegistry() { 437 return mHandlerRegistry; 438 } 439 440 public List getHandlerChain() { 441 return mHandlerRegistry.getHandlerChain(new QName (mTargetNS, mPort)); 442 } 443 444 public Service getService() { 445 return mService; 446 } 447 448 449 public void setOperations(Map operations) { 450 mOperations = operations; 451 } 452 453 454 public Map getOperations() { 455 return mOperations; 456 } 457 458 public String getTargetNS() { 459 return mTargetNS; 460 } 461 462 public String getSOAPEncodingNS() { 463 return mSOAPEncodingNS; 464 } 465 466 public String getServiceName() { 467 return mServiceName; 468 } 469 470 public String getPort() { 471 return mPort; 472 } 473 474 public String getEndpointAddress() { 475 return mEndpointAddress; 476 } 477 478 public String getTransport() { 479 return mTransport; 480 } 481 482 483 public String getWSDL() { 484 return mWSDL; 485 } 486 487 488 public void setWSDL(String wsdl) { 489 mWSDL = wsdl; 490 } 491 492 495 public void setSchemaComplexTypes(Map schemaComplexTypes) { 496 mSchemaComplexTypes = schemaComplexTypes; 497 498 if (mSchemaComplexTypes != null) { 500 Iterator iter = mSchemaComplexTypes.values().iterator(); 501 while (iter.hasNext()) { 502 ComplexType value = (ComplexType)iter.next(); 503 if ( value.getType() == ComplexType.TYPE_STRUCT ) { 504 QName structQName = value.getName(); 505 mDefaultTypeMapping.register(ObjectWrapper.class, structQName, 508 mObjectSerializerFactory, 509 mSWFObjectDeserializerFactory); 510 mDefaultSOAPEncodingTypeMapping.register(ObjectWrapper.class, structQName, 511 mObjectSerializerFactory, 512 mSWFObjectDeserializerFactory); 513 if (mLogger.isDebugEnabled()) { 514 mLogger.debug("registered type mapping for object: " + structQName); 515 } 516 } 517 } 520 } 521 } 522 523 526 public Map getSchemaComplexTypes() { 527 return mSchemaComplexTypes; 528 } 529 530 public void toComplexTypesXML(StringBuffer sb) { 531 sb.append("<complex-types>"); 532 if (mSchemaComplexTypes != null) { 533 Iterator iter = mSchemaComplexTypes.entrySet().iterator(); 534 while (iter.hasNext()) { 535 Map.Entry entry = (Map.Entry )iter.next(); 536 ComplexType ct =(ComplexType)entry.getValue(); 537 ct.toXML(sb); 538 } 539 } 540 sb.append("</complex-types>"); 541 } 542 543 public void toOperationXML(StringBuffer sb) { 544 sb.append("<operations>"); 545 Iterator iter = mOperations.keySet().iterator(); 546 while (iter.hasNext()) { 547 String key = (String )iter.next(); 548 LZSOAPOperation op = (LZSOAPOperation)mOperations.get(key); 549 op.toXML(sb); 550 } 551 sb.append("</operations>"); 552 } 553 554 public void toXML(StringBuffer sb) { 555 sb.append("<service") 556 .append(" name=\"").append(mServiceName).append("\"") 557 .append(" port=\"").append(mPort).append("\"") 558 .append(" endpoint=\"").append(mEndpointAddress).append("\"") 559 .append(" transport=\"").append(mTransport).append("\"") 560 .append(" target-namespace=\"").append(mTargetNS).append("\">"); 561 toOperationXML(sb); 562 toComplexTypesXML(sb); 563 sb.append("</service>"); 564 } 565 566 580 591 } 592 | Popular Tags |