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/com/sun/jmx/mbeanserver/PerInterface.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/jmx/mbeanserver/PerInterface.java+280−0
@@ -0,0 +1,280 @@
1+/*
2+ * Copyright (c) 2005, 2006, 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 com.sun.jmx.mbeanserver;
27+
28+import java.security.AccessController;
29+import java.util.Arrays;
30+import java.util.Collections;
31+import java.util.List;
32+import java.util.Map;
33+import javax.management.AttributeNotFoundException;
34+import javax.management.InvalidAttributeValueException;
35+import javax.management.MBeanException;
36+import javax.management.MBeanInfo;
37+import javax.management.ReflectionException;
38+
39+import static com.sun.jmx.mbeanserver.Util.*;
40+
41+/**
42+ * Per-MBean-interface behavior. A single instance of this class can be shared
43+ * by all MBeans of the same kind (Standard MBean or MXBean) that have the same
44+ * MBean interface.
45+ *
46+ * @since 1.6
47+ */
48+final class PerInterface<M> {
49+ PerInterface(Class<?> mbeanInterface, MBeanIntrospector<M> introspector,
50+ MBeanAnalyzer<M> analyzer, MBeanInfo mbeanInfo) {
51+ this.mbeanInterface = mbeanInterface;
52+ this.introspector = introspector;
53+ this.mbeanInfo = mbeanInfo;
54+ analyzer.visit(new InitMaps());
55+ }
56+
57+ Class<?> getMBeanInterface() {
58+ return mbeanInterface;
59+ }
60+
61+ MBeanInfo getMBeanInfo() {
62+ return mbeanInfo;
63+ }
64+
65+ boolean isMXBean() {
66+ return introspector.isMXBean();
67+ }
68+
69+ Object getAttribute(Object resource, String attribute, Object cookie)
70+ throws AttributeNotFoundException,
71+ MBeanException,
72+ ReflectionException {
73+
74+ final M cm = getters.get(attribute);
75+ if (cm == null) {
76+ final String msg;
77+ if (setters.containsKey(attribute))
78+ msg = "Write-only attribute: " + attribute;
79+ else
80+ msg = "No such attribute: " + attribute;
81+ throw new AttributeNotFoundException(msg);
82+ }
83+ return introspector.invokeM(cm, resource, (Object[]) null, cookie);
84+ }
85+
86+ void setAttribute(Object resource, String attribute, Object value,
87+ Object cookie)
88+ throws AttributeNotFoundException,
89+ InvalidAttributeValueException,
90+ MBeanException,
91+ ReflectionException {
92+
93+ final M cm = setters.get(attribute);
94+ if (cm == null) {
95+ final String msg;
96+ if (getters.containsKey(attribute))
97+ msg = "Read-only attribute: " + attribute;
98+ else
99+ msg = "No such attribute: " + attribute;
100+ throw new AttributeNotFoundException(msg);
101+ }
102+ introspector.invokeSetter(attribute, cm, resource, value, cookie);
103+ }
104+
105+ Object invoke(Object resource, String operation, Object[] params,
106+ String[] signature, Object cookie)
107+ throws MBeanException, ReflectionException {
108+
109+ final List<MethodAndSig> list = ops.get(operation);
110+ if (list == null) {
111+ final String msg = "No such operation: " + operation;
112+ return noSuchMethod(msg, resource, operation, params, signature,
113+ cookie);
114+ }
115+ if (signature == null)
116+ signature = new String[0];
117+ MethodAndSig found = null;
118+ for (MethodAndSig mas : list) {
119+ if (Arrays.equals(mas.signature, signature)) {
120+ found = mas;
121+ break;
122+ }
123+ }
124+ if (found == null) {
125+ final String badSig = sigString(signature);
126+ final String msg;
127+ if (list.size() == 1) { // helpful exception message
128+ msg = "Signature mismatch for operation " + operation +
129+ ": " + badSig + " should be " +
130+ sigString(list.get(0).signature);
131+ } else {
132+ msg = "Operation " + operation + " exists but not with " +
133+ "this signature: " + badSig;
134+ }
135+ return noSuchMethod(msg, resource, operation, params, signature,
136+ cookie);
137+ }
138+ return introspector.invokeM(found.method, resource, params, cookie);
139+ }
140+
141+ /*
142+ * This method is called when invoke doesn't find the named method.
143+ * Before throwing an exception, we check to see whether the
144+ * jmx.invoke.getters property is set, and if so whether the method
145+ * being invoked might be a getter or a setter. If so we invoke it
146+ * and return the result. This is for compatibility
147+ * with code based on JMX RI 1.0 or 1.1 which allowed invoking getters
148+ * and setters. It is *not* recommended that new code use this feature.
149+ *
150+ * Since this method is either going to throw an exception or use
151+ * functionality that is strongly discouraged, we consider that its
152+ * performance is not very important.
153+ *
154+ * A simpler way to implement the functionality would be to add the getters
155+ * and setters to the operations map when jmx.invoke.getters is set.
156+ * However, that means that the property is consulted when an MBean
157+ * interface is being introspected and not thereafter. Previously,
158+ * the property was consulted on every invocation. So this simpler
159+ * implementation could potentially break code that sets and unsets
160+ * the property at different times.
161+ */
162+ private Object noSuchMethod(String msg, Object resource, String operation,
163+ Object[] params, String[] signature,
164+ Object cookie)
165+ throws MBeanException, ReflectionException {
166+
167+ // Construct the exception that we will probably throw
168+ final NoSuchMethodException nsme =
169+ new NoSuchMethodException(operation + sigString(signature));
170+ final ReflectionException exception =
171+ new ReflectionException(nsme, msg);
172+
173+ if (introspector.isMXBean())
174+ throw exception; // No compatibility requirement here
175+
176+ // Is the compatibility property set?
177+ GetPropertyAction act = new GetPropertyAction("jmx.invoke.getters");
178+ String invokeGettersS;
179+ try {
180+ invokeGettersS = AccessController.doPrivileged(act);
181+ } catch (Exception e) {
182+ // We don't expect an exception here but if we get one then
183+ // we'll simply assume that the property is not set.
184+ invokeGettersS = null;
185+ }
186+ if (invokeGettersS == null)
187+ throw exception;
188+
189+ int rest = 0;
190+ Map<String, M> methods = null;
191+ if (signature == null || signature.length == 0) {
192+ if (operation.startsWith("get"))
193+ rest = 3;
194+ else if (operation.startsWith("is"))
195+ rest = 2;
196+ if (rest != 0)
197+ methods = getters;
198+ } else if (signature.length == 1 &&
199+ operation.startsWith("set")) {
200+ rest = 3;
201+ methods = setters;
202+ }
203+
204+ if (rest != 0) {
205+ String attrName = operation.substring(rest);
206+ M method = methods.get(attrName);
207+ if (method != null && introspector.getName(method).equals(operation)) {
208+ String[] msig = introspector.getSignature(method);
209+ if ((signature == null && msig.length == 0) ||
210+ Arrays.equals(signature, msig)) {
211+ return introspector.invokeM(method, resource, params, cookie);
212+ }
213+ }
214+ }
215+
216+ throw exception;
217+ }
218+
219+ private String sigString(String[] signature) {
220+ StringBuilder b = new StringBuilder("(");
221+ if (signature != null) {
222+ for (String s : signature) {
223+ if (b.length() > 1)
224+ b.append(", ");
225+ b.append(s);
226+ }
227+ }
228+ return b.append(")").toString();
229+ }
230+
231+ /**
232+ * Visitor that sets up the method maps (operations, getters, setters).
233+ */
234+ private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> {
235+ public void visitAttribute(String attributeName,
236+ M getter,
237+ M setter) {
238+ if (getter != null) {
239+ introspector.checkMethod(getter);
240+ final Object old = getters.put(attributeName, getter);
241+ assert(old == null);
242+ }
243+ if (setter != null) {
244+ introspector.checkMethod(setter);
245+ final Object old = setters.put(attributeName, setter);
246+ assert(old == null);
247+ }
248+ }
249+
250+ public void visitOperation(String operationName,
251+ M operation) {
252+ introspector.checkMethod(operation);
253+ final String[] sig = introspector.getSignature(operation);
254+ final MethodAndSig mas = new MethodAndSig();
255+ mas.method = operation;
256+ mas.signature = sig;
257+ List<MethodAndSig> list = ops.get(operationName);
258+ if (list == null)
259+ list = Collections.singletonList(mas);
260+ else {
261+ if (list.size() == 1)
262+ list = newList(list);
263+ list.add(mas);
264+ }
265+ ops.put(operationName, list);
266+ }
267+ }
268+
269+ private class MethodAndSig {
270+ M method;
271+ String[] signature;
272+ }
273+
274+ private final Class<?> mbeanInterface;
275+ private final MBeanIntrospector<M> introspector;
276+ private final MBeanInfo mbeanInfo;
277+ private final Map<String, M> getters = newMap();
278+ private final Map<String, M> setters = newMap();
279+ private final Map<String, List<MethodAndSig>> ops = newMap();
280+}