- 浏览: 554472 次
- 性别:
- 来自: 中华大丈夫学院
-
文章分类
最新评论
-
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 *

/**
* 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 4162申请了一个微信公众账号,还没想好服务器端用什么技术开发。 ... -
jaxb的类型绑定
2011-07-04 20:06 1882今天一个同事使用jaxb将海航的wsdl里的几个sch ... -
log4j定时轮换文件
2011-04-18 15:03 4896网友 zhangyang6380006在帖子 http:/ ... -
websocket的例子
2011-02-28 11:39 2473flash的websocket实现:https://gi ... -
eclipse e4的web版本开发工具orion
2011-02-18 15:33 4430Orion是一个新提名的eclipse顶级项目,目前处于准备阶 ... -
一个简单的投票机
2010-09-05 03:51 4275刚才无意间看到一个投票,在页面右键,源码,看了下,就几个 ... -
SWT中ole/activex实践--操作word的一个例子
2010-08-26 01:08 8003这几年,做了很多word/excel/ppt方面的开发,特别是 ... -
jetty7的log
2010-07-20 17:05 3911jetty7启动的时候,总是自己打出来3行log信息。 自己 ... -
JNI技术实践小结--原理分析和详细步骤截图说明
2008-12-25 23:40 15604JNI技术实践小结 xx组 ...
相关推荐
"axis-src-1_4.tar.gz" 是一个使用tar和gzip工具打包的Linux/Unix格式的压缩文件。解压后,用户可以查看和修改Axis框架的所有源代码,这对于理解其工作原理、自定义功能或调试错误非常有帮助。 4. **文件名称列表*...
在Axis中,可以通过配置服务端或客户端的HTTP连接器来启用Gzip或Deflate压缩。例如,可以在服务端的部署描述符文件中添加相关设置,或者在客户端的SOAP调用中指定Accept-Encoding头来请求压缩响应。 在服务端,我们...
还可以使用GZIP压缩减少传输数据量。 10. **RESTful API**: 对于更现代的Web Services,可能采用REST(Representational State Transfer)架构,它基于HTTP协议,更加轻量级。Java的Jersey、Spring MVC或Retrofit...
开发WAP网站通常需要Java IDE(如Eclipse或IntelliJ IDEA),以及支持JSP和WML的Web服务器(如Tomcat)。开发者还需要了解Apache Axis等WAP服务器的相关配置。 总结,构建WAP网站后台管理及手机显示的过程涉及了...
内容概要:本文详细解析了Apollo 7.0行为预测模块的关键升级点,主要包括新增的Inter-TNT模式、VECTORNET_EVALUATOR以及JOINTLY_PREDICTION_PLANNING_EVALUATOR。这些组件通过引入轨迹交互模拟、动态归一化、联合预测规划等创新机制,显著提高了障碍物轨迹预测的准确性和场景适应性。特别是在处理复杂交通场景如高速公路变道、十字路口交汇时表现出色。此外,文中还介绍了增量式特征更新机制的应用,有效减少了CPU占用,提升了系统的实时性能。 适用人群:适用于对自动驾驶技术感兴趣的开发者、研究人员和技术爱好者,尤其是那些希望深入了解Apollo平台行为预测模块工作原理的人群。 使用场景及目标:①帮助读者理解Apollo 7.0行为预测模块的技术细节;②指导开发者如何利用这些新技术提升自动驾驶系统的预测精度;③为研究者提供有价值的参考资料,促进相关领域的进一步探索。 其他说明:文章不仅提供了详细的代码解读,还包括了实际应用场景中的效果对比,使读者能够全面掌握新旧版本之间的差异。同时,附带的思维导图有助于快速理清各个子模块之间的调用关系和数据流向。
内容概要:本文详细介绍了利用西门子S7-200 PLC和MCGS组态软件构建智能交通灯控制系统的方法。首先阐述了系统的硬件配置,包括选用的PLC型号、输入输出设备及其具体的功能分配。接着深入探讨了梯形图编程的核心逻辑,如定时器嵌套、车流量检测与响应机制,确保红绿灯能够根据实际情况灵活调整。此外还讲解了MCGS组态界面的设计要点,通过图形化方式呈现交通状况并提供人机交互功能。最后分享了一些实际调试过程中遇到的问题及解决方案。 适合人群:从事工业自动化领域的工程师和技术人员,特别是对PLC编程和组态软件有一定了解的人群。 使用场景及目标:适用于城市交通管理部门或相关科研机构进行智能交通系统的研究与开发;旨在提高道路交叉口的通行效率,减少拥堵现象。 其他说明:文中不仅提供了详细的理论指导,还包括了许多实践经验教训,对于初学者来说非常有价值。同时提到一些进阶话题,如加入V2V通信模块的可能性,为未来研究指出了方向。
内容概要:本文详细介绍了光伏特性曲线模型的基本概念及其在Matlab和Simulink中的实现方法。首先阐述了光伏电池的电流-电压(I-V)和功率-电压(P-V)曲线的基础理论,包括理想二极管方程及相关参数的意义。接着展示了如何使用Matlab编写代码来计算并绘制简单的I-V曲线,随后探讨了Simulink环境下构建光伏特性曲线模型的方法,强调了图形化界面的优势。此外,还讨论了分布式光伏系统的特点,通过修改基础模型以适应多电池串联或并联系统的需求。文中不仅提供了具体的代码实例,还分享了一些实用的经验和技术细节,如温度系数、辐照度变化对模型的影响等。 适合人群:从事光伏系统研究的技术人员、高校相关专业师生、对光伏建模感兴趣的工程爱好者。 使用场景及目标:①理解和掌握光伏电池的工作原理及其数学模型;②学会使用Matlab和Simulink进行光伏特性曲线的建模与仿真;③能够分析不同环境条件下光伏系统的性能表现,为优化设计提供依据。 其他说明:文章中包含了大量详细的代码片段和操作指南,有助于读者快速上手实践。同时提醒读者关注模型参数的选择与调整,确保仿真结果贴近实际情况。
BergSoft NextSuite 是一个强大的 Delphi 和 C++ Builder 组件套件。NextGrid 是一个易于使用的组件,具有设计时(带可视化列编辑器)和运行时的方法和属性理解。NextGrid 具有卓越的 StringGrid 功能和标准的 Delphi ListView。NextDBGrid 是一个基于著名的 NextGrid 组件的强大 Delphi 数据网格和 C++ Builder。
中职计算机软件工程.pdf
内容概要:本文详细介绍了如何利用Verilog语言在FPGA平台上实现高性能伺服驱动系统。主要内容涵盖多个关键模块,包括电流环、坐标变换、速度环、位置环、电机反馈接口、SVPWM生成和编码器协议。每个模块都通过具体的Verilog代码片段展示了其功能和实现方式。电流环部分重点讲解了电流反馈和电压输出的计算;坐标变换部分讨论了从三相静止坐标系到两相旋转坐标系的转换;速度环和位置环则采用了PID控制算法实现对电机的速度和位置的精确控制;电机反馈接口和编码器协议确保了电机位置信息的准确获取;SVPWM模块生成了高效的三相PWM波形。这些模块共同协作,实现了对电机的高效、精准控制。 适合人群:具备一定硬件开发基础,特别是熟悉FPGA和Verilog编程的技术人员,以及从事电机控制和伺服系统开发的研究人员。 使用场景及目标:适用于需要深入了解和掌握FPGA平台上的伺服控制系统设计的专业人士。主要目标是帮助读者理解各模块的工作原理及其在实际应用中的实现方法,提升他们在伺服驱动系统设计方面的能力。 阅读建议:由于涉及大量具体代码和技术细节,建议读者在阅读过程中结合实际电路图和仿真工具进行理解和验证。此外,可以尝试自己动手实现部分模块,以便更好地掌握相关技术和优化设计。
ffmepg windows 下载详细教程2025年(最新)
内容概要:本文探讨了一种新型的超表面设计,能够在保持结构对称性的同时实现偏振无关的连续域束缚态(BIC)。传统的BIC设计通常需要破坏结构对称性,从而导致偏振依赖的问题。新的设计方案通过调整几何参数和模式耦合,使得不同偏振模式能够自然耦合并形成稳定的BIC。文中详细介绍了使用COMSOL进行仿真的步骤,包括参数扫描、模式特征分析以及实验验证。结果显示,新机制不仅能在较宽的偏振范围内保持高Q因子,而且对制造误差具有较高的容忍度。 适合人群:从事光学、电磁学研究的专业人士,尤其是对超表面设计和BIC感兴趣的科研人员。 使用场景及目标:适用于需要高精度、高稳定性和宽偏振适应性的应用场景,如LiDAR系统、光电探测、生化传感等领域。目标是提供一种创新的设计思路和技术实现路径,突破传统BIC设计的局限。 其他说明:文中提供了详细的MATLAB和COMSOL代码片段,帮助读者理解和复现实验结果。此外,强调了新机制在实际制备中的优势,特别是对制造误差的高容忍度。
内容概要:本文详细探讨了永磁同步电机(PMSM)控制系统中的关键技术,尤其是最大转矩电流比(MTPA)控制和弱磁控制。首先介绍了MTPA的基本原理,包括基于查表法和公式的实现方式,以及应对温度变化引起的参数漂移的方法。接着讨论了速度环PI控制器的设计,强调了防积分饱和机制的重要性。对于弱磁控制,则着重讲解了电压极限圆的概念及其在过调制情况下的应用,同时提供了具体的Python和C语言代码示例。此外,还涉及到了SVPWM过调制处理的技术细节,如调制比超过1后的波形调整策略。最后分享了一些实际工程项目中的经验教训和技术挑战。 适合人群:从事电机控制领域的工程师、研究人员以及相关专业的学生。 使用场景及目标:帮助读者深入了解PMSM控制系统的内部运作机制,掌握MTPA和弱磁控制的具体实现方法,提高解决实际问题的能力。 其他说明:文中引用了多篇学术文献作为理论支持,并附上了大量源代码片段供参考学习。
MiniTool重点技术共享Windows数据恢复软件.doc
内容概要:本文详细介绍了ADS54J60高速采集卡FMC子卡的设计与实现。该子卡支持4通道16位1G采样率,涵盖了硬件架构设计(原理图、PCB布局)、FPGA源码实现(Verilog代码)等方面。硬件方面,着重讨论了电源管理、时钟分配、信号完整性等问题;FPGA部分,则展示了ADC控制逻辑、数据同步及传输优化的具体实现方法。此外,文中还分享了许多实践经验,如电源纹波控制、LVDS接口配置、数据同步算法等,帮助开发者避免常见陷阱。 适合人群:从事高速数据采集系统的硬件工程师、FPGA开发人员、嵌入式系统设计师。 使用场景及目标:适用于需要高性能数据采集的应用场合,如通信系统、雷达信号处理等。目标是帮助读者掌握ADS54J60 FMC子卡的设计与实现,从而加速项目开发进程。 其他说明:文中提供的设计文件和代码可以直接用于制板生产,大大缩短了从设计到应用的时间。同时,作者还分享了一些实用技巧和经验教训,有助于提高系统的稳定性和性能。
内容概要:本文详细介绍了Linux摄像头驱动的工作原理及其开发流程。首先解释了摄像头驱动的重要性,它是Linux系统与摄像头硬件交互的桥梁,使系统能够识别并操作摄像头。接着深入探讨了V4L2框架作为Linux摄像头驱动的核心,它为视频设备提供了标准化接口,简化了应用与硬件间的交互。文章还具体分析了USB摄像头的工作流程,包括图像捕捉、信号转换、数据传输等环节。开发指南部分则强调了前期准备的重要性,如理解Linux内核架构、USB子系统原理及掌握C语言编程技能。随后阐述了开发步骤,涵盖编写内核模块、注册USB驱动程序以及适配不同摄像头。最后讨论了常见问题及解决方案,如驱动加载失败和图像显示异常,并展望了Linux摄像头驱动在未来智能安防和物联网等领域的应用前景。 适用人群:对Linux系统有一定了解,尤其是对设备驱动开发感兴趣的开发者和技术爱好者。 使用场景及目标:①帮助读者理解Linux摄像头驱动的工作原理,包括V4L2框架和USB摄像头的数据传输过程;②指导读者进行Linux摄像头驱动的开发,从前期准备到具体实现步骤;③解决开发过程中可能出现的常见问题,如驱动加载失败和图像显示异常。 其他说明:本文不仅提供了理论知识,还结合实际案例详细讲解了开发流程中的各个环节,旨在帮助读者更好地掌握Linux摄像头驱动的开发技巧,同时展望了其未来在智能安防和物联网等领域的应用潜力。
内容概要:本文详细介绍了利用MATLAB进行光伏板向蓄电池充电仿真的全过程。主要内容涵盖光伏电池模型建立、Buck电路设计及其参数选择、PWM信号生成、闭环控制系统设计等方面。文中不仅提供了具体的MATLAB代码示例,还深入探讨了如何通过调整电感、电容值及PWM占空比等参数来优化充电效果,确保输出电压稳定在10.8-14.4V之间,并能提供80A的大电流。此外,文章还讨论了针对不同充电阶段采用不同的充电策略,如强充、缓充和浮充,以保护蓄电池免受过充损害。 适合人群:从事电力电子、新能源技术研究的专业人士,尤其是那些对光伏系统有兴趣的技术人员。 使用场景及目标:适用于需要理解和掌握光伏板向蓄电池充电原理和技术细节的人群。目标是帮助读者学会构建完整的充电系统仿真模型,理解各部件的工作机制,并掌握优化方法。 其他说明:文中提到的一些具体数值和参数设置基于特定应用场景,实际应用时可根据实际情况进行适当调整。同时,文中提供的MATLAB代码片段可以直接应用于MATLAB环境,方便读者动手实践。
vika.cnAirtable
内容概要:本文详细介绍了如何使用 COMSOL Multiphysics 对变压器进行时域和频域分析,探讨了磁致伸缩、噪声和洛伦兹力的影响。文中通过具体的代码示例展示了如何设置时域和频域的边界条件,定义磁致伸缩系数,计算洛伦兹力,并通过多物理场耦合模拟变压器的振动和噪声。此外,还讨论了一些常见的仿真技巧和注意事项,如相位对齐、材料非线性特性和边界条件设置等。 适合人群:从事电力系统研究、变压器设计和仿真的工程师和技术人员。 使用场景及目标:适用于希望深入了解变压器内部物理机制及其对外界因素响应的专业人士。通过掌握这些方法,可以优化变压器设计,减少噪声,提升电力系统的稳定性和可靠性。 其他说明:文章不仅提供了理论背景,还给出了实用的代码片段和仿真技巧,帮助读者更好地理解和应用 COMSOL 进行变压器建模。
分析师预测偏差/分析师预测误差/分析师预测准确度/分析师盈余预测误差/分析师盈余 预测准确度 分析师预测分歧度/分析师盈余预测分歧度 方法一,分母为实际每股盈余( 此帖) 方法一,分母为实际每股盈余 分析师预测偏差(FERROR)是指分析师的盈 余预测值与实际盈余值的平均偏差 分析师预测分歧度(FDISP1和FDISP2)是 指每个分析师最近一次盈余预测值的标准差 本文参考周国开等的度量方法,首先剔除了分 析师预测公布日晚于年报公布日的样本,如果同一分析师在一年内对同一家公同发布了多份 预测,则仅保留该分析师在那年的最后一次预测值样本;其次剔除了每股实际收益和每股预 测收益缺失的样本;最后运用公式(1)和公式度量分析师预测偏差,运用公式(2)和公 式(3)度量分析师预测分歧度。 其中: FEPSit为i公司当年的分析师预测每股 盈余 Mean(FEPSi,t)为公司i第t年的所有证券分析师最近一次每股盈余预 测的平均值 Std(FEPSi,t)为公司i第t年的所有证券分析师最近一次每股盈 余预测的标准差 MEPSit为i公司当年的实际每股盈余 样本选择:全部A股200 1-2022年数