1 4 5 9 10 package org.openlaszlo.data; 11 12 import org.openlaszlo.iv.flash.api.FlashFile; 13 import org.openlaszlo.iv.flash.api.Frame; 14 import org.openlaszlo.iv.flash.api.Script; 15 import org.openlaszlo.iv.flash.api.action.DoAction; 16 import org.openlaszlo.iv.flash.util.FlashOutput; 17 import org.openlaszlo.iv.flash.util.IVException; 18 import org.openlaszlo.iv.flash.api.action.Actions; 19 import org.openlaszlo.iv.flash.api.action.Program; 20 import org.openlaszlo.iv.flash.util.FlashBuffer; 21 import org.openlaszlo.server.LPS; 22 import org.openlaszlo.servlets.LoadCount; 24 import org.openlaszlo.media.MimeType; 25 import org.openlaszlo.remote.soap.LZSOAPService; 26 import org.openlaszlo.remote.soap.WSDLException; 27 import org.openlaszlo.remote.soap.WSDLParser; 28 import org.openlaszlo.remote.soap.encoding.SOAPDataEncoder; 29 import org.openlaszlo.server.LPS; 30 import org.openlaszlo.xml.internal.XMLUtils; 31 import java.io.ByteArrayInputStream ; 32 import java.io.File ; 33 import java.io.InputStream ; 34 import java.io.InterruptedIOException ; 35 import java.io.IOException ; 36 import java.io.StringReader ; 37 import java.net.URLDecoder ; 38 import java.net.URLEncoder ; 39 import java.rmi.RemoteException ; 40 import java.util.Date ; 41 import java.util.HashMap ; 42 import java.util.Iterator ; 43 import java.util.Properties ; 44 import java.util.Vector ; 45 import javax.xml.parsers.DocumentBuilder ; 46 import javax.xml.parsers.DocumentBuilderFactory ; 47 import javax.xml.parsers.ParserConfigurationException ; 48 import javax.xml.rpc.ServiceException ; 49 import javax.servlet.http.HttpServletRequest ; 50 import javax.servlet.http.HttpServletResponse ; 51 import org.apache.axis.message.SOAPBodyElement; 52 import org.apache.axis.AxisFault; 53 import org.apache.log4j.Logger; 54 import org.xml.sax.InputSource ; 55 import org.xml.sax.SAXException ; 56 import org.w3c.dom.DOMException ; 57 import org.w3c.dom.Element ; 58 import org.w3c.dom.NodeList ; 59 import org.w3c.dom.Text ; 60 import org.apache.axis.AxisProperties; 61 import org.apache.axis.configuration.EngineConfigurationFactoryDefault; 62 import org.apache.axis.components.net.DefaultCommonsHTTPClientProperties; 63 import org.apache.axis.message.SOAPHeader; 64 65 66 69 public class SOAPDataSource extends DataSource 70 { 71 private static Logger mLogger = Logger.getLogger(SOAPDataSource.class); 72 73 74 static DocumentBuilder mBuilder = null; 75 76 static String mLoadOption; 77 78 static HashMap mServiceMap = new HashMap (); 79 80 84 static long mLastCleared = -1; 85 86 static LoadCount mInvokeLoad = new LoadCount(10); 87 static LoadCount mGetServiceLoad = new LoadCount(10); 88 89 93 94 { 95 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 96 try { 97 mBuilder = factory.newDocumentBuilder(); 98 } catch (ParserConfigurationException e) { 99 System.err.println("Can't create DocumentBuilder"); 100 } 101 102 mLoadOption = LPS.getProperty("rpc.soap.wsdlLoadOption", "always"); 103 if (mLogger.isDebugEnabled()) { 104 mLogger.debug("WSDL load option is set to \"" + mLoadOption + "\""); 105 } 106 } 107 108 public SOAPDataSource() { 109 clearLoadInfo(); 110 111 String clientConfigFile = 115 LPS.getProperties().getProperty("axis.clientConfigFile", LPS.getConfigDirectory() + 116 File.separatorChar + "client-config.wsdd"); 117 118 AxisProperties.setProperty(EngineConfigurationFactoryDefault.OPTION_CLIENT_CONFIG_FILE, 119 clientConfigFile); 120 121 AxisProperties.setProperty(DefaultCommonsHTTPClientProperties.MAXIMUM_TOTAL_CONNECTIONS_PROPERTY_KEY, 123 "" + HTTPDataSource.getMaxTotalConnections()); 124 AxisProperties.setProperty(DefaultCommonsHTTPClientProperties.MAXIMUM_CONNECTIONS_PER_HOST_PROPERTY_KEY, 125 "" + HTTPDataSource.getMaxConnectionsPerHost()); 126 AxisProperties.setProperty(DefaultCommonsHTTPClientProperties.CONNECTION_POOL_TIMEOUT_KEY, 127 "" + HTTPDataSource.getConnectionPoolTimeout()); 128 } 129 130 133 public String name() 134 { 135 return "soap"; 136 } 137 138 144 public Data getData(String app, HttpServletRequest req, 145 HttpServletResponse res, long lastModifiedTime) 146 throws InterruptedIOException , IOException , DataSourceException { 147 if (mLogger.isDebugEnabled()) { 148 mLogger.debug("getData"); 149 } 150 151 String request = req.getParameter("request"); 152 if (request == null || request.equals("")) 153 request = "invoke"; 154 155 int swfnum = LPS.getSWFVersionNum(req); 156 157 long t0, t1; 158 t0 = System.currentTimeMillis(); 159 if (request.equals("invoke")) { 160 mInvokeLoad.increment(); 161 try { 162 return invoke(app, req, res, swfnum); 163 } finally { 164 t1 = System.currentTimeMillis(); 165 mInvokeLoad.decrement((int)(t1-t0)); 166 } 167 } else if (request.equals("load")) { 168 mGetServiceLoad.increment(); 169 try { 170 LZSOAPService service = getService(app, req, res, true); 171 return new SOAPData( service.getClientSOAPService(swfnum) ); 172 } catch (ServiceException e) { 173 return exceptionToSOAPData 174 ( swfnum, new DataSourceException(e.getMessage()) ); 175 } finally { 176 t1 = System.currentTimeMillis(); 177 mGetServiceLoad.decrement((int)(t1-t0)); 178 } 179 } 180 181 return exceptionToSOAPData 182 ( swfnum, new DataSourceException("unknown SOAP datasource request") ); 183 } 184 185 public Data invoke(String app, HttpServletRequest req, 186 HttpServletResponse res, int swfnum) { 187 188 if (! req.getMethod().equals("POST")) { 189 mLogger.error("request must be POST"); 190 return exceptionToSOAPData 191 ( swfnum, new DataSourceException("request must be POST") ); 192 } 193 194 String xml = req.getParameter("lzpostbody"); 195 if (xml == null || xml.equals("")) { 196 mLogger.error("no post body"); 197 return exceptionToSOAPData 198 ( swfnum, new DataSourceException("no post body") ); 199 } 200 201 if (mLogger.isDebugEnabled()) { 202 mLogger.debug("lzpostbody: " + xml); 203 } 204 205 try { 206 207 LZSOAPService service = getService(app, req, res, false); 208 if (service == null) { 209 return exceptionToSOAPData 210 ( swfnum, new DataSourceException("could not find service") ); 211 } 212 213 214 try { 215 String operation = req.getParameter("operation"); 216 Object [] value = service.invoke(operation, xml); 217 218 if ( value[0].equals("rpc") ) { 219 return programToSOAPData(swfnum, 220 (Program)value[1], 221 (SOAPHeader)value[2] ); 222 } else { 223 return documentsToSOAPData(swfnum, 224 (Vector )value[1], 225 (SOAPHeader)value[2]); 226 } 227 } catch (AxisFault fault) { 228 return new SOAPData 230 ( new SOAPDataEncoder(swfnum).buildFromFault(fault) ); 231 } 232 233 } catch (RemoteException e) { 234 mLogger.error("RemoteException: " + e.getMessage(), e); 235 return exceptionToSOAPData(swfnum, e); 236 } catch (DataSourceException e) { 237 mLogger.error("DataSourceException: " + e.getMessage(), e); 238 return exceptionToSOAPData(swfnum, e); 239 } catch (IOException e) { 240 mLogger.error("IOException: " + e.getMessage(), e); 241 return exceptionToSOAPData(swfnum, e); 242 } catch (ServiceException e) { 243 mLogger.error("ServiceException: " + e.getMessage(), e); 244 return exceptionToSOAPData(swfnum, e); 245 } catch (Exception e) { 246 mLogger.error("Exception: " + e.getMessage(), e); 247 return exceptionToSOAPData(swfnum, e); 248 } 249 250 } 251 252 SOAPData exceptionToSOAPData(int swfnum, Exception e) { 253 mLogger.error("Exception", e); 254 return new SOAPData( new SOAPDataEncoder(swfnum).buildFromException(e) ); 255 } 256 257 258 SOAPData documentsToSOAPData(int swfnum, Vector docs, SOAPHeader header) 259 throws DataSourceException { 260 261 if (mLogger.isDebugEnabled()) { 262 mLogger.debug("documentsToSOAPData"); 263 } 264 265 if (docs.size() == 0) { 266 mLogger.error("no document return"); 267 throw new DataSourceException("no document return"); 268 } 269 270 try { 271 return new SOAPData( new SOAPDataEncoder(swfnum, docs, header) ); 272 } catch (Exception e) { 273 mLogger.error("problems getting SOAP document element", e); 274 throw new DataSourceException("problems getting SOAP document element"); 275 } 276 } 277 278 279 280 281 289 public String key(String wsdl, String service, String port) { 290 return wsdl + " " + service + " " + port; 291 } 292 293 294 301 synchronized public LZSOAPService getService(String app, 302 HttpServletRequest req, 303 HttpServletResponse res, 304 boolean checkLoadOption) 305 throws DataSourceException { 306 307 String wsdl = req.getParameter("wsdl"); 308 String service = req.getParameter("service"); 309 String port = req.getParameter("port"); 310 311 if (wsdl == null || wsdl.equals("")) { 312 throw new DataSourceException("no wsdl specified"); 313 } 314 315 LZSOAPService soapService = null; 316 if (checkLoadOption) { 317 if ( "never" == mLoadOption.intern() ) { 318 soapService = (LZSOAPService)mServiceMap.get( key(wsdl,service,port) ); 319 } 320 } else { 321 soapService = (LZSOAPService)mServiceMap.get( key(wsdl,service,port) ); 322 } 323 if (soapService != null) 324 return soapService; 325 326 return fetchService(app, req, res); 327 } 328 329 332 synchronized public LZSOAPService fetchService(String app, 333 HttpServletRequest req, 334 HttpServletResponse res) 335 throws DataSourceException { 336 337 String wsdl = req.getParameter("wsdl"); 338 String service = req.getParameter("service"); 339 String port = req.getParameter("port"); 340 341 try { 343 Data data; 344 if (wsdl.startsWith("file:")) { 345 data = FileDataSource.getFileData(app, req, res, wsdl, -1); 346 } else if (wsdl.startsWith("http://") || wsdl.startsWith("https://")) { 347 data = HTTPDataSource.getHTTPData(req, res, wsdl, -1); 348 } else { 349 throw new DataSourceException("unsupported WSDL protocol: " + 350 wsdl); 351 } 352 353 String _wsdl = data.getAsString(); 354 LZSOAPService soapService = 355 WSDLParser.parse(wsdl, new InputSource (new StringReader (_wsdl)), 356 service, port); 357 358 if (soapService == null) { 359 throw new DataSourceException("could not find SOAP service (" + 360 wsdl + ", " + service + ", " + 361 port + ")"); 362 } 363 364 mServiceMap.put( key(wsdl,soapService.getServiceName(),soapService.getPort()), 365 soapService); 366 367 if (service == null || port == null) { 369 mServiceMap.put( key(wsdl,service,port), soapService); 370 } 371 372 return soapService; 373 374 } catch (IOException e) { 375 mLogger.error("Exception", e); 376 throw new DataSourceException(e.getMessage()); 377 } catch (WSDLException e) { 378 mLogger.error("Exception", e); 379 throw new DataSourceException(e.getMessage()); 380 } catch (ServiceException e) { 381 mLogger.error("Exception", e); 382 throw new DataSourceException(e.getMessage()); 383 } catch (Exception e) { 384 mLogger.error("Exception", e); 385 throw new DataSourceException(e.getMessage()); 386 } 387 } 388 389 390 SOAPData programToSOAPData(int swfnum, Program program, SOAPHeader header) 391 throws DataSourceException { 392 393 if (mLogger.isDebugEnabled()) { 394 mLogger.debug("programToSOAPData"); 395 } 396 397 try { 398 return new SOAPData( new SOAPDataEncoder(swfnum, program, header) ); 399 } catch (Exception e) { 400 mLogger.error("problems creating RPC program", e); 401 throw new DataSourceException("problems creating RPC program"); 402 } 403 } 404 405 408 synchronized public static void serviceXML(StringBuffer sb, String serviceKey) { 409 LZSOAPService service = (LZSOAPService)mServiceMap.get(serviceKey); 410 if (service != null) { 411 service.toXML(sb); 412 } else { 413 sb.append("<error>").append(serviceKey).append(" service not found.") 414 .append("</error>"); 415 } 416 } 417 418 synchronized public static void listServicesXML(StringBuffer sb) { 419 sb.append("<services count=\"").append(mServiceMap.size()).append("\">"); 420 Iterator iter = mServiceMap.keySet().iterator(); 421 while (iter.hasNext()) { 422 String k = (String )iter.next(); 423 sb.append("<service") 424 .append(" name=\"").append(XMLUtils.escapeXml(k)).append("\"") 425 .append(" urlname=\"").append(URLEncoder.encode(k)).append("\"") 426 .append("/>"); 427 } 428 sb.append("</services>"); 429 } 430 431 synchronized static public void toXML(StringBuffer sb) { 432 Date lc = new Date (mLastCleared); 433 sb.append("<soapinfo ") 434 .append(" last-cleared=\"").append(lc).append("\"") 435 .append(">"); 436 { 437 sb.append(mInvokeLoad.toXML("invoke_load")); 438 sb.append(mGetServiceLoad.toXML("get_service_load")); 439 listServicesXML(sb); 440 } 441 sb.append("</soapinfo>"); 442 } 443 444 public static void clearLoadInfo() { 445 mInvokeLoad.reset(); 446 mGetServiceLoad.reset(); 447 mLastCleared = System.currentTimeMillis(); 448 } 449 450 453 public class SOAPData extends Data 454 { 455 byte[] mObject = null; 456 SOAPDataEncoder mSOAPDataEncoder = null; 457 public SOAPData(byte[] object) { 458 mObject = object; 459 } 460 461 public SOAPData(SOAPDataEncoder de) { 462 mSOAPDataEncoder = de; 463 } 464 465 public String getMimeType() { 466 return MimeType.SWF; 467 } 468 469 public InputStream getInputStream() 470 throws IOException { 471 if (mObject != null) { 472 return new ByteArrayInputStream (mObject); 473 } else if (mSOAPDataEncoder != null) { 474 return mSOAPDataEncoder.getInputStream(); 475 } 476 477 throw new IOException ("no input stream"); 478 } 479 480 public long size() { 481 if (mObject != null) { 482 return mObject.length; 483 } else if (mSOAPDataEncoder != null) { 484 try { 485 return mSOAPDataEncoder.getSize(); 486 } catch (IOException e) { 487 mLogger.warn("ioexception getting size soap data encoder"); 488 } 489 } 490 491 return 0; 492 } 493 } 494 } 495 | Popular Tags |