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