|
|||||||||||||||||||
| 30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| AbstractWebTestCaller.java | 43.8% | 55.2% | 76.9% | 56% |
|
||||||||||||||
| 1 |
/*
|
|
| 2 |
* ========================================================================
|
|
| 3 |
*
|
|
| 4 |
* Copyright 2001-2004 The Apache Software Foundation.
|
|
| 5 |
*
|
|
| 6 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
| 7 |
* you may not use this file except in compliance with the License.
|
|
| 8 |
* You may obtain a copy of the License at
|
|
| 9 |
*
|
|
| 10 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
| 11 |
*
|
|
| 12 |
* Unless required by applicable law or agreed to in writing, software
|
|
| 13 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
| 14 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
| 15 |
* See the License for the specific language governing permissions and
|
|
| 16 |
* limitations under the License.
|
|
| 17 |
*
|
|
| 18 |
* ========================================================================
|
|
| 19 |
*/
|
|
| 20 |
package org.apache.cactus.internal.server;
|
|
| 21 |
|
|
| 22 |
import java.io.IOException;
|
|
| 23 |
import java.io.Writer;
|
|
| 24 |
|
|
| 25 |
import java.lang.reflect.Constructor;
|
|
| 26 |
|
|
| 27 |
import javax.servlet.ServletException;
|
|
| 28 |
|
|
| 29 |
import junit.framework.Test;
|
|
| 30 |
import junit.framework.TestCase;
|
|
| 31 |
|
|
| 32 |
import org.apache.cactus.internal.CactusTestCase;
|
|
| 33 |
import org.apache.cactus.internal.HttpServiceDefinition;
|
|
| 34 |
import org.apache.cactus.internal.ServiceEnumeration;
|
|
| 35 |
import org.apache.cactus.internal.WebTestResult;
|
|
| 36 |
import org.apache.cactus.internal.configuration.Version;
|
|
| 37 |
import org.apache.cactus.internal.util.ClassLoaderUtils;
|
|
| 38 |
import org.apache.commons.logging.Log;
|
|
| 39 |
import org.apache.commons.logging.LogFactory;
|
|
| 40 |
|
|
| 41 |
/**
|
|
| 42 |
* Responsible for instanciating the <code>TestCase</code> class on the server
|
|
| 43 |
* side, set up the implicit objects and call the test method. This class
|
|
| 44 |
* provides a common abstraction for all test web requests.
|
|
| 45 |
*
|
|
| 46 |
* @version $Id: AbstractWebTestCaller.java 238991 2004-05-22 11:34:50Z vmassol $
|
|
| 47 |
*/
|
|
| 48 |
public abstract class AbstractWebTestCaller |
|
| 49 |
{
|
|
| 50 |
/**
|
|
| 51 |
* Name of the attribute in the <code>application</code> scope that will
|
|
| 52 |
* hold the results of the test.
|
|
| 53 |
*/
|
|
| 54 |
protected static final String TEST_RESULTS = |
|
| 55 |
"ServletTestRedirector_TestResults";
|
|
| 56 |
|
|
| 57 |
/**
|
|
| 58 |
* The logger.
|
|
| 59 |
*/
|
|
| 60 |
private static final Log LOGGER = |
|
| 61 |
LogFactory.getLog(AbstractWebTestCaller.class);
|
|
| 62 |
|
|
| 63 |
/**
|
|
| 64 |
* The implicit objects (which will be used to set the test case fields
|
|
| 65 |
* in the <code>setTesCaseFields</code> method.
|
|
| 66 |
*/
|
|
| 67 |
protected WebImplicitObjects webImplicitObjects;
|
|
| 68 |
|
|
| 69 |
/**
|
|
| 70 |
* @param theObjects the implicit objects coming from the redirector
|
|
| 71 |
*/
|
|
| 72 | 48 |
public AbstractWebTestCaller(WebImplicitObjects theObjects)
|
| 73 |
{
|
|
| 74 | 48 |
this.webImplicitObjects = theObjects;
|
| 75 |
} |
|
| 76 |
|
|
| 77 |
/**
|
|
| 78 |
* Sets the implicit object in the test case class
|
|
| 79 |
*
|
|
| 80 |
* @param theTestCase the instance of the test case class on which the
|
|
| 81 |
* class variable (implicit objects) should be set
|
|
| 82 |
* @exception Exception if an errors occurs when setting the implicit
|
|
| 83 |
* objects
|
|
| 84 |
*/
|
|
| 85 |
protected abstract void setTestCaseFields(TestCase theTestCase) |
|
| 86 |
throws Exception;
|
|
| 87 |
|
|
| 88 |
/**
|
|
| 89 |
* @return a <code>Writer</code> object that will be used to return the
|
|
| 90 |
* test result to the client side.
|
|
| 91 |
* @exception IOException if an error occurs when retrieving the writer
|
|
| 92 |
*/
|
|
| 93 |
protected abstract Writer getResponseWriter() throws IOException; |
|
| 94 |
|
|
| 95 |
/**
|
|
| 96 |
* Calls a test method. The parameters needed to call this method are found
|
|
| 97 |
* in the HTTP request. Save the results in the <code>application</code>
|
|
| 98 |
* scope so that the Get Test Result service can find them.
|
|
| 99 |
*
|
|
| 100 |
* @exception ServletException if an unexpected error occurred
|
|
| 101 |
*/
|
|
| 102 | 24 |
public void doTest() throws ServletException |
| 103 |
{
|
|
| 104 | 24 |
WebTestResult result = null;
|
| 105 |
|
|
| 106 | 24 |
try
|
| 107 |
{
|
|
| 108 |
// Create an instance of the test class
|
|
| 109 | 24 |
TestCase testInstance = getTestClassInstance( |
| 110 |
getTestClassName(), getWrappedTestClassName(), |
|
| 111 |
getTestMethodName()); |
|
| 112 |
|
|
| 113 |
// Set its fields (implicit objects)
|
|
| 114 | 24 |
setTestCaseFields(testInstance); |
| 115 |
|
|
| 116 |
// Call it's method corresponding to the current test case
|
|
| 117 | 24 |
if (testInstance instanceof CactusTestCase) |
| 118 |
{
|
|
| 119 | 24 |
((CactusTestCase) testInstance).runBareServer(); |
| 120 |
|
|
| 121 |
} |
|
| 122 |
else
|
|
| 123 |
{
|
|
| 124 | 0 |
testInstance.runBare(); |
| 125 |
} |
|
| 126 |
|
|
| 127 |
// Return an instance of <code>WebTestResult</code> with a
|
|
| 128 |
// positive result.
|
|
| 129 | 24 |
result = new WebTestResult();
|
| 130 |
} |
|
| 131 |
catch (Throwable e)
|
|
| 132 |
{
|
|
| 133 |
// An error occurred, return an instance of
|
|
| 134 |
// <code>WebTestResult</code> with an exception.
|
|
| 135 | 0 |
result = new WebTestResult(e);
|
| 136 |
} |
|
| 137 |
|
|
| 138 | 24 |
LOGGER.debug("Test result : [" + result + "]"); |
| 139 |
|
|
| 140 |
|
|
| 141 |
// Set the test result.
|
|
| 142 | 24 |
this.webImplicitObjects.getServletContext()
|
| 143 |
.setAttribute(TEST_RESULTS, result); |
|
| 144 |
|
|
| 145 | 24 |
LOGGER.debug("Result saved in context scope");
|
| 146 |
} |
|
| 147 |
|
|
| 148 |
/**
|
|
| 149 |
* Return the last test results in the HTTP response.
|
|
| 150 |
*
|
|
| 151 |
* @exception ServletException if an unexpected error occurred
|
|
| 152 |
*/
|
|
| 153 | 24 |
public void doGetResults() throws ServletException |
| 154 |
{
|
|
| 155 |
// One could think there is a potential risk that the client side of
|
|
| 156 |
// Cactus will request the result before it has been written to the
|
|
| 157 |
// context scope as the HTTP request will not block in some containers.
|
|
| 158 |
// However this will not happen because on the client side, once the
|
|
| 159 |
// first request is done to execute the test, all the result is read
|
|
| 160 |
// by the AutoReadHttpURLConnection class, thus ensuring that the
|
|
| 161 |
// request is fully finished and the result has been committed ...
|
|
| 162 | 24 |
WebTestResult result = (WebTestResult) (this.webImplicitObjects
|
| 163 |
.getServletContext().getAttribute(TEST_RESULTS)); |
|
| 164 |
|
|
| 165 |
// It can happen that the result has not been written in the Servlet
|
|
| 166 |
// context. This could happen for example when using a load-balancer
|
|
| 167 |
// which would direct the second Cactus HTTP connection to another
|
|
| 168 |
// instance. In that case, we throw an error.
|
|
| 169 | 24 |
if (result == null) |
| 170 |
{
|
|
| 171 | 0 |
String message = "Error getting test result. This could happen "
|
| 172 |
+ "for example if you're using a load-balancer. Please disable "
|
|
| 173 |
+ "it before running Cactus tests.";
|
|
| 174 |
|
|
| 175 | 0 |
LOGGER.error(message); |
| 176 | 0 |
throw new ServletException(message); |
| 177 |
} |
|
| 178 |
|
|
| 179 | 24 |
LOGGER.debug("Test Result = [" + result + "]"); |
| 180 |
|
|
| 181 |
// Write back the results to the outgoing stream as an XML string.
|
|
| 182 |
|
|
| 183 |
// Use UTF-8 to transfer the result back
|
|
| 184 | 24 |
webImplicitObjects.getHttpServletResponse().setContentType( |
| 185 |
"text/xml; charset=UTF-8");
|
|
| 186 |
|
|
| 187 | 24 |
try
|
| 188 |
{
|
|
| 189 | 24 |
Writer writer = getResponseWriter(); |
| 190 |
|
|
| 191 | 24 |
writer.write(result.toXml()); |
| 192 | 24 |
writer.close(); |
| 193 |
} |
|
| 194 |
catch (IOException e)
|
|
| 195 |
{
|
|
| 196 | 0 |
String message = "Error writing WebTestResult instance to output "
|
| 197 |
+ "stream";
|
|
| 198 |
|
|
| 199 | 0 |
LOGGER.error(message, e); |
| 200 | 0 |
throw new ServletException(message, e); |
| 201 |
} |
|
| 202 |
} |
|
| 203 |
|
|
| 204 |
/**
|
|
| 205 |
* Run the connection test between client and server. This is just to
|
|
| 206 |
* ensure that configuration is set up correctly.
|
|
| 207 |
*
|
|
| 208 |
* @exception ServletException if an unexpected error occurred
|
|
| 209 |
*/
|
|
| 210 | 0 |
public void doRunTest() throws ServletException |
| 211 |
{
|
|
| 212 |
// Do not return any http response (not needed). It is enough to
|
|
| 213 |
// know this point has been reached ... it means the connection has
|
|
| 214 |
// been established !
|
|
| 215 |
} |
|
| 216 |
|
|
| 217 |
/**
|
|
| 218 |
* Return the cactus version. This is to make sure both the client side
|
|
| 219 |
* and server side are using the same version.
|
|
| 220 |
*
|
|
| 221 |
* @exception ServletException if an unexpected error occurred
|
|
| 222 |
*/
|
|
| 223 | 0 |
public void doGetVersion() throws ServletException |
| 224 |
{
|
|
| 225 | 0 |
try
|
| 226 |
{
|
|
| 227 | 0 |
Writer writer = getResponseWriter(); |
| 228 | 0 |
writer.write(Version.VERSION); |
| 229 | 0 |
writer.close(); |
| 230 |
} |
|
| 231 |
catch (IOException e)
|
|
| 232 |
{
|
|
| 233 | 0 |
String message = "Error writing HTTP response back to client "
|
| 234 |
+ "for service [" + ServiceEnumeration.GET_VERSION_SERVICE
|
|
| 235 |
+ "]";
|
|
| 236 |
|
|
| 237 | 0 |
LOGGER.error(message, e); |
| 238 | 0 |
throw new ServletException(message, e); |
| 239 |
} |
|
| 240 |
} |
|
| 241 |
|
|
| 242 |
/**
|
|
| 243 |
* Create an HTTP Session and returns the response that contains the
|
|
| 244 |
* HTTP session as a cookie (unless URL rewriting is used in which
|
|
| 245 |
* case the jsesssionid cookie is not returned).
|
|
| 246 |
*
|
|
| 247 |
* @exception ServletException if an unexpected error occurred
|
|
| 248 |
*/
|
|
| 249 | 0 |
public void doCreateSession() throws ServletException |
| 250 |
{
|
|
| 251 |
// Create an HTTP session
|
|
| 252 | 0 |
this.webImplicitObjects.getHttpServletRequest().getSession(true); |
| 253 |
|
|
| 254 | 0 |
try
|
| 255 |
{
|
|
| 256 | 0 |
Writer writer = getResponseWriter(); |
| 257 | 0 |
writer.close(); |
| 258 |
} |
|
| 259 |
catch (IOException e)
|
|
| 260 |
{
|
|
| 261 | 0 |
String message = "Error writing HTTP response back to client "
|
| 262 |
+ "for service [" + ServiceEnumeration.CREATE_SESSION_SERVICE
|
|
| 263 |
+ "]";
|
|
| 264 |
|
|
| 265 | 0 |
LOGGER.error(message, e); |
| 266 | 0 |
throw new ServletException(message, e); |
| 267 |
} |
|
| 268 |
} |
|
| 269 |
|
|
| 270 |
/**
|
|
| 271 |
* @return the class to test class name, extracted from the HTTP request
|
|
| 272 |
* @exception ServletException if the class name of the test case is missing
|
|
| 273 |
* from the HTTP request
|
|
| 274 |
*/
|
|
| 275 | 24 |
protected String getTestClassName() throws ServletException |
| 276 |
{
|
|
| 277 | 24 |
String queryString = this.webImplicitObjects.getHttpServletRequest()
|
| 278 |
.getQueryString(); |
|
| 279 | 24 |
String className = ServletUtil.getQueryStringParameter(queryString, |
| 280 |
HttpServiceDefinition.CLASS_NAME_PARAM); |
|
| 281 |
|
|
| 282 | 24 |
if (className == null) |
| 283 |
{
|
|
| 284 | 0 |
String message = "Missing class name parameter ["
|
| 285 |
+ HttpServiceDefinition.CLASS_NAME_PARAM |
|
| 286 |
+ "] in HTTP request.";
|
|
| 287 |
|
|
| 288 | 0 |
LOGGER.error(message); |
| 289 | 0 |
throw new ServletException(message); |
| 290 |
} |
|
| 291 |
|
|
| 292 | 24 |
LOGGER.debug("Class to call = [" + className + "]"); |
| 293 |
|
|
| 294 | 24 |
return className;
|
| 295 |
} |
|
| 296 |
|
|
| 297 |
/**
|
|
| 298 |
* @return the optional test class that is wrapped by a Cactus test case,
|
|
| 299 |
* extracted from the HTTP request
|
|
| 300 |
* @exception ServletException if the wrapped class name is missing from
|
|
| 301 |
* the HTTP request
|
|
| 302 |
*/
|
|
| 303 | 24 |
protected String getWrappedTestClassName() throws ServletException |
| 304 |
{
|
|
| 305 | 24 |
String queryString = this.webImplicitObjects.getHttpServletRequest()
|
| 306 |
.getQueryString(); |
|
| 307 | 24 |
String className = ServletUtil.getQueryStringParameter(queryString, |
| 308 |
HttpServiceDefinition.WRAPPED_CLASS_NAME_PARAM); |
|
| 309 |
|
|
| 310 | 24 |
if (className == null) |
| 311 |
{
|
|
| 312 | 24 |
LOGGER.debug("No wrapped test class");
|
| 313 |
} |
|
| 314 |
else
|
|
| 315 |
{
|
|
| 316 | 0 |
LOGGER.debug("Wrapped test class = [" + className + "]"); |
| 317 |
} |
|
| 318 |
|
|
| 319 | 24 |
return className;
|
| 320 |
} |
|
| 321 |
|
|
| 322 |
/**
|
|
| 323 |
* @return the class method to call for the current test case, extracted
|
|
| 324 |
* from the HTTP request
|
|
| 325 |
* @exception ServletException if the method name of the test case is
|
|
| 326 |
* missing from the HTTP request
|
|
| 327 |
*/
|
|
| 328 | 24 |
protected String getTestMethodName() throws ServletException |
| 329 |
{
|
|
| 330 | 24 |
String queryString = this.webImplicitObjects.getHttpServletRequest()
|
| 331 |
.getQueryString(); |
|
| 332 | 24 |
String methodName = ServletUtil.getQueryStringParameter(queryString, |
| 333 |
HttpServiceDefinition.METHOD_NAME_PARAM); |
|
| 334 |
|
|
| 335 | 24 |
if (methodName == null) |
| 336 |
{
|
|
| 337 | 0 |
String message = "Missing method name parameter ["
|
| 338 |
+ HttpServiceDefinition.METHOD_NAME_PARAM |
|
| 339 |
+ "] in HTTP request.";
|
|
| 340 |
|
|
| 341 | 0 |
LOGGER.error(message); |
| 342 | 0 |
throw new ServletException(message); |
| 343 |
} |
|
| 344 |
|
|
| 345 | 24 |
LOGGER.debug("Method to call = " + methodName);
|
| 346 |
|
|
| 347 | 24 |
return methodName;
|
| 348 |
} |
|
| 349 |
|
|
| 350 |
/**
|
|
| 351 |
* @return true if the auto session flag for the Session can be found in
|
|
| 352 |
* the HTTP request
|
|
| 353 |
*/
|
|
| 354 | 19 |
protected boolean isAutoSession() |
| 355 |
{
|
|
| 356 | 19 |
String queryString = this.webImplicitObjects.getHttpServletRequest()
|
| 357 |
.getQueryString(); |
|
| 358 | 19 |
String autoSession = ServletUtil.getQueryStringParameter(queryString, |
| 359 |
HttpServiceDefinition.AUTOSESSION_NAME_PARAM); |
|
| 360 |
|
|
| 361 | 19 |
boolean isAutomaticSession =
|
| 362 |
Boolean.valueOf(autoSession).booleanValue(); |
|
| 363 |
|
|
| 364 | 19 |
LOGGER.debug("Auto session is " + isAutomaticSession);
|
| 365 |
|
|
| 366 | 19 |
return isAutomaticSession;
|
| 367 |
} |
|
| 368 |
|
|
| 369 |
/**
|
|
| 370 |
* @param theClassName the name of the test class
|
|
| 371 |
* @param theWrappedClassName the name of the wrapped test class. Can be
|
|
| 372 |
* null if there is none
|
|
| 373 |
* @param theTestCaseName the name of the current test case
|
|
| 374 |
* @return an instance of the test class to call
|
|
| 375 |
* @exception ServletException if the test case instance for the current
|
|
| 376 |
* test fails to be instanciated (for example if some
|
|
| 377 |
* information is missing from the HTTP request)
|
|
| 378 |
*/
|
|
| 379 | 24 |
protected TestCase getTestClassInstance(
|
| 380 |
String theClassName, String theWrappedClassName, |
|
| 381 |
String theTestCaseName) throws ServletException
|
|
| 382 |
{
|
|
| 383 |
// Get the class to call and build an instance of it.
|
|
| 384 | 24 |
Class testClass = getTestClassClass(theClassName); |
| 385 | 24 |
TestCase testInstance = null;
|
| 386 | 24 |
Constructor constructor; |
| 387 |
|
|
| 388 | 24 |
try
|
| 389 |
{
|
|
| 390 | 24 |
if (theWrappedClassName == null) |
| 391 |
{
|
|
| 392 | 24 |
constructor = getTestClassConstructor(testClass); |
| 393 |
|
|
| 394 | 24 |
if (constructor.getParameterTypes().length == 0)
|
| 395 |
{
|
|
| 396 | 24 |
testInstance = (TestCase) constructor.newInstance( |
| 397 |
new Object[0]);
|
|
| 398 | 24 |
((TestCase) testInstance).setName(theTestCaseName); |
| 399 |
} |
|
| 400 |
else
|
|
| 401 |
{
|
|
| 402 | 0 |
testInstance = (TestCase) constructor.newInstance( |
| 403 |
new Object[] {theTestCaseName});
|
|
| 404 |
} |
|
| 405 |
} |
|
| 406 |
else
|
|
| 407 |
{
|
|
| 408 | 0 |
Class wrappedTestClass = |
| 409 |
getTestClassClass(theWrappedClassName); |
|
| 410 | 0 |
Constructor wrappedConstructor = |
| 411 |
getTestClassConstructor(wrappedTestClass); |
|
| 412 |
|
|
| 413 | 0 |
TestCase wrappedTestInstance; |
| 414 | 0 |
if (wrappedConstructor.getParameterTypes().length == 0)
|
| 415 |
{
|
|
| 416 | 0 |
wrappedTestInstance = |
| 417 |
(TestCase) wrappedConstructor.newInstance( |
|
| 418 |
new Object[0]);
|
|
| 419 | 0 |
wrappedTestInstance.setName(theTestCaseName); |
| 420 |
} |
|
| 421 |
else
|
|
| 422 |
{
|
|
| 423 | 0 |
wrappedTestInstance = |
| 424 |
(TestCase) wrappedConstructor.newInstance( |
|
| 425 |
new Object[] {theTestCaseName});
|
|
| 426 |
} |
|
| 427 |
|
|
| 428 | 0 |
constructor = testClass.getConstructor( |
| 429 |
new Class[] {String.class, Test.class}); |
|
| 430 |
|
|
| 431 | 0 |
testInstance = |
| 432 |
(TestCase) constructor.newInstance( |
|
| 433 |
new Object[] {theTestCaseName, wrappedTestInstance});
|
|
| 434 |
} |
|
| 435 |
} |
|
| 436 |
catch (Exception e)
|
|
| 437 |
{
|
|
| 438 | 0 |
String message = "Error instantiating class [" + theClassName + "([" |
| 439 |
+ theTestCaseName + "], [" + theWrappedClassName + "])]"; |
|
| 440 |
|
|
| 441 | 0 |
LOGGER.error(message, e); |
| 442 | 0 |
throw new ServletException(message, e); |
| 443 |
} |
|
| 444 |
|
|
| 445 | 24 |
return testInstance;
|
| 446 |
} |
|
| 447 |
|
|
| 448 |
/**
|
|
| 449 |
* @param theTestClass the test class for which we want to find the
|
|
| 450 |
* constructor
|
|
| 451 |
* @return the availble constructor for the test class
|
|
| 452 |
* @throws NoSuchMethodException if no suitable constructor is found
|
|
| 453 |
*/
|
|
| 454 | 24 |
private Constructor getTestClassConstructor(Class theTestClass)
|
| 455 |
throws NoSuchMethodException
|
|
| 456 |
{
|
|
| 457 | 24 |
Constructor constructor; |
| 458 | 24 |
try
|
| 459 |
{
|
|
| 460 | 24 |
constructor = theTestClass.getConstructor( |
| 461 |
new Class[] {String.class}); |
|
| 462 |
} |
|
| 463 |
catch (NoSuchMethodException e)
|
|
| 464 |
{
|
|
| 465 | 24 |
constructor = theTestClass.getConstructor(new Class[0]);
|
| 466 |
} |
|
| 467 | 24 |
return constructor;
|
| 468 |
} |
|
| 469 |
|
|
| 470 |
/**
|
|
| 471 |
* @param theClassName the name of the test class
|
|
| 472 |
* @return the class object the test class to call
|
|
| 473 |
* @exception ServletException if the class of the current test case
|
|
| 474 |
* cannot be loaded in memory (i.e. it is not in the
|
|
| 475 |
* classpath)
|
|
| 476 |
*/
|
|
| 477 | 24 |
protected Class getTestClassClass(String theClassName)
|
| 478 |
throws ServletException
|
|
| 479 |
{
|
|
| 480 |
// Get the class to call and build an instance of it.
|
|
| 481 | 24 |
Class testClass = null;
|
| 482 |
|
|
| 483 | 24 |
try
|
| 484 |
{
|
|
| 485 | 24 |
testClass = ClassLoaderUtils.loadClass(theClassName, |
| 486 |
this.getClass());
|
|
| 487 |
} |
|
| 488 |
catch (Exception e)
|
|
| 489 |
{
|
|
| 490 | 0 |
String message = "Error finding class [" + theClassName
|
| 491 |
+ "] using both the Context classloader and the webapp "
|
|
| 492 |
+ "classloader. Possible causes include:\r\n";
|
|
| 493 |
|
|
| 494 | 0 |
message += ("\t- Your webapp does not include your test "
|
| 495 |
+ "classes,\r\n");
|
|
| 496 | 0 |
message += ("\t- The cactus.jar is not located in your "
|
| 497 |
+ "WEB-INF/lib directory and your Container has not set the "
|
|
| 498 |
+ "Context classloader to point to the webapp one");
|
|
| 499 |
|
|
| 500 | 0 |
LOGGER.error(message, e); |
| 501 | 0 |
throw new ServletException(message, e); |
| 502 |
} |
|
| 503 |
|
|
| 504 | 24 |
return testClass;
|
| 505 |
} |
|
| 506 |
|
|
| 507 |
} |
|
| 508 |
|
|
||||||||||