| 
What this is
 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
 | 
| ... this post is sponsored by my books ... | |
         
           #1 New Release!  | 
      
         
           FP Best Seller  | 
  
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.