1 package nl.tudelft.simulation.naming.context.event;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.lang.reflect.Constructor;
6 import java.lang.reflect.InvocationTargetException;
7 import java.util.Collection;
8 import java.util.Hashtable;
9 import java.util.Map;
10 import java.util.Properties;
11 import java.util.Set;
12
13 import javax.naming.Context;
14 import javax.naming.InvalidNameException;
15 import javax.naming.NameNotFoundException;
16 import javax.naming.NamingException;
17 import javax.naming.NoInitialContextException;
18 import javax.naming.NotContextException;
19
20 import org.djutils.event.EventListener;
21 import org.djutils.event.EventListenerMap;
22 import org.djutils.event.EventType;
23 import org.djutils.event.reference.ReferenceType;
24 import org.djutils.exceptions.Throw;
25 import org.djutils.io.ResourceResolver;
26 import org.djutils.logger.CategoryLogger;
27
28 import nl.tudelft.simulation.naming.context.ContextFactory;
29 import nl.tudelft.simulation.naming.context.ContextInterface;
30 import nl.tudelft.simulation.naming.context.util.ContextUtil;
31
32
33
34
35
36
37
38
39
40
41
42
43
44 @SuppressWarnings("checkstyle:needbraces")
45 public final class InitialEventContext implements EventContext
46 {
47
48
49
50
51
52
53
54
55
56
57 public static final String INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial";
58
59
60
61
62
63
64
65
66
67
68 public static final String PROVIDER_URL = "java.naming.provider.url";
69
70
71
72
73
74
75
76
77
78
79
80
81 public static final String WRAPPED_CONTEXT_FACTORY = "wrapped.naming.factory.initial";
82
83
84 private static InitialEventContext INSTANCE;
85
86
87 protected Hashtable<?, ?> properties = null;
88
89
90
91
92
93 protected ContextInterface defaultInitCtx = null;
94
95
96 protected boolean gotDefault = false;
97
98
99 public ContextEventProducerImpl contextEventProducerImpl;
100
101
102
103
104
105
106
107
108 private InitialEventContext(final Hashtable<?, ?> environment, final String atomicName) throws NamingException
109 {
110 init(environment, atomicName);
111 this.contextEventProducerImpl = new ContextEventProducerImpl(this);
112 }
113
114
115
116
117
118
119
120 public static InitialEventContext instantiate(final String atomicName) throws NamingException
121 {
122 return instantiate(null, atomicName);
123 }
124
125
126
127
128
129
130
131
132 public static InitialEventContext instantiate(final Hashtable<?, ?> environment, final String atomicName)
133 throws NamingException
134 {
135 if (INSTANCE != null)
136 {
137 return INSTANCE;
138 }
139
140 INSTANCE = new InitialEventContext(environment, atomicName);
141 INSTANCE.init(environment == null ? null : (Hashtable<?, ?>) environment.clone(), atomicName);
142 return INSTANCE;
143 }
144
145
146
147
148
149
150
151 protected void init(final Hashtable<?, ?> environment, final String atomicName) throws NamingException
152 {
153 this.properties = buildEnvironment(environment);
154 if (this.properties.get(Context.INITIAL_CONTEXT_FACTORY) != null)
155 {
156 getDefaultInitCtx(atomicName);
157 }
158 }
159
160
161
162
163
164
165
166
167
168
169 protected Hashtable<?, ?> buildEnvironment(final Hashtable<?, ?> environment)
170 {
171 Hashtable<String, String> result = new Hashtable<>();
172 String[] keys = new String[] {INITIAL_CONTEXT_FACTORY, PROVIDER_URL, WRAPPED_CONTEXT_FACTORY};
173
174
175 result.put(INITIAL_CONTEXT_FACTORY, "nl.tudelft.simulation.naming.context.JvmContextFactory");
176
177
178 Map<String, String> sysEnv = System.getenv();
179 for (String key : keys)
180 {
181 if (sysEnv.containsKey(key))
182 {
183 result.put(key, sysEnv.get(key));
184 }
185 }
186
187
188 Properties javaProps = System.getProperties();
189 for (String key : keys)
190 {
191 if (javaProps.containsKey(key))
192 {
193 result.put(key, javaProps.get(key).toString());
194 }
195 }
196
197
198 try
199 {
200 InputStream stream = ResourceResolver.resolve("/jndi.properties").openStream();
201 if (stream != null)
202 {
203 Properties jndiProps = new Properties();
204 jndiProps.load(stream);
205 for (String key : keys)
206 {
207 if (jndiProps.containsKey(key))
208 {
209 result.put(key, jndiProps.get(key).toString());
210 }
211 }
212 }
213 }
214 catch (IOException exception)
215 {
216 CategoryLogger.always().error(exception);
217 }
218
219
220 if (environment != null)
221 {
222 for (String key : keys)
223 {
224 if (environment.containsKey(key))
225 {
226 result.put(key, environment.get(key).toString());
227 }
228 }
229 }
230
231 return result;
232 }
233
234
235
236
237
238
239
240
241 protected ContextInterface getDefaultInitCtx(final String atomicName) throws NamingException
242 {
243 try
244 {
245 if (!this.gotDefault)
246 {
247 String factoryName = this.properties.get(Context.INITIAL_CONTEXT_FACTORY).toString();
248 Throw.when(factoryName == null, NamingException.class,
249 "value of " + Context.INITIAL_CONTEXT_FACTORY + " not in properties");
250 @SuppressWarnings("unchecked")
251 Class<ContextFactory> factoryClass = (Class<ContextFactory>) Class.forName(factoryName);
252 Constructor<ContextFactory> factoryConstructor = factoryClass.getDeclaredConstructor();
253 ContextFactory factory = factoryConstructor.newInstance();
254 this.defaultInitCtx = factory.getInitialContext(this.properties, atomicName);
255 this.gotDefault = true;
256 }
257 if (this.defaultInitCtx == null)
258 {
259 throw new NoInitialContextException();
260 }
261 return this.defaultInitCtx;
262 }
263 catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
264 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
265 {
266 throw new NamingException("Unable to get default initial context: " + exception.getMessage());
267 }
268 }
269
270
271
272
273
274 public Hashtable<?, ?> getEnvironment()
275 {
276 return (Hashtable<?, ?>) this.properties.clone();
277 }
278
279 @Override
280 public void close() throws NamingException
281 {
282 this.properties = null;
283 if (this.defaultInitCtx != null)
284 {
285 this.defaultInitCtx.close();
286 this.defaultInitCtx = null;
287 }
288 this.gotDefault = false;
289 }
290
291 @Override
292 public String getAtomicName()
293 {
294 if (this.defaultInitCtx != null)
295 return this.defaultInitCtx.getAtomicName();
296 throw new RuntimeException(new NoInitialContextException());
297 }
298
299 @Override
300 public ContextInterface getParent()
301 {
302 if (this.defaultInitCtx != null)
303 return this.defaultInitCtx.getParent();
304 throw new RuntimeException(new NoInitialContextException());
305
306 }
307
308 @Override
309 public ContextInterface getRootContext()
310 {
311 if (this.defaultInitCtx != null)
312 return this.defaultInitCtx.getRootContext();
313 throw new RuntimeException(new NoInitialContextException());
314 }
315
316 @Override
317 public String getAbsolutePath()
318 {
319 if (this.defaultInitCtx != null)
320 return this.defaultInitCtx.getAbsolutePath();
321 throw new RuntimeException(new NoInitialContextException());
322 }
323
324 @Override
325 public Object get(final String name) throws NamingException
326 {
327 if (this.defaultInitCtx != null)
328 return this.defaultInitCtx.get(name);
329 throw new RuntimeException(new NoInitialContextException());
330 }
331
332 @Override
333 public Object getObject(final String key) throws NamingException
334 {
335 if (this.defaultInitCtx != null)
336 return this.defaultInitCtx.getObject(key);
337 throw new NoInitialContextException();
338 }
339
340 @Override
341 public boolean exists(final String name) throws NamingException
342 {
343 if (this.defaultInitCtx != null)
344 return this.defaultInitCtx.exists(name);
345 throw new NoInitialContextException();
346 }
347
348 @Override
349 public boolean hasKey(final String key) throws NamingException
350 {
351 if (this.defaultInitCtx != null)
352 return this.defaultInitCtx.hasKey(key);
353 throw new NoInitialContextException();
354 }
355
356 @Override
357 public boolean hasObject(final Object object)
358 {
359 if (this.defaultInitCtx != null)
360 return this.defaultInitCtx.hasObject(object);
361 throw new RuntimeException(new NoInitialContextException());
362 }
363
364 @Override
365 public boolean isEmpty()
366 {
367 if (this.defaultInitCtx != null)
368 return this.defaultInitCtx.isEmpty();
369 throw new RuntimeException(new NoInitialContextException());
370 }
371
372 @Override
373 public void bind(final String name, final Object object) throws NamingException
374 {
375 if (this.defaultInitCtx != null)
376 this.defaultInitCtx.bind(name, object);
377 else
378 throw new NoInitialContextException();
379 }
380
381 @Override
382 public void bindObject(final String key, final Object object) throws NamingException
383 {
384 if (this.defaultInitCtx != null)
385 this.defaultInitCtx.bindObject(key, object);
386 else
387 throw new NoInitialContextException();
388 }
389
390 @Override
391 public void bindObject(final Object object) throws NamingException
392 {
393 if (this.defaultInitCtx != null)
394 this.defaultInitCtx.bindObject(object);
395 else
396 throw new NoInitialContextException();
397 }
398
399 @Override
400 public void unbind(final String name) throws NamingException
401 {
402 if (this.defaultInitCtx != null)
403 this.defaultInitCtx.unbind(name);
404 else
405 throw new NoInitialContextException();
406 }
407
408 @Override
409 public void unbindObject(final String key) throws NamingException
410 {
411 if (this.defaultInitCtx != null)
412 this.defaultInitCtx.unbindObject(key);
413 else
414 throw new NoInitialContextException();
415 }
416
417 @Override
418 public void rebind(final String name, final Object object) throws NamingException
419 {
420 if (this.defaultInitCtx != null)
421 this.defaultInitCtx.rebind(name, object);
422 else
423 throw new NoInitialContextException();
424 }
425
426 @Override
427 public void rebindObject(final String key, final Object object) throws NamingException
428 {
429 if (this.defaultInitCtx != null)
430 this.defaultInitCtx.rebindObject(key, object);
431 else
432 throw new NoInitialContextException();
433 }
434
435 @Override
436 public void rename(final String oldName, final String newName) throws NamingException
437 {
438 if (this.defaultInitCtx != null)
439 this.defaultInitCtx.rename(oldName, newName);
440 else
441 throw new NoInitialContextException();
442 }
443
444 @Override
445 public ContextInterface createSubcontext(final String name) throws NamingException
446 {
447 if (this.defaultInitCtx != null)
448 return this.defaultInitCtx.createSubcontext(name);
449 else
450 throw new NoInitialContextException();
451 }
452
453 @Override
454 public void destroySubcontext(final String name) throws NamingException
455 {
456 if (this.defaultInitCtx != null)
457 this.defaultInitCtx.destroySubcontext(name);
458 else
459 throw new NoInitialContextException();
460 }
461
462 @Override
463 public void checkCircular(final Object newObject) throws NamingException
464 {
465 if (this.defaultInitCtx != null)
466 this.defaultInitCtx.checkCircular(newObject);
467 else
468 throw new NoInitialContextException();
469 }
470
471 @Override
472 public Set<String> keySet()
473 {
474 if (this.defaultInitCtx != null)
475 return this.defaultInitCtx.keySet();
476 throw new RuntimeException(new NoInitialContextException());
477 }
478
479 @Override
480 public Collection<Object> values()
481 {
482 if (this.defaultInitCtx != null)
483 return this.defaultInitCtx.values();
484 throw new RuntimeException(new NoInitialContextException());
485 }
486
487 @Override
488 public Map<String, Object> bindings()
489 {
490 if (this.defaultInitCtx != null)
491 return this.defaultInitCtx.bindings();
492 throw new RuntimeException(new NoInitialContextException());
493 }
494
495 @Override
496 public void fireObjectChangedEventValue(final Object object)
497 throws NameNotFoundException, NullPointerException, NamingException
498 {
499 if (this.defaultInitCtx != null)
500 this.defaultInitCtx.fireObjectChangedEventValue(object);
501 else
502 throw new NoInitialContextException();
503 }
504
505 @Override
506 public void fireObjectChangedEventKey(final String key) throws NameNotFoundException, NullPointerException, NamingException
507 {
508 if (this.defaultInitCtx != null)
509 this.defaultInitCtx.fireObjectChangedEventKey(key);
510 else
511 throw new NoInitialContextException();
512 }
513
514 @Override
515 public String toString()
516 {
517 if (this.defaultInitCtx != null)
518 return "InitialEventContext[" + this.defaultInitCtx.toString() + "]";
519 return "InitialEventContext[null]";
520 }
521
522 @Override
523 public String toString(final boolean verbose)
524 {
525 if (!verbose)
526 {
527 return "InitialEventContext[" + getAtomicName() + "]";
528 }
529 return ContextUtil.toText(this);
530 }
531
532
533
534
535
536 @Override
537 public synchronized boolean addListener(final EventListener listener, final EventType eventType)
538 {
539 if (this.defaultInitCtx != null)
540 return this.defaultInitCtx.addListener(listener, eventType);
541 throw new RuntimeException(new NoInitialContextException());
542 }
543
544 @Override
545 public synchronized boolean addListener(final EventListener listener, final EventType eventType,
546 final ReferenceType referenceType)
547 {
548 if (this.defaultInitCtx != null)
549 return this.defaultInitCtx.addListener(listener, eventType, referenceType);
550 throw new RuntimeException(new NoInitialContextException());
551 }
552
553 @Override
554 public synchronized boolean addListener(final EventListener listener, final EventType eventType, final int position)
555
556 {
557 if (this.defaultInitCtx != null)
558 return this.defaultInitCtx.addListener(listener, eventType, position);
559 throw new RuntimeException(new NoInitialContextException());
560 }
561
562 @Override
563 public synchronized boolean addListener(final EventListener listener, final EventType eventType, final int position,
564 final ReferenceType referenceType)
565 {
566 if (this.defaultInitCtx != null)
567 return this.defaultInitCtx.addListener(listener, eventType, position, referenceType);
568 throw new RuntimeException(new NoInitialContextException());
569 }
570
571 @Override
572 public synchronized boolean removeListener(final EventListener listener, final EventType eventType)
573 {
574 if (this.defaultInitCtx != null)
575 return this.defaultInitCtx.removeListener(listener, eventType);
576 throw new RuntimeException(new NoInitialContextException());
577 }
578
579 @Override
580 public EventListenerMap getEventListenerMap()
581 {
582 if (this.defaultInitCtx != null)
583 return this.defaultInitCtx.getEventListenerMap();
584 throw new RuntimeException(new NoInitialContextException());
585 }
586
587
588
589
590
591 @Override
592 public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope)
593 throws NameNotFoundException, InvalidNameException, NotContextException, NamingException, NullPointerException
594 {
595 if (this.defaultInitCtx != null)
596 return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope);
597 throw new RuntimeException(new NoInitialContextException());
598 }
599
600 @Override
601 public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope,
602 final ReferenceType referenceType)
603 throws NameNotFoundException, InvalidNameException, NotContextException, NamingException, NullPointerException
604 {
605 if (this.defaultInitCtx != null)
606 return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope, referenceType);
607 throw new RuntimeException(new NoInitialContextException());
608 }
609
610 @Override
611 public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope,
612 final int position)
613 throws NameNotFoundException, InvalidNameException, NotContextException, NamingException, NullPointerException
614 {
615 if (this.defaultInitCtx != null)
616 return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope, position);
617 throw new RuntimeException(new NoInitialContextException());
618 }
619
620 @Override
621 public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope,
622 final int position, final ReferenceType referenceType)
623 throws NameNotFoundException, InvalidNameException, NotContextException, NamingException, NullPointerException
624 {
625 if (this.defaultInitCtx != null)
626 return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope, position, referenceType);
627 throw new RuntimeException(new NoInitialContextException());
628 }
629
630 @Override
631 public boolean removeListener(final EventListener listener, final String absolutePath, final ContextScope contextScope)
632 throws InvalidNameException, NullPointerException
633 {
634 if (this.defaultInitCtx != null)
635 return this.contextEventProducerImpl.removeListener(listener, absolutePath, contextScope);
636 throw new RuntimeException(new NoInitialContextException());
637 }
638
639 @Override
640 public int removeAllListeners()
641 {
642 if (this.defaultInitCtx != null)
643 return this.contextEventProducerImpl.removeAllListeners();
644 throw new RuntimeException(new NoInitialContextException());
645 }
646
647 }