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.modules.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import org.apache.tomcat.core.BaseInterceptor;
import org.apache.tomcat.core.Context;
import org.apache.tomcat.core.ContextManager;
import org.apache.tomcat.core.TomcatException;
import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.hooks.Hooks;
import org.apache.tomcat.util.io.FileUtil;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.util.xml.SaxContext;
import org.apache.tomcat.util.xml.XmlAction;
import org.apache.tomcat.util.xml.XmlMapper;
import org.xml.sax.AttributeList;

/**
 * This is a configuration module that will read a server.xml file
 * and dynamically configure the server by adding modules and interceptors.
 *
 * Tomcat can be configured ( and auto-configured ) in many ways, and
 * a configuration module will have access to all server events, and will
 * be able to update it's state, etc.
 *
 * @author Costin Manolache
 */
public class ServerXmlReader extends BaseInterceptor {
    private static StringManager sm =
	StringManager.getManager("org.apache.tomcat.resources");

    
    public ServerXmlReader() {
    }

    // -------------------- Properties --------------------
    String configFile=null;
    String moduleFile=null;
    static final String DEFAULT_CONFIG="conf/server.xml";
    static final String DEFAULT_MODULES="conf/modules.xml";
    boolean useCachedModules=true;// can roll back
    
    public void setConfig( String s ) {
	configFile=s;
    }

    public void setHome( String h ) {
	System.getProperties().put("tomcat.home", h);
    }

    public void setModuleConfig( String f ) {
	moduleFile=f;
    }
    
    // -------------------- Hooks --------------------

    /** When this module is added, it'll automatically load
     *  a configuration file and add all global modules.
     */
    public void addInterceptor(ContextManager cm, Context ctx,
			       BaseInterceptor module)
	throws TomcatException
    {
	//	checkHooks(cm, ctx, module);
	if( this != module ) return;
	setupHookFinder();
	XmlMapper xh=new XmlMapper();
	xh.setDebug( debug );
	xh.addRule( "ContextManager", xh.setProperties() );
	setPropertiesRules( cm, xh );
	setTagRules( xh );
	addDefaultTags(cm, xh);
	//addTagRules( cm, xh );
	setBackward( xh );

	// load the config file(s)
	File f  = null;
	if (configFile == null) {
	    f=new File( cm.getHome(), DEFAULT_CONFIG);
	} else {
	    // All other paths are relative to TOMCAT_HOME, except this one.
	    // The user will either type an absolute path or a path relative
	    // to his working dir ( relative to TOMCAT_HOME is counterintuitive)
	    f=new File(configFile);
	}

	if( f.exists() ){
	    f=new File( f.getAbsolutePath());
            cm.setNote( "configFile", f.getAbsolutePath());
	    loadConfigFile(xh,f,cm);
	    String s=f.getAbsolutePath();
	    if( s.startsWith( cm.getHome()))
		s="$TOMCAT_HOME" + s.substring( cm.getHome().length());
	    log( "Config=" + s);
            // load server-*.xml
            Vector v = getUserConfigFiles(f);
            for (Enumeration e = v.elements();
                 e.hasMoreElements() ; ) {
                f = (File)e.nextElement();
                loadConfigFile(xh,f,cm);
		cm.log(sm.getString("tomcat.loading") + " " + f);
            }
        }
        else
            log("Warning: Server configuration file " + f + " was not found!");
    }

    // -------------------- Xml reading details --------------------

    public static void loadConfigFile(XmlMapper xh, File f, Object cm)
	throws TomcatException
    {
	try {
	    xh.readXml(f,cm);
	} catch( Exception ex ) {
	    ex.printStackTrace();
	    //	    cm.log( sm.getString("tomcat.fatalconfigerror"), ex );
	    throw new TomcatException(ex);
	}
    }

    static class CMPropertySource
	implements IntrospectionUtils.PropertySource
    {
	ContextManager cm;
	
	CMPropertySource( ContextManager cm ) {
	    this.cm=cm;
	}
	
	public String getProperty( String key ) {
	    if( "tomcat.home".equals( key ) ) {
		return cm.getHome();
	    }
            if( "tomcat.install".equals( key ) ) {
                return cm.getInstallDir();
	    }
	    // XXX add other "predefined" properties
	    String s=cm.getProperty( key );
	    if( s==null )
		s=System.getProperty(key);
	    return s;
	}
    }

    public static void setPropertiesRules( ContextManager cm, XmlMapper xh )
	throws TomcatException
    {
	CMPropertySource propS=new CMPropertySource( cm );
	xh.setPropertySource( propS );

        // add the "correct" first-letter-capitalized version
        xh.addRule( "ContextManager/Property", new XmlAction() {
                public void start(SaxContext ctx ) throws Exception {
                    AttributeList attributes = ctx.getCurrentAttributes();
                    String name=attributes.getValue("name");
                    String value=attributes.getValue("value");
                    if( name==null || value==null ) return;
                    XmlMapper xm=ctx.getMapper();

                    ContextManager cm1=(ContextManager)ctx.currentObject();
                    // replace ${foo} in value
                    value=xm.replaceProperties( value );
                    if( cm1.getDebug() > 0 )
                        cm1.log("Setting " + name + "=" + value);
                    cm1.setProperty( name, value );
                }
            });

        // for backward compatibility, keep old version
	xh.addRule( "ContextManager/property", new XmlAction() {
		public void start(SaxContext ctx ) throws Exception {
		    AttributeList attributes = ctx.getCurrentAttributes();
		    String name=attributes.getValue("name");
		    String value=attributes.getValue("value");
		    if( name==null || value==null ) return;
		    XmlMapper xm=ctx.getMapper();
		    
		    ContextManager cm1=(ContextManager)ctx.currentObject();
		    // replace ${foo} in value
		    value=xm.replaceProperties( value );
		    if( cm1.getDebug() > 0 )
			cm1.log("Setting " + name + "=" + value);
		    cm1.setProperty( name, value );
		}
	    });
    }

    public static void addTagRules( ContextManager cm, XmlMapper xh )
	throws TomcatException
    {
	Hashtable modules=(Hashtable)cm.getNote("modules");
	if( modules==null) return;
	Enumeration keys=modules.keys();
	while( keys.hasMoreElements() ) {
	    String tag=(String)keys.nextElement();
	    String classN=(String)modules.get( tag );

	    addTagRule( xh, tag, classN );
	}
    }

    public static void addTagRule( XmlMapper xh, String tag, String classN ) {
	xh.addRule( tag ,
		    xh.objectCreate( classN, null ));
	xh.addRule( tag ,
		    xh.setProperties());
	xh.addRule( tag,
		    xh.addChild( "addInterceptor",
				 "org.apache.tomcat.core.BaseInterceptor"));
    }

    public static void setTagRules( XmlMapper xh ) {
	xh.addRule( "module",  new XmlAction() {
		public void start(SaxContext ctx ) throws Exception {
		    Object elem=ctx.currentObject();
		    AttributeList attributes = ctx.getCurrentAttributes();
		    String name=attributes.getValue("name");
		    String classN=attributes.getValue("javaClass");
		    if( name==null || classN==null ) return;
		    ContextManager cm=(ContextManager)ctx.currentObject();
		    Hashtable modules=(Hashtable)cm.getNote("modules");
		    modules.put( name, classN );
		    addTagRule( ctx.getMapper(), name, classN );
		    if( ctx.getDebug() > 0 ) ctx.log("Adding " + name + " " + classN );
		}
	    });
    }

    // read modules.xml, if any, and load taskdefs
    public void addDefaultTags( ContextManager cm, XmlMapper xh)
	throws TomcatException
    {
	if( cm.getNote( "modules" ) != null )
	    return;
	if( moduleFile==null ) moduleFile=DEFAULT_MODULES;
        File f=new File(moduleFile);
        if ( !f.isAbsolute())
	    f=new File( cm.getHome(), moduleFile );

	if( f.exists() ) {
	    // try cached value
	    File cachedM=new File( cm.getWorkDir() );
	    if( !cachedM.isAbsolute())
		cachedM=new File( cm.getHome(), cm.getWorkDir());
	    cachedM=new File( cachedM, "modules.properties");
	    Properties modules=new Properties();
	    cm.setNote( "modules", modules );
	    if( useCachedModules &&
		cachedM.exists() &&
		cachedM.lastModified() > f.lastModified() ) {
		// XXX check the other modules-foo.xml
		loadCachedModules(cachedM, modules );
		addTagRules( cm, xh );
		return;
	    } else {
		loadConfigFile( xh, f, cm );
		// load module-*.xml
		Vector v = getUserConfigFiles(f);
		for (Enumeration e = v.elements();
		     e.hasMoreElements() ; ) {
		    f = (File)e.nextElement();
		    loadConfigFile(xh,f,cm);
		}
		saveCachedModules(cachedM, modules);
	    }
	}
        else
            log("Warning: Modules configuration file " + f + " was not found!");
    }

    void loadCachedModules( File f, Properties mods ) {
	try {
	    FileInputStream pos=new FileInputStream( f );
	    mods.load( pos );
	} catch(IOException ex ) {
	    log("Error loading modules ", ex );
	}
    }

    void saveCachedModules( File f, Properties mods ) {
	try {
	    FileOutputStream pos=new FileOutputStream( f );
	    mods.save( pos, "Auto-generated cache file");
	} catch(IOException ex ) {
	    //log("Error saving modules ", ex );
	}
    }

    void setupHookFinder() {
	Hooks.setHookFinder( new IntrospectionHookFinder() );
    }

    static class IntrospectionHookFinder implements Hooks.HookFinder {
	public boolean hasHook( Object o, String hook ) {
	    return IntrospectionUtils.hasHook( o, hook );
	}
    }
    // -------------------- File utils --------------------

    // get additional files
    public static Vector getUserConfigFiles(File master) {
	File dir = new File(master.getParent());
	String[] names = dir.list();
	//	System.out.println("getUserConfigFiles " + dir );

	String masterName=master.getAbsolutePath();

	String base=FileUtil.getBase(masterName) + "-";
	String ext=FileUtil.getExtension( masterName );
	
	Vector v = new Vector();
	if( names==null ) return v;
	for (int i=0; i
	xh.addRule( "ContextManager/Connector",
		    xh.objectCreate(null, "className"));
	xh.addRule( "ContextManager/Connector",
		    xh.setParent( "setContextManager",
				  "org.apache.tomcat.core.ContextManager") );
	xh.addRule( "ContextManager/Connector",
		    xh.addChild( "addInterceptor",
				 "org.apache.tomcat.core.BaseInterceptor"));

	xh.addRule( "ContextManager/Connector/Parameter",
		    xh.methodSetter("setProperty",2) );
	xh.addRule( "ContextManager/Connector/Parameter",
		    xh.methodParam(0, "name") );
	xh.addRule( "ContextManager/Connector/Parameter",
		    xh.methodParam(1, "value") );

	// old 
	xh.addRule("Server/Logger",
		   xh.objectCreate("org.apache.tomcat.util.log.QueueLogger"));
	xh.addRule("Server/Logger", xh.setProperties());
	xh.addRule("Server/Logger", 
		   xh.addChild("addLogger",
			       "org.apache.tomcat.util.log.Logger") );

    }


}

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 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.