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.