History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tracing/ProviderSkeleton.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tracing/ProviderSkeleton.java+251−0
@@ -0,0 +1,251 @@
1/*
2 * Copyright (c) 2008, 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
26package sun.tracing;
27
28import java.lang.reflect.InvocationHandler;
29import java.lang.reflect.Method;
30import java.lang.reflect.Proxy;
31import java.lang.reflect.InvocationTargetException;
32import java.lang.reflect.AnnotatedElement;
33import java.lang.annotation.Annotation;
34import java.util.HashMap;
35import java.security.AccessController;
36import java.security.PrivilegedAction;
37
38import com.sun.tracing.Provider;
39import com.sun.tracing.Probe;
40import com.sun.tracing.ProviderName;
41
42/**
43 * Provides a common code for implementation of {@code Provider} classes.
44 *
45 * Each tracing subsystem needs to provide three classes, a factory
46 * (derived from {@code ProviderFactory}, a provider (a subclass of
47 * {@code Provider}, and a probe type (subclass of {@code ProbeSkeleton}).
48 *
49 * The factory object takes a user-defined interface and provides an
50 * implementation of it whose method calls will trigger probes in the
51 * tracing framework.
52 *
53 * The framework's provider class, and its instances, are not seen by the
54 * user at all -- they usually sit in the background and receive and dispatch
55 * the calls to the user's provider interface. The {@code ProviderSkeleton}
56 * class provides almost all of the implementation needed by a framework
57 * provider. Framework providers must only provide a constructor and
58 * disposal method, and implement the {@code createProbe} method to create
59 * an appropriate {@code ProbeSkeleton} subclass.
60 *
61 * The framework's probe class provides the implementation of the two
62 * probe methods, {@code isEnabled()} and {@code uncheckedTrigger()}. Both are
63 * framework-dependent implementations.
64 *
65 * @since 1.7
66 */
67
68public abstract class ProviderSkeleton implements InvocationHandler, Provider {
69
70 protected boolean active; // set to false after dispose() is called
71 protected Class<? extends Provider> providerType; // user's interface
72 protected HashMap<Method, ProbeSkeleton> probes; // methods to probes
73
74
75 /**
76 * Creates a framework-specific probe subtype.
77 *
78 * This method is implemented by the framework's provider and returns
79 * framework-specific probes for a method.
80 *
81 * @param method A method in the user's interface
82 * @return a subclass of ProbeSkeleton for the particular framework.
83 */
84 protected abstract ProbeSkeleton createProbe(Method method);
85
86 /**
87 * Initializes the provider.
88 *
89 * @param type the user's interface
90 */
91 protected ProviderSkeleton(Class<? extends Provider> type) {
92 this.active = false; // in case of some error during initialization
93 this.providerType = type;
94 this.probes = new HashMap<Method,ProbeSkeleton>();
95 }
96
97 /**
98 * Post-constructor initialization routine.
99 *
100 * Subclass instances must be initialized before they can create probes.
101 * It is up to the factory implementations to call this after construction.
102 */
103 public void init() {
104 Method[] methods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
105 public Method[] run() {
106 return providerType.getDeclaredMethods();
107 }
108 });
109
110 for (Method m : methods) {
111 if ( m.getReturnType() != Void.TYPE ) {
112 throw new IllegalArgumentException(
113 "Return value of method is not void");
114 } else {
115 probes.put(m, createProbe(m));
116 }
117 }
118 this.active = true;
119 }
120
121 /**
122 * Magic routine which creates an implementation of the user's interface.
123 *
124 * This method creates the instance of the user's interface which is
125 * passed back to the user. Every call upon that interface will be
126 * redirected to the {@code invoke()} method of this class (until
127 * overridden by the VM).
128 *
129 * @return an implementation of the user's interface
130 */
131 @SuppressWarnings("unchecked")
132 public <T extends Provider> T newProxyInstance() {
133 return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
134 new Class<?>[] { providerType }, this);
135 }
136
137 /**
138 * Triggers a framework probe when a user interface method is called.
139 *
140 * This method dispatches a user interface method call to the appropriate
141 * probe associated with this framework.
142 *
143 * If the invoked method is not a user-defined member of the interface,
144 * then it is a member of {@code Provider} or {@code Object} and we
145 * invoke the method directly.
146 *
147 * @param proxy the instance whose method was invoked
148 * @param method the method that was called
149 * @param args the arguments passed in the call.
150 * @return always null, if the method is a user-defined probe
151 */
152 public Object invoke(Object proxy, Method method, Object[] args) {
153 if (method.getDeclaringClass() != providerType) {
154 try {
155 return method.invoke(this, args);
156 } catch (IllegalAccessException e) {
157 assert false;
158 } catch (InvocationTargetException e) {
159 assert false;
160 }
161 } else if (active) {
162 ProbeSkeleton p = probes.get(method);
163 if (p != null) {
164 // Skips argument check -- already done by javac
165 p.uncheckedTrigger(args);
166 }
167 }
168 return null;
169 }
170
171 /**
172 * Direct accessor for {@code Probe} objects.
173 *
174 * @param m the method corresponding to a probe
175 * @return the method associated probe object, or null
176 */
177 public Probe getProbe(Method m) {
178 return active ? probes.get(m) : null;
179 }
180
181 /**
182 * Default provider disposal method.
183 *
184 * This is overridden in subclasses as needed.
185 */
186 public void dispose() {
187 active = false;
188 probes.clear();
189 }
190
191 /**
192 * Gets the user-specified provider name for the user's interface.
193 *
194 * If the user's interface has a {@ProviderName} annotation, that value
195 * is used. Otherwise we use the simple name of the user interface's class.
196 * @return the provider name
197 */
198 protected String getProviderName() {
199 return getAnnotationString(
200 providerType, ProviderName.class, providerType.getSimpleName());
201 }
202
203 /**
204 * Utility method for getting a string value from an annotation.
205 *
206 * Used for getting a string value from an annotation with a 'value' method.
207 *
208 * @param element the element that was annotated, either a class or method
209 * @param annotation the class of the annotation we're interested in
210 * @param defaultValue the value to return if the annotation doesn't
211 * exist, doesn't have a "value", or the value is empty.
212 */
213 protected static String getAnnotationString(
214 AnnotatedElement element, Class<? extends Annotation> annotation,
215 String defaultValue) {
216 String ret = (String)getAnnotationValue(
217 element, annotation, "value", defaultValue);
218 return ret.isEmpty() ? defaultValue : ret;
219 }
220
221 /**
222 * Utility method for calling an arbitrary method in an annotation.
223 *
224 * @param element the element that was annotated, either a class or method
225 * @param annotation the class of the annotation we're interested in
226 * @param methodName the name of the method in the annotation we wish
227 * to call.
228 * @param defaultValue the value to return if the annotation doesn't
229 * exist, or we couldn't invoke the method for some reason.
230 * @return the result of calling the annotation method, or the default.
231 */
232 protected static Object getAnnotationValue(
233 AnnotatedElement element, Class<? extends Annotation> annotation,
234 String methodName, Object defaultValue) {
235 Object ret = defaultValue;
236 try {
237 Method m = annotation.getMethod(methodName);
238 Annotation a = element.getAnnotation(annotation);
239 ret = m.invoke(a);
240 } catch (NoSuchMethodException e) {
241 assert false;
242 } catch (IllegalAccessException e) {
243 assert false;
244 } catch (InvocationTargetException e) {
245 assert false;
246 } catch (NullPointerException e) {
247 assert false;
248 }
249 return ret;
250 }
251}