1 package nl.tudelft.simulation.naming.context;
2
3 import java.net.InetAddress;
4 import java.net.URL;
5 import java.rmi.ConnectException;
6 import java.rmi.NotBoundException;
7 import java.rmi.registry.LocateRegistry;
8 import java.rmi.registry.Registry;
9 import java.util.Hashtable;
10 import java.util.Iterator;
11
12 import javax.naming.Context;
13
14 import org.djutils.logger.CategoryLogger;
15
16 import nl.tudelft.simulation.naming.context.event.InitialEventContext;
17
18 /**
19 * A factory for RemoteContextClient instances, automatically invoked by JNDI when the correct jndi.properties file has been
20 * used.
21 * <p>
22 * Copyright (c) 2002-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
23 * for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
24 * project is distributed under a three-clause BSD-style license, which can be found at
25 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">
26 * https://https://simulation.tudelft.nl/dsol/docs/latest/license.html</a>.
27 * </p>
28 * @author <a href="https://www.linkedin.com/in/peterhmjacobs">Peter Jacobs </a>
29 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
30 */
31 public class RemoteContextFactory implements ContextFactory
32 {
33 /** context refers to the static RemoteContextClient. */
34 private static RemoteContext context = null;
35
36 /** {@inheritDoc} */
37 @Override
38 public synchronized ContextInterface getInitialContext(final Hashtable<?, ?> environment, final String atomicName)
39 {
40 // If the context is already looked up, let's return immediately
41 if (RemoteContextFactory.context != null)
42 {
43 return RemoteContextFactory.context;
44 }
45
46 // Let's look for our remote partner
47 try
48 {
49 URL url = new URL(environment.get(Context.PROVIDER_URL).toString());
50 Registry registry = LocateRegistry.getRegistry(url.getHost(), url.getPort());
51
52 // If there is no registry, registry!=null, so we have to test the registry
53 // to make sure whether there is one or not. We test by requesting a list. This code might be improved.
54 try
55 {
56 registry.list();
57 }
58 catch (ConnectException connectException)
59 {
60 // Since we cannot find the registry, we must perhaps create one.
61 // This is only allowed if the host is our localhost. We cannot create a registry on a remote host.
62 if (!(url.getHost().equals("localhost") || url.getHost().equals("127.0.0.1")
63 || url.getHost().equals(InetAddress.getLocalHost().getHostName())
64 || url.getHost().equals(InetAddress.getLocalHost().getHostAddress())))
65 {
66 throw new IllegalArgumentException("cannot create registry on remote host");
67 }
68 registry = LocateRegistry.createRegistry(url.getPort());
69 }
70 // We now have a registry. Let's resolve the context object
71
72 RemoteContext remoteContext = null;
73 try
74 {
75 remoteContext = (RemoteContext) registry.lookup(url.getFile());
76 }
77 catch (NotBoundException notBoundException)
78 {
79 // Since we cannot find the context, we must create one.
80 // This is done based on the java.naming.wrapped properties in jndi.properties
81 Hashtable<Object, Object> wrappedEnvironment = new Hashtable<Object, Object>();
82 for (Iterator<?> iterator = environment.keySet().iterator(); iterator.hasNext();)
83 {
84 String key = iterator.next().toString();
85 if (key.equals(InitialEventContext.WRAPPED_CONTEXT_FACTORY))
86 {
87 wrappedEnvironment.put(InitialEventContext.INITIAL_CONTEXT_FACTORY, environment.get(key));
88 }
89 }
90 if (wrappedEnvironment.isEmpty())
91 {
92 // If we do not throw this exception and accept an empty
93 // environment, we'll get in an infinite loop
94 throw new IllegalArgumentException("no wrapped initial context factory defined");
95 }
96 ContextInterface wrappedContext = InitialEventContext.instantiate(wrappedEnvironment, atomicName);
97 remoteContext = new RemoteContext(url, wrappedContext, url.getFile() + "_producer");
98 // registry.bind(url.getFile(), remoteContext);
99 }
100 RemoteContextFactory.context = remoteContext;
101 return RemoteContextFactory.context;
102 }
103 catch (Exception exception)
104 {
105 CategoryLogger.always().error(exception, "getInitialContext");
106 return null;
107 }
108 }
109 }