vmassol 01/06/17 06:39:46 Modified: cactus/src/framework/share/org/apache/commons/cactus/server ServletTestCaller.java ServletTestRedirector.java Log: correction of bug #1612 + added some logs Revision Changes Path 1.4 +43 -9 jakarta-commons/cactus/src/framework/share/org/apache/commons/cactus/server/ServletTestCaller.java Index: ServletTestCaller.java =================================================================== RCS file: /home/cvs/jakarta-commons/cactus/src/framework/share/org/apache/commons/cactus/server/ServletTestCaller.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- ServletTestCaller.java 2001/05/05 14:38:44 1.3 +++ ServletTestCaller.java 2001/06/17 13:39:45 1.4 @@ -62,6 +62,7 @@ import javax.servlet.http.*; import org.apache.commons.cactus.*; +import org.apache.commons.cactus.util.log.*; /** * Call the test method on the server side after assigning the servlet implicit @@ -78,6 +79,11 @@ private final static String TEST_RESULTS = "ServletTestRedirector_TestResults"; /** + * The logger + */ + private static Log logger = LogService.getInstance().getLog(ServletTestRedirector.class.getName()); + + /** * Call the method to test. * * @param theClassName the name of the test class to call @@ -87,6 +93,8 @@ */ private void callTestMethod(String theClassName, String theMethod, ServletImplicitObjects theObjects) throws Throwable { + logger.entry("callTestMethod(...)"); + // Get the class to call and build an instance of it. Class testClass = null; ServletTestCase testInstance = null; @@ -139,6 +147,7 @@ // Call the test method testInstance.runBareServerTest(); + logger.exit("callTestMethod"); } /** @@ -152,10 +161,23 @@ */ public void doTest(ServletImplicitObjects theObjects) throws ServletException { - ServletTestResult result = null; + logger.entry("doTest(...)"); + ServletTestResult result = null; + + // Reset TEST_RESULTS to a new results holder to prevent premature + // requests for results from seeing either no results or old results + ResultHolder holder = new ResultHolder(); + theObjects.m_Config.getServletContext().setAttribute(TEST_RESULTS, holder); + + logger.debug("Result holder semaphore is in place"); + + // From this point forward, any thread trying to access the result + // stored in the holder, itself stored in the application scope, will + // block and wait until a result is set. + try { - + // Extract from the HTTP request the test class name and method to call. String testClassName = theObjects.m_Request.getParameter(ServiceDefinition.CLASS_NAME_PARAM); @@ -164,12 +186,16 @@ ServiceDefinition.CLASS_NAME_PARAM + "] in HTTP request."); } + logger.debug("Class to call = " + testClassName); + String methodName = theObjects.m_Request.getParameter(ServiceDefinition.METHOD_NAME_PARAM); if (methodName == null) { throw new ServletException("Missing parameter [" + ServiceDefinition.METHOD_NAME_PARAM + "] in HTTP request."); } + logger.debug("Method to call = " + methodName); + // Call the method to test callTestMethod(testClassName, methodName, theObjects); @@ -184,10 +210,13 @@ result = new ServletTestResult(e); } + + // Set the test result. + holder.setResult(result); - // Save the test result. - theObjects.m_Config.getServletContext().setAttribute(TEST_RESULTS, result); + logger.debug("Result holder semaphore inactive (result set in holder)"); + logger.exit("doTest"); } /** @@ -199,11 +228,15 @@ */ public void doGetResults(ServletImplicitObjects theObjects) throws ServletException { - ServletTestResult result = (ServletTestResult)theObjects.m_Config.getServletContext().getAttribute(TEST_RESULTS); - if (result == null) { - throw new ServletException("No test results found in the application scope"); - } + logger.entry("doGetResults(...)"); + + logger.debug("Try to read results from Holder ..."); + ResultHolder holder = (ResultHolder)(theObjects.m_Config.getServletContext().getAttribute(TEST_RESULTS)); + ServletTestResult result = holder.getResult(); + + logger.debug("... results read"); + // Write back the results as a serialized object to the outgoing stream. try { @@ -218,6 +251,7 @@ } catch (IOException e) { throw new ServletException("Error writing ServletTestResult instance to output stream", e); } - } + logger.exit("doGetResults"); + } } 1.2 +74 -2 jakarta-commons/cactus/src/framework/share/org/apache/commons/cactus/server/ServletTestRedirector.java Index: ServletTestRedirector.java =================================================================== RCS file: /home/cvs/jakarta-commons/cactus/src/framework/share/org/apache/commons/cactus/server/ServletTestRedirector.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ServletTestRedirector.java 2001/04/09 11:52:37 1.1 +++ ServletTestRedirector.java 2001/06/17 13:39:45 1.2 @@ -62,6 +62,7 @@ import javax.servlet.http.*; import org.apache.commons.cactus.*; +import org.apache.commons.cactus.util.log.*; /** * Generic Servlet redirector that calls a test method on the server side. @@ -72,6 +73,28 @@ public class ServletTestRedirector extends HttpServlet { /** + * Initialize the logging subsystem so that it can get it's configuration + * details from the correct properties file. Initialization is done here + * as this servlet is the first point of entry to the server code. + */ + static { + LogService.getInstance().init("/log_server.properties"); + } + + /** + * The logger + */ + private static Log logger = LogService.getInstance().getLog(ServletTestRedirector.class.getName()); + + /** + * Some magic keyword that is prepended to the servlet output stream in + * order to never have an empty stream returned to the client side. This is + * needed because the client side will try to read all the returned data and + * if there is none will block ... + */ + static final String MAGIC_KEYWORD = "C*&()C$$"; + + /** * Handle GET requests. * * @param theRequest the incoming HTTP client request @@ -80,10 +103,14 @@ * @exception ServletException if an error occurred when sending back * the response to the client. */ - public void doGet(HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException + public void doGet(HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException { + logger.entry("doGet(...)"); + // Same handling than for a POST doPost(theRequest, theResponse); + + logger.exit("doGet"); } /** @@ -95,8 +122,12 @@ * * @exception ServletException if an unexpected error occurred */ - public void doPost(HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException + public void doPost(HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException { + logger.entry("doPost(...)"); + + logger.debug("Default buffer size = " + theResponse.getBufferSize()); + // Call the correct Service method String serviceName = theRequest.getParameter(ServiceDefinition.SERVICE_NAME_PARAM); if (serviceName == null) { @@ -104,6 +135,8 @@ ServiceDefinition.SERVICE_NAME_PARAM + "] in HTTP request."); } + logger.debug("Service called = " + serviceName); + ServletTestCaller caller = new ServletTestCaller(); ServletImplicitObjects objects = new ServletImplicitObjects(); objects.m_Config = getServletConfig(); @@ -115,6 +148,43 @@ caller.doTest(objects); + // Ugly hack here : The client side need to read all the data + // returned on the servlet output stream. Otherwise the servlet + // engine might do an io block, waiting for the client to read + // more data. Is this happens, then we are stuck because the client + // side is waiting for the test result to be committed but the + // latter will only be committed when all the data has been sent + // on the servlet output stream. So we need to read the data from + // the client side. However, some tests do not return any data and + // thus the read would block ... So we always send at the end of + // the stream a magic keyword so that the returned stream is never + // empty. This magic keyword will be ignored by the client side + // ... ugly, no ? + + // This can easily be corrected with the Servlet API 2.3 (by + // doing all the read on the server side instead of the client side + // ). However it does not work on some 2.2 API servlet engines + // (like Tomcat 3.2 ...). + + // Send magic keyword ... well at least try ... Yes, you read it + // correctly ! I said 'try' because if the test has done a forward + // for example, then the Writer or OutputStream will have already + // been used and thus it would lead to an error to try to write to + // them ... In that case, we won't write anything back but that + // should be fine as a forward is supposed to return something ... + + // Note: There might still be the case where I get a Writer in my + // test case but don't use it ... hum ... To verify ... later ... + + // Try sending the magic keyword ... + logger.debug("Sending magic keyword ..."); + try { + theResponse.getOutputStream().print(MAGIC_KEYWORD); + } catch (Exception e) { + logger.debug("Failed to to send magic keyword (this is normal)", e); + // It failed ... Do nothing + } + // Is it the get test results service ? } else if (ServiceEnumeration.GET_RESULTS_SERVICE.equals(serviceName)) { @@ -124,6 +194,8 @@ throw new ServletException("Unknown service [" + serviceName + "] in HTTP request."); } + + logger.exit("doPost"); }