Had this email rejected twice with the following error: "_we_don't_accept_email_with_executable_content_"
I tried attaching a .zip file containing the two files I am attaching now. Who the heck is considering .zip to be an "executable"???? How annoying! Anyway, read on.....
At 02:47 PM 3/22/2004 +0800, you wrote:
I'm glad to say I have had some success. Based on Jake's recommendations, I used the ContextClassLoaderSelector from Log4j CVS with success. I also avoided the OptionConverter class and used the PropertyConfigurator and DOMConfigurator classes instead. I think I also had not initialised log4j in my service thread correctly, after setting the context class loader.
Many thanks to both Jake and Carl for your help and advice.
Good to hear :-)
One thing to note (which I just found out myself) is that the RepositorySelector interface has changed in Log4j-1.3 CVS. Might want to take a look at ContextJNDISelector in logging-log4j. Ceki modified it from the one that was in logging-log4j-sandbox. So, just beware that the ContextClassLoaderSelector in the sandbox will not work with Log4j-1.3. Here's the new method that needs to be implemented for 1.3...
public void setDefaultRepository(LoggerRepository def);
Ceki, if you are reading this, why the change to the interface? You had been pretty opposed to this before. Also, why the change to the JNDI lookup in ContextJNDISelector to to be "java:comp/env/log4j/context-name" instead of "java:comp/env/log4j/logging-context" as it was in the sandbox? I realize that the sandbox is not official code, but it makes moving to Log4j-1.3 more difficult since anyone using the old one will have it configured to use "logging-context" (including me, of course). I think the javadoc still refers to "logging-context" not "context-name" in one spot, although the example provided says "context-name". If there is no real good reason to change the name, can it move back to "logging-context"? The new autoconfiguration looks interesting. Maybe my advice to Vance about configuration not belonging in the repository selector was premature. I'll have to try it sometime here. In any case, could you detail your reasons for the change to the RepositorySelector interface?
BTW, I've made some recent changes to the InitShutdownController class per a private submission from Andreas Werner. He pointed out a few things that were a bit buggy and split things out into multiple methods instead of having so much in the InitializeLog4j(ServletContext) method. I modified a few of his changes since they would have introduced a few bugs themselves, but the result is pretty nice and definitely easier to read. One interesting thing I've done is add code to modify the thread context class loader to be the current classloader during initialization and restore it afterwards. It prevents class cast exceptions. I would commit it except that, apparently, Apache doesn't have my CLA on file. A new one has been faxed, but I'm not sure when they'll process it. So, maybe I'll post it here to get some feedback. I've provided an explanation about the context class loader stuff in a readme I'll also attach to this post. I may make changes between now and when these changes are committed, so this isn't final code yet. Let me know if anyone experiences any problems with it.
Jake
Vance
-----Original Message----- From: Jacob Kjome [mailto:[EMAIL PROTECTED] Sent: Saturday, 20 March 2004 12:23 AM To: Log4J Users List Subject: RE: Contextual Repository Selector problem
Quoting Vance Karimi <[EMAIL PROTECTED]>:
> Hi Jake, > I actually read through the Log4j CVS ContextClassLoaderSelector and servlet > specific package java files. They were very helpful and documented > extremely well. > > Forgive me if I'm just re-stating the obvious. > > If I understand it right, the init method of InitServlet is called by the > container. This is called once per context start-up right? >
Yes, but note that one would want to use InitContextListener, not InitServlet, but that's a bit off-topic for this discussion.
> This method performs the initializeLog4j task which sets the > RepositorySelector by creating a new instance of ContextClassLoaderSelector, > if one is not already created.
Actually, the InitShutdownController does all this in the setSelector(ServletContext) method and simply attempts each time to set the repository selector. It then catches various exceptions that might occur if the repository selector is already set. It can only be set once unless provided with the original guard object which was used to initially set it. Of course, this is per Log4j instance. If one has log4j.jar in each app's WEB-INF/lib, then each will set a selector successfully since none of the apps can see each other's classloader. The real reason for using a repository selector is when there is a single global log4j.jar that everyone uses.
For info on this method, see the original source at... http://tinyurl.com/3aw7q
Having done that, it will load the log4j > properties or xml file associated with the context. >
It should, although automatic configuration won't happen after the first time Log4j is loaded up in a classloader. Upon server startup, Log4j will look for the config file, but not after that. Apps would have to initialize Log4j themselves in this environment, unless they put Log4j in their WEB-INF/lib directories. But then that is a whole new instance of Log4j with no particular reason to be using a repository selector except for guarding against the case where the app doesn't include Log4j.jar in WEB-INF/lib. Of course, setting the repository selector should normally be done by the container. The code in InitShutdownController is Kludge for making sure one exists before doing configuration in case the server hasn't set it (because almost none I know of do).
> Only 1 instance of the ContextClassLoaderSelector is created and set using > LogManager so that we can track each Hierarchy based on the context > classloader.
Sounds right
> > I believe I do all of that, however I do not manually call > PropertyConfigurator or DOMConfigurator. I use > OptionConverter.selectAndConfigure, as it should determine if the log4j > config file is an xml or properties file and call the corresponding > Configurator. >
To be honest, I've never looked at OptionConverter. I'll have to do that sometime.
> The other difference I see is that I call OptionConverter.selectAndConfigure > in my getLoggerRepository implementation method.
I would avoid this. That is not the place to do configuration. That's an app's responsibility.
My understanding is that > when I call Logger.getLogger(..) and having set the > Thread.currentThread().contextClassLoader, a new LoggerRepository/Hierarchy > will be created or looked up if already exists. I can't see why it would > make a difference if I manually call the OptionConverter.selectAndConfigure > when a new context is about to run for the first time. But, it is something > I will try. >
Yes, try that. You might want to just try the existing ContextClassLoaderSelector in logging-log4j-sandbox ( http://tinyurl.com/32htr ) and see if that works for you. If it does, then you know the problem is in your code somewhere. If that doesn't work for you, then you know to look elsewhere. In that case, ask back here because I'd be very interested in knowing it is not working in certain cases.
> If you have any other thoughts, I'd appreciate them. >
Hopefully what I've provided will get you back on track. Let me know if it doesn't. Also let me know of any success you may have.
> Cheers, > Vance >
Jake
> -----Original Message----- > From: Jacob Kjome [mailto:[EMAIL PROTECTED] > Sent: Friday, 19 March 2004 2:31 AM > To: Log4J Users List > Subject: Re: Contextual Repository Selector problem > > I don't have much time to respond, but there already exists implementations > of > repository selectors in the latest Log4j CVS (ContextJNDIRepositorySelector) > and > in the latest Log4j sandbox CVS (ContextClassLoaderSelector). I added lots > of > instructions to them. Also look in InitShutdownController (in Log4j > sandbox) to > see how I initialize the repository selector. See more here... > > http://nagoya.apache.org/wiki/apachewiki.cgi?Log4JProjectPages/AppContainerL > ogging > > > Jake > > Quoting Vance Karimi <[EMAIL PROTECTED]>: > > > Hi > > I am writing a container server application that runs services/contexts > > within it. These services are hot deployed in a jar file and I manage the > > ClassLoaders to handle separate contexts. I need to implement the > > repository selector in Log4j so each thread that runs a service logs to a > > separate log file. > > > > Based on the following http://www.qos.ch/logging/sc.html I have a > Repository > > Selector something very similar to: > > > > > > import org.apache.log4j.spi.RepositorySelector; > > import org.apache.log4j.spi.LoggerRepository; > > import org.apache.log4j.spi.RootCategory; > > import org.apache.log4j.Hierarchy; > > import org.apache.log4j.Level; > > import java.util.Hashtable; > > > > public class CRS implements RepositorySelector { > > > > // key: current thread's ContextClassLoader, > > // value: Hierarchy instance > > private Hashtable ht; > > > > public CRS() { > > ht = new Hashtable(); > > } > > > > public LoggerRepository getLoggerRepository() { > > LoggerRepository loggerRepository = null; > > > > ClassLoader classLoader = > > Thread.currentThread().getContextClassLoader(); > > > > loggerRepository = (LoggerRepository) > > loggerRepositories.get(classLoader.toString()); > > > > if (loggerRepository != null) { > > // do nothing > > } else { > > loggerRepository = new Hierarchy(new RootCategory((Level) > > Level.DEBUG)); > > loadRepository(loggerRepository); > > loggerRepositories.put(classLoader.toString(), loggerRepository); > > > > } > > > > return loggerRepository; > > } > > > > /** > > * The Container should remove the entry when the web-application > > * is removed or restarted. > > * */ > > public void remove(ClassLoader cl) { > > if (loggerRepositories.containsKey(cl.toString())) { > > LoggerRepository lr = (LoggerRepository) > > loggerRepositories.get(cl.toString()); > > lr.resetConfiguration(); > > } > > loggerRepositories.remove(cl.toString()); > > } > > > > private static void loadRepository(LoggerRepository loggerRepository) { > > > > URL url = getURL(resources); > > > > if (url != null) { > > OptionConverter.selectAndConfigure(url, null, loggerRepository); > > } > > } > > ..... > > } > > > > > > I set the Context Repository Selector when the server first starts up: > > > > if (guard == null) { > > guard = new Object(); > > } > > > > ContextRepositorySelector crs = > agent.registerContextRepositorySelector(); > > LogManager.setRepositorySelector(crs, guard); > > > > > > I have enabled debugging in Log4j. When my server first starts up, I get > > the following debug statements due to the log4j.properties of the server, > > showing the root context and 2 appenders (Default and Console) > > > > log4j: Parsing for [root] with value=[DEBUG, Default, Console]. > > log4j: Level token is [DEBUG]. > > log4j: Category root set to DEBUG > > log4j: Parsing appender named "Default". > > log4j: Parsing layout options for "Default". > > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n]. > > log4j: End of parsing for "Default". > > log4j: Setting property [append] to [true]. > > log4j: Setting property [file] to [server/log/server.log]. > > log4j: Setting property [datePattern] to ['.'yyyy-MM-dd]. > > log4j: setFile called: server/log/server.log, true > > log4j: setFile ended > > log4j: Appender [Default] to be rolled at midnight. > > log4j: Parsed "Default" options. > > log4j: Parsing appender named "Console". > > log4j: Parsing layout options for "Console". > > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n]. > > log4j: End of parsing for "Console". > > log4j: Parsed "Console" options. > > log4j: Finished configuring. > > log4j: JIVS: Time taken to look up loggerRepository 368ms > > > > I then deploy my service and call Logger.getLogger(my.service.class) to > get > > the following for the root logger with 2 appenders(A1 and A2): > > > > log4j: Parsing for [root] with value=[DEBUG, A1, A2]. > > log4j: Level token is [DEBUG]. > > log4j: Category root set to DEBUG > > log4j: Parsing appender named "A1". > > log4j: Parsing layout options for "A1". > > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n]. > > log4j: End of parsing for "A1". > > log4j: Setting property [file] to [server/log/recorder.log]. > > log4j: Setting property [append] to [true]. > > log4j: Setting property [datePattern] to ['.'yyyy-MM-dd]. > > log4j: setFile called: server/log/recorder.log, true > > log4j: setFile ended > > log4j: Appender [A1] to be rolled at midnight. > > log4j: Parsed "A1" options. > > log4j: Parsing appender named "A2". > > log4j: Parsing layout options for "A2". > > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n]. > > log4j: End of parsing for "A2". > > log4j: Parsed "A2" options. > > log4j: Finished configuring. > > log4j: JIVS: Time taken to look up loggerRepository 33ms > > > > Now the problem: > > > > All my logs are directed to server.log and the console. The recorder.log > > (log for the deployed service) is created, but no logs are appended to the > > file. I know the log4j.properties config file of the service is found and > > loaded correctly due to the debug statements. > > > > I really need some direction here and have come to a dead end. Your > > feedback would be really appreciated. > > > > Cheers, > > Vance > > > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
If the Log4j InitShutdownController exists in a parent classloader and one includes log4j.jar in WEB-INF/lib, there is a risk, nay, guarantee of a ClassCastException with Configurator being loaded from the parent and DOMConfigurator being loaded from the WebappClassLoader. This can be avoided by setting the context class loader to the class loader of the InitShutdownController at the start of initialization and restoring the original at end of initialization, as described here...
http://www-106.ibm.com/developerworks/websphere/library/techarticles/0310_searle/searle.html The one confusing thing about this is that the webapp will have a configured logger repository entry in the parent's Log4j instance, but the app won't actually use that since it will load Log4j from its own class loader and attempt to find a log4j config file in the classpath and will be using the local default logger repository for logging. To avoid this, one of two things can be done: 1. Don't put log4j.jar in WEB-INF/lib and only load it from the server's classpath. log4j-sandbox.jar can be in either in the server's classpath or in WEB-INF/lib. There will be no noticeable difference in functionality either way. 2. Put both log4j.jar and log4j-sandbox.jar in WEB-INF/lib. One would do this if not sure about log4j.jar being in the server's classpath. If one is sure, having log4j.jar here would be totally unnecessary. Note: the above comments assume that the InitShutdownController is in a separate jar from log4j.jar. If it is in log4j.jar, there is almost nothing to worry about because all classes will always be together in the same classloader and will work regardless.
/* * Copyright 1999,2004 The Apache Software 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.log4j.servlet; import org.apache.log4j.LogManager; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.helpers.LogLog; import org.apache.log4j.spi.RepositorySelector; import org.apache.log4j.xml.DOMConfigurator; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.Properties; import javax.servlet.ServletContext; /** * Diese Klasse ist aus der Sandbox des Apache Projekts entnommen, und wurde * f�r die Verwendung innerhalb der Kioskapplikation angepasst. * * @see http://nagoya.apache.org/wiki/apachewiki.cgi?Log4JProjectPages/AppContainerLogging * * Used to initialize and cleanup Log4j in a servlet environment. * <p>See [EMAIL PROTECTED] InitContextListener} for web.xml configuration instructions.</p> * <p>Besides basic webapp lifecycle control when used with InitContextListener * and [EMAIL PROTECTED] InitServlet}, this class can be used by any class at runtime to * control initialization and shutdown of Log4j loggers and appenders.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">Jacob Kjome</a> * @since 1.3 */ public class InitShutdownController { /** * preferred repository selector config param. * Maps to web.xml <context-param> with * <param-name>log4j-selector</param-name> */ public static final String PARAM_LOG4J_PREF_SELECTOR = "log4j-selector"; /** * relative path to config file within current webapp config param. * Maps to web.xml <context-param> with * <param-name>log4j-config</param-name> */ public static final String PARAM_LOG4J_CONFIG_PATH = "log4j-config"; /** * config file re-reading specified in milliseconds config param. * Maps to web.xml <context-param> with * <param-name>log4j-cron</param-name> */ public static final String PARAM_LOG4J_WATCH_INTERVAL = "log4j-cron"; /** * path to be read from a log4j xml config file as a system property * config param. Maps to web.xml <context-param> with * <param-name>log4j-log-home</param-name> */ public static final String PARAM_LOG4J_LOG_HOME = "log4j-log-home"; /** * system property to be used in a log4j xml config file config param. * Maps to web.xml <context-param> with * <param-name>log4j-sysprop-name</param-name> */ public static final String PARAM_LOG4J_SYSPROP_NAME = "log4j-sysprop-name"; /** * default path to write log files if using a file appender */ private static final String DEFAULT_LOG_HOME = "WEB-INF" + File.separator + "logs"; /** * Log4j specific cleanup. Shuts down all loggers and appenders. * * @param context the current servlet context */ public static void shutdownLog4j(final ServletContext context) { //shutdown this webapp's logger repository context.log( "Cleaning up Log4j resources for context: " + context.getServletContextName() + "..."); context.log("Shutting down all loggers and appenders..."); org.apache.log4j.LogManager.shutdown(); context.log("Log4j cleaned up."); } /** * Log4j specific initialization. Sets up log4j for the current * servlet context. Installs a custom repository selector if one hasn't * already been installed. * * @param context the current servlet context */ public static void initializeLog4j(final ServletContext context) { ClassLoader savedClassLoader = null; try { savedClassLoader = Thread.currentThread().getContextClassLoader(); //attempt to set the thread context class loader to the current class //loader to avoid ClassCastExceptions when this library is in a parent //class loader (along with log4j.jar) and a webapp includes log4j.jar //in WEB-INF/lib, but not this library (assuming they aren't both in //log4j.jar). Thread.currentThread().setContextClassLoader( InitShutdownController.class.getClassLoader()); } catch (SecurityException se) { //oh, well, we tried. Security is turned on and we aren't allowed to //tamper with the thread context class loader. You're on your own! } try { //Attempt to set the repository selector no matter what else happens setSelector(context); String configPath = getLog4jConfigPathFromContext(context); if ((configPath != null) && (configPath.length() >= 1)) { setLog4jLogHome(context); if (context.getRealPath("/") != null) { configureLog4jFromFile(configPath, context); } else { configureLog4jFromURL(configPath, context); } } else { if (configPath == null) { LogLog.error("Missing log4j-config servlet parameter missing."); } else { LogLog.error("Zero length Log4j config file path given."); } displayConfigNotFoundMessage(); } } finally { if (savedClassLoader != null) { //reset the thread context class loader to the original saved class //loader now that our purpose (avoiding class cast exceptions) has been //served Thread.currentThread().setContextClassLoader(savedClassLoader); } } } /** * Determines the path to log4j config file from the servlet context param * 'logj4-config'. The path is assumed to be relative to the current context. * If set, the path is normalized with any preceeding slash removed as the * other methods expect the path to be formatted this way. * * @param context The servlet context * @return the path to the log4j config file within the context or null if * the 'log4j-config' context param is not set. */ private static String getLog4jConfigPathFromContext( final ServletContext context) { String configPath = context.getInitParameter(PARAM_LOG4J_CONFIG_PATH); if (configPath != null) { if (configPath.startsWith("/")) { configPath = (configPath.length() > 1) ? configPath.substring(1) : ""; } } return configPath; } /** * Determines the log4j home to use. If the context parameter * 'log4j-log-home' is set, this is used as the environment variable. * Otherwise the the default 'WEB-INF/logs' is used. * * @param context the current servlet context */ private static void setLog4jLogHome(final ServletContext context) { // set up log path System property String logHome = context.getInitParameter(PARAM_LOG4J_LOG_HOME); if (logHome != null) { // set up custom log path system property setFileAppenderSystemProperty(logHome, context); } else { String contextPath = context.getRealPath("/"); if (contextPath != null) { //no log path specified in web.xml. Setting to default within current //context path logHome = contextPath + DEFAULT_LOG_HOME; setFileAppenderSystemProperty(logHome, context); } } } /** * Configures log4j via url * * @param configPath the location of the log4j configuration file * relative to the context path * @param context the current servlet context */ private static void configureLog4jFromURL( final String configPath, final ServletContext context) { //The webapp is deployed from a .war file, not directly off the file system //so we *cannot* do File IO. Note that we *won't* be able to use //configureAndWatch() here because that requires an absolute system file //path. boolean isXMLConfigFile = (configPath.endsWith(".xml")) ? true : false; URL log4jURL = null; try { log4jURL = context.getResource("/" + configPath); } catch (MalformedURLException murle) { //ignore...we check for null later ; } //Now let's check if the given configPath actually exists. if (log4jURL != null) { context.log("Configuring Log4j from URL at path: /" + configPath); if (isXMLConfigFile) { try { DOMConfigurator.configure(log4jURL); //catch (javax.xml.parsers.FactoryConfigurationError fce) {} } catch (Exception e) { //report errors to server logs LogLog.error(e.getMessage()); } } else { Properties log4jProps = new Properties(); try { log4jProps.load(log4jURL.openStream()); PropertyConfigurator.configure(log4jProps); //catch (java.io.IOException ioe) {} } catch (Exception e) { //report errors to server logs LogLog.error(e.getMessage()); } } } else { //The given configPath does not exist. So, let's just let Log4j look for //the default files (log4j.properties or log4j.xml) on its own. displayConfigNotFoundMessage(); } } /** * Configures log4j from a File * * @param systemConfigPath the fully qualified system path location of the * log4j configuration file * @param context the current servlet context */ private static void configureLog4jFromFile( final String configPath, final ServletContext context) { //The webapp is deployed directly off the filesystem, not from a .war file //so we *can* do File IO. This means we can use configureAndWatch() to //re-read the the config file at defined intervals. boolean isXMLConfigFile = (configPath.endsWith(".xml")) ? true : false; String contextPath = context.getRealPath("/"); String systemConfigPath = configPath.replace('/', File.separatorChar); File log4jFile = new File(contextPath + systemConfigPath); //Now let's check if the given configPath actually exists. if (log4jFile.canRead()) { log4jFile = null; long timerIntervalVal = getTimerIntervalFromContext(context); context.log( "Configuring Log4j from File: " + contextPath + systemConfigPath); if (timerIntervalVal > 0) { context.log( "Configuring Log4j with watch interval: " + timerIntervalVal + "ms"); if (isXMLConfigFile) { DOMConfigurator.configureAndWatch( contextPath + systemConfigPath, timerIntervalVal); } else { PropertyConfigurator.configureAndWatch( contextPath + systemConfigPath, timerIntervalVal); } } else { if (isXMLConfigFile) { DOMConfigurator.configure(contextPath + systemConfigPath); } else { PropertyConfigurator.configure(contextPath + systemConfigPath); } } } else { // The given configPath does not exist. So, let's just // let Log4j look for the default files ( // log4j.properties or log4j.xml) on its own. displayConfigNotFoundMessage(); } } /** * Retrieves the timer interval from the servlet context. * * @param context the current servlet context */ private static long getTimerIntervalFromContext( final ServletContext context) { String timerInterval = context.getInitParameter(PARAM_LOG4J_WATCH_INTERVAL); long timerIntervalVal = 0L; if (timerInterval != null) { try { timerIntervalVal = Integer.valueOf(timerInterval).longValue(); } catch (NumberFormatException nfe) { //ignore...we just won't use configureAndWatch if there is no valid int ; } } return timerIntervalVal; } /** * standard configuration not found message */ private static void displayConfigNotFoundMessage() { LogLog.warn( "No Log4j configuration file found at given path. " + "Falling back to Log4j auto-configuration."); } /** * sets the [webapp].log.home system property for use with a file appender. * * @param logHome the path to a logging directory * @param context the current servlet context */ private static void setFileAppenderSystemProperty( final String logHome, final ServletContext context) { String logHomePropName = null; String customPropName = context.getInitParameter(PARAM_LOG4J_SYSPROP_NAME); File logHomeDir = new File(logHome); if (logHomeDir.exists() || logHomeDir.mkdirs()) { if (customPropName != null) { logHomePropName = customPropName; } else { logHomePropName = getContextPath(context) + ".log.home"; } context.log( "Setting system property [ " + logHomePropName + " ] to [ " + logHome + " ]"); System.setProperty(logHomePropName, logHome); } } /** * Retrieves the context path of the web application from the servlet context. * * @param context the current servlet context * @return the derived context path, guaranteed non-null */ private static String getContextPath(final ServletContext context) { //old way to determine context path //String tempdir = "" + //context.getAttribute("javax.servlet.context.tempdir"); //int lastSlash = tempdir.lastIndexOf(File.separator); //if ((tempdir.length() - 1) > lastSlash) { // logHomePropName = tempdir.substring(lastSlash + 1) + ".log.home"; //} String contextPath = ""; try { //use a more standard way to obtain the context path name //which should work across all servers. The tmpdir technique //(above) depends upon the naming scheme that Tomcat uses. String path = context.getResource("/").getPath(); //first remove trailing slash, then take what's left over //which should be the context path less the preceeding //slash such as "MyContext" contextPath = path.substring(0, path.lastIndexOf("/")); contextPath = contextPath.substring(contextPath.lastIndexOf("/") + 1); } catch (Exception e) { ; } return contextPath; } /** * Do idempotent initialization of the the logger repository. Only one * repository selector may be set during runtime of log4j. Therefore, this * method is only a guarantee that a repository selector will have been set. * It does not guarantee that your preferred selector will be used. If * some other code sets the selector first, that is the selector that all * applications using Log4j will use, assuming log4j is running in a shared * class loader. * * @param context the current servlet context */ private static void setSelector(final ServletContext context) { String selector = context.getInitParameter(PARAM_LOG4J_PREF_SELECTOR); if (selector == null) { LogLog.warn( "No preferred selector supplied. Using default repository selector..."); return; } try { Object guard = new Object(); Class clazz = Class.forName( selector, true, Thread.currentThread().getContextClassLoader()); LogManager.setRepositorySelector( (RepositorySelector) clazz.newInstance(), guard); } catch (ClassNotFoundException cnfe) { LogLog.warn( "Preferred selector not found. Using default repository selector..."); } catch (InstantiationException ie) { LogLog.warn( "Error in instantiation of preferred selector. Using default " + "repository selector..."); } catch (IllegalAccessException iae) { LogLog.warn( "Unable to access preferred selector. Using default repository " + "selector..."); } catch (IllegalArgumentException iae) { LogLog.warn( "Preferred repository selector not installed because one has already " + "exists. No problem, using existing selector..."); } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
