1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.intel.bluetooth.rmi;
27
28 import java.lang.reflect.InvocationHandler;
29 import java.lang.reflect.Method;
30 import java.lang.reflect.Proxy;
31 import java.rmi.NotBoundException;
32 import java.rmi.RemoteException;
33 import java.rmi.registry.LocateRegistry;
34 import java.rmi.registry.Registry;
35 import java.security.AccessControlContext;
36 import java.security.AccessController;
37 import java.security.PrivilegedActionException;
38 import java.security.PrivilegedExceptionAction;
39 import java.util.List;
40 import java.util.Vector;
41
42 public class Client {
43
44 private static final String rmiRegistryHostDefault = "localhost";
45
46 private static final int rmiRegistryPortDefault = Server.rmiRegistryPortDefault;
47
48 private static RemoteService remoteService;
49
50 private static class ServiceProxy implements InvocationHandler {
51
52 private AccessControlContext accessControlContext;
53
54 private ServiceProxy() {
55 accessControlContext = AccessController.getContext();
56 }
57
58 public Object invoke(Object proxy, final Method m, Object[] args) throws Throwable {
59 final ServiceRequest request = new ServiceRequest(m.getDeclaringClass().getCanonicalName(), m.getName(), m
60 .getParameterTypes(), args);
61 ServiceResponse response;
62 try {
63 response = AccessController.doPrivileged(new PrivilegedExceptionAction<ServiceResponse>() {
64 public ServiceResponse run() throws RuntimeException {
65 return execute(request, m);
66 }
67 }, accessControlContext);
68 } catch (PrivilegedActionException e) {
69 Throwable cause = e.getCause();
70 if (cause != null) {
71 throw new RuntimeException(cause.getMessage(), cause);
72 } else {
73 throw e;
74 }
75 }
76 if (response.getException() == null) {
77 return response.getReturnValue();
78 } else {
79 Throwable t = response.getException();
80
81 StackTraceElement[] remote = t.getStackTrace();
82 StackTraceElement[] curreent = Thread.currentThread().getStackTrace();
83 List<StackTraceElement> combined = new Vector<StackTraceElement>();
84 for (int i = 0; i < remote.length; i++) {
85 combined.add(remote[i]);
86 if ((remote[i].getMethodName().equals(m.getName()))
87 && (remote[i].getClassName().startsWith(m.getDeclaringClass().getCanonicalName()))) {
88 break;
89 }
90 }
91 int startClient = curreent.length;
92 for (int i = 0; i < curreent.length; i++) {
93 if (curreent[i].getClassName().equals(this.getClass().getName())) {
94 startClient = i + 1;
95 break;
96 }
97 }
98 for (int i = startClient; i < curreent.length; i++) {
99 combined.add(curreent[i]);
100 }
101 t.setStackTrace(combined.toArray(new StackTraceElement[combined.size()]));
102 throw t;
103 }
104 }
105 }
106
107 private static String getRemoteExceptionMessage(RemoteException e) {
108 String message = e.getMessage();
109 int idx = message.indexOf("; nested exception is:");
110 if (idx != -1) {
111 return message.substring(0, idx);
112 }
113 return message;
114 }
115
116 public synchronized static Object getService(Class<?> interfaceClass, boolean isMaster, String host, String port)
117 throws RuntimeException {
118 if (remoteService == null) {
119 try {
120 if (isMaster) {
121 if ((host != null) && (!"localhost".equals(host))) {
122 throw new IllegalArgumentException("Can't start RMI registry while connecting to remote host "
123 + host);
124 }
125 Server.start(port);
126 }
127 remoteService = getRemoteService(host, port);
128 remoteService.verify(interfaceClass.getCanonicalName());
129 } catch (RemoteException e) {
130 Throwable t = (e.getCause() != null) ? e.getCause() : e;
131 throw new RuntimeException(getRemoteExceptionMessage(e), t);
132 } catch (NotBoundException e) {
133 throw new RuntimeException(e.getMessage(), e);
134 }
135 }
136 Class<?>[] allInterfaces = new Class[interfaceClass.getInterfaces().length + 1];
137 allInterfaces[0] = interfaceClass;
138 System.arraycopy(interfaceClass.getInterfaces(), 0, allInterfaces, 1, interfaceClass.getInterfaces().length);
139 return Proxy.newProxyInstance(interfaceClass.getClassLoader(), allInterfaces, new ServiceProxy());
140 }
141
142 private static ServiceResponse execute(ServiceRequest request, Method method) throws RuntimeException {
143 try {
144 return remoteService.execute(request);
145 } catch (RemoteException e) {
146 Throwable t = (e.getCause() != null) ? e.getCause() : e;
147 throw new RuntimeException(getRemoteExceptionMessage(e), t);
148 }
149 }
150
151 private static RemoteService getRemoteService(String host, String port) throws RemoteException, NotBoundException {
152 String rmiHost = rmiRegistryHostDefault;
153 if ((host != null) && (host.length() > 0)) {
154 rmiHost = host;
155 }
156 int rmiPort = rmiRegistryPortDefault;
157 if ((port != null) && (port.length() > 0)) {
158 rmiPort = Integer.parseInt(port);
159 }
160 if (rmiPort == 0) {
161
162 return new RemoteServiceImpl();
163 } else {
164 Registry registry = LocateRegistry.getRegistry(rmiHost, rmiPort);
165 return (RemoteService) registry.lookup(RemoteService.SERVICE_NAME);
166 }
167 }
168 }