From 8e5436fcadac897d33aef3b0874cb326ebe32659 Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Wed, 10 Jun 2015 15:17:29 +0100 Subject: [PATCH] [feature] Added support for properties interpolation of log4j config location --- .../logging/log4j/core/lookup/Interpolator.java | 1 + .../logging/log4j/core/lookup/Log4jLookup.java | 79 ++++++++++++++++++++++ .../logging/log4j/core/lookup/Log4jLookupTest.java | 70 +++++++++++++++++++ .../core/lookup/Log4jLookupWindowsPathTest.java | 71 +++++++++++++++++++ .../core/lookup/Log4jLookupWithSpacesTest.java | 71 +++++++++++++++++++ src/site/xdoc/manual/configuration.xml.vm | 4 ++ 6 files changed, 296 insertions(+) create mode 100644 log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Log4jLookup.java create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupTest.java create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWindowsPathTest.java create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWithSpacesTest.java diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java index de0a466..ec2fbc0 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java @@ -82,6 +82,7 @@ public class Interpolator extends AbstractLookup { public Interpolator(final Map properties) { this.defaultLookup = new MapLookup(properties == null ? new HashMap() : properties); // TODO: this ought to use the PluginManager + lookups.put("log4j", new Log4jLookup()); lookups.put("sys", new SystemPropertiesLookup()); lookups.put("env", new EnvironmentLookup()); lookups.put("main", MainMapLookup.MAIN_SINGLETON); diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Log4jLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Log4jLookup.java new file mode 100644 index 0000000..dc71f77 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Log4jLookup.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 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.logging.log4j.core.lookup; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.impl.ContextAnchor; +import org.apache.logging.log4j.status.StatusLogger; + +/** + * Lookup properties of Log4j + */ +@Plugin(name = "log4j", category = StrLookup.CATEGORY) +public class Log4jLookup extends AbstractLookup { + + private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger(); + + public final static String KEY_CONFIG_LOCATION = "configLocation"; + public final static String KEY_CONFIG_PARENT_LOCATION = "configParentLocation"; + + @Override + public String lookup(final LogEvent event, final String key) { + final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get(); + if(ctx == null) { + return null; + } + + switch (key) { + case KEY_CONFIG_LOCATION: + return asPath(ctx.getConfigLocation()); + + case KEY_CONFIG_PARENT_LOCATION: + try { + return asPath(getParent(ctx.getConfigLocation())); + } catch(final URISyntaxException use) { + LOGGER.error(use); + return null; + } + + default: + return null; + } + } + + private static URI getParent(final URI uri) throws URISyntaxException { + final String s = uri.toString(); + final int offset = s.lastIndexOf('/'); + if(offset > -1) { + return new URI(s.substring(0, offset)); + } else { + return new URI("../"); + } + } + + private static String asPath(final URI uri) { + if(uri.getScheme() == null || uri.getScheme().equals("file")) { + return uri.getPath(); + } else { + return uri.toString(); + } + } +} diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupTest.java new file mode 100644 index 0000000..a2ddadb --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 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.logging.log4j.core.lookup; + +import java.net.URI; +import java.net.URISyntaxException; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.impl.ContextAnchor; +import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_LOCATION; +import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_PARENT_LOCATION; +import org.junit.Test; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.junit.After; +import static org.junit.Assert.assertEquals; +import org.junit.Before; + +/** + * + */ +public class Log4jLookupTest { + + private LoggerContext mockCtx = null; + + @Before + public void setup() throws URISyntaxException { + this.mockCtx = EasyMock.createMock(LoggerContext.class); + expect(mockCtx.getConfigLocation()).andReturn(new URI("/a/b/c/d/e/log4j2.xml")); + ContextAnchor.THREAD_CONTEXT.set(mockCtx); + + replay(mockCtx); + } + + @After + public void cleanup() { + verify(mockCtx); + + ContextAnchor.THREAD_CONTEXT.set(null); + this.mockCtx = null; + } + + @Test + public void lookupConfigLocation() { + final StrLookup log4jLookup = new Log4jLookup(); + final String value = log4jLookup.lookup(KEY_CONFIG_LOCATION); + assertEquals("/a/b/c/d/e/log4j2.xml", value); + } + + @Test + public void lookupConfigParentLocation() { + final StrLookup log4jLookup = new Log4jLookup(); + final String value = log4jLookup.lookup(KEY_CONFIG_PARENT_LOCATION); + assertEquals("/a/b/c/d/e", value); + } +} diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWindowsPathTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWindowsPathTest.java new file mode 100644 index 0000000..54dd36c --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWindowsPathTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 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.logging.log4j.core.lookup; + +import java.io.File; +import java.net.URISyntaxException; + +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.impl.ContextAnchor; +import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_LOCATION; +import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_PARENT_LOCATION; +import org.junit.Test; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.junit.After; +import static org.junit.Assert.assertEquals; +import org.junit.Before; + +/** + * + */ +public class Log4jLookupWindowsPathTest { + + private LoggerContext mockCtx = null; + + @Before + public void setup() throws URISyntaxException { + this.mockCtx = EasyMock.createMock(LoggerContext.class); + expect(mockCtx.getConfigLocation()).andReturn(new File("/a a/b b/c c/d d/e e/log4j2 file.xml").toURI()); + ContextAnchor.THREAD_CONTEXT.set(mockCtx); + + replay(mockCtx); + } + + @After + public void cleanup() { + verify(mockCtx); + + ContextAnchor.THREAD_CONTEXT.set(null); + this.mockCtx = null; + } + + @Test + public void lookupConfigLocation_withSpaces() { + final StrLookup log4jLookup = new Log4jLookup(); + final String value = log4jLookup.lookup(KEY_CONFIG_LOCATION); + assertEquals(new File("/a a/b b/c c/d d/e e/log4j2 file.xml").toURI().getPath(), value); + } + + @Test + public void lookupConfigParentLocation_withSpaces() { + final StrLookup log4jLookup = new Log4jLookup(); + final String value = log4jLookup.lookup(KEY_CONFIG_PARENT_LOCATION); + assertEquals(new File("/a a/b b/c c/d d/e e").toURI().getPath(), value); + } +} diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWithSpacesTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWithSpacesTest.java new file mode 100644 index 0000000..e34d4a6 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/Log4jLookupWithSpacesTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 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.logging.log4j.core.lookup; + +import java.io.File; +import java.net.URISyntaxException; + +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.impl.ContextAnchor; +import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_LOCATION; +import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_PARENT_LOCATION; +import org.junit.Test; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.junit.After; +import static org.junit.Assert.assertEquals; +import org.junit.Before; + +/** + * + */ +public class Log4jLookupWithSpacesTest { + + private LoggerContext mockCtx = null; + + @Before + public void setup() throws URISyntaxException { + this.mockCtx = EasyMock.createMock(LoggerContext.class); + expect(mockCtx.getConfigLocation()).andReturn(new File("/a a/b b/c c/d d/e e/log4j2 file.xml").toURI()); + ContextAnchor.THREAD_CONTEXT.set(mockCtx); + + replay(mockCtx); + } + + @After + public void cleanup() { + verify(mockCtx); + + ContextAnchor.THREAD_CONTEXT.set(null); + this.mockCtx = null; + } + + @Test + public void lookupConfigLocation_withSpaces() { + final StrLookup log4jLookup = new Log4jLookup(); + final String value = log4jLookup.lookup(KEY_CONFIG_LOCATION); + assertEquals(new File("/a a/b b/c c/d d/e e/log4j2 file.xml").toURI().getPath(), value); + } + + @Test + public void lookupConfigParentLocation_withSpaces() { + final StrLookup log4jLookup = new Log4jLookup(); + final String value = log4jLookup.lookup(KEY_CONFIG_PARENT_LOCATION); + assertEquals(new File("/a a/b b/c c/d d/e e").toURI().getPath(), value); + } +} diff --git a/src/site/xdoc/manual/configuration.xml.vm b/src/site/xdoc/manual/configuration.xml.vm index 8015054..9e77ac0 100644 --- a/src/site/xdoc/manual/configuration.xml.vm +++ b/src/site/xdoc/manual/configuration.xml.vm @@ -904,6 +904,10 @@ public class Bar { Not available on Android. + log4j + Log4j configuration properties. Currently provides ${log4j:configLocation} and ${log4j:configParentLocation} which provide the absolute path to the log4j configuration file and its parent folder respectively. + + main A value set with MapLookup.setMainArguments(String[]) -- 2.2.1