1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix.rmi;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.nio.file.Files;
23 import java.rmi.Naming;
24 import java.rmi.RemoteException;
25 import java.rmi.ServerException;
26 import java.rmi.registry.Registry;
27 import java.rmi.server.RMIClientSocketFactory;
28 import java.rmi.server.RMIServerSocketFactory;
29 import java.rmi.server.UnicastRemoteObject;
30 import java.util.Objects;
31 import java.util.concurrent.TimeUnit;
32
33 import org.newsclub.net.unix.AFUNIXSocket;
34
35
36
37
38
39
40
41 public final class AFUNIXNaming extends AFNaming {
42 private static final String PROP_RMI_SOCKET_DIR = "org.newsclub.net.unix.rmi.socketdir";
43 private static final File DEFAULT_SOCKET_DIRECTORY = new File(System.getProperty(
44 PROP_RMI_SOCKET_DIR, "/tmp"));
45
46 private boolean deleteRegistrySocketDir = false;
47 private final File registrySocketDir;
48
49 private final RMIClientSocketFactory defaultClientSocketFactory;
50 private final RMIServerSocketFactory defaultServerSocketFactory;
51
52 private final String socketPrefix;
53 private final String socketSuffix;
54
55 private AFUNIXNaming(File socketDir, int registryPort, String socketPrefix, String socketSuffix)
56 throws IOException {
57 super(registryPort, RMIPorts.RMI_SERVICE_PORT);
58 Objects.requireNonNull(socketDir);
59 this.registrySocketDir = socketDir;
60 this.socketPrefix = socketPrefix;
61 this.socketSuffix = socketSuffix;
62
63 this.defaultClientSocketFactory = null;
64 this.defaultServerSocketFactory = null;
65 }
66
67
68
69
70
71
72
73
74
75 public static File getDefaultSocketDirectory() {
76 return DEFAULT_SOCKET_DIRECTORY;
77 }
78
79
80
81
82
83
84
85
86 public static AFUNIXNaming newPrivateInstance() throws IOException {
87 File tmpDir = Files.createTempDirectory("junixsocket-").toFile();
88 if (!tmpDir.canWrite()) {
89 throw new IOException("Could not create temporary directory: " + tmpDir);
90 }
91 AFUNIXNaming instance = getInstance(tmpDir, RMIPorts.DEFAULT_REGISTRY_PORT);
92 synchronized (instance) {
93 instance.deleteRegistrySocketDir = true;
94 }
95 return instance;
96 }
97
98
99
100
101
102
103
104
105 public static AFUNIXNaming getInstance() throws IOException {
106 return getInstance(DEFAULT_SOCKET_DIRECTORY, RMIPorts.DEFAULT_REGISTRY_PORT);
107 }
108
109
110
111
112
113
114
115
116
117 public static AFUNIXNaming getInstance(final File socketDir) throws RemoteException {
118 return getInstance(socketDir, RMIPorts.DEFAULT_REGISTRY_PORT);
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public static AFUNIXNaming getInstance(File socketDir, final int registryPort)
134 throws RemoteException {
135 return getInstance(socketDir, registryPort, null, null);
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public static AFUNIXNaming getInstance(File socketDir, final int registryPort,
154 String socketPrefix, String socketSuffix) throws RemoteException {
155 return AFNaming.getInstance(registryPort, new AFUNIXNamingProvider(socketDir, socketPrefix,
156 socketSuffix));
157 }
158
159 private static final class AFUNIXNamingProvider implements AFNamingProvider<AFUNIXNaming> {
160 private final File socketDir;
161 private final String socketPrefix;
162 private final String socketSuffix;
163
164 public AFUNIXNamingProvider(File socketDir, String socketPrefix, String socketSuffix)
165 throws RemoteException {
166 try {
167 this.socketDir = socketDir.getCanonicalFile();
168 } catch (IOException e) {
169 throw new RemoteException(e.getMessage(), e);
170 }
171 this.socketPrefix = socketPrefix == null ? AFUNIXRMISocketFactory.DEFAULT_SOCKET_FILE_PREFIX
172 : socketPrefix;
173 this.socketSuffix = socketSuffix == null ? AFUNIXRMISocketFactory.DEFAULT_SOCKET_FILE_SUFFIX
174 : socketSuffix;
175 }
176
177 @Override
178 public AFUNIXNaming newInstance(int port) throws IOException {
179 return new AFUNIXNaming(socketDir, port, socketPrefix, socketSuffix);
180 }
181 }
182
183
184
185
186
187
188
189
190
191 public static AFNaming getSingleFileInstance(final File socketFile) throws IOException {
192 return getInstance(socketFile, RMIPorts.PLAIN_FILE_SOCKET);
193 }
194
195 @Override
196 public AFUNIXRMISocketFactory getSocketFactory() {
197 return (AFUNIXRMISocketFactory) super.getSocketFactory();
198 }
199
200 @Override
201 public AFRegistry getRegistry() throws RemoteException {
202 return getRegistry(0, TimeUnit.SECONDS);
203 }
204
205 @Override
206 public AFUNIXRegistry getRegistry(long timeout, TimeUnit unit) throws RemoteException {
207 return (AFUNIXRegistry) super.getRegistry(timeout, unit);
208 }
209
210 @Override
211 public AFUNIXRegistry getRegistry(boolean create) throws RemoteException {
212 return (AFUNIXRegistry) super.getRegistry(create);
213 }
214
215 @Override
216 public AFUNIXRegistry createRegistry() throws RemoteException {
217 return (AFUNIXRegistry) super.createRegistry();
218 }
219
220
221
222
223
224
225
226
227 public File getRegistrySocketFile() {
228 return getSocketFactory().getFile(getRegistryPort());
229 }
230
231 @Override
232 protected AFUNIXRMISocketFactory initSocketFactory() throws IOException {
233 return new AFUNIXRMISocketFactory(this, registrySocketDir, defaultClientSocketFactory,
234 defaultServerSocketFactory, socketPrefix, socketSuffix);
235 }
236
237 @Override
238 protected AFUNIXRegistry newAFRegistry(Registry impl) throws RemoteException {
239 return new AFUNIXRegistry(this, impl);
240 }
241
242 @Override
243 protected AFRegistry openRegistry(long timeout, TimeUnit unit) throws RemoteException {
244 File socketFile = getRegistrySocketFile();
245 if (!socketFile.exists()) {
246 if (waitUntilFileExists(socketFile, timeout, unit)) {
247 AFRegistry reg = getRegistry(false);
248 if (reg != null) {
249 return reg;
250 }
251 }
252 }
253 throw new ShutdownException("Could not find registry at " + getRegistrySocketFile());
254 }
255
256 private boolean waitUntilFileExists(File f, long timeout, TimeUnit unit) {
257 long timeWait = unit.toMillis(timeout);
258
259 try {
260 while (timeWait > 0 && !f.exists()) {
261 Thread.sleep(Math.min(50, timeWait));
262 timeWait -= 50;
263 }
264 } catch (InterruptedException e) {
265
266 }
267
268 return f.exists();
269 }
270
271 private synchronized void deleteSocketDir() {
272 if (deleteRegistrySocketDir && registrySocketDir != null) {
273 try {
274 Files.delete(registrySocketDir.toPath());
275 } catch (IOException e) {
276
277 }
278 }
279 }
280
281 @Override
282 protected void shutdownRegistryFinishingTouches() {
283 deleteSocketDir();
284 }
285
286
287
288
289
290
291 public File getRegistrySocketDir() {
292 return registrySocketDir;
293 }
294
295 @Override
296 protected void initRegistryPrerequisites() throws ServerException {
297 if (registrySocketDir != null && !registrySocketDir.mkdirs() && !registrySocketDir
298 .isDirectory()) {
299 throw new ServerException("Cannot create socket directory:" + registrySocketDir);
300 }
301 }
302 }