1 /*
2 * ========================================================================
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * ========================================================================
20 */
21 package org.apache.cactus.internal.server;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletRequest;
25
26 import org.apache.cactus.internal.HttpServiceDefinition;
27 import org.apache.cactus.internal.ServiceEnumeration;
28 import org.apache.cactus.spi.server.ImplicitObjects;
29 import org.apache.cactus.spi.server.TestController;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 /**
34 * Controller that extracts the requested service from the HTTP request and
35 * executes the request. Examples of requests are: executing a given test,
36 * returning the test result, verifying that the controller is correctly
37 * configured, etc.
38 *
39 * @version $Id: AbstractWebTestController.java 238991 2004-05-22 11:34:50Z vmassol $
40 */
41 public abstract class AbstractWebTestController implements TestController
42 {
43 /**
44 * The logger.
45 */
46 private static final Log LOGGER =
47 LogFactory.getLog(AbstractWebTestController.class);
48
49 /**
50 * @param theObjects the implicit objects coming from the redirector
51 * @return the test caller that will be used to execute the test
52 */
53 protected abstract AbstractWebTestCaller getTestCaller(
54 WebImplicitObjects theObjects);
55
56 /**
57 * Handles the incoming request by extracting the requested service and
58 * calling the correct method on a <code>WebTestCaller</code>.
59 *
60 * @param theObjects the implicit objects (they are different for the
61 * different redirectors)
62 * @exception ServletException if an error occurs when servicing the
63 * request
64 */
65 public void handleRequest(ImplicitObjects theObjects)
66 throws ServletException
67 {
68 WebImplicitObjects webImplicitObjects = (WebImplicitObjects) theObjects;
69
70 // If the Cactus user has forgotten to put a needed jar on the server
71 // classpath (i.e. in WEB-INF/lib), then the servlet engine Webapp
72 // class loader will throw a NoClassDefFoundError exception. As this
73 // method is the entry point of the webapp, we'll catch all
74 // NoClassDefFoundError exceptions and report a nice error message
75 // for the user so that he knows he has forgotten to put a jar in the
76 // classpath. If we don't do this, the error will be trapped by the
77 // container and may not result in an ... err ... understandable error
78 // message (like in Tomcat) ...
79 try
80 {
81 String serviceName =
82 getServiceName(webImplicitObjects.getHttpServletRequest());
83
84 AbstractWebTestCaller caller = getTestCaller(webImplicitObjects);
85
86 // TODO: will need a factory here real soon...
87
88 ServiceEnumeration service =
89 ServiceEnumeration.valueOf(serviceName);
90
91 // Is it the call test method service ?
92 if (service == ServiceEnumeration.CALL_TEST_SERVICE)
93 {
94 caller.doTest();
95 }
96 // Is it the get test results service ?
97 else if (service == ServiceEnumeration.GET_RESULTS_SERVICE)
98 {
99 caller.doGetResults();
100 }
101 // Is it the test connection service ?
102 // This service is only used to verify that connection between
103 // client and server is working fine
104 else if (service == ServiceEnumeration.RUN_TEST_SERVICE)
105 {
106 caller.doRunTest();
107 }
108 // Is it the service to create an HTTP session?
109 else if (service == ServiceEnumeration.CREATE_SESSION_SERVICE)
110 {
111 caller.doCreateSession();
112 }
113 else if (service == ServiceEnumeration.GET_VERSION_SERVICE)
114 {
115 caller.doGetVersion();
116 }
117 else
118 {
119 String message = "Unknown service [" + serviceName
120 + "] in HTTP request.";
121
122 LOGGER.error(message);
123 throw new ServletException(message);
124 }
125 }
126 catch (NoClassDefFoundError e)
127 {
128 // try to display messages as descriptive as possible !
129 if (e.getMessage().startsWith("junit/framework"))
130 {
131 String message = "You must put the JUnit jar in "
132 + "your server classpath (in WEB-INF/lib for example)";
133
134 LOGGER.error(message, e);
135 throw new ServletException(message, e);
136 }
137 else
138 {
139 String message = "You are missing a jar in your "
140 + "classpath (class [" + e.getMessage()
141 + "] could not " + "be found";
142
143 LOGGER.error(message, e);
144 throw new ServletException(message, e);
145 }
146 }
147 }
148
149 /**
150 * @param theRequest the HTTP request
151 * @return the service name of the service to call (there are 2 services
152 * "do test" and "get results"), extracted from the HTTP request
153 * @exception ServletException if the service to execute is missing from
154 * the HTTP request
155 */
156 private String getServiceName(HttpServletRequest theRequest)
157 throws ServletException
158 {
159 // Call the correct Service method
160 String queryString = theRequest.getQueryString();
161 String serviceName = ServletUtil.getQueryStringParameter(queryString,
162 HttpServiceDefinition.SERVICE_NAME_PARAM);
163
164 if (serviceName == null)
165 {
166 String message = "Missing service name parameter ["
167 + HttpServiceDefinition.SERVICE_NAME_PARAM
168 + "] in HTTP request. Received query string is ["
169 + queryString + "].";
170
171 LOGGER.debug(message);
172 throw new ServletException(message);
173 }
174
175 LOGGER.debug("Service to call = " + serviceName);
176
177 return serviceName;
178 }
179 }