alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*   
 *  Copyright 1999-2004 The Apache Sofware Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.tomcat.core;

import org.apache.tomcat.util.hooks.Hooks;
import java.util.Hashtable;
import java.util.Enumeration;

// XXX better names: Location, URLPattern,  

/**
 * A group of resources, with some common properties.
 * Container is similar with Apache "dir_conf" structue.
 *
 * Each Context has a default Container and one container for
 * each URL property ( mapping handlers and  security constraints ).
 *
 * The ContextManager has a defaultContainer containing global
 * properties.
 *
 * Each time a container is added to a Context, addContainer() hook is
 * called to notify all modules of a new URL property.
 *
 * Modules that implement contextMap/requestMap and security constraints
 * ( authenticate/authorize hooks ) will construct specialized data
 * structures. 
 * You can associate trees, hashtables or other data types with the
 * context using notes - no application/module should assume any
 * particular structure is in used, the user can choose any mapper.
 * See SimpleMapper1 for an example of such structures.
 *
 * A container will be selected by best-matching a request using the
 * alghoritms described in the servlet API. 
 */
public class Container implements Cloneable{
    /* It is not yet finalized - it is possible to use more
     * "rules" for matching ( if future APIs will define that ).
     * You can use notes or attributes to extend the model -
     * the attributes that are defined and have get/set methods
     * are the one defined in the API and with wide use.
     */

    // The "controler"
    private ContextManager contextM;

    // The webapp including this container, if any
    private Context context;

    // The type of the mapping
    public static final int UNKNOWN_MAP=0;
    public static final int PATH_MAP=1;
    public static final int PREFIX_MAP=2;
    public static final int EXTENSION_MAP=3;
    public static final int DEFAULT_MAP=4;
    private int mapType=0;


    // Common map parameters ( path prefix, ext, etc)
    private String transport;
    private String path;
    private String proto;
    private String vhosts[];

    // Container attributes - it's better to use
    // notes, as the access time is much smaller
    private Hashtable attributes = new Hashtable();

    /** The handler associated with this container.
     */
    private Handler handler;
    private String handlerName;
    
    /** Security constraints associated with this Container
     */
    private String roles[]=null;

    private String methods[]=null;

    private boolean special=false;
    
    public Container() {
	initHooks();
    }

    /** Get the context manager
     */
    public ContextManager getContextManager() {
	if( contextM==null && context==null ) {
	    /* assert */
	    throw new RuntimeException( "Assert: container.contextM==null" );
	}
	if( contextM==null )
	    contextM=context.getContextManager();
	return contextM;
    }

    public void setContextManager(ContextManager cm) {
	contextM=cm;
    }

    /** Set the context, if this container is part of a web application.
     *  Right now all container in use have a context.
     */
    public void setContext( Context ctx ) {
	this.context=ctx;
    }

    /** The parent web application, if any. 
     */
    public Context getContext() {
	return context;
    }

    public void setSpecial( boolean b ) {
	special=b;
    }

    public boolean isSpecial() {
	return special;
    }
    
    // -------------------- Mapping LHS --------------------
       
    
    /** Return the type of the mapping ( extension, prefix, default, etc)
     */
    public int getMapType() {
	if( mapType!=0) return mapType;
	// What happens with "" or null ?
	// XXX Which one is default servlet ? API doesn't say,
	// but people expect it to work.
	if( path==null ||
	    path.equals("" ) ||
	    path.equals( "/")) {
	    mapType=DEFAULT_MAP;
	} else if (path.startsWith("/") &&
	    path.endsWith("/*")) {
	    mapType=PREFIX_MAP;
	} else if (path.startsWith("*.")) {
	    mapType=EXTENSION_MAP;
	} else {
	    mapType=PATH_MAP;
	}
	return mapType;
    }

    /** The mapping string that creates this Container.
     *  Not that this is an un-parsed string, like a regexp.
     */
    public void setPath( String path ) {
	// XXX use a better name - setMapping for example
	if( path==null)
	    this.path=""; // default mapping
	else
	    this.path=path.trim();
    }

    /** Return the path
     */
    public String getPath() {
	return path;
    }

    /** Set the protocol - if it's set it will be used
     *  in mapping
     */
    public void setProtocol( String protocol ) {
	this.proto=protocol;
    }

    /** Protocol matching. With Servlet 2.2 the protocol
     * can be used only with security mappings, not with
     * handler ( servlet ) maps
    */
    public String getProtocol() {
	return proto;
    }

    /** The transport - another component of the matching.
     *  Defined only for security mappings.
     */
    public void setTransport(String transport ) {
	this.transport=transport;
    }

    /** The transport - another component of the matching.
     *  Defined only for security mappings.
     */
    public String getTransport() {
	return transport;
    }

    /** Any alias that can match a particular vhost
     */
    public String[] getVhosts() {
	return vhosts;
    }

    /** Any alias that can match a particular vhost
     */
    public void setVhosts(String vhosts[]) {
	this.vhosts=vhosts;
    }
    
    /** If not null, this container can only be accessed by users
     *  in roles.
     */
    public String []getMethods() {
	return methods;
    }

    /** If not null, this container can only be accessed by users
	in roles.
    */
    public void setMethods( String m[] ) {
	this.methods=m;
    }

    // -------------------- Mapping RHS --------------------
    
    public Handler getHandler() {
	return handler;
    }

    /** The handler ( servlet ) for this container
     */
    public void setHandler(Handler h) {
	handler=h;
    }

    public void setHandlerName(String hn) {
	handlerName=hn;
    }

    /** The handler name for this container.
     *  @return null if no handler is defined for this
     *          container ( this container defines only
     *          security or other type of properties, but
     *          not a handler )
     */
    public String getHandlerName() {
	if( handlerName != null ) 
	    return handlerName;
	if( handler != null )
	    return handler.getName();
	return null;
    }

    /** If not null, this container can only be accessed by users
     *  in roles.
     */
    public String []getRoles() {
	return roles;
    }

    /** If not null, this container can only be accessed by users
	in roles.
    */
    public void setRoles( String roles[] ) {
	this.roles=roles;
    }

    /** Per container attributes. Not used - can be removed
     *  ( it's here for analogy with the other components )
     */
    public Object getAttribute(String name) {
            return attributes.get(name);
    }

    /** Per container attributes. Not used - can be removed
     *  ( it's here for analogy with the other components )
     */
    public Enumeration getAttributeNames() {
        return attributes.keys();
    }

    /** Per container attributes. Not used - can be removed
     *  ( it's here for analogy with the other components )
     */
    public void setAttribute(String name, Object object) {
        attributes.put(name, object);
    }

    /** Per container attributes. Not used - can be removed
     *  ( it's here for analogy with the other components )
     */
    public void removeAttribute(String name) {
        attributes.remove(name);
    }

    // -------------------- Utils --------------------
    /** Print a short string describing the mapping
     */
    public String toString() {
	StringBuffer sb=new StringBuffer();
	sb.append( "Ct (" );
	sb.append(path ).append( " " );
	if( handler!= null) sb.append( handler.toString() );
	if( roles!=null) {
	    	sb.append(" Roles: ");
		for( int i=0; i< roles.length; i++ )
		    sb.append(" ").append( roles[i]);
	}
	sb.append( " )");
	return sb.toString();
    }

    public Container getClone() {
	try {
	    return (Container)this.clone();
	} catch( CloneNotSupportedException ex ) {
	    return this;
	}
    }

    // -------------------- Per-Container "notes"
    Object notes[]=new Object[ContextManager.MAX_NOTES];

    /** See ContextManager comments.
     */
    public final void setNote( int pos, Object value ) {
	notes[pos]=value;
    }

    public final Object getNote( int pos ) {
	return notes[pos];
    }

    public Object getNote( String name ) throws TomcatException {
	int id=getContextManager().getNoteId( ContextManager.CONTAINER_NOTE,
					      name );
	return getNote( id );
    }

    public void setNote( String name, Object value ) throws TomcatException {
	int id=getContextManager().getNoteId( ContextManager.CONTAINER_NOTE,
					      name );
	setNote( id, value );
    }
    


    // -------------------- Interceptors --------------------
    public static final int H_postReadRequest=0;
    public static final int H_requestMap=1;
    public static final int H_contextMap=2;
    public static final int H_authenticate=3;
    public static final int H_authorize=4;
    public static final int H_preService=5;
    public static final int H_beforeBody=6;
    public static final int H_findSession=7;
    public static final int H_sessionState=8;
    public static final int H_beforeCommit=9;
    public static final int H_afterBody=10;
    public static final int H_postService=11;
    public static final int H_postRequest=12;
    public static final int H_handleError=13;
    public static final int H_getInfo=14;
    public static final int H_setInfo=15;
    public static final int H_engineInit=16;
    public static final int H_preInitCheck=17;
    public static final int H_postInitCheck=18;
    public static final int H_copyContext=19;
    public static final int H_COUNT=20;

    private Hooks hooks=new Hooks();
    private BaseInterceptor hooksCache[][]=null;
    private BaseInterceptor allHooksCache[]=null;

    private void initHooks() {
	hooks.registerHook( "postReadRequest", H_postReadRequest );
	hooks.registerHook( "requestMap", H_requestMap );
	hooks.registerHook( "contextMap", H_contextMap );
	hooks.registerHook( "authenticate", H_authenticate );
	hooks.registerHook( "authorize", H_authorize );
	hooks.registerHook( "preService", H_preService );
	hooks.registerHook( "beforeBody", H_beforeBody );
	hooks.registerHook( "findSession", H_findSession );
	hooks.registerHook( "sessionState", H_sessionState );
	hooks.registerHook( "beforeCommit", H_beforeCommit );
	hooks.registerHook( "afterBody", H_afterBody );
	hooks.registerHook( "postService", H_postService );
	hooks.registerHook( "postRequest", H_postRequest );
	hooks.registerHook( "handleError", H_handleError );
	hooks.registerHook( "getInfo", H_getInfo );
	hooks.registerHook( "setInfo", H_setInfo );
	hooks.registerHook( "engineInit", H_engineInit );
	hooks.registerHook( "preInitCheck", H_preInitCheck );
	hooks.registerHook( "postInitCheck", H_postInitCheck );
	hooks.registerHook( "copyContext", H_copyContext );
    }

    public Hooks getHooks() {
	return hooks;
    }

    /** Add the interceptor to all the hook chains it's interested
     *	in
     */
    public void addInterceptor( BaseInterceptor bi ) {
	bi.setContext( getContext() );

	int status=bi.registerHooks( hooks, contextM, context );
	if( status!=BaseInterceptor.OK ) {
	    hooks.addModule( bi );
	}
	hooksCache=null;
	allHooksCache=null;
    }

    public void removeInterceptor( BaseInterceptor bi ) {
	hooks.removeModule( bi );
	hooksCache=null;
	allHooksCache=null;
    }
    
    public BaseInterceptor[] getInterceptors( int type )
    {
	if( hooksCache != null ) {
	    if( hooksCache[type] == null ) {
		Container gContainer = getContextManager().getContainer();
		Hooks gHooks = gContainer.getHooks();
		if( this != gContainer ) {
		    hooksCache[type] = mergeHooks(gHooks.getModules(type),
						  getHooks().getModules(type));
		} else {
		    hooksCache[type] = mergeHooks(gHooks.getModules(type), null);
		}
	    }
	    return hooksCache[type];
	}

	// load the cache with all the hooks
	Container globalIntContainer=getContextManager().getContainer();
	Hooks globals=globalIntContainer.getHooks();

	hooksCache=new BaseInterceptor[H_COUNT][];
	for( int i=0; i
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.