1  /**
     2   * com.sekati.services.SOAPClient
     3   * @version 1.0.6
     4   * @author jason m horwitz | sekati.com
     5   * Copyright (C) 2007  jason m horwitz, Sekat LLC. All Rights Reserved.
     6   * Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
     7   */
     8  
     9  import com.sekati.core.CoreObject;
    10  import com.sekati.events.Dispatcher;
    11  import com.sekati.log.Logger;
    12  import com.sekati.services.ISOAPClient;
    13  import com.sekati.services.SOAPEvent;
    14  import com.sekati.utils.Delegate;
    15  import com.sekati.validate.TypeValidation;
    16  import mx.services.SOAPCall;
    17  import mx.services.WebService;
    18  
    19  /**
    20   * Soap Client class to be used with <a href="http://consume.sekati.com/?sid=swsdk">JNuSOAP</a>.<br>
    21   * TODO Replace Singleton Dispatcher for call result handling granularity.
    22   * 
    23   * <br>Q: 'There are multiple possible ports in the WSDL file; please specify a service name and port name!?'
    24   * <br>A: add port to class instance, seach for "port" in the wsdl & see url's below for more info.
    25   * 
    26   * @see <a href="http://www.intangibleinc.com/movabletype/archives/000007.html">http://www.intangibleinc.com/movabletype/archives/000007.html</a>
    27   * @see <a href="http://livedocs.macromedia.com/fms/2/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000796.html">http://livedocs.macromedia.com/fms/2/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000796.html</a>
    28   * @see <a href="http://www.flash-db.com/Tutorials/lclasses/lclasses.php?page=2">http://www.flash-db.com/Tutorials/lclasses/lclasses.php?page=2</a>
    29   * @see <a href="http://www.adobe.com/devnet/flash/articles/flmxpro_webservices_03.html">http://www.adobe.com/devnet/flash/articles/flmxpro_webservices_03.html</a>
    30   */
    31  class com.sekati.services.SOAPClient extends CoreObject implements ISOAPClient {
    32  
    33  	private static var _instance:SOAPClient;
    34  	private var _ws:WebService;
    35  	private var _wsdl:String;
    36  	private var _port:String;
    37  	private var _isConnected:Boolean;
    38  	private var _isVerbose:Boolean;
    39  
    40  	/**
    41  	 * Singleton Private Constructor
    42  	 */
    43  	private function SOAPClient() {
    44  		super( );
    45  		_isConnected = false;
    46  		_isVerbose = false;
    47  	}
    48  
    49  	/**
    50  	 * Singleton Accessor.
    51  	 * @return SOAPClient
    52  	 */
    53  	public static function getInstance():SOAPClient {
    54  		if (!_instance) {
    55  			_instance = new SOAPClient( );
    56  		}
    57  		return _instance;
    58  	}
    59  
    60  	/**
    61  	 * shorthand singleton accessor getter.
    62  	 * @return SOAPClient
    63  	 */
    64  	public static function get $():SOAPClient {
    65  		return SOAPClient.getInstance( );	
    66  	}
    67  
    68  	/**
    69  	 * Connect the SOAP client to webservice.
    70  	 * @param wsdl (String) wsdl URL.
    71  	 * @param port (String) optional service port - <a href="http://www.adobe.com/devnet/flash/articles/flmxpro_webservices_03.html">see more</a>
    72  	 * @return Void
    73  	 */
    74  	public function connect(wsdl:String, port:String):Void {
    75  		_wsdl = wsdl;
    76  		_port = port;
    77  		_ws = new WebService( _wsdl );
    78  		if (port) _ws._portName = port;
    79  		_ws.onLoad = Delegate.create( _instance, connectLoad );
    80  		_ws.onFault = Delegate.create( _instance, connectFault );
    81  	}
    82  
    83  	/**
    84  	 * SOAP webservice method call.
    85  	 * @param method (String) service method name
    86  	 * @param args (Array) array of service method arguments
    87  	 * @return Void
    88  	 */
    89  	public function call(method:String, args:Array):Void {
    90  		/*
    91  		 * Call Remote WebService Method using args array; then broadcast the result/fault event.
    92  		 * NOTE: webservice method invocations return an asynchronous callback. 
    93  		 * callback is undefined if the service itself is not created (and service.onFault fires)
    94  		 */
    95  		var _call:Function = _ws[method].apply( _ws, args );
    96  		_call.onResult = Delegate.create( _instance, callResult, method );
    97  		_call.onFault = Delegate.create( _instance, callFault, method, _call.request, _call.response );
    98  	}
    99  
   100  	/**
   101  	 * Get verbosity SOAPClient sends to {@link Logger} 
   102  	 * @return Boolean
   103  	 */
   104  	public function get verbose():Boolean {
   105  		return _isVerbose;	
   106  	}
   107  
   108  	/**
   109  	 * Set verbosity SOAPClient sends to {@link Logger} 
   110  	 * @param b (Boolean)
   111  	 * @return Void
   112  	 */
   113  	public function set verbose(b:Boolean):Void {
   114  		_isVerbose = b;	
   115  	}	
   116  
   117  	/**
   118  	 * Connect onLoad Handler
   119  	 * @param wsdl (String)
   120  	 * @return Void
   121  	 */
   122  	private function connectLoad(wsdl:String):Void {
   123  		_isConnected = true;
   124  		Dispatcher.$.dispatchEvent( new SOAPEvent( SOAPEvent.CONNECT, {wsdl:_wsdl} ) );
   125  		if (_isVerbose) Logger.$.status( _instance.toString( ), "Webservice Connection SUCCESS Load: '" + _wsdl + "'" );		
   126  	}
   127  
   128  	/**
   129  	 * Connect onFault Handler
   130  	 * @param fault (Object)
   131  	 * @return Void
   132  	 */
   133  	private function connectFault(fault:Object):Void {
   134  		_isConnected = false;
   135  		Dispatcher.$.dispatchEvent( new SOAPEvent( SOAPEvent.FAULT, {fault:fault} ) );
   136  		if (_isVerbose) Logger.$.fatal( _instance.toString( ), "Webservice Connection FAILURE Fault: '" + _wsdl + "'\nfaultstring: " + fault.faultstring + "\nfaultcode: " + fault.faultcode + "\ndetail: " + fault.detail + "\nfaultactor: " + fault.faultactor + "\nfault: " + fault );		
   137  	}
   138  
   139  	/**
   140  	 * Call onResult Handler
   141  	 * @param method (String)
   142  	 * @param result (Object)
   143  	 * @return Void
   144  	 */
   145  	private function callResult(method:String, result:Object):Void {
   146  		Dispatcher.$.dispatchEvent( new SOAPEvent( SOAPEvent.CALL_RESULT, {method:method, result:result} ) );	
   147  		if (_isVerbose) {
   148  			Logger.$.info( _instance.toString( ), "Webservice Call Result: '" + method + "'\nresult (" + TypeValidation.getType( result ).name + "): " + result );
   149  		}
   150  	}
   151  
   152  	/**
   153  	 * Call onFault Handler
   154  	 * @param method (String)
   155  	 * @param fault (Object)
   156  	 * @return Void
   157  	 */
   158  	private function callFault(method:String, response:Object, request:Object, fault:Object):Void {
   159  		Dispatcher.$.dispatchEvent( new SOAPEvent( SOAPEvent.CALL_FAULT, {method:method, fault:fault} ) );
   160  		if (_isVerbose) {
   161  			var props:String = "", call:String = "";
   162  			for(var i:String in SOAPCall) props += "\nSOAPCall Properties: " + i + "  " + this[i];
   163  			for (var j:String in SOAPCall) call += "\nSOAPCall-> " + j + " " + SOAPCall[j];
   164  			Logger.$.error( _instance.toString( ), "Webservice Call Fault: '" + method + "'\nfaultstring: " + fault.faultstring + "\nfaultcode: " + fault.faultcode + "\ndetail: " + fault.detail + "\nfaultactor: " + fault.faultactor + "\nrequest: " + request + "\nSOAP response envelope: " + response + "\nfault: " + fault + "\n" + props + "\n" + call );
   165  		}		
   166  	}	
   167  }