You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-cvs@jakarta.apache.org by ce...@apache.org on 2001/01/24 00:35:03 UTC

cvs commit: jakarta-log4j/org/apache/log4j/examples/appserver AppServerCategory.java AppServerCategoryFactory.java AppServerLoggingEvent.java AppServerPatternLayout.java AppServerPatternParser.java package.html

ceki        01/01/23 15:35:03

  Added:       org/apache/log4j/examples/appserver AppServerCategory.java
                        AppServerCategoryFactory.java
                        AppServerLoggingEvent.java
                        AppServerPatternLayout.java
                        AppServerPatternParser.java package.html
  Log:
  Paul Glezen example code that accompanies the deepExtension document.
  (I will take care of the rest of the integration tomorrow,)
  
  Submitted by: Paul Glezen
  
  Revision  Changes    Path
  1.1                  jakarta-log4j/org/apache/log4j/examples/appserver/AppServerCategory.java
  
  Index: AppServerCategory.java
  ===================================================================
  package org.apache.log4j.examples.appserver;
  
  import org.apache.log4j.Priority;
  import org.apache.log4j.Category;
  import org.apache.log4j.spi.CategoryFactory;
  import org.apache.log4j.spi.LoggingEvent;
  
  /**
   *  <code>AppServerCategory</code> extends <code>Category</code>
   *  by adding four extra attributes relevant to applications
   *  run in application servers.  These attributes are
   *  <p>
   *  <ul>
   *  <li><b>host</b> - the name of the machine on which the
   *      code is running
   *  <li><b>server</b> - the name of the server process in which
   *      the code is running
   *  <li><b>component</b> - the name of the component of which
   *      the code is a part
   *  <li><b>version</b> - the version of this code
   *  </ul>
   *  <p>This <code>Category</code> subclass generates
   *  <code>AppServerLoggingEvent</code> subclasses of
   *  <code>LoggingEvent</code> which include the additional
   *  attributes.  <code>AppServerPatternLayout</code> provides
   *  the ability to format these attributes.
   *  <p>
   *  Rather than set all these attributes for each
   *  <code>AppServerCategory</code> instance, it is usually more
   *  convenient to set them on <code>AppServerCategoryFactory</code>
   *  and associate this factory statically with
   *  <code>AppServerCategory</code> (using the static
   *  <code>setFactory</code>) method.  The
   *  <code>AppServerCategory.getInstance(Object)</code> method can
   *  then be used to create <code>AppServerCategory</code>
   *  instances conveniently.
   *
   *  @author Paul Glezen
   */
  public class AppServerCategory extends Category
  {
  	/** The name of the component using this category.  */
  	protected String component;
  
  	/** The hostname on which this category resides.  */
  	protected String hostname;
  
  	/** The application server name for this category. This is 
  	    particularly meaningful in a CORBA or EBJ application
  		 server environment.  */
  	protected String server;
  
  	/** An identifier for this particular version/release. */
  	protected String version;
  
  	/** A reference to the factory to create <code>AppServerCategory</code>
  	    instances.  */
  	private static CategoryFactory factory = new AppServerCategoryFactory(null, null, null);
  
  	/**
  	 *  Construct a new AppServerCategory with the provided
  	 *  attributes.  The constructor is protected because the only
  	 *  classes invoking it should be a CategoryFactory subclass or
  	 *  a subclass of AppServerCategory.
  	 *
  	 *  @param categoryName the name of the category.
  	 *  @param hostname     the name of the physical machine on which this
  	 *                      category resides.  This may be null.
  	 *  @param server       the name of the server using this category.  This
  	 *                      may be null.
  	 *  @param component    the name of the component using this category.
  	 *                      This may be null.
  	 *  @param version      the version identifier of the component.  This may
  	 *                      may be null.
  	 */
  	protected  AppServerCategory( String categoryName,
  	                              String hostname,
                                   String server,
  	                              String component,
  										   String version )
  	{
  		super( categoryName );
  		instanceFQN = "org.apache.log4j.examples.appserver.AppServerCategory";
  		
  		this.hostname  = hostname;
  		this.server    = server;
  		this.component = component;
  		this.version   = version;
  	}
  
  	/**
  	 *  Get the component name for this category.
  	 *
  	 *  @return the category name
  	 */
  	public String getComponent()
  	{
  		String result = "";
  
  		if ( component != null )
  			result = component;
  
  		return result;
  	}
  
  	/**
  	 *  Get the hostname for this category.
  	 *
  	 *  @return a string representation of the hostname
  	 */
  	public String getHostname()
  	{
  		String result = "";
  
  		if ( hostname != null )
  			result = hostname;
  
  		return result;
  	}
  
  	/**
  	 *  Return an <code>AppServerCategory</code> instance with the
  	 *  provided name.  If such an instance exists, return it.
  	 *  Otherwise, create a new one.
  	 *
  	 *  @param name the name of the Catgory
  	 *  @return an instance of <code>AppServerCategory</code>.  The
  	 *          signature indicates <code>Category</code> to maintain
  	 *          compatibility with the base class.
  	 */
  	public static Category getInstance(String name)
  	{
  		return Category.getInstance(name, factory);
  	}
  
  	/**
  	 * Get the server name for this category.  This attribute is more
  	 * germane in application server environments such as CORBA and EJB.
  	 *
  	 * @return a string representing the server name
  	 */
  	public String getServer()
  	{
  		String result = "";
  
  		if ( server != null )
  			result = server;
  
  		return result;
  	}
  
  	/**
  	 *  Get the version name for this category.
  	 *
  	 *  @return the version of the the component for this category.
  	 */
  	public String getVersion()
  	{
  		String result = "";
  
  		if ( version != null )
  			result = version;
  
  		return result;
  	}
  
     /**
      *  This method is overridden to ensure an instance of
  	 *  <code>AppServerLoggingEvent</code> is sent to the
  	 *  appenders.
      */
     protected void forcedLog(String fqn, Priority priority, Object message, Throwable t) 
  	{
  		String s;
  		LoggingEvent event;
  		if(message instanceof String) 
  			s = (String) message;
  		else
  			s = myContext.getRendererMap().findAndRender(message);
  
  		event = new AppServerLoggingEvent(fqn, this, priority, s, t);
  		callAppenders( event );
  	}
  
  	/**
  	 *  Log a message based on a key used to index into a message
  	 *  catalog stored in a <code>java.util.ResourceBundle</code>.
  	 *  This version of l7dlog assumes no substitutable parameters.
  	 *  This class overrides its corresponding method in
  	 *  <code>Category</code> so that an <code>AppServerLoggingEvent</code>
  	 *  is created rather than a <code>LoggingEvent</code> instance.
  	 *
  	 *  @param priority the priority at which to log this message
  	 *  @param key used to index into a <code>ResourceBundle</code>
  	 *         for retrieving a message.
  	 *  @param t an exception instance from which to extract more
  	 *         information.
  	 */
  	public void l7dlog(Priority priority, String key, Throwable t) 
  	{
  		if( disable >= priority.toInt() )
  			return;
  
  		if( priority.isGreaterOrEqual( getChainedPriority() ) ) 
  		{
  			String msg = getResourceBundleString(key);
  			// if message corresponding to 'key' could not be found in the
  			// resource bundle, then default to 'key'.
  			if(msg == null) 
  				msg = key;
  
  			callAppenders(new AppServerLoggingEvent(instanceFQN, this, priority, msg, t));
  		 }
    }
  
  	/**
  	 *  Log a message based on a key used to index into a message
  	 *  catalog stored in a <code>java.util.ResourceBundle</code>.
  	 *  This version of l7dlog provides for substitutable parameters
  	 *  in the form of an object array.
  	 *  This class overrides its corresponding method in
  	 *  <code>Category</code> so that an <code>AppServerLoggingEvent</code>
  	 *  is created rather than a <code>LoggingEvent</code> instance.
  	 *
  	 *  @param priority the priority at which to log this message
  	 *  @param key used to index into a <code>ResourceBundle</code>
  	 *         for retrieving a message.
  	 *  @param params the substitutable parameters.
  	 *  @param t an exception instance from which to extract more
  	 *         information.
  	 */
  	public void l7dlog(Priority priority, String key, Object[] params, Throwable t) 
  	{
  		if(disable >= priority.toInt() ) 
  			return;
  
  		if(priority.isGreaterOrEqual(this.getChainedPriority())) 
  		{
  			String pattern = getResourceBundleString(key);
  			String msg;
  			if(pattern == null) 
  				msg = key;
  			else 
  				msg = java.text.MessageFormat.format(pattern, params);
  
  			callAppenders(new AppServerLoggingEvent( instanceFQN, this, priority, msg, t));
  		}
    }
    
  	/**
  	 *  Set the component name for this category.
  	 *
  	 *  @param categoryName the component name to be used for this category.
  	 */
  	public void setComponent(String componentName)
  	{
  		component = componentName;
  	}
  
  	/**
  	 *  Set the factory instance for creation of
  	 *  <code>AppServerCategory</code> instances.
  	 *  in the <code>getInstance</code> method.
  	 *
  	 *  @param factory an <code>AppServerCategory</code> factory
  	 */
  	public static void setFactory(CategoryFactory factory)
  	{
  		AppServerCategory.factory = factory;
  	}
  
  	/**
  	 *  Explicity set the hostname for this category.
  	 *
  	 *  @param hostname the hostname to be used for this category.
  	 */
  	public void setHostname(String hostname)
  	{
  		this.hostname = hostname;
  	}
  
  	/**
  	 *  Set the server name for this category.
  	 *
  	 *  @param serverName the server name to be used for this category.
  	 *             This is useful in CORBA and EJB environments.
  	 */
  	public void setServer(String serverName)
  	{
  		server = serverName;
  	}
  
  	/**
  	 *  Set the version of the component for this category.
  	 *
  	 *  @param versionName version name
  	 */
  	public void setVersion(String versionName)
  	{
  		version = versionName;
  	}
  }
  
  
  
  1.1                  jakarta-log4j/org/apache/log4j/examples/appserver/AppServerCategoryFactory.java
  
  Index: AppServerCategoryFactory.java
  ===================================================================
  package org.apache.log4j.examples.appserver;
  
  import java.util.ResourceBundle;
  import java.net.InetAddress;
  import java.net.UnknownHostException;
  
  import org.apache.log4j.Category;
  import org.apache.log4j.spi.CategoryFactory;
  
  /**
   *  <code>AppServerCategoryFactory</code> is responsible for
   *  creating correctly populated instances of
   *  <code>AppServerCategory</code>.  An attempt is made to
   *  determine the <code>hostname</code> using the 
   *  <code>java.net</code> API.  The other three attributes
   *  <p>
   *  <ol>
   *  <li>server name
   *  <li>component name
   *  <li>version string
   *  </ol>
   *  <p>
   *  can be set via the constructor.  All four attributes may
   *  be obtained and set through getters and setters.
   *
   *  @author Paul Glezen
   */
  public class AppServerCategoryFactory implements CategoryFactory
  {
  	/** The hostname on which this factory resides.  This is
  	    determined dynamically using the java.net.InetAddress
  		 class. */
  	protected String hostname;
  
  	/** The application server name for this factory.  This
  	    is particularly meaningful in a CORBA or EBJ application
  		 server environment.  */
  	protected String server;
  
  	/** The name of the component using this factory.  */
  	protected String component;
  
  	/** An identifier for this particular version/release. */
  	protected String version;
  
  	/** The message bundle to be used by all categories.  */
  	protected ResourceBundle messageBundle;
  
  	/**
  	 *  Construct a new <code>AppServerCategoryFactory</code> with 
  	 *  the provided attributes.  An attempt is made to obtain the
  	 *  hostname from the java.net API.
  	 *
  	 *  @param categoryName  the name of the category.
  	 *  @param serverName    the name of the server using this category.  This
  	 *                       may be null.
  	 *  @param componentName the name of the component using this category.
  	 *                       This may be null.
  	 *  @param versionName   the version identifier of the component.  This may
  	 *                       may be null.
  	 */
  	public AppServerCategoryFactory( String serverName,
  	                                 String componentName,
  			   					         String versionName )
  	{
  		try
  		{
  			hostname = java.net.InetAddress.getLocalHost().getHostName();
  		}
  		catch ( java.net.UnknownHostException uhe )
  		{
  			System.err.println("AppServerCategoryFactory: could not determine local hostname.");
  		}
  
  		server    = serverName;
  		component = componentName;
  		version   = versionName;
  	}
  
  	/**
  	 *  Get the name of the component for which this category is logging.
  	 *
  	 *  @return the component name
  	 */
  	public String getComponent()
  	{
  		return component;
  	}
  
  	/**
  	 *  Get the hostname of the machine on which this category is running.
  	 *
  	 *  @return the hostname
  	 */
  	public String getHostname()
  	{
  		return hostname;
  	}
  
  	/**
  	 *  Get the name of the server process in which this category is running.
  	 *
  	 *  @return the server name
  	 */
  	public String getServer()
  	{
  		return server;
  	}
  
  	/**
  	 *  Get the version name of the component in which this category is
  	 *  running.
  	 *
  	 *  @return the version name
  	 */
  	public String getVersion()
  	{
  		return version;
  	}
  
  	/**
  	 *  Create a new instance of <code>AppServerCategory</code>
  	 *  using the information contained in this instance.
  	 */
  	public Category makeNewCategoryInstance(String name)
  	{
  		Category result = new AppServerCategory(name, hostname, server, component, version);
  		if ( messageBundle != null )
  			result.setResourceBundle( messageBundle );
  
  		return result;
  	}
  
  	/**
  	 *  Set the name of the component for which the category will be logging.
  	 *
  	 *  @param component name of component
  	 *
  	 */
  	public void setComponent(String component)
  	{
  		this.component = component;
  	}
  
  	/**
  	 *  Set the host name of the component on which this category is running.
  	 *  An attempt is made by the constructor to determine the hostname using
  	 *  the java.net API.  Use this method only to override this
  	 *  determination.
  	 *
  	 *  @param hostname the host name.
  	 */
  	public void setHostname( String hostname )
  	{
  		this.hostname = hostname;
  	}
  
  	/**
  	 *  Set the message bundle to be used for all <code>Category</code>
  	 *  objects created by this <code>CatgoryFactory</code>.
  	 *
  	 *  param bundle a bundle of messages
  	 */
  	public void setMessageBundle(ResourceBundle bundle)
  	{
  		messageBundle = bundle;
  	}
  
  	/**
  	 *  Set the name of the application server process in which this
  	 *  category is logging.
  	 *
  	 *  @param server name of application server process.
  	 */
  	public void setServer(String server)
  	{
  		this.server = server;
  	}
  
  	/**
  	 *  Set the version string for the component.
  	 *
  	 *  @param version version name of component
  	 */
  	public void setVersion(String version)
  	{
  		this.version = version;
  	}
  
  }
  
  
  
  1.1                  jakarta-log4j/org/apache/log4j/examples/appserver/AppServerLoggingEvent.java
  
  Index: AppServerLoggingEvent.java
  ===================================================================
  package org.apache.log4j.examples.appserver;
  
  import org.apache.log4j.Category;
  import org.apache.log4j.Priority;
  import org.apache.log4j.spi.LoggingEvent;
  
  /**
   *  The internal representation of logging events. When an affirmative
   *  logging decision is made a <code>LoggingEvent</code> instance is
   *  created. This instance is passed around the different log4j
   *  components.  This sub-class of <code>LoggingEvent</code> provides
   *	 for a few additional attributes:
   *  <p>
   *  <ul>
   *  <li>hostname of originator
   *  <li>server name of event originator
   *  <li>component name of event originator
   *  <li>component version of event originator
   *  </ul>
   *  <p>
   *  This class is used to add some application server related attributes
   *  to those already provided by log4j.  It is instanciated by 
   *  <code>AppServerCategory.forcedLog</code> methods.
   *
   *  @author Paul Glezen
   */
  public class AppServerLoggingEvent extends LoggingEvent
                                     implements java.io.Serializable 
  {
  	/** Hostname of machine from which this event originated. */
  	public String hostname;
  
  	/** Name of component from which this event originated.   */
  	public String component;
  
  	/** Name of server from which this event originated.  This
  	    attribute may be more germane to CORBA/EJB environments. */
     public String server;
  
  	/** Version name of server/component. */
  	public String version;
  
  
    /**
     *  Instantiate an AppServerLoggingEvent from the supplied parameters.
     *  <p>
  	*  All the fields of
     *  <code>AppServerLoggingEvent</code> are obtained from
  	*  <code>AppServerCategory</code> or filled when actually needed.
     *  <p>
     *  @param fqnOfCategoryClass The Category class name.
     *  @param category  The category of this event.
     *  @param priority  The priority of this event.
     *  @param message   The message of this event.
     *  @param throwable The throwable of this event.  
  	*/
  	public AppServerLoggingEvent( String    fqnOfCategoryClass, 
  											AppServerCategory  category, 
  											Priority  priority, 
  											String    message, 
  											Throwable throwable) 
  	{
  		super( fqnOfCategoryClass,
  		       category,
  		       priority,
  		       message,
  		       throwable );
  
  		hostname  = category.getHostname();
  		component = category.getComponent();
  		server    = category.getServer();
  		version   = category.getVersion();
  	}
  }
  
  
  
  1.1                  jakarta-log4j/org/apache/log4j/examples/appserver/AppServerPatternLayout.java
  
  Index: AppServerPatternLayout.java
  ===================================================================
  package org.apache.log4j.examples.appserver;
  
  import org.apache.log4j.helpers.PatternParser;
  import org.apache.log4j.PatternLayout;
  
  /**
   *  This class extends <code>PatternLayout</code> to
   *  create instances of <code>AppServerPatternParser</code>
   *  for parsing pattern strings.
   *
   *  @see AppServerPatternParser
   *  @see org.apache.log4j.PatternParser
   *  @see org.apache.log4j.PatternLayout
   *
   *  @author Paul Glezen
   */
  public class AppServerPatternLayout extends PatternLayout 
  {
  	public AppServerPatternLayout() 
  	{
  		this(DEFAULT_CONVERSION_PATTERN);
  	}
  
  	public AppServerPatternLayout(String pattern) 
  	{
  		super(pattern);
  	}
      
  	public PatternParser createPatternParser(String pattern) 
  	{
  		PatternParser result;
  		if ( pattern == null )
  			result = new AppServerPatternParser( DEFAULT_CONVERSION_PATTERN );
  		else
  			result = new AppServerPatternParser ( pattern );
  
  		return result;
    }
  }
  
  
  
  1.1                  jakarta-log4j/org/apache/log4j/examples/appserver/AppServerPatternParser.java
  
  Index: AppServerPatternParser.java
  ===================================================================
  package org.apache.log4j.examples.appserver;
  
  import org.apache.log4j.*;
  import org.apache.log4j.helpers.FormattingInfo;
  import org.apache.log4j.helpers.PatternConverter;
  import org.apache.log4j.helpers.PatternParser;
  import org.apache.log4j.spi.LoggingEvent;
  
  /**
   *  Extend PatternParser to recognize additional conversion characters  
   *  suitable for use by application servers.  
   *  <p>
   *  <ul>
   *  <li>s - server name
   *  <li>h - hostname
   *  <li>b - category name (c and C already in use)
   *  <li>v - version name
   *  </ul>
   *  <p>
   *  
   *  @see org.apache.log4j.examples.MyPatternLayout
   *  @see org.apache.log4j.helpers.PatternParser
   *  @see org.apache.log4j.PatternLayout
   *
   *  @author Paul Glezen
   */
  public class AppServerPatternParser extends PatternParser 
  {
  	protected static final char HOSTNAME_CHAR  = 'h';
  	protected static final char SERVER_CHAR    = 's';
  	protected static final char COMPONENT_CHAR = 'b';
  	protected static final char VERSION_CHAR   = 'v';
  
  	/**
  	 *  Create a parser with the provided pattern.
  	 *
  	 *  @param pattern a formatting pattern to parse
  	 */
  	public AppServerPatternParser(String pattern) 
  	{
  		super(pattern);
  	}
      
  	/**
  	 *  Decide, based on the format character, which subtype of
  	 *  <code>Converter</code> to instanciate.  The converter is
  	 *  then added to the converter list using the
  	 *  <code>addConverter</code> superclass method.
  	 *  If the format character is not recognized, it is passed
  	 *  to the superclass for interpretation.
  	 */
     public void finalizeConverter(char formatChar) 
     {
  		PatternConverter pc = null;
  		switch( formatChar )
  		{
  			case HOSTNAME_CHAR:
  				pc = new HostnamePatternConverter( formattingInfo );
  				currentLiteral.setLength(0);
  				addConverter( pc );
  			   break;
  			case SERVER_CHAR:
  				pc = new ServerPatternConverter( formattingInfo );
  				currentLiteral.setLength(0);
  				addConverter( pc );
  			   break;
  			case COMPONENT_CHAR:
  				pc = new ComponentPatternConverter( formattingInfo );
  				currentLiteral.setLength(0);
  				addConverter( pc );
  			   break;
  			case VERSION_CHAR:
  				pc = new VersionPatternConverter( formattingInfo );
  				currentLiteral.setLength(0);
  				addConverter( pc );
  			   break;
  			default:
  				super.finalizeConverter( formatChar );
        }
     }
    
     /**
  	 *  The <code>AppServerPatternConverter</code> inner class factors
  	 *  out all the duties of a converter except
  	 */
  	private static abstract class AppServerPatternConverter extends PatternConverter 
  	{
  		AppServerPatternConverter(FormattingInfo formattingInfo) 
  		{
  			super(formattingInfo);     
  		}
  
  		public String convert(LoggingEvent event) 
  		{
  			String result = null;
  			AppServerLoggingEvent appEvent = null;
  
  			if ( event instanceof AppServerLoggingEvent )
  			{
  				appEvent = (AppServerLoggingEvent) event;
  				result = convert( appEvent );
  			}
  			return result;
  		}
  
  		public abstract String convert( AppServerLoggingEvent event );
  	}
  
  	private static class HostnamePatternConverter extends AppServerPatternConverter
  	{
  		HostnamePatternConverter( FormattingInfo formatInfo )
  		{  super( formatInfo );  }
  
  		public String convert( AppServerLoggingEvent event )
  		{  return event.hostname;  }
  	}
  
  	private static class ServerPatternConverter extends AppServerPatternConverter
  	{
  		ServerPatternConverter( FormattingInfo formatInfo )
  		{  super( formatInfo );  }
  
  		public String convert( AppServerLoggingEvent event )
  		{  return event.server;  }
  	}
  
  	private static class ComponentPatternConverter extends AppServerPatternConverter
  	{
  		ComponentPatternConverter( FormattingInfo formatInfo )
  		{  super( formatInfo );  }
  
  		public String convert( AppServerLoggingEvent event )
  		{  return event.component;  }
  	}
  
  	private static class VersionPatternConverter extends AppServerPatternConverter
  	{
  		VersionPatternConverter( FormattingInfo formatInfo )
  		{  super( formatInfo );  }
  
  		public String convert( AppServerLoggingEvent event )
  		{  return event.version;  }
  	}
  }
  
  
  
  1.1                  jakarta-log4j/org/apache/log4j/examples/appserver/package.html
  
  Index: package.html
  ===================================================================
  <html>
  <body>
  This package extends log4j to add extra logging attributes useful in 
  distributed application server environments.  Specifically, it adds 
  the following information to each logging event.
  <p>
  <ol>
  <li><b>host (h)</b> - the name of the machine from which the message
  	was logged
  <li><b>server (s)</b> - the name of the server process from which the
  	message was logged
  <li><b>component (b)</b> - the name of the component from which the
  	message was logged
  <li><b>version (v)</b> - a version string for the code from which the
     message was logged
  </ol>
  <p>
  <h3>Usage</h3>
  Using this package in your programs differs little from using the
  corresponding classes from <code>org.apache.log4j</code>.  At log4j 
  initialization you create an
  instance of 
  <a href="AppServerCategoryFactory.html"><code>AppServerCategoryFactory</code></a>
  populated with the attributes you wish.  You can either supply these 
  in the factory's constructor
  or set them afterwards.  The host name is determined automatically
  using the <code>java.net</code> API and can be reset manually.  It
  is ok to set any of the attributes to null.
  <p>
  After creating an appropriate <code>AppServerCategoryFactory</code>
  instance, set a static reference to it using the
  <a href="AppServerCategory.html#setFactory">
  <code>AppServerCategory.setFactory</code></a> method.  This
  sets everything up for acquiring an 
  <a href="AppServerCategory.html"><code>AppServerCategory</code></a>
  reference whenever you need it.
  <p>
  <table border=1>
  <tr><td><pre>
  import org.apache.log4j.spi.CategoryFactory;
  import org.apache.log4j.Category;
  import org.apache.log4j.examples.appserver.AppServerCategoryFactory;
  import org.apache.log4j.examples.appserver.AppServerCategory;
  
  ...
  
  org.apache.log4j.BasicConfigurator.configure();
  CategoryFactory factory = new AppServerCategoryFactory("MyServer", null, null);
  AppServerCategory.setFactory( factory );
  
  ...
  
  Category cat = AppServerCategory.getInstance("my.category");
  cat.info("Entry");
  </pre>
  </table>
  <p>
  <h3>A Note on Configurators</h3>
  Using <code>AppServerCategory</code> with the 
  <a href="../../PropertyConfigurator.html">
  <code>PropertyConfigurator</code></a> or
  <a href="../../xml/DOMConfigurator.html">
  <code>DOMConfigurator</code></a>
  requires one note of caution.  These configurators do not
  know that 
  <a href="../../Category.html"><code>Category</code></a>
  has been subclassed.  Upon
  constructing a configuration from a set of properties, it will
  construct <code>Category</code> instances rather than the desired
  subclass.  There at least two ways to work around this.
  <p>
  By instanciating any anticipated <code>AppServerCategory</code>
  instances before calling a configurator, the configurator will
  use the instances you create rather than trying to (incorrectly)
  create its own.  The consequence of this route is that you can
  not always predict which categories will be created.  Their
  dynamic nature is the reason for externalizing their configuration
  in the first place.
  <p>
  Another way is to take advantage of a recently added feature
  allowing you to specify the type of factory used for creating
  <code>Category</code> instances to a <code>DOMConfigurator</code>
  or a <code>PropertyConfigurator</code>.  The consequence of this
  route is that only the default constructor is used to create
  the factory instance.  For <code>AppServerCategoryFactory</code>,
  this will only populate the hostname attribute.  The server name,
  component name and version name will be blank.  This may be
  satisfactory for many cases.
  <p>
  <h3>Compatibility</h3>
  The log4j package naming conventions used in
  this package are compatible with log4j version 1.0.
  <p>
  <h3>Try It Yourself</h3>
  While the attributes extended in this package are oriented toward
  application servers, there is nothing application server specific
  in the code structure.  This package may be used as a template for
  specifying your own collection of attributes or extended to include
  additional attributes.  A 
  <a href="../../../../../../doc/DeepExtension.html">log4j extension manual</a> 
  accompanies this package that will take you step by step through the 
  process.
  </body>
  </html>