001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-05-09 18:05:40 +0000 (Wed, 09 May 2012) $' 
007 * '$Revision: 29823 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.sdm.spa;
031
032import java.util.HashMap;
033import java.util.HashSet;
034import java.util.Iterator;
035import java.util.List;
036import java.util.Map;
037import java.util.Set;
038import java.util.Vector;
039
040import javax.wsdl.Binding;
041import javax.wsdl.Operation;
042import javax.wsdl.Port;
043import javax.wsdl.Service;
044import javax.wsdl.extensions.soap.SOAPAddress;
045import javax.xml.namespace.QName;
046import javax.xml.rpc.Call;
047import javax.xml.rpc.ServiceException;
048
049import org.apache.axis.wsdl.gen.Parser;
050import org.apache.axis.wsdl.symbolTable.BindingEntry;
051import org.apache.axis.wsdl.symbolTable.Parameters;
052import org.apache.axis.wsdl.symbolTable.ServiceEntry;
053import org.apache.axis.wsdl.symbolTable.SymTabEntry;
054import org.apache.axis.wsdl.symbolTable.SymbolTable;
055import org.apache.commons.logging.Log;
056import org.apache.commons.logging.LogFactory;
057import org.w3c.dom.Node;
058
059import ptolemy.actor.IOPort;
060import ptolemy.actor.TypedAtomicActor;
061import ptolemy.actor.TypedIOPort;
062import ptolemy.actor.parameters.ParameterPort;
063import ptolemy.actor.parameters.PortParameter;
064import ptolemy.data.ArrayToken;
065import ptolemy.data.BooleanToken;
066import ptolemy.data.DoubleToken;
067import ptolemy.data.IntToken;
068import ptolemy.data.LongToken;
069import ptolemy.data.StringToken;
070import ptolemy.data.Token;
071import ptolemy.data.UnsignedByteToken;
072import ptolemy.data.expr.Parameter;
073import ptolemy.data.expr.SingletonParameter;
074import ptolemy.data.expr.StringParameter;
075import ptolemy.data.type.ArrayType;
076import ptolemy.data.type.BaseType;
077import ptolemy.gui.GraphicalMessageHandler;
078import ptolemy.kernel.CompositeEntity;
079import ptolemy.kernel.Relation;
080import ptolemy.kernel.util.Attribute;
081import ptolemy.kernel.util.IllegalActionException;
082import ptolemy.kernel.util.NameDuplicationException;
083
084//////////////////////////////////////////////////////////////////////////
085////WebService
086/**
087 * <p>
088 * The WebService actor provides the user with a plug-in interface to execute
089 * any WSDL-defined web service. Given a URL for the WSDL of a web service and
090 * an operation name that is included in the WSDL, this actor customizes itself
091 * to execute this web service operation.
092 * </p>
093 * <p>
094 * WSDL is an XML format for describing network services as a set of endpoints
095 * operating on messages containing either document-oriented or procedure-
096 * oriented information. The operations and messages are described abstractly,
097 * and then bound to a concrete network protocol and message format to define an
098 * endpoint. Related concrete endpoints are combined into abstract endpoints
099 * (services). WSDL is extensible to allow description of endpoints and their
100 * messages regardless of what message formats or network protocols are used to
101 * communicate. More information on WSDL and realted standard can be found at:
102 * http://www.w3.org/TR/wsdl
103 * </p>
104 * <p>
105 * The user can instantiate the generic web service actor by providing the WSDL
106 * URL and choosing the desired web service operation. The actor then a
107 * utomatically specializes itself and adds ports with the inputs and outputs as
108 * described by the WSDL. The so instantiated actor acts as a proxy for the web
109 * service being executed and links to the other actors through its ports.
110 * </p>
111 * <p>
112 * The WSDL is parsed to get the input, output and binding information. It
113 * dynamically generates ports for each input and output of the operation. This
114 * customization happens at the configuration time of a model. When the actor is
115 * fired at run time, it gets the binding information and creates a call object
116 * to run the model. Using this call object, it invokes the web service and
117 * broadcasts the response to the output ports.
118 * </p>
119 * <p>
120 * <i><b>Notices to users:</b></i>
121 * <ul>
122 * <li>Please double-click on the actor to start customization.</li>
123 * <li>To enter a WSDL URL which is not in the given list of WSDL URLs, click on
124 * the "Preferences" button on the configuration interface and change the type
125 * of the parameter to "Text". Then you can type in the WSDL you would like to
126 * use.</li>
127 * <li>After you select the WSDL, "Commit" and double-click on the actor again.
128 * This will reconfigure the list of available operations. Please do this
129 * everytime you change the WSDL URL.</li>
130 * </ul>
131 * </i>
132 * </p>
133 * 
134 * @author Ilkay Altintas, Updates by: Karen L. Schuchardt, Zhiming Zhao,
135 *         Daniel Crawl
136 * @version $Id: WebService.java 29823 2012-05-09 18:05:40Z crawl $
137 */
138
139public class WebService extends TypedAtomicActor {
140
141        /**
142         * Construct a WebService actor with the given container and name.
143         * 
144         * @param container
145         *            The container.
146         * @param name
147         *            The name of this actor.
148         * @exception IllegalActionException
149         *                If the actor cannot be contained by the proposed
150         *                container.
151         * @exception NameDuplicationException
152         *                If the container already has an actor with this name.
153         */
154        public WebService(CompositeEntity container, String name)
155                        throws NameDuplicationException, IllegalActionException {
156
157                super(container, name);
158
159                wsdlUrl = new StringParameter(this, "wsdlUrl");
160                // wsdlUrl.setExpression("http://xml.nig.ac.jp/wsdl/DDBJ.wsdl");
161                methodName = new StringParameter(this, "methodName");
162                userName = new StringParameter(this, "userName");
163                password = new StringParameter(this, "password");
164                timeout = new StringParameter(this, "timeout");
165                timeout.setExpression("" + 600000);
166
167                startTrigger = new TypedIOPort(this, "startTrigger", true, false);
168                // new Attribute(startTrigger, "_showName");
169                // startTrigger.setContainer(null);
170                hide = new SingletonParameter(startTrigger, "_hide");
171                hide.setToken(BooleanToken.TRUE);
172                // Set the trigger Flag.
173                hasTrigger = new Parameter(this, "hasTrigger", new BooleanToken(false));
174                hasTrigger.setTypeEquals(BaseType.BOOLEAN);
175
176                clientExecErrors = new TypedIOPort(this, "clientExecErrors", false,
177                                true);
178                clientExecErrors.setTypeEquals(BaseType.STRING);
179
180                _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" "
181                                + "width=\"60\" height=\"30\" " + "style=\"fill:white\"/>\n"
182                                + "</svg>\n");
183        }
184
185        // /////////////////////////////////////////////////////////////////
186        // // ports and parameters ////
187
188        /**
189         * The parameter for the URL of the web service WSDL.
190         */
191        public StringParameter wsdlUrl;
192        /**
193         * The parameter for the method name.
194         */
195        public StringParameter methodName;
196        /**
197         * The userName to invoke the web service if necessary.
198         */
199        public StringParameter userName;
200        /**
201         * The password to invoke the web service if necessary.
202         */
203        public StringParameter password;
204        /**
205         * The timeout duration in web service call.
206         */
207        public StringParameter timeout;
208        /**
209         * This is an parameter to activate the optional startTrigger port. Please
210         * activate it <i>ONLY</i> when the actor has no input and it is required
211         * for scheduling of the actor.
212         */
213        public Parameter hasTrigger;
214        /**
215         * This is an optional input port that can be used to help the scheduling of
216         * the actor.
217         * 
218         * <p>
219         * This port is activated by the hasTrigger parameter. Double-click on the
220         * actor to enable. Please enable it <i>ONLY</i> when the actor has no input
221         * and it is required for scheduling of the actor.
222         * </p>
223         */
224        public TypedIOPort startTrigger;
225        /**
226         * It outputs the errors if any occured when actor is executing. It outputs
227         * "NO ERRORS." if there are no exceptional cases.
228         * 
229         */
230        public TypedIOPort clientExecErrors;
231
232        public SingletonParameter hide;
233
234        // /////////////////////////////////////////////////////////////////
235        // // public methods ////
236
237        /**
238         * Callback for changes in attribute values Get the WSDL from the given URL.
239         * 
240         * @param at
241         *            The attribute that changed.
242         * @exception IllegalActionException
243         */
244        public void attributeChanged(Attribute at) throws IllegalActionException {
245       
246        if(_isDebugging) {
247            _log.debug("attribute changed: " + at);
248        }
249
250                if (at == hasTrigger) {
251                        _triggerFlag = ((BooleanToken) hasTrigger.getToken())
252                                        .booleanValue();
253                        _debug("<TRIGGER_FLAG>" + _triggerFlag + "</TRIGGER_FLAG>");
254                        if (_triggerFlag) {
255                                hide.setToken(BooleanToken.FALSE);
256                        } else {
257                                List<?> inPortList = inputPortList();
258                                Iterator<?> ports = inPortList.iterator();
259                                while (ports.hasNext()) {
260                                        IOPort p = (IOPort) ports.next();
261                                        if (p.isInput()) {
262                                                if (p.getName().equals("startTrigger")) {
263                                                        // p.setContainer(null);
264                                                        hide.setToken(BooleanToken.TRUE);
265                                                }
266                                        }
267                                }
268                        }
269                } else if (at == wsdlUrl) {
270                    
271                    String newUrlStr = ((StringToken)wsdlUrl.getToken()).stringValue();
272                    
273                    if(!_urlStr.equals(newUrlStr))
274                    {
275                        _urlStr = newUrlStr;
276                                
277                        methodName.removeAllChoices();
278                                //_deletePorts();
279                                _wsdlParser = null;
280                                
281                                if(_urlStr.length() > 0)
282                                {
283                                _wsdlParser = new Parser();
284                                // Parse the wsdl for the web service.
285                                try
286                                {
287                                    _wsdlParser.run(_urlStr);
288                                }
289                    catch(Exception e)
290                    {
291                        throw new IllegalActionException(this, e,
292                                "Could not run WSDL parser.");
293                    }
294                    
295                                _configureOperationNames();             
296                                
297                    if(_methodNameStr.length() > 0)
298                    {
299                        _configureActor();
300                    }
301                                }
302                    }
303                        
304                } else if (at == methodName) {
305                        
306                        String newMethodStr = ((StringToken)methodName.getToken()).stringValue();
307                        
308                        if(!_methodNameStr.equals(newMethodStr))
309                        {
310                            //_deletePorts();
311                _methodNameStr = newMethodStr;                
312                _debug("<METHOD_NAME>" + _methodNameStr + "</METHOD_NAME>");
313
314
315                                if(_urlStr.length() > 0)
316                                {
317                                int slashIndex = _urlStr.lastIndexOf('/');
318                                String wsName = _urlStr.substring(slashIndex + 1,
319                                                _urlStr.length() - 5);
320    
321                                _attachText(
322                                                "_iconDescription",
323                                                "<svg>\n"
324                                                                + "<rect x=\"0\" y=\"0\" "
325                                                                + "width=\"160\" height=\"50\" "
326                                                                + "style=\"fill:white\"/>\n"
327                                                                + "<text x=\"20\" y=\"25\" "
328                                                                + "style=\"font-size:11; fill:red; font-family:SansSerif\">"
329                                                                + wsName + "_" + _methodNameStr + "</text>\n"
330                                                                + "</svg>\n");
331    
332    
333                                if(_methodNameStr.length() > 0 && _urlStr.length() > 0)
334                                {
335                                    _configureActor();
336                                }
337                                }
338            }
339                }
340        } // end of attributeChanged
341
342        /** Configure the actor for the entered operation of the given web service. */
343        private void _configureOperationNames() throws IllegalActionException {
344                
345            _service = null;
346
347                // Find the entry for the ServiceEntry class in the symbol table.
348                HashMap map = _wsdlParser.getSymbolTable().getHashMap();
349                Iterator<?> entrySetIter = map.entrySet().iterator();
350                while (entrySetIter.hasNext()) {
351                        final Map.Entry currentEntry = (Map.Entry) entrySetIter.next();
352                        final Vector valueVector = (Vector) currentEntry.getValue();
353                        int vecSize = valueVector.size();
354                        for (int index = 0; index < vecSize; ++index) {
355                                SymTabEntry symTabEntryObj = (SymTabEntry) valueVector
356                                                .get(index);
357                                if ((ServiceEntry.class).isInstance(symTabEntryObj)) {
358                                        _service = ((ServiceEntry) symTabEntryObj).getService();
359                                }
360                        }
361                }
362
363                if(_service == null)
364                {
365                    String str = _urlStr;
366                    _urlStr = "";
367                    throw new IllegalActionException(this, "Unable to find service entry for " + str);
368                }
369                
370                Port port = _getSOAPAddress(_service.getPorts());
371                if (port == null) {
372                        _log.debug("<ERROR> No port was returned by the _getSOAPAddress. </ERROR>");
373
374                }
375                _portName = "";
376                _portName = port.getName();
377                _binding = port.getBinding();
378                SymbolTable symbolTable = _wsdlParser.getSymbolTable();
379                BindingEntry bEntry = symbolTable.getBindingEntry(_binding
380                                .getQName());
381
382                Iterator<?> iter = bEntry.getParameters().keySet().iterator();
383                for (; iter.hasNext();) {
384                        final Operation oper = (Operation) iter.next();
385                        methodName.addChoice(oper.getName());
386                }
387        } // end-of-configureOperationNames
388
389        /** Configure the actor for the entered operation of the given web service. */
390        private void _configureActor() throws IllegalActionException {
391            
392            if(_service == null)
393            {
394                throw new IllegalActionException(this, "No service entry.");
395            }
396
397                Port port = _getSOAPAddress(_service.getPorts());
398                if (port == null) {
399                        _debug("<ERROR> No port was returned by the _getSOAPAddress. </ERROR>");
400                }
401                _portName = "";
402                _portName = port.getName();
403                _binding = port.getBinding();
404                SymbolTable symbolTable = _wsdlParser.getSymbolTable();
405                BindingEntry bEntry = symbolTable.getBindingEntry(_binding
406                                .getQName());
407
408                boolean foundOperation = false;
409                Iterator<?> iter = bEntry.getParameters().keySet().iterator();
410                for (; iter.hasNext();) {
411                        Operation operation = (Operation) iter.next();
412                        if (operation.getName().equals(_methodNameStr)) {
413                                foundOperation = true;
414                                final Parameters parameters = (Parameters) bEntry.getParameters().get(operation);
415                                
416                                _inputNameSet.clear();
417                                _inputNameSet.add("startTrigger");
418                                
419                                _outputNameSet.clear();
420                                _outputNameSet.add("clientExecErrors");
421                                
422                                //System.out.println("cleared name sets.");
423                                
424                                try
425                                {
426                                    _createPorts(parameters);
427                                }
428                                catch(NameDuplicationException e)
429                                {
430                                    throw new IllegalActionException(this, e,
431                                            "Error creating ports.");
432                                }
433
434                                // Set output type
435                                if (parameters.returnParam == null) {
436                                        _returnMode = 1; // Get outputs into a map object!
437                                } else if (parameters.returnParam != null) {
438                                        _returnMode = 2; // Get the invoke result value as a
439                                                                                // single value.
440                                        // Get the QName for the return Type
441                                        QName returnQName = parameters.returnParam.getQName();
442                                        if (((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
443                                                        .getType().getDimensions().equals("[]")) {
444                                                Node arrTypeNode = ((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
445                                                                .getType().getNode();
446
447                                                /*
448                                                 * Original code String baseTypeStr =
449                                                 * _getArrayBaseType(arrTypeNode);
450                                                 */
451                                                /* This code updated by Zhiming Zhao */
452                                                String baseTypeStr = (String) ((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
453                                                                .getType().getRefType().getQName()
454                                                                .getLocalPart()
455                                                                + "[]";
456                                                QName nodeQname = ((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
457                                                                .getType().getRefType().getQName();
458
459                                                /* End */
460
461                                                _debug("ARRAY PARAM BASE TYPE: " + baseTypeStr);
462
463                                                try {
464                                                    _createPort(
465                                                                ((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
466                                                                                .getMode(), baseTypeStr,
467                                                                (String) returnQName.getLocalPart());
468                                                } catch(NameDuplicationException e) {
469                                    throw new IllegalActionException(this, e,
470                                            "Error creating ports.");
471                                }
472                                        } else {
473                                            try {
474                                                _createPort(
475                                                                ((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
476                                                                                .getMode(),
477                                                                ((org.apache.axis.wsdl.symbolTable.Parameter) parameters.returnParam)
478                                                                                .getType().getQName()
479                                                                                .getLocalPart(),
480                                                                (String) returnQName.getLocalPart());
481                                            } catch(NameDuplicationException e) {
482                            throw new IllegalActionException(this, e,
483                                    "Error creating ports.");
484                        }
485                                        }
486                                        _debug("<RETURN_QNAME>" + returnQName.getLocalPart()
487                                                        + "</RETURN_QNAME>");
488                                }
489                                // Break out of the loop
490                                break;
491                        }
492                }
493                
494                if(!foundOperation)
495                {
496                    String str = _methodNameStr;
497                    _methodNameStr = "";
498                    throw new IllegalActionException(this, "Could not find operation " + str);
499                }
500                
501                // remove unused ports
502                for(Object obj: inputPortList())
503                {
504                    IOPort curPort = (IOPort)obj;
505                    
506                    if(!_inputNameSet.contains(curPort.getName()))
507                    {
508                        //System.out.println("old input: " + curPort.getName());
509                        try
510                        {
511                        if(curPort instanceof ParameterPort)
512                        {
513                            ((ParameterPort)curPort).getParameter().setContainer(null);
514                        }
515                        
516                        curPort.setContainer(null);
517                        }
518                        catch(NameDuplicationException e)
519                        {
520                            throw new IllegalActionException(this, e, "Error removing " + curPort.getName());
521                        }
522                    }
523                }
524                
525                for(Object obj: outputPortList())
526                {
527                    IOPort curPort = (IOPort)obj;
528                    if(!_outputNameSet.contains(curPort.getName()))
529                    {
530                        //System.out.println("old output: " + curPort.getName());
531                        try
532                        {
533                            curPort.setContainer(null);
534                        }
535                catch(NameDuplicationException e)
536                {
537                    throw new IllegalActionException(this, e, "Error removing " + curPort.getName());
538                }
539                    }
540                }
541                
542                
543        } // end-of-configureActor
544
545        
546        /** Creates ports for the web service operation */
547        private void _createPorts(Parameters params) 
548            throws IllegalActionException, NameDuplicationException {
549                for (int j = 0; j < params.list.size(); j++) {
550                        org.apache.axis.wsdl.symbolTable.Parameter param = (org.apache.axis.wsdl.symbolTable.Parameter) params.list
551                                        .get(j);
552                        _debug("PARAM DIMENSION: " + param.getType().getDimensions());
553                        _debug("PARAM TYPE: "
554                                        + param.getType().getQName().getLocalPart());
555                        if (param.getType().getDimensions().equals("[]")) {
556
557                                Node arrTypeNode = param.getType().getNode();
558                                _debug("TYPE NAME: "
559                                                + arrTypeNode.getAttributes().getNamedItem("name"));
560                                /*
561                                 * String baseTypeStr =
562                                 * arrTypeNode.getFirstChild().getFirstChild().
563                                 * getFirstChild
564                                 * ().getAttributes().getNamedItem("wsdl:arrayType").
565                                 * getNodeValue(); String[] result = baseTypeStr.split(":");
566                                 * baseTypeStr = result[1];
567                                 */
568                                /* Updated by Zhiming */
569                                String baseTypeStr = param.getType().getRefType()
570                                                .getQName().getLocalPart()
571                                                + "[]";
572                                /* Updated by Zhiming End */
573
574                                _debug("ARRAY PARAM BASE TYPE: " + baseTypeStr);
575                                _createPort(param.getMode(), baseTypeStr, (String) param
576                                                .getQName().getLocalPart());
577                        } else { // if (param.getType().getDimension() != null) {
578                                _createPort(param.getMode(), param.getType().getQName()
579                                                .getLocalPart(), (String) param.getQName()
580                                                .getLocalPart());
581                        }
582                }
583        }
584
585        /** Create a port if it does not already exist, and set its type. */
586        private void _createPort(int mode, String portTypeStr, String portNameStr) 
587            throws IllegalActionException, NameDuplicationException {
588            
589            TypedIOPort port = null;
590            
591            // see if port already exists.
592            boolean exists = false;
593            port = (TypedIOPort) getPort(portNameStr);
594            if(port != null)
595            {
596                if(mode == 3 || (port.isInput() && mode == 1) ||
597                    (port.isOutput() && mode == 2))
598                {
599                    exists = true;
600                }
601            }
602           
603            // create port if necessary
604                if (mode == 1) { // input
605                    if(!exists) {
606                        PortParameter parameter = new PortParameter(this, portNameStr);
607                        port = parameter.getPort();
608                        _debug("<INPUT>" + portNameStr + "</INPUT>");   
609                    }
610                } else if (mode == 2) { // output
611                    if(!exists) {
612                        port = new TypedIOPort(this, portNameStr, false, true);
613                        _debug("<OUTPUT>" + portNameStr + "</OUTPUT>");
614                    }
615                } else if (mode == 3) { // input/output
616                    // XXX is this possible? can't have two ports w/ same name!
617                    if(!exists) {
618                        TypedIOPort pin = new TypedIOPort(this, portNameStr, true, false);
619                        new Attribute(pin, "_showName");
620                        _setPortType(pin, portTypeStr);
621                        _debug("<INPUT>" + portNameStr + "</INPUT>");
622                        port = new TypedIOPort(this, portNameStr, false, true);
623                        _debug("<OUTPUT>" + portNameStr + "</OUTPUT>");
624                    }
625                }       
626                
627                if(!exists) {
628                    // show port name
629                    new Attribute(port, "_showName");
630                }
631                
632        // set type.
633        _setPortType(port, portTypeStr);
634        
635        if(mode == 1 || mode == 3) {
636            _inputNameSet.add(portNameStr);
637        } 
638        
639        if(mode == 2 || mode == 3) {
640            _outputNameSet.add(portNameStr);
641        }
642
643        } // end-of-createPort
644
645        /** Deletes all the ports of this actor. */
646        /*
647        protected void _deletePorts() throws IllegalActionException {
648                List<?> inPortList = inputPortList();
649                Iterator<?> ports = inPortList.iterator();
650                while (ports.hasNext()) {
651                        IOPort port = (IOPort) ports.next();
652                        try {
653                                if (!(port.getName().equals("startTrigger"))) {
654                                    if(port instanceof ParameterPort) {
655                                        ((ParameterPort)port).getParameter().setContainer(null);
656                                    }
657                                    
658                                        port.setContainer(null);
659                                }
660                        } catch (NameDuplicationException e) {
661                            throw new IllegalActionException(this, e, 
662                                    "Could not delete the input port: " + port.getName());
663                        }
664                }
665
666                List<?> outPortList = outputPortList();
667                Iterator<?> oports = outPortList.iterator();
668                while (oports.hasNext()) {
669                        IOPort port = (IOPort) oports.next();
670                        try {
671                                if (!(port.getName().equals("clientExecErrors"))) {
672                                    port.setContainer(null);
673                                }
674                        } catch (NameDuplicationException e) {
675                                throw new IllegalActionException(this, e, 
676                                        "Could not delete the output port: " + port.getName());
677                        }
678                }
679        } // end of deletePorts
680        */
681
682        /**
683         * Get the URL address of the the location of the web service defined by the
684         * given WSDL. Get the the namespace and binding information of the web
685         * service using the given WSDL and methodName. Add a parameter to the call
686         * object for each input part.Fill these parameters with the input values on
687         * channels on the ports that correspond to them. Invoke the web service
688         * using all the gathered information. Send the response of the call to the
689         * result port.
690         * 
691         * @exception IllegalActionException
692         *                If there is no director.
693         */
694        public void fire() throws IllegalActionException {
695
696                super.fire();
697
698                // triggerring the actor..
699                if (startTrigger.getWidth() > 0) {
700                        for (int i = 0; i < startTrigger.getWidth(); i++)
701                                startTrigger.get(i);
702                }
703
704                _urlStr = ((StringToken)wsdlUrl.getToken()).stringValue();
705                _methodNameStr = ((StringToken)methodName.getToken()).stringValue();
706
707                _wsdlParser = new Parser();
708
709                try {
710                        _wsdlParser.run(new String(_urlStr));
711                } catch (Exception ex) {
712                        _debug("<EXCEPTION> There was an error while parsing the WSDL in fire for URL: "
713                                        + _urlStr + " .\n" + ex + ". </EXCEPTION>");
714                        // GraphicalMessageHandler.message(
715                        _errorsStr += "\n"
716                                        + ex.getMessage()
717                                        + "Error in fire: There was an error while parsing the WSDL in the actor: "
718                                        + this.getName();// );
719
720                        /*
721                         * The following exception is thrown and for the case when the web
722                         * service's server is down. The director SDF4WS catches the
723                         * exception thrown below and re-tries to get web service
724                         * access.After three re-trials the director finally switches over
725                         * to the same service but at a different server (if second server
726                         * is available)
727                         */
728
729                        GraphicalMessageHandler.message("\nWebService WSDL:" + _urlStr
730                                        + " Not Responding");
731                        throw new IllegalActionException(
732                                        "\nWebService WSDL Not Responding.");
733
734                }
735                _getServiceBinding();
736                try {
737                        SymbolTable symbolTable = _wsdlParser.getSymbolTable();
738                        BindingEntry bEntry = symbolTable.getBindingEntry(_binding
739                                        .getQName());
740                        Parameters parameters = null;
741                        Iterator<?> iter = bEntry.getParameters().keySet().iterator();
742                        for (; iter.hasNext();) {
743                                final Operation operation = (Operation) iter.next();
744                                if (operation.getName().equals(_methodNameStr)) {
745                                        parameters = (Parameters) bEntry.getParameters().get(operation);
746                                        // Set output type
747                                        if (parameters.returnParam == null) {
748                                                _returnMode = 1; // Get outputs into a map object!
749                                        } else if (parameters.returnParam != null) {
750                                                _returnMode = 2; // Get the invoke result value as a
751                                                                                        // single value.
752                                        }
753                                        // Break out of the loop
754                                        break;
755                                }
756                        }
757                } catch (Exception ex) {
758                        _debug("<EXCEPTION>In fire when setting the return mode: " + ex
759                                        + ". </EXCEPTION>");
760                        // GraphicalMessageHandler.message(
761                        _errorsStr += "\n"
762                                        + ex.getMessage()
763                                        + "There was an error when setting up the return mode of the web "
764                                        + "service at: " + this.getName();// );
765                }
766
767                try {
768                        org.apache.axis.client.Service myServiceClient = new org.apache.axis.client.Service(
769                                        _wsdlParser, _service.getQName());
770                        _call = myServiceClient.createCall(QName.valueOf(_portName), QName
771                                        .valueOf(_methodNameStr));
772                        _debug(_call.getClass().getName() + "Call implementation");
773
774                        // KLS((org.apache.axis.client.Call) _call).setTimeout(new
775                        // Integer(600000));
776                        ((org.apache.axis.client.Call) _call).setTimeout(new Integer(
777                                        timeout.stringValue()));
778
779                        // Add a parameter to the call object for each input part.
780                        List<?> inPortList = inputPortList();
781                        int numInPorts = inPortList.size();
782                        // _debug("<TRIGGER_FLAG_BEFORE_OBJECT_ARR>" + _triggerFlag +
783                        // "</TRIGGER_FLAG_BEFORE_OBJECT_ARR>");
784                        // if (_triggerFlag) {
785                        _objArr = new Object[numInPorts - 1];
786                        // }
787                        // else {
788                        // _objArr = new Object[numInPorts];
789                        // }
790                        Iterator<?> ports = inPortList.iterator();
791                        int i = 0;
792                        while (ports.hasNext()) {
793                                // Fill these parameters with the input values on channels on
794                                // the
795                                // ports that correspond to them.
796                                TypedIOPort p = (TypedIOPort) ports.next();
797                                _debug("<INPUT_PORT>" + p.getName() + "</INPUT_PORT>");
798                                if (p.getName().equals("startTrigger")) {
799                                        _debug("Skipped the value of the trigger port in fire.");
800                                } else {
801                                    
802                                    PortParameter input = ((ParameterPort)p).getParameter();
803                                    input.update();
804                                    _objArr[i] = _getObjectFromToken(input.getToken());
805                                    i++;
806                                }
807                        }
808                        for (int j = 0; j < i; j++) {
809                                _debug("_objArr[" + j + "]=" + _objArr[j]);
810                        }
811
812                        _debug("<OBJ_ARR_LENGTH> "
813                                        + (new Integer(_objArr.length)).toString()
814                                        + " </OBJ_ARR_LENGTH>");
815                        _debug("<USERNAME> " + userName.stringValue() + " </USERNAME>");
816                        _call.setProperty(Call.USERNAME_PROPERTY, userName.stringValue());
817                        _debug("<PASSWORD> " + password.stringValue() + " </PASSWORD>");
818                        _call.setProperty(Call.PASSWORD_PROPERTY, password.stringValue());
819
820                        _debug("Starting the invoke!");
821                        // Element invokeResult = (Element) call.invoke(objArr);
822                        Object invokeResult = _call.invoke(_objArr);
823                        _debug("Got results from the invoke...");
824                        List<?> outPortList = this.outputPortList();
825                        Iterator<?> oports = outPortList.iterator();
826                        _debug("<RETURN_MODE> " + new Integer(_returnMode).toString()
827                                        + " </RETURN_MODE>");
828                        if (_returnMode == 2) {
829                                while (oports.hasNext()) {
830                                        TypedIOPort po = (TypedIOPort) oports.next();
831                                        if (!(po.getName().equals("clientExecErrors"))) {
832                                                _sendOutput(po, invokeResult);
833                                        }
834                                }
835                        } else if (_returnMode == 1) {
836                                Map outParams = _call.getOutputParams();
837                                while (oports.hasNext()) {
838                                        // Fill these parameters with the input values on
839                                        // channels on the ports that correspond to them.
840                                        TypedIOPort po = (TypedIOPort) oports.next();
841                                        _debug("<OUTPUT_PORT>" + po.getName() + ", "
842                                                        + po.getType().toString() + "</OUTPUT_PORT>");
843                                        try {
844                                                if (!(po.getName().equals("clientExecErrors"))) {
845                                                        _sendOutput(po, outParams.get(new QName("", po
846                                                                        .getName())));
847                                                }
848                                        } catch (Exception ex) {
849                                                _debug("<EXCEPTION> There was an exception when sending the outputs."
850                                                                + " OutValue: "
851                                                                + (String) org.apache.axis.utils.JavaUtils
852                                                                                .convert(outParams.get(new QName("", po
853                                                                                                .getName())),
854                                                                                                java.lang.String.class)
855                                                                + ". </EXCEPTION>");
856                                                // GraphicalMessageHandler.message(
857                                                _errorsStr += "\n"
858                                                                + ex.getMessage()
859                                                                + "\nThe error occured in the actor: "
860                                                                + this.getName()
861                                                                + "\n Please look at the debugging details for this actor for "
862                                                                + "more information.";// );
863                                        }
864                                }
865                        }
866                } catch (ServiceException se) {
867                    throw new IllegalActionException(this, se, "Service error.");
868                } catch (java.rmi.RemoteException rex) {
869                    throw new IllegalActionException(this, rex, "Web service error.");
870                }
871
872                System.out.println(_errorsStr);
873                if (!(_errorsStr.equals(""))) {
874                        clientExecErrors.broadcast(new StringToken(_errorsStr));
875                } else {
876                        clientExecErrors.broadcast(new StringToken("NO ERRORS."));
877                }
878        } // end of fire
879
880        /** Configure the service, port and binding info. */
881        private void _getServiceBinding() throws IllegalActionException {
882                try {
883                        _service = null;
884
885                        // Find the entry for the ServiceEntry class in the symbol table.
886                        HashMap map = _wsdlParser.getSymbolTable().getHashMap();
887                        Iterator entrySetIter = map.entrySet().iterator();
888                        while (entrySetIter.hasNext()) {
889                                Map.Entry currentEntry = (Map.Entry) entrySetIter.next();
890                                Vector valueVector = (Vector) currentEntry.getValue();
891                                int vecSize = valueVector.size();
892                                for (int index = 0; index < vecSize; ++index) {
893                                        SymTabEntry symTabEntryObj = (SymTabEntry) valueVector
894                                                        .get(index);
895                                        if ((ServiceEntry.class).isInstance(symTabEntryObj)) {
896                                                _service = ((ServiceEntry) symTabEntryObj).getService();
897                                        }
898                                }
899                        }
900
901                        Port port = _getSOAPAddress(_service.getPorts());
902                        if (port == null) {
903                                _debug("<ERROR> No port was returned by the _getSOAPAddress. </ERROR>");
904                        }
905                        _portName = "";
906                        _portName = port.getName();
907                        _binding = port.getBinding();
908                } catch (Exception ex) {
909                        _debug("<EXCEPTION> There was an error when configuring the actor: "
910                                        + ex + ". </EXCEPTION>");
911                        throw new IllegalActionException(this, ex, "There was an error configuring the actor.");
912                }
913        } // end-of-getServiceBinding
914
915        
916        public void preinitialize() throws IllegalActionException
917        {
918            // convert existing input ports that are not port parameters
919            // to port parameters.
920            
921            Set<IOPort> portsToChange = new HashSet<IOPort>();
922            
923            List<?> inputList = inputPortList();
924            for(Object obj: inputList)
925            {
926                IOPort port = (IOPort)obj;
927                if(! port.getName().equals("startTrigger") &&
928                    !(port instanceof ParameterPort))
929                {
930                    portsToChange.add(port);
931                }
932            }
933            
934            for(IOPort port : portsToChange)
935            {
936                // get any connections to this port
937                List<?> relationList = port.linkedRelationList();
938                String name = port.getName();
939                try 
940                {
941                port.setContainer(null);
942            }
943                catch (NameDuplicationException e)
944            {
945                    throw new IllegalActionException(this, e, "Error removing old port " + name);
946            }
947                
948                PortParameter parameter;
949            try 
950            {
951                parameter = new PortParameter(this, name);
952            }
953            catch (NameDuplicationException e)
954            {
955                throw new IllegalActionException(this, e, "Error creating port parameter " + name);
956            }
957                
958            port = parameter.getPort();
959                for(Object obj : relationList)
960                {
961                    port.link((Relation)obj);
962                }
963                
964            }
965            
966            
967            // NOTE: call parent's preinitialize last since the ports may have
968            // changed.
969            super.preinitialize();
970        }
971
972        // ////////////////////////////////////////////////////////////////////
973        // // private methods ////
974
975        /**
976         * Returns a port with a SOAPAddress extensibility element.
977         */
978        private Port _getSOAPAddress(Map ports) {
979                Iterator<?> nameIter = ports.keySet().iterator();
980                while (nameIter.hasNext()) {
981                        String portName = (String) nameIter.next();
982                        Port port = (Port) ports.get(portName);
983                        List<?> extElemList = port.getExtensibilityElements();
984                        for (int i = 0; (extElemList != null) && (i < extElemList.size()); i++) {
985                                Object extEl = extElemList.get(i);
986                                if (extEl instanceof SOAPAddress) {
987                                        return port;
988                                }
989                        }
990                }
991                return null;
992        } // end-of-getSOAPAddress
993
994        /**
995         * _sendOutput Send the output ports from the given port with the right type
996         * casting.
997         * 
998         * @param outPort
999         * @param res
1000         */
1001        private void _sendOutput(TypedIOPort outPort, Object res) {
1002                _debug("<RES_CLASS_NAME>" + res.getClass().getName()
1003                                + "</RES_CLASS_NAME>");
1004                try {
1005                        if (res instanceof String) {
1006                                if (outPort.getType().toString().equals("string")) {
1007                                        outPort.broadcast(new StringToken((String) res));
1008                                } else {
1009                                        _debug("<ERROR> The outPort type ("
1010                                                        + outPort.getType().toString()
1011                                                        + ") and the res type(String) do not match in _sendOutput(). <ERROR>");
1012                                }
1013                        } else if (res instanceof Integer) {
1014                                if (outPort.getType().toString().equals("int")) {
1015                                        outPort.broadcast(new IntToken(((Integer) res).intValue()));
1016                                } else {
1017                                        _debug("<ERROR> The outPort type ("
1018                                                        + outPort.getType().toString()
1019                                                        + ") and the res type(Integer) do not match in _sendOutput(). <ERROR>");
1020                                }
1021                        } else if (res instanceof Double) {
1022                                if (outPort.getType().toString().equals("double")) {
1023                                        outPort.broadcast(new DoubleToken(((Double) res)
1024                                                        .doubleValue()));
1025                                } else {
1026                                        _debug("<ERROR> The outPort type ("
1027                                                        + outPort.getType().toString()
1028                                                        + ") and the res type(Double) do not match in _sendOutput(). <ERROR>");
1029                                }
1030                        } else if (res instanceof Long) {
1031                                if (outPort.getType().toString().equals("long")) {
1032                                        outPort.broadcast(new LongToken(((Long) res).longValue()));
1033                                } else {
1034                                        _debug("<ERROR> The outPort type ("
1035                                                        + outPort.getType().toString()
1036                                                        + ") and the res type(Long) do not match in _sendOutput(). <ERROR>");
1037                                }
1038                        } else if (res instanceof Boolean) {
1039                                if (outPort.getType().toString().equals("boolean")) {
1040                                        outPort.broadcast(new BooleanToken(((Boolean) res)
1041                                                        .booleanValue()));
1042                                } else {
1043                                        _debug("<ERROR> The outPort type ("
1044                                                        + outPort.getType().toString()
1045                                                        + ") and the res type(Boolean) do not match in _sendOutput(). <ERROR>");
1046                                }
1047                        } else if (res instanceof String[]) {
1048                                if (outPort.getType().toString().equals("{string}")) {
1049                                        String[] resultArr = (String[]) res;
1050                                        int xxx = resultArr.length;
1051
1052                                        /*
1053                                         * Original code String resultArrStr = "{"; for (int
1054                                         * resCount = 0; resCount < xxx - 1; resCount++) {
1055                                         * _debug("resultArr[" + resCount + "] = " +
1056                                         * resultArr[resCount]); resultArrStr += resultArr[resCount]
1057                                         * + ", ";
1058                                         * 
1059                                         * } resultArrStr += resultArr[xxx - 1] + "}";
1060                                         */
1061                                        /* code updated by zhiming */
1062
1063                                        String resultArrStr = "{";
1064                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1065                                                _debug("resultArr[" + resCount + "] = "
1066                                                                + resultArr[resCount]);
1067
1068                                                /*
1069                                                 * Check if '"' is included in the string array.
1070                                                 */
1071                                                if (((resultArr[resCount].getBytes())[0] == (resultArr[resCount]
1072                                                                .getBytes())[resultArr[resCount].length() - 1])
1073                                                                && (resultArr[resCount].getBytes()[0] == 34)) {
1074                                                        resultArrStr += resultArr[resCount] + ",";
1075                                                        // System.out.println("Without adding \"");;
1076
1077                                                } else {
1078                                                        resultArrStr += "\"" + resultArr[resCount] + "\",";
1079                                                        // System.out.println("add \"");;
1080                                                }
1081                                        }
1082                                        if (((resultArr[xxx - 1].getBytes())[0] == (resultArr[xxx - 1]
1083                                                        .getBytes())[resultArr[xxx - 1].length() - 1])
1084                                                        && ((resultArr[xxx - 1].getBytes())[0] == 34)) {
1085                                                resultArrStr += resultArr[xxx - 1] + "}";
1086                                                // System.out.println("Without adding \"");;
1087                                        } else {
1088                                                resultArrStr += "\"" + resultArr[xxx - 1] + "\"}";
1089                                                // System.out.println("add \"");;
1090                                        }
1091                                        // System.out.println("stringArrayB: "+resultArrStr);;
1092                                        /* End Zhiming */
1093
1094                                        outPort.broadcast(new ArrayToken(resultArrStr));
1095                                } else {
1096                                        _debug("<ERROR> The outPort type ("
1097                                                        + outPort.getType().toString()
1098                                                        + ") and the res type(String[]) do not match in _sendOutput(). <ERROR>");
1099                                }
1100                        } else if ((res instanceof Integer[])) {
1101                                _debug("IN Integer[]");
1102                                if (outPort.getType().toString().equals("{int}")) {
1103                                        Integer[] resultArr = (Integer[]) res;
1104                                        int xxx = resultArr.length;
1105                                        String resultArrStr = "{";
1106                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1107                                                _debug("resultArr[" + resCount + "] = "
1108                                                                + resultArr[resCount]);
1109                                                resultArrStr += resultArr[resCount] + ", ";
1110                                        }
1111                                        resultArrStr += resultArr[xxx - 1] + "}";
1112                                        outPort.broadcast(new ArrayToken(resultArrStr));
1113                                } else {
1114                                        _debug("<ERROR> The outPort type ("
1115                                                        + outPort.getType().toString()
1116                                                        + ") and the res type(String[]) do not match in _sendOutput(). <ERROR>");
1117                                }
1118                        } else if (res instanceof int[]) {
1119                                _debug("IN int[]");
1120                                if (outPort.getType().toString().equals("{int}")) {
1121                                        int[] resultArr = (int[]) res;
1122                                        int xxx = resultArr.length;
1123                                        String resultArrStr = "{";
1124                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1125                                                _debug("resultArr[" + resCount + "] = "
1126                                                                + resultArr[resCount]);
1127                                                resultArrStr += resultArr[resCount] + ", ";
1128                                        }
1129                                        resultArrStr += resultArr[xxx - 1] + "}";
1130                                        _debug(resultArrStr);
1131                                        outPort.broadcast(new ArrayToken(resultArrStr));
1132                                } else {
1133                                        _debug("<ERROR> The outPort type ("
1134                                                        + outPort.getType().toString()
1135                                                        + ") and the res type(String[]) do not match in _sendOutput(). <ERROR>");
1136                                }
1137                        } else if (res instanceof Double[]) {
1138                                _debug("IN Double[]");
1139                                if (outPort.getType().toString().equals("{double}")) {
1140                                        Double[] resultArr = (Double[]) res;
1141                                        int xxx = resultArr.length;
1142                                        String resultArrStr = "{";
1143                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1144                                                _debug("resultArr[" + resCount + "] = "
1145                                                                + resultArr[resCount]);
1146                                                resultArrStr += resultArr[resCount] + ", ";
1147                                        }
1148                                        resultArrStr += resultArr[xxx - 1] + "}";
1149                                        _debug(resultArrStr);
1150                                        outPort.broadcast(new ArrayToken(resultArrStr));
1151                                } else {
1152                                        _debug("<ERROR> The outPort type ("
1153                                                        + outPort.getType().toString()
1154                                                        + ") and the res type(Double[]) do not match in _sendOutput(). <ERROR>");
1155                                }
1156                        } else if (res instanceof double[]) {
1157                                _debug("IN double[]");
1158                                if (outPort.getType().toString().equals("{double}")) {
1159                                        double[] resultArr = (double[]) res;
1160                                        int xxx = resultArr.length;
1161                                        String resultArrStr = "{";
1162                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1163                                                _debug("resultArr[" + resCount + "] = "
1164                                                                + resultArr[resCount]);
1165                                                resultArrStr += resultArr[resCount] + ", ";
1166                                        }
1167                                        resultArrStr += resultArr[xxx - 1] + "}";
1168                                        _debug(resultArrStr);
1169                                        outPort.broadcast(new ArrayToken(resultArrStr));
1170                                } else {
1171                                        _debug("<ERROR> The outPort type ("
1172                                                        + outPort.getType().toString()
1173                                                        + ") and the res type(double[]) do not match in _sendOutput(). <ERROR>");
1174                                }
1175                        } else if (res instanceof Float[]) {
1176                                _debug("IN Float[]");
1177                                if (outPort.getType().toString().equals("{double}")) {
1178                                        Float[] resultArr = (Float[]) res;
1179                                        int xxx = resultArr.length;
1180                                        String resultArrStr = "{";
1181                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1182                                                _debug("resultArr[" + resCount + "] = "
1183                                                                + resultArr[resCount]);
1184                                                resultArrStr += resultArr[resCount] + ", ";
1185                                        }
1186                                        resultArrStr += resultArr[xxx - 1] + "}";
1187                                        _debug(resultArrStr);
1188                                        outPort.broadcast(new ArrayToken(resultArrStr));
1189                                } else {
1190                                        _debug("<ERROR> The outPort type ("
1191                                                        + outPort.getType().toString()
1192                                                        + ") and the res type(Float[]) do not match in _sendOutput(). <ERROR>");
1193                                }
1194                        }
1195
1196                        else if (res instanceof float[]) {
1197                                _debug("IN float[]");
1198                                if (outPort.getType().toString().equals("{double}")) {
1199                                        float[] resultArr = (float[]) res;
1200                                        int xxx = resultArr.length;
1201                                        String resultArrStr = "{";
1202                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1203                                                _debug("resultArr[" + resCount + "] = "
1204                                                                + resultArr[resCount]);
1205                                                resultArrStr += resultArr[resCount] + ", ";
1206                                        }
1207                                        resultArrStr += resultArr[xxx - 1] + "}";
1208                                        _debug(resultArrStr);
1209                                        outPort.broadcast(new ArrayToken(resultArrStr));
1210                                } else {
1211                                        _debug("<ERROR> The outPort type ("
1212                                                        + outPort.getType().toString()
1213                                                        + ") and the res type(float[]) do not match in _sendOutput(). <ERROR>");
1214                                }
1215                        } else if (res instanceof Boolean[]) {
1216                                _debug("IN Boolean[]");
1217                                if (outPort.getType().toString().equals("{boolean}")) {
1218                                        Boolean[] resultArr = (Boolean[]) res;
1219                                        int xxx = resultArr.length;
1220                                        String resultArrStr = "{";
1221                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1222                                                _debug("resultArr[" + resCount + "] = "
1223                                                                + resultArr[resCount]);
1224                                                resultArrStr += resultArr[resCount] + ", ";
1225                                        }
1226                                        resultArrStr += resultArr[xxx - 1] + "}";
1227                                        _debug(resultArrStr);
1228                                        outPort.broadcast(new ArrayToken(resultArrStr));
1229                                } else {
1230                                        _debug("<ERROR> The outPort type ("
1231                                                        + outPort.getType().toString()
1232                                                        + ") and the res type(Boolean[]) do not match in _sendOutput(). <ERROR>");
1233                                }
1234                        }
1235
1236                        else if (res instanceof boolean[]) {
1237                                _debug("IN boolean[]");
1238                                if (outPort.getType().toString().equals("{boolean}")) {
1239                                        boolean[] resultArr = (boolean[]) res;
1240                                        int xxx = resultArr.length;
1241                                        String resultArrStr = "{";
1242                                        for (int resCount = 0; resCount < xxx - 1; resCount++) {
1243                                                _debug("resultArr[" + resCount + "] = "
1244                                                                + resultArr[resCount]);
1245                                                resultArrStr += resultArr[resCount] + ", ";
1246                                        }
1247                                        resultArrStr += resultArr[xxx - 1] + "}";
1248                                        _debug(resultArrStr);
1249                                        outPort.broadcast(new ArrayToken(resultArrStr));
1250                                } else {
1251                                        _debug("<ERROR> The outPort type ("
1252                                                        + outPort.getType().toString()
1253                                                        + ") and the res type(boolean[]) do not match in _sendOutput(). <ERROR>");
1254                                }
1255                        }
1256
1257                        else if (res instanceof byte[]) {
1258                                _debug("IN byte[]");
1259                                if (outPort.getType().toString().equals("{unsignedByte}")) {
1260                                        byte[] resultArr = (byte[]) res;
1261                                        int bytesAvailable = resultArr.length;
1262                                        Token[] dataTokens = new Token[bytesAvailable];
1263
1264                                        for (int j = 0; j < bytesAvailable; j++) {
1265                                                dataTokens[j] = new UnsignedByteToken(resultArr[j]);
1266                                        }
1267
1268                                        outPort.broadcast(new ArrayToken(dataTokens));
1269                                } else {
1270                                        _debug("<ERROR> The outPort type ("
1271                                                        + outPort.getType().toString()
1272                                                        + ") and the res type(boolean[]) do not match in _sendOutput(). <ERROR>");
1273                                }
1274                        }
1275
1276                        else
1277                                outPort.broadcast(new StringToken(
1278                                                "Cannot identify the type instance of the result!"));
1279                } catch (IllegalActionException iae) {
1280                        _debug("<EXCEPTION> There was an exception in _sendOutput(): "
1281                                        + iae.toString() + ". </EXCEPTION>");
1282                        // GraphicalMessageHandler.message(
1283                        _errorsStr += "\n"
1284                                        + iae.getMessage()
1285                                        + "There was an exception when sending the outputs in actor: "
1286                                        + this.getName() + iae.toString();// );
1287                }
1288        } // end-of-sendOutput
1289
1290        /** Get the native object from a Token. */
1291        private Object _getObjectFromToken(Token token) {
1292                        if(token instanceof DoubleToken) {
1293                            return ((DoubleToken)token).doubleValue();
1294                        } else if(token instanceof IntToken) {
1295                            return ((IntToken)token).intValue();
1296                        } else if (token instanceof StringToken) {
1297                            return ((StringToken)token).stringValue();
1298                        } else if (token instanceof LongToken) {
1299                            return ((LongToken)token).longValue();
1300                        } else if (token instanceof BooleanToken) {
1301                            return ((BooleanToken)token).booleanValue();
1302                        } else if(token instanceof ArrayToken) {
1303                            ArrayToken arrayToken = (ArrayToken)token;
1304                            Object[] arrayObj = new Object[arrayToken.length()];
1305                            for(int i = 0; i < arrayToken.length(); i++) {
1306                                arrayObj[i] = _getObjectFromToken(arrayToken.getElement(i));
1307                            }
1308                            return arrayObj;
1309                        } else {
1310                            System.out.println("WARNING: unknown type of token: " + token.getType());
1311                            return token.toString();
1312                        }
1313                }
1314
1315        /**
1316         * Set the type of a port based on a string representation of that type that
1317         * was extracted from the WSDL description.
1318         * 
1319         * @param arrayTypes
1320         *            a hash of defined array types by name
1321         * @param port
1322         *            the port whose type is to be set
1323         * @param typeStr
1324         *            the string representation of the type to be set
1325         */
1326        private void _setPortType(TypedIOPort port, String typeStr) {
1327                /*
1328                 * NOTE TO SELF: I used:
1329                 * http://www-106.ibm.com/developerworks/webservices
1330                 * /library/ws-soapmap1/ as reference for the Apache->SOAP type mapping.
1331                 * Haven't got to the special "object encoding" and "Sending blobs"
1332                 * parts of the doc. Need to consider them seperately if we wanna do it.
1333                 */
1334                if (typeStr.equals("int")) {
1335                        port.setTypeEquals(BaseType.INT);
1336                } else if (typeStr.equals("boolean")) {
1337                        port.setTypeEquals(BaseType.BOOLEAN);
1338                } else if (typeStr.equals("long")) {
1339                        port.setTypeEquals(BaseType.LONG);
1340                } else if (typeStr.equals("double")) {
1341                        port.setTypeEquals(BaseType.DOUBLE);
1342                } else if (typeStr.equals("float")) { // There is no float in Ptolemy
1343                                                                                                // type sys.
1344                        port.setTypeEquals(BaseType.DOUBLE);
1345                } else if (typeStr.equals("byte")) {
1346                        // ->There is no byte in Ptolemy type sys. So I cast the byte to
1347                        // INT.
1348                        port.setTypeEquals(BaseType.INT);
1349                } else if (typeStr.equals("short")) {
1350                        // ->There is no short in Ptolemy type sys. So again cast it to INT
1351                        port.setTypeEquals(BaseType.INT);
1352                } else if (typeStr.equals("string")) {
1353                        port.setTypeEquals(BaseType.STRING);
1354                } else if (typeStr.equals("string[]")) {
1355                        port.setTypeEquals(new ArrayType(BaseType.STRING));
1356                } else if (typeStr.equals("byte[]")) {
1357                        port.setTypeEquals(new ArrayType(BaseType.INT));
1358                } else if (typeStr.equals("short[]")) {
1359                        port.setTypeEquals(new ArrayType(BaseType.INT));
1360                } else if (typeStr.equals("int[]")) {
1361                        port.setTypeEquals(new ArrayType(BaseType.INT));
1362                } else if (typeStr.equals("long[]")) {
1363                        port.setTypeEquals(new ArrayType(BaseType.LONG));
1364                } else if (typeStr.equals("double[]")) {
1365                        port.setTypeEquals(new ArrayType(BaseType.DOUBLE));
1366                } else if (typeStr.equals("float[]")) {
1367                        port.setTypeEquals(new ArrayType(BaseType.DOUBLE));
1368                } else if (typeStr.equals("boolean[]")) {
1369                        port.setTypeEquals(new ArrayType(BaseType.BOOLEAN));
1370                } else {
1371                        _debug("<WARNING>Could not specify the type. Setting it to string. </WARNING>");
1372                        port.setTypeEquals(BaseType.STRING);
1373                }
1374        }
1375
1376        // ////////////////////////////////////////////////////////////////////
1377        // // private variables ////
1378
1379        private Binding _binding = null;
1380        // The main service call object
1381        private Call _call = null;
1382        // The name of the method that this web service actor binds to
1383        // static private String _methodNameStr = "";
1384        private String _methodNameStr = "";
1385        // The input values to be sent when invoking the web service call.
1386        private Object[] _objArr;
1387        // The name of the port...
1388        private String _portName = null;
1389        private int _returnMode = 0; // 1--multiple output 2--single output param
1390        private Service _service = null;
1391        // The URL of the WSDL that describes the web service
1392        // static private String _urlStr = new String();
1393        private String _urlStr = new String();
1394        // The parser for the WSDL. Will be initiated by the _urlStr.
1395        private Parser _wsdlParser = null;
1396        private String _errorsStr = "";
1397        private boolean _triggerFlag = false;
1398
1399    private static final Log _log = LogFactory.getLog(WebService.class.getName());
1400    private static final boolean _isDebugging = _log.isDebugEnabled();
1401    
1402    private Set<String> _inputNameSet = new HashSet<String>();
1403    private Set<String> _outputNameSet = new HashSet<String>();
1404    
1405
1406} // end of WebService