001    package railo.runtime.net.rpc.server;
002    
003    import java.io.IOException;
004    import java.io.InputStream;
005    import java.io.PrintWriter;
006    import java.lang.reflect.InvocationTargetException;
007    import java.lang.reflect.Method;
008    import java.util.Enumeration;
009    import java.util.HashMap;
010    import java.util.Iterator;
011    import java.util.Map;
012    import java.util.WeakHashMap;
013    
014    import javax.servlet.ServletContext;
015    import javax.servlet.ServletException;
016    import javax.servlet.http.HttpServletRequest;
017    import javax.servlet.http.HttpServletResponse;
018    import javax.servlet.http.HttpUtils;
019    import javax.xml.namespace.QName;
020    import javax.xml.soap.MimeHeader;
021    import javax.xml.soap.MimeHeaders;
022    import javax.xml.soap.SOAPException;
023    import javax.xml.soap.SOAPMessage;
024    
025    import org.apache.axis.AxisEngine;
026    import org.apache.axis.AxisFault;
027    import org.apache.axis.ConfigurationException;
028    import org.apache.axis.Constants;
029    import org.apache.axis.Handler;
030    import org.apache.axis.Message;
031    import org.apache.axis.MessageContext;
032    import org.apache.axis.SimpleChain;
033    import org.apache.axis.SimpleTargetedChain;
034    import org.apache.axis.components.logger.LogFactory;
035    import org.apache.axis.encoding.TypeMappingRegistry;
036    import org.apache.axis.management.ServiceAdmin;
037    import org.apache.axis.security.servlet.ServletSecurityProvider;
038    import org.apache.axis.server.AxisServer;
039    import org.apache.axis.transport.http.AxisHttpSession;
040    import org.apache.axis.transport.http.FilterPrintWriter;
041    import org.apache.axis.transport.http.HTTPConstants;
042    import org.apache.axis.transport.http.ServletEndpointContextImpl;
043    import org.apache.axis.utils.Messages;
044    import org.apache.commons.logging.Log;
045    import org.w3c.dom.Element;
046    
047    import railo.commons.io.IOUtil;
048    import railo.commons.lang.ClassException;
049    import railo.commons.lang.ClassUtil;
050    import railo.runtime.Component;
051    import railo.runtime.exp.PageException;
052    import railo.runtime.exp.PageServletException;
053    import railo.runtime.net.rpc.TypeMappingUtil;
054    import railo.runtime.op.Caster;
055    
056    /**
057     * xdoclet tags are not active yet; keep web.xml in sync.
058     * To change the location of the services, change url-pattern in web.xml and
059     * set parameter axis.servicesPath in server-config.wsdd. For more information see
060     * <a href="http://ws.apache.org/axis/java/reference.html">Axis Reference Guide</a>.
061     */
062    public final class RPCServer{
063    
064            protected static Log log =LogFactory.getLog(RPCServer.class.getName());
065        private static Log tlog =LogFactory.getLog(Constants.TIME_LOG_CATEGORY);
066        private static Log exceptionLog =LogFactory.getLog(Constants.EXCEPTION_LOG_CATEGORY);
067    
068        public static final String INIT_PROPERTY_TRANSPORT_NAME ="transport.name";
069        public static final String INIT_PROPERTY_USE_SECURITY ="use-servlet-security";
070        public static final String INIT_PROPERTY_ENABLE_LIST ="axis.enableListQuery";
071        public static final String INIT_PROPERTY_JWS_CLASS_DIR ="axis.jws.servletClassDir";
072        public static final String INIT_PROPERTY_DISABLE_SERVICES_LIST ="axis.disableServiceList";
073        public static final String INIT_PROPERTY_SERVICES_PATH ="axis.servicesPath";
074    
075        private Handler transport;
076        private ServletSecurityProvider securityProvider = null;
077            private ServletContext context;
078            private String webInfPath;
079            private String homeDir;
080            private AxisServer axisServer;
081            private org.apache.axis.encoding.TypeMapping typeMapping;
082            
083            private static boolean isDevelopment=false;
084            private static boolean isDebug = false;
085            private static Map servers=new WeakHashMap();
086    
087    
088        /**
089         * Initialization method.
090         * @throws AxisFault 
091         */
092        private RPCServer(ServletContext context) throws AxisFault {
093            this.context=context;
094            
095            initQueryStringHandlers();
096            ServiceAdmin.setEngine(this.getEngine(), context.getServerInfo());
097            
098            webInfPath = context.getRealPath("/WEB-INF");
099            homeDir = context.getRealPath("/");
100            
101        }
102        
103    
104    
105    
106        /**
107         * Process GET requests. This includes handoff of pseudo-SOAP requests
108         *
109         * @param request request in
110         * @param response request out
111         * @throws ServletException
112         */
113        public void doGet(HttpServletRequest request, HttpServletResponse response, Component component) throws ServletException {
114            PrintWriter writer = new FilterPrintWriter(response);
115            
116            try {
117                            if (!doGet(request, response, writer,component)) {
118                                    response.setContentType("text/html; charset=utf-8");
119                    writer.println("<html><h1>Railo Webservice</h1>");
120                    writer.println(Messages.getMessage("reachedServlet00"));
121                    writer.println("<p>" + Messages.getMessage("transportName00","<b>http</b>"));
122                    writer.println("</html>");
123                            }
124                    } 
125            catch (Throwable e) {
126                    if(e instanceof InvocationTargetException)
127                            e= ((InvocationTargetException)e).getTargetException();
128                    if(e instanceof PageException)
129                    throw new PageServletException((PageException)e);
130                    throw new ServletException(e);
131                    }
132        }
133    
134        /**
135         * routine called whenever an axis fault is caught; where they
136         * are logged and any other business. The method may modify the fault
137         * in the process
138         * @param fault what went wrong.
139         */
140        private void processAxisFault(AxisFault fault) {
141            //log the fault
142            Element runtimeException = fault.lookupFaultDetail(
143                    Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
144            if (runtimeException != null) {
145                exceptionLog.info(Messages.getMessage("axisFault00"), fault);
146                //strip runtime details
147                fault.removeFaultDetail(Constants.
148                                        QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
149            } else if (exceptionLog.isDebugEnabled()) {
150                exceptionLog.debug(Messages.getMessage("axisFault00"), fault);
151            }
152            //dev systems only give fault dumps
153            //if (!isDevelopment()) {
154                //strip out the stack trace
155                fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE);
156            //}
157        }
158    
159        /**
160         * log any exception to our output log, at our chosen level
161         * @param e what went wrong
162         */
163        private void logException(Throwable e) {
164            exceptionLog.info(Messages.getMessage("exception00"), e);
165        }
166    
167        /* *
168         * print a snippet of service info.
169         * @param service service
170         * @param writer output channel
171         * @param serviceName where to put stuff
172         * /
173        private void reportServiceInfo(HttpServletResponse response,
174                                         PrintWriter writer, SOAPService service,
175                                         String serviceName) {
176            response.setContentType("text/html; charset=utf-8");
177    
178            writer.println("<h1>"
179                           + service.getName()
180                           + "</h1>");
181            writer.println(
182                    "<p>" +
183                    Messages.getMessage("axisService00") +
184                    "</p>");
185            writer.println(
186                    "<i>" +
187                    Messages.getMessage("perhaps00") +
188                    "</i>");
189        }*/
190    
191    
192    
193    
194    
195        /**
196         * Process a POST to the servlet by handing it off to the Axis Engine.
197         * Here is where SOAP messages are received
198         * @param req posted request
199         * @param res respose
200         * @throws ServletException trouble
201         * @throws IOException different trouble
202         */
203        public void doPost(HttpServletRequest req, HttpServletResponse res, Component component) throws
204                ServletException, IOException {
205            long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
206            String soapAction = null;
207            MessageContext msgContext = null;
208            
209            Message responseMsg = null;
210            String contentType = null;
211            InputStream is=null;
212            try {
213                AxisEngine engine = getEngine();
214    
215                if (engine == null) {
216                    // !!! should return a SOAP fault...
217                    ServletException se =
218                            new ServletException(Messages.getMessage("noEngine00"));
219                    log.debug("No Engine!", se);
220                    throw se;
221                }
222    
223                res.setBufferSize(1024 * 8); // provide performance boost.
224    
225                /** get message context w/ various properties set
226                 */
227                msgContext = createMessageContext(engine, req, res,component);
228    
229                // ? OK to move this to 'getMessageContext',
230                // ? where it would also be picked up for 'doGet()' ?
231                if (securityProvider != null) {
232                    if (isDebug) {
233                        log.debug("securityProvider:" + securityProvider);
234                    }
235                    msgContext.setProperty(MessageContext.SECURITY_PROVIDER,
236                                           securityProvider);
237                }
238    
239                is=req.getInputStream();
240                Message requestMsg =
241                        new Message(is,
242                                    false,
243                                    req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE),
244                                    req.getHeader(HTTPConstants.
245                                                  HEADER_CONTENT_LOCATION));
246                // Transfer HTTP headers to MIME headers for request message.
247                MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders();
248                for (Enumeration e = req.getHeaderNames(); e.hasMoreElements(); ) {
249                    String headerName = (String) e.nextElement();
250                    for (Enumeration f = req.getHeaders(headerName);
251                                         f.hasMoreElements(); ) {
252                        String headerValue = (String) f.nextElement();
253                        requestMimeHeaders.addHeader(headerName, headerValue);
254                    }
255                }
256    
257                if (isDebug) {
258                    log.debug("Request Message:" + requestMsg);
259    
260                    /* Set the request(incoming) message field in the context */
261                    /**********************************************************/
262                }
263                msgContext.setRequestMessage(requestMsg);
264                String url = HttpUtils.getRequestURL(req).toString();
265                msgContext.setProperty(MessageContext.TRANS_URL, url);
266                // put character encoding of request to message context
267                // in order to reuse it during the whole process.
268                String requestEncoding;
269                try {
270                    requestEncoding = (String) requestMsg.getProperty(SOAPMessage.
271                            CHARACTER_SET_ENCODING);
272                    if (requestEncoding != null) {
273                        msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING,
274                                               requestEncoding);
275                    }
276                } catch (SOAPException e1) {
277                    
278                }
279    
280                try {
281                    /**
282                     * Save the SOAPAction header in the MessageContext bag.
283                     * This will be used to tell the Axis Engine which service
284                     * is being invoked.  This will save us the trouble of
285                     * having to parse the Request message - although we will
286                     * need to double-check later on that the SOAPAction header
287                     * does in fact match the URI in the body.
288                     */
289                    // (is this last stmt true??? (I don't think so - Glen))
290                    /********************************************************/
291                    soapAction = getSoapAction(req);
292                    if (soapAction != null) {
293                        msgContext.setUseSOAPAction(true);
294                        msgContext.setSOAPActionURI(soapAction);
295                    }
296    
297                    // Create a Session wrapper for the HTTP session.
298                    // These can/should be pooled at some point.
299                    // (Sam is Watching! :-)
300                    msgContext.setSession(new AxisHttpSession(req));
301    
302                    if (tlog.isDebugEnabled()) {
303                        t1 = System.currentTimeMillis();
304                    }
305                    /* Invoke the Axis engine... */
306                    /*****************************/
307                    if (isDebug) {
308                        log.debug("Invoking Axis Engine.");
309                        //here we run the message by the engine
310                    }
311                    
312                    engine.invoke(msgContext);
313                    if (isDebug) {
314                        log.debug("Return from Axis Engine.");
315                    }
316                    if (tlog.isDebugEnabled()) {
317                        t2 = System.currentTimeMillis();
318                    }
319                    responseMsg = msgContext.getResponseMessage();
320    
321                    // We used to throw exceptions on null response messages.
322                    // They are actually OK in certain situations (asynchronous
323                    // services), so fall through here and return an ACCEPTED
324                    // status code below.  Might want to install a configurable
325                    // error check for this later.
326                } catch (AxisFault fault) {
327                    
328                    //log and sanitize
329                    processAxisFault(fault);
330                    configureResponseFromAxisFault(res, fault);
331                    responseMsg = msgContext.getResponseMessage();
332                    if (responseMsg == null) {
333                        responseMsg = new Message(fault);
334                        ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).
335                                getMessage().setMessageContext(msgContext);
336                    }
337                } catch (Throwable t) {
338                    if(t instanceof InvocationTargetException)
339                            t=((InvocationTargetException)t).getTargetException();
340                    // Exception
341                    if(t instanceof Exception) {
342                            Exception e=(Exception) t;
343                            //other exceptions are internal trouble
344                            responseMsg = msgContext.getResponseMessage();
345                            res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
346                            responseMsg = convertExceptionToAxisFault(e, responseMsg);
347                            ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).
348                                    getMessage().setMessageContext(msgContext);
349                            
350                    }
351                    // throwable
352                    else {
353                            logException(t);
354                        //other exceptions are internal trouble
355                        responseMsg = msgContext.getResponseMessage();
356                        res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
357                        responseMsg = new Message(new AxisFault(t.toString(),t));
358                        ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).
359                                getMessage().setMessageContext(msgContext);
360                    }
361                } 
362            } catch (AxisFault fault) {
363                    
364                processAxisFault(fault);
365                configureResponseFromAxisFault(res, fault);
366                responseMsg = msgContext.getResponseMessage();
367                if (responseMsg == null) {
368                    responseMsg = new Message(fault);
369                    ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).
370                            getMessage().setMessageContext(msgContext);
371                }
372            }
373            finally {
374                    IOUtil.closeEL(is);
375            }
376    
377            if (tlog.isDebugEnabled()) {
378                t3 = System.currentTimeMillis();
379            }
380    
381            /* Send response back along the wire...  */
382            /***********************************/
383            if (responseMsg != null) {
384                // Transfer MIME headers to HTTP headers for response message.
385                MimeHeaders responseMimeHeaders = responseMsg.getMimeHeaders();
386                for (Iterator i = responseMimeHeaders.getAllHeaders(); i.hasNext(); ) {
387                    MimeHeader responseMimeHeader = (MimeHeader) i.next();
388                    res.addHeader(responseMimeHeader.getName(),
389                                  responseMimeHeader.getValue());
390                }
391                // synchronize the character encoding of request and response
392                String responseEncoding = (String) msgContext.getProperty(
393                        SOAPMessage.CHARACTER_SET_ENCODING);
394                if (responseEncoding != null) {
395                    try {
396                        responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING,
397                                                responseEncoding);
398                    } catch (SOAPException e) {
399                    }
400                }
401                //determine content type from message response
402                contentType = responseMsg.getContentType(msgContext.
403                        getSOAPConstants());
404                sendResponse(contentType, res, responseMsg);
405            } else {
406                // No content, so just indicate accepted
407                res.setStatus(202);
408            }
409            
410            if (isDebug) {
411                log.debug("Response sent.");
412                log.debug("Exit: doPost()");
413            }
414            if (tlog.isDebugEnabled()) {
415                t4 = System.currentTimeMillis();
416                tlog.debug("axisServlet.doPost: " + soapAction +
417                           " pre=" + (t1 - t0) +
418                           " invoke=" + (t2 - t1) +
419                           " post=" + (t3 - t2) +
420                           " send=" + (t4 - t3) +
421                           " " + msgContext.getTargetService() + "." +
422                           ((msgContext.getOperation() == null) ?
423                            "" : msgContext.getOperation().getName()));
424            }
425    
426        }
427    
428        /**
429         * Configure the servlet response status code and maybe other headers
430         * from the fault info.
431         * @param response response to configure
432         * @param fault what went wrong
433         */
434        private void configureResponseFromAxisFault(HttpServletResponse response,
435                                                    AxisFault fault) {
436            // then get the status code
437            // It's been suggested that a lack of SOAPAction
438            // should produce some other error code (in the 400s)...
439            int status = getHttpServletResponseStatus(fault);
440            if (status == HttpServletResponse.SC_UNAUTHORIZED) {
441                response.setHeader("WWW-Authenticate", "Basic realm=\"AXIS\"");
442            }
443            response.setStatus(status);
444        }
445    
446        /**
447         * turn any Exception into an AxisFault, log it, set the response
448         * status code according to what the specifications say and
449         * return a response message for posting. This will be the response
450         * message passed in if non-null; one generated from the fault otherwise.
451         *
452         * @param exception what went wrong
453         * @param responseMsg what response we have (if any)
454         * @return a response message to send to the user
455         */
456        private Message convertExceptionToAxisFault(Exception exception,
457                                                    Message responseMsg) {
458            logException(exception);
459            if (responseMsg == null) {
460                AxisFault fault = AxisFault.makeFault(exception);
461                processAxisFault(fault);
462                responseMsg = new Message(fault);
463            }
464            return responseMsg;
465        }
466    
467        /**
468         * Extract information from AxisFault and map it to a HTTP Status code.
469         *
470         * @param af Axis Fault
471         * @return HTTP Status code.
472         */
473        private int getHttpServletResponseStatus(AxisFault af) {
474            // subclasses... --Glen
475            return af.getFaultCode().getLocalPart().startsWith("Server.Unauth")
476                    ? HttpServletResponse.SC_UNAUTHORIZED
477                    : HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
478            // This will raise a 401 for both
479            // "Unauthenticated" & "Unauthorized"...
480        }
481    
482        /**
483         * write a message to the response, set appropriate headers for content
484         * type..etc.
485         * @param res   response
486         * @param responseMsg message to write
487         * @throws AxisFault
488         * @throws IOException if the response stream can not be written to
489         */
490        private void sendResponse(String contentType,
491                                  HttpServletResponse res,
492                                  Message responseMsg) throws AxisFault,
493                IOException {
494            if (responseMsg == null) {
495                res.setStatus(HttpServletResponse.SC_NO_CONTENT);
496                if (isDebug) {
497                    log.debug("NO AXIS MESSAGE TO RETURN!");
498                }
499            } else {
500                if (isDebug) {
501                    log.debug("Returned Content-Type:" +
502                              contentType);
503                    // log.debug("Returned Content-Length:" +
504                    //          responseMsg.getContentLength());
505                }
506    
507                try {
508                    res.setContentType(contentType);
509    
510                    responseMsg.writeTo(res.getOutputStream());
511                } catch (SOAPException e) {
512                    logException(e);
513                }
514            }
515    
516            if (!res.isCommitted()) {
517                res.flushBuffer(); // Force it right now.
518            }
519        }
520    
521        /**
522         * Place the Request message in the MessagContext object - notice
523         * that we just leave it as a 'ServletRequest' object and let the
524         * Message processing routine convert it - we don't do it since we
525         * don't know how it's going to be used - perhaps it might not
526         * even need to be parsed.
527         * @return a message context
528         */
529        private MessageContext createMessageContext(AxisEngine engine, HttpServletRequest req, HttpServletResponse res, Component component) {
530            MessageContext msgContext = new MessageContext(engine);
531    
532            String requestPath = getRequestPath(req);
533    
534            if (isDebug) {
535                log.debug("MessageContext:" + msgContext);
536                log.debug("HEADER_CONTENT_TYPE:" +
537                          req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
538                log.debug("HEADER_CONTENT_LOCATION:" +
539                          req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
540                log.debug("Constants.MC_HOME_DIR:" + String.valueOf(homeDir));
541                log.debug("Constants.MC_RELATIVE_PATH:" + requestPath);
542                log.debug("HTTPConstants.MC_HTTP_SERVLETLOCATION:" +String.valueOf(webInfPath));
543                log.debug("HTTPConstants.MC_HTTP_SERVLETPATHINFO:" +req.getPathInfo());
544                log.debug("HTTPConstants.HEADER_AUTHORIZATION:" +req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
545                log.debug("Constants.MC_REMOTE_ADDR:" + req.getRemoteAddr());
546                log.debug("configPath:" + String.valueOf(webInfPath));
547            }
548    
549            /* Set the Transport */
550            /*********************/
551            msgContext.setTransportName("http");
552    
553            /* Save some HTTP specific info in the bag in case someone needs it */
554            /********************************************************************/
555            //msgContext.setProperty(Constants.MC_JWS_CLASSDIR, jwsClassDir);
556            msgContext.setProperty(Constants.MC_HOME_DIR, homeDir);
557            msgContext.setProperty(Constants.MC_RELATIVE_PATH, requestPath);
558            msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this);
559            msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req);
560            msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res);
561            msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION,webInfPath);
562            msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO,req.getPathInfo());
563            msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION,req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
564            msgContext.setProperty(railo.runtime.net.rpc.server.Constants.COMPONENT, component);
565            msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr());
566            
567            // Set up a javax.xml.rpc.server.ServletEndpointContext
568            ServletEndpointContextImpl sec = new ServletEndpointContextImpl();
569    
570            msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);
571            /* Save the real path */
572            /**********************/
573            String realpath = context.getRealPath(requestPath);
574    
575            if (realpath != null) {
576                msgContext.setProperty(Constants.MC_REALPATH, realpath);
577            }
578    
579            msgContext.setProperty(Constants.MC_CONFIGPATH, webInfPath);
580    
581            return msgContext;
582        }
583    
584        /**
585         * Extract the SOAPAction header.
586         * if SOAPAction is null then we'll we be forced to scan the body for it.
587         * if SOAPAction is "" then use the URL
588         * @param req incoming request
589         * @return the action
590         * @throws AxisFault
591         */
592        private String getSoapAction(HttpServletRequest req) throws AxisFault {
593            String soapAction = req.getHeader(HTTPConstants.HEADER_SOAP_ACTION);
594            if (soapAction == null) {
595                String contentType = req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
596                if(contentType != null) {
597                    int index = contentType.indexOf("action");
598                    if(index != -1){
599                        soapAction = contentType.substring(index + 7);
600                    }
601                }
602            }
603    
604            if (isDebug) {
605                log.debug("HEADER_SOAP_ACTION:" + soapAction);
606    
607                /**
608                 * Technically, if we don't find this header, we should probably fault.
609                 * It's required in the SOAP HTTP binding.
610                 */
611            }
612            if (soapAction == null) {
613                AxisFault af = new AxisFault("Client.NoSOAPAction",
614                                             Messages.getMessage("noHeader00",
615                        "SOAPAction"),
616                                             null, null);
617    
618                exceptionLog.error(Messages.getMessage("genFault00"), af);
619    
620                throw af;
621            }
622            // the SOAP 1.1 spec & WS-I 1.0 says:
623            // soapaction    = "SOAPAction" ":" [ <"> URI-reference <"> ]
624            // some implementations leave off the quotes
625            // we strip them if they are present
626            if (soapAction.startsWith("\"") && soapAction.endsWith("\"")
627                && soapAction.length() >= 2) {
628                int end = soapAction.length() - 1;
629                soapAction = soapAction.substring(1, end);
630            }
631    
632            if (soapAction.length() == 0) {
633                soapAction = req.getContextPath(); // Is this right?
634    
635            }
636            return soapAction;
637        }
638    
639    
640        /**
641         * Initialize a Handler for the transport defined in the Axis server config.
642         * This includes optionally filling in query string handlers.
643         */
644    
645        public void initQueryStringHandlers() {
646                this.transport = new SimpleTargetedChain();
647                this.transport.setOption("qs.list","org.apache.axis.transport.http.QSListHandler");
648                this.transport.setOption("qs.method","org.apache.axis.transport.http.QSMethodHandler");
649                this.transport.setOption("qs.wsdl","org.apache.axis.transport.http.QSWSDLHandler");
650                
651        }
652        
653        private boolean doGet(HttpServletRequest request,HttpServletResponse response,PrintWriter writer,Component component) throws AxisFault, ClassException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException  {
654    
655            String path = request.getServletPath();
656            String queryString = request.getQueryString();
657            
658            AxisEngine engine = getEngine();
659            
660            Iterator i = this.transport.getOptions().keySet().iterator();
661    
662            if (queryString == null) {
663                return false;
664            }
665    
666            String servletURI = request.getContextPath() + path;
667            String reqURI = request.getRequestURI();
668            
669            // service name
670            String serviceName;
671            if (servletURI.length() + 1 < reqURI.length()) {
672                serviceName = reqURI.substring(servletURI.length() + 1);
673            } else {
674                serviceName = "";
675            } 
676            
677            while (i.hasNext()) {
678                String queryHandler = (String) i.next();
679                //print.ln("queryhandler:"+queryHandler);
680                if (queryHandler.startsWith("qs.")) {
681                    // Only attempt to match the query string with transport
682                    // parameters prefixed with "qs:".
683    
684                    String handlerName = queryHandler.substring
685                                         (queryHandler.indexOf(".") + 1).
686                                         toLowerCase();
687                    //print.ln("handlerName:"+handlerName);
688                    // Determine the name of the plugin to invoke by using all text
689                    // in the query string up to the first occurence of &, =, or the
690                    // whole string if neither is present.
691    
692                    int length = 0;
693                    boolean firstParamFound = false;
694    
695                    while (firstParamFound == false && length < queryString.length()) {
696                        char ch = queryString.charAt(length++);
697    
698                        if (ch == '&' || ch == '=') {
699                            firstParamFound = true;
700    
701                            --length;
702                        }
703                    }
704    
705                    if (length < queryString.length()) {
706                        queryString = queryString.substring(0, length);
707                    }
708    
709                    if (queryString.toLowerCase().equals(handlerName) == true) {
710                        // Query string matches a defined query string handler name.
711    
712                        // If the defined class name for this query string handler is blank,
713                        // just return (the handler is "turned off" in effect).
714    
715                        if (this.transport.getOption(queryHandler).equals("")) {
716                            return false;
717                        }
718    
719                            // Attempt to dynamically load the query string handler
720                            // and its "invoke" method.
721    
722                            MessageContext msgContext = createMessageContext(engine,request, response,component);
723                            Class plugin=ClassUtil.loadClass((String)this.transport.getOption(queryHandler));
724                            Method pluginMethod = plugin.getDeclaredMethod("invoke", new Class[] {msgContext.getClass()});
725    
726                            msgContext.setProperty(MessageContext.TRANS_URL, HttpUtils.getRequestURL(request).toString());
727                            //msgContext.setProperty(MessageContext.TRANS_URL, "http://DefaultNamespace");
728                            msgContext.setProperty(HTTPConstants.PLUGIN_SERVICE_NAME, serviceName);
729                            msgContext.setProperty(HTTPConstants.PLUGIN_NAME,handlerName);
730                            msgContext.setProperty(HTTPConstants.PLUGIN_IS_DEVELOPMENT,Caster.toBoolean(isDevelopment));
731                            msgContext.setProperty(HTTPConstants.PLUGIN_ENABLE_LIST,Boolean.FALSE);
732                            msgContext.setProperty(HTTPConstants.PLUGIN_ENGINE,engine);
733                            msgContext.setProperty(HTTPConstants.PLUGIN_WRITER,writer);
734                            msgContext.setProperty(HTTPConstants.PLUGIN_LOG, log);
735                            msgContext.setProperty(HTTPConstants.PLUGIN_EXCEPTION_LOG,exceptionLog);
736                            
737                            // Invoke the plugin.
738                            pluginMethod.invoke(ClassUtil.loadInstance(plugin),new Object[] {msgContext});
739                            writer.close();
740    
741                            return true;
742                        
743                    }
744                }
745            }
746    
747            return false;
748        }
749        
750    
751        /**
752         * getRequestPath a returns request path for web service padded with
753         * request.getPathInfo for web services served from /services directory.
754         * This is a required to support serving .jws web services from /services
755         * URL. See AXIS-843 for more information.
756         *
757         * @param request HttpServletRequest
758         * @return String
759         */
760        private static String getRequestPath(HttpServletRequest request) {
761            return request.getServletPath() + ((request.getPathInfo() != null) ?
762                                               request.getPathInfo() : "");
763        }
764        
765    
766        /**
767         * get the engine for this Server from cache or context
768         * @return
769         * @throws AxisFault 
770         */
771        public AxisServer getEngine() throws AxisFault {
772            if (axisServer == null) {
773                synchronized (context) {
774                    Map environment = new HashMap();
775                    environment.put(AxisEngine.ENV_SERVLET_CONTEXT, context);
776                    axisServer = AxisServer.getServer(environment);
777                    axisServer.setName("RailoCFC");
778                }
779                
780                // add Component Handler
781                try {
782                                    SimpleChain sc=(SimpleChain) axisServer.getGlobalRequest();
783                                    sc.addHandler(new ComponentHandler());  
784                            }
785                catch (ConfigurationException e) {
786                                    throw AxisFault.makeFault(e);
787                            }
788                TypeMappingUtil.registerDefaults(axisServer.getTypeMappingRegistry());
789                
790            }
791            return axisServer;
792        }
793        
794            public static RPCServer getInstance(int id, ServletContext servletContext) throws AxisFault {
795                    RPCServer server=(RPCServer) servers.get(Caster.toString(id));
796                    if(server==null){
797                            servers.put(Caster.toString(id), server=new RPCServer(servletContext));
798                    }
799                    return server;
800            }
801    
802    
803    
804    
805            public void registerTypeMapping(Class clazz) {
806                    String fullname = clazz.getName();//,name,packages;
807                    QName qname = new QName("http://DefaultNamespace",fullname);
808                    registerTypeMapping(clazz, qname);
809            }
810            
811            private void registerTypeMapping(Class clazz,QName qname) {
812                    TypeMappingRegistry reg = axisServer.getTypeMappingRegistry();
813                    
814                    org.apache.axis.encoding.TypeMapping tm;
815                    tm=reg.getOrMakeTypeMapping("http://schemas.xmlsoap.org/soap/encoding/");
816                    Class c = tm.getClassForQName(qname);
817                    if(c!=null && c!=clazz) {
818                            tm.removeDeserializer(c, qname);
819                            tm.removeSerializer(c, qname);
820                    }
821                    TypeMappingUtil.registerBeanTypeMapping(tm,clazz, qname);
822            }
823    }