001    package railo.runtime.net.rpc.client;
002    
003    import java.io.IOException;
004    import java.net.MalformedURLException;
005    import java.net.URL;
006    import java.rmi.RemoteException;
007    import java.util.ArrayList;
008    import java.util.Iterator;
009    import java.util.List;
010    import java.util.Map;
011    import java.util.TimeZone;
012    import java.util.Vector;
013    
014    import javax.wsdl.Binding;
015    import javax.wsdl.Operation;
016    import javax.wsdl.Port;
017    import javax.wsdl.extensions.soap.SOAPAddress;
018    import javax.xml.namespace.QName;
019    import javax.xml.rpc.ServiceException;
020    import javax.xml.rpc.encoding.TypeMapping;
021    
022    import org.apache.axis.EngineConfiguration;
023    import org.apache.axis.client.Call;
024    import org.apache.axis.client.Service;
025    import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
026    import org.apache.axis.configuration.SimpleProvider;
027    import org.apache.axis.encoding.TypeMappingRegistry;
028    import org.apache.axis.message.SOAPHeaderElement;
029    import org.apache.axis.transport.http.CommonsHTTPSender;
030    import org.apache.axis.wsdl.gen.Parser;
031    import org.apache.axis.wsdl.symbolTable.BindingEntry;
032    import org.apache.axis.wsdl.symbolTable.ElementDecl;
033    import org.apache.axis.wsdl.symbolTable.Parameter;
034    import org.apache.axis.wsdl.symbolTable.Parameters;
035    import org.apache.axis.wsdl.symbolTable.ServiceEntry;
036    import org.apache.axis.wsdl.symbolTable.SymTabEntry;
037    import org.apache.axis.wsdl.symbolTable.SymbolTable;
038    import org.apache.axis.wsdl.symbolTable.TypeEntry;
039    import org.apache.axis.wsdl.toJava.Utils;
040    import org.w3c.dom.Element;
041    import org.w3c.dom.Node;
042    import org.w3c.dom.NodeList;
043    import org.w3c.dom.Text;
044    
045    import railo.commons.lang.ClassUtil;
046    import railo.commons.lang.StringUtil;
047    import railo.runtime.PageContext;
048    import railo.runtime.config.Config;
049    import railo.runtime.dump.DumpData;
050    import railo.runtime.dump.DumpProperties;
051    import railo.runtime.dump.DumpTable;
052    import railo.runtime.dump.DumpTablePro;
053    import railo.runtime.dump.SimpleDumpData;
054    import railo.runtime.engine.ThreadLocalPageContext;
055    import railo.runtime.exp.ExpressionException;
056    import railo.runtime.exp.PageException;
057    import railo.runtime.net.proxy.Proxy;
058    import railo.runtime.net.proxy.ProxyData;
059    import railo.runtime.net.rpc.AxisCaster;
060    import railo.runtime.net.rpc.Pojo;
061    import railo.runtime.net.rpc.RPCException;
062    import railo.runtime.net.rpc.TypeMappingUtil;
063    import railo.runtime.op.Caster;
064    import railo.runtime.text.xml.XMLUtil;
065    import railo.runtime.type.Collection;
066    import railo.runtime.type.Iteratorable;
067    import railo.runtime.type.Objects;
068    import railo.runtime.type.Struct;
069    import railo.runtime.type.StructImpl;
070    import railo.runtime.type.UDFImpl;
071    import railo.runtime.type.dt.DateTime;
072    import railo.runtime.type.it.ObjectsIterator;
073    import railo.runtime.type.util.ArrayUtil;
074    import railo.runtime.type.util.ComponentUtil;
075    import railo.runtime.util.ArrayIterator;
076    import railo.transformer.bytecode.util.ASMProperty;
077    import railo.transformer.bytecode.util.ASMPropertyImpl;
078    
079    /**
080     * Wrapper for a Webservice
081     */
082    public final class RPCClient implements Objects, Iteratorable{
083    
084        
085        
086    
087            private static final long serialVersionUID = 1L;
088            private Parser parser = new Parser();
089            //private Map properties=new HashTable();
090        private String wsdlUrl;
091            private ProxyData proxyData;
092            private String username;
093            private String password;
094            private Call last;
095            private List<SOAPHeaderElement> headers;
096            
097            static {
098                    EngineConfiguration engine = EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig();
099                    SimpleProvider provider = new SimpleProvider(engine);
100                    provider.deployTransport("http", new CommonsHTTPSender());      
101            }
102            
103    
104        /**
105         * @param wsdlUrl
106         * @param username 
107         * @param password 
108         * @throws PageException
109         */
110        public RPCClient( String wsdlUrl, String username, String password) throws PageException {
111                    this(wsdlUrl,username,password,null);
112        }
113    
114        public RPCClient( String wsdlUrl) throws PageException {
115           this(wsdlUrl,null,null,null);
116        }
117        
118            public RPCClient(String wsdlUrl, ProxyData proxyData) throws PageException {
119                    this(wsdlUrl,null,null,proxyData);
120            }
121    
122            public RPCClient(String wsdlUrl, String username, String password, ProxyData proxyData) throws PageException {
123                    if(!StringUtil.isEmpty(username)) {
124                            if(password==null)password="";
125                            parser.setUsername(username);
126                    parser.setPassword(password);
127                    //parser.setTimeout(1000);
128                    this.username=username;
129                    this.password=password;
130                    
131                    }
132                    this.proxyData=proxyData;
133                    run(wsdlUrl);
134            }
135    
136            private void run(String wsdlUrl) throws PageException {
137            this.wsdlUrl=wsdlUrl;
138            try {
139                parser.run(wsdlUrl);
140            }
141            catch(Throwable e) {
142                throw Caster.toPageException(e);
143            }
144        }
145    
146        /**
147         * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct)
148         */
149            public Object callWithNamedValues(PageContext pc, String methodName, Struct arguments) throws PageException {
150            try {
151                return (_callMethod(pc.getConfig(),methodName,arguments,null));
152            } 
153            catch (Exception e) {
154                throw Caster.toPageException(e);
155            }
156        }
157            
158            public Object callWithNamedValues(Config config, String methodName, Struct arguments) throws PageException {
159            try {
160                return (_callMethod(config,methodName,arguments,null));
161            } 
162            catch (Exception e) {
163                throw Caster.toPageException(e);
164            }
165        }
166    
167            /**
168             * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, railo.runtime.type.Collection.Key, railo.runtime.type.Struct)
169             */
170            public Object callWithNamedValues(PageContext pc, Collection.Key methodName, Struct args) throws PageException {
171                    return callWithNamedValues(pc, methodName.getString(), args);
172            }
173    
174        /**
175         * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, java.lang.String, java.lang.Object[])
176         */
177        public Object call(PageContext pc, String methodName,Object[] arguments) throws PageException {
178            try {
179                return _callMethod(pc.getConfig(),methodName,null,arguments);
180            } 
181            catch (Throwable t) {
182                    throw Caster.toPageException(t);
183                    } 
184        }
185    
186        public Object call(Config config, String methodName,Object[] arguments) throws PageException {
187            try {
188                return (_callMethod(config,methodName,null,arguments));
189            } 
190            catch (Exception e) {
191                    throw Caster.toPageException(e);
192                    } 
193        }
194    
195            /**
196             *
197             * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object[])
198             */
199            public Object call(PageContext pc, Collection.Key methodName, Object[] arguments) throws PageException {
200                    return call(pc, methodName.getString(), arguments);
201            }
202    
203        private Object _callMethod(Config config,String methodName, Struct namedArguments,Object[] arguments) throws PageException, ServiceException, RemoteException {
204            
205                    javax.wsdl.Service service = getWSDLService();
206                    
207                    Service axisService = null;
208                    axisService = new Service(parser, service.getQName());
209                    TypeMappingUtil.registerDefaults(axisService.getTypeMappingRegistry());
210                    
211                    
212                    
213                    
214                    
215                    
216                    Port port = getWSDLPort(service);
217                    
218                    Binding binding = port.getBinding();
219            
220            Parameters parameters = null;
221                    Parameter p = null;
222                    SymbolTable symbolTable = parser.getSymbolTable();
223                    BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
224                    
225                    Iterator itr = bEntry.getParameters().keySet().iterator();
226                    Operation tmpOp = null;
227                    Operation operation = null;
228                    while(itr.hasNext())  {
229                            tmpOp = (Operation)itr.next();  
230                if(tmpOp.getName().equalsIgnoreCase(methodName)) {
231                                    operation = tmpOp;
232                                    parameters = (Parameters)bEntry.getParameters().get(tmpOp);
233                    break;
234                            }
235                    }
236                    if(operation == null || parameters == null)
237                            throw new RPCException("Cannot locate method " + methodName + " in webservice " + wsdlUrl);
238                    
239            org.apache.axis.client.Call call = (Call)axisService.createCall(QName.valueOf(port.getName()), QName.valueOf(tmpOp.getName()));
240            
241            if(!StringUtil.isEmpty(username,true)){
242                    call.setUsername(username);
243                    call.setPassword(password);
244            }
245            
246            org.apache.axis.encoding.TypeMapping tm = (org.apache.axis.encoding.TypeMapping) 
247                    axisService.getTypeMappingRegistry().getDefaultTypeMapping();
248            TypeMappingRegistry reg=(TypeMappingRegistry) axisService.getTypeMappingRegistry();
249            
250            //tm=reg.getOrMakeTypeMapping("http://schemas.xmlsoap.org/soap/encoding/");
251            tm=call.getMessageContext().getTypeMapping();
252            
253            Vector<String> inNames = new Vector<String>();
254                    Vector<Parameter> inTypes = new Vector<Parameter>();
255                    Vector<String> outNames = new Vector<String>();
256                    Vector<Parameter> outTypes = new Vector<Parameter>();
257                    for(int j = 0; j < parameters.list.size(); j++) {
258                            p = (Parameter)parameters.list.get(j);
259                            map(config,call,tm,p.getType());
260                            switch(p.getMode()) {
261                case Parameter.IN:
262                    inNames.add(p.getQName().getLocalPart());
263                    inTypes.add(p);
264                break;
265                case Parameter.OUT:
266                    outNames.add(p.getQName().getLocalPart());
267                    outTypes.add(p);
268                break;
269                case Parameter.INOUT:
270                    inNames.add(p.getQName().getLocalPart());
271                    inTypes.add(p);
272                    outNames.add(p.getQName().getLocalPart());
273                    outTypes.add(p);
274                break;
275                }
276                    }
277    
278                    // set output type
279                    if (parameters.returnParam != null) {
280                    QName rtnQName = parameters.returnParam.getQName();
281                    TypeEntry rtnType = parameters.returnParam.getType();
282                    map(config,call,tm,rtnType);
283                outNames.add(rtnQName.getLocalPart());
284                outTypes.add(parameters.returnParam);
285                
286            }
287            
288            
289            
290            //Iterator it = outTypes.iterator();
291           
292            // check arguments
293            Object[] inputs = new Object[inNames.size()];
294            if(arguments!=null) {
295                    if(inNames.size() != arguments.length)
296                            throw new RPCException("Invalid arguments count for operation " + methodName+" ("+arguments.length+" instead of "+inNames.size()+")");
297                    
298                for(int pos = 0; pos < inNames.size(); pos++) {
299                            p = (Parameter)inTypes.get(pos);
300                    inputs[pos]=getArgumentData(tm,ThreadLocalPageContext.getTimeZone(config), p, arguments[pos]);
301                    }
302            }
303            else {
304                UDFImpl.argumentCollection(namedArguments);
305                if(inNames.size() != namedArguments.size())
306                    throw new RPCException("Invalid arguments count for operation " + methodName+" ("+namedArguments.size()+" instead of "+inNames.size()+")");
307                
308                
309                Object arg;
310                String name;
311                for(int pos = 0; pos < inNames.size(); pos++) {
312                    p = (Parameter)inTypes.get(pos);
313                    name=p.getName();
314                    arg=namedArguments.get(name,null);
315                    
316                    if(arg==null) {
317                        throw new RPCException("Invalid arguments for operation " + methodName,
318                                getErrorDetailForArguments((String[])inNames.toArray(new String[inNames.size()]),namedArguments.keysAsString()));
319                    }
320                    inputs[pos]=getArgumentData(tm,ThreadLocalPageContext.getTimeZone(config), p, arg);
321                }
322            }
323            
324            Object ret=null;
325            
326         // add header
327            if(headers!=null && !headers.isEmpty()) {
328                    Iterator<SOAPHeaderElement> it = headers.iterator();
329                    while(it.hasNext()){
330                            call.addHeader(it.next());
331                    }
332            }
333            
334            if(proxyData!=null && !StringUtil.isEmpty(proxyData.getServer(),true)) {
335                    try {
336                            Proxy.start(proxyData);
337                            ret = call.invoke(inputs);
338                            //ret = invoke(call,inputs);
339                            
340                    }
341                    finally {
342                            Proxy.end();
343                    }
344            }
345            else {
346                    ret = call.invoke(inputs);
347            }
348                    last=call;
349                    
350                    if(outNames.size()<=1) return AxisCaster.toRailoType(null,ret);
351            //getParamData((org.apache.axis.client.Call)call,parameters.returnParam,ret);
352                    Map outputs = call.getOutputParams();
353                    
354                    Struct sct = new StructImpl();
355                    for(int pos = 0; pos < outNames.size(); pos++) {
356                            String name = (String)outNames.get(pos);
357                //print.ln(name);
358                            Object value = outputs.get(name);
359                            if(value == null && pos == 0) {
360                                    sct.setEL(name, AxisCaster.toRailoType(null,ret));
361                            }
362                            else {
363                                    sct.setEL(name, AxisCaster.toRailoType(null,value));
364                            }
365                    }
366                    return sct;
367            }
368        
369            private void map(Config config,Call call, org.apache.axis.encoding.TypeMapping tm, TypeEntry type) throws PageException {
370                    Vector els = type.getContainedElements();
371                    
372                    if(els==null) mapSimple(tm, type);
373            else {
374                    // class is already registed
375                    Class rtnClass=tm.getClassForQName(type.getQName());
376                    if(rtnClass!=null && rtnClass.getName().equals(getClientClassName(type))) return;
377                    
378                    
379                    ClassLoader cl=null;
380                            try {
381                                    cl = config.getRPCClassLoader(false);
382                            } catch (IOException e) {}
383                            
384                    Class cls = mapComplex(config,call,tm, type);   
385                    // TODO make a better impl; this is not the fastest way to make sure all pojos use the same classloader
386                    if(cls!=null && cl!=cls.getClassLoader()){
387                            mapComplex(config,call,tm, type); 
388                    }
389                    
390            }
391            }
392            
393            private Class mapComplex(Config config,Call call, org.apache.axis.encoding.TypeMapping tm, TypeEntry type) throws PageException {
394                    Vector children = type.getContainedElements();
395                    TypeEntry ref=type.getRefType();
396                    if(ref==null) return _mapComplex(config, call, tm, type);
397                    children = ref.getContainedElements();
398                    
399                    if(children==null) {
400                            mapSimple(tm, ref);
401                            return null;
402                    }
403                    Class clazz = mapComplex(config, call, tm, ref);
404                    if(clazz==null) return null;
405                    Class arr = ClassUtil.toArrayClass(clazz);
406                    TypeMappingUtil.registerBeanTypeMapping(tm, arr, type.getQName());
407                    return arr;
408            }
409    
410            private Class _mapComplex(Config config,Call call, org.apache.axis.encoding.TypeMapping tm, TypeEntry type) throws PageException {
411                    Vector children = type.getContainedElements();
412                    ArrayList<ASMPropertyImpl> properties=new ArrayList<ASMPropertyImpl>();
413                    if(children!=null) {
414                            Iterator it = children.iterator();
415                            ElementDecl el;
416                            Class clazz;
417                            TypeEntry t;
418                            String name;
419                            while(it.hasNext()){
420                                    clazz=null;
421                            el=(ElementDecl) it.next();
422                            t=el.getType();
423                            Vector els = t.getContainedElements();
424                        if(els!=null) {
425                            clazz=mapComplex(config, call, tm, t);
426                        }
427                            name=railo.runtime.type.List.last(el.getQName().getLocalPart(), '>');
428                            
429                            if(clazz==null)clazz=tm.getClassForQName(t.getQName());
430                            if(clazz==null)clazz=Object.class;
431                            
432                            properties.add(new ASMPropertyImpl(clazz,name));
433                    }
434                    }
435                    ASMProperty[] props = properties.toArray(new ASMProperty[properties.size()]);
436                    String clientClassName=getClientClassName(type);
437                    Pojo pojo = (Pojo) ComponentUtil.getClientComponentPropertiesObject(config,clientClassName,props);
438                    
439                    TypeMappingUtil.registerBeanTypeMapping(tm,
440                            pojo.getClass(), 
441                            type.getQName());
442                    
443            return pojo.getClass();
444            }
445            
446            private String getClientClassName(TypeEntry type) {
447                    String className=StringUtil.toVariableName(type.getQName().getLocalPart());
448                    
449                    String url=urlToClass(wsdlUrl);
450                    String ns = type.getQName().getNamespaceURI();
451                    //if(props!=null){String p = ASMUtil.createMD5(props);
452                    //print.e("p:"+p);}
453                    // has namespace 
454                    if(ns!=null && !"http://DefaultNamespace".equalsIgnoreCase(ns)){
455                            ns=StringUtil.replace(ns, "http://", "", true);
456                            ns=toClassName(ns,true);
457                            if(!StringUtil.isEmpty(ns)) return ns+"."+className;
458                    }
459                    return url+"."+className;
460            } 
461    
462            private static String urlToClass(String wsdlUrl) {
463                    
464                    StringBuffer sb=new StringBuffer();
465                    try {
466                            URL url = new URL(wsdlUrl);
467                            
468                            // protocol
469                            if("http".equalsIgnoreCase(url.getProtocol())){}
470                            else{
471                                    sb.append(toClassName(url.getProtocol(), false));
472                                    sb.append('.');
473                            }
474                            
475                            // host
476                            sb.append(toClassName(url.getHost(), true));
477                            
478                            // port
479                            if(url.getPort()>0 && url.getPort()!=80){
480                                    sb.append(".p");
481                                    sb.append(url.getPort());
482                            }
483                            
484                            // path
485                            if(!StringUtil.isEmpty(url.getPath())){
486                                    sb.append('.');
487                                    sb.append(toClassName(url.getPath(), false));
488                            }
489                            
490                            // query
491                            if(!StringUtil.isEmpty(url.getQuery()) && !"wsdl".equals(url.getQuery())){
492                                    sb.append('.');
493                                    sb.append(toClassName(url.getQuery(), false));
494                            }
495                            
496                            
497                            return sb.toString();
498                    } 
499                    catch (MalformedURLException e) {
500                            return StringUtil.toVariableName(wsdlUrl);
501                    }
502            }
503    
504            private static String toClassName(String raw,boolean reverse) {
505                    raw=raw.trim();
506                    if(raw.endsWith("/"))raw=raw.substring(0,raw.length()-1);
507                    StringBuffer sb=new StringBuffer();
508                    String[] arr=null;
509                    try {
510                            arr = railo.runtime.type.List.toStringArray(railo.runtime.type.List.listToArray(raw, "./&="));
511                    } catch (PageException e) {}
512                    String el;
513                    for(int i=0;i<arr.length;i++){
514                            el=arr[i].trim();
515                            if(el.length()==0)continue;
516                            if(reverse){
517                                    if(sb.length()>0)sb.insert(0,'.');
518                                    sb.insert(0,StringUtil.lcFirst(StringUtil.toVariableName(arr[i])));
519                                    
520                            }
521                            else {
522                                    if(sb.length()>0)sb.append('.');
523                                    sb.append(StringUtil.lcFirst(StringUtil.toVariableName(arr[i])));
524                            }
525                    }
526                    return sb.toString();
527            }
528    
529            private void mapSimple(org.apache.axis.encoding.TypeMapping tm, TypeEntry type) {
530                    //print.out("simple");
531                    //print.out(tm);
532                    //print.out(type);
533            }
534    
535            private String getErrorDetailForArguments(String[] names, String[] argKeys) {
536            String name;
537            boolean found;
538            
539            for(int i=0;i<names.length;i++) {
540                name=names[i];
541                found=false;
542                for(int y=0;y<argKeys.length;y++) {
543                    if(name.equalsIgnoreCase(argKeys[y]))found=true;
544                }
545                if(!found) {
546                    if(names.length>1)
547                        return "missing argument with name ["+name+"], needed argument are ["+railo.runtime.type.List.arrayToList(names,", ")+"]";
548                    return "missing argument with name ["+name+"]";
549                }
550            }
551            return "";
552        }
553    
554        /**
555         * returns the WSDL Service for this Object
556             * @return WSDL Service
557             * @throws RPCException
558             */
559            public javax.wsdl.Service getWSDLService() throws RPCException {
560                    SymTabEntry symTabEntry = null;
561                    Map.Entry entry = null;
562                    Vector v = null;
563                    for(Iterator iterator = parser.getSymbolTable().getHashMap().entrySet().iterator(); iterator.hasNext();) {
564                            entry = (Map.Entry)iterator.next();
565                            v = (Vector)entry.getValue();
566                            for(int i = 0; i < v.size(); i++) {
567                                    if(!(org.apache.axis.wsdl.symbolTable.ServiceEntry.class).isInstance(v.elementAt(i)))
568                                            continue;
569                                    symTabEntry = (SymTabEntry)v.elementAt(i);
570                                    break;
571                            }
572    
573                    }
574    
575                    if(symTabEntry == null)
576                            throw new RPCException("Can't locate service entry in WSDL");
577                    return ((ServiceEntry)symTabEntry).getService();
578            }
579    
580            /**
581         * returns the WSDL Port
582             * @param service
583             * @return WSDL Port
584             * @throws RPCException
585             */
586            public Port getWSDLPort(javax.wsdl.Service service) throws RPCException {
587                    String name = null;
588                    Port port = null;
589                    List list = null;
590                    Map ports = service.getPorts();
591                    for(Iterator itr = ports.keySet().iterator(); itr.hasNext();) {
592                            name = (String)itr.next();
593                            port = (Port)ports.get(name);
594                            list = port.getExtensibilityElements();
595                            if(list != null) {
596                                    for(int i = 0; i < list.size(); i++)
597                                            if(list.get(i) instanceof SOAPAddress)
598                                                    return port;
599    
600                            }
601                    }
602                    throw new RPCException("Can't locate port entry for service " + service.getQName().toString() + " WSDL");
603            }
604    
605            private Object getArgumentData(TypeMapping tm,TimeZone tz, Parameter p, Object arg) throws PageException {
606                    QName paramType = Utils.getXSIType(p);
607                    Object o = AxisCaster.toAxisType(tm,tz,paramType,arg,null);
608            return o;
609            }
610    
611        /**
612         * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, java.lang.String)
613         */
614        public Object get(PageContext pc, String propertyName) throws PageException {
615            return call(pc,"get"+propertyName, ArrayUtil.OBJECT_EMPTY);
616        }
617    
618            /**
619             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key)
620             */
621            public Object get(PageContext pc, Collection.Key key) throws PageException {
622                    return get(pc, key.getString());
623            }
624    
625        /**
626         *
627         * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, java.lang.String, java.lang.Object)
628         */
629        public Object get(PageContext pc, String propertyName, Object defaultValue) {
630            try {
631                return call(pc,"get"+StringUtil.ucFirst(propertyName), ArrayUtil.OBJECT_EMPTY);
632            } catch (PageException e) {
633                return defaultValue;
634            }
635        }
636    
637            /**
638             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
639             */
640            public Object get(PageContext pc, Collection.Key key, Object defaultValue) {
641                    return get(pc, key.getString(), defaultValue); 
642            }
643    
644        /**
645         * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, java.lang.String, java.lang.Object)
646         */
647        public Object set(PageContext pc, String propertyName, Object value) throws PageException {
648            return call(pc,"set"+propertyName, new Object[]{value});
649        }
650    
651            /**
652             * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
653             */
654            public Object set(PageContext pc, Collection.Key propertyName, Object value) throws PageException {
655                    return set(pc, propertyName.toString(), value);
656            }
657    
658        /**
659         * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, java.lang.String, java.lang.Object)
660         */
661        public Object setEL(PageContext pc, String propertyName, Object value) {
662            try {
663                return call(pc,"set"+propertyName, new Object[]{value});
664            } catch (PageException e) {
665                return null;
666            }
667        }
668    
669            /**
670             * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
671             */
672            public Object setEL(PageContext pc, Collection.Key propertyName, Object value) {
673                    return setEL(pc, propertyName.toString(), value);
674            }
675    
676        /**
677         * @see railo.runtime.type.Objects#isInitalized()
678         */
679        public boolean isInitalized() {
680            return true;
681        }
682    
683        /**
684         *
685         * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int)
686         */
687        public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
688            try {
689                return _toDumpData(pageContext,maxlevel,dp);
690            } catch (Exception e) {
691                DumpTable table = new DumpTablePro("webservice","#ccccff","#cccc00","#000000");
692                table.appendRow(1,new SimpleDumpData("webservice"),new SimpleDumpData(wsdlUrl));
693                return table;
694            }
695        }
696        private DumpData _toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) throws RPCException {
697                    
698            DumpTable box = new DumpTablePro("webservice","#ccccff","#cccc00","#000000");
699            box.setTitle("Web Service");
700            if(dp.getMetainfo())box.appendRow(1,new SimpleDumpData("url"),new SimpleDumpData(wsdlUrl));
701            DumpTable functions = new DumpTable("#ccccff","#cccc00","#000000");
702            
703            
704            javax.wsdl.Service service = getWSDLService();
705            Port port = getWSDLPort(service);
706            Binding binding = port.getBinding();
707            
708         
709            //Parameters parameters = null;
710            //Parameter p = null;
711            SymbolTable symbolTable = parser.getSymbolTable();
712            BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
713            Iterator itr = bEntry.getParameters().keySet().iterator();
714            Operation tmpOp = null;
715            //Operation operation = null;
716            while(itr.hasNext())  {
717                tmpOp = (Operation)itr.next();
718                Element el = tmpOp.getDocumentationElement();
719                StringBuffer doc=new StringBuffer();
720                if(el!=null){
721                    NodeList children = XMLUtil.getChildNodes(el, Node.TEXT_NODE);
722                    int len=children.getLength();
723                    Text text;
724                    for(int i=0;i<len;i++){
725                            text=(Text) children.item(i);
726                            doc.append(text.getData());
727                    }
728                }
729                //parameters = (Parameters)bEntry.getParameters().get(tmpOp);
730                functions.appendRow(1,
731                            new SimpleDumpData(tmpOp.getName()),
732                            _toHTMLOperation(doc.toString(),(Parameters)bEntry.getParameters().get(tmpOp)));
733            }
734            
735            box.appendRow(1,new SimpleDumpData(""),functions);
736            return box;
737        }
738    
739        private DumpData _toHTMLOperation(String doc, Parameters parameters) {
740            DumpTable table = new DumpTable("#ccccff","#ccff66","#000000");
741            DumpTable attributes = new DumpTable("#ccccff","#ccff66","#000000");
742            String returns = "void";
743            attributes.appendRow(3,new SimpleDumpData("name"),new SimpleDumpData("type"));
744            
745            for(int j = 0; j < parameters.list.size(); j++) {
746                Parameter p = (Parameter)parameters.list.get(j);
747                
748                QName paramType = org.apache.axis.wsdl.toJava.Utils.getXSIType(p);
749                String strType=paramType.getLocalPart();
750                            
751                switch(p.getMode()) {
752                case Parameter.IN:
753                    attributes.appendRow(0,new SimpleDumpData(p.getName()),new SimpleDumpData(toRailoType(strType)));
754                break;
755                case Parameter.OUT:
756                    returns=toRailoType(strType);
757                break;
758                case Parameter.INOUT:
759                    attributes.appendRow(0,new SimpleDumpData(p.getName()),new SimpleDumpData(toRailoType(strType)));
760                    returns=toRailoType(strType);
761                    
762                break;
763                }
764            }
765            Parameter rtn = parameters.returnParam;
766            if(rtn!=null) {
767                QName paramType = org.apache.axis.wsdl.toJava.Utils.getXSIType(rtn);
768                String strType=paramType.getLocalPart();
769                returns=toRailoType(strType);
770            }
771            table.appendRow(1,new SimpleDumpData("arguments"),attributes);
772            table.appendRow(1,new SimpleDumpData("return type"),new SimpleDumpData(returns));
773            if(doc.length()>0)table.appendRow(1,new SimpleDumpData("hint"),new SimpleDumpData(doc));
774            
775            
776            return table;
777            
778        }
779        private String toRailoType(String strType) {
780            strType=strType.toLowerCase();
781            if(strType.startsWith("array"))strType="array";
782            else if(strType.equals("map"))strType="struct";
783            else if(strType.startsWith("query"))strType="query";
784            else if(strType.equals("double"))strType="numeric";
785            else if(strType.startsWith("any"))strType="any";
786            else if(strType.equals("date"))strType="date";
787            return strType;
788            }
789    
790            /**
791         * @see railo.runtime.op.Castable#castToString()
792         */
793        public String castToString() throws ExpressionException {
794            throw new RPCException("can't cast Webservice to a string");
795        }
796    
797            /**
798             * @see railo.runtime.op.Castable#castToString(java.lang.String)
799             */
800            public String castToString(String defaultValue) {
801                    return defaultValue;
802            }
803    
804        /**
805         * @see railo.runtime.op.Castable#castToBooleanValue()
806         */
807        public boolean castToBooleanValue() throws ExpressionException {
808            throw new RPCException("can't cast Webservice to a boolean");
809        }
810        
811        /**
812         * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean)
813         */
814        public Boolean castToBoolean(Boolean defaultValue) {
815            return defaultValue;
816        }
817    
818        /**
819         * @see railo.runtime.op.Castable#castToDoubleValue()
820         */
821        public double castToDoubleValue() throws ExpressionException {
822            throw new RPCException("can't cast Webservice to a number");
823        }
824        
825        /**
826         * @see railo.runtime.op.Castable#castToDoubleValue(double)
827         */
828        public double castToDoubleValue(double defaultValue) {
829            return defaultValue;
830        }
831    
832        /**
833         * @see railo.runtime.op.Castable#castToDateTime()
834         */
835        public DateTime castToDateTime() throws RPCException {
836            throw new RPCException("can't cast Webservice to a Date Object");
837        }
838        
839        /**
840         * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime)
841         */
842        public DateTime castToDateTime(DateTime defaultValue) {
843            return defaultValue;
844        }
845    
846            /**
847             * @see railo.runtime.op.Castable#compare(boolean)
848             */
849            public int compareTo(boolean b) throws ExpressionException {
850                    throw new ExpressionException("can't compare Webservice Object with a boolean value");
851            }
852    
853            /**
854             * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime)
855             */
856            public int compareTo(DateTime dt) throws PageException {
857                    throw new ExpressionException("can't compare Webservice Object with a DateTime Object");
858            }
859    
860            /**
861             * @see railo.runtime.op.Castable#compareTo(double)
862             */
863            public int compareTo(double d) throws PageException {
864                    throw new ExpressionException("can't compare Webservice Object with a numeric value");
865            }
866    
867            /**
868             * @see railo.runtime.op.Castable#compareTo(java.lang.String)
869             */
870            public int compareTo(String str) throws PageException {
871                    throw new ExpressionException("can't compare Webservice Object with a String");
872            }
873    
874        /**
875         * @see railo.runtime.type.Iteratorable#keyIterator()
876         */
877        public Iterator keyIterator() {
878            List list=new ArrayList();
879            javax.wsdl.Service service = null;
880            Port port = null;
881            try {
882                    service = getWSDLService();
883                port = getWSDLPort(service);
884            }
885            catch(Exception e) {
886                    return new ArrayIterator(ArrayUtil.OBJECT_EMPTY);
887            }
888            
889            Binding binding = port.getBinding();
890            
891            SymbolTable symbolTable = parser.getSymbolTable();
892            BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
893            Iterator itr = bEntry.getParameters().keySet().iterator();
894            Operation tmpOp = null;
895            //Operation operation = null;
896            while(itr.hasNext())  {
897                tmpOp = (Operation)itr.next();
898                //Parameters p = (Parameters)bEntry.getParameters().get(tmpOp);
899                list.add(tmpOp.getName());
900                
901            }
902            return new ArrayIterator(list.toArray());
903        }
904            /**
905             *
906             * @see railo.runtime.type.Iteratorable#iterator()
907             */
908            public Iterator iterator() {
909                    return keyIterator();
910            }
911    
912            /**
913             * @see railo.runtime.type.Iteratorable#valueIterator()
914             */
915            public Iterator valueIterator() {
916                    return new ObjectsIterator(keyIterator(),this);
917            }
918    
919            public Call getLastCall() {
920                    return last;
921            }
922    
923            public void addHeader(SOAPHeaderElement header) {
924                    if(headers==null)headers=new ArrayList<SOAPHeaderElement>();
925                    headers.add(header);
926            }
927    }