diff --git a/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java b/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java index 7092b94de6dc745c789680ef5f5181c9e16111f6..a06087b0b0e6eb2d4567e7a4da2f4e4aab85cd09 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java +++ b/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java @@ -13,15 +13,13 @@ */ package ch.qos.logback.access.joran.action; -import ch.qos.logback.core.status.OnConsoleStatusListener; -import ch.qos.logback.core.util.OptionHelper; -import ch.qos.logback.core.util.StatusListenerConfigHelper; - import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.ContextUtil; +import ch.qos.logback.core.status.OnConsoleStatusListener; +import ch.qos.logback.core.util.OptionHelper; +import ch.qos.logback.core.util.StatusListenerConfigHelper; public class ConfigurationAction extends Action { static final String INTERNAL_DEBUG_ATTR = "debug"; @@ -44,8 +42,6 @@ public class ConfigurationAction extends Action { StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener()); } - new ContextUtil(context).addHostNameAsProperty(); - // the context is appender attachable, so it is pushed on top of the stack ec.pushObject(getContext()); } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java index 5724ebe373c36e678ca90c0bd703d75048637f34..693f9271b532a167516de4c22643136b78a666db 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java @@ -61,14 +61,12 @@ public class ConfigurationAction extends Action { processScanAttrib(ic, attributes); - ContextUtil contextUtil = new ContextUtil(context); - contextUtil.addHostNameAsProperty(); - LoggerContext lc = (LoggerContext) context; boolean packagingData = OptionHelper.toBoolean(ic.subst(attributes.getValue(PACKAGING_DATA_ATTR)), LoggerContext.DEFAULT_PACKAGING_DATA); lc.setPackagingDataEnabled(packagingData); if (EnvUtil.isGroovyAvailable()) { + ContextUtil contextUtil = new ContextUtil(context); contextUtil.addGroovyPackages(lc.getFrameworkPackages()); } diff --git a/logback-classic/src/test/input/joran/hostnameProperty.xml b/logback-classic/src/test/input/joran/hostnameProperty.xml new file mode 100755 index 0000000000000000000000000000000000000000..f7ddeb7fe9eb70cf7fb535bbad70ebebad791493 --- /dev/null +++ b/logback-classic/src/test/input/joran/hostnameProperty.xml @@ -0,0 +1,4 @@ + + + + diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java index 630d16794aa21e3cd6c1ee1c5b0fa6c4d1adba3b..46faaf8e10336f275a005004a4d11d5e82bfcc69 100755 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java @@ -390,7 +390,6 @@ public class JoranConfiguratorTest { @Test public void properties() throws JoranException { String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "properties.xml"; - assertNull(loggerContext.getProperty(CoreConstants.HOSTNAME_KEY)); assertNull(System.getProperty("sys")); configure(configFileAsStr); @@ -403,6 +402,13 @@ public class JoranConfiguratorTest { checker.assertIsErrorFree(); } + @Test + public void hostnameProperty() throws JoranException { + String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "hostnameProperty.xml"; + configure(configFileAsStr); + assertEquals("A", loggerContext.getProperty(CoreConstants.HOSTNAME_KEY)); + } + // see also http://jira.qos.ch/browse/LBCORE-254 @Test public void sysProps() throws JoranException { @@ -427,8 +433,7 @@ public class JoranConfiguratorTest { configure(configFileAsStr); assertTrue(loggerContext.isPackagingDataEnabled()); } - - + @Test public void valueOfConvention() throws JoranException { String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "valueOfConvention.xml"; diff --git a/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java b/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java index edd3a3219f3d9399df1f22bffdf57f806fa3211c..a6025ff76f875b4a825114fc50311dab99377b2a 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java @@ -14,6 +14,7 @@ package ch.qos.logback.core; import static ch.qos.logback.core.CoreConstants.CONTEXT_NAME_KEY; +import static ch.qos.logback.core.CoreConstants.HOSTNAME_KEY; import static ch.qos.logback.core.CoreConstants.FA_FILENAME_COLLISION_MAP; import static ch.qos.logback.core.CoreConstants.RFA_FILENAME_PATTERN_COLLISION_MAP; @@ -29,6 +30,7 @@ import ch.qos.logback.core.rolling.helper.FileNamePattern; import ch.qos.logback.core.spi.LifeCycle; import ch.qos.logback.core.spi.LogbackLock; import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.ContextUtil; import ch.qos.logback.core.util.ExecutorServiceUtil; public class ContextBase implements Context, LifeCycle { @@ -81,7 +83,11 @@ public class ContextBase implements Context, LifeCycle { } public void putProperty(String key, String val) { - this.propertyMap.put(key, val); + if (HOSTNAME_KEY.equalsIgnoreCase(key)) { + putHostnameProperty(val); + } else { + this.propertyMap.put(key, val); + } } protected void initCollisionMaps() { @@ -99,10 +105,31 @@ public class ContextBase implements Context, LifeCycle { public String getProperty(String key) { if (CONTEXT_NAME_KEY.equals(key)) return getName(); + if (HOSTNAME_KEY.equalsIgnoreCase(key)) { + return lazyGetHostname(); + } return (String) this.propertyMap.get(key); } + private String lazyGetHostname() { + String hostname = (String) this.propertyMap.get(HOSTNAME_KEY); + if (hostname == null) { + hostname = new ContextUtil(this).safelyGetLocalHostName(); + putHostnameProperty(hostname); + } + return hostname; + } + + private void putHostnameProperty(String hostname) { + String existingHostname = (String) this.propertyMap.get(HOSTNAME_KEY); + if (existingHostname == null) { + this.propertyMap.put(CoreConstants.HOSTNAME_KEY, hostname); + } else { + + } + } + public Object getObject(String key) { return objectMap.get(key); } @@ -130,7 +157,7 @@ public class ContextBase implements Context, LifeCycle { // We don't check "started" here, because the executor service uses // lazy initialization, rather than being created in the start method stopExecutorService(); - + started = false; } @@ -143,7 +170,7 @@ public class ContextBase implements Context, LifeCycle { * shutdown hook */ public void reset() { - + removeShutdownHook(); getLifeCycleManager().reset(); propertyMap.clear(); @@ -248,7 +275,5 @@ public class ContextBase implements Context, LifeCycle { public List> getScheduledFutures() { return new ArrayList>(scheduledFutures); } - - } diff --git a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java index 90b0ffc18f9a3e5c28a2a7abfc62174e0aab88e2..a9eb5df0e4b41d8d23b618254665be93ed39610f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java +++ b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java @@ -168,6 +168,8 @@ public class CoreConstants { */ public static final String HOSTNAME_KEY = "HOSTNAME"; + public static final String UNKNOWN_LOCALHOST = "UNKNOWN_LOCALHOST"; + /** * The key under which the current context name is registered in the logger * context. diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/ContextUtil.java b/logback-core/src/main/java/ch/qos/logback/core/util/ContextUtil.java index fcbdb7a178920d8935be5e2766fa436641fbf3df..fe6291f39adecc7b935808e9e0c9f571fd75e2f3 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/util/ContextUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/ContextUtil.java @@ -13,11 +13,6 @@ */ package ch.qos.logback.core.util; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.rolling.helper.FileNamePattern; -import ch.qos.logback.core.spi.ContextAwareBase; - import static ch.qos.logback.core.CoreConstants.FA_FILENAME_COLLISION_MAP; import static ch.qos.logback.core.CoreConstants.RFA_FILENAME_PATTERN_COLLISION_MAP; @@ -31,6 +26,11 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.spi.ContextAwareBase; + public class ContextUtil extends ContextAwareBase { public ContextUtil(Context context) { @@ -67,10 +67,10 @@ public class ContextUtil extends ContextAwareBase { /** * Add the local host's name as a property */ - public void addHostNameAsProperty() { + public String safelyGetLocalHostName() { try { String localhostName = getLocalHostName(); - context.putProperty(CoreConstants.HOSTNAME_KEY, localhostName); + return localhostName; } catch (UnknownHostException e) { addError("Failed to get local hostname", e); } catch (SocketException e) { @@ -78,6 +78,7 @@ public class ContextUtil extends ContextAwareBase { } catch (SecurityException e) { addError("Failed to get local hostname", e); } + return CoreConstants.UNKNOWN_LOCALHOST; } public void addProperties(Properties props) { diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java index 1248d366e992d64cc57aaea3d037182142e5e640..41bac749eb0fad375616334ac670cdd898e6cb08 100755 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java @@ -26,6 +26,7 @@ import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.Status; import ch.qos.logback.core.util.CoreTestConstants; import ch.qos.logback.core.util.StatusPrinter; @@ -148,13 +149,13 @@ public class PropertyActionTest { } private boolean checkError() { - Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); + Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); ErrorStatus es = (ErrorStatus) it.next(); return PropertyAction.INVALID_ATTRIBUTES.equals(es.getMessage()); } private boolean checkFileErrors() { - Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); + Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); ErrorStatus es1 = (ErrorStatus) it.next(); return "Could not find properties file [toto].".equals(es1.getMessage()); } diff --git a/logback-site/src/site/pages/manual/configuration.html b/logback-site/src/site/pages/manual/configuration.html index 84ba197a38b42c40835124d5d3d9efcb1ec07866..e28550f4e5b66c0be351dd241f9eb639b2d0e285 100755 --- a/logback-site/src/site/pages/manual/configuration.html +++ b/logback-site/src/site/pages/manual/configuration.html @@ -1512,7 +1512,12 @@ import ch.qos.logback.classic.LoggerContext;

As they often come in handy, the HOSTNAME and CONTEXT_NAME - variables are automatically defined and have context scope.

+ variables are automatically defined and have context scope. Given + that in some environments it may take some time to compute the + hostname, its value is computed lazily (only when needed). Moreover, + HOSTNAME can be set from within the configuration directly. +

Defining variables

diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 3501ad94fdcff5aaec8035c8e6f93ebc5179af3e..3371f0ad15251991cb37371a6d6459a95ab58c49 100755 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -51,8 +51,15 @@ and Mark Elliot for hunting down this bug.

-

Joran now supports external XML entities. This feature was +

As it may be time consuming in certain environments, the + HOSTNAME property is now computed lazily. This optimization requested in LOGBACK-1221 by + Eugene Petrenko. +

+ +

Joran now + supports external XML entities. This feature was requested in 1091.