/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.codahale.agent; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.yammer.metrics.annotation.Timed; import javassist.bytecode.annotation.AnnotationImpl; import javassist.bytecode.annotation.EnumMemberValue; import javassist.bytecode.annotation.StringMemberValue; /** * <p>Title: AnnotationType</p> * <p>Description: </p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.codahale.agent.AnnotationType</code></p> */ public enum AnnotationType implements AnnotationValuesExtractor { // /** Represents the annotation that meters exception on a join-point */ // EXCEPTION_METERED, // /** Represents the annotation that counts invocations of a join-point */ // COUNTER, // /** Represents the annotation that computes statistics regarding a join-point */ // HISTOGRAM, /** Represents the annotation that computes timings of executions of a join-point */ TIMED(Timed.class, new TimedAnnotationExtractor()); /** Maps annotation classes to the annotation type enum */ public static final Map<String, AnnotationType> CLASS2TYPE; /** Maps annotation type enums to annotation classes */ public static final Map<AnnotationType, Class<? extends Annotation>> TYPE2CLASS; static { Map<String, AnnotationType> toType = new HashMap<String, AnnotationType>(10); Map<AnnotationType, Class<? extends Annotation>> toClass = new HashMap<AnnotationType, Class<? extends Annotation>>(10); for(AnnotationType ann: AnnotationType.values()) { toType.put(ann.annotationClazz.getName(), ann); toClass.put(ann, ann.annotationClazz); } CLASS2TYPE = Collections.unmodifiableMap(toType); TYPE2CLASS = Collections.unmodifiableMap(toClass); } /** * Returns the annotation type enum for the passed annotation class * @param clazz The annotation class to get the annotation type enum for * @return the annotation type enum */ public static AnnotationType getTypeForAnnotation(Class<?> clazz) { if(clazz==null) throw new IllegalArgumentException("The passed class was null", new Throwable()); AnnotationType ann = CLASS2TYPE.get(clazz.getName()); if(ann==null) throw new IllegalArgumentException("The passed class [" + clazz.getName() + "] is not a supported annotation", new Throwable()); return ann; } /** * Returns the annotation type enum for the passed annotation instance * @param ann The annotation instance to get the annotation type enum for * @return the annotation type enum */ public static AnnotationType getTypeForAnnotation(Annotation ann) { if(ann==null) throw new IllegalArgumentException("The passed annotation instance was null", new Throwable()); return getTypeForAnnotation(ann.annotationType()); } /** * Determines if the passed annotation instance is a supported type * @param ann The annotation instance to test * @return true if the instance's type is supported, false if it not supported or was null */ public static boolean isSupportedAnnotation(Object ann) { if(ann==null) return false; return CLASS2TYPE.get(ann.getClass().getName())!=null; } // GAUGE ? Not appropriate for byte code instrumentation ? private AnnotationType(Class<? extends Annotation> annotationClazz, AnnotationValuesExtractor extractor) { this.annotationClazz = annotationClazz; this.extractor = extractor; } private final Class<? extends Annotation> annotationClazz; private final AnnotationValuesExtractor extractor; /** * Returns this enum instance's annotation type * @return this enum instance's annotation type */ public Class<? extends Annotation> getAnnotationClazz() { return annotationClazz; } /** * Returns this enum instance's {@link AnnotationValuesExtractor} * @return this enum instance's {@link AnnotationValuesExtractor} */ public AnnotationValuesExtractor getExtractor() { return extractor; } /** * {@inheritDoc} * @see org.helios.apmrouter.codahale.agent.AnnotationValuesExtractor#extract(javassist.bytecode.annotation.AnnotationImpl) */ @Override public Map<String, ?> extract(AnnotationImpl annotation) { return this.extractor.extract(annotation); } /** * <p>Title: TimedAnnotationExtractor</p> * <p>Description: Extractor for Timed annotation instances</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.codahale.agent.AnnotationType.TimedAnnotationExtractor</code></p> */ public static class TimedAnnotationExtractor implements AnnotationValuesExtractor { /** * {@inheritDoc} * @see org.helios.apmrouter.codahale.agent.AnnotationValuesExtractor#extract(javassist.bytecode.annotation.AnnotationImpl) */ @Override public Map<String, ?> extract(AnnotationImpl annotation) { Map<String, Object> map = new HashMap<String, Object>(); javassist.bytecode.annotation.Annotation ann = annotation.getAnnotation(); map.put("group", ((StringMemberValue)ann.getMemberValue("group")).getValue()); map.put("type", ((StringMemberValue)ann.getMemberValue("type")).getValue()); map.put("scope", ((StringMemberValue)ann.getMemberValue("scope")).getValue()); map.put("name", ((StringMemberValue)ann.getMemberValue("name")).getValue()); map.put("rateUnit", ((EnumMemberValue)ann.getMemberValue("rateUnit")).getValue()); map.put("durationUnit", ((EnumMemberValue)ann.getMemberValue("durationUnit")).getValue()); return map; } } }