1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.backsource.jmx;
21 import java.util.HashMap;
22 import java.util.Hashtable;
23 import java.rmi.RemoteException;
24 import java.lang.reflect.Method;
25 import java.lang.reflect.Proxy;
26 import java.lang.reflect.InvocationHandler;
27 import java.lang.reflect.InvocationTargetException;
28 import javax.management.*;
29
30 import javax.naming.InitialContext;
31 import javax.naming.Context;
32 import javax.naming.NamingException;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
38 /***
39 * A proxy and proxy factory to access MBean as normal classes. Server may
40 * be both local or remote.
41 *
42 *
43 * @author <a href="mailto:pra@mogul.com">Peter Antman</a>
44 * @version $Revision: 1.1.1.1 $
45 */
46
47 public class MBeanProxy implements InvocationHandler, java.io.Serializable{
48 private static Log log = LogFactory.getLog(MBeanProxy.class);
49
50 private static final String RMI_ADAPTOR_NAME = "jmx/invoker/RMIAdaptor";
51
52 /*** ObjectName of the MBean to invoke */
53 ObjectName name;
54 /*** JNDIUrl of a remote MBeanServer to invoke,i.e this is NOT the remtote version of the MBean server this proxy was created in, but in another JNDI context
55 */
56 String jndiURL;
57 /***
58 * The local mbean server, which will not be serialized and is therefore
59 * null when used remotely!
60 */
61 transient MBeanServer localServer;
62 /***
63 * The RMI version of the MBean server.
64 */
65 RMIAdaptor remoteServer;
66
67 private HashMap attributeMap = new HashMap();
68 /***
69 * Create a proxy wich will invoke the MBean by ObjectName name.
70 *
71 * <p>This proxy may be used both locally (the invokation is done directly against the MBean server) or remotely.
72 */
73 public MBeanProxy(String name)
74 throws OperationsException, NamingException {
75 this(name,null);
76
77 }
78
79 /***
80 * Create a proxy wich will invoke the MBean by ObjectName name.
81 *
82 * <p>if jndiURL is non null, the MBean server will be looked up with
83 * that url as its java.naming.provider.url. This means that the proxy
84 * will actually proxy an MBean in <b>another</b> mbean server.</p>
85 */
86 public MBeanProxy(String name, String jndiURL)
87 throws OperationsException, NamingException {
88 try {
89 this.name = new ObjectName(name);
90 this.jndiURL = jndiURL;
91 MBeanInfo info = null;
92
93
94
95 if ( jndiURL != null) {
96 remoteServer = getRemoteServer(jndiURL);
97 info = remoteServer.getMBeanInfo(this.name);
98 }
99
100
101 else {
102
103 localServer = (MBeanServer) MBeanServerFactory.findMBeanServer(null).iterator().next();
104 remoteServer = getRemoteServer(null);
105 info = localServer.getMBeanInfo(this.name);
106 }
107
108 MBeanAttributeInfo[] attributes = info.getAttributes();
109
110 for (int i = 0; i < attributes.length; ++i)
111 attributeMap.put(attributes[i].getName(), attributes[i]);
112 }catch (InstanceNotFoundException e)
113 {
114 throw new NamingException("Object name " + name + " not found: " + e.toString());
115 }
116 catch (IntrospectionException e)
117 {
118 throw new OperationsException(e.toString());
119 }
120 catch (ReflectionException e)
121 {
122 throw new OperationsException(e.toString());
123 }
124 catch (MalformedObjectNameException e)
125 {
126 throw new OperationsException(e.toString());
127 }
128 catch (RemoteException e)
129 {
130 throw new OperationsException(e.toString());
131 }
132 }
133
134 private static RMIAdaptor getRemoteServer(String jndiURL) throws NamingException{
135 Context ctx = new InitialContext();
136 RMIAdaptor adaptor = null;
137
138 if ( jndiURL != null) {
139
140 Hashtable h = ctx.getEnvironment();
141 h.put("java.naming.provider.url", jndiURL);
142 ctx = new InitialContext(h);
143 }
144 try {
145 adaptor = (RMIAdaptor)ctx.lookup(RMI_ADAPTOR_NAME);
146 } catch (NamingException e) {
147
148
149 log.warn("Could not lookup RMI adapter;remove server will be null:" +e);
150 }
151 return adaptor;
152 }
153
154 public Object invoke(Object proxy, Method method, Object[] args) throws Exception
155 {
156 try {
157 String methodName = method.getName();
158
159 if (methodName.startsWith("get") && args == null)
160 {
161 String attrName = methodName.substring(3, methodName.length());
162
163 MBeanAttributeInfo info = (MBeanAttributeInfo)attributeMap.get(attrName);
164 if (info != null)
165 {
166 String retType = method.getReturnType().getName();
167
168 if (retType.equals(info.getType()))
169 {
170 if ( localServer != null) {
171 return localServer.getAttribute(name, attrName);
172 } else if (remoteServer != null ) {
173 return remoteServer.getAttribute(name, attrName);
174 } else {
175 throw new Exception("No server to invoke");
176 }
177
178
179
180 }
181 }
182 }
183
184 else if (methodName.startsWith("is") && args == null)
185 {
186 String attrName = methodName.substring(2, methodName.length());
187
188 MBeanAttributeInfo info = (MBeanAttributeInfo)attributeMap.get(attrName);
189 if (info != null && info.isIs())
190 {
191 Class retType = method.getReturnType();
192
193 if (retType.equals(Boolean.class) || retType.equals(Boolean.TYPE))
194 {
195 if ( localServer != null) {
196 return localServer.getAttribute(name, attrName);
197 } else if (remoteServer != null ) {
198 return remoteServer.getAttribute(name, attrName);
199 } else {
200 throw new Exception("No server to invoke");
201 }
202 }
203 }
204 }
205
206 else if (methodName.startsWith("set") && args != null && args.length == 1)
207 {
208 String attrName = methodName.substring(3, methodName.length());
209
210 MBeanAttributeInfo info = (MBeanAttributeInfo)attributeMap.get(attrName);
211 if (info != null && method.getReturnType().equals(Void.TYPE))
212 {
213 ClassLoader cl = Thread.currentThread().getContextClassLoader();
214
215 Class signatureClass = null;
216 String classType = info.getType();
217
218 if (isPrimitive(classType))
219 signatureClass = getPrimitiveClass(classType);
220 else
221 signatureClass = cl.loadClass(info.getType());
222
223 if (signatureClass.isAssignableFrom(args[0].getClass()))
224 {
225 if ( localServer != null) {
226 localServer.setAttribute(name, new Attribute(attrName, args[0]));
227 } else if (remoteServer != null ) {
228 remoteServer.setAttribute(name, new Attribute(attrName, args[0]));
229 } else {
230 throw new Exception("No server to invoke");
231 }
232
233
234
235 return null;
236 }
237 }
238 }
239
240 String[] signature = null;
241
242 if (args != null)
243 {
244 signature = new String[args.length];
245 Class[] sign = method.getParameterTypes();
246
247 for (int i = 0; i < sign.length; ++i)
248 signature[i] = sign[i].getName();
249 }
250 if ( localServer != null) {
251 return localServer.invoke(name, methodName, args, signature);
252 } else if (remoteServer != null ) {
253 return remoteServer.invoke(name, methodName, args, signature);
254 } else {
255 throw new Exception("No server to invoke");
256 }
257 }
258
259
260
261
262
263 catch (InstanceNotFoundException e)
264 {
265 throw new RuntimeException("Instance not found: " + e.toString());
266 }
267 catch (AttributeNotFoundException e)
268 {
269 throw new RuntimeException("Attribute not found: " + e.toString());
270 }
271 catch (InvalidAttributeValueException e)
272 {
273 throw new RuntimeException("Invalid attribute value: " + e.toString());
274 }
275 catch (MBeanException e)
276 {
277
278
279
280 throw e.getTargetException();
281 }
282 catch (ReflectionException e)
283 {
284
285
286
287 Exception target = e.getTargetException();
288 log.error(target);
289 if (target instanceof RuntimeException)
290 throw target;
291 else
292 throw new RuntimeException(target.toString());
293 }
294 catch (RuntimeOperationsException e)
295 {
296
297 throw e.getTargetException();
298 }
299 catch (RuntimeMBeanException e)
300 {
301
302 throw e.getTargetException();
303 }
304 catch (RuntimeErrorException e)
305 {
306
307 throw e.getTargetError();
308 }
309 catch (RemoteException e) {
310 if ( e.detail != null && e.detail instanceof Exception ) {
311 throw (Exception)e.detail;
312 } else {
313 throw new RuntimeException(e.toString());
314 }
315
316 }
317
318 }
319 private boolean isPrimitive(String type)
320 {
321 if (type.equals(Integer.TYPE.getName())) return true;
322 if (type.equals(Long.TYPE.getName())) return true;
323 if (type.equals(Boolean.TYPE.getName())) return true;
324 if (type.equals(Byte.TYPE.getName())) return true;
325 if (type.equals(Character.TYPE.getName())) return true;
326 if (type.equals(Short.TYPE.getName())) return true;
327 if (type.equals(Float.TYPE.getName())) return true;
328 if (type.equals(Double.TYPE.getName())) return true;
329 if (type.equals(Void.TYPE.getName())) return true;
330
331 return false;
332 }
333
334 private Class getPrimitiveClass(String type)
335 {
336 if (type.equals(Integer.TYPE.getName())) return Integer.TYPE;
337 if (type.equals(Long.TYPE.getName())) return Long.TYPE;
338 if (type.equals(Boolean.TYPE.getName())) return Boolean.TYPE;
339 if (type.equals(Byte.TYPE.getName())) return Byte.TYPE;
340 if (type.equals(Character.TYPE.getName()))return Character.TYPE;
341 if (type.equals(Short.TYPE.getName())) return Short.TYPE;
342 if (type.equals(Float.TYPE.getName())) return Float.TYPE;
343 if (type.equals(Double.TYPE.getName())) return Double.TYPE;
344 if (type.equals(Void.TYPE.getName())) return Void.TYPE;
345
346 return null;
347 }
348
349 }