1 9 package org.jboss.remoting; 10 11 import java.io.IOException ; 12 import java.net.InetAddress ; 13 import java.util.HashMap ; 14 import java.util.Iterator ; 15 import java.util.Map ; 16 import javax.management.MBeanServer ; 17 import javax.management.MBeanServerInvocationHandler ; 18 import javax.management.MalformedObjectNameException ; 19 import javax.management.ObjectName ; 20 import org.jboss.remoting.callback.Callback; 21 import org.jboss.remoting.callback.InvokerCallbackHandler; 22 import org.jboss.remoting.callback.ServerInvokerCallbackHandler; 23 import org.jboss.remoting.invocation.InternalInvocation; 24 import org.jboss.remoting.invocation.OnewayInvocation; 25 import org.jboss.remoting.loading.ClassBytes; 26 import org.jboss.remoting.stream.StreamHandler; 27 import org.jboss.remoting.stream.StreamInvocationHandler; 28 import org.jboss.remoting.transport.PortUtil; 29 import org.jboss.util.threadpool.BasicThreadPool; 30 import org.jboss.util.threadpool.BlockingMode; 31 import org.jboss.util.threadpool.ThreadPool; 32 import org.jboss.util.threadpool.ThreadPoolMBean; 33 34 42 public abstract class ServerInvoker extends AbstractInvoker implements ServerInvokerMBean 43 { 44 public static final String MAX_NUM_ONEWAY_THREADS_KEY = "maxNumThreadsOneway"; 45 public static final String ONEWAY_THREAD_POOL_CLASS_KEY = "onewayThreadPool"; 46 public static final String SERVER_BIND_ADDRESS_KEY = "serverBindAddress"; 47 public static final String CLIENT_CONNECT_ADDRESS_KEY = "clientConnectAddress"; 48 public static final String SERVER_BIND_PORT_KEY = "serverBindPort"; 49 public static final String CLIENT_CONNECT_PORT_KEY = "clientConnectPort"; 50 51 56 public static final int MAX_NUM_ONEWAY_THREADS = 100; 57 58 61 private int maxNumberThreads = MAX_NUM_ONEWAY_THREADS; 62 private String onewayThreadPoolClass = null; 63 private ThreadPool onewayThreadPool; 64 65 protected Map handlers = new HashMap (); 66 protected Map callbackHandlers = new HashMap (); 67 private Map clientCallbackListener = new HashMap (); 68 private boolean started = false; 69 private boolean created = false; 70 71 private MBeanServer mbeanServer = null; 72 73 private Map configuration = new HashMap (); 74 75 private String dataType; 76 77 private String serverBindAddress = null; 78 private int serverBindPort = 0; 79 private String clientConnectAddress = null; 80 private int clientConnectPort = -1; 81 82 83 public ServerInvoker(InvokerLocator locator) 84 { 85 super(locator); 86 Map params = locator.getParameters(); 87 if(configuration != null && params != null) 88 { 89 configuration.putAll(locator.getParameters()); 90 } 91 } 92 93 public ServerInvoker(InvokerLocator locator, Map configuration) 94 { 95 super(locator); 96 this.configuration = configuration; 97 Map locatorParams = locator.getParameters(); 98 if(configuration != null && locatorParams != null) 99 { 100 configuration.putAll(locator.getParameters()); 101 } 102 } 103 104 protected void setup() throws Exception 105 { 106 Map config = getConfiguration(); 107 String maxNumOfThreads = (String ) config.get(MAX_NUM_ONEWAY_THREADS_KEY); 108 if(maxNumOfThreads != null && maxNumOfThreads.length() > 0) 109 { 110 try 111 { 112 maxNumberThreads = Integer.parseInt(maxNumOfThreads); 113 } 114 catch(NumberFormatException e) 115 { 116 log.error("Can not convert max number of threads value (" + maxNumOfThreads + ") into a number."); 117 } 118 } 119 onewayThreadPoolClass = (String ) config.get(ONEWAY_THREAD_POOL_CLASS_KEY); 120 121 String locatorHost = locator.getHost(); 122 InetAddress addr = null; 123 if(locatorHost != null) 124 { 125 addr = InetAddress.getByName(locator.getHost()); 126 } 127 else 128 { 129 addr = InetAddress.getLocalHost(); 130 } 131 int port = locator.getPort(); 132 if(port <= 0) 133 { 134 port = PortUtil.findFreePort(); 135 InvokerLocator newLocator = new InvokerLocator(locator.getProtocol(), locator.getHost(), port, locator.getPath(), locator.getParameters()); 137 InvokerRegistry.updateServerInvokerLocator(locator, newLocator); 139 this.locator = newLocator; 140 } 141 142 serverBindAddress = (String ) config.get(SERVER_BIND_ADDRESS_KEY); 144 clientConnectAddress = (String ) config.get(CLIENT_CONNECT_ADDRESS_KEY); 145 if(serverBindAddress == null) 146 { 147 if(clientConnectAddress != null) 148 { 149 serverBindAddress = InetAddress.getLocalHost().getHostAddress(); 151 } 152 else 153 { 154 serverBindAddress = addr.getHostAddress(); 155 } 156 } 157 158 String serverBindPortString = (String ) config.get(SERVER_BIND_PORT_KEY); 160 String clientConnectPortString = (String ) config.get(CLIENT_CONNECT_PORT_KEY); 161 if(clientConnectPortString != null) 162 { 163 try 164 { 165 clientConnectPort = Integer.parseInt(clientConnectPortString); 166 } 167 catch(NumberFormatException e) 168 { 169 throw new InvalidConfigurationException("Can not set client bind port because can not convert given value (" + clientConnectPortString + ") to a number."); 170 } 171 } 172 if(serverBindPortString != null) 173 { 174 try 175 { 176 serverBindPort = Integer.parseInt(serverBindPortString); 177 if(serverBindPort <= 0) 178 { 179 serverBindPort = PortUtil.findFreePort(); 180 InvokerLocator newLocator = new InvokerLocator(locator.getProtocol(), locator.getHost(), serverBindPort, locator.getPath(), locator.getParameters()); 182 InvokerRegistry.updateServerInvokerLocator(locator, newLocator); 184 this.locator = newLocator; 185 } 186 187 } 188 catch(NumberFormatException e) 189 { 190 throw new InvalidConfigurationException("Can not set server bind port because can not convert given value (" + serverBindPortString + ") to a number."); 191 } 192 } 193 else 194 { 195 if(clientConnectPort > 0) 196 { 197 serverBindPort = PortUtil.findFreePort(); 199 } 200 else 201 { 202 serverBindPort = port; 203 } 204 } 205 } 206 207 210 public String getClientConnectAddress() 211 { 212 return clientConnectAddress; 213 } 214 215 public int getClientConnectPort() 216 { 217 return clientConnectPort; 218 } 219 220 public void setClientConnectPort(int clientConnectPort) 221 { 222 this.clientConnectPort = clientConnectPort; 223 } 224 225 234 public void setClientConnectAddress(String clientConnectAddress) 235 { 236 this.clientConnectAddress = clientConnectAddress; 237 } 238 239 240 public String getServerBindAddress() 241 { 242 return serverBindAddress; 243 } 244 245 public int getServerBindPort() 246 { 247 return serverBindPort; 248 } 249 250 251 public void setMaxNumberOfOnewayThreads(int numOfThreads) 252 { 253 this.maxNumberThreads = numOfThreads; 254 } 255 256 public int getMaxNumberOfOnewayThreads() 257 { 258 return this.maxNumberThreads; 259 } 260 261 public ThreadPool getOnewayThreadPool() 262 { 263 if(onewayThreadPool == null) 264 { 265 if(onewayThreadPoolClass == null || onewayThreadPoolClass.length() == 0) 267 { 268 BasicThreadPool pool = new BasicThreadPool("JBossRemoting Client Oneway"); 269 pool.setMaximumPoolSize(maxNumberThreads); 270 pool.setBlockingMode(BlockingMode.WAIT); 271 onewayThreadPool = pool; 272 } 273 else 274 { 275 boolean isObjName = false; 277 try 278 { 279 ObjectName objName = new ObjectName (onewayThreadPoolClass); 280 onewayThreadPool = createThreadPoolProxy(objName); 281 isObjName = true; 282 } 283 catch(MalformedObjectNameException e) 284 { 285 log.debug("Thread pool class supplied is not an object name."); 286 } 287 288 if(!isObjName) 289 { 290 try 291 { 292 onewayThreadPool = (ThreadPool) getClassLoader().loadClass(onewayThreadPoolClass).newInstance(); 293 } 294 catch(Exception e) 295 { 296 throw new RuntimeException ("Error loading instance of ThreadPool based on class name: " + onewayThreadPoolClass); 297 } 298 } 299 300 } 301 302 } 303 return onewayThreadPool; 304 } 305 306 public void setOnewayThreadPool(ThreadPool pool) 307 { 308 this.onewayThreadPool = pool; 309 } 310 311 private ThreadPool createThreadPoolProxy(ObjectName objName) 312 { 313 ThreadPool pool; 314 MBeanServer server = getMBeanServer(); 315 if(server != null) 316 { 317 ThreadPoolMBean poolMBean = (ThreadPoolMBean) 318 MBeanServerInvocationHandler.newProxyInstance(server, 319 objName, 320 ThreadPoolMBean.class, 321 false); 322 pool = poolMBean.getInstance(); 323 } 324 else 325 { 326 throw new RuntimeException ("Can not register MBean ThreadPool as the ServerInvoker has not been registered with a MBeanServer."); 327 } 328 return pool; 329 } 330 331 332 public MBeanServer getMBeanServer() 333 { 334 return mbeanServer; 335 } 336 337 public void setMBeanServer(MBeanServer server) 338 { 339 348 this.mbeanServer = server; 349 } 350 351 357 public synchronized boolean hasInvocationHandler(String subsystem) 358 { 359 return handlers.containsKey(subsystem); 360 } 361 362 367 public synchronized String [] getSupportedSubsystems() 368 { 369 String subsystems [] = new String [handlers.size()]; 370 return (String []) handlers.keySet().toArray(subsystems); 371 } 372 373 378 public synchronized ServerInvocationHandler[] getInvocationHandlers() 379 { 380 ServerInvocationHandler ih [] = new ServerInvocationHandler[handlers.size()]; 381 return (ServerInvocationHandler[]) handlers.values().toArray(ih); 382 } 383 384 393 public synchronized ServerInvocationHandler addInvocationHandler(String subsystem, ServerInvocationHandler handler) 394 { 395 handler.setInvoker(this); 396 return (ServerInvocationHandler) handlers.put(subsystem.toUpperCase(), handler); 397 } 398 399 404 public synchronized ServerInvocationHandler removeInvocationHandler(String subsystem) 405 { 406 return (ServerInvocationHandler) handlers.remove(subsystem.toUpperCase()); 407 } 408 409 415 public synchronized ServerInvocationHandler getInvocationHandler(String subsystem) 416 { 417 return (ServerInvocationHandler) handlers.get(subsystem.toUpperCase()); 418 } 419 420 public Object invoke(Object invoke) throws IOException 421 { 422 InvocationRequest request = null; 423 InvocationResponse response = null; 424 425 if(log.isTraceEnabled()) 426 { 427 log.trace("server received invocation =>" + invoke); 428 } 429 430 if(invoke != null && invoke instanceof InvocationRequest) 431 { 432 request = (InvocationRequest) invoke; 433 try 434 { 435 436 Object result = invoke(request); 437 438 response = new InvocationResponse(request.getSessionId(), 439 result, false, request.getReturnPayload()); 440 441 } 442 catch(Throwable throwable) 443 { 444 if(log.isTraceEnabled()) 445 { 446 throwable.printStackTrace(); 447 } 448 response = new InvocationResponse(request.getSessionId(), 449 throwable, true, request.getReturnPayload()); 450 } 451 } 452 else 453 { 454 log.error("server invoker received " + invoke + " as invocation. Must not be null and must be of type InvocationRequest."); 455 response = new InvocationResponse(request.getSessionId(), 456 new Exception ("Error processing invocation request on " + getLocator() + ". Either invocation was null or of wrong type."), 457 true, request.getReturnPayload()); 458 } 459 return response; 460 461 } 462 463 471 public String getDataType() 472 { 473 if(dataType == null) 474 { 475 dataType = getDataType(getLocator()); 476 if(dataType == null) 477 { 478 dataType = getDefaultDataType(); 479 } 480 } 481 return dataType; 482 } 483 484 private String getDataType(InvokerLocator locator) 486 { 487 String type = null; 488 489 if(locator != null) 490 { 491 Map params = locator.getParameters(); 492 if(params != null) 493 { 494 type = (String ) params.get(InvokerLocator.DATATYPE); 495 } 496 } 497 return type; 498 } 499 500 protected abstract String getDefaultDataType(); 501 502 510 public Object invoke(InvocationRequest invocation) throws Throwable 511 { 512 Object param = invocation.getParameter(); 513 Object result = null; 514 515 if("$PING$".equals(param)) 517 { 518 return new InvocationResponse(invocation.getSessionId(), Boolean.TRUE, false, null); 520 } 521 522 if(param instanceof OnewayInvocation) 525 { 526 handleOnewayInvocation((OnewayInvocation) param, invocation); 527 } 528 else { 530 String subsystem = invocation.getSubsystem(); 531 String clientId = invocation.getSessionId(); 532 533 ServerInvocationHandler handler = null; 536 if(subsystem != null) 537 { 538 handler = (ServerInvocationHandler) handlers.get(subsystem.toUpperCase()); 539 } 540 else 541 { 542 if(!handlers.isEmpty()) 544 { 545 handler = (ServerInvocationHandler) handlers.values().iterator().next(); 546 } 547 } 548 if(param instanceof InternalInvocation) 549 { 550 result = handleInternalInvocation((InternalInvocation) param, invocation, handler); 551 552 } 553 else 554 { 555 if(log.isTraceEnabled()) 556 { 557 log.trace("dispatching invocation: " + invocation + " to subsystem: " + subsystem + " from client: " + clientId); 558 } 559 560 if(handler == null) 561 { 562 throw new InvalidConfigurationException("Can not handle invocation request because there are no " + 563 "ServerInvocationHandlers registered. Please add via xml configuration " + 564 "or via the Connector's addInvocationHandler() method."); 565 } 566 result = handler.invoke(invocation); 567 } 568 if(log.isTraceEnabled()) 569 { 570 log.trace("dispatch invocation, returning back: " + result + " from subsystem: " + subsystem + 571 " to client: " + clientId); 572 } 573 } 574 575 576 return result; 577 } 578 579 587 private void handleOnewayInvocation(OnewayInvocation onewayInvocation, InvocationRequest invocation) throws Throwable 588 { 589 Object [] objs = onewayInvocation.getParameters(); 590 Object realParam = objs[0]; 592 invocation.setParameter(realParam); 593 final InvocationRequest newInvocation = invocation; 594 595 ThreadPool executor = getOnewayThreadPool(); 596 Runnable onewayRun = new Runnable () 597 { 598 public void run() 599 { 600 try 601 { 602 invoke(newInvocation); 603 } 604 catch(Throwable e) 605 { 606 log.error("Error executing server oneway invocation request: " + newInvocation, e); 608 } 609 } 610 }; 611 executor.run(onewayRun); 612 } 613 614 624 private Object handleInternalInvocation(InternalInvocation param, 625 InvocationRequest invocation, 626 ServerInvocationHandler handler) 627 throws Throwable 628 { 629 Object result = null; 630 String methodName = param.getMethodName(); 631 if(log.isTraceEnabled()) 632 { 633 log.trace("handling InternalInvocation where method name = " + methodName); 634 } 635 if(InternalInvocation.ADDLISTENER.equals(methodName)) 637 { 638 if(handler == null) 639 { 640 throw new InvalidConfigurationException("Can not accept a callback listener since there are no " + 641 "ServerInvocationHandlers registered. Please add via xml configuration " + 642 "or via the Connector's addInvocationHandler() method."); 643 644 } 645 InvokerCallbackHandler callbackHandler = getCallbackHandler(invocation); 646 handler.addListener(callbackHandler); 647 } 648 else if(InternalInvocation.REMOVELISTENER.equals(methodName)) 649 { 650 ServerInvokerCallbackHandler callbackHandler = removeCallbackHandler(invocation); 651 if(callbackHandler != null) 652 { 653 if(handler == null) 654 { 655 throw new InvalidConfigurationException("Can not remove a callback listener since there are no " + 656 "ServerInvocationHandlers registered. Please add via xml configuration " + 657 "or via the Connector's addInvocationHandler() method."); 658 } 659 handler.removeListener(callbackHandler); 660 if(log.isTraceEnabled()) 661 { 662 log.trace("ServerInvoker (" + this + ") removing server callback handler " + callbackHandler + "."); 663 } 664 665 callbackHandler.destroy(); 666 } 667 else 668 { 669 String sessionId = ServerInvokerCallbackHandler.getId(invocation); 670 throw new RuntimeException ("Can not remove callback listener from target server with id of " + sessionId + " as it does not exist as a registered callback listener."); 671 } 672 } 673 else if(InternalInvocation.GETCALLBACKS.equals(methodName)) 674 { 675 ServerInvokerCallbackHandler callbackHandler = getCallbackHandler(invocation); 676 if(log.isTraceEnabled()) 677 { 678 log.trace("ServerInvoker (" + this + ") getting callbacks for callback handler " + callbackHandler + "."); 679 } 680 681 result = callbackHandler.getCallbacks(); 682 } 683 else if(InternalInvocation.ADDCLIENTLISTENER.equals(methodName)) 684 { 685 String sessionId = ServerInvokerCallbackHandler.getId(invocation); 686 Object [] params = param.getParameters(); 687 if(params == null || params.length < 0 || params.length > 3) 689 { 690 log.error("Recieved addClientListener InternalInvocation, but getParameters() " + 691 "returned: " + params); 692 throw new RuntimeException ("InvokerCallbackHandler and callback handle object (optional) must be supplied as the only " + 693 "parameter objects within the InternalInvocation when " + 694 "calling addClientListener."); 695 } 696 InvokerCallbackHandler callbackHandler = (InvokerCallbackHandler) params[0]; 697 Object callbackHandleObject = params[1]; 698 CallbackContainer callbackContainer = new CallbackContainer(callbackHandler, callbackHandleObject); 699 clientCallbackListener.put(sessionId, callbackContainer); 700 701 log.debug("ServerInvoker (" + this + ") added client callback handler " + callbackHandler + " with session id of " + sessionId + 702 " and callback handle object of " + callbackHandleObject + "."); 703 704 } 705 else if(InternalInvocation.REMOVECLIENTLISTENER.equals(methodName)) 706 { 707 String sessionId = ServerInvokerCallbackHandler.getId(invocation); 708 log.debug("ServerInvoker (" + this + ") removing client callback handler with session id of " + sessionId + "."); 709 Object cbo = clientCallbackListener.remove(sessionId); 710 if(cbo == null) 711 { 712 throw new RuntimeException ("Can not remove callback listener from callback server with id of " + sessionId + " as it does not exist as a registered callback listener."); 713 } 714 715 } 716 else if(InternalInvocation.HANDLECALLBACK.equals(methodName)) 717 { 718 String sessionId = ServerInvokerCallbackHandler.getId(invocation); 719 if(log.isTraceEnabled()) 720 { 721 log.trace("ServerInvoker (" + this + ") is being asked to deliver callback on client callback handler with session id of " + sessionId + "."); 722 } 723 CallbackContainer callbackContainer = (CallbackContainer) clientCallbackListener.get(sessionId); 724 if(callbackContainer != null && callbackContainer.getCallbackHandler() != null) 725 { 726 Object [] params = param.getParameters(); 727 Callback callbackRequest = (Callback) params[0]; 728 Map callbackHandleObject = callbackRequest.getReturnPayload(); 729 if(callbackHandleObject == null) 730 { 731 callbackHandleObject = new HashMap (); 732 } 733 callbackHandleObject.put(Callback.CALLBACK_HANDLE_OBJECT_KEY, callbackContainer.getCallbackHandleObject()); 734 callbackRequest.setReturnPayload(callbackHandleObject); 735 InvokerCallbackHandler callbackHandler = callbackContainer.getCallbackHandler(); 736 callbackHandler.handleCallback(callbackRequest); 737 } 738 else 739 { 740 log.error("Could not find callback handler to call upon for handleCallback " + 741 "where session id equals " + sessionId); 742 } 743 744 745 } 746 else if(InternalInvocation.ADDSTREAMCALLBACK.equals(methodName)) 747 { 748 StreamHandler streamHandler = getStreamHandler(invocation); 749 if(handler instanceof StreamInvocationHandler) 750 { 751 InternalInvocation inv = (InternalInvocation) invocation.getParameter(); 752 result = ((StreamInvocationHandler) handler).handleStream(streamHandler, inv.getParameters()[1]); 754 } 755 else 756 { 757 log.error("Client request is an InputStream, but the registered handlers do not " + 758 "implement the StreamInvocationHandler interface, so could not process call."); 759 throw new RuntimeException ("No handler registered of proper type (StreamInvocationHandler)."); 760 } 761 } 762 else 763 { 764 log.error("Error processing InternalInvocation. Unable to process method " + 765 methodName + ". Please make sure this should be an InternalInvocation."); 766 throw new RuntimeException ("Error processing InternalInvocation. Unable to process method " + 767 methodName); 768 } 769 return result; 770 } 771 772 private StreamHandler getStreamHandler(InvocationRequest invocation) throws Exception 773 { 774 InternalInvocation inv = (InternalInvocation) invocation.getParameter(); 775 String locator = (String ) inv.getParameters()[0]; 776 StreamHandler streamHandler = new StreamHandler(locator); 777 return streamHandler; 779 } 780 781 private ServerInvokerCallbackHandler getCallbackHandler(InvocationRequest invocation) throws Exception 782 { 783 ServerInvokerCallbackHandler callbackHandler = null; 784 String id = ServerInvokerCallbackHandler.getId(invocation); 785 786 synchronized(callbackHandlers) 787 { 788 callbackHandler = (ServerInvokerCallbackHandler) callbackHandlers.get(id); 789 if(callbackHandler == null) 791 { 792 callbackHandler = new ServerInvokerCallbackHandler(invocation, getLocator(), this); 793 callbackHandlers.put(id, callbackHandler); 794 } 795 } 796 if(log.isTraceEnabled()) 797 { 798 log.trace("ServerInvoker (" + this + ") adding server callback handler " + callbackHandler + " with id of " + id + "."); 799 } 800 801 return callbackHandler; 802 } 803 804 private ServerInvokerCallbackHandler removeCallbackHandler(InvocationRequest invocation) 805 { 806 String id = ServerInvokerCallbackHandler.getId(invocation); 807 ServerInvokerCallbackHandler callbackHandler = null; 808 809 synchronized(callbackHandlers) 810 { 811 callbackHandler = (ServerInvokerCallbackHandler) callbackHandlers.remove(id); 812 } 813 return callbackHandler; 814 } 815 816 817 825 protected void preProcess(String sessionId, ClassBytes arg, Map payload, InvokerLocator locator) 826 { 827 } 828 829 837 protected void postProcess(String sessionId, Object param, Map payload, InvokerLocator locator) 838 { 839 } 840 841 public void create() 842 { 843 if(!created) 844 { 845 try 846 { 847 setup(); 848 } 849 catch(Exception e) 850 { 851 throw new RuntimeException ("Error setting up server invoker " + this, e); 852 } 853 created = true; 854 } 855 } 856 857 862 public void start() throws IOException 863 { 864 started = true; 865 log.info("Invoker started for locator: " + getLocator()); 866 } 867 868 873 public boolean isStarted() 874 { 875 return started; 876 } 877 878 881 public void stop() 882 { 883 started = false; 884 } 885 886 889 public void destroy() 890 { 891 if(classbyteloader != null) 892 { 893 classbyteloader.destroy(); 894 } 895 } 896 897 903 public void setConfigration(Map configuration) 904 { 905 this.configuration = configuration; 906 } 907 908 913 public Map getConfiguration() 914 { 915 return configuration; 916 } 917 918 923 public String getMBeanObjectName() 924 { 925 InvokerLocator locator = getLocator(); 926 StringBuffer buffer = new StringBuffer ("jboss.remoting:service=invoker,transport= " + locator.getProtocol()); 927 buffer.append(",host=" + locator.getHost()); 928 buffer.append(",port=" + locator.getPort()); 929 Map param = locator.getParameters(); 930 if(param != null) 931 { 932 Iterator itr = param.keySet().iterator(); 933 while(itr.hasNext()) 934 { 935 buffer.append(","); 936 String key = (String ) itr.next(); 937 String value = (String ) param.get(key); 938 buffer.append(key); 939 buffer.append("="); 940 buffer.append(value); 941 } 942 } 943 return buffer.toString(); 944 } 945 946 private class CallbackContainer 947 { 948 private InvokerCallbackHandler handler; 949 private Object handleObject; 950 951 public CallbackContainer(InvokerCallbackHandler handler, Object handleObject) 952 { 953 this.handler = handler; 954 this.handleObject = handleObject; 955 } 956 957 public InvokerCallbackHandler getCallbackHandler() 958 { 959 return handler; 960 } 961 962 public Object getCallbackHandleObject() 963 { 964 return handleObject; 965 } 966 } 967 } 968 | Popular Tags |