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