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 }