1 /* 2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr; 27 28 import java.lang.annotation.Annotation; 29 import java.util.Arrays; 30 import java.util.Collections; 31 import java.util.LinkedHashMap; 32 import java.util.List; 33 import java.util.Map; 34 import java.util.Objects; 35 36 import jdk.jfr.internal.JVMSupport; 37 import jdk.jfr.internal.MetadataRepository; 38 import jdk.jfr.internal.PlatformEventType; 39 import jdk.jfr.internal.Type; 40 import jdk.jfr.internal.Utils; 41 42 /** 43 * Describes an event, its fields, settings and annotations. 44 * 45 * @since 9 46 */ 47 public final class EventType { 48 private final PlatformEventType platformEventType; 49 private final List<String> UNCATEGORIZED = Collections.singletonList("Uncategorized"); 50 private Map<String, ValueDescriptor> cache; // create lazy to avoid memory overhead 51 // helper constructor EventType(PlatformEventType platformEventType)52 EventType(PlatformEventType platformEventType) { 53 this.platformEventType = platformEventType; 54 } 55 56 /** 57 * Returns an immutable list of descriptors that describe the event fields of 58 * this event type. 59 * 60 * @return the list of field descriptors, not {@code null} 61 */ getFields()62 public List<ValueDescriptor> getFields() { 63 return platformEventType.getFields(); 64 } 65 66 /** 67 * Returns the field with the specified name, or {@code null} if it doesn't 68 * exist. 69 * 70 * @return a value descriptor that describes the field, or <code>null</code> if 71 * the field with the specified name doesn't exist 72 * 73 * @return a value descriptor, or <code>null</code> if it doesn't exist 74 */ getField(String name)75 public ValueDescriptor getField(String name) { 76 Objects.requireNonNull(name); 77 if (cache == null) { 78 List<ValueDescriptor> fields = getFields(); 79 Map<String, ValueDescriptor> newCache = new LinkedHashMap<String, ValueDescriptor>(fields.size()); 80 for (ValueDescriptor v :fields) { 81 newCache.put(v.getName(), v); 82 } 83 cache = newCache; 84 } 85 return cache.get(name); 86 } 87 88 /** 89 * Returns an identifier for the event (for example, 90 * {@code "jdk.CPULoad"}). 91 * <p> 92 * The identifier is the fully qualified name of the event class, if not set using 93 * the {@link Name} annotation. 94 * 95 * @return the name, not {@code null} 96 * 97 * @see Name 98 */ getName()99 public String getName() { 100 return platformEventType.getName(); 101 } 102 103 /** 104 * Returns a human-readable name (for example, {@code "CPU Load"}). 105 * <p> 106 * The label of an event class can be set with {@link Label}. 107 * 108 * @return the label, or {@code null} if a label is not set 109 * 110 * @see Label 111 */ getLabel()112 public String getLabel() { 113 return platformEventType.getLabel(); 114 } 115 116 /** 117 * Returns a unique ID for this event type in the Java Virtual Machine (JVM). 118 * 119 * @return the ID that is used in the JVM 120 */ getId()121 public long getId() { 122 return platformEventType.getId(); 123 } 124 125 /** 126 * Returns an immutable list of annotation elements for this event type. 127 * 128 * @return an immutable list of annotations or an empty list if no 129 * annotations exists, not {@code null} 130 */ getAnnotationElements()131 public List<AnnotationElement> getAnnotationElements() { 132 return platformEventType.getAnnotationElements(); 133 } 134 135 /** 136 * Returns {@code true} if the event is enabled and at least one recording is 137 * running, {@code false} otherwise. 138 * <p> 139 * By default, the event is enabled. The event can be enabled or disabled by 140 * setting the enabled setting to {@code true} or {@code false}, programmatically or by using a 141 * configuration file. The event can also be disabled by annotating event with 142 * the {@code @Enabled(false)} annotation. 143 * 144 * @return true if event is enabled, false otherwise 145 * 146 * @see Enabled 147 * @see Recording#enable(Class) 148 */ isEnabled()149 public boolean isEnabled() { 150 return platformEventType.isEnabled(); 151 } 152 153 /** 154 * Returns a short sentence that describes the event class. 155 * <p> 156 * The description of an event class can be set with {@link Description}. 157 * 158 * @return the description, or {@code null} if no description exists 159 * 160 * @see Description 161 */ getDescription()162 public String getDescription() { 163 return platformEventType.getDescription(); 164 } 165 166 /** 167 * Returns the first annotation for the specified type if an annotation 168 * element with the same name is directly present, otherwise {@code null}. 169 * 170 * @param <A> the type of the annotation to query for and return if present 171 * @param annotationClass the {@code Class} object that corresponds to the 172 * annotation type, not {@code null} 173 * @return this element's annotation for the specified annotation type if 174 * directly present, else {@code null} 175 */ getAnnotation(Class<A> annotationClass)176 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { 177 Objects.requireNonNull(annotationClass); 178 return platformEventType.getAnnotation(annotationClass); 179 } 180 181 /** 182 * Returns the event type for an event class, or {@code null} if it doesn't 183 * exist. 184 * 185 * @param eventClass the event class, not {@code null} 186 * @return the event class, or null if class doesn't exist 187 * 188 * @throws IllegalArgumentException if {@code eventClass} is an abstract class 189 * 190 * @throws IllegalStateException if the class is annotated with 191 * {@code Registered(false)}, but not manually registered 192 */ getEventType(Class<? extends Event> eventClass)193 public static EventType getEventType(Class<? extends Event> eventClass) { 194 Objects.requireNonNull(eventClass); 195 Utils.ensureValidEventSubclass(eventClass); 196 JVMSupport.ensureWithInternalError(); 197 return MetadataRepository.getInstance().getEventType(eventClass); 198 } 199 200 /** 201 * Returns an immutable list of the setting descriptors that describe the available 202 * event settings for this event type. 203 * 204 * @return the list of setting descriptors for this event type, not 205 * {@code null} 206 */ getSettingDescriptors()207 public List<SettingDescriptor> getSettingDescriptors() { 208 return Collections.unmodifiableList(platformEventType.getSettings()); 209 } 210 211 /** 212 * Returns the list of human-readable names that makes up the categories for 213 * this event type (for example, {@code "Java Application"}, {@code "Statistics"}). 214 * 215 * @return an immutable list of category names, or a list with the name 216 * {@code "Uncategorized"} if no category is set 217 * 218 * @see Category 219 */ getCategoryNames()220 public List<String> getCategoryNames() { 221 Category c = platformEventType.getAnnotation(Category.class); 222 if (c == null) { 223 return UNCATEGORIZED; 224 } 225 return Collections.unmodifiableList(Arrays.asList(c.value())); 226 } 227 228 // package private getType()229 Type getType() { 230 return platformEventType; 231 } 232 233 // package private getPlatformEventType()234 PlatformEventType getPlatformEventType() { 235 return platformEventType; 236 } 237 } 238