- 浏览: 537025 次
- 性别:
- 来自: 中华大丈夫学院
文章分类
最新评论
-
lxmin0702:
你好,我刚下载了您的附件,但是发现里面并没有正文所提到的Lis ...
SWT中ole/activex实践--操作word的一个例子 -
kkkwoai:
我想请教下 我有个要求是实现ppt解析为图片,用的是jac ...
Office 开发: 现实生活中的 OBA 解决方案模式 -
pengshan:
However, the mutability of the ...
【翻译】Spring Integration参考手册-第二章 -
kms1989:
导出pdf中文乱码怎么搞?
jsPDF介绍与兼容IE的补丁 -
kms1989:
你好,请问不支持中文怎么解决?
jsPDF介绍与兼容IE的补丁
webservice相对于其他的rpc来说,报文数据实在太大了,所以,来回双向的gzip是个不错的方案。
webservice调用一般走soap over http, 响应的报文,可以通过在应用服务器端配置gzip(比如tomcat)来做。
客户端如果发送的请求报文数据时gzip的,axis2支持,axis是不支持的。
axis2通过设置
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.MC_GZIP_REQUEST, Boolean.TRUE);
即可实现请求的http报文头添加Content-Encoding: gzip,报文体为gzip过的soap。
服务器端拿到Content-Encoding,一看为gzip,自动解压过处理。
而axis的AxisServlet实现里,并没有判断Content-Encoding,所以不支持。
继承AxisServlet,添加如上axis2的处理步骤即可使axis支持gzip的请求。
把这个类复制到项目,然后把web.xml中的AxisServlet的class改成这个。
package org.qsoft.axis; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.zip.GZIPInputStream; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpUtils; import javax.xml.soap.MimeHeader; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import org.apache.axis.AxisEngine; import org.apache.axis.AxisFault; import org.apache.axis.ConfigurationException; import org.apache.axis.Constants; import org.apache.axis.Handler; import org.apache.axis.Message; import org.apache.axis.MessageContext; import org.apache.axis.SimpleTargetedChain; import org.apache.axis.components.logger.LogFactory; import org.apache.axis.description.OperationDesc; import org.apache.axis.description.ServiceDesc; import org.apache.axis.handlers.soap.SOAPService; import org.apache.axis.management.ServiceAdmin; import org.apache.axis.security.servlet.ServletSecurityProvider; import org.apache.axis.transport.http.AxisHttpSession; import org.apache.axis.transport.http.AxisServlet; import org.apache.axis.transport.http.FilterPrintWriter; import org.apache.axis.transport.http.HTTPConstants; import org.apache.axis.transport.http.HTTPTransport; import org.apache.axis.transport.http.ServletEndpointContextImpl; import org.apache.axis.utils.JavaUtils; import org.apache.axis.utils.Messages; import org.apache.axis.utils.XMLUtils; import org.apache.commons.logging.Log; import org.w3c.dom.Element; /** * Servlet implementation class QsoftAxisServlet */ public class QsoftAxisServlet extends AxisServlet { private static final long serialVersionUID = -1530368108781213835L; protected static Log log = LogFactory.getLog(QsoftAxisServlet.class.getName()); /** * this log is for timing */ private static Log tlog = LogFactory.getLog(Constants.TIME_LOG_CATEGORY); /** * a separate log for exceptions lets users route them differently from * general low level debug info */ private static Log exceptionLog = LogFactory.getLog(Constants.EXCEPTION_LOG_CATEGORY); // These have default values. private String transportName; private Handler transport; private ServletSecurityProvider securityProvider = null; private String servicesPath; /** * cache of logging debug option; only evaluated at init time. So no dynamic * switching of logging options with this servlet. */ private static boolean isDebug = false; /** * Should we enable the "?list" functionality on GETs? (off by default * because deployment information is a potential security hole) */ private boolean enableList = false; /** * Should we turn off the list of services when we receive a GET at the * servlet root? */ private boolean disableServicesList = false; /** * Cached path to JWS output directory */ private String jwsClassDir = null; protected String getJWSClassDir() { return jwsClassDir; } /** * create a new servlet instance */ public QsoftAxisServlet() { } /** * Initialization method. */ public void init() throws javax.servlet.ServletException { // super.init(); ServletContext context = getServletConfig().getServletContext(); isDebug = log.isDebugEnabled(); if (isDebug) { log.debug("In servlet init"); } transportName = getOption(context, INIT_PROPERTY_TRANSPORT_NAME, HTTPTransport.DEFAULT_TRANSPORT_NAME); if (JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_USE_SECURITY, null))) { securityProvider = new ServletSecurityProvider(); } enableList = JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_ENABLE_LIST, null)); jwsClassDir = getOption(context, INIT_PROPERTY_JWS_CLASS_DIR, null); // Should we list services? disableServicesList = JavaUtils.isTrue(getOption(context, INIT_PROPERTY_DISABLE_SERVICES_LIST, "false")); servicesPath = getOption(context, INIT_PROPERTY_SERVICES_PATH, "/services/"); /** * There are DEFINATE problems here if getHomeDir and/or * getDefaultJWSClassDir return null (as they could with WebLogic). This * needs to be reexamined in the future, but this should fix any NPE's * in the mean time. */ if (jwsClassDir != null) { if (getHomeDir() != null) { jwsClassDir = getHomeDir() + jwsClassDir; } } else { jwsClassDir = getDefaultJWSClassDir(); } initQueryStringHandlers(); // Setup the service admin try { ServiceAdmin.setEngine(this.getEngine(), context.getServerInfo()); } catch (AxisFault af) { exceptionLog.info("Exception setting AxisEngine on ServiceAdmin " + af); } } /** * Process GET requests. This includes handoff of pseudo-SOAP requests * * @param request * request in * @param response * request out * @throws ServletException * @throws IOException */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (isDebug) { log.debug("Enter: doGet()"); } PrintWriter writer = new FilterPrintWriter(response); try { AxisEngine engine = getEngine(); ServletContext servletContext = getServletConfig().getServletContext(); String pathInfo = request.getPathInfo(); String realpath = servletContext.getRealPath(request.getServletPath()); if (realpath == null) { realpath = request.getServletPath(); } // JWS pages are special; they are the servlet path and there // is no pathinfo...we map the pathinfo to the servlet path to keep // it happy boolean isJWSPage = request.getRequestURI().endsWith(".jws"); if (isJWSPage) { pathInfo = request.getServletPath(); } // Try to execute a query string plugin and return upon success. if (processQuery(request, response, writer) == true) { return; } boolean hasNoPath = (pathInfo == null || pathInfo.equals("")); if (!disableServicesList) { if (hasNoPath) { // If the user requested the servlet (i.e. // /axis/servlet/AxisServlet) // with no service name, present the user with a list of // deployed // services to be helpful // Don't do this if has been turned off reportAvailableServices(response, writer, request); } else if (realpath != null) { // We have a pathname, so now we perform WSDL or list // operations // get message context w/ various properties set MessageContext msgContext = createMessageContext(engine, request, response); // NOTE: HttpUtils.getRequestURL has been deprecated. // This line SHOULD be: // String url = req.getRequestURL().toString() // HOWEVER!!!! DON'T REPLACE IT! There's a bug in // req.getRequestURL that is not in HttpUtils.getRequestURL // req.getRequestURL returns "localhost" in the remote // scenario rather than the actual host name. // // But more importantly, getRequestURL() is a servlet 2.3 // API and to support servlet 2.2 (aka WebSphere 4) // we need to leave this in for a while longer. tomj // 10/14/2004 // String url = HttpUtils.getRequestURL(request).toString(); msgContext.setProperty(MessageContext.TRANS_URL, url); // See if we can locate the desired service. If we // can't, return a 404 Not Found. Otherwise, just // print the placeholder message. String serviceName; if (pathInfo.startsWith("/")) { serviceName = pathInfo.substring(1); } else { serviceName = pathInfo; } SOAPService s = engine.getService(serviceName); if (s == null) { // no service: report it if (isJWSPage) { reportCantGetJWSService(request, response, writer); } else { reportCantGetAxisService(request, response, writer); } } else { // print a snippet of service info. reportServiceInfo(response, writer, s, serviceName); } } } else { // We didn't have a real path in the request, so just // print a message informing the user that they reached // the servlet. response.setContentType("text/html; charset=utf-8"); writer.println("<html><h1>Axis HTTP Servlet</h1>"); writer.println(Messages.getMessage("reachedServlet00")); writer.println("<p>" + Messages.getMessage("transportName00", "<b>" + transportName + "</b>")); writer.println("</html>"); } } catch (AxisFault fault) { reportTroubleInGet(fault, response, writer); } catch (Exception e) { reportTroubleInGet(e, response, writer); } finally { writer.close(); if (isDebug) { log.debug("Exit: doGet()"); } } } /** * when we get an exception or an axis fault in a GET, we handle it almost * identically: we go 'something went wrong', set the response code to 500 * and then dump info. But we dump different info for an axis fault or * subclass thereof. * * @param exception * what went wrong * @param response * current response * @param writer * open writer to response */ private void reportTroubleInGet(Throwable exception, HttpServletResponse response, PrintWriter writer) { response.setContentType("text/html; charset=utf-8"); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); writer.println("<h2>" + Messages.getMessage("error00") + "</h2>"); writer.println("<p>" + Messages.getMessage("somethingWrong00") + "</p>"); if (exception instanceof AxisFault) { AxisFault fault = (AxisFault) exception; processAxisFault(fault); writeFault(writer, fault); } else { logException(exception); writer.println("<pre>Exception - " + exception + "<br>"); // dev systems only give fault dumps if (isDevelopment()) { writer.println(JavaUtils.stackToString(exception)); } writer.println("</pre>"); } } /** * routine called whenever an axis fault is caught; where they are logged * and any other business. The method may modify the fault in the process * * @param fault * what went wrong. */ protected void processAxisFault(AxisFault fault) { // log the fault Element runtimeException = fault.lookupFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION); if (runtimeException != null) { exceptionLog.info(Messages.getMessage("axisFault00"), fault); // strip runtime details fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION); } else if (exceptionLog.isDebugEnabled()) { exceptionLog.debug(Messages.getMessage("axisFault00"), fault); } // dev systems only give fault dumps if (!isDevelopment()) { // strip out the stack trace fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE); } } /** * log any exception to our output log, at our chosen level * * @param e * what went wrong */ protected void logException(Throwable e) { exceptionLog.info(Messages.getMessage("exception00"), e); } /** * this method writes a fault out to an HTML stream. This includes escaping * the strings to defend against cross-site scripting attacks * * @param writer * @param axisFault */ private void writeFault(PrintWriter writer, AxisFault axisFault) { String localizedMessage = XMLUtils.xmlEncodeString(axisFault.getLocalizedMessage()); writer.println("<pre>Fault - " + localizedMessage + "<br>"); writer.println(axisFault.dumpToString()); writer.println("</pre>"); } /** * print a snippet of service info. * * @param service * service * @param writer * output channel * @param serviceName * where to put stuff */ protected void reportServiceInfo(HttpServletResponse response, PrintWriter writer, SOAPService service, String serviceName) { response.setContentType("text/html; charset=utf-8"); writer.println("<h1>" + service.getName() + "</h1>"); writer.println("<p>" + Messages.getMessage("axisService00") + "</p>"); writer.println("<i>" + Messages.getMessage("perhaps00") + "</i>"); } /** * report that we have no WSDL * * This method was moved to the querystring handler QSWSDLHandler. The * method reportNoWSDL in AxisServlet is never called. Perhaps the method is * overwritten in subclasses of AxisServlet so the method wasn't removed. * See the discussion in * * http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23845 * * @param res * @param writer * @param moreDetailCode * optional name of a message to provide more detail * @param axisFault * optional fault string, for extra info at debug time only */ protected void reportNoWSDL(HttpServletResponse res, PrintWriter writer, String moreDetailCode, AxisFault axisFault) { } /** * This method lists the available services; it is called when there is * nothing to execute on a GET * * @param response * @param writer * @param request * @throws ConfigurationException * @throws AxisFault */ protected void reportAvailableServices(HttpServletResponse response, PrintWriter writer, HttpServletRequest request) throws ConfigurationException, AxisFault { AxisEngine engine = getEngine(); response.setContentType("text/html; charset=utf-8"); writer.println("<h2>And now... Some Services</h2>"); Iterator i; try { i = engine.getConfig().getDeployedServices(); } catch (ConfigurationException configException) { // turn any internal configuration exceptions back into axis faults // if that is what they are if (configException.getContainedException() instanceof AxisFault) { throw (AxisFault) configException.getContainedException(); } else { throw configException; } } // baseURL may change if <endpointURL> tag is used for // custom deployment at a different location String defaultBaseURL = getWebappBase(request) + servicesPath; writer.println("<ul>"); while (i.hasNext()) { ServiceDesc sd = (ServiceDesc) i.next(); StringBuffer sb = new StringBuffer(); sb.append("<li>"); String name = sd.getName(); sb.append(name); sb.append(" <a href=\""); String endpointURL = sd.getEndpointURL(); String baseURL = (endpointURL == null) ? defaultBaseURL : endpointURL; sb.append(baseURL); sb.append(name); sb.append("?wsdl\"><i>(wsdl)</i></a></li>"); writer.println(sb.toString()); ArrayList operations = sd.getOperations(); if (!operations.isEmpty()) { writer.println("<ul>"); for (Iterator it = operations.iterator(); it.hasNext();) { OperationDesc desc = (OperationDesc) it.next(); writer.println("<li>" + desc.getName()); } writer.println("</ul>"); } } writer.println("</ul>"); } /** * generate the error response to indicate that there is apparently no * endpoint there * * @param request * the request that didnt have an edpoint * @param response * response we are generating * @param writer * open writer for the request */ protected void reportCantGetAxisService(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) { // no such service.... response.setStatus(HttpURLConnection.HTTP_NOT_FOUND); response.setContentType("text/html; charset=utf-8"); writer.println("<h2>" + Messages.getMessage("error00") + "</h2>"); writer.println("<p>" + Messages.getMessage("noService06") + "</p>"); } /** * probe for a JWS page and report 'no service' if one is not found there * * @param request * the request that didnt have an edpoint * @param response * response we are generating * @param writer * open writer for the request */ protected void reportCantGetJWSService(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) { // first look to see if there is a service // requestPath is a work around to support serving .jws web services // from services URL - see AXIS-843 for more information String requestPath = request.getServletPath() + ((request.getPathInfo() != null) ? request.getPathInfo() : ""); String realpath = getServletConfig().getServletContext().getRealPath(requestPath); log.debug("JWS real path: " + realpath); boolean foundJWSFile = (new File(realpath).exists()) && (realpath.endsWith(Constants.JWS_DEFAULT_FILE_EXTENSION)); response.setContentType("text/html; charset=utf-8"); if (foundJWSFile) { response.setStatus(HttpURLConnection.HTTP_OK); writer.println(Messages.getMessage("foundJWS00") + "<p>"); String url = request.getRequestURI(); String urltext = Messages.getMessage("foundJWS01"); writer.println("<a href='" + url + "?wsdl'>" + urltext + "</a>"); } else { response.setStatus(HttpURLConnection.HTTP_NOT_FOUND); writer.println(Messages.getMessage("noService06")); } } /** * Process a POST to the servlet by handing it off to the Axis Engine. Here * is where SOAP messages are received * * @param req * posted request * @param res * respose * @throws ServletException * trouble * @throws IOException * different trouble */ public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; String soapAction = null; MessageContext msgContext = null; if (isDebug) { log.debug("Enter: doPost()"); } if (tlog.isDebugEnabled()) { t0 = System.currentTimeMillis(); } Message responseMsg = null; String contentType = null; try { AxisEngine engine = getEngine(); if (engine == null) { // !!! should return a SOAP fault... ServletException se = new ServletException(Messages.getMessage("noEngine00")); log.debug("No Engine!", se); throw se; } res.setBufferSize(1024 * 8); // provide performance boost. /** * get message context w/ various properties set */ msgContext = createMessageContext(engine, req, res); // ? OK to move this to 'getMessageContext', // ? where it would also be picked up for 'doGet()' ? if (securityProvider != null) { if (isDebug) { log.debug("securityProvider:" + securityProvider); } msgContext.setProperty(MessageContext.SECURITY_PROVIDER, securityProvider); } /* * Get request message modified by kimmking Content-Encoding: gzip */ Message requestMsg = null; String contentEncoding = req.getHeader("Content-Encoding"); log.debug("Content-Encoding:" + contentEncoding); if ("gzip".equalsIgnoreCase(contentEncoding)) { byte[] bytes = inputStreamToByteArray(req.getInputStream()); String soap = new String(bytes, "utf-8"); log.debug("SOAP ==> " + soap); requestMsg = new Message(bytes, false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION)); } else { requestMsg = new Message(req.getInputStream(), false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION)); } // Transfer HTTP headers to MIME headers for request message. MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders(); for (Enumeration e = req.getHeaderNames(); e.hasMoreElements();) { String headerName = (String) e.nextElement(); for (Enumeration f = req.getHeaders(headerName); f.hasMoreElements();) { String headerValue = (String) f.nextElement(); requestMimeHeaders.addHeader(headerName, headerValue); } } if (isDebug) { log.debug("Request Message:" + requestMsg); /* Set the request(incoming) message field in the context */ /**********************************************************/ } msgContext.setRequestMessage(requestMsg); String url = HttpUtils.getRequestURL(req).toString(); msgContext.setProperty(MessageContext.TRANS_URL, url); // put character encoding of request to message context // in order to reuse it during the whole process. String requestEncoding; try { requestEncoding = (String) requestMsg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING); if (requestEncoding != null) { msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestEncoding); } } catch (SOAPException e1) { } try { /** * Save the SOAPAction header in the MessageContext bag. This * will be used to tell the Axis Engine which service is being * invoked. This will save us the trouble of having to parse the * Request message - although we will need to double-check later * on that the SOAPAction header does in fact match the URI in * the body. */ // (is this last stmt true??? (I don't think so - Glen)) /********************************************************/ soapAction = getSoapAction(req); if (soapAction != null) { msgContext.setUseSOAPAction(true); msgContext.setSOAPActionURI(soapAction); } // Create a Session wrapper for the HTTP session. // These can/should be pooled at some point. // (Sam is Watching! :-) msgContext.setSession(new AxisHttpSession(req)); if (tlog.isDebugEnabled()) { t1 = System.currentTimeMillis(); } /* Invoke the Axis engine... */ /*****************************/ if (isDebug) { log.debug("Invoking Axis Engine."); // here we run the message by the engine } engine.invoke(msgContext); if (isDebug) { log.debug("Return from Axis Engine."); } if (tlog.isDebugEnabled()) { t2 = System.currentTimeMillis(); } responseMsg = msgContext.getResponseMessage(); // We used to throw exceptions on null response messages. // They are actually OK in certain situations (asynchronous // services), so fall through here and return an ACCEPTED // status code below. Might want to install a configurable // error check for this later. } catch (AxisFault fault) { // log and sanitize processAxisFault(fault); configureResponseFromAxisFault(res, fault); responseMsg = msgContext.getResponseMessage(); if (responseMsg == null) { responseMsg = new Message(fault); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext); } } catch (Exception e) { // other exceptions are internal trouble responseMsg = msgContext.getResponseMessage(); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); responseMsg = convertExceptionToAxisFault(e, responseMsg); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext); } catch (Throwable t) { logException(t); // other exceptions are internal trouble responseMsg = msgContext.getResponseMessage(); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); responseMsg = new Message(new AxisFault(t.toString(), t)); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext); } } catch (AxisFault fault) { processAxisFault(fault); configureResponseFromAxisFault(res, fault); responseMsg = msgContext.getResponseMessage(); if (responseMsg == null) { responseMsg = new Message(fault); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext); } } if (tlog.isDebugEnabled()) { t3 = System.currentTimeMillis(); } /* Send response back along the wire... */ /***********************************/ if (responseMsg != null) { // Transfer MIME headers to HTTP headers for response message. MimeHeaders responseMimeHeaders = responseMsg.getMimeHeaders(); for (Iterator i = responseMimeHeaders.getAllHeaders(); i.hasNext();) { MimeHeader responseMimeHeader = (MimeHeader) i.next(); res.addHeader(responseMimeHeader.getName(), responseMimeHeader.getValue()); } // synchronize the character encoding of request and response String responseEncoding = (String) msgContext.getProperty(SOAPMessage.CHARACTER_SET_ENCODING); if (responseEncoding != null) { try { responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, responseEncoding); } catch (SOAPException e) { } } // determine content type from message response contentType = responseMsg.getContentType(msgContext.getSOAPConstants()); sendResponse(contentType, res, responseMsg); } else { // No content, so just indicate accepted res.setStatus(202); } if (isDebug) { log.debug("Response sent."); log.debug("Exit: doPost()"); } if (tlog.isDebugEnabled()) { t4 = System.currentTimeMillis(); tlog.debug("axisServlet.doPost: " + soapAction + " pre=" + (t1 - t0) + " invoke=" + (t2 - t1) + " post=" + (t3 - t2) + " send=" + (t4 - t3) + " " + msgContext.getTargetService() + "." + ((msgContext.getOperation() == null) ? "" : msgContext.getOperation().getName())); } } /** * Configure the servlet response status code and maybe other headers from * the fault info. * * @param response * response to configure * @param fault * what went wrong */ private void configureResponseFromAxisFault(HttpServletResponse response, AxisFault fault) { // then get the status code // It's been suggested that a lack of SOAPAction // should produce some other error code (in the 400s)... int status = getHttpServletResponseStatus(fault); if (status == HttpServletResponse.SC_UNAUTHORIZED) { // unauth access results in authentication request // TODO: less generic realm choice? response.setHeader("WWW-Authenticate", "Basic realm=\"AXIS\""); } response.setStatus(status); } /** * turn any Exception into an AxisFault, log it, set the response status * code according to what the specifications say and return a response * message for posting. This will be the response message passed in if * non-null; one generated from the fault otherwise. * * @param exception * what went wrong * @param responseMsg * what response we have (if any) * @return a response message to send to the user */ private Message convertExceptionToAxisFault(Exception exception, Message responseMsg) { logException(exception); if (responseMsg == null) { AxisFault fault = AxisFault.makeFault(exception); processAxisFault(fault); responseMsg = new Message(fault); } return responseMsg; } /** * Extract information from AxisFault and map it to a HTTP Status code. * * @param af * Axis Fault * @return HTTP Status code. */ protected int getHttpServletResponseStatus(AxisFault af) { // TODO: Should really be doing this with explicit AxisFault // subclasses... --Glen return af.getFaultCode().getLocalPart().startsWith("Server.Unauth") ? HttpServletResponse.SC_UNAUTHORIZED : HttpServletResponse.SC_INTERNAL_SERVER_ERROR; // This will raise a 401 for both // "Unauthenticated" & "Unauthorized"... } /** * write a message to the response, set appropriate headers for content * type..etc. * * @param res * response * @param responseMsg * message to write * @throws AxisFault * @throws IOException * if the response stream can not be written to */ private void sendResponse(String contentType, HttpServletResponse res, Message responseMsg) throws AxisFault, IOException { if (responseMsg == null) { res.setStatus(HttpServletResponse.SC_NO_CONTENT); if (isDebug) { log.debug("NO AXIS MESSAGE TO RETURN!"); // String resp = Messages.getMessage("noData00"); // res.setContentLength((int) resp.getBytes().length); // res.getWriter().print(resp); } } else { if (isDebug) { log.debug("Returned Content-Type:" + contentType); // log.debug("Returned Content-Length:" + // responseMsg.getContentLength()); } try { res.setContentType(contentType); /* * My understand of Content-Length HTTP 1.0 -Required for * requests, but optional for responses. HTTP 1.1 - Either * Content-Length or HTTP Chunking is required. Most servlet * engines will do chunking if content-length is not specified. */ // if(clientVersion == HTTPConstants.HEADER_PROTOCOL_V10) //do // chunking if necessary. // res.setContentLength(responseMsg.getContentLength()); responseMsg.writeTo(res.getOutputStream()); } catch (SOAPException e) { logException(e); } } if (!res.isCommitted()) { res.flushBuffer(); // Force it right now. } } /** * Place the Request message in the MessagContext object - notice that we * just leave it as a 'ServletRequest' object and let the Message processing * routine convert it - we don't do it since we don't know how it's going to * be used - perhaps it might not even need to be parsed. * * @return a message context */ private MessageContext createMessageContext(AxisEngine engine, HttpServletRequest req, HttpServletResponse res) { MessageContext msgContext = new MessageContext(engine); String requestPath = getRequestPath(req); if (isDebug) { log.debug("MessageContext:" + msgContext); log.debug("HEADER_CONTENT_TYPE:" + req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE)); log.debug("HEADER_CONTENT_LOCATION:" + req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION)); log.debug("Constants.MC_HOME_DIR:" + String.valueOf(getHomeDir())); log.debug("Constants.MC_RELATIVE_PATH:" + requestPath); log.debug("HTTPConstants.MC_HTTP_SERVLETLOCATION:" + String.valueOf(getWebInfPath())); log.debug("HTTPConstants.MC_HTTP_SERVLETPATHINFO:" + req.getPathInfo()); log.debug("HTTPConstants.HEADER_AUTHORIZATION:" + req.getHeader(HTTPConstants.HEADER_AUTHORIZATION)); log.debug("Constants.MC_REMOTE_ADDR:" + req.getRemoteAddr()); log.debug("configPath:" + String.valueOf(getWebInfPath())); } /* Set the Transport */ /*********************/ msgContext.setTransportName(transportName); /* Save some HTTP specific info in the bag in case someone needs it */ /********************************************************************/ msgContext.setProperty(Constants.MC_JWS_CLASSDIR, jwsClassDir); msgContext.setProperty(Constants.MC_HOME_DIR, getHomeDir()); msgContext.setProperty(Constants.MC_RELATIVE_PATH, requestPath); msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this); msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req); msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res); msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION, getWebInfPath()); msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO, req.getPathInfo()); msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION, req.getHeader(HTTPConstants.HEADER_AUTHORIZATION)); msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr()); // Set up a javax.xml.rpc.server.ServletEndpointContext ServletEndpointContextImpl sec = new ServletEndpointContextImpl(); msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec); /* Save the real path */ /**********************/ String realpath = getServletConfig().getServletContext().getRealPath(requestPath); if (realpath != null) { msgContext.setProperty(Constants.MC_REALPATH, realpath); } msgContext.setProperty(Constants.MC_CONFIGPATH, getWebInfPath()); return msgContext; } /** * Extract the SOAPAction header. if SOAPAction is null then we'll we be * forced to scan the body for it. if SOAPAction is "" then use the URL * * @param req * incoming request * @return the action * @throws AxisFault */ private String getSoapAction(HttpServletRequest req) throws AxisFault { String soapAction = req.getHeader(HTTPConstants.HEADER_SOAP_ACTION); if (soapAction == null) { String contentType = req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE); if (contentType != null) { int index = contentType.indexOf("action"); if (index != -1) { soapAction = contentType.substring(index + 7); } } } if (isDebug) { log.debug("HEADER_SOAP_ACTION:" + soapAction); /** * Technically, if we don't find this header, we should probably * fault. It's required in the SOAP HTTP binding. */ } if (soapAction == null) { AxisFault af = new AxisFault("Client.NoSOAPAction", Messages.getMessage("noHeader00", "SOAPAction"), null, null); exceptionLog.error(Messages.getMessage("genFault00"), af); throw af; } // the SOAP 1.1 spec & WS-I 1.0 says: // soapaction = "SOAPAction" ":" [ <"> URI-reference <"> ] // some implementations leave off the quotes // we strip them if they are present if (soapAction.startsWith("\"") && soapAction.endsWith("\"") && soapAction.length() >= 2) { int end = soapAction.length() - 1; soapAction = soapAction.substring(1, end); } if (soapAction.length() == 0) { soapAction = req.getContextPath(); // Is this right? } return soapAction; } /** * Provided to allow overload of default JWSClassDir by derived class. * * @return directory for JWS files */ protected String getDefaultJWSClassDir() { return (getWebInfPath() == null) ? null // ??? what is a good FINAL // default for WebLogic? : getWebInfPath() + File.separator + "jwsClasses"; } /** * Initialize a Handler for the transport defined in the Axis server config. * This includes optionally filling in query string handlers. */ public void initQueryStringHandlers() { try { this.transport = getEngine().getTransport(this.transportName); if (this.transport == null) { // No transport by this name is defined. Therefore, fill in // default // query string handlers. this.transport = new SimpleTargetedChain(); this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler"); this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler"); this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler"); return; } else { // See if we should use the default query string handlers. // By default, set this to true (for backwards compatibility). boolean defaultQueryStrings = true; String useDefaults = (String) this.transport.getOption("useDefaultQueryStrings"); if ((useDefaults != null) && useDefaults.toLowerCase().equals("false")) { defaultQueryStrings = false; } if (defaultQueryStrings == true) { // We should use defaults, so fill them in. this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler"); this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler"); this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler"); } } } catch (AxisFault e) { // Some sort of problem occurred, let's just make a default // transport. this.transport = new SimpleTargetedChain(); this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler"); this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler"); this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler"); return; } } /** * Attempts to invoke a plugin for the query string supplied in the URL. * * @param request * the servlet's HttpServletRequest object. * @param response * the servlet's HttpServletResponse object. * @param writer * the servlet's PrintWriter object. */ private boolean processQuery(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) throws AxisFault { // Attempt to instantiate a plug-in handler class for the query string // handler classes defined in the HTTP transport. String path = request.getServletPath(); String queryString = request.getQueryString(); String serviceName; AxisEngine engine = getEngine(); Iterator i = this.transport.getOptions().keySet().iterator(); if (queryString == null) { return false; } String servletURI = request.getContextPath() + path; String reqURI = request.getRequestURI(); // chop off '/'. if (servletURI.length() + 1 < reqURI.length()) { serviceName = reqURI.substring(servletURI.length() + 1); } else { serviceName = ""; } while (i.hasNext() == true) { String queryHandler = (String) i.next(); if (queryHandler.startsWith("qs.") == true) { // Only attempt to match the query string with transport // parameters prefixed with "qs:". String handlerName = queryHandler.substring(queryHandler.indexOf(".") + 1).toLowerCase(); // Determine the name of the plugin to invoke by using all text // in the query string up to the first occurence of &, =, or the // whole string if neither is present. int length = 0; boolean firstParamFound = false; while (firstParamFound == false && length < queryString.length()) { char ch = queryString.charAt(length++); if (ch == '&' || ch == '=') { firstParamFound = true; --length; } } if (length < queryString.length()) { queryString = queryString.substring(0, length); } if (queryString.toLowerCase().equals(handlerName) == true) { // Query string matches a defined query string handler name. // If the defined class name for this query string handler // is blank, // just return (the handler is "turned off" in effect). if (this.transport.getOption(queryHandler).equals("")) { return false; } try { // Attempt to dynamically load the query string handler // and its "invoke" method. MessageContext msgContext = createMessageContext(engine, request, response); Class plugin = Class.forName((String) this.transport.getOption(queryHandler)); Method pluginMethod = plugin.getDeclaredMethod("invoke", new Class[] { msgContext.getClass() }); String url = HttpUtils.getRequestURL(request).toString(); // Place various useful servlet-related objects in // the MessageContext object being delivered to the // plugin. msgContext.setProperty(MessageContext.TRANS_URL, url); msgContext.setProperty(HTTPConstants.PLUGIN_SERVICE_NAME, serviceName); msgContext.setProperty(HTTPConstants.PLUGIN_NAME, handlerName); msgContext.setProperty(HTTPConstants.PLUGIN_IS_DEVELOPMENT, new Boolean(isDevelopment())); msgContext.setProperty(HTTPConstants.PLUGIN_ENABLE_LIST, new Boolean(enableList)); msgContext.setProperty(HTTPConstants.PLUGIN_ENGINE, engine); msgContext.setProperty(HTTPConstants.PLUGIN_WRITER, writer); msgContext.setProperty(HTTPConstants.PLUGIN_LOG, log); msgContext.setProperty(HTTPConstants.PLUGIN_EXCEPTION_LOG, exceptionLog); // Invoke the plugin. pluginMethod.invoke(plugin.newInstance(), new Object[] { msgContext }); writer.close(); return true; } catch (InvocationTargetException ie) { reportTroubleInGet(ie.getTargetException(), response, writer); // return true to prevent any further processing return true; } catch (Exception e) { reportTroubleInGet(e, response, writer); // return true to prevent any further processing return true; } } } } return false; } /** * getRequestPath a returns request path for web service padded with * request.getPathInfo for web services served from /services directory. * This is a required to support serving .jws web services from /services * URL. See AXIS-843 for more information. * * @param request * HttpServletRequest * @return String */ private static String getRequestPath(HttpServletRequest request) { return request.getServletPath() + ((request.getPathInfo() != null) ? request.getPathInfo() : ""); } public static byte[] inputStreamToByteArray(InputStream is) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPInputStream gis = new GZIPInputStream (is); int i = -1; byte[] bs = new byte[1024]; while ((i = gis.read(bs)) != -1) { baos.write(bs,0,i); } gis.close(); return baos.toByteArray(); } }
评论
1 楼
geminiyellow
2010-09-18
<div class="quote_title">kimmking 写道</div><div class="quote_div"><p>webservice相对于其他的rpc来说,报文数据实在太大了,所以,来回双向的gzip是个不错的方案。</p>
<p>webservice调用一般走soap over http, 响应的报文,可以通过在应用服务器端配置gzip(比如tomcat)来做。</p>
<p> </p>
<p> </p>
<p>客户端如果发送的请求报文数据时gzip的,axis2支持,axis是不支持的。</p>
<p> </p>
<p>axis2通过设置</p>
<p>options.setProperty(org.apache.axis2.transport.http.HTTPConstants.MC_GZIP_REQUEST, Boolean.TRUE);</p>
<p>即可实现请求的http报文头添加Content-Encoding: gzip,报文体为gzip过的soap。</p>
<p>服务器端拿到Content-Encoding,一看为gzip,自动解压过处理。</p>
<p> </p>
<p>而axis的AxisServlet实现里,并没有判断Content-Encoding,所以不支持。</p>
<p>继承AxisServlet,添加如上axis2的处理步骤即可使axis支持gzip的请求。</p>
<p> </p>
<p>把这个类复制到项目,然后把web.xml中的AxisServlet的class改成这个。</p>
<p> </p>
<p> </p>
<pre name="code" class="java">package org.qsoft.axis;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.GZIPInputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.apache.axis.AxisEngine;
import org.apache.axis.AxisFault;
import org.apache.axis.ConfigurationException;
import org.apache.axis.Constants;
import org.apache.axis.Handler;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.SimpleTargetedChain;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.description.ServiceDesc;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.management.ServiceAdmin;
import org.apache.axis.security.servlet.ServletSecurityProvider;
import org.apache.axis.transport.http.AxisHttpSession;
import org.apache.axis.transport.http.AxisServlet;
import org.apache.axis.transport.http.FilterPrintWriter;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.transport.http.HTTPTransport;
import org.apache.axis.transport.http.ServletEndpointContextImpl;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.XMLUtils;
import org.apache.commons.logging.Log;
import org.w3c.dom.Element;
/**
* Servlet implementation class QsoftAxisServlet
*/
public class QsoftAxisServlet extends AxisServlet {
private static final long serialVersionUID = -1530368108781213835L;
protected static Log log = LogFactory.getLog(QsoftAxisServlet.class.getName());
/**
* this log is for timing
*/
private static Log tlog = LogFactory.getLog(Constants.TIME_LOG_CATEGORY);
/**
* a separate log for exceptions lets users route them differently from
* general low level debug info
*/
private static Log exceptionLog = LogFactory.getLog(Constants.EXCEPTION_LOG_CATEGORY);
// These have default values.
private String transportName;
private Handler transport;
private ServletSecurityProvider securityProvider = null;
private String servicesPath;
/**
* cache of logging debug option; only evaluated at init time. So no dynamic
* switching of logging options with this servlet.
*/
private static boolean isDebug = false;
/**
* Should we enable the "?list" functionality on GETs? (off by default
* because deployment information is a potential security hole)
*/
private boolean enableList = false;
/**
* Should we turn off the list of services when we receive a GET at the
* servlet root?
*/
private boolean disableServicesList = false;
/**
* Cached path to JWS output directory
*/
private String jwsClassDir = null;
protected String getJWSClassDir() {
return jwsClassDir;
}
/**
* create a new servlet instance
*/
public QsoftAxisServlet() {
}
/**
* Initialization method.
*/
public void init() throws javax.servlet.ServletException {
// super.init();
ServletContext context = getServletConfig().getServletContext();
isDebug = log.isDebugEnabled();
if (isDebug) {
log.debug("In servlet init");
}
transportName = getOption(context, INIT_PROPERTY_TRANSPORT_NAME, HTTPTransport.DEFAULT_TRANSPORT_NAME);
if (JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_USE_SECURITY, null))) {
securityProvider = new ServletSecurityProvider();
}
enableList = JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_ENABLE_LIST, null));
jwsClassDir = getOption(context, INIT_PROPERTY_JWS_CLASS_DIR, null);
// Should we list services?
disableServicesList = JavaUtils.isTrue(getOption(context, INIT_PROPERTY_DISABLE_SERVICES_LIST, "false"));
servicesPath = getOption(context, INIT_PROPERTY_SERVICES_PATH, "/services/");
/**
* There are DEFINATE problems here if getHomeDir and/or
* getDefaultJWSClassDir return null (as they could with WebLogic). This
* needs to be reexamined in the future, but this should fix any NPE's
* in the mean time.
*/
if (jwsClassDir != null) {
if (getHomeDir() != null) {
jwsClassDir = getHomeDir() + jwsClassDir;
}
} else {
jwsClassDir = getDefaultJWSClassDir();
}
initQueryStringHandlers();
// Setup the service admin
try {
ServiceAdmin.setEngine(this.getEngine(), context.getServerInfo());
} catch (AxisFault af) {
exceptionLog.info("Exception setting AxisEngine on ServiceAdmin " + af);
}
}
/**
* Process GET requests. This includes handoff of pseudo-SOAP requests
*
* @param request
* request in
* @param response
* request out
* @throws ServletException
* @throws IOException
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (isDebug) {
log.debug("Enter: doGet()");
}
PrintWriter writer = new FilterPrintWriter(response);
try {
AxisEngine engine = getEngine();
ServletContext servletContext = getServletConfig().getServletContext();
String pathInfo = request.getPathInfo();
String realpath = servletContext.getRealPath(request.getServletPath());
if (realpath == null) {
realpath = request.getServletPath();
}
// JWS pages are special; they are the servlet path and there
// is no pathinfo...we map the pathinfo to the servlet path to keep
// it happy
boolean isJWSPage = request.getRequestURI().endsWith(".jws");
if (isJWSPage) {
pathInfo = request.getServletPath();
}
// Try to execute a query string plugin and return upon success.
if (processQuery(request, response, writer) == true) {
return;
}
boolean hasNoPath = (pathInfo == null || pathInfo.equals(""));
if (!disableServicesList) {
if (hasNoPath) {
// If the user requested the servlet (i.e.
// /axis/servlet/AxisServlet)
// with no service name, present the user with a list of
// deployed
// services to be helpful
// Don't do this if has been turned off
reportAvailableServices(response, writer, request);
} else if (realpath != null) {
// We have a pathname, so now we perform WSDL or list
// operations
// get message context w/ various properties set
MessageContext msgContext = createMessageContext(engine, request, response);
// NOTE: HttpUtils.getRequestURL has been deprecated.
// This line SHOULD be:
// String url = req.getRequestURL().toString()
// HOWEVER!!!! DON'T REPLACE IT! There's a bug in
// req.getRequestURL that is not in HttpUtils.getRequestURL
// req.getRequestURL returns "localhost" in the remote
// scenario rather than the actual host name.
//
// But more importantly, getRequestURL() is a servlet 2.3
// API and to support servlet 2.2 (aka WebSphere 4)
// we need to leave this in for a while longer. tomj
// 10/14/2004
//
String url = HttpUtils.getRequestURL(request).toString();
msgContext.setProperty(MessageContext.TRANS_URL, url);
// See if we can locate the desired service. If we
// can't, return a 404 Not Found. Otherwise, just
// print the placeholder message.
String serviceName;
if (pathInfo.startsWith("/")) {
serviceName = pathInfo.substring(1);
} else {
serviceName = pathInfo;
}
SOAPService s = engine.getService(serviceName);
if (s == null) {
// no service: report it
if (isJWSPage) {
reportCantGetJWSService(request, response, writer);
} else {
reportCantGetAxisService(request, response, writer);
}
} else {
// print a snippet of service info.
reportServiceInfo(response, writer, s, serviceName);
}
}
} else {
// We didn't have a real path in the request, so just
// print a message informing the user that they reached
// the servlet.
response.setContentType("text/html; charset=utf-8");
writer.println("<html><h1>Axis HTTP Servlet</h1>");
writer.println(Messages.getMessage("reachedServlet00"));
writer.println("<p>" + Messages.getMessage("transportName00", "<b>" + transportName + "</b>"));
writer.println("</html>");
}
} catch (AxisFault fault) {
reportTroubleInGet(fault, response, writer);
} catch (Exception e) {
reportTroubleInGet(e, response, writer);
} finally {
writer.close();
if (isDebug) {
log.debug("Exit: doGet()");
}
}
}
/**
* when we get an exception or an axis fault in a GET, we handle it almost
* identically: we go 'something went wrong', set the response code to 500
* and then dump info. But we dump different info for an axis fault or
* subclass thereof.
*
* @param exception
* what went wrong
* @param response
* current response
* @param writer
* open writer to response
*/
private void reportTroubleInGet(Throwable exception, HttpServletResponse response, PrintWriter writer) {
response.setContentType("text/html; charset=utf-8");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
writer.println("<h2>" + Messages.getMessage("error00") + "</h2>");
writer.println("<p>" + Messages.getMessage("somethingWrong00") + "</p>");
if (exception instanceof AxisFault) {
AxisFault fault = (AxisFault) exception;
processAxisFault(fault);
writeFault(writer, fault);
} else {
logException(exception);
writer.println("<pre>Exception - " + exception + "<br>");
// dev systems only give fault dumps
if (isDevelopment()) {
writer.println(JavaUtils.stackToString(exception));
}
writer.println("</pre>");
}
}
/**
* routine called whenever an axis fault is caught; where they are logged
* and any other business. The method may modify the fault in the process
*
* @param fault
* what went wrong.
*/
protected void processAxisFault(AxisFault fault) {
// log the fault
Element runtimeException = fault.lookupFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
if (runtimeException != null) {
exceptionLog.info(Messages.getMessage("axisFault00"), fault);
// strip runtime details
fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
} else if (exceptionLog.isDebugEnabled()) {
exceptionLog.debug(Messages.getMessage("axisFault00"), fault);
}
// dev systems only give fault dumps
if (!isDevelopment()) {
// strip out the stack trace
fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE);
}
}
/**
* log any exception to our output log, at our chosen level
*
* @param e
* what went wrong
*/
protected void logException(Throwable e) {
exceptionLog.info(Messages.getMessage("exception00"), e);
}
/**
* this method writes a fault out to an HTML stream. This includes escaping
* the strings to defend against cross-site scripting attacks
*
* @param writer
* @param axisFault
*/
private void writeFault(PrintWriter writer, AxisFault axisFault) {
String localizedMessage = XMLUtils.xmlEncodeString(axisFault.getLocalizedMessage());
writer.println("<pre>Fault - " + localizedMessage + "<br>");
writer.println(axisFault.dumpToString());
writer.println("</pre>");
}
/**
* print a snippet of service info.
*
* @param service
* service
* @param writer
* output channel
* @param serviceName
* where to put stuff
*/
protected void reportServiceInfo(HttpServletResponse response, PrintWriter writer, SOAPService service, String serviceName) {
response.setContentType("text/html; charset=utf-8");
writer.println("<h1>" + service.getName() + "</h1>");
writer.println("<p>" + Messages.getMessage("axisService00") + "</p>");
writer.println("<i>" + Messages.getMessage("perhaps00") + "</i>");
}
/**
* report that we have no WSDL
*
* This method was moved to the querystring handler QSWSDLHandler. The
* method reportNoWSDL in AxisServlet is never called. Perhaps the method is
* overwritten in subclasses of AxisServlet so the method wasn't removed.
* See the discussion in
*
* http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23845
*
* @param res
* @param writer
* @param moreDetailCode
* optional name of a message to provide more detail
* @param axisFault
* optional fault string, for extra info at debug time only
*/
protected void reportNoWSDL(HttpServletResponse res, PrintWriter writer, String moreDetailCode, AxisFault axisFault) {
}
/**
* This method lists the available services; it is called when there is
* nothing to execute on a GET
*
* @param response
* @param writer
* @param request
* @throws ConfigurationException
* @throws AxisFault
*/
protected void reportAvailableServices(HttpServletResponse response, PrintWriter writer, HttpServletRequest request) throws ConfigurationException, AxisFault {
AxisEngine engine = getEngine();
response.setContentType("text/html; charset=utf-8");
writer.println("<h2>And now... Some Services</h2>");
Iterator i;
try {
i = engine.getConfig().getDeployedServices();
} catch (ConfigurationException configException) {
// turn any internal configuration exceptions back into axis faults
// if that is what they are
if (configException.getContainedException() instanceof AxisFault) {
throw (AxisFault) configException.getContainedException();
} else {
throw configException;
}
}
// baseURL may change if <endpointURL> tag is used for
// custom deployment at a different location
String defaultBaseURL = getWebappBase(request) + servicesPath;
writer.println("<ul>");
while (i.hasNext()) {
ServiceDesc sd = (ServiceDesc) i.next();
StringBuffer sb = new StringBuffer();
sb.append("<li>");
String name = sd.getName();
sb.append(name);
sb.append(" <a href=\"");
String endpointURL = sd.getEndpointURL();
String baseURL = (endpointURL == null) ? defaultBaseURL : endpointURL;
sb.append(baseURL);
sb.append(name);
sb.append("?wsdl\"><i>(wsdl)</i></a></li>");
writer.println(sb.toString());
ArrayList operations = sd.getOperations();
if (!operations.isEmpty()) {
writer.println("<ul>");
for (Iterator it = operations.iterator(); it.hasNext();) {
OperationDesc desc = (OperationDesc) it.next();
writer.println("<li>" + desc.getName());
}
writer.println("</ul>");
}
}
writer.println("</ul>");
}
/**
* generate the error response to indicate that there is apparently no
* endpoint there
*
* @param request
* the request that didnt have an edpoint
* @param response
* response we are generating
* @param writer
* open writer for the request
*/
protected void reportCantGetAxisService(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) {
// no such service....
response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
response.setContentType("text/html; charset=utf-8");
writer.println("<h2>" + Messages.getMessage("error00") + "</h2>");
writer.println("<p>" + Messages.getMessage("noService06") + "</p>");
}
/**
* probe for a JWS page and report 'no service' if one is not found there
*
* @param request
* the request that didnt have an edpoint
* @param response
* response we are generating
* @param writer
* open writer for the request
*/
protected void reportCantGetJWSService(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) {
// first look to see if there is a service
// requestPath is a work around to support serving .jws web services
// from services URL - see AXIS-843 for more information
String requestPath = request.getServletPath() + ((request.getPathInfo() != null) ? request.getPathInfo() : "");
String realpath = getServletConfig().getServletContext().getRealPath(requestPath);
log.debug("JWS real path: " + realpath);
boolean foundJWSFile = (new File(realpath).exists()) && (realpath.endsWith(Constants.JWS_DEFAULT_FILE_EXTENSION));
response.setContentType("text/html; charset=utf-8");
if (foundJWSFile) {
response.setStatus(HttpURLConnection.HTTP_OK);
writer.println(Messages.getMessage("foundJWS00") + "<p>");
String url = request.getRequestURI();
String urltext = Messages.getMessage("foundJWS01");
writer.println("<a href='" + url + "?wsdl'>" + urltext + "</a>");
} else {
response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
writer.println(Messages.getMessage("noService06"));
}
}
/**
* Process a POST to the servlet by handing it off to the Axis Engine. Here
* is where SOAP messages are received
*
* @param req
* posted request
* @param res
* respose
* @throws ServletException
* trouble
* @throws IOException
* different trouble
*/
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
String soapAction = null;
MessageContext msgContext = null;
if (isDebug) {
log.debug("Enter: doPost()");
}
if (tlog.isDebugEnabled()) {
t0 = System.currentTimeMillis();
}
Message responseMsg = null;
String contentType = null;
try {
AxisEngine engine = getEngine();
if (engine == null) {
// !!! should return a SOAP fault...
ServletException se = new ServletException(Messages.getMessage("noEngine00"));
log.debug("No Engine!", se);
throw se;
}
res.setBufferSize(1024 *; // provide performance boost.
/**
* get message context w/ various properties set
*/
msgContext = createMessageContext(engine, req, res);
// ? OK to move this to 'getMessageContext',
// ? where it would also be picked up for 'doGet()' ?
if (securityProvider != null) {
if (isDebug) {
log.debug("securityProvider:" + securityProvider);
}
msgContext.setProperty(MessageContext.SECURITY_PROVIDER, securityProvider);
}
/*
* Get request message modified by kimmking Content-Encoding: gzip
*/
Message requestMsg = null;
String contentEncoding = req.getHeader("Content-Encoding");
log.debug("Content-Encoding:" + contentEncoding);
if ("gzip".equalsIgnoreCase(contentEncoding)) {
byte[] bytes = inputStreamToByteArray(req.getInputStream());
String soap = new String(bytes, "utf-8");
log.debug("SOAP ==> " + soap);
requestMsg = new Message(bytes, false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
} else {
requestMsg = new Message(req.getInputStream(), false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
}
// Transfer HTTP headers to MIME headers for request message.
MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders();
for (Enumeration e = req.getHeaderNames(); e.hasMoreElements();) {
String headerName = (String) e.nextElement();
for (Enumeration f = req.getHeaders(headerName); f.hasMoreElements();) {
String headerValue = (String) f.nextElement();
requestMimeHeaders.addHeader(headerName, headerValue);
}
}
if (isDebug) {
log.debug("Request Message:" + requestMsg);
/* Set the request(incoming) message field in the context */
/**********************************************************/
}
msgContext.setRequestMessage(requestMsg);
String url = HttpUtils.getRequestURL(req).toString();
msgContext.setProperty(MessageContext.TRANS_URL, url);
// put character encoding of request to message context
// in order to reuse it during the whole process.
String requestEncoding;
try {
requestEncoding = (String) requestMsg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (requestEncoding != null) {
msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestEncoding);
}
} catch (SOAPException e1) {
}
try {
/**
* Save the SOAPAction header in the MessageContext bag. This
* will be used to tell the Axis Engine which service is being
* invoked. This will save us the trouble of having to parse the
* Request message - although we will need to double-check later
* on that the SOAPAction header does in fact match the URI in
* the body.
*/
// (is this last stmt true??? (I don't think so - Glen))
/********************************************************/
soapAction = getSoapAction(req);
if (soapAction != null) {
msgContext.setUseSOAPAction(true);
msgContext.setSOAPActionURI(soapAction);
}
// Create a Session wrapper for the HTTP session.
// These can/should be pooled at some point.
// (Sam is Watching! :-)
msgContext.setSession(new AxisHttpSession(req));
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
/* Invoke the Axis engine... */
/*****************************/
if (isDebug) {
log.debug("Invoking Axis Engine.");
// here we run the message by the engine
}
engine.invoke(msgContext);
if (isDebug) {
log.debug("Return from Axis Engine.");
}
if (tlog.isDebugEnabled()) {
t2 = System.currentTimeMillis();
}
responseMsg = msgContext.getResponseMessage();
// We used to throw exceptions on null response messages.
// They are actually OK in certain situations (asynchronous
// services), so fall through here and return an ACCEPTED
// status code below. Might want to install a configurable
// error check for this later.
} catch (AxisFault fault) {
// log and sanitize
processAxisFault(fault);
configureResponseFromAxisFault(res, fault);
responseMsg = msgContext.getResponseMessage();
if (responseMsg == null) {
responseMsg = new Message(fault);
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
}
} catch (Exception e) {
// other exceptions are internal trouble
responseMsg = msgContext.getResponseMessage();
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
responseMsg = convertExceptionToAxisFault(e, responseMsg);
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
} catch (Throwable t) {
logException(t);
// other exceptions are internal trouble
responseMsg = msgContext.getResponseMessage();
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
responseMsg = new Message(new AxisFault(t.toString(), t));
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
}
} catch (AxisFault fault) {
processAxisFault(fault);
configureResponseFromAxisFault(res, fault);
responseMsg = msgContext.getResponseMessage();
if (responseMsg == null) {
responseMsg = new Message(fault);
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
}
}
if (tlog.isDebugEnabled()) {
t3 = System.currentTimeMillis();
}
/* Send response back along the wire... */
/***********************************/
if (responseMsg != null) {
// Transfer MIME headers to HTTP headers for response message.
MimeHeaders responseMimeHeaders = responseMsg.getMimeHeaders();
for (Iterator i = responseMimeHeaders.getAllHeaders(); i.hasNext();) {
MimeHeader responseMimeHeader = (MimeHeader) i.next();
res.addHeader(responseMimeHeader.getName(), responseMimeHeader.getValue());
}
// synchronize the character encoding of request and response
String responseEncoding = (String) msgContext.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (responseEncoding != null) {
try {
responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, responseEncoding);
} catch (SOAPException e) {
}
}
// determine content type from message response
contentType = responseMsg.getContentType(msgContext.getSOAPConstants());
sendResponse(contentType, res, responseMsg);
} else {
// No content, so just indicate accepted
res.setStatus(202);
}
if (isDebug) {
log.debug("Response sent.");
log.debug("Exit: doPost()");
}
if (tlog.isDebugEnabled()) {
t4 = System.currentTimeMillis();
tlog.debug("axisServlet.doPost: " + soapAction + " pre=" + (t1 - t0) + " invoke=" + (t2 - t1) + " post=" + (t3 - t2) + " send=" + (t4 - t3) + " "
+ msgContext.getTargetService() + "." + ((msgContext.getOperation() == null) ? "" : msgContext.getOperation().getName()));
}
}
/**
* Configure the servlet response status code and maybe other headers from
* the fault info.
*
* @param response
* response to configure
* @param fault
* what went wrong
*/
private void configureResponseFromAxisFault(HttpServletResponse response, AxisFault fault) {
// then get the status code
// It's been suggested that a lack of SOAPAction
// should produce some other error code (in the 400s)...
int status = getHttpServletResponseStatus(fault);
if (status == HttpServletResponse.SC_UNAUTHORIZED) {
// unauth access results in authentication request
// TODO: less generic realm choice?
response.setHeader("WWW-Authenticate", "Basic realm=\"AXIS\"");
}
response.setStatus(status);
}
/**
* turn any Exception into an AxisFault, log it, set the response status
* code according to what the specifications say and return a response
* message for posting. This will be the response message passed in if
* non-null; one generated from the fault otherwise.
*
* @param exception
* what went wrong
* @param responseMsg
* what response we have (if any)
* @return a response message to send to the user
*/
private Message convertExceptionToAxisFault(Exception exception, Message responseMsg) {
logException(exception);
if (responseMsg == null) {
AxisFault fault = AxisFault.makeFault(exception);
processAxisFault(fault);
responseMsg = new Message(fault);
}
return responseMsg;
}
/**
* Extract information from AxisFault and map it to a HTTP Status code.
*
* @param af
* Axis Fault
* @return HTTP Status code.
*/
protected int getHttpServletResponseStatus(AxisFault af) {
// TODO: Should really be doing this with explicit AxisFault
// subclasses... --Glen
return af.getFaultCode().getLocalPart().startsWith("Server.Unauth") ? HttpServletResponse.SC_UNAUTHORIZED : HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
// This will raise a 401 for both
// "Unauthenticated" & "Unauthorized"...
}
/**
* write a message to the response, set appropriate headers for content
* type..etc.
*
* @param res
* response
* @param responseMsg
* message to write
* @throws AxisFault
* @throws IOException
* if the response stream can not be written to
*/
private void sendResponse(String contentType, HttpServletResponse res, Message responseMsg) throws AxisFault, IOException {
if (responseMsg == null) {
res.setStatus(HttpServletResponse.SC_NO_CONTENT);
if (isDebug) {
log.debug("NO AXIS MESSAGE TO RETURN!");
// String resp = Messages.getMessage("noData00");
// res.setContentLength((int) resp.getBytes().length);
// res.getWriter().print(resp);
}
} else {
if (isDebug) {
log.debug("Returned Content-Type:" + contentType);
// log.debug("Returned Content-Length:" +
// responseMsg.getContentLength());
}
try {
res.setContentType(contentType);
/*
* My understand of Content-Length HTTP 1.0 -Required for
* requests, but optional for responses. HTTP 1.1 - Either
* Content-Length or HTTP Chunking is required. Most servlet
* engines will do chunking if content-length is not specified.
*/
// if(clientVersion == HTTPConstants.HEADER_PROTOCOL_V10) //do
// chunking if necessary.
// res.setContentLength(responseMsg.getContentLength());
responseMsg.writeTo(res.getOutputStream());
} catch (SOAPException e) {
logException(e);
}
}
if (!res.isCommitted()) {
res.flushBuffer(); // Force it right now.
}
}
/**
* Place the Request message in the MessagContext object - notice that we
* just leave it as a 'ServletRequest' object and let the Message processing
* routine convert it - we don't do it since we don't know how it's going to
* be used - perhaps it might not even need to be parsed.
*
* @return a message context
*/
private MessageContext createMessageContext(AxisEngine engine, HttpServletRequest req, HttpServletResponse res) {
MessageContext msgContext = new MessageContext(engine);
String requestPath = getRequestPath(req);
if (isDebug) {
log.debug("MessageContext:" + msgContext);
log.debug("HEADER_CONTENT_TYPE:" + req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
log.debug("HEADER_CONTENT_LOCATION:" + req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
log.debug("Constants.MC_HOME_DIR:" + String.valueOf(getHomeDir()));
log.debug("Constants.MC_RELATIVE_PATH:" + requestPath);
log.debug("HTTPConstants.MC_HTTP_SERVLETLOCATION:" + String.valueOf(getWebInfPath()));
log.debug("HTTPConstants.MC_HTTP_SERVLETPATHINFO:" + req.getPathInfo());
log.debug("HTTPConstants.HEADER_AUTHORIZATION:" + req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
log.debug("Constants.MC_REMOTE_ADDR:" + req.getRemoteAddr());
log.debug("configPath:" + String.valueOf(getWebInfPath()));
}
/* Set the Transport */
/*********************/
msgContext.setTransportName(transportName);
/* Save some HTTP specific info in the bag in case someone needs it */
/********************************************************************/
msgContext.setProperty(Constants.MC_JWS_CLASSDIR, jwsClassDir);
msgContext.setProperty(Constants.MC_HOME_DIR, getHomeDir());
msgContext.setProperty(Constants.MC_RELATIVE_PATH, requestPath);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION, getWebInfPath());
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO, req.getPathInfo());
msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION, req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr());
// Set up a javax.xml.rpc.server.ServletEndpointContext
ServletEndpointContextImpl sec = new ServletEndpointContextImpl();
msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);
/* Save the real path */
/**********************/
String realpath = getServletConfig().getServletContext().getRealPath(requestPath);
if (realpath != null) {
msgContext.setProperty(Constants.MC_REALPATH, realpath);
}
msgContext.setProperty(Constants.MC_CONFIGPATH, getWebInfPath());
return msgContext;
}
/**
* Extract the SOAPAction header. if SOAPAction is null then we'll we be
* forced to scan the body for it. if SOAPAction is "" then use the URL
*
* @param req
* incoming request
* @return the action
* @throws AxisFault
*/
private String getSoapAction(HttpServletRequest req) throws AxisFault {
String soapAction = req.getHeader(HTTPConstants.HEADER_SOAP_ACTION);
if (soapAction == null) {
String contentType = req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentType != null) {
int index = contentType.indexOf("action");
if (index != -1) {
soapAction = contentType.substring(index + 7);
}
}
}
if (isDebug) {
log.debug("HEADER_SOAP_ACTION:" + soapAction);
/**
* Technically, if we don't find this header, we should probably
* fault. It's required in the SOAP HTTP binding.
*/
}
if (soapAction == null) {
AxisFault af = new AxisFault("Client.NoSOAPAction", Messages.getMessage("noHeader00", "SOAPAction"), null, null);
exceptionLog.error(Messages.getMessage("genFault00"), af);
throw af;
}
// the SOAP 1.1 spec & WS-I 1.0 says:
// soapaction = "SOAPAction" ":" [ <"> URI-reference <"> ]
// some implementations leave off the quotes
// we strip them if they are present
if (soapAction.startsWith("\"") && soapAction.endsWith("\"") && soapAction.length() >= 2) {
int end = soapAction.length() - 1;
soapAction = soapAction.substring(1, end);
}
if (soapAction.length() == 0) {
soapAction = req.getContextPath(); // Is this right?
}
return soapAction;
}
/**
* Provided to allow overload of default JWSClassDir by derived class.
*
* @return directory for JWS files
*/
protected String getDefaultJWSClassDir() {
return (getWebInfPath() == null) ? null // ??? what is a good FINAL
// default for WebLogic?
: getWebInfPath() + File.separator + "jwsClasses";
}
/**
* Initialize a Handler for the transport defined in the Axis server config.
* This includes optionally filling in query string handlers.
*/
public void initQueryStringHandlers() {
try {
this.transport = getEngine().getTransport(this.transportName);
if (this.transport == null) {
// No transport by this name is defined. Therefore, fill in
// default
// query string handlers.
this.transport = new SimpleTargetedChain();
this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler");
this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler");
this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler");
return;
}
else {
// See if we should use the default query string handlers.
// By default, set this to true (for backwards compatibility).
boolean defaultQueryStrings = true;
String useDefaults = (String) this.transport.getOption("useDefaultQueryStrings");
if ((useDefaults != null) && useDefaults.toLowerCase().equals("false")) {
defaultQueryStrings = false;
}
if (defaultQueryStrings == true) {
// We should use defaults, so fill them in.
this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler");
this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler");
this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler");
}
}
}
catch (AxisFault e) {
// Some sort of problem occurred, let's just make a default
// transport.
this.transport = new SimpleTargetedChain();
this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler");
this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler");
this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler");
return;
}
}
/**
* Attempts to invoke a plugin for the query string supplied in the URL.
*
* @param request
* the servlet's HttpServletRequest object.
* @param response
* the servlet's HttpServletResponse object.
* @param writer
* the servlet's PrintWriter object.
*/
private boolean processQuery(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) throws AxisFault {
// Attempt to instantiate a plug-in handler class for the query string
// handler classes defined in the HTTP transport.
String path = request.getServletPath();
String queryString = request.getQueryString();
String serviceName;
AxisEngine engine = getEngine();
Iterator i = this.transport.getOptions().keySet().iterator();
if (queryString == null) {
return false;
}
String servletURI = request.getContextPath() + path;
String reqURI = request.getRequestURI();
// chop off '/'.
if (servletURI.length() + 1 < reqURI.length()) {
serviceName = reqURI.substring(servletURI.length() + 1);
} else {
serviceName = "";
}
while (i.hasNext() == true) {
String queryHandler = (String) i.next();
if (queryHandler.startsWith("qs.") == true) {
// Only attempt to match the query string with transport
// parameters prefixed with "qs:".
String handlerName = queryHandler.substring(queryHandler.indexOf(".") + 1).toLowerCase();
// Determine the name of the plugin to invoke by using all text
// in the query string up to the first occurence of &, =, or the
// whole string if neither is present.
int length = 0;
boolean firstParamFound = false;
while (firstParamFound == false && length < queryString.length()) {
char ch = queryString.charAt(length++);
if (ch == '&' || ch == '=') {
firstParamFound = true;
--length;
}
}
if (length < queryString.length()) {
queryString = queryString.substring(0, length);
}
if (queryString.toLowerCase().equals(handlerName) == true) {
// Query string matches a defined query string handler name.
// If the defined class name for this query string handler
// is blank,
// just return (the handler is "turned off" in effect).
if (this.transport.getOption(queryHandler).equals("")) {
return false;
}
try {
// Attempt to dynamically load the query string handler
// and its "invoke" method.
MessageContext msgContext = createMessageContext(engine, request, response);
Class plugin = Class.forName((String) this.transport.getOption(queryHandler));
Method pluginMethod = plugin.getDeclaredMethod("invoke", new Class[] { msgContext.getClass() });
String url = HttpUtils.getRequestURL(request).toString();
// Place various useful servlet-related objects in
// the MessageContext object being delivered to the
// plugin.
msgContext.setProperty(MessageContext.TRANS_URL, url);
msgContext.setProperty(HTTPConstants.PLUGIN_SERVICE_NAME, serviceName);
msgContext.setProperty(HTTPConstants.PLUGIN_NAME, handlerName);
msgContext.setProperty(HTTPConstants.PLUGIN_IS_DEVELOPMENT, new Boolean(isDevelopment()));
msgContext.setProperty(HTTPConstants.PLUGIN_ENABLE_LIST, new Boolean(enableList));
msgContext.setProperty(HTTPConstants.PLUGIN_ENGINE, engine);
msgContext.setProperty(HTTPConstants.PLUGIN_WRITER, writer);
msgContext.setProperty(HTTPConstants.PLUGIN_LOG, log);
msgContext.setProperty(HTTPConstants.PLUGIN_EXCEPTION_LOG, exceptionLog);
// Invoke the plugin.
pluginMethod.invoke(plugin.newInstance(), new Object[] { msgContext });
writer.close();
return true;
} catch (InvocationTargetException ie) {
reportTroubleInGet(ie.getTargetException(), response, writer);
// return true to prevent any further processing
return true;
} catch (Exception e) {
reportTroubleInGet(e, response, writer);
// return true to prevent any further processing
return true;
}
}
}
}
return false;
}
/**
* getRequestPath a returns request path for web service padded with
* request.getPathInfo for web services served from /services directory.
* This is a required to support serving .jws web services from /services
* URL. See AXIS-843 for more information.
*
* @param request
* HttpServletRequest
* @return String
*/
private static String getRequestPath(HttpServletRequest request) {
return request.getServletPath() + ((request.getPathInfo() != null) ? request.getPathInfo() : "");
}
public static byte[] inputStreamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPInputStream gis = new GZIPInputStream (is);
int i = -1;
byte[] bs = new byte[1024];
while ((i = gis.read(bs)) != -1) {
baos.write(bs,0,i);
}
gis.close();
return baos.toByteArray();
}
}</pre>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p></div><br/>你可以的,太长了。
<p>webservice调用一般走soap over http, 响应的报文,可以通过在应用服务器端配置gzip(比如tomcat)来做。</p>
<p> </p>
<p> </p>
<p>客户端如果发送的请求报文数据时gzip的,axis2支持,axis是不支持的。</p>
<p> </p>
<p>axis2通过设置</p>
<p>options.setProperty(org.apache.axis2.transport.http.HTTPConstants.MC_GZIP_REQUEST, Boolean.TRUE);</p>
<p>即可实现请求的http报文头添加Content-Encoding: gzip,报文体为gzip过的soap。</p>
<p>服务器端拿到Content-Encoding,一看为gzip,自动解压过处理。</p>
<p> </p>
<p>而axis的AxisServlet实现里,并没有判断Content-Encoding,所以不支持。</p>
<p>继承AxisServlet,添加如上axis2的处理步骤即可使axis支持gzip的请求。</p>
<p> </p>
<p>把这个类复制到项目,然后把web.xml中的AxisServlet的class改成这个。</p>
<p> </p>
<p> </p>
<pre name="code" class="java">package org.qsoft.axis;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.GZIPInputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.apache.axis.AxisEngine;
import org.apache.axis.AxisFault;
import org.apache.axis.ConfigurationException;
import org.apache.axis.Constants;
import org.apache.axis.Handler;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.SimpleTargetedChain;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.description.ServiceDesc;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.management.ServiceAdmin;
import org.apache.axis.security.servlet.ServletSecurityProvider;
import org.apache.axis.transport.http.AxisHttpSession;
import org.apache.axis.transport.http.AxisServlet;
import org.apache.axis.transport.http.FilterPrintWriter;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.transport.http.HTTPTransport;
import org.apache.axis.transport.http.ServletEndpointContextImpl;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.XMLUtils;
import org.apache.commons.logging.Log;
import org.w3c.dom.Element;
/**
* Servlet implementation class QsoftAxisServlet
*/
public class QsoftAxisServlet extends AxisServlet {
private static final long serialVersionUID = -1530368108781213835L;
protected static Log log = LogFactory.getLog(QsoftAxisServlet.class.getName());
/**
* this log is for timing
*/
private static Log tlog = LogFactory.getLog(Constants.TIME_LOG_CATEGORY);
/**
* a separate log for exceptions lets users route them differently from
* general low level debug info
*/
private static Log exceptionLog = LogFactory.getLog(Constants.EXCEPTION_LOG_CATEGORY);
// These have default values.
private String transportName;
private Handler transport;
private ServletSecurityProvider securityProvider = null;
private String servicesPath;
/**
* cache of logging debug option; only evaluated at init time. So no dynamic
* switching of logging options with this servlet.
*/
private static boolean isDebug = false;
/**
* Should we enable the "?list" functionality on GETs? (off by default
* because deployment information is a potential security hole)
*/
private boolean enableList = false;
/**
* Should we turn off the list of services when we receive a GET at the
* servlet root?
*/
private boolean disableServicesList = false;
/**
* Cached path to JWS output directory
*/
private String jwsClassDir = null;
protected String getJWSClassDir() {
return jwsClassDir;
}
/**
* create a new servlet instance
*/
public QsoftAxisServlet() {
}
/**
* Initialization method.
*/
public void init() throws javax.servlet.ServletException {
// super.init();
ServletContext context = getServletConfig().getServletContext();
isDebug = log.isDebugEnabled();
if (isDebug) {
log.debug("In servlet init");
}
transportName = getOption(context, INIT_PROPERTY_TRANSPORT_NAME, HTTPTransport.DEFAULT_TRANSPORT_NAME);
if (JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_USE_SECURITY, null))) {
securityProvider = new ServletSecurityProvider();
}
enableList = JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_ENABLE_LIST, null));
jwsClassDir = getOption(context, INIT_PROPERTY_JWS_CLASS_DIR, null);
// Should we list services?
disableServicesList = JavaUtils.isTrue(getOption(context, INIT_PROPERTY_DISABLE_SERVICES_LIST, "false"));
servicesPath = getOption(context, INIT_PROPERTY_SERVICES_PATH, "/services/");
/**
* There are DEFINATE problems here if getHomeDir and/or
* getDefaultJWSClassDir return null (as they could with WebLogic). This
* needs to be reexamined in the future, but this should fix any NPE's
* in the mean time.
*/
if (jwsClassDir != null) {
if (getHomeDir() != null) {
jwsClassDir = getHomeDir() + jwsClassDir;
}
} else {
jwsClassDir = getDefaultJWSClassDir();
}
initQueryStringHandlers();
// Setup the service admin
try {
ServiceAdmin.setEngine(this.getEngine(), context.getServerInfo());
} catch (AxisFault af) {
exceptionLog.info("Exception setting AxisEngine on ServiceAdmin " + af);
}
}
/**
* Process GET requests. This includes handoff of pseudo-SOAP requests
*
* @param request
* request in
* @param response
* request out
* @throws ServletException
* @throws IOException
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (isDebug) {
log.debug("Enter: doGet()");
}
PrintWriter writer = new FilterPrintWriter(response);
try {
AxisEngine engine = getEngine();
ServletContext servletContext = getServletConfig().getServletContext();
String pathInfo = request.getPathInfo();
String realpath = servletContext.getRealPath(request.getServletPath());
if (realpath == null) {
realpath = request.getServletPath();
}
// JWS pages are special; they are the servlet path and there
// is no pathinfo...we map the pathinfo to the servlet path to keep
// it happy
boolean isJWSPage = request.getRequestURI().endsWith(".jws");
if (isJWSPage) {
pathInfo = request.getServletPath();
}
// Try to execute a query string plugin and return upon success.
if (processQuery(request, response, writer) == true) {
return;
}
boolean hasNoPath = (pathInfo == null || pathInfo.equals(""));
if (!disableServicesList) {
if (hasNoPath) {
// If the user requested the servlet (i.e.
// /axis/servlet/AxisServlet)
// with no service name, present the user with a list of
// deployed
// services to be helpful
// Don't do this if has been turned off
reportAvailableServices(response, writer, request);
} else if (realpath != null) {
// We have a pathname, so now we perform WSDL or list
// operations
// get message context w/ various properties set
MessageContext msgContext = createMessageContext(engine, request, response);
// NOTE: HttpUtils.getRequestURL has been deprecated.
// This line SHOULD be:
// String url = req.getRequestURL().toString()
// HOWEVER!!!! DON'T REPLACE IT! There's a bug in
// req.getRequestURL that is not in HttpUtils.getRequestURL
// req.getRequestURL returns "localhost" in the remote
// scenario rather than the actual host name.
//
// But more importantly, getRequestURL() is a servlet 2.3
// API and to support servlet 2.2 (aka WebSphere 4)
// we need to leave this in for a while longer. tomj
// 10/14/2004
//
String url = HttpUtils.getRequestURL(request).toString();
msgContext.setProperty(MessageContext.TRANS_URL, url);
// See if we can locate the desired service. If we
// can't, return a 404 Not Found. Otherwise, just
// print the placeholder message.
String serviceName;
if (pathInfo.startsWith("/")) {
serviceName = pathInfo.substring(1);
} else {
serviceName = pathInfo;
}
SOAPService s = engine.getService(serviceName);
if (s == null) {
// no service: report it
if (isJWSPage) {
reportCantGetJWSService(request, response, writer);
} else {
reportCantGetAxisService(request, response, writer);
}
} else {
// print a snippet of service info.
reportServiceInfo(response, writer, s, serviceName);
}
}
} else {
// We didn't have a real path in the request, so just
// print a message informing the user that they reached
// the servlet.
response.setContentType("text/html; charset=utf-8");
writer.println("<html><h1>Axis HTTP Servlet</h1>");
writer.println(Messages.getMessage("reachedServlet00"));
writer.println("<p>" + Messages.getMessage("transportName00", "<b>" + transportName + "</b>"));
writer.println("</html>");
}
} catch (AxisFault fault) {
reportTroubleInGet(fault, response, writer);
} catch (Exception e) {
reportTroubleInGet(e, response, writer);
} finally {
writer.close();
if (isDebug) {
log.debug("Exit: doGet()");
}
}
}
/**
* when we get an exception or an axis fault in a GET, we handle it almost
* identically: we go 'something went wrong', set the response code to 500
* and then dump info. But we dump different info for an axis fault or
* subclass thereof.
*
* @param exception
* what went wrong
* @param response
* current response
* @param writer
* open writer to response
*/
private void reportTroubleInGet(Throwable exception, HttpServletResponse response, PrintWriter writer) {
response.setContentType("text/html; charset=utf-8");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
writer.println("<h2>" + Messages.getMessage("error00") + "</h2>");
writer.println("<p>" + Messages.getMessage("somethingWrong00") + "</p>");
if (exception instanceof AxisFault) {
AxisFault fault = (AxisFault) exception;
processAxisFault(fault);
writeFault(writer, fault);
} else {
logException(exception);
writer.println("<pre>Exception - " + exception + "<br>");
// dev systems only give fault dumps
if (isDevelopment()) {
writer.println(JavaUtils.stackToString(exception));
}
writer.println("</pre>");
}
}
/**
* routine called whenever an axis fault is caught; where they are logged
* and any other business. The method may modify the fault in the process
*
* @param fault
* what went wrong.
*/
protected void processAxisFault(AxisFault fault) {
// log the fault
Element runtimeException = fault.lookupFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
if (runtimeException != null) {
exceptionLog.info(Messages.getMessage("axisFault00"), fault);
// strip runtime details
fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
} else if (exceptionLog.isDebugEnabled()) {
exceptionLog.debug(Messages.getMessage("axisFault00"), fault);
}
// dev systems only give fault dumps
if (!isDevelopment()) {
// strip out the stack trace
fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE);
}
}
/**
* log any exception to our output log, at our chosen level
*
* @param e
* what went wrong
*/
protected void logException(Throwable e) {
exceptionLog.info(Messages.getMessage("exception00"), e);
}
/**
* this method writes a fault out to an HTML stream. This includes escaping
* the strings to defend against cross-site scripting attacks
*
* @param writer
* @param axisFault
*/
private void writeFault(PrintWriter writer, AxisFault axisFault) {
String localizedMessage = XMLUtils.xmlEncodeString(axisFault.getLocalizedMessage());
writer.println("<pre>Fault - " + localizedMessage + "<br>");
writer.println(axisFault.dumpToString());
writer.println("</pre>");
}
/**
* print a snippet of service info.
*
* @param service
* service
* @param writer
* output channel
* @param serviceName
* where to put stuff
*/
protected void reportServiceInfo(HttpServletResponse response, PrintWriter writer, SOAPService service, String serviceName) {
response.setContentType("text/html; charset=utf-8");
writer.println("<h1>" + service.getName() + "</h1>");
writer.println("<p>" + Messages.getMessage("axisService00") + "</p>");
writer.println("<i>" + Messages.getMessage("perhaps00") + "</i>");
}
/**
* report that we have no WSDL
*
* This method was moved to the querystring handler QSWSDLHandler. The
* method reportNoWSDL in AxisServlet is never called. Perhaps the method is
* overwritten in subclasses of AxisServlet so the method wasn't removed.
* See the discussion in
*
* http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23845
*
* @param res
* @param writer
* @param moreDetailCode
* optional name of a message to provide more detail
* @param axisFault
* optional fault string, for extra info at debug time only
*/
protected void reportNoWSDL(HttpServletResponse res, PrintWriter writer, String moreDetailCode, AxisFault axisFault) {
}
/**
* This method lists the available services; it is called when there is
* nothing to execute on a GET
*
* @param response
* @param writer
* @param request
* @throws ConfigurationException
* @throws AxisFault
*/
protected void reportAvailableServices(HttpServletResponse response, PrintWriter writer, HttpServletRequest request) throws ConfigurationException, AxisFault {
AxisEngine engine = getEngine();
response.setContentType("text/html; charset=utf-8");
writer.println("<h2>And now... Some Services</h2>");
Iterator i;
try {
i = engine.getConfig().getDeployedServices();
} catch (ConfigurationException configException) {
// turn any internal configuration exceptions back into axis faults
// if that is what they are
if (configException.getContainedException() instanceof AxisFault) {
throw (AxisFault) configException.getContainedException();
} else {
throw configException;
}
}
// baseURL may change if <endpointURL> tag is used for
// custom deployment at a different location
String defaultBaseURL = getWebappBase(request) + servicesPath;
writer.println("<ul>");
while (i.hasNext()) {
ServiceDesc sd = (ServiceDesc) i.next();
StringBuffer sb = new StringBuffer();
sb.append("<li>");
String name = sd.getName();
sb.append(name);
sb.append(" <a href=\"");
String endpointURL = sd.getEndpointURL();
String baseURL = (endpointURL == null) ? defaultBaseURL : endpointURL;
sb.append(baseURL);
sb.append(name);
sb.append("?wsdl\"><i>(wsdl)</i></a></li>");
writer.println(sb.toString());
ArrayList operations = sd.getOperations();
if (!operations.isEmpty()) {
writer.println("<ul>");
for (Iterator it = operations.iterator(); it.hasNext();) {
OperationDesc desc = (OperationDesc) it.next();
writer.println("<li>" + desc.getName());
}
writer.println("</ul>");
}
}
writer.println("</ul>");
}
/**
* generate the error response to indicate that there is apparently no
* endpoint there
*
* @param request
* the request that didnt have an edpoint
* @param response
* response we are generating
* @param writer
* open writer for the request
*/
protected void reportCantGetAxisService(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) {
// no such service....
response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
response.setContentType("text/html; charset=utf-8");
writer.println("<h2>" + Messages.getMessage("error00") + "</h2>");
writer.println("<p>" + Messages.getMessage("noService06") + "</p>");
}
/**
* probe for a JWS page and report 'no service' if one is not found there
*
* @param request
* the request that didnt have an edpoint
* @param response
* response we are generating
* @param writer
* open writer for the request
*/
protected void reportCantGetJWSService(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) {
// first look to see if there is a service
// requestPath is a work around to support serving .jws web services
// from services URL - see AXIS-843 for more information
String requestPath = request.getServletPath() + ((request.getPathInfo() != null) ? request.getPathInfo() : "");
String realpath = getServletConfig().getServletContext().getRealPath(requestPath);
log.debug("JWS real path: " + realpath);
boolean foundJWSFile = (new File(realpath).exists()) && (realpath.endsWith(Constants.JWS_DEFAULT_FILE_EXTENSION));
response.setContentType("text/html; charset=utf-8");
if (foundJWSFile) {
response.setStatus(HttpURLConnection.HTTP_OK);
writer.println(Messages.getMessage("foundJWS00") + "<p>");
String url = request.getRequestURI();
String urltext = Messages.getMessage("foundJWS01");
writer.println("<a href='" + url + "?wsdl'>" + urltext + "</a>");
} else {
response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
writer.println(Messages.getMessage("noService06"));
}
}
/**
* Process a POST to the servlet by handing it off to the Axis Engine. Here
* is where SOAP messages are received
*
* @param req
* posted request
* @param res
* respose
* @throws ServletException
* trouble
* @throws IOException
* different trouble
*/
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
String soapAction = null;
MessageContext msgContext = null;
if (isDebug) {
log.debug("Enter: doPost()");
}
if (tlog.isDebugEnabled()) {
t0 = System.currentTimeMillis();
}
Message responseMsg = null;
String contentType = null;
try {
AxisEngine engine = getEngine();
if (engine == null) {
// !!! should return a SOAP fault...
ServletException se = new ServletException(Messages.getMessage("noEngine00"));
log.debug("No Engine!", se);
throw se;
}
res.setBufferSize(1024 *; // provide performance boost.
/**
* get message context w/ various properties set
*/
msgContext = createMessageContext(engine, req, res);
// ? OK to move this to 'getMessageContext',
// ? where it would also be picked up for 'doGet()' ?
if (securityProvider != null) {
if (isDebug) {
log.debug("securityProvider:" + securityProvider);
}
msgContext.setProperty(MessageContext.SECURITY_PROVIDER, securityProvider);
}
/*
* Get request message modified by kimmking Content-Encoding: gzip
*/
Message requestMsg = null;
String contentEncoding = req.getHeader("Content-Encoding");
log.debug("Content-Encoding:" + contentEncoding);
if ("gzip".equalsIgnoreCase(contentEncoding)) {
byte[] bytes = inputStreamToByteArray(req.getInputStream());
String soap = new String(bytes, "utf-8");
log.debug("SOAP ==> " + soap);
requestMsg = new Message(bytes, false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
} else {
requestMsg = new Message(req.getInputStream(), false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
}
// Transfer HTTP headers to MIME headers for request message.
MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders();
for (Enumeration e = req.getHeaderNames(); e.hasMoreElements();) {
String headerName = (String) e.nextElement();
for (Enumeration f = req.getHeaders(headerName); f.hasMoreElements();) {
String headerValue = (String) f.nextElement();
requestMimeHeaders.addHeader(headerName, headerValue);
}
}
if (isDebug) {
log.debug("Request Message:" + requestMsg);
/* Set the request(incoming) message field in the context */
/**********************************************************/
}
msgContext.setRequestMessage(requestMsg);
String url = HttpUtils.getRequestURL(req).toString();
msgContext.setProperty(MessageContext.TRANS_URL, url);
// put character encoding of request to message context
// in order to reuse it during the whole process.
String requestEncoding;
try {
requestEncoding = (String) requestMsg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (requestEncoding != null) {
msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestEncoding);
}
} catch (SOAPException e1) {
}
try {
/**
* Save the SOAPAction header in the MessageContext bag. This
* will be used to tell the Axis Engine which service is being
* invoked. This will save us the trouble of having to parse the
* Request message - although we will need to double-check later
* on that the SOAPAction header does in fact match the URI in
* the body.
*/
// (is this last stmt true??? (I don't think so - Glen))
/********************************************************/
soapAction = getSoapAction(req);
if (soapAction != null) {
msgContext.setUseSOAPAction(true);
msgContext.setSOAPActionURI(soapAction);
}
// Create a Session wrapper for the HTTP session.
// These can/should be pooled at some point.
// (Sam is Watching! :-)
msgContext.setSession(new AxisHttpSession(req));
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
/* Invoke the Axis engine... */
/*****************************/
if (isDebug) {
log.debug("Invoking Axis Engine.");
// here we run the message by the engine
}
engine.invoke(msgContext);
if (isDebug) {
log.debug("Return from Axis Engine.");
}
if (tlog.isDebugEnabled()) {
t2 = System.currentTimeMillis();
}
responseMsg = msgContext.getResponseMessage();
// We used to throw exceptions on null response messages.
// They are actually OK in certain situations (asynchronous
// services), so fall through here and return an ACCEPTED
// status code below. Might want to install a configurable
// error check for this later.
} catch (AxisFault fault) {
// log and sanitize
processAxisFault(fault);
configureResponseFromAxisFault(res, fault);
responseMsg = msgContext.getResponseMessage();
if (responseMsg == null) {
responseMsg = new Message(fault);
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
}
} catch (Exception e) {
// other exceptions are internal trouble
responseMsg = msgContext.getResponseMessage();
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
responseMsg = convertExceptionToAxisFault(e, responseMsg);
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
} catch (Throwable t) {
logException(t);
// other exceptions are internal trouble
responseMsg = msgContext.getResponseMessage();
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
responseMsg = new Message(new AxisFault(t.toString(), t));
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
}
} catch (AxisFault fault) {
processAxisFault(fault);
configureResponseFromAxisFault(res, fault);
responseMsg = msgContext.getResponseMessage();
if (responseMsg == null) {
responseMsg = new Message(fault);
((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).getMessage().setMessageContext(msgContext);
}
}
if (tlog.isDebugEnabled()) {
t3 = System.currentTimeMillis();
}
/* Send response back along the wire... */
/***********************************/
if (responseMsg != null) {
// Transfer MIME headers to HTTP headers for response message.
MimeHeaders responseMimeHeaders = responseMsg.getMimeHeaders();
for (Iterator i = responseMimeHeaders.getAllHeaders(); i.hasNext();) {
MimeHeader responseMimeHeader = (MimeHeader) i.next();
res.addHeader(responseMimeHeader.getName(), responseMimeHeader.getValue());
}
// synchronize the character encoding of request and response
String responseEncoding = (String) msgContext.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (responseEncoding != null) {
try {
responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, responseEncoding);
} catch (SOAPException e) {
}
}
// determine content type from message response
contentType = responseMsg.getContentType(msgContext.getSOAPConstants());
sendResponse(contentType, res, responseMsg);
} else {
// No content, so just indicate accepted
res.setStatus(202);
}
if (isDebug) {
log.debug("Response sent.");
log.debug("Exit: doPost()");
}
if (tlog.isDebugEnabled()) {
t4 = System.currentTimeMillis();
tlog.debug("axisServlet.doPost: " + soapAction + " pre=" + (t1 - t0) + " invoke=" + (t2 - t1) + " post=" + (t3 - t2) + " send=" + (t4 - t3) + " "
+ msgContext.getTargetService() + "." + ((msgContext.getOperation() == null) ? "" : msgContext.getOperation().getName()));
}
}
/**
* Configure the servlet response status code and maybe other headers from
* the fault info.
*
* @param response
* response to configure
* @param fault
* what went wrong
*/
private void configureResponseFromAxisFault(HttpServletResponse response, AxisFault fault) {
// then get the status code
// It's been suggested that a lack of SOAPAction
// should produce some other error code (in the 400s)...
int status = getHttpServletResponseStatus(fault);
if (status == HttpServletResponse.SC_UNAUTHORIZED) {
// unauth access results in authentication request
// TODO: less generic realm choice?
response.setHeader("WWW-Authenticate", "Basic realm=\"AXIS\"");
}
response.setStatus(status);
}
/**
* turn any Exception into an AxisFault, log it, set the response status
* code according to what the specifications say and return a response
* message for posting. This will be the response message passed in if
* non-null; one generated from the fault otherwise.
*
* @param exception
* what went wrong
* @param responseMsg
* what response we have (if any)
* @return a response message to send to the user
*/
private Message convertExceptionToAxisFault(Exception exception, Message responseMsg) {
logException(exception);
if (responseMsg == null) {
AxisFault fault = AxisFault.makeFault(exception);
processAxisFault(fault);
responseMsg = new Message(fault);
}
return responseMsg;
}
/**
* Extract information from AxisFault and map it to a HTTP Status code.
*
* @param af
* Axis Fault
* @return HTTP Status code.
*/
protected int getHttpServletResponseStatus(AxisFault af) {
// TODO: Should really be doing this with explicit AxisFault
// subclasses... --Glen
return af.getFaultCode().getLocalPart().startsWith("Server.Unauth") ? HttpServletResponse.SC_UNAUTHORIZED : HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
// This will raise a 401 for both
// "Unauthenticated" & "Unauthorized"...
}
/**
* write a message to the response, set appropriate headers for content
* type..etc.
*
* @param res
* response
* @param responseMsg
* message to write
* @throws AxisFault
* @throws IOException
* if the response stream can not be written to
*/
private void sendResponse(String contentType, HttpServletResponse res, Message responseMsg) throws AxisFault, IOException {
if (responseMsg == null) {
res.setStatus(HttpServletResponse.SC_NO_CONTENT);
if (isDebug) {
log.debug("NO AXIS MESSAGE TO RETURN!");
// String resp = Messages.getMessage("noData00");
// res.setContentLength((int) resp.getBytes().length);
// res.getWriter().print(resp);
}
} else {
if (isDebug) {
log.debug("Returned Content-Type:" + contentType);
// log.debug("Returned Content-Length:" +
// responseMsg.getContentLength());
}
try {
res.setContentType(contentType);
/*
* My understand of Content-Length HTTP 1.0 -Required for
* requests, but optional for responses. HTTP 1.1 - Either
* Content-Length or HTTP Chunking is required. Most servlet
* engines will do chunking if content-length is not specified.
*/
// if(clientVersion == HTTPConstants.HEADER_PROTOCOL_V10) //do
// chunking if necessary.
// res.setContentLength(responseMsg.getContentLength());
responseMsg.writeTo(res.getOutputStream());
} catch (SOAPException e) {
logException(e);
}
}
if (!res.isCommitted()) {
res.flushBuffer(); // Force it right now.
}
}
/**
* Place the Request message in the MessagContext object - notice that we
* just leave it as a 'ServletRequest' object and let the Message processing
* routine convert it - we don't do it since we don't know how it's going to
* be used - perhaps it might not even need to be parsed.
*
* @return a message context
*/
private MessageContext createMessageContext(AxisEngine engine, HttpServletRequest req, HttpServletResponse res) {
MessageContext msgContext = new MessageContext(engine);
String requestPath = getRequestPath(req);
if (isDebug) {
log.debug("MessageContext:" + msgContext);
log.debug("HEADER_CONTENT_TYPE:" + req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
log.debug("HEADER_CONTENT_LOCATION:" + req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
log.debug("Constants.MC_HOME_DIR:" + String.valueOf(getHomeDir()));
log.debug("Constants.MC_RELATIVE_PATH:" + requestPath);
log.debug("HTTPConstants.MC_HTTP_SERVLETLOCATION:" + String.valueOf(getWebInfPath()));
log.debug("HTTPConstants.MC_HTTP_SERVLETPATHINFO:" + req.getPathInfo());
log.debug("HTTPConstants.HEADER_AUTHORIZATION:" + req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
log.debug("Constants.MC_REMOTE_ADDR:" + req.getRemoteAddr());
log.debug("configPath:" + String.valueOf(getWebInfPath()));
}
/* Set the Transport */
/*********************/
msgContext.setTransportName(transportName);
/* Save some HTTP specific info in the bag in case someone needs it */
/********************************************************************/
msgContext.setProperty(Constants.MC_JWS_CLASSDIR, jwsClassDir);
msgContext.setProperty(Constants.MC_HOME_DIR, getHomeDir());
msgContext.setProperty(Constants.MC_RELATIVE_PATH, requestPath);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res);
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION, getWebInfPath());
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO, req.getPathInfo());
msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION, req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr());
// Set up a javax.xml.rpc.server.ServletEndpointContext
ServletEndpointContextImpl sec = new ServletEndpointContextImpl();
msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);
/* Save the real path */
/**********************/
String realpath = getServletConfig().getServletContext().getRealPath(requestPath);
if (realpath != null) {
msgContext.setProperty(Constants.MC_REALPATH, realpath);
}
msgContext.setProperty(Constants.MC_CONFIGPATH, getWebInfPath());
return msgContext;
}
/**
* Extract the SOAPAction header. if SOAPAction is null then we'll we be
* forced to scan the body for it. if SOAPAction is "" then use the URL
*
* @param req
* incoming request
* @return the action
* @throws AxisFault
*/
private String getSoapAction(HttpServletRequest req) throws AxisFault {
String soapAction = req.getHeader(HTTPConstants.HEADER_SOAP_ACTION);
if (soapAction == null) {
String contentType = req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentType != null) {
int index = contentType.indexOf("action");
if (index != -1) {
soapAction = contentType.substring(index + 7);
}
}
}
if (isDebug) {
log.debug("HEADER_SOAP_ACTION:" + soapAction);
/**
* Technically, if we don't find this header, we should probably
* fault. It's required in the SOAP HTTP binding.
*/
}
if (soapAction == null) {
AxisFault af = new AxisFault("Client.NoSOAPAction", Messages.getMessage("noHeader00", "SOAPAction"), null, null);
exceptionLog.error(Messages.getMessage("genFault00"), af);
throw af;
}
// the SOAP 1.1 spec & WS-I 1.0 says:
// soapaction = "SOAPAction" ":" [ <"> URI-reference <"> ]
// some implementations leave off the quotes
// we strip them if they are present
if (soapAction.startsWith("\"") && soapAction.endsWith("\"") && soapAction.length() >= 2) {
int end = soapAction.length() - 1;
soapAction = soapAction.substring(1, end);
}
if (soapAction.length() == 0) {
soapAction = req.getContextPath(); // Is this right?
}
return soapAction;
}
/**
* Provided to allow overload of default JWSClassDir by derived class.
*
* @return directory for JWS files
*/
protected String getDefaultJWSClassDir() {
return (getWebInfPath() == null) ? null // ??? what is a good FINAL
// default for WebLogic?
: getWebInfPath() + File.separator + "jwsClasses";
}
/**
* Initialize a Handler for the transport defined in the Axis server config.
* This includes optionally filling in query string handlers.
*/
public void initQueryStringHandlers() {
try {
this.transport = getEngine().getTransport(this.transportName);
if (this.transport == null) {
// No transport by this name is defined. Therefore, fill in
// default
// query string handlers.
this.transport = new SimpleTargetedChain();
this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler");
this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler");
this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler");
return;
}
else {
// See if we should use the default query string handlers.
// By default, set this to true (for backwards compatibility).
boolean defaultQueryStrings = true;
String useDefaults = (String) this.transport.getOption("useDefaultQueryStrings");
if ((useDefaults != null) && useDefaults.toLowerCase().equals("false")) {
defaultQueryStrings = false;
}
if (defaultQueryStrings == true) {
// We should use defaults, so fill them in.
this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler");
this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler");
this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler");
}
}
}
catch (AxisFault e) {
// Some sort of problem occurred, let's just make a default
// transport.
this.transport = new SimpleTargetedChain();
this.transport.setOption("qs.list", "org.apache.axis.transport.http.QSListHandler");
this.transport.setOption("qs.method", "org.apache.axis.transport.http.QSMethodHandler");
this.transport.setOption("qs.wsdl", "org.apache.axis.transport.http.QSWSDLHandler");
return;
}
}
/**
* Attempts to invoke a plugin for the query string supplied in the URL.
*
* @param request
* the servlet's HttpServletRequest object.
* @param response
* the servlet's HttpServletResponse object.
* @param writer
* the servlet's PrintWriter object.
*/
private boolean processQuery(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) throws AxisFault {
// Attempt to instantiate a plug-in handler class for the query string
// handler classes defined in the HTTP transport.
String path = request.getServletPath();
String queryString = request.getQueryString();
String serviceName;
AxisEngine engine = getEngine();
Iterator i = this.transport.getOptions().keySet().iterator();
if (queryString == null) {
return false;
}
String servletURI = request.getContextPath() + path;
String reqURI = request.getRequestURI();
// chop off '/'.
if (servletURI.length() + 1 < reqURI.length()) {
serviceName = reqURI.substring(servletURI.length() + 1);
} else {
serviceName = "";
}
while (i.hasNext() == true) {
String queryHandler = (String) i.next();
if (queryHandler.startsWith("qs.") == true) {
// Only attempt to match the query string with transport
// parameters prefixed with "qs:".
String handlerName = queryHandler.substring(queryHandler.indexOf(".") + 1).toLowerCase();
// Determine the name of the plugin to invoke by using all text
// in the query string up to the first occurence of &, =, or the
// whole string if neither is present.
int length = 0;
boolean firstParamFound = false;
while (firstParamFound == false && length < queryString.length()) {
char ch = queryString.charAt(length++);
if (ch == '&' || ch == '=') {
firstParamFound = true;
--length;
}
}
if (length < queryString.length()) {
queryString = queryString.substring(0, length);
}
if (queryString.toLowerCase().equals(handlerName) == true) {
// Query string matches a defined query string handler name.
// If the defined class name for this query string handler
// is blank,
// just return (the handler is "turned off" in effect).
if (this.transport.getOption(queryHandler).equals("")) {
return false;
}
try {
// Attempt to dynamically load the query string handler
// and its "invoke" method.
MessageContext msgContext = createMessageContext(engine, request, response);
Class plugin = Class.forName((String) this.transport.getOption(queryHandler));
Method pluginMethod = plugin.getDeclaredMethod("invoke", new Class[] { msgContext.getClass() });
String url = HttpUtils.getRequestURL(request).toString();
// Place various useful servlet-related objects in
// the MessageContext object being delivered to the
// plugin.
msgContext.setProperty(MessageContext.TRANS_URL, url);
msgContext.setProperty(HTTPConstants.PLUGIN_SERVICE_NAME, serviceName);
msgContext.setProperty(HTTPConstants.PLUGIN_NAME, handlerName);
msgContext.setProperty(HTTPConstants.PLUGIN_IS_DEVELOPMENT, new Boolean(isDevelopment()));
msgContext.setProperty(HTTPConstants.PLUGIN_ENABLE_LIST, new Boolean(enableList));
msgContext.setProperty(HTTPConstants.PLUGIN_ENGINE, engine);
msgContext.setProperty(HTTPConstants.PLUGIN_WRITER, writer);
msgContext.setProperty(HTTPConstants.PLUGIN_LOG, log);
msgContext.setProperty(HTTPConstants.PLUGIN_EXCEPTION_LOG, exceptionLog);
// Invoke the plugin.
pluginMethod.invoke(plugin.newInstance(), new Object[] { msgContext });
writer.close();
return true;
} catch (InvocationTargetException ie) {
reportTroubleInGet(ie.getTargetException(), response, writer);
// return true to prevent any further processing
return true;
} catch (Exception e) {
reportTroubleInGet(e, response, writer);
// return true to prevent any further processing
return true;
}
}
}
}
return false;
}
/**
* getRequestPath a returns request path for web service padded with
* request.getPathInfo for web services served from /services directory.
* This is a required to support serving .jws web services from /services
* URL. See AXIS-843 for more information.
*
* @param request
* HttpServletRequest
* @return String
*/
private static String getRequestPath(HttpServletRequest request) {
return request.getServletPath() + ((request.getPathInfo() != null) ? request.getPathInfo() : "");
}
public static byte[] inputStreamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPInputStream gis = new GZIPInputStream (is);
int i = -1;
byte[] bs = new byte[1024];
while ((i = gis.read(bs)) != -1) {
baos.write(bs,0,i);
}
gis.close();
return baos.toByteArray();
}
}</pre>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p></div><br/>你可以的,太长了。
发表评论
-
微信公众平台申请消息接口验证工具
2013-08-06 16:37 4038申请了一个微信公众账号,还没想好服务器端用什么技术开发。 ... -
jaxb的类型绑定
2011-07-04 20:06 1782今天一个同事使用jaxb将海航的wsdl里的几个sch ... -
log4j定时轮换文件
2011-04-18 15:03 4731网友 zhangyang6380006在帖子 http:/ ... -
websocket的例子
2011-02-28 11:39 2393flash的websocket实现:https://gi ... -
eclipse e4的web版本开发工具orion
2011-02-18 15:33 4367Orion是一个新提名的eclipse顶级项目,目前处于准备阶 ... -
一个简单的投票机
2010-09-05 03:51 4175刚才无意间看到一个投票,在页面右键,源码,看了下,就几个 ... -
SWT中ole/activex实践--操作word的一个例子
2010-08-26 01:08 7898这几年,做了很多word/excel/ppt方面的开发,特别是 ... -
jetty7的log
2010-07-20 17:05 3848jetty7启动的时候,总是自己打出来3行log信息。 自己 ... -
JNI技术实践小结--原理分析和详细步骤截图说明
2008-12-25 23:40 15518JNI技术实践小结 xx组 ...
相关推荐
AXIS生成java请求客户端,直接下载,修改本地jdk路径和输出代码路径即可
axis2实现webservice请求,资源包中有需要jar及实现的具体demo
Axis1.4如何实现头部鉴权(包括实现类模板)
axis2请求.Net webservice接口,以天气预报getSupportCity接口为例
axis发布webservice教程axis发布webservice教程axis发布webservice教程axis发布webservice教程
axis调用第三方webservice接口所需的jar包,包括axis-1.4.jar,axis-jaxrpc-1.3.jar,axis-jaxrpc-1.4.jar,commons-discovery-0.5.jar,commons-logging-1.2.jar,cxf-rt-databinding-jaxb-3.3.1.jar,javax.mail-...
1、axis2相关jar包如下: axiom-api-1.2.10.jar axiom-dom-1.2.10.jar axiom-impl-1.2.10.jar ...2、eclipse支持插件包如下: axis2-eclipse-codegen-plugin-1.6.2.zip axis2-eclipse-service-plugin-1.6.2.zip
axis1.4和axis2相关jar文件,axis1.4和axis2相关jar文件
WebService之axis的复杂对象传输方案
axis 1.x与axis2.x开发 以及jar
axis复杂类型axis复杂类型axis复杂类型axis复杂类型
Axis2 虽然由 Axis 1.x 处理程序模型提供支持,但它具有更强的灵活性并可扩展到新的体系结构。Axis2 基于新的体系结构进行了全新编写,而且没有采用 Axis 1.x 的常用代码。支持开发 Axis2 的动力是探寻模块化更强、...
Axis2 虽然由 Axis 1.x 处理程序模型提供支持,但它具有更强的灵活性并可扩展到新的体系结构。Axis2 基于新的体系结构进行了全新编写,而且没有采用 Axis 1.x 的常用代码。支持开发 Axis2 的动力是探寻模块化更强、...
Axis2 虽然由 Axis 1.x 处理程序模型提供支持,但它具有更强的灵活性并可扩展到新的体系结构。Axis2 基于新的体系结构进行了全新编写,而且没有采用 Axis 1.x 的常用代码。支持开发 Axis2 的动力是探寻模块化更强、...
WebService Axis demo 初学者,摸索了半天,终于能跑起来了
axis的包axis的包axis的包axis的包
axis2例子 webservice axis2 示例axis2例子 webservice axis2 示例axis2例子 webservice axis2 示例axis2例子 webservice axis2 示例axis2例子 webservice axis2 示例
axis教程 axis教程 axis教程 axis教程 axis教程
webService—Axis实例webService—Axis实例webService—Axis实例webService—Axis实例webService—Axis实例webService—Axis实例webService—Axis实例
Axis分为1.x系列和Axis 2系列,两个系列体系结构和使用上有较大的区别,相对而言,Axis1.x更加稳定,文档也比较齐全,因此本文内容以Axis 1.x系列最新版本1.4为基础,Axis有C++和Java两个版本的实现,本文描述Java...