You can put a class in an annotation?
On 27 May 2014 10:49, Remko Popma <[email protected]> wrote: > You may want to document that you use String FQCNs on purpose even though > annotations let you use Classes, to make it OSGi-friendly. Otherwise the > next person may refactor this... > > > On Tue, May 27, 2014 at 10:57 PM, <[email protected]> wrote: > >> Author: mattsicker >> Date: Tue May 27 13:57:31 2014 >> New Revision: 1597790 >> >> URL: http://svn.apache.org/r1597790 >> Log: >> Switch from a registry-based strategy to a meta-annotation-based strategy >> for associating visitors to annotations. >> >> - More easily extensible as there is no registry or special file to >> maintain. >> - Still maintains OSGi compatibility with correct ClassLoader usage. >> - Updated PluginVisitor(Builder|s) accordingly to use new algorithm. >> >> Added: >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginVisitorStrategy.java >> (with props) >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitors.java >> - copied, changed from r1597667, >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitorRegistry.java >> Removed: >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitorRegistry.java >> Modified: >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/SensitivePluginAttribute.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java >> >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/package-info.java >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java >> Tue May 27 13:57:31 2014 >> @@ -32,6 +32,7 @@ import java.lang.annotation.Target; >> @Documented >> @Retention(RetentionPolicy.RUNTIME) >> @Target({ElementType.PARAMETER, ElementType.FIELD}) >> >> +@PluginVisitorStrategy("org.apache.logging.log4j.core.config.plugins.visitors.PluginAttributeVisitor") >> public @interface PluginAttribute { >> >> // TODO: could we allow a blank value and infer the attribute name >> through reflection? >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.java >> Tue May 27 13:57:31 2014 >> @@ -29,5 +29,6 @@ import java.lang.annotation.Target; >> @Documented >> @Retention(RetentionPolicy.RUNTIME) >> @Target({ElementType.PARAMETER, ElementType.FIELD}) >> >> +@PluginVisitorStrategy("org.apache.logging.log4j.core.config.plugins.visitors.PluginConfigurationVisitor") >> public @interface PluginConfiguration { >> } >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java >> Tue May 27 13:57:31 2014 >> @@ -28,6 +28,7 @@ import java.lang.annotation.Target; >> @Documented >> @Retention(RetentionPolicy.RUNTIME) >> @Target({ElementType.PARAMETER, ElementType.FIELD}) >> >> +@PluginVisitorStrategy("org.apache.logging.log4j.core.config.plugins.visitors.PluginElementVisitor") >> public @interface PluginElement { >> >> /** >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginNode.java >> Tue May 27 13:57:31 2014 >> @@ -28,5 +28,6 @@ import java.lang.annotation.Target; >> @Documented >> @Retention(RetentionPolicy.RUNTIME) >> @Target({ElementType.PARAMETER, ElementType.FIELD}) >> >> +@PluginVisitorStrategy("org.apache.logging.log4j.core.config.plugins.visitors.PluginNodeVisitor") >> public @interface PluginNode { >> } >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java >> Tue May 27 13:57:31 2014 >> @@ -31,6 +31,7 @@ import java.lang.annotation.Target; >> @Documented >> @Retention(RetentionPolicy.RUNTIME) >> @Target(ElementType.PARAMETER) >> >> +@PluginVisitorStrategy("org.apache.logging.log4j.core.config.plugins.visitors.PluginValueVisitor") >> public @interface PluginValue { >> >> String value(); >> >> Added: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginVisitorStrategy.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginVisitorStrategy.java?rev=1597790&view=auto >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginVisitorStrategy.java >> (added) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginVisitorStrategy.java >> Tue May 27 13:57:31 2014 >> @@ -0,0 +1,40 @@ >> +/* >> + * 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.Documented; >> +import java.lang.annotation.ElementType; >> +import java.lang.annotation.Retention; >> +import java.lang.annotation.RetentionPolicy; >> +import java.lang.annotation.Target; >> + >> +/** >> + * Meta-annotation to denote the class name to use that implements >> + * {@link >> org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitor} for >> the annotated annotation. >> + */ >> +@Documented >> +@Retention(RetentionPolicy.RUNTIME) >> +@Target(ElementType.ANNOTATION_TYPE) >> +public @interface PluginVisitorStrategy { >> + >> + /** >> + * The class name to use that implements {@link >> org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitor} >> + * for the given annotation. >> + */ >> + String value(); >> +} >> >> Propchange: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginVisitorStrategy.java >> >> ------------------------------------------------------------------------------ >> svn:eol-style = native >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/SensitivePluginAttribute.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/SensitivePluginAttribute.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/SensitivePluginAttribute.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/SensitivePluginAttribute.java >> Tue May 27 13:57:31 2014 >> @@ -34,6 +34,7 @@ import java.lang.annotation.Target; >> @Documented >> @Retention(RetentionPolicy.RUNTIME) >> @Target(ElementType.PARAMETER) >> >> +@PluginVisitorStrategy("org.apache.logging.log4j.core.config.plugins.visitors.SensitivePluginAttributeVisitor") >> public @interface SensitivePluginAttribute { >> String value(); >> >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java >> Tue May 27 13:57:31 2014 >> @@ -34,7 +34,7 @@ import org.apache.logging.log4j.core.con >> import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; >> import org.apache.logging.log4j.core.config.plugins.PluginFactory; >> import >> org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitor; >> -import >> org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitorRegistry; >> +import >> org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitors; >> import org.apache.logging.log4j.core.util.Assert; >> import org.apache.logging.log4j.core.util.Builder; >> import org.apache.logging.log4j.status.StatusLogger; >> @@ -164,7 +164,7 @@ public class PluginBuilder<T> implements >> continue; // already processed >> } >> final PluginVisitor<? extends Annotation> visitor = >> - >> PluginVisitorRegistry.findVisitor(a.annotationType()); >> + PluginVisitors.findVisitor(a.annotationType()); >> if (visitor != null) { >> final Object value = visitor.setAliases(aliases) >> .setAnnotation(a) >> @@ -200,7 +200,7 @@ public class PluginBuilder<T> implements >> if (a instanceof PluginAliases) { >> continue; // already processed >> } >> - final PluginVisitor<? extends Annotation> visitor = >> PluginVisitorRegistry.findVisitor( >> + final PluginVisitor<? extends Annotation> visitor = >> PluginVisitors.findVisitor( >> a.annotationType()); >> if (visitor != null) { >> args[i] = visitor.setAliases(aliases) >> >> Copied: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitors.java >> (from r1597667, >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitorRegistry.java) >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitors.java?p2=logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitors.java&p1=logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitorRegistry.java&r1=1597667&r2=1597790&rev=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitorRegistry.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginVisitors.java >> Tue May 27 13:57:31 2014 >> @@ -18,58 +18,24 @@ >> package org.apache.logging.log4j.core.config.plugins.visitors; >> >> import java.lang.annotation.Annotation; >> -import java.util.Map; >> -import java.util.concurrent.ConcurrentHashMap; >> >> import org.apache.logging.log4j.Logger; >> -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; >> -import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; >> -import org.apache.logging.log4j.core.config.plugins.PluginElement; >> -import org.apache.logging.log4j.core.config.plugins.PluginNode; >> -import org.apache.logging.log4j.core.config.plugins.PluginValue; >> -import >> org.apache.logging.log4j.core.config.plugins.SensitivePluginAttribute; >> +import >> org.apache.logging.log4j.core.config.plugins.PluginVisitorStrategy; >> import org.apache.logging.log4j.status.StatusLogger; >> >> /** >> - * Registry for associating Plugin annotations with PluginVisitor >> implementations. >> + * Utility class to locate an appropriate PluginVisitor implementation >> for an annotation. >> */ >> -public final class PluginVisitorRegistry { >> +public final class PluginVisitors { >> >> private static final Logger LOGGER = StatusLogger.getLogger(); >> >> - // map of annotation classes to their corresponding PluginVisitor >> classes >> - // generics are fun! >> - private static final Map<Class<? extends Annotation>, Class<? >> extends PluginVisitor<? extends Annotation>>> REGISTRY; >> - >> - static { >> - // register the default PluginVisitor classes >> - // TODO: this could probably be combined with the usual plugin >> architecture instead >> - REGISTRY = new ConcurrentHashMap<Class<? extends Annotation>, >> Class<? extends PluginVisitor<? extends Annotation>>>(); >> - registerVisitor(PluginAttribute.class, >> PluginAttributeVisitor.class); >> - registerVisitor(SensitivePluginAttribute.class, >> SensitivePluginAttributeVisitor.class); >> - registerVisitor(PluginConfiguration.class, >> PluginConfigurationVisitor.class); >> - registerVisitor(PluginNode.class, PluginNodeVisitor.class); >> - registerVisitor(PluginValue.class, PluginValueVisitor.class); >> - registerVisitor(PluginElement.class, PluginElementVisitor.class); >> - } >> - >> - private PluginVisitorRegistry() { >> - } >> - >> - /** >> - * Registers a PluginVisitor class associated to a specific >> annotation. >> - * >> - * @param annotation the Plugin annotation to associate with. >> - * @param helper the PluginVisitor class to use for the >> annotation. >> - * @param <A> the Plugin annotation type. >> - */ >> - public static <A extends Annotation> void registerVisitor(final >> Class<A> annotation, >> - final >> Class<? extends PluginVisitor<A>> helper) { >> - REGISTRY.put(annotation, helper); >> + private PluginVisitors() { >> } >> >> /** >> - * Creates a PluginVisitor instance for the given annotation class. >> This instance must be further populated with >> + * Creates a PluginVisitor instance for the given annotation class >> using metadata provided by the annotation's >> + * {@link PluginVisitorStrategy} annotation. This instance must be >> further populated with >> * data to be useful. Such data is passed through both the setters >> and the visit method. >> * >> * @param annotation the Plugin annotation class to find a >> PluginVisitor for. >> @@ -78,14 +44,21 @@ public final class PluginVisitorRegistry >> */ >> @SuppressWarnings("unchecked") // we're keeping track of types, >> thanks >> public static <A extends Annotation> PluginVisitor<A> >> findVisitor(final Class<A> annotation) { >> + final PluginVisitorStrategy strategy = >> annotation.getAnnotation(PluginVisitorStrategy.class); >> + if (strategy == null) { >> + LOGGER.debug("No PluginVisitorStrategy found on annotation >> [{}]. Ignoring.", annotation); >> + return null; >> + } >> + final String visitorClassName = strategy.value(); >> try { >> - final Class<PluginVisitor<A>> clazz = >> (Class<PluginVisitor<A>>) REGISTRY.get(annotation); >> - if (clazz == null) { >> - return null; >> - } >> - return clazz.newInstance(); >> + // if a PluginVisitor is in a different JAR than log4j-core, >> it can be safely assumed that the >> + // corresponding annotation is in the same JAR as the >> PluginVisitor implementation. thus, we use that >> + // ClassLoader instead of any default one >> + final Class<? extends PluginVisitor<A>> visitorClass = >> + (Class<? extends PluginVisitor<A>>) >> annotation.getClassLoader().loadClass(visitorClassName); >> + return visitorClass.newInstance(); >> } catch (final Exception e) { >> - LOGGER.debug("No PluginVisitor found for annotation: {}.", >> annotation); >> + LOGGER.error("Error loading PluginVisitor [{}] for >> annotation [{}].", visitorClassName, annotation, e); >> return null; >> } >> } >> >> Modified: >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/package-info.java >> URL: >> http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/package-info.java?rev=1597790&r1=1597789&r2=1597790&view=diff >> >> ============================================================================== >> --- >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/package-info.java >> (original) >> +++ >> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/package-info.java >> Tue May 27 13:57:31 2014 >> @@ -17,5 +17,8 @@ >> >> /** >> * Visitor classes for extracting values from a Configuration or Node >> corresponding to a plugin annotation. >> + * Visitor implementations must implement {@link >> org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitor}, >> + * and the corresponding annotation must be annotated with >> + * {@link >> org.apache.logging.log4j.core.config.plugins.PluginVisitorStrategy}. >> */ >> package org.apache.logging.log4j.core.config.plugins.visitors; >> \ No newline at end of file >> >> >> > -- Matt Sicker <[email protected]>
