`
kimmking
  • 浏览: 537025 次
  • 性别: Icon_minigender_1
  • 来自: 中华大丈夫学院
社区版块
存档分类
最新评论

Axis支持gzip的请求

    博客分类:
  • java
阅读更多

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("&lt;html&gt;&lt;h1&gt;Axis HTTP Servlet&lt;/h1&gt;");
writer.println(Messages.getMessage("reachedServlet00"));

writer.println("&lt;p&gt;" + Messages.getMessage("transportName00", "&lt;b&gt;" + transportName + "&lt;/b&gt;"));
writer.println("&lt;/html&gt;");
}
} 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("&lt;h2&gt;" + Messages.getMessage("error00") + "&lt;/h2&gt;");
writer.println("&lt;p&gt;" + Messages.getMessage("somethingWrong00") + "&lt;/p&gt;");
if (exception instanceof AxisFault) {
AxisFault fault = (AxisFault) exception;
processAxisFault(fault);
writeFault(writer, fault);
} else {
logException(exception);
writer.println("&lt;pre&gt;Exception - " + exception + "&lt;br&gt;");
// dev systems only give fault dumps
if (isDevelopment()) {
writer.println(JavaUtils.stackToString(exception));
}
writer.println("&lt;/pre&gt;");
}
}

/**
* 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("&lt;pre&gt;Fault - " + localizedMessage + "&lt;br&gt;");
writer.println(axisFault.dumpToString());
writer.println("&lt;/pre&gt;");
}

/**
* 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("&lt;h1&gt;" + service.getName() + "&lt;/h1&gt;");
writer.println("&lt;p&gt;" + Messages.getMessage("axisService00") + "&lt;/p&gt;");
writer.println("&lt;i&gt;" + Messages.getMessage("perhaps00") + "&lt;/i&gt;");
}

/**
* 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("&lt;h2&gt;And now... Some Services&lt;/h2&gt;");

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 &lt;endpointURL&gt; tag is used for
// custom deployment at a different location
String defaultBaseURL = getWebappBase(request) + servicesPath;
writer.println("&lt;ul&gt;");
while (i.hasNext()) {
ServiceDesc sd = (ServiceDesc) i.next();
StringBuffer sb = new StringBuffer();
sb.append("&lt;li&gt;");
String name = sd.getName();
sb.append(name);
sb.append(" &lt;a href=\"");
String endpointURL = sd.getEndpointURL();
String baseURL = (endpointURL == null) ? defaultBaseURL : endpointURL;
sb.append(baseURL);
sb.append(name);
sb.append("?wsdl\"&gt;&lt;i&gt;(wsdl)&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;");
writer.println(sb.toString());
ArrayList operations = sd.getOperations();
if (!operations.isEmpty()) {
writer.println("&lt;ul&gt;");
for (Iterator it = operations.iterator(); it.hasNext();) {
OperationDesc desc = (OperationDesc) it.next();
writer.println("&lt;li&gt;" + desc.getName());
}
writer.println("&lt;/ul&gt;");
}
}
writer.println("&lt;/ul&gt;");
}

/**
* 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("&lt;h2&gt;" + Messages.getMessage("error00") + "&lt;/h2&gt;");
writer.println("&lt;p&gt;" + Messages.getMessage("noService06") + "&lt;/p&gt;");
}

/**
* 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()) &amp;&amp; (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") + "&lt;p&gt;");
String url = request.getRequestURI();
String urltext = Messages.getMessage("foundJWS01");
writer.println("&lt;a href='" + url + "?wsdl'&gt;" + urltext + "&lt;/a&gt;");
} 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            ==&gt;   " + 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" &amp; "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 &amp; WS-I 1.0 says:
// soapaction = "SOAPAction" ":" [ &lt;"&gt; URI-reference &lt;"&gt; ]
// some implementations leave off the quotes
// we strip them if they are present
if (soapAction.startsWith("\"") &amp;&amp; soapAction.endsWith("\"") &amp;&amp; soapAction.length() &gt;= 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) &amp;&amp; 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 &lt; 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 &amp;, =, or the
// whole string if neither is present.

int length = 0;
boolean firstParamFound = false;

while (firstParamFound == false &amp;&amp; length &lt; queryString.length()) {
char ch = queryString.charAt(length++);

if (ch == '&amp;' || ch == '=') {
firstParamFound = true;

--length;
}
}

if (length &lt; 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/>你可以的,太长了。

相关推荐

Global site tag (gtag.js) - Google Analytics