You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2019/06/11 02:50:17 UTC
[logging-log4j2] branch LOG4J2-2621 updated: LOG4J2-2621 - Provide
compatibility for Log4j 2 2.x plugins
This is an automated email from the ASF dual-hosted git repository.
rgoers pushed a commit to branch LOG4J2-2621
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/LOG4J2-2621 by this push:
new 84fd87a LOG4J2-2621 - Provide compatibility for Log4j 2 2.x plugins
84fd87a is described below
commit 84fd87acdb874711887178c7b000a7f835ede99a
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Mon Jun 10 19:50:06 2019 -0700
LOG4J2-2621 - Provide compatibility for Log4j 2 2.x plugins
---
log4j-core/pom.xml | 13 ++
.../log4j/core/config/plugins/PluginAliases.java | 31 +++
.../log4j/core/config/plugins/PluginAttribute.java | 101 ++++++++++
.../config}/plugins/PluginBuilderAttribute.java | 12 +-
.../core/config/plugins/PluginBuilderFactory.java | 31 +++
.../log4j/core/config/plugins/PluginElement.java | 38 ++++
.../log4j/core/config/plugins/PluginFactory.java | 34 ++++
.../log4j/core/config/plugins/PluginNode.java | 34 ++++
.../log4j/core/config/plugins/PluginValue.java | 39 ++++
.../core/config/plugins/util/PluginBuilder.java | 51 ++++-
.../plugins/visitors/PluginAttributeVisitor.java | 80 ++++++++
.../visitors/PluginBuilderAttributeVisitor.java | 51 +++++
.../plugins/visitors/PluginElementVisitor.java | 113 +++++++++++
.../config/plugins/visitors/PluginNodeVisitor.java | 44 +++++
.../plugins/visitors/PluginValueVisitor.java | 57 ++++++
.../core/time/internal/format/FastDateFormat.java | 14 ++
.../apache/logging/log4j/core/util/Builder.java | 46 +++++
.../log4j/core/util/datetime/FastDateFormat.java | 213 +++++++++++++++++++++
.../core/config/plugins/LegacyPluginTest.java | 62 ++++++
log4j-core/src/test/resources/legacy-plugins.xml | 36 ++++
.../log4j/plugins/PluginBuilderAttribute.java | 2 +-
.../plugins/visitors/AbstractPluginVisitor.java | 1 -
22 files changed, 1084 insertions(+), 19 deletions(-)
diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index 4ac43c1..d790b1d 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -31,6 +31,7 @@
<log4jParentDir>${basedir}/..</log4jParentDir>
<docLabel>Core Documentation</docLabel>
<projectDir>/core</projectDir>
+ <log4j2-logstash-layout.version>0.18</log4j2-logstash-layout.version>
</properties>
<dependencies>
<!-- Naturally, all implementations require the log4j-api JAR -->
@@ -311,6 +312,18 @@
<artifactId>HdrHistogram</artifactId>
<scope>test</scope>
</dependency>
+ <!-- For testing log4j 2 2.x plugins -->
+ <dependency>
+ <groupId>com.vlkan.log4j2</groupId>
+ <artifactId>log4j2-logstash-layout</artifactId>
+ <version>${log4j2-logstash-layout.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.ivandzf</groupId>
+ <artifactId>log4j2-custom-layout</artifactId>
+ <version>1.1.0</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java
new file mode 100644
index 0000000..2b06df6
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import java.lang.annotation.*;
+
+/**
+ * Identifies a list of aliases for a Plugin, PluginAttribute, or PluginBuilderAttribute.
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.TYPE, ElementType.FIELD})
+public @interface PluginAliases {
+
+ String[] value();
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java
new file mode 100644
index 0000000..03e78d8
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import org.apache.logging.log4j.plugins.PluginVisitorStrategy;
+import org.apache.logging.log4j.core.config.plugins.visitors.PluginAttributeVisitor;
+import org.apache.logging.log4j.util.Strings;
+
+import java.lang.annotation.*;
+
+/**
+ * Identifies a Plugin Attribute and its default value. Note that only one of the defaultFoo attributes will be
+ * used based on the type this annotation is attached to. Thus, for primitive types, the default<i>Type</i>
+ * attribute will be used for some <i>Type</i>. However, for more complex types (including enums), the default
+ * string value is used instead and should correspond to the string that would correctly convert to the appropriate
+ * enum value using {@link Enum#valueOf(Class, String) Enum.valueOf}.
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@PluginVisitorStrategy(PluginAttributeVisitor.class)
+public @interface PluginAttribute {
+
+ /**
+ * Specifies the default boolean value to use.
+ */
+ boolean defaultBoolean() default false;
+
+ /**
+ * Specifies the default byte value to use.
+ */
+ byte defaultByte() default 0;
+
+ /**
+ * Specifies the default byte value to use.
+ */
+ char defaultChar() default 0;
+
+ /**
+ * Specifies the default {@link Class} value to use.
+ */
+ Class<?> defaultClass() default Object.class;
+
+ /**
+ * Specifies the default double floating point value to use.
+ */
+ double defaultDouble() default 0.0d;
+
+ /**
+ * Specifies the default floating point value to use.
+ */
+ float defaultFloat() default 0.0f;
+
+ /**
+ * Specifies the default integer value to use.
+ */
+ int defaultInt() default 0;
+
+ /**
+ * Specifies the default long value to use.
+ */
+ long defaultLong() default 0L;
+
+ /**
+ * Specifies the default long value to use.
+ */
+ short defaultShort() default 0;
+
+ /**
+ * Specifies the default value this attribute should use if none is provided or if the provided value is invalid.
+ */
+ String defaultString() default Strings.EMPTY;
+
+ // TODO: could we allow a blank value and infer the attribute name through reflection?
+ /**
+ * Specifies the name of the attribute (case-insensitive) this annotation corresponds to.
+ */
+ String value();
+
+ /**
+ * Indicates that this attribute is a sensitive one that shouldn't be logged directly. Such attributes will instead
+ * be output as a hashed value.
+ */
+ boolean sensitive() default false;
+
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java
similarity index 82%
copy from log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java
copy to log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java
index c7fce2f..e34369f 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java
@@ -15,19 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.plugins;
+package org.apache.logging.log4j.core.config.plugins;
-import org.apache.logging.log4j.plugins.visitors.PluginBuilderAttributeVisitor;
+import org.apache.logging.log4j.plugins.PluginVisitorStrategy;
+import org.apache.logging.log4j.core.config.plugins.visitors.PluginBuilderAttributeVisitor;
import org.apache.logging.log4j.util.Strings;
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
/**
* Marks a field as a Plugin Attribute.
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderFactory.java
new file mode 100644
index 0000000..0ea7221
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderFactory.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import java.lang.annotation.*;
+
+/**
+ * Marks a method as a factory for custom Plugin builders.
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface PluginBuilderFactory {
+ // empty
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java
new file mode 100644
index 0000000..9c1156b
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import org.apache.logging.log4j.core.config.plugins.visitors.PluginElementVisitor;
+import org.apache.logging.log4j.plugins.PluginVisitorStrategy;
+
+import java.lang.annotation.*;
+
+/**
+ * Identifies a parameter as a Plugin and corresponds with an XML element (or equivalent) in configuration files.
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@PluginVisitorStrategy(PluginElementVisitor.class)
+public @interface PluginElement {
+
+ /**
+ * Identifies the case-insensitive element name (or attribute name) this corresponds with in a configuration file.
+ */
+ String value();
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginFactory.java
new file mode 100644
index 0000000..2e25631
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import java.lang.annotation.*;
+
+/**
+ * Identifies a Method as the factory to create the plugin. This annotation should only be used on a {@code static}
+ * method, and its parameters should be annotated with the appropriate Plugin annotations.
+ * <p>
+ * There can only be one factory method per class.
+ * </p>
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface PluginFactory {
+ // empty
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java
new file mode 100644
index 0000000..b359253
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import org.apache.logging.log4j.core.config.plugins.visitors.PluginNodeVisitor;
+import org.apache.logging.log4j.plugins.PluginVisitorStrategy;
+
+import java.lang.annotation.*;
+
+/**
+ * Identifies a Plugin configuration Node.
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@PluginVisitorStrategy(PluginNodeVisitor.class)
+public @interface PluginNode {
+ // empty
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java
new file mode 100644
index 0000000..4b12c77
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import org.apache.logging.log4j.core.config.plugins.visitors.PluginValueVisitor;
+import org.apache.logging.log4j.plugins.PluginVisitorStrategy;
+
+
+import java.lang.annotation.*;
+
+/**
+ * Identifies a parameter as a value. These correspond with property values generally, but are meant as values to be
+ * used as a placeholder value somewhere.
+ *
+ * @see org.apache.logging.log4j.core.config.PropertiesPlugin
+ * @deprecated Exists for compatibility with Log4j 2 2.x plugins. Not used for Log4j 2 3.x plugins.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@PluginVisitorStrategy(PluginValueVisitor.class)
+public @interface PluginValue {
+
+ String value();
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
index 5982af4..e05523a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
@@ -27,6 +27,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import org.apache.logging.log4j.Logger;
@@ -34,12 +36,11 @@ import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationException;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
-import org.apache.logging.log4j.plugins.util.Builder;
-import org.apache.logging.log4j.util.ReflectionUtil;
import org.apache.logging.log4j.plugins.Node;
import org.apache.logging.log4j.plugins.PluginAliases;
import org.apache.logging.log4j.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.plugins.PluginFactory;
+import org.apache.logging.log4j.plugins.util.Builder;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
@@ -47,6 +48,7 @@ import org.apache.logging.log4j.plugins.validation.ConstraintValidators;
import org.apache.logging.log4j.plugins.visitors.PluginVisitor;
import org.apache.logging.log4j.plugins.visitors.PluginVisitors;
import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.ReflectionUtil;
import org.apache.logging.log4j.util.StringBuilders;
/**
@@ -64,6 +66,7 @@ public class PluginBuilder implements Builder<Object> {
private Node node;
private LogEvent event;
private Substitutor substitutor;
+ private ConcurrentMap<String, Boolean> aliases = new ConcurrentHashMap<>();
/**
* Constructs a PluginBuilder for a given PluginType.
@@ -160,23 +163,30 @@ public class PluginBuilder implements Builder<Object> {
TypeUtil.isAssignable(Builder.class, method.getReturnType())) {
ReflectionUtil.makeAccessible(method);
return (Builder<?>) method.invoke(null);
+ } else if (method.isAnnotationPresent(org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory.class) &&
+ Modifier.isStatic(method.getModifiers()) &&
+ TypeUtil.isAssignable(org.apache.logging.log4j.core.util.Builder.class, method.getReturnType())) {
+ ReflectionUtil.makeAccessible(method);
+ return new BuilderWrapper((org.apache.logging.log4j.core.util.Builder<?>) method.invoke(null));
}
}
return null;
}
private void injectFields(final Builder<?> builder) throws IllegalAccessException {
- final List<Field> fields = TypeUtil.getAllDeclaredFields(builder.getClass());
+ final Object target = builder instanceof BuilderWrapper ? ((BuilderWrapper) builder).getBuilder() : builder;
+ final List<Field> fields = TypeUtil.getAllDeclaredFields(target.getClass());
AccessibleObject.setAccessible(fields.toArray(new Field[] {}), true);
final StringBuilder log = new StringBuilder();
boolean invalid = false;
StringBuilder reason = new StringBuilder();
for (final Field field : fields) {
- log.append(log.length() == 0 ? simpleName(builder) + "(" : ", ");
+ log.append(log.length() == 0 ? simpleName(target) + "(" : ", ");
final Annotation[] annotations = field.getDeclaredAnnotations();
final String[] aliases = extractPluginAliases(annotations);
- for (final Annotation a : annotations) {
- if (a instanceof PluginAliases) {
+ for (Annotation a : annotations) {
+ if (a instanceof PluginAliases ||
+ a instanceof org.apache.logging.log4j.core.config.plugins.PluginAliases) {
continue; // already processed
}
final PluginVisitor<? extends Annotation, Configuration> visitor =
@@ -189,13 +199,13 @@ public class PluginBuilder implements Builder<Object> {
.visit(configuration, node, substitutor, log);
// don't overwrite default values if the visitor gives us no value to inject
if (value != null) {
- field.set(builder, value);
+ field.set(target, value);
}
}
}
final Collection<ConstraintValidator<?>> validators =
ConstraintValidators.findValidators(annotations);
- final Object value = field.get(builder);
+ final Object value = field.get(target);
for (final ConstraintValidator<?> validator : validators) {
if (!validator.isValid(field.getName(), value)) {
invalid = true;
@@ -233,7 +243,8 @@ public class PluginBuilder implements Builder<Object> {
private static Method findFactoryMethod(final Class<?> clazz) {
for (final Method method : clazz.getDeclaredMethods()) {
- if (method.isAnnotationPresent(PluginFactory.class) &&
+ if ((method.isAnnotationPresent(PluginFactory.class) ||
+ method.isAnnotationPresent(org.apache.logging.log4j.core.config.plugins.PluginFactory.class)) &&
Modifier.isStatic(method.getModifiers())) {
ReflectionUtil.makeAccessible(method);
return method;
@@ -252,11 +263,13 @@ public class PluginBuilder implements Builder<Object> {
log.append(log.length() == 0 ? factory.getName() + "(" : ", ");
final String[] aliases = extractPluginAliases(annotations[i]);
for (final Annotation a : annotations[i]) {
- if (a instanceof PluginAliases) {
+ if (a instanceof PluginAliases ||
+ a instanceof org.apache.logging.log4j.core.config.plugins.PluginAliases) {
continue; // already processed
}
final PluginVisitor<? extends Annotation, Configuration> visitor = PluginVisitors.findVisitor(
a.annotationType());
+
if (visitor != null) {
final Object value = visitor.setAliases(aliases)
.setAnnotation(a)
@@ -294,6 +307,8 @@ public class PluginBuilder implements Builder<Object> {
for (final Annotation a : parmTypes) {
if (a instanceof PluginAliases) {
aliases = ((PluginAliases) a).value();
+ } else if (a instanceof org.apache.logging.log4j.core.config.plugins.PluginAliases) {
+ aliases = ((org.apache.logging.log4j.core.config.plugins.PluginAliases) a).value();
}
}
return aliases;
@@ -346,4 +361,20 @@ public class PluginBuilder implements Builder<Object> {
return strSubstitutor.replace(event, str);
}
}
+
+ public static class BuilderWrapper<T> implements Builder<T> {
+ private final org.apache.logging.log4j.core.util.Builder<T> builder;
+
+ BuilderWrapper(org.apache.logging.log4j.core.util.Builder<T> builder) {
+ this.builder = builder;
+ }
+
+ public T build() {
+ return builder.build();
+ }
+
+ org.apache.logging.log4j.core.util.Builder<T> getBuilder() {
+ return builder;
+ }
+ }
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java
new file mode 100644
index 0000000..bf3da4f
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins.visitors;
+
+import org.apache.logging.log4j.plugins.Node;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.plugins.visitors.AbstractPluginVisitor;
+import org.apache.logging.log4j.util.NameUtil;
+import org.apache.logging.log4j.util.StringBuilders;
+
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * @deprecated. Provided to support legacy plugins.
+ */
+public class PluginAttributeVisitor extends AbstractPluginVisitor<PluginAttribute, Object> {
+ public PluginAttributeVisitor() {
+ super(PluginAttribute.class);
+ }
+
+ @Override
+ public Object visit(final Object unused, final Node node, final Function<String, String> substitutor,
+ final StringBuilder log) {
+ final String name = this.annotation.value();
+ final Map<String, String> attributes = node.getAttributes();
+ final String rawValue = removeAttributeValue(attributes, name, this.aliases);
+ final String replacedValue = substitutor.apply(rawValue);
+ final Object defaultValue = findDefaultValue(substitutor);
+ final Object value = convert(replacedValue, defaultValue);
+ final Object debugValue = this.annotation.sensitive() ? NameUtil.md5(value + this.getClass().getName()) : value;
+ StringBuilders.appendKeyDqValue(log, name, debugValue);
+ return value;
+ }
+
+ private Object findDefaultValue(Function<String, String> substitutor) {
+ if (this.conversionType == int.class || this.conversionType == Integer.class) {
+ return this.annotation.defaultInt();
+ }
+ if (this.conversionType == long.class || this.conversionType == Long.class) {
+ return this.annotation.defaultLong();
+ }
+ if (this.conversionType == boolean.class || this.conversionType == Boolean.class) {
+ return this.annotation.defaultBoolean();
+ }
+ if (this.conversionType == float.class || this.conversionType == Float.class) {
+ return this.annotation.defaultFloat();
+ }
+ if (this.conversionType == double.class || this.conversionType == Double.class) {
+ return this.annotation.defaultDouble();
+ }
+ if (this.conversionType == byte.class || this.conversionType == Byte.class) {
+ return this.annotation.defaultByte();
+ }
+ if (this.conversionType == char.class || this.conversionType == Character.class) {
+ return this.annotation.defaultChar();
+ }
+ if (this.conversionType == short.class || this.conversionType == Short.class) {
+ return this.annotation.defaultShort();
+ }
+ if (this.conversionType == Class.class) {
+ return this.annotation.defaultClass();
+ }
+ return substitutor.apply(this.annotation.defaultString());
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java
new file mode 100644
index 0000000..7c5ed21
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins.visitors;
+
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.plugins.Node;
+import org.apache.logging.log4j.plugins.visitors.AbstractPluginVisitor;
+import org.apache.logging.log4j.util.NameUtil;
+import org.apache.logging.log4j.util.StringBuilders;
+
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * @deprecated Provided for support for PluginBuilderAttribute.
+ */
+public class PluginBuilderAttributeVisitor extends AbstractPluginVisitor<PluginBuilderAttribute, Object> {
+
+ public PluginBuilderAttributeVisitor() {
+ super(PluginBuilderAttribute.class);
+ }
+
+ @Override
+ public Object visit(final Object unused, final Node node, final Function<String, String> substitutor,
+ final StringBuilder log) {
+ final String overridden = this.annotation.value();
+ final String name = overridden.isEmpty() ? this.member.getName() : overridden;
+ final Map<String, String> attributes = node.getAttributes();
+ final String rawValue = removeAttributeValue(attributes, name, this.aliases);
+ final String replacedValue = substitutor.apply(rawValue);
+ final Object value = convert(replacedValue, null);
+ final Object debugValue = this.annotation.sensitive() ? NameUtil.md5(value + this.getClass().getName()) : value;
+ StringBuilders.appendKeyDqValue(log, name, debugValue);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java
new file mode 100644
index 0000000..a5380b8
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins.visitors;
+
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.plugins.Node;
+import org.apache.logging.log4j.plugins.util.PluginType;
+import org.apache.logging.log4j.plugins.visitors.AbstractPluginVisitor;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * @deprecated. Provided to support legacy plugins.
+ */
+public class PluginElementVisitor extends AbstractPluginVisitor<PluginElement, Object> {
+ public PluginElementVisitor() {
+ super(PluginElement.class);
+ }
+
+ @Override
+ public Object visit(final Object unused, final Node node, final Function<String, String> substitutor,
+ final StringBuilder log) {
+ final String name = this.annotation.value();
+ if (this.conversionType.isArray()) {
+ setConversionType(this.conversionType.getComponentType());
+ final List<Object> values = new ArrayList<>();
+ final Collection<Node> used = new ArrayList<>();
+ log.append("={");
+ boolean first = true;
+ for (final Node child : node.getChildren()) {
+ final PluginType<?> childType = child.getType();
+ if (name.equalsIgnoreCase(childType.getElementName()) ||
+ this.conversionType.isAssignableFrom(childType.getPluginClass())) {
+ if (!first) {
+ log.append(", ");
+ }
+ first = false;
+ used.add(child);
+ final Object childObject = child.getObject();
+ if (childObject == null) {
+ LOGGER.error("Null object returned for {} in {}.", child.getName(), node.getName());
+ continue;
+ }
+ if (childObject.getClass().isArray()) {
+ log.append(Arrays.toString((Object[]) childObject)).append('}');
+ node.getChildren().removeAll(used);
+ return childObject;
+ }
+ log.append(child.toString());
+ values.add(childObject);
+ }
+ }
+ log.append('}');
+ // note that we need to return an empty array instead of null if the types are correct
+ if (!values.isEmpty() && !this.conversionType.isAssignableFrom(values.get(0).getClass())) {
+ LOGGER.error("Attempted to assign attribute {} to list of type {} which is incompatible with {}.",
+ name, values.get(0).getClass(), this.conversionType);
+ return null;
+ }
+ node.getChildren().removeAll(used);
+ // we need to use reflection here because values.toArray() will cause type errors at runtime
+ final Object[] array = (Object[]) Array.newInstance(this.conversionType, values.size());
+ for (int i = 0; i < array.length; i++) {
+ array[i] = values.get(i);
+ }
+ return array;
+ }
+ final Node namedNode = findNamedNode(name, node.getChildren());
+ if (namedNode == null) {
+ log.append(name).append("=null");
+ return null;
+ }
+ log.append(namedNode.getName()).append('(').append(namedNode.toString()).append(')');
+ node.getChildren().remove(namedNode);
+ return namedNode.getObject();
+ }
+
+ private Node findNamedNode(final String name, final Iterable<Node> children) {
+ for (final Node child : children) {
+ final PluginType<?> childType = child.getType();
+ if (childType == null) {
+ //System.out.println();
+ }
+ if (name.equalsIgnoreCase(childType.getElementName()) ||
+ this.conversionType.isAssignableFrom(childType.getPluginClass())) {
+ // FIXME: check child.getObject() for null?
+ // doing so would be more consistent with the array version
+ return child;
+ }
+ }
+ return null;
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginNodeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginNodeVisitor.java
new file mode 100644
index 0000000..5e651b1
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginNodeVisitor.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins.visitors;
+
+import org.apache.logging.log4j.core.config.plugins.PluginNode;
+import org.apache.logging.log4j.plugins.Node;
+import org.apache.logging.log4j.plugins.visitors.AbstractPluginVisitor;
+
+import java.util.function.Function;
+
+/**
+ * @deprecated. Provided to support legacy plugins.
+ */
+public class PluginNodeVisitor extends AbstractPluginVisitor<PluginNode, Object> {
+ public PluginNodeVisitor() {
+ super(PluginNode.class);
+ }
+
+ @Override
+ public Object visit(final Object unused, final Node node, final Function<String, String> substitutor,
+ final StringBuilder log) {
+ if (this.conversionType.isInstance(node)) {
+ log.append("Node=").append(node.getName());
+ return node;
+ }
+ LOGGER.warn("Variable annotated with @PluginNode is not compatible with the type {}.", node.getClass());
+ return null;
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginValueVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginValueVisitor.java
new file mode 100644
index 0000000..deee939
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginValueVisitor.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins.visitors;
+
+import org.apache.logging.log4j.core.config.plugins.PluginValue;
+import org.apache.logging.log4j.plugins.Node;
+import org.apache.logging.log4j.plugins.visitors.AbstractPluginVisitor;
+import org.apache.logging.log4j.util.StringBuilders;
+import org.apache.logging.log4j.util.Strings;
+
+import java.util.function.Function;
+
+/**
+ * @deprecated. Provided to support legacy plugins.
+ */
+public class PluginValueVisitor extends AbstractPluginVisitor<PluginValue, Object> {
+ public PluginValueVisitor() {
+ super(PluginValue.class);
+ }
+
+ @Override
+ public Object visit(final Object unused, final Node node, final Function<String, String> substitutor,
+ final StringBuilder log) {
+ final String name = this.annotation.value();
+ final String elementValue = node.getValue();
+ final String attributeValue = node.getAttributes().get("value");
+ String rawValue = null; // if neither is specified, return null (LOG4J2-1313)
+ if (Strings.isNotEmpty(elementValue)) {
+ if (Strings.isNotEmpty(attributeValue)) {
+ LOGGER.error("Configuration contains {} with both attribute value ({}) AND element" +
+ " value ({}). Please specify only one value. Using the element value.",
+ node.getName(), attributeValue, elementValue);
+ }
+ rawValue = elementValue;
+ } else {
+ rawValue = removeAttributeValue(node.getAttributes(), "value");
+ }
+ final String value = substitutor.apply(rawValue);
+ StringBuilders.appendKeyDqValue(log, name, value);
+ return value;
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/format/FastDateFormat.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/format/FastDateFormat.java
index c452a86..5685884 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/format/FastDateFormat.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/format/FastDateFormat.java
@@ -372,6 +372,20 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
return cache.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale);
}
+ /**
+ * <p>Constructs a new FastDateFormat.</p>
+ *
+ * @param pattern {@link java.text.SimpleDateFormat} compatible pattern
+ * @param timeZone non-null time zone to use
+ * @param locale non-null locale to use
+ * @param centuryStart The start of the 100 year period to use as the "default century" for 2 digit year parsing. If centuryStart is null, defaults to now - 80 years
+ * @throws NullPointerException if pattern, timeZone, or locale is null.
+ * @since 3.0
+ */
+ public static FastDateFormat getDateTimeInstance(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) {
+ return new FastDateFormat(pattern, timeZone, locale, centuryStart);
+ }
+
// Constructor
//-----------------------------------------------------------------------
/**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Builder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Builder.java
new file mode 100644
index 0000000..9acc9d5
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Builder.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.util;
+
+/**
+ * A type of builder that can be used to configure and create a instances using a Java DSL instead of
+ * through a configuration file. These builders are primarily useful for internal code and unit tests, but they can
+ * technically be used as a verbose alternative to configuration files.
+ *
+ * <p>
+ * When creating <em>plugin</em> builders, it is customary to create the builder class as a public static inner class
+ * called {@code Builder}. For instance, the builder class for
+ * {@link org.apache.logging.log4j.core.layout.PatternLayout PatternLayout} would be
+ * {@code PatternLayout.Builder}.
+ * </p>
+ *
+ * @param <T> This builder creates instances of this class.
+ * @deprecated Present only for compatibility with Log4j 2 2.x plugins. Use Builder from log4j-plugins.
+ */
+public interface Builder<T> {
+
+ /**
+ * Builds the object after all configuration has been set. This will use default values for any
+ * unspecified attributes for the object.
+ *
+ * @return the configured instance.
+ * @throws org.apache.logging.log4j.core.config.ConfigurationException if there was an error building the
+ * object.
+ */
+ T build();
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java
new file mode 100644
index 0000000..691b268
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.util.datetime;
+
+import java.text.FieldPosition;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.logging.log4j.core.time.internal.format.*;
+
+/**
+ *
+ * @deprecated Use {@link org.apache.logging.log4j.core.time.internal.format.FastDateFormat}
+ */
+public class FastDateFormat extends Format implements DateParser, DatePrinter {
+
+ private org.apache.logging.log4j.core.time.internal.format.FastDateFormat formatter = null;
+
+ public static FastDateFormat getInstance() {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getInstance());
+ }
+
+ public static FastDateFormat getInstance(final String pattern) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getInstance(pattern));
+ }
+
+ public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getInstance(pattern, timeZone));
+ }
+
+ public static FastDateFormat getInstance(final String pattern, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getInstance(pattern, locale));
+ }
+
+ public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getInstance(pattern, timeZone, locale));
+ }
+
+ public static FastDateFormat getDateInstance(final int style) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateInstance(style));
+ }
+
+ public static FastDateFormat getDateInstance(final int style, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateInstance(style, locale));
+ }
+
+ public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateInstance(style, timeZone));
+ }
+
+ public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateInstance(style, timeZone, locale));
+ }
+
+ public static FastDateFormat getTimeInstance(final int style) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getTimeInstance(style));
+ }
+
+ public static FastDateFormat getTimeInstance(final int style, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getTimeInstance(style, locale));
+ }
+
+ public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getTimeInstance(style, timeZone));
+ }
+
+ public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getTimeInstance(style, timeZone, locale));
+ }
+
+ public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateTimeInstance(dateStyle, timeStyle));
+ }
+
+ public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateTimeInstance(dateStyle, timeStyle, locale));
+ }
+
+ public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateTimeInstance(dateStyle, timeStyle, timeZone));
+ }
+
+ public static FastDateFormat getDateTimeInstance(
+ final int dateStyle, final int timeStyle, final TimeZone timeZone, final Locale locale) {
+ return new FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale));
+ }
+
+ private FastDateFormat(org.apache.logging.log4j.core.time.internal.format.FastDateFormat formatter) {
+ this.formatter = formatter;
+ }
+
+ protected FastDateFormat(final String pattern, final TimeZone timeZone, final Locale locale) {
+ formatter = org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getInstance(pattern,
+ timeZone, locale);
+ }
+
+ protected FastDateFormat(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) {
+ formatter = org.apache.logging.log4j.core.time.internal.format.FastDateFormat.getDateTimeInstance(pattern,
+ timeZone, locale, centuryStart);
+ }
+
+ @Override
+ public StringBuilder format(final Object obj, final StringBuilder toAppendTo, final FieldPosition pos) {
+ return formatter.format(obj, toAppendTo, pos);
+ }
+
+ @Override
+ public String format(final long millis) {
+ return formatter.format(millis);
+ }
+
+ @Override
+ public String format(final Date date) {
+ return formatter.format(date);
+ }
+
+ @Override
+ public String format(final Calendar calendar) {
+ return formatter.format(calendar);
+ }
+
+ @Override
+ public <B extends Appendable> B format(final long millis, final B buf) {
+ return formatter.format(millis, buf);
+ }
+
+ @Override
+ public <B extends Appendable> B format(final Date date, final B buf) {
+ return formatter.format(date, buf);
+ }
+
+ @Override
+ public <B extends Appendable> B format(final Calendar calendar, final B buf) {
+ return formatter.format(calendar, buf);
+ }
+
+ @Override
+ public Date parse(final String source) throws ParseException {
+ return formatter.parse(source);
+ }
+
+ @Override
+ public Date parse(final String source, final ParsePosition pos) {
+ return formatter.parse(source, pos);
+ }
+
+ @Override
+ public boolean parse(final String source, final ParsePosition pos, final Calendar calendar) {
+ return formatter.parse(source, pos, calendar);
+ }
+
+ @Override
+ public Object parseObject(final String source, final ParsePosition pos) {
+ return formatter.parseObject(source, pos);
+ }
+
+ @Override
+ public String getPattern() {
+ return formatter.getPattern();
+ }
+
+ @Override
+ public TimeZone getTimeZone() {
+ return formatter.getTimeZone();
+ }
+
+ @Override
+ public Locale getLocale() {
+ return formatter.getLocale();
+ }
+
+ public int getMaxLengthEstimate() {
+ return formatter.getMaxLengthEstimate();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof FastDateFormat == false) {
+ return false;
+ }
+ final FastDateFormat other = (FastDateFormat) obj;
+ // no need to check parser, as it has same invariants as printer
+ return formatter.equals(other.formatter);
+ }
+
+ @Override
+ public int hashCode() {
+ return formatter.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return formatter.toString();
+ }
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/plugins/LegacyPluginTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/plugins/LegacyPluginTest.java
new file mode 100644
index 0000000..3aad3c6
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/plugins/LegacyPluginTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.config.plugins;
+
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
+import org.apache.logging.log4j.spi.LoggerContext;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Class Description goes here.
+ */
+public class LegacyPluginTest {
+
+ private static final String CONFIG_FILE = "legacy-plugins.xml";
+
+ @Test
+ public void testLegacy() throws Exception {
+ LoggerContext context = Configurator.initialize("LegacyTest", null, CONFIG_FILE);
+ assertNotNull("No Logger Context", context);
+ Configuration configuration = ((org.apache.logging.log4j.core.LoggerContext) context).getConfiguration();
+ assertNotNull("No Configuration", configuration);
+ assertTrue("Incorrect Configuration class " + configuration.getClass().getName(),
+ configuration instanceof XmlConfiguration);
+ for (Map.Entry<String, Appender> entry : configuration.getAppenders().entrySet()) {
+ if (entry.getKey().equalsIgnoreCase("console")) {
+ Layout layout = entry.getValue().getLayout();
+ assertNotNull("No layout for Console Appender");
+ String name = layout.getClass().getSimpleName();
+ assertTrue("Incorrect Layout class. Expected LogstashLayout, Actual " + name,
+ name.equals("LogstashLayout"));
+ } else if (entry.getKey().equalsIgnoreCase("customConsole")) {
+ Layout layout = entry.getValue().getLayout();
+ assertNotNull("No layout for CustomConsole Appender");
+ String name = layout.getClass().getSimpleName();
+ assertTrue("Incorrect Layout class. Expected CustomConsoleLayout, Actual " + name,
+ name.equals("CustomConsoleLayout"));
+ }
+ }
+ }
+}
diff --git a/log4j-core/src/test/resources/legacy-plugins.xml b/log4j-core/src/test/resources/legacy-plugins.xml
new file mode 100644
index 0000000..725be17
--- /dev/null
+++ b/log4j-core/src/test/resources/legacy-plugins.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<Configuration status="ERROR" name="XMLConfigTest">
+
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <LogstashLayout dateTimeFormatPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZZZ" prettyPrintEnabled="true"
+ stackTraceEnabled="true"/>
+ </Console>
+ <Console name="customConsole">
+ <CustomConsoleLayout/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="trace">
+ <AppenderRef ref="Console"/>
+ </Root>
+ </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java
index c7fce2f..ed22bb9 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginBuilderAttribute.java
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.PARAMETER, ElementType.FIELD})
+@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE})
@PluginVisitorStrategy(PluginBuilderAttributeVisitor.class)
public @interface PluginBuilderAttribute {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visitors/AbstractPluginVisitor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visitors/AbstractPluginVisitor.java
index b98dc09..01e1e66 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visitors/AbstractPluginVisitor.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visitors/AbstractPluginVisitor.java
@@ -26,7 +26,6 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Member;
import java.util.Map;
import java.util.Objects;
-import java.util.function.Function;
/**
* Base class for PluginVisitor implementations. Provides convenience methods as well as all method implementations