KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > mbeanserver > PerInterface


1 /*
2  * @(#)PerInterface.java 1.5 05/11/17
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.mbeanserver;
9
10 import java.security.AccessController JavaDoc;
11 import java.util.Arrays JavaDoc;
12 import java.util.Collections JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15 import javax.management.AttributeNotFoundException JavaDoc;
16 import javax.management.InvalidAttributeValueException JavaDoc;
17 import javax.management.MBeanException JavaDoc;
18 import javax.management.MBeanInfo JavaDoc;
19 import javax.management.ReflectionException JavaDoc;
20
21 import static com.sun.jmx.mbeanserver.Util.*;
22
23 /**
24  * Per-MBean-interface behavior. A single instance of this class can be shared
25  * by all MBeans of the same kind (Standard MBean or MXBean) that have the same
26  * MBean interface.
27  *
28  * @since 1.6
29  */

30 final class PerInterface<M> {
31     PerInterface(Class JavaDoc<?> mbeanInterface, MBeanIntrospector<M> introspector,
32          MBeanAnalyzer<M> analyzer, MBeanInfo JavaDoc mbeanInfo) {
33     this.mbeanInterface = mbeanInterface;
34     this.introspector = introspector;
35         this.mbeanInfo = mbeanInfo;
36     analyzer.visit(new InitMaps());
37     }
38
39     Class JavaDoc<?> getMBeanInterface() {
40     return mbeanInterface;
41     }
42
43     MBeanInfo JavaDoc getMBeanInfo() {
44     return mbeanInfo;
45     }
46
47     boolean isMXBean() {
48     return introspector.isMXBean();
49     }
50
51     Object JavaDoc getAttribute(Object JavaDoc resource, String JavaDoc attribute, Object JavaDoc cookie)
52         throws AttributeNotFoundException JavaDoc,
53            MBeanException JavaDoc,
54            ReflectionException JavaDoc {
55
56     final M cm = getters.get(attribute);
57     if (cm == null) {
58         final String JavaDoc msg;
59         if (setters.containsKey(attribute))
60         msg = "Write-only attribute: " + attribute;
61         else
62         msg = "No such attribute: " + attribute;
63         throw new AttributeNotFoundException JavaDoc(msg);
64     }
65     return introspector.invokeM(cm, resource, (Object JavaDoc[]) null, cookie);
66     }
67
68     void setAttribute(Object JavaDoc resource, String JavaDoc attribute, Object JavaDoc value,
69                       Object JavaDoc cookie)
70         throws AttributeNotFoundException JavaDoc,
71            InvalidAttributeValueException JavaDoc,
72            MBeanException JavaDoc,
73            ReflectionException JavaDoc {
74
75     final M cm = setters.get(attribute);
76     if (cm == null) {
77         final String JavaDoc msg;
78         if (getters.containsKey(attribute))
79         msg = "Read-only attribute: " + attribute;
80         else
81         msg = "No such attribute: " + attribute;
82         throw new AttributeNotFoundException JavaDoc(msg);
83     }
84         introspector.invokeSetter(attribute, cm, resource, value, cookie);
85     }
86
87     Object JavaDoc invoke(Object JavaDoc resource, String JavaDoc operation, Object JavaDoc[] params,
88           String JavaDoc[] signature, Object JavaDoc cookie)
89         throws MBeanException JavaDoc, ReflectionException JavaDoc {
90
91     final List JavaDoc<MethodAndSig> list = ops.get(operation);
92     if (list == null) {
93             final String JavaDoc msg = "No such operation: " + operation;
94             return noSuchMethod(msg, resource, operation, params, signature,
95                                 cookie);
96     }
97     if (signature == null)
98         signature = new String JavaDoc[0];
99     MethodAndSig found = null;
100     for (MethodAndSig mas : list) {
101         if (Arrays.equals(mas.signature, signature)) {
102         found = mas;
103         break;
104         }
105     }
106     if (found == null) {
107         final String JavaDoc badSig = sigString(signature);
108         final String JavaDoc msg;
109         if (list.size() == 1) { // helpful exception message
110
msg = "Signature mismatch for operation " + operation +
111             ": " + badSig + " should be " +
112             sigString(list.get(0).signature);
113         } else {
114         msg = "Operation " + operation + " exists but not with " +
115             "this signature: " + badSig;
116         }
117         return noSuchMethod(msg, resource, operation, params, signature,
118                                 cookie);
119     }
120     return introspector.invokeM(found.method, resource, params, cookie);
121     }
122
123     /*
124      * This method is called when invoke doesn't find the named method.
125      * Before throwing an exception, we check to see whether the
126      * jmx.invoke.getters property is set, and if so whether the method
127      * being invoked might be a getter or a setter. If so we invoke it
128      * and return the result. This is for compatibility
129      * with code based on JMX RI 1.0 or 1.1 which allowed invoking getters
130      * and setters. It is *not* recommended that new code use this feature.
131      *
132      * Since this method is either going to throw an exception or use
133      * functionality that is strongly discouraged, we consider that its
134      * performance is not very important.
135      *
136      * A simpler way to implement the functionality would be to add the getters
137      * and setters to the operations map when jmx.invoke.getters is set.
138      * However, that means that the property is consulted when an MBean
139      * interface is being introspected and not thereafter. Previously,
140      * the property was consulted on every invocation. So this simpler
141      * implementation could potentially break code that sets and unsets
142      * the property at different times.
143      */

144     private Object JavaDoc noSuchMethod(String JavaDoc msg, Object JavaDoc resource, String JavaDoc operation,
145                 Object JavaDoc[] params, String JavaDoc[] signature,
146                 Object JavaDoc cookie)
147         throws MBeanException JavaDoc, ReflectionException JavaDoc {
148
149         // Construct the exception that we will probably throw
150
final NoSuchMethodException JavaDoc nsme =
151             new NoSuchMethodException JavaDoc(operation + sigString(signature));
152         final ReflectionException JavaDoc exception =
153             new ReflectionException JavaDoc(nsme, msg);
154
155         if (introspector.isMXBean())
156             throw exception; // No compatibility requirement here
157

158         // Is the compatibility property set?
159
GetPropertyAction act = new GetPropertyAction("jmx.invoke.getters");
160         String JavaDoc invokeGettersS;
161         try {
162             invokeGettersS = AccessController.doPrivileged(act);
163         } catch (Exception JavaDoc e) {
164             // We don't expect an exception here but if we get one then
165
// we'll simply assume that the property is not set.
166
invokeGettersS = null;
167         }
168         if (invokeGettersS == null)
169             throw exception;
170
171     int rest = 0;
172         Map JavaDoc<String JavaDoc, M> methods = null;
173     if (signature == null || signature.length == 0) {
174         if (operation.startsWith("get"))
175         rest = 3;
176         else if (operation.startsWith("is"))
177         rest = 2;
178             if (rest != 0)
179                 methods = getters;
180     } else if (signature != null && signature.length == 1 &&
181            operation.startsWith("set")) {
182         rest = 3;
183             methods = setters;
184         }
185
186     if (rest != 0) {
187         String JavaDoc attrName = operation.substring(rest);
188         M method = methods.get(attrName);
189             if (method != null && introspector.getName(method).equals(operation)) {
190                 String JavaDoc[] msig = introspector.getSignature(method);
191                 if ((signature == null && msig.length == 0) ||
192                         Arrays.equals(signature, msig)) {
193                     return introspector.invokeM(method, resource, params, cookie);
194                 }
195             }
196     }
197
198         throw exception;
199     }
200
201     private String JavaDoc sigString(String JavaDoc[] signature) {
202     StringBuilder JavaDoc b = new StringBuilder JavaDoc("(");
203         if (signature != null) {
204             for (String JavaDoc s : signature) {
205                 if (b.length() > 1)
206                     b.append(", ");
207                 b.append(s);
208             }
209         }
210     return b.append(")").toString();
211     }
212     
213     /**
214      * Visitor that sets up the method maps (operations, getters, setters).
215      */

216     private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> {
217     public void visitAttribute(String JavaDoc attributeName,
218                    M getter,
219                    M setter) {
220         if (getter != null) {
221                 introspector.checkMethod(getter);
222         final Object JavaDoc old = getters.put(attributeName, getter);
223         assert(old == null);
224         }
225         if (setter != null) {
226                 introspector.checkMethod(setter);
227         final Object JavaDoc old = setters.put(attributeName, setter);
228         assert(old == null);
229         }
230     }
231
232     public void visitOperation(String JavaDoc operationName,
233                    M operation) {
234             introspector.checkMethod(operation);
235         final String JavaDoc[] sig = introspector.getSignature(operation);
236         final MethodAndSig mas = new MethodAndSig();
237         mas.method = operation;
238         mas.signature = sig;
239             List JavaDoc<MethodAndSig> list = ops.get(operationName);
240             if (list == null)
241                 list = Collections.singletonList(mas);
242             else {
243                 if (list.size() == 1)
244                     list = newList(list);
245                 list.add(mas);
246             }
247             ops.put(operationName, list);
248     }
249     }
250
251     private class MethodAndSig {
252         M method;
253         String JavaDoc[] signature;
254     }
255
256     private final Class JavaDoc<?> mbeanInterface;
257     private final MBeanIntrospector<M> introspector;
258     private final MBeanInfo JavaDoc mbeanInfo;
259     private final Map JavaDoc<String JavaDoc, M> getters = newMap();
260     private final Map JavaDoc<String JavaDoc, M> setters = newMap();
261     private final Map JavaDoc<String JavaDoc, List JavaDoc<MethodAndSig>> ops = newMap();
262 }
263
Popular Tags