| Method from org.apache.tomcat.core.ServletWrapper Detail: |
void destroy() {
// Fancy sync logic is to make sure that no threads are in the
// handlerequest when this is called and, furthermore, that
// no threads go through handle request after this method starts!
if (servlet != null) {
synchronized (this) {
// Wait until there are no outstanding service calls,
// or until 30 seconds have passed (to avoid a hang)
while (serviceCount > 0) {
try {
wait(30000);
break;
} catch (InterruptedException e) { }
}
try {
final Servlet sinstance = servlet;
Context context = getContext();
handleInvocation(
context.getDestroyInterceptors().elements(),
new LifecycleInvocationHandler(context, servlet) {
void method() throws ServletException {
sinstance.destroy();
}
});
} catch(IOException ioe) {
// Should never come here...
} catch(ServletException se) {
// Should never come here...
}
}
}
}
|
String getPath() {
return this.path;
}
|
Servlet getServlet() {
return servlet;
}
|
String getServletClass() {
return this.servletClassName;
}
|
String getServletDescription() {
return this.description;
}
|
String getServletName() {
return config.getServletName();
}
|
public void handleException(HttpServletRequestFacade request,
HttpServletResponseFacade response,
Throwable t) {
Context context = request.getRealRequest().getContext();
ServletContextFacade contextFacade = context.getFacade();
// Scan the exception's inheritance tree looking for a rule
// that this type of exception should be forwarded
String path = null;
Class clazz = t.getClass();
while (path == null && clazz != null) {
String name = clazz.getName();
path = context.getErrorPage(name);
clazz = clazz.getSuperclass();
}
// If path is non-null, we should do a forward
// Don't do a forward if exception_type is already defined though to
// avoid an infinite loop.
if (path != null &&
request.getAttribute(
Constants.Attribute.ERROR_EXCEPTION_TYPE) == null) {
RequestDispatcher rd = contextFacade.getRequestDispatcher(path);
// XXX
// The spec should really be changed to allow us to include
// the full exception object. Oh well.
request.setAttribute(Constants.Attribute.ERROR_EXCEPTION_TYPE,
t.getClass().getName());
request.setAttribute(Constants.Attribute.ERROR_MESSAGE,
t.getMessage());
try {
try {
// A forward would be ideal, so reset and try it
response.getRealResponse().reset();
rd.forward(request, response);
} catch (IllegalStateException ise) {
// Oops, too late for a forward; settle for an include
rd.include(request, response);
}
} catch (IOException e) {
// Shouldn't get here
} catch (ServletException e) {
// Shouldn't get here
}
} else {
try {
sendInternalServletError(t, response);
} catch (IOException e) {
// ???
}
}
}
|
void handleRequest(HttpServletRequestFacade request,
HttpServletResponseFacade response) throws IOException {
// if (isReloadable) {
// long lm = servletClassFile.lastModified();
// if (lm > classFileLastMod) {
// //container.recycle();
// }
// }
// make sure that only one thread goes through
// this block at a time!
synchronized (this) {
// XXX
// rather klunky - this method needs a once over
if (path != null &&
servletClass == null &&
servletClassName == null) {
String requestURI = path + request.getPathInfo();
RequestDispatcher rd =
request.getRequestDispatcher(requestURI);
try {
// Watch out, ugly code ahead...
// We need to do a forward or include here, but we can't
// easily determine which. So we try a forward, and if
// there's an IllegalStateException thrown, then we know
// we should have tried an include, so we do the include.
// It's so ugly I have to giggle.
// All this to support dispatching to named JSPs!
try {
rd.forward(request, response);
} catch (IllegalStateException e) {
rd.include(request, response);
}
} catch (ServletException se) {
//FIXME: markd@lutris.com: Need to log here.
response.sendError(404);
} catch (IOException ioe) {
//FIXME: markd@lutris.com: Need to log here.
response.sendError(404);
}
return;
} else {
if (servlet == null) {
try {
loadServlet();
} catch (ClassNotFoundException e) {
//FIXME: markd@lutris.com: Need to log here.
container.getContext().getLogChannel().write(com.lutris.logging.Logger.ERROR,
"Class not found " + servletClassName);
response.sendError(404);
return;
} catch (Exception e) {
// Make sure the servlet will never
// service a request
servlet = null;
// XXX
// check to see what kind of exception it was --
// maybe it should be reported to the user
// differently or at least logged differently
// XXX
// we really need to pick up an error file on
// a per context basis or, failing that from the
// classpath
//FIXME: markd@lutris.com: Need to log here.
sendInternalServletError(e, response);
return;
}
}
}
}
try {
synchronized(this) {
serviceCount++;
}
Context context = getContext();
Enumeration serviceInterceptors =
context.getServiceInterceptors().elements();
ServiceInvocationHandler serviceHandler =
new ServiceInvocationHandler(context, servlet,
request, response);
handleInvocation(serviceInterceptors, serviceHandler);
} catch (ServletException e) {
// XXX
// check to see if it's unavailable and set internal status
// appropriately
// XXX
// if it's an unvailable exception, we probably want
// to paint a different screen
handleException(request, response, e);
return;
} catch (SocketException e) {
// XXX
// Catch and eat all SocketExceptions
// *Should* only eat client disconnected socket exceptions
return;
} catch (Throwable e) {
// if we are in an include, then we should rethrow the
// exception
// XXX
// we need a better way of dealing with figuring out
// if we are in an include -- this particular gem
// will pass IllegalStateException when we are in
// an include 'cause users will like to know when
// that happens in their included servlet
//if (e instanceof IllegalStateException) {
// String str = (String)request.getAttribute
// (Constants.Attribute.RequestURI);
// if (str != null) {
// throw (IllegalStateException)e;
// }
//}
// XXX
// decide which exceptions we should not eat at this point
handleException(request, response, e);
return;
} finally {
synchronized(this) {
serviceCount--;
notifyAll();
}
}
}
|
void loadServlet() throws ClassNotFoundException, ServletException, IllegalAccessException, InstantiationException {
// Check if this is a JSP, they get special treatment
if (path != null &&
servletClass == null &&
servletClassName == null) {
// XXX XXX XXX
// core shouldn't depend on a particular connector!
// need to find out what this code does!
RequestAdapterImpl reqA=new RequestAdapterImpl();
ResponseAdapterImpl resA=new ResponseAdapterImpl();
Request request = new Request();
Response response = new Response();
request.recycle();
response.recycle();
request.setRequestAdapter( reqA );
response.setResponseAdapter( resA );
request.setResponse(response);
response.setRequest(request);
String requestURI = path + "?" +
Constants.JSP.Directive.Compile.Name + "=" +
Constants.JSP.Directive.Compile.Value;
reqA.setRequestURI(getContext().getPath() + path);
reqA.setQueryString( Constants.JSP.Directive.Compile.Name + "=" +
Constants.JSP.Directive.Compile.Value );
request.setContext(getContext());
request.getSession(true);
RequestDispatcher rd =
config.getServletContext().getRequestDispatcher(requestURI);
try {
rd.forward(request.getFacade(), response.getFacade());
} catch (ServletException se) {
} catch (IOException ioe) {
}
} else {
if (servletClass == null) {
if (servletClassName == null) {
String msg = sm.getString("wrapper.load.noclassname");
throw new IllegalStateException(msg);
}
servletClass = container.getLoader().loadServlet(this,
servletClassName);
}
// make sure we have a classname or class def
//if (servletClassName == null || servletClass == null) {
// String msg = sm.getString("wrapper.load.noclassname");
// throw new IllegalStateException(msg);
// }
//Class c = container.getLoader().loadServlet(this,
//servletClassName);
servlet = (Servlet)servletClass.newInstance();
config.setServletClassName(servlet.getClass().getName());
try {
final Servlet sinstance = servlet;
final ServletConfigImpl servletConfig = config;
Context context = getContext();
handleInvocation(context.getInitInterceptors().elements(),
new LifecycleInvocationHandler(context, servlet) {
void method() throws ServletException {
sinstance.init(servletConfig);
}
});
} catch(IOException ioe) {
// Should never come here...
}
}
}
|
void printRootCause(ServletException e,
PrintWriter out) {
Throwable cause = e.getRootCause();
if (cause != null) {
out.println("< b >Root cause:< /b >");
out.println("< pre >");
cause.printStackTrace(out);
out.println("< /pre >");
if (cause instanceof ServletException) {
printRootCause((ServletException)cause, out); // recurse
}
}
}
|
void sendInternalServletError(Throwable e,
HttpServletResponseFacade response) throws IOException {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println("< b >Internal Servlet Error:< /b >< br >");
pw.println("< pre >");
e.printStackTrace(pw);
pw.println("< /pre >");
if (e instanceof ServletException) {
printRootCause((ServletException) e, pw);
}
response.sendError(500, sw.toString());
}
|
void setInitArgs(Hashtable initArgs) {
config.setInitArgs(initArgs);
}
|
void setPath(String path) {
this.path = path;
}
|
void setReloadable(boolean reloadable) {
isReloadable = reloadable;
}
|
void setServletClass(String servletClassName) {
this.servletClassName = servletClassName;
config.setServletClassName(servletClassName);
}
|
void setServletClass(Class servletClass) {
this.servletClass = servletClass;
config.setServletClassName(this.servletClass.getName());
}
|
void setServletClassFile(File servletClassFile) {
this.servletClassFile = servletClassFile;
classFileLastMod = servletClassFile.lastModified();
config.setServletClassName(this.servletClassFile.getName());
}
|
void setServletDescription(String description) {
this.description = description;
}
|
void setServletName(String servletName) {
config.setServletName(servletName);
}
|