You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@locus.apache.org on 2000/09/17 08:47:25 UTC
cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/task ApacheConfig.java StopTomcat.java
costin 00/09/16 23:47:25
Modified: src/share/org/apache/tomcat/core BaseInterceptor.java
Container.java ContextManager.java Request.java
src/share/org/apache/tomcat/startup EmbededTomcat.java
src/share/org/apache/tomcat/task ApacheConfig.java
StopTomcat.java
Log:
- Added code to detect what methods are overriden in interceptors.
This allows to call only the interceptors that are interested in a certain
event.
- copied the comments from Request and ContextInterceptor to BaseInterceptor.
- moved the code handling interceptors from ContextManager to Container.
This is based on Nacho's changes that allows setting per/container interceptor.
- added individual chains. Right now this duplicates the old system,
after more tests the old requestInterceptors[] will be removed and replaced
by the new chains.
- Updated comments in ContextManager, removed old debug messages, removed unused
code hanging around
Revision Changes Path
1.18 +174 -16 jakarta-tomcat/src/share/org/apache/tomcat/core/BaseInterceptor.java
Index: BaseInterceptor.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/BaseInterceptor.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- BaseInterceptor.java 2000/08/13 02:04:12 1.17
+++ BaseInterceptor.java 2000/09/17 06:47:21 1.18
@@ -67,8 +67,12 @@
import java.io.*;
import java.net.*;
import java.util.*;
+import java.lang.reflect.*;
-/**
+/** Implement "Chain of Responsiblity" pattern ( == hooks ).
+ *
+ * You can extend this class and implement a number of hooks.
+ *
*/
public class BaseInterceptor implements RequestInterceptor, ContextInterceptor {
protected ContextManager cm;
@@ -83,10 +87,39 @@
public BaseInterceptor() {
}
+ // -------------------- Helpers --------------------
public void setDebug( int d ) {
debug=d;
}
+ public static final String BASE_I="org.apache.tomcat.core.BaseInterceptor";
+
+ /** Test if the interceptor implements a particular
+ method
+ */
+ public boolean hasHook( String methodN ) {
+ // all interceptors will participate in all context-level
+ // hooks - no need to exagerate
+ if( "engineInit".equals( methodN ) )
+ return true;
+ try {
+ Method myMethods[]=this.getClass().getMethods();
+ for( int i=0; i< myMethods.length; i++ ) {
+ if( methodN.equals ( myMethods[i].getName() )) {
+ // check if it's overriden
+ Class declaring=myMethods[i].getDeclaringClass();
+ if( ! BASE_I.equals(declaring.getName() )) {
+ //log( "Found overriden method " + methodN);
+ return true;
+ }
+ }
+ }
+ } catch ( Exception ex ) {
+ ex.printStackTrace();
+ }
+ return false;
+ }
+
public void setContextManager( ContextManager cm ) {
this.cm=cm;
this.ct=cm.getContainer();
@@ -115,44 +148,96 @@
}
// -------------------- Request notifications --------------------
+
+ /** Handle mappings inside a context.
+ * You are required to respect the mappings in web.xml.
+ */
public int requestMap(Request request ) {
return 0;
}
-
+ /** Will detect the context path for a request.
+ * It need to set: context, contextPath, lookupPath
+ *
+ * A possible use for this would be a "user-home" interceptor
+ * that will implement ~costin servlets ( add and map them at run time).
+ */
public int contextMap( Request rrequest ) {
return 0;
}
+ /**
+ * This callback is used to extract and verify the user identity
+ * and credentials.
+ *
+ * It will set the RemoteUser field if it can authenticate.
+ * The auth event is generated by a user asking for the remote
+ * user field of by tomcat if a request requires authenticated
+ * id.
+ */
public int authenticate(Request request, Response response) {
return 0;
}
+ /**
+ * Will check if the current ( authenticated ) user is authorized
+ * to access a resource, by checking if it have one of the
+ * required roles.
+ *
+ * This is used by tomcat to delegate the authorization to modules.
+ * The authorize is called by isUserInRole() and by ContextManager
+ * if the request have security constraints.
+ *
+ * @returns 0 if the module can't take a decision
+ * 401 If the user is not authorized ( doesn't have
+ * any of the required roles )
+ * 200 If the user have the right roles. No further module
+ * will be called.
+ */
public int authorize(Request request, Response response,
String reqRoles[]) {
return 0;
}
+ /** Called before service method is invoked.
+ */
public int preService(Request request, Response response) {
return 0;
}
+ /** Called before the first body write, and before sending
+ * the headers. The interceptor have a chance to change the
+ * output headers.
+ */
public int beforeBody( Request rrequest, Response response ) {
return 0;
}
+ /** New Session notification - called when the servlet
+ asks for a new session. You can do all kind of stuff with
+ this notification - the most important is create a session
+ object. This will be the base for controling the
+ session allocation.
+ */
public int newSessionRequest( Request request, Response response) {
return 0;
}
+ /** Called before the output buffer is commited.
+ */
public int beforeCommit( Request request, Response response) {
return 0;
}
+ /** Called after the output stream is closed ( either by servlet
+ * or automatically at end of service ).
+ */
public int afterBody( Request request, Response response) {
return 0;
}
+ /** Called after service method ends. Log is a particular use.
+ */
public int postService(Request request, Response response) {
return 0;
}
@@ -162,15 +247,56 @@
}
// -------------------- Context notifications --------------------
- public void contextInit(Context ctx) throws TomcatException {
+ /** Notify when a context is initialized.
+ * The first interceptor in the chain for contextInit must read web.xml
+ * and set the context. When this method is called you can expect the
+ * context to be filled in with all the informations from web.xml.
+ */
+ public void contextInit(Context ctx)
+ throws TomcatException
+ {
}
- public void contextShutdown(Context ctx) throws TomcatException {
+ /** Called when a context is stoped, before removeContext.
+ * You must free all resources.
+ * XXX - do we need this or removeContext is enough ?? ( will be
+ * removed from 3.1 if nobody asks for it)
+ */
+ public void contextShutdown(Context ctx)
+ throws TomcatException
+ {
}
- public void addContainer(Container container) throws TomcatException {
+
+ /** A new location was added to the server. A location is defined as a
+ * set of URL patterns with common properties. All servlet mappings
+ * and security constraints are in this category - with a common
+ * handler and a common set of authorized roles.
+ *
+ * An interceptor interested in mapping must implement this method
+ * and construct it's internal representation. The mapper is _required_
+ * to find the Container associated with a request using the mapping
+ * rules defined in the Servlet API.
+ *
+ * The interceptor must also take care of "merging" parent with child
+ * containers. It is possible that this method will be called several
+ * times for the same url pattern ( for example to define a handler
+ * and then security constraints), the interceptor needs to
+ * merge the 2 containers.
+ *
+ * XXX define "merging" of containers
+ */
+ public void addContainer(Container container)
+ throws TomcatException
+ {
}
+
+ /** A rule was removed, update the internal strucures. You can also
+ * clean up and reload everything using Context.getContainers()
+ */
- public void removeContainer(Container container) throws TomcatException {
+ public void removeContainer(Container container)
+ throws TomcatException
+ {
}
/**
@@ -182,27 +308,51 @@
/** Called when the ContextManger is started
*/
- public void engineInit(ContextManager cm) throws TomcatException {
+ public void engineInit(ContextManager cm)
+ throws TomcatException
+ {
this.cm=cm;
}
/** Called before the ContextManager is stoped.
* You need to stop any threads and remove any resources.
*/
- public void engineShutdown(ContextManager cm) throws TomcatException {
+ public void engineShutdown(ContextManager cm)
+ throws TomcatException
+ {
}
- /** Called when a context is added to a CM
+ /** Called when a context is added to a CM. The context is probably not
+ * initialized yet, only path and docRoot are probably set.
+ *
+ * If you need informations that are available in web.xml use
+ * contextInit()( a WebXmlReader needs to be the first interceptor in
+ * the contextInit chain ).
+ *
+ * We do that to support ( eventualy ) a "lazy" init, where you have
+ * many contexts, most of them not in active use, and you'll init them
+ * at first request. ( for example an ISP with many users )
+ *
*/
- public void addContext( ContextManager cm, Context ctx ) throws TomcatException {
+ public void addContext( ContextManager cm, Context ctx )
+ throws TomcatException
+ {
}
- /** Called when a context is removed from a CM
+ /** Called when a context is removed from a CM. A context is removed
+ * either as a result of admin ( remove or update), to support "clean"
+ * servlet reloading or at shutdown.
*/
- public void removeContext( ContextManager cm, Context ctx ) throws TomcatException {
+ public void removeContext( ContextManager cm, Context ctx )
+ throws TomcatException
+ {
}
+ /** Reload notification - called whenever a reload is done.
+ This can be used to serialize sessions, log the event,
+ remove any resource that was class-loader dependent.
+ */
public void reload( Request req, Context ctx)
throws TomcatException
{
@@ -210,20 +360,28 @@
/** Servlet Init notification
*/
- public void preServletInit( Context ctx, Handler sw ) throws TomcatException {
+ public void preServletInit( Context ctx, Handler sw )
+ throws TomcatException
+ {
}
- public void postServletInit( Context ctx, Handler sw ) throws TomcatException {
+ public void postServletInit( Context ctx, Handler sw )
+ throws TomcatException
+ {
}
/** Servlet Destroy notification
*/
- public void preServletDestroy( Context ctx, Handler sw ) throws TomcatException {
+ public void preServletDestroy( Context ctx, Handler sw )
+ throws TomcatException
+ {
}
- public void postServletDestroy( Context ctx, Handler sw ) throws TomcatException {
+ public void postServletDestroy( Context ctx, Handler sw )
+ throws TomcatException
+ {
}
}
1.30 +207 -78 jakarta-tomcat/src/share/org/apache/tomcat/core/Container.java
Index: Container.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Container.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- Container.java 2000/08/15 23:29:32 1.29
+++ Container.java 2000/09/17 06:47:22 1.30
@@ -121,16 +121,6 @@
// notes, as the access time is much smaller
private Hashtable attributes = new Hashtable();
- /** Per/container interceptors.
- XXX Not implemented, it's easy to wire it in ( 2-3 h).
- */
- Vector contextInterceptors=new Vector();
- Vector requestInterceptors=new Vector();
- // interceptor cache - avoid Vector enumeration
- ContextInterceptor cInterceptors[];
- RequestInterceptor rInterceptors[];
- RequestInterceptor rCachedRequestInterceptors[]={};
- ContextInterceptor rCachedContextInterceptors[]={};
/** The handler associated with this container.
*/
Handler handler;
@@ -147,10 +137,12 @@
/** Get the context manager
*/
public ContextManager getContextManager() {
- if( contextM==null ) {
+ if( contextM==null && context==null ) {
/* assert */
throw new RuntimeException( "Assert: container.contextM==null" );
}
+ if( contextM==null )
+ contextM=context.getContextManager();
return contextM;
}
@@ -296,65 +288,6 @@
this.roles=roles;
}
- // -------------------- Per-container interceptors
-
- /** Add a per/container context interceptor. It will be notified
- * of all context events happening inside this container.
- * XXX incomplete implementation
- */
- public void addContextInterceptor( ContextInterceptor ci) {
- contextInterceptors.addElement( ci );
- }
-
- /** Return the context interceptors as an array.
- * For performance reasons we use an array instead of
- * returning the vector - the interceptors will not change at
- * runtime and array access is faster and easier than vector
- * access
- */
- public ContextInterceptor[] getContextInterceptors() {
- if( cInterceptors == null ||
- cInterceptors.length != contextInterceptors.size()) {
- cInterceptors=new ContextInterceptor[contextInterceptors.size()];
- for( int i=0; i<cInterceptors.length; i++ ) {
- cInterceptors[i]=(ContextInterceptor)contextInterceptors.
- elementAt(i);
- }
- }
- return cInterceptors;
- }
-
- /** Add a per/container request interceptor. It will be called back for
- * all operations for requests that are mapped to this container.
- * Note that all global interceptors will be called first.
- * XXX incomplete implementation.
- */
- public void addRequestInterceptor( RequestInterceptor ri) {
- requestInterceptors.addElement( ri );
- if( ri instanceof ContextInterceptor )
- addContextInterceptor( (ContextInterceptor)ri );
- }
-
- /** Return the context interceptors as an array.
- For performance reasons we use an array instead of
- returning the vector - the interceptors will not change at
- runtime and array access is faster and easier than vector
- access
- */
- public RequestInterceptor[] getRequestInterceptors() {
- if( rInterceptors == null ||
- rInterceptors.length != requestInterceptors.size())
- {
- rInterceptors=new RequestInterceptor[requestInterceptors.size()];
- for( int i=0; i<rInterceptors.length; i++ ) {
- rInterceptors[i]=(RequestInterceptor)requestInterceptors.
- elementAt(i);
- }
- }
- return rInterceptors;
- }
-
-
/** Per container attributes. Not used - can be removed
* ( it's here for analogy with the other components )
*/
@@ -420,20 +353,216 @@
return notes[pos];
}
- public RequestInterceptor[] getCachedRequestInterceptors() {
- return rCachedRequestInterceptors;
+ // -------------------- Interceptors --------------------
+ public static final int MAX_HOOKS=20;
+ public static final String PREDEFINED_I[]= {
+ "requestMap", "contextMap", "authenticate",
+ "authorize", "preService", "beforeBody",
+ "newSessionRequest", "beforeCommit",
+ "afterBody", "postService",
+ // special case - all interceptors will be added to the "context"
+ // chain. We plan to use a simpler Event/Listener model for
+ // all context hooks, since they don't have any performance requirement
+ "engineInit" };
+
+ // local interceptors - all interceptors added to this
+ // container
+ Vector interceptors[]=new Vector[ MAX_HOOKS ];
+
+ // Merged interceptors - local and global ( upper-level ) interceptors
+ BaseInterceptor hooks[][]=new BaseInterceptor[MAX_HOOKS][];
+
+ // used internally
+ Vector getLocalInterceptors(int hookId) {
+ if( interceptors[hookId]==null )
+ interceptors[hookId]=new Vector();
+ return interceptors[hookId];
+ }
+
+ /** Add the interceptor to all the hook chains it's interested
+ in
+ */
+ public void addInterceptor( BaseInterceptor bi ) {
+ for( int i=0; i< PREDEFINED_I.length; i++ ) {
+ if( bi.hasHook( PREDEFINED_I[i] )) {
+ if( interceptors[i]==null )
+ interceptors[i]=new Vector();
+ interceptors[i].addElement( bi );
+ }
+ }
}
- public void setCachedRequestInterceptors(RequestInterceptor[] newRCachedInterceptors) {
- rCachedRequestInterceptors = newRCachedInterceptors;
+ // make sure we reset the cache.
+ // dynamic addition of interceptors is not implemented,
+ // but this is a start
+ public void resetInterceptorCache( int id ) {
+ hooks[id]=null;
}
- public ContextInterceptor[] getCachedContextInterceptors() {
- return rCachedContextInterceptors;
+
+ public static int getHookId( String hookName ) {
+ for( int i=0; i< PREDEFINED_I.length; i++ ) {
+ if( PREDEFINED_I[i].equals(hookName)){
+ return i;
+ }
+ }
+ // get all interceptors for unknown hook names
+ return PREDEFINED_I.length-1;
}
+
+ public BaseInterceptor[] getInterceptors( int type ) {
+ if( hooks[type] != null ) {
+ return hooks[type];
+ }
+ Container globalIntContainer=getContextManager().getContainer();
+ Vector globals=globalIntContainer.getLocalInterceptors( type );
+ Vector locals=this.getLocalInterceptors( type );
+
+ int gsize=globals.size();
+ int lsize=locals.size();
+ hooks[type]=new BaseInterceptor[gsize+lsize];
+
+ for ( int i = 0 ; i < gsize ; i++ ){
+ hooks[type][i]=(BaseInterceptor)globals.elementAt(i);
+ }
+ for ( int i = 0 ; i < lsize ; i++ ){
+ hooks[type][gsize+i]=(BaseInterceptor)locals.elementAt(i);
+ }
+
+ return hooks[type];
+ }
+
+
+
+
+
+ // -------------------- Old code handling interceptors
+ // DEPRECATED ( after the new code is tested )
+
+ /** Per/container interceptors.
+ */
+ Vector contextInterceptors=new Vector();
+ Vector requestInterceptors=new Vector();
+
+ // interceptor cache - avoid Vector enumeration
+ ContextInterceptor cInterceptors[];
+ RequestInterceptor rInterceptors[];
+ RequestInterceptor rCachedRequestInterceptors[]={};
+ ContextInterceptor rCachedContextInterceptors[]={};
- public void setCachedContextInterceptors(ContextInterceptor[] newRCachedInterceptors) {
- rCachedContextInterceptors = newRCachedInterceptors;
+ /** Add a per/container context interceptor. It will be notified
+ * of all context events happening inside this container.
+ * XXX incomplete implementation
+ */
+ public void addContextInterceptor( ContextInterceptor ci) {
+ contextInterceptors.addElement( ci );
+ addInterceptor( (BaseInterceptor) ci );
}
+ /** Add a per/container request interceptor. It will be called back for
+ * all operations for requests that are mapped to this container.
+ * Note that all global interceptors will be called first.
+ * XXX incomplete implementation.
+ */
+ public void addRequestInterceptor( RequestInterceptor ri) {
+ requestInterceptors.addElement( ri );
+ addInterceptor( (BaseInterceptor) ri );
+ if( ri instanceof ContextInterceptor )
+ addContextInterceptor( (ContextInterceptor)ri );
+ }
+ // -------------------- Getting the active interceptors
+
+ /** Return the context interceptors as an array.
+ * For performance reasons we use an array instead of
+ * returning the vector - the interceptors will not change at
+ * runtime and array access is faster and easier than vector
+ * access
+ */
+ public ContextInterceptor[] getContextInterceptors() {
+ if( cInterceptors == null ||
+ cInterceptors.length != contextInterceptors.size()) {
+ cInterceptors=new ContextInterceptor[contextInterceptors.size()];
+ for( int i=0; i<cInterceptors.length; i++ ) {
+ cInterceptors[i]=(ContextInterceptor)contextInterceptors.
+ elementAt(i);
+ }
+ }
+ return cInterceptors;
+ }
+
+ /** Return the context interceptors as an array.
+ For performance reasons we use an array instead of
+ returning the vector - the interceptors will not change at
+ runtime and array access is faster and easier than vector
+ access
+ */
+ public RequestInterceptor[] getRequestInterceptors() {
+ if( rInterceptors == null ||
+ rInterceptors.length != requestInterceptors.size())
+ {
+ rInterceptors=new RequestInterceptor[requestInterceptors.size()];
+ for( int i=0; i<rInterceptors.length; i++ ) {
+ rInterceptors[i]=(RequestInterceptor)requestInterceptors.
+ elementAt(i);
+ }
+ }
+ return rInterceptors;
+ }
+
+ /** Return all interceptors for this container ( local and
+ global )
+ */
+ public RequestInterceptor[] getCachedRequestInterceptors()
+ {
+ RequestInterceptor[] ari=rCachedRequestInterceptors;
+
+ if (ari.length == 0){
+ RequestInterceptor[] cri=this.getRequestInterceptors();
+ RequestInterceptor[] gri=getContextManager()
+ .getRequestInterceptors();
+ if (cri!=null && cri.length > 0) {
+ int al=cri.length+gri.length;
+ ari=new RequestInterceptor[al];
+ int i;
+ for ( i = 0 ; i < gri.length ; i++ ){
+ ari[i]=gri[i];
+ }
+ for (int j = 0 ; j < cri.length ; j++ ){
+ ari[i+j]=cri[j];
+ }
+ } else {
+ ari=gri;
+ }
+ rCachedRequestInterceptors=ari;
+ }
+ return rCachedRequestInterceptors;
+ }
+
+ /** Return all interceptors for this container ( local and
+ global )
+ */
+ public ContextInterceptor[] getCachedContextInterceptors()
+ {
+ ContextInterceptor[] aci=rCachedContextInterceptors;
+ if (aci.length == 0){
+ ContextInterceptor[] cci=this.getContextInterceptors();
+ ContextInterceptor[] gci=getContextManager().
+ getContextInterceptors();
+ if (cci!=null && cci.length > 0) {
+ int al=cci.length+gci.length;
+ aci=new ContextInterceptor[al];
+ int i;
+ for ( i = 0 ; i < gci.length ; i++ ){
+ aci[i]=gci[i];
+ }
+ for (int j = 0 ; j < cci.length ; j++ ){
+ aci[i+j]=cci[j];
+ }
+ } else {
+ aci=gci;
+ }
+ rCachedContextInterceptors=aci;
+ }
+ return rCachedContextInterceptors;
+ }
}
1.130 +76 -204 jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java
Index: ContextManager.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v
retrieving revision 1.129
retrieving revision 1.130
diff -u -r1.129 -r1.130
--- ContextManager.java 2000/09/14 00:40:16 1.129
+++ ContextManager.java 2000/09/17 06:47:22 1.130
@@ -71,59 +71,37 @@
import java.net.*;
import java.util.*;
-//import java.security.*;
-
-/* XXX The main function of CM is to serve as an entry point into
- tomcat and manage a list of resources that are part of the servlet
- processing. ( manage == keep a list and provide centralized access ).
-
- It also have helper functions for common callbacks - but we need to
- review and change that.
-*/
-/*
- * It is possible to extend and override some of the methods ( this is not
- * "final" ), but this is an extreme case and shouldn't be used - if you want
- * to extend the server you should use interceptors.
- * Another extreme case is having more than one ContextManager instances.
- * Each will corespond to a separate servlet engine/container that will work
- * independent of each other in the same VM ( each having possible multiple
- * virtual hosts, etc). Both uses are not forbiden, but shouldn't be used
- * unless there is real need for that - and if that happen we should
- * add interfaces to express the use cases.
- */
-
-
/**
* ContextManager is the entry point and "controler" of the servlet execution.
- * It maintains a list of WebApplications and a list of global event interceptors
- * that are set up to handle the actual execution.
+ * It maintains a list of WebApplications and a list of global event
+ * interceptors that are set up to handle the actual execution.
*
- * The ContextManager is a helper that will direct the request processing flow
+ * The ContextManager will direct the request processing flow
* from its arrival from the server/protocl adapter ( in service() ).
- * It is also responsible for controlling the request processing steps, from
- * request parsing and mapping, auth, autorization, pre/post service, actual
- * invocation and logging.
+ * It will do that by calling a number of hooks implemented by Interceptors.
*
- * It will also store properties that are global to the servlet container -
- * like root directory, install dir, work dir.
+ * Hooks are provided for request parsing and mapping, auth, autorization,
+ * pre/post service, actual invocation and logging.
*
+ * ContextManager will also store properties that are global to the servlet
+ * container - like root directory, install dir, work dir.
*
+ * The extension mechanism for tomcat is the Interceptor.
+ * This class is final - if you need to change certain functionality
+ * you should add a new hook.
+ *
+ * ContextManager is not a singleton - it represent a servlet container
+ * instance ( with all associated ports and configurations ).
+ * One application may try to embed multiple ( distinct ) servlet containers -
+ * this feature hasn't been tested or used
+ *
* @author James Duncan Davidson [duncan@eng.sun.com]
* @author James Todd [gonzo@eng.sun.com]
* @author Harish Prabandham
* @author costin@eng.sun.com
* @author Hans Bergsten [hans@gefionsoftware.com]
*/
-public class ContextManager implements LogAware{
- /**
- * The default security permissions to use
- */
- private Object permissions;
-
- /** Adapters for the incoming protocol
- */
- Vector connectors=new Vector();
-
+public final class ContextManager implements LogAware{
/** Contexts managed by this server
*/
private Vector contextsV=new Vector();
@@ -146,6 +124,11 @@
*/
String installDir;
+ /** Property used to set the random number generator
+ */
+ public static final String RANDOM_CLASS_PROPERTY=
+ "tomcat.sessionid.randomclass";
+
/** Default work dir, relative to home
*/
public static final String DEFAULT_WORK_DIR="work";
@@ -165,6 +148,7 @@
public ContextManager() {
defaultContainer=new Container();
defaultContainer.setContext( null );
+ defaultContainer.setContextManager( this );
defaultContainer.setPath( null ); // default container
}
@@ -191,16 +175,6 @@
* just throw error instead of guessing wrong.
*/
public String getHome() {
- if( debug > 20 ) {
- // we want to know all places that need this property
- // and find how it's computed - for embeding tc.
- log( "getHome " + home + " " + installDir + " " +
- System.getProperty("tomcat.home") + " " +
- FileUtil.getCanonicalPath( "." ),
- new Throwable("trace")
- );
- }
-
if(home!=null) return home;
// If none defined, assume tomcat.home is used as base.
@@ -223,14 +197,6 @@
* evaluate it relative to the current working directory.
*/
public String getInstallDir() {
- if( debug > 20 ) {
- // we want to know all places that need this property
- // and find how it's computed - for embeding tc.
- log( "getInstallDir " + installDir + " " +
- System.getProperty("tomcat.home"),
- new Throwable("trace"));
- }
-
if(installDir!= null) return installDir;
installDir=System.getProperty("tomcat.home");
@@ -255,14 +221,7 @@
*/
public void setWorkDir( String wd ) {
if(debug>0) log("set work dir " + wd);
- // make it absolute
- File f=new File( wd );
- if( ! f.isAbsolute() ) {
- File wdF=getAbsolute( f );
- wd= wdF.getAbsolutePath();
- }
-
- this.workDir=wd;
+ this.workDir=FileUtil.getCanonicalPath( wd );
}
/**
@@ -274,20 +233,6 @@
return workDir;
}
- /**
- * Get the default Security Permissions for this server
- */
- public Object getPermissions() {
- return permissions;
- }
-
- /**
- * Add a Permission to the default Permissions
- */
- public void setPermissions(Object permissions) {
- this.permissions = permissions;
- }
-
/** Parent loader is the "base" class loader of the
* application that starts tomcat, and includes no
* tomcat classes. All servlet loaders will have it as
@@ -314,12 +259,13 @@
public void setServerClassPath( URL urls[] ) {
serverClassPath=urls;
}
-
- /** Get the name of the class to be used for generating random numbers by the
- * session id generator. By default this is <code>java.security.SecureRandom</code>.
+
+ /** Get the name of the class to be used for generating random numbers by
+ * the session id generator. By default this is
+ * <code>java.security.SecureRandom</code>.
**/
public String getRandomClass() {
- String randomClass = System.getProperty("tomcat.sessionid.randomclass");
+ String randomClass = System.getProperty(RANDOM_CLASS_PROPERTY);
return randomClass == null ? "java.security.SecureRandom" : randomClass;
}
@@ -327,24 +273,28 @@
* session id generator.
*/
public void setRandomClass(String randomClass) {
- System.setProperty("tomcat.sessionid.randomclass", randomClass);
+ System.setProperty(RANDOM_CLASS_PROPERTY, randomClass);
}
// -------------------- Support functions --------------------
- /** Init() is called after the context manager is set up
- * and configured. It will init all internal components
- * to be ready for start.
+
+ /**
+ * Init() is called after the context manager is set up
+ * and configured ( all setFoo methods are called, all initial
+ * interceptors are added and their setters are called ).
*
- * There is a difference between Context and Adapters - the
- * adapter has start/stop, the Context has init/shutdown(destroy
- * may be a better name ? ). ( Initializing is different from starting.)
+ * CM will call the following hooks:
+ * - Interceptor.engineInit()
+ *
+ * It will tehn call initContext() for all the contexts (
+ * including those added by interceptors )
*/
public void init() throws TomcatException {
if(debug>0 ) log( "Tomcat classpath = " +
System.getProperty( "java.class.path" ));
- setAccount( ACC_INIT_START, System.currentTimeMillis());
+ cntr.touchCounter( ACC_INIT_START );
ContextInterceptor cI[]=getContextInterceptors();
for( int i=0; i< cI.length; i++ ) {
@@ -352,7 +302,6 @@
}
// init contexts
- // XXX init must be called whith no context inside !!!
Enumeration enum = getContexts();
while (enum.hasMoreElements()) {
Context context = (Context)enum.nextElement();
@@ -361,15 +310,15 @@
} catch (TomcatException ex ) {
if( context!=null ) {
log( "ERROR initializing " + context.toString(), ex );
- // log will print root cause too if it's there
removeContext( context );
}
}
}
- setAccount( ACC_INIT_END, System.currentTimeMillis() );
+ cntr.touchCounter( ACC_INIT_END);
}
- /** Will shutdown all contexts
+ /** Remove all contexts.
+ * Call Intereptor.engineShutdown hooks.
*/
public void shutdown() throws TomcatException {
Enumeration enum = getContexts();
@@ -391,7 +340,7 @@
* <p>This method must be called
* before any requests are handled by this context. It will be called
* after the context was added, typically when the engine starts
- * or after the admin added a new context.
+ * or after the admin adds a new context.
*/
public void initContext( Context ctx ) throws TomcatException {
ContextInterceptor cI[]=getContextInterceptors(ctx);
@@ -428,24 +377,16 @@
/** Will start the connectors and begin serving requests.
* It must be called after init.
+ * XXX Do nothing ?? Tomcat is started up by calling the init
+ * hooks, there is no need for special code here - in the worst
+ * case we should add a new hook
*/
- public void start() throws Exception {// XXX TomcatException {
- // XXX we may need a special callback to disable/enable the
- // server from accepting connections ( to allow for startup ).
- // Enumeration connE=getConnectors();
- // while( connE.hasMoreElements() ) {
- // ((ServerConnector)connE.nextElement()).start();
- // }
+ public void start() throws Exception {
}
/** Will stop all connectors
*/
- public void stop() throws Exception {// XXX TomcatException {
- // if(debug>0) log("Stopping context manager ");
- // Enumeration connE=getConnectors();
- // while( connE.hasMoreElements() ) {
- // ((ServerConnector)connE.nextElement()).stop();
- // }
+ public void stop() throws Exception {
shutdown();
}
@@ -539,25 +480,13 @@
cI[i].removeContainer( container);
}
}
-
- // -------------------- Connectors and Interceptors --------------------
-
- /**
- * Add the specified server connector to the those attached to this server.
- *
- * @param con The new server connector
- */
- public synchronized void addServerConnector( ContextInterceptor con ) {
- if(debug>0) log("Add connector javaClass=\"" +
- con.getClass().getName() + "\"");
- // con.setServer( this );
- connectors.addElement( con );
- }
-
- public Enumeration getConnectors() {
- return connectors.elements();
- }
+ // -------------------- Interceptors --------------------
+ // The interceptors are handled per/container ( thanks to Nacho
+ // for this contribution ). We just delegate to the right
+ // container ( in future we should remove this, and use the
+ // right objects )
+
public void addRequestInterceptor( RequestInterceptor ri ) {
defaultContainer.addRequestInterceptor(ri);
}
@@ -570,10 +499,9 @@
For performance reasons we use arrays and cache the result inside
containers.
- XXX Todo: container-level interceptors are not supported.
+ XXX Todo:
Dynamic add of interceptors is not supported.
*/
-
public RequestInterceptor[] getRequestInterceptors( Request req ) {
Context ctx=req.getContext();
// if Bad request (ctx == null) only global interceptors are called
@@ -581,34 +509,10 @@
return getRequestInterceptors();
Container ct=ctx.getContainer();
RequestInterceptor[] ari=ct.getCachedRequestInterceptors();
- if (ari.length == 0){
- RequestInterceptor[] cri=ct.getRequestInterceptors();
- RequestInterceptor[] gri=getRequestInterceptors();
- if (cri!=null && cri.length > 0) {
- int al=cri.length+gri.length;
- ari=new RequestInterceptor[al];
- int i;
- for ( i = 0 ; i < gri.length ; i++ ){
- ari[i]=gri[i];
- }
- for (int j = 0 ; j < cri.length ; j++ ){
- ari[i+j]=cri[j];
- }
- } else {
- ari=gri;
- }
- ct.setCachedRequestInterceptors(ari);
- }
return ari;
}
- /** Return the context interceptors as an array.
- For performance reasons we use an array instead of
- returning the vector - the interceptors will not change at
- runtime and array access is faster and easier than vector
- access
- */
public RequestInterceptor[] getRequestInterceptors() {
return defaultContainer.getRequestInterceptors();
}
@@ -617,38 +521,12 @@
defaultContainer.addContextInterceptor(ci);
}
-
- /** Return the context interceptors as an array.
- For performance reasons we use an array instead of
- returning the vector - the interceptors will not change at
- runtime and array access is faster and easier than vector
- access
- */
public ContextInterceptor[] getContextInterceptors() {
return defaultContainer.getContextInterceptors();
}
public ContextInterceptor[] getContextInterceptors(Container ct) {
ContextInterceptor[] aci=ct.getCachedContextInterceptors();
- if (aci.length == 0){
- ContextInterceptor[] cci=ct.getContextInterceptors();
- ContextInterceptor[] gci=getContextInterceptors();
- if (cci!=null && cci.length > 0) {
- int al=cci.length+gci.length;
- aci=new ContextInterceptor[al];
- int i;
- for ( i = 0 ; i < gci.length ; i++ ){
- aci[i]=gci[i];
- }
- for (int j = 0 ; j < cci.length ; j++ ){
- aci[i+j]=cci[j];
- }
- } else {
- aci=gci;
- }
- ct.setCachedContextInterceptors(aci);
- }
-
return aci;
}
@@ -741,27 +619,33 @@
}
}
+ static int contextMap_ID=Container.getHookId( "contextMap");
+ static int requestMap_ID=Container.getHookId( "requestMap");
+
+
/** Will find the Handler for a servlet, assuming we already have
* the Context. This is also used by Dispatcher and getResource -
* where the Context is already known.
*/
public int processRequest( Request req ) {
- if(debug>9) log("ProcessRequest: "+req.toString());
+ if(debug>9) log("Before processRequest(): "+req.toString());
+
int status=0;
- RequestInterceptor ri[]=getRequestInterceptors();
+ BaseInterceptor ri[];
+ ri=defaultContainer.getInterceptors(contextMap_ID);
+
for( int i=0; i< ri.length; i++ ) {
- status=((RequestInterceptor)ri[i]).
- contextMap( req );
+ status=ri[i].contextMap( req );
if( status!=0 ) return status;
}
+ ri=defaultContainer.getInterceptors( requestMap_ID);
for( int i=0; i< ri.length; i++ ) {
- status=((RequestInterceptor)ri[i]).
- requestMap( req );
+ status=ri[i].requestMap( req );
if( status!=0 ) return status;
}
- if(debug>9) log("After processing: "+req.toString());
+ if(debug>9) log("After processRequest(): "+req.toString());
return 0;
}
@@ -933,16 +817,9 @@
urlPath = urlPath.substring(0, i);
}
- /** Creates an "internal" request
- */
Request lr = new Request();
lr.setRequestURI( urlPath );
lr.setQueryString( queryString );
- // lr.processQueryString();
-
- // lr.setContext( ctx );
-
- // XXX set query string too
return lr;
}
@@ -966,7 +843,7 @@
// error
// XXX this log was intended to debug the status code generation.
// it can be removed for all cases.
- if( code != 302 && code != 401 ) // tuneme
+ if( code != 302 && code != 401 && code!=400 ) // tuneme
ctx.log( "Status code:" + code + " request:" + req + " msg:" +
req.getAttribute("javax.servlet.error.message"));
@@ -1272,21 +1149,16 @@
// -------------------- Accounting --------------------
// XXX Can be implemented as note !
-
public static final int ACC_INIT_START=0;
public static final int ACC_INIT_END=0;
-
public static final int ACCOUNTS=7;
- long accTable[]=new long[ACCOUNTS];
- public void setAccount( int pos, long value ) {
- accTable[pos]=value;
- }
+ Counters cntr=new Counters(ACCOUNTS);
- public long getAccount( int pos ) {
- return accTable[pos];
+ public Counters getCounters() {
+ return cntr;
}
-
+
// -------------------- DEPRECATED --------------------
// XXX host and port are used only to construct a unique
// work-dir for contexts, using them and the path
1.58 +12 -7 jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java
Index: Request.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- Request.java 2000/08/29 03:44:20 1.57
+++ Request.java 2000/09/17 06:47:23 1.58
@@ -477,10 +477,9 @@
if( ! create ) return null;
- // context.log("Request: created new session!");
contextM.doNewSessionRequest( this, response );
+
if ( serverSession == null ) {
- // context.log("Request: no session created!");
return null;
}
@@ -797,12 +796,18 @@
}
- // XXX I hate this - but the only way to remove this method from the
- // inteface is to implement it on top of doRead(b[]).
- // Don't use this method if you can ( it is bad for performance !!)
- // you need to override this method if you want non-empty InputStream
+ // This method must be removed and replaced with a real buffer !!!
public int doRead() throws IOException {
- return -1;
+ byte []b = new byte[1];
+ int rc = doRead(b, 0, 1);
+
+ if(rc <= 0) {
+ return -1;
+ }
+
+ return b[0];
+ // ??
+ //return ((int)b[0]) & 0x000000FF;
}
// -------------------- "cooked" info --------------------
1.20 +20 -20 jakarta-tomcat/src/share/org/apache/tomcat/startup/EmbededTomcat.java
Index: EmbededTomcat.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/startup/EmbededTomcat.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- EmbededTomcat.java 2000/08/27 21:03:33 1.19
+++ EmbededTomcat.java 2000/09/17 06:47:24 1.20
@@ -5,8 +5,9 @@
import org.apache.tomcat.core.*;
import org.apache.tomcat.request.*;
-import org.apache.tomcat.service.*;
-import org.apache.tomcat.service.http.*;
+import org.apache.tomcat.modules.server.*;
+//import org.apache.tomcat.service.*;
+//import org.apache.tomcat.service.http.*;
import org.apache.tomcat.session.StandardSessionInterceptor;
import org.apache.tomcat.context.*;
import org.apache.tomcat.logging.*;
@@ -103,16 +104,16 @@
if(debug>0) log( "addConnector " + port + " " + addr +
" " + hostname );
- PoolTcpConnector sc=new PoolTcpConnector();
+ HttpInterceptor sc=new HttpInterceptor();
sc.setServer( contextM );
sc.setDebug( debug );
- sc.setAttribute( "vhost_port" , new Integer( port ) );
- if( addr != null ) sc.setAttribute( "vhost_address", addr );
- if( hostname != null ) sc.setAttribute( "vhost_name", hostname );
+ sc.setPort( port ) ;
+ if( addr != null ) sc.setAddress( addr );
+ if( hostname != null ) sc.setHostName( hostname );
- sc.setTcpConnectionHandler( new HttpConnectionHandler());
+ // sc.setTcpConnectionHandler( new HttpConnectionHandler());
- contextM.addServerConnector( sc );
+ contextM.addRequestInterceptor( sc );
}
/** Add a secure web service.
@@ -122,22 +123,21 @@
{
if(debug>0) log( "addSecureConnector " + port + " " + addr + " " +
hostname );
-
- PoolTcpConnector sc=new PoolTcpConnector();
+
+ HttpInterceptor sc=new HttpInterceptor();
sc.setServer( contextM );
- sc.setAttribute( "vhost_port" , new Integer( port ) );
- if( addr != null ) sc.setAttribute( "vhost_address", addr );
- if( hostname != null ) sc.setAttribute( "vhost_name", hostname );
-
- sc.setAttribute( "socketFactory",
- "org.apache.tomcat.net.SSLSocketFactory");
+ sc.setPort( port ) ;
+ if( addr != null ) sc.setAddress( addr );
+ if( hostname != null ) sc.setHostName( hostname );
+
+ sc.setSocketFactory("org.apache.tomcat.net.SSLSocketFactory");
// log("XXX " + keyFile + " " + keyPass);
- HttpConnectionHandler hc=new HttpConnectionHandler();
- hc.setSecure(true);
- sc.setTcpConnectionHandler( hc );
+ // HttpConnectionHandler hc=new HttpConnectionHandler();
+ sc.setSecure(true);
+ // sc.setTcpConnectionHandler( hc );
// XXX add the secure socket
- contextM.addServerConnector( sc );
+ contextM.addRequestInterceptor( sc );
}
// -------------------- Context add/remove --------------------
1.16 +11 -14 jakarta-tomcat/src/share/org/apache/tomcat/task/ApacheConfig.java
Index: ApacheConfig.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/task/ApacheConfig.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- ApacheConfig.java 2000/09/09 23:15:34 1.15
+++ ApacheConfig.java 2000/09/17 06:47:24 1.16
@@ -133,20 +133,17 @@
pw.println("ApJServLogLevel notice");
pw.println();
- // Find Ajp12 connector
- int portInt=8007;
- Enumeration enum=cm.getConnectors();
- while( enum.hasMoreElements() ) {
- Object con=enum.nextElement();
- if( con instanceof PoolTcpConnector ) {
- PoolTcpConnector tcpCon=(PoolTcpConnector) con;
- if( tcpCon.getTcpConnectionHandler()
- instanceof Ajp12ConnectionHandler ) {
- portInt=tcpCon.getPort();
- }
- }
+ // Find Ajp12 connector
+ int portInt=8007;
+ ContextInterceptor ci[]=cm.getContextInterceptors();
+ for( int i=0; i<ci.length; i++ ) {
+ Object con=ci[i];
+ if( con instanceof Ajp12ConnectionHandler ) {
+ PoolTcpConnector tcpCon=(PoolTcpConnector) con;
+ portInt=tcpCon.getPort();
}
- pw.println("ApJServDefaultPort " + portInt);
+ }
+ pw.println("ApJServDefaultPort " + portInt);
pw.println();
pw.println("AddType text/jsp .jsp");
@@ -200,7 +197,7 @@
// Set up contexts
// XXX deal with Virtual host configuration !!!!
- enum = cm.getContexts();
+ Enumeration enum = cm.getContexts();
while (enum.hasMoreElements()) {
Context context = (Context)enum.nextElement();
String path = context.getPath();
1.7 +6 -9 jakarta-tomcat/src/share/org/apache/tomcat/task/StopTomcat.java
Index: StopTomcat.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/task/StopTomcat.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- StopTomcat.java 2000/08/18 03:42:16 1.6
+++ StopTomcat.java 2000/09/17 06:47:24 1.7
@@ -172,16 +172,13 @@
// Find Ajp12 connector
int portInt=8007;
InetAddress address=null;
- Enumeration enum=cm.getConnectors();
- while( enum.hasMoreElements() ) {
- Object con=enum.nextElement();
- if( con instanceof PoolTcpConnector ) {
+ ContextInterceptor ci[]=cm.getContextInterceptors();
+ for( int i=0; i<ci.length; i++ ) {
+ Object con=ci[i];
+ if( con instanceof Ajp12ConnectionHandler ) {
PoolTcpConnector tcpCon=(PoolTcpConnector) con;
- if( tcpCon.getTcpConnectionHandler()
- instanceof Ajp12ConnectionHandler ) {
- portInt=tcpCon.getPort();
- address=tcpCon.getAddress();
- }
+ portInt=tcpCon.getPort();
+ address=tcpCon.getAddress();
}
}