📄 servletwrapper.java
字号:
if (servletClass == null) {
if (servletClassName == null) {
throw new IllegalStateException("Can't happen - classname "
+ "is null, who added this ?");
}
ServletLoader loader=context.getServletLoader();
servletClass=loader.loadClass(servletClassName);
}
servlet = (Servlet)servletClass.newInstance();
// hack for internal servlets
if( ! servletClassName.startsWith("org.apache.tomcat") ) return;
}
/** Override Handler's init - load the servlet before calling
and interceptor
*/
public void init()
throws Exception
{
// make sure the servlet in loaded before calling preInit
// Jsp case - maybe another Jsp engine is used
if( servlet==null && path != null && servletClassName == null) {
// System.out.println("Handle Jsp init " + servletClassName);
handleJspInit();
}
// Will throw exception if it can't load, let upper
// levels handle this
// try {
if( servlet==null ) loadServlet();
// } catch( ClassNotFoundException ex ) {
// } catch( InstantiationException ex ) {
//} catch( IllegalStateException ex ) {
//}
// Call pre, doInit and post
super.init();
}
protected void doInit()
throws Exception
{
// The servlet is loaded and not null - otherwise init()
// throws exception
try {
// if multiple threads will call the same servlet at once,
// we should have only one init
synchronized( this ) {
// we may have 2 threads entering doInit,
// the first one may init the servlet
if( initialized )
return;
final Servlet sinstance = servlet;
final ServletConfig servletConfig = configF;
// init - only if unavailable was null or
// unavailable period expired
servlet.init(servletConfig);
initialized=true;
}
} catch( UnavailableException ex ) {
unavailable=ex;
unavailableTime=System.currentTimeMillis();
unavailableTime += ex.getUnavailableSeconds() * 1000;
servlet=null;
throw ex;
} catch( Exception ex ) {
unavailable=ex;
servlet=null;
throw ex;
}
}
/** Override service to hook reloading - it can be done in a clean
* interceptor. It also hooks jsp - we should have a separate
* JspHandler
*
* @exception IOException if an input/output error occurs and we are
* processing an included servlet (otherwise it is swallowed and
* handled by the top level error handler mechanism)
* @exception ServletException if a servlet throws an exception and
* we are processing an included servlet (otherwise it is swallowed
* and handled by the top level error handler mechanism)
*/
public void service(Request req, Response res)
throws IOException, ServletException
{
try {
handleReload(req);
} catch( TomcatException ex ) {
ex.printStackTrace();// what to do ?
}
// <servlet><jsp-file> case
if( path!=null ) {
if( path.startsWith("/"))
req.setAttribute( "javax.servlet.include.request_uri",
req.getContext().getPath() + path );
else
req.setAttribute( "javax.servlet.include.request_uri",
req.getContext().getPath() + "/" + path );
req.setAttribute( "javax.servlet.include.servlet_path", path );
}
if( unavailable!=null ) {
// check servlet availability, throw appropriate exception if not
servletAvailable(req,res);
}
// called only if unavailable==null or timer expired.
// will do an init
try {
super.service( req, res );
} catch( IOException e ) {
throw e;
} catch ( UnavailableException e ) {
// if unavailable not set, assume thrown from service(), not init()
if (unavailable == null && res.getErrorException() != e) {
synchronized(this) {
if (unavailable == null) {
res.setErrorException(e);
unavailable = e;
// XXX if the UnavailableException is permanent we are supposed
// to destroy the servlet. Synchronization of this destruction
// needs review before adding this.
unavailableTime = System.currentTimeMillis();
unavailableTime += e.getUnavailableSeconds() * 1000;
}
}
}
throw e;
} catch( ServletException e ) {
throw e;
}
}
protected void doService(Request req, Response res)
throws Exception
{
// We are initialized and fine
if (servlet instanceof SingleThreadModel) {
synchronized(servlet) {
servlet.service(req.getFacade(), res.getFacade());
}
} else {
servlet.service(req.getFacade(), res.getFacade());
}
// clear any error exception since none were thrown
res.setErrorException(null);
res.setErrorURI(null);
}
// -------------------- Reloading --------------------
// XXX Move it to interceptor - so it can be customized
// Reloading
// XXX ugly - should find a better way to deal with invoker
// The problem is that we are just clearing up invoker, not
// the class loaded by invoker.
void handleReload(Request req) throws TomcatException {
// That will be reolved after we reset the context - and many
// other conflicts.
if( isReloadable ) {// && ! "invoker".equals( getServletName())) {
ServletLoader loader=context.getServletLoader();
if( loader!=null) {
// We need to syncronize here so that multiple threads don't
// try and reload the class. The first thread through will
// create the new loader which will make shouldReload return
// false for subsequent threads.
synchronized(this) {
// XXX no need to check after we remove the old loader
if( loader.shouldReload() ) {
// workaround for destroy
try {
destroy();
} catch(Exception ex ) {
context.log( "Error in destroy ", ex );
}
initialized=false;
loader.reload();
ContextManager cm=context.getContextManager();
cm.doReload( req, context );
servlet=null;
servletClass=null;
/* Initial attempt to shut down the context and sessions.
String path=context.getPath();
String docBase=context.getDocBase();
// XXX all other properties need to be saved
// or something else
ContextManager cm=context.getContextManager();
cm.removeContext(path);
Context ctx=new Context();
ctx.setPath( path );
ctx.setDocBase( docBase );
cm.addContext( ctx );
context=ctx;
// XXX shut down context, remove sessions, etc
*/
}
}
}
}
}
// -------------------- Jsp hooks
// <servlet><jsp-file> case - we know it's a jsp
void handleJspInit() {
// XXX Jsp Servlet is initialized, the servlet is not generated -
// we can't hook in! It's jspServet that has to pass the config -
// but it can't so easily, plus it'll have to hook in.
// I don't think that ever worked anyway - and I don't think
// it can work without integrating Jsp handling into tomcat
// ( using interceptor )
ServletWrapper jspServletW = context.getServletByName("jsp");
servletClassName = jspServletW.getServletClass();
}
// -------------------- Unavailable --------------------
/** Check if we can try again an init
*/
private void servletAvailable(Request req, Response res)
throws IOException, ServletException
{
// if permanently unavailable, rethrow exception
if (unavailable instanceof UnavailableException &&
((UnavailableException)unavailable).isPermanent()) {
res.setErrorException(unavailable);
contextM.saveErrorURI( req, res );
throw (UnavailableException)unavailable;
}
// we have a timer - maybe we can try again - how much
// do we have to wait - (in mSec)
long moreWaitTime=unavailableTime - System.currentTimeMillis();
if( moreWaitTime > 0 ) {
// get seconds left, rounded up to at least one second
int secs = (int)((moreWaitTime + 999) / 1000);
// set updated exception
res.setErrorException(new UnavailableException(
unavailable.getMessage(), secs));
contextM.saveErrorURI( req, res );
// throw updated exception
throw (UnavailableException)res.getErrorException();
}
// we can try again
unavailable=null;
unavailableTime=-1;
context.log(getServletName() + " unavailable time expired," +
" try again ");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -