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
26package com.sun.jmx.mbeanserver;
27
28import java.security.AccessController;
29import java.util.Arrays;
30import java.util.Collections;
31import java.util.List;
32import java.util.Map;
33import javax.management.AttributeNotFoundException;
34import javax.management.InvalidAttributeValueException;
35import javax.management.MBeanException;
36import javax.management.MBeanInfo;
37import javax.management.ReflectionException;
38
39import 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 */
48final 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}