1 22 package org.jboss.jmx.connector.invoker; 23 24 import java.lang.reflect.InvocationTargetException ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.UndeclaredThrowableException ; 27 import java.rmi.RemoteException ; 28 import java.util.Collections ; 29 import java.util.HashMap ; 30 import java.util.HashSet ; 31 import java.util.Map ; 32 import java.security.Principal ; 33 import javax.management.InstanceNotFoundException ; 34 import javax.management.ListenerNotFoundException ; 35 import javax.management.MBeanServer ; 36 import javax.management.Notification ; 37 import javax.management.NotificationFilter ; 38 import javax.management.NotificationListener ; 39 import javax.management.ObjectName ; 40 41 import org.jboss.invocation.Invocation; 42 import org.jboss.invocation.MarshalledInvocation; 43 import org.jboss.jmx.adaptor.rmi.RMINotificationListener; 44 import org.jboss.jmx.connector.invoker.client.InvokerAdaptorException; 45 import org.jboss.mx.server.ServerConstants; 46 import org.jboss.system.Registry; 47 import org.jboss.system.ServiceMBeanSupport; 48 49 73 public class InvokerAdaptorService 74 extends ServiceMBeanSupport 75 implements InvokerAdaptorServiceMBean, ServerConstants 76 { 77 private ObjectName mbeanRegistry; 78 79 private Map marshalledInvocationMapping = new HashMap (); 80 81 private Class [] exportedInterfaces; 82 83 private HashSet addNotificationListeners = new HashSet (); 84 85 private HashSet removeNotificationListeners = new HashSet (); 86 88 protected HashMap remoteListeners = new HashMap (); 89 90 public InvokerAdaptorService() 91 { 92 } 93 94 97 public Class [] getExportedInterfaces() 98 { 99 return exportedInterfaces; 100 } 101 104 public void setExportedInterfaces(Class [] exportedInterfaces) 105 { 106 this.exportedInterfaces = exportedInterfaces; 107 } 108 109 protected void startService() 110 throws Exception 111 { 112 mbeanRegistry = new ObjectName (MBEAN_REGISTRY); 113 114 HashMap tmpMap = new HashMap (61); 116 for(int n = 0; n < exportedInterfaces.length; n ++) 117 { 118 Class iface = exportedInterfaces[n]; 119 Method [] methods = iface.getMethods(); 120 for(int m = 0; m < methods.length; m ++) 121 { 122 Method method = methods[m]; 123 Long hash = new Long (MarshalledInvocation.calculateHash(method)); 124 tmpMap.put(hash, method); 125 } 126 130 try 131 { 132 Class [] sig = {ObjectName .class, RMINotificationListener.class, 133 NotificationFilter .class, Object .class}; 134 Method addNotificationListener = iface.getMethod( 135 "addNotificationListener", sig); 136 addNotificationListeners.add(addNotificationListener); 137 } 138 catch(Exception e) 139 { 140 log.debug(iface+"No addNotificationListener(ObjectName, RMINotificationListener)"); 141 } 142 143 146 try 147 { 148 Class [] sig = {ObjectName .class, RMINotificationListener.class}; 149 Method removeNotificationListener = iface.getMethod( 150 "removeNotificationListener", sig); 151 removeNotificationListeners.add(removeNotificationListener); 152 } 153 catch(Exception e) 154 { 155 log.debug(iface+"No removeNotificationListener(ObjectName, RMINotificationListener)"); 156 } 157 } 158 marshalledInvocationMapping = Collections.unmodifiableMap(tmpMap); 159 160 Registry.bind(new Integer (serviceName.hashCode()), serviceName); 162 } 163 164 protected void stopService() 165 throws Exception 166 { 167 if( exportedInterfaces != null ) 169 { 170 for(int n = 0; n < exportedInterfaces.length; n ++) 171 MarshalledInvocation.removeHashes(exportedInterfaces[n]); 172 } 173 marshalledInvocationMapping = null; 174 remoteListeners.clear(); 175 Registry.unbind(new Integer (serviceName.hashCode())); 176 } 177 178 185 public Map getMethodMap() 186 { 187 return marshalledInvocationMapping; 188 } 189 190 200 public Object invoke(Invocation invocation) 201 throws Exception 202 { 203 try 204 { 205 ClassLoader oldCL = SecurityActions.getContextClassLoader(); 207 208 ClassLoader newCL = null; 209 ObjectName objectName = (ObjectName ) invocation.getValue("JMX_OBJECT_NAME"); 211 if (objectName != null) 212 { 213 newCL = (ClassLoader ) server.invoke 215 ( 216 mbeanRegistry, "getValue", 217 new Object [] { objectName, CLASSLOADER }, 218 new String [] { ObjectName .class.getName(), String .class.getName() } 219 ); 220 } 221 222 if (newCL != null && newCL != oldCL) 223 SecurityActions.setContextClassLoader(newCL); 224 225 try 226 { 227 if (invocation instanceof MarshalledInvocation) 229 { 230 MarshalledInvocation mi = (MarshalledInvocation) invocation; 231 mi.setMethodMap(marshalledInvocationMapping); 232 } 233 Method method = invocation.getMethod(); 235 Object [] args = invocation.getArguments(); 236 Principal principal = invocation.getPrincipal(); 237 Object credential = invocation.getCredential(); 238 Object value = null; 239 SecurityActions.pushSubjectContext(principal, credential, null); 241 242 try 243 { 244 if( addNotificationListeners.contains(method) ) 245 { 246 ObjectName name = (ObjectName ) args[0]; 247 RMINotificationListener listener = (RMINotificationListener) 248 args[1]; 249 NotificationFilter filter = (NotificationFilter ) args[2]; 250 Object handback = args[3]; 251 addNotificationListener(name, listener, filter, handback); 252 } 253 else if( removeNotificationListeners.contains(method) ) 254 { 255 ObjectName name = (ObjectName ) args[0]; 256 RMINotificationListener listener = (RMINotificationListener) 257 args[1]; 258 removeNotificationListener(name, listener); 259 } 260 else 261 { 262 String name = method.getName(); 263 Class [] paramTypes = method.getParameterTypes(); 264 Method mbeanServerMethod = MBeanServer .class.getMethod(name, 265 paramTypes); 266 value = mbeanServerMethod.invoke(server, args); 267 } 268 } 269 catch(InvocationTargetException e) 270 { 271 Throwable t = e.getTargetException(); 272 if( t instanceof Exception ) 273 throw (Exception ) t; 274 else 275 throw new UndeclaredThrowableException (t, method.toString()); 276 } 277 278 return value; 279 } 280 finally 281 { 282 SecurityActions.popSubjectContext(); 284 if (newCL != null && newCL != oldCL) 286 SecurityActions.setContextClassLoader(oldCL); 287 } 288 } 289 catch (Throwable t) 290 { 291 throw new InvokerAdaptorException(t); 292 } 293 } 294 295 public void addNotificationListener(ObjectName name, 296 RMINotificationListener listener, NotificationFilter filter, 297 Object handback) 298 throws InstanceNotFoundException , RemoteException 299 { 300 if( log.isTraceEnabled() ) 301 log.trace("addNotificationListener, name="+name+", listener="+listener); 302 NotificationListenerDelegate delegate = 303 new NotificationListenerDelegate(listener, name); 304 remoteListeners.put(listener, delegate); 305 getServer().addNotificationListener(name, delegate, filter, handback); 306 } 307 308 public void removeNotificationListener(ObjectName name, 309 RMINotificationListener listener) 310 throws InstanceNotFoundException , ListenerNotFoundException , 311 RemoteException 312 { 313 if( log.isTraceEnabled() ) 314 log.trace("removeNotificationListener, name="+name+", listener="+listener); 315 NotificationListenerDelegate delegate = (NotificationListenerDelegate) 316 remoteListeners.remove(listener); 317 if( delegate == null ) 318 throw new ListenerNotFoundException ("No listener matches: "+listener); 319 getServer().removeNotificationListener(name, delegate); 320 } 321 322 private class NotificationListenerDelegate 323 implements NotificationListener 324 { 325 326 private RMINotificationListener client; 327 328 private ObjectName targetName; 329 330 public NotificationListenerDelegate(RMINotificationListener client, 331 ObjectName targetName) 332 { 333 this.client = client; 334 this.targetName = targetName; 335 } 336 337 public void handleNotification(Notification notification, 338 Object handback) 339 { 340 try 341 { 342 if( log.isTraceEnabled() ) 343 { 344 log.trace("Sending notification to client, event:"+notification); 345 } 346 client.handleNotification(notification, handback); 347 } 348 catch(Throwable t) 349 { 350 log.debug("Failed to notify client, unregistering listener", t); 351 try 352 { 353 removeNotificationListener(targetName, client); 354 } 355 catch(Exception e) 356 { 357 log.debug("Failed to unregister listener", e); 358 } 359 } 360 } 361 } 362 363 } 364 | Popular Tags |