View Javadoc
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.rmi.RemoteException;
8   import java.util.Collection;
9   import java.util.Hashtable;
10  import java.util.Map;
11  import java.util.Properties;
12  import java.util.Set;
13  
14  import javax.naming.Context;
15  import javax.naming.InvalidNameException;
16  import javax.naming.NameNotFoundException;
17  import javax.naming.NamingException;
18  import javax.naming.NoInitialContextException;
19  import javax.naming.NotContextException;
20  
21  import org.djutils.event.EventListener;
22  import org.djutils.event.EventListenerMap;
23  import org.djutils.event.EventType;
24  import org.djutils.event.reference.ReferenceType;
25  import org.djutils.exceptions.Throw;
26  import org.djutils.io.URLResource;
27  import org.djutils.logger.CategoryLogger;
28  
29  import nl.tudelft.simulation.naming.context.ContextFactory;
30  import nl.tudelft.simulation.naming.context.ContextInterface;
31  import nl.tudelft.simulation.naming.context.util.ContextUtil;
32  
33  /**
34   * InitialEventContext class. This class is the starting context for performing naming operations. The class is loosely based on
35   * InitialContext in the Java JNDI package, but creates a lightweight Context that implements the DSOL ContextInterface. The
36   * InitialEventContext is a singleton class.
37   * <p>
38   * Copyright (c) 2002-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
39   * for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
40   * project is distributed under a three-clause BSD-style license, which can be found at
41   * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">
42   * https://https://simulation.tudelft.nl/dsol/docs/latest/license.html</a>.
43   * </p>
44   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
45   */
46  @SuppressWarnings("checkstyle:needbraces")
47  public final class InitialEventContext implements EventContext
48  {
49      /** */
50      private static final long serialVersionUID = 20200101L;
51  
52      /**
53       * Constant that holds the name of the environment property for specifying the initial context factory to use. The value of
54       * the property should be the fully qualified class name of the factory class that will create an initial context. This
55       * property may be specified in the environment parameter passed to the initial context constructor, a system property, or
56       * an application resource file. If it is not specified in any of these sources, {@code NoInitialContextException} is thrown
57       * when an initial context is required to complete an operation.
58       * <p>
59       * The value of this constant is "java.naming.factory.initial".
60       * </p>
61       */
62      public static final String INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial";
63  
64      /**
65       * Constant that holds the name of the environment property for specifying configuration information for the service
66       * provider to use. The value of the property should contain a URL string (e.g. "http://localhost:1099/remoteContext"). This
67       * property may be specified in the environment, a system property, or a resource file. If it is not specified in any of
68       * these sources, the default configuration is determined by the service provider.
69       * <p>
70       * The value of this constant is "java.naming.provider.url".
71       * </p>
72       */
73      public static final String PROVIDER_URL = "java.naming.provider.url";
74  
75      /**
76       * Constant that holds the name of the environment property for specifying the initial context factory to use, as embedded
77       * factory in a remote context that is specified by the INITIAL_CONTEXT_FACTORY constant. The value of the property should
78       * be the fully qualified class name of the factory class that will create an initial context that will be embedded within
79       * the remote context. This property may be specified in the environment parameter passed to the initial context
80       * constructor, a system property, or an application resource file. If it is not specified in any of these sources,
81       * {@code NoInitialContextException} is thrown when an initial context is required to complete an operation.
82       * <p>
83       * The value of this constant is "wrapped.naming.factory.initial".
84       * </p>
85       */
86      public static final String WRAPPED_CONTEXT_FACTORY = "wrapped.naming.factory.initial";
87  
88      /** the singleton instance of the InitialEventContext. */
89      private static InitialEventContext INSTANCE;
90  
91      /** the properties of the initialEventContext. */
92      protected Hashtable<?, ?> properties = null;
93  
94      /**
95       * The initial context, usually built by a factory. It is set by getDefaultInitCtx() the first time getDefaultInitCtx() is
96       * called. Subsequent invocations of getDefaultInitCtx() return the value of defaultInitCtx until close() is called.
97       */
98      protected ContextInterface defaultInitCtx = null;
99  
100     /** has the default context been generated? */
101     protected boolean gotDefault = false;
102 
103     /** The event producer to which context events will be delegated for handling. */
104     public ContextEventProducerImpl contextEventProducerImpl;
105 
106     /**
107      * Constructs an initial context. No environment properties are supplied. Equivalent to
108      * <code>new InitialContext(null)</code>.
109      * @param environment the overriding environment variables for the Factory that constructs the wrapped Context
110      * @param atomicName String; the name under which the root context will be registered
111      * @throws NamingException if a naming exception is encountered
112      * @throws RemoteException if a network connection failure occurs
113      */
114     private InitialEventContext(final Hashtable<?, ?> environment, final String atomicName)
115             throws NamingException, RemoteException
116     {
117         init(environment, atomicName);
118         this.contextEventProducerImpl = new ContextEventProducerImpl(this);
119     }
120 
121     /**
122      * Constructs an initial context using the supplied environment; no overriding environment variables are provided.
123      * @param atomicName String; the name under which the root context will be registered
124      * @return a singleton instance of InitialEventContext
125      * @throws NamingException when the provided ContextFactory was not able to instantiate the wrapped context
126      * @throws RemoteException if a network connection failure occurs
127      */
128     public static InitialEventContext instantiate(final String atomicName) throws NamingException, RemoteException
129     {
130         return instantiate(null, atomicName);
131     }
132 
133     /**
134      * Constructs an initial context using the supplied environment.
135      * @param environment Hashtable&lt;?,?&gt;; environment used to create the initial context. Null indicates an empty
136      *            environment.
137      * @param atomicName String; the name under which the root context will be registered
138      * @return a singleton instance of InitialEventContext
139      * @throws NamingException when the provided ContextFactory was not able to instantiate the wrapped context
140      * @throws RemoteException if a network connection failure occurs
141      */
142     public static InitialEventContext instantiate(final Hashtable<?, ?> environment, final String atomicName)
143             throws NamingException, RemoteException
144     {
145         if (INSTANCE != null)
146         {
147             return INSTANCE;
148         }
149 
150         INSTANCE = new InitialEventContext(environment, atomicName);
151         INSTANCE.init(environment == null ? null : (Hashtable<?, ?>) environment.clone(), atomicName);
152         return INSTANCE;
153     }
154 
155     /**
156      * Initializes the initial context using the supplied environment.
157      * @param environment Hashtable&lt;?,?&gt;; environment used to create the initial context. Null indicates an empty
158      *            environment.
159      * @param atomicName String; the name under which the root context will be registered
160      * @throws NamingException when the provided ContextFactory was not able to instantiate the wrapped context
161      * @throws RemoteException if a network connection failure occurs
162      */
163     protected void init(final Hashtable<?, ?> environment, final String atomicName) throws NamingException, RemoteException
164     {
165         this.properties = buildEnvironment(environment);
166         if (this.properties.get(Context.INITIAL_CONTEXT_FACTORY) != null)
167         {
168             getDefaultInitCtx(atomicName);
169         }
170     }
171 
172     /**
173      * Build the properties that the generation of the initial event context will use. In sequence, the following sources of
174      * properties are explored: (1) default values, (2) system environment, (3) Java system properties, (4) content of the
175      * /resources/jndi.properties file, (5) the provided environment. If a property is available in a later evaluation, it takes
176      * precedence over an earlier definition.
177      * @param environment the final overwriting environment to use (can be null)
178      * @return Hashtable&lt;?,?&gt;; a combined Hashtable with information from system properties, jndi.properties and the
179      *         provided environment Hashtable
180      */
181     protected Hashtable<?, ?> buildEnvironment(final Hashtable<?, ?> environment)
182     {
183         Hashtable<String, String> result = new Hashtable<>();
184         String[] keys = new String[] {INITIAL_CONTEXT_FACTORY, PROVIDER_URL, WRAPPED_CONTEXT_FACTORY};
185 
186         // (1) defaults
187         result.put(INITIAL_CONTEXT_FACTORY, "nl.tudelft.simulation.naming.context.JvmContextFactory");
188 
189         // (2) system properties
190         Map<String, String> sysEnv = System.getenv();
191         for (String key : keys)
192         {
193             if (sysEnv.containsKey(key))
194             {
195                 result.put(key, sysEnv.get(key));
196             }
197         }
198 
199         // (3) Java system properties
200         Properties javaProps = System.getProperties();
201         for (String key : keys)
202         {
203             if (javaProps.containsKey(key))
204             {
205                 result.put(key, javaProps.get(key).toString());
206             }
207         }
208 
209         // (4) content of the /resources/jndi.properties file
210         InputStream stream = URLResource.getResourceAsStream("/resources/jndi.properties");
211         if (stream != null)
212         {
213             Properties jndiProps = new Properties();
214             try
215             {
216                 jndiProps.load(stream);
217                 for (String key : keys)
218                 {
219                     if (jndiProps.containsKey(key))
220                     {
221                         result.put(key, jndiProps.get(key).toString());
222                     }
223                 }
224             }
225             catch (IOException exception)
226             {
227                 CategoryLogger.always().error(exception);
228             }
229         }
230 
231         // (5) the provided environment (if provided)
232         if (environment != null)
233         {
234             for (String key : keys)
235             {
236                 if (environment.containsKey(key))
237                 {
238                     result.put(key, environment.get(key).toString());
239                 }
240             }
241         }
242 
243         return result;
244     }
245 
246     /**
247      * Retrieves the initial context by calling NamingManager.getInitialContext() and cache it in defaultInitCtx. Set
248      * <code>gotDefault</code> so that we know we've tried this before.
249      * @param atomicName String; the name under which the root context will be registered
250      * @return The non-null cached initial context.
251      * @throws NamingException if a naming exception was encountered
252      * @throws RemoteException if a network connection failure occurs
253      */
254     protected ContextInterface getDefaultInitCtx(final String atomicName) throws NamingException, RemoteException
255     {
256         try
257         {
258             if (!this.gotDefault)
259             {
260                 String factoryName = this.properties.get(Context.INITIAL_CONTEXT_FACTORY).toString();
261                 Throw.when(factoryName == null, NamingException.class,
262                         "value of " + Context.INITIAL_CONTEXT_FACTORY + " not in properties");
263                 @SuppressWarnings("unchecked")
264                 Class<ContextFactory> factoryClass = (Class<ContextFactory>) Class.forName(factoryName);
265                 Constructor<ContextFactory> factoryConstructor = factoryClass.getDeclaredConstructor();
266                 ContextFactory factory = factoryConstructor.newInstance();
267                 this.defaultInitCtx = factory.getInitialContext(this.properties, atomicName);
268                 this.gotDefault = true;
269             }
270             if (this.defaultInitCtx == null)
271             {
272                 throw new NoInitialContextException();
273             }
274             return this.defaultInitCtx;
275         }
276         catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
277                 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
278         {
279             throw new NamingException("Unable to get default initial context: " + exception.getMessage());
280         }
281     }
282 
283     /**
284      * Return a safe copy of the used environment variables.
285      * @return Hashtable&lt;?, ?&gt;; a safe copy of the used environment variables
286      */
287     public Hashtable<?, ?> getEnvironment()
288     {
289         return (Hashtable<?, ?>) this.properties.clone();
290     }
291 
292     /** {@inheritDoc} */
293     @Override
294     public void close() throws NamingException, RemoteException
295     {
296         this.properties = null;
297         if (this.defaultInitCtx != null)
298         {
299             this.defaultInitCtx.close();
300             this.defaultInitCtx = null;
301         }
302         this.gotDefault = false;
303     }
304 
305     /** {@inheritDoc} */
306     @Override
307     public String getAtomicName() throws RemoteException
308     {
309         if (this.defaultInitCtx != null)
310             return this.defaultInitCtx.getAtomicName();
311         throw new RuntimeException(new NoInitialContextException());
312     }
313 
314     /** {@inheritDoc} */
315     @Override
316     public ContextInterface getParent() throws RemoteException
317     {
318         if (this.defaultInitCtx != null)
319             return this.defaultInitCtx.getParent();
320         throw new RuntimeException(new NoInitialContextException());
321 
322     }
323 
324     /** {@inheritDoc} */
325     @Override
326     public ContextInterface getRootContext() throws RemoteException
327     {
328         if (this.defaultInitCtx != null)
329             return this.defaultInitCtx.getRootContext();
330         throw new RuntimeException(new NoInitialContextException());
331     }
332 
333     /** {@inheritDoc} */
334     @Override
335     public String getAbsolutePath() throws RemoteException
336     {
337         if (this.defaultInitCtx != null)
338             return this.defaultInitCtx.getAbsolutePath();
339         throw new RuntimeException(new NoInitialContextException());
340     }
341 
342     /** {@inheritDoc} */
343     @Override
344     public Object get(final String name) throws NamingException, RemoteException
345     {
346         if (this.defaultInitCtx != null)
347             return this.defaultInitCtx.get(name);
348         throw new RuntimeException(new NoInitialContextException());
349     }
350 
351     /** {@inheritDoc} */
352     @Override
353     public Object getObject(final String key) throws NamingException, RemoteException
354     {
355         if (this.defaultInitCtx != null)
356             return this.defaultInitCtx.getObject(key);
357         throw new NoInitialContextException();
358     }
359 
360     /** {@inheritDoc} */
361     @Override
362     public boolean exists(final String name) throws NamingException, RemoteException
363     {
364         if (this.defaultInitCtx != null)
365             return this.defaultInitCtx.exists(name);
366         throw new NoInitialContextException();
367     }
368 
369     /** {@inheritDoc} */
370     @Override
371     public boolean hasKey(final String key) throws NamingException, RemoteException
372     {
373         if (this.defaultInitCtx != null)
374             return this.defaultInitCtx.hasKey(key);
375         throw new NoInitialContextException();
376     }
377 
378     /** {@inheritDoc} */
379     @Override
380     public boolean hasObject(final Object object) throws RemoteException
381     {
382         if (this.defaultInitCtx != null)
383             return this.defaultInitCtx.hasObject(object);
384         throw new RuntimeException(new NoInitialContextException());
385     }
386 
387     /** {@inheritDoc} */
388     @Override
389     public boolean isEmpty() throws RemoteException
390     {
391         if (this.defaultInitCtx != null)
392             return this.defaultInitCtx.isEmpty();
393         throw new RuntimeException(new NoInitialContextException());
394     }
395 
396     /** {@inheritDoc} */
397     @Override
398     public void bind(final String name, final Object object) throws NamingException, RemoteException
399     {
400         if (this.defaultInitCtx != null)
401             this.defaultInitCtx.bind(name, object);
402         else
403             throw new NoInitialContextException();
404     }
405 
406     /** {@inheritDoc} */
407     @Override
408     public void bindObject(final String key, final Object object) throws NamingException, RemoteException
409     {
410         if (this.defaultInitCtx != null)
411             this.defaultInitCtx.bindObject(key, object);
412         else
413             throw new NoInitialContextException();
414     }
415 
416     /** {@inheritDoc} */
417     @Override
418     public void bindObject(final Object object) throws NamingException, RemoteException
419     {
420         if (this.defaultInitCtx != null)
421             this.defaultInitCtx.bindObject(object);
422         else
423             throw new NoInitialContextException();
424     }
425 
426     /** {@inheritDoc} */
427     @Override
428     public void unbind(final String name) throws NamingException, RemoteException
429     {
430         if (this.defaultInitCtx != null)
431             this.defaultInitCtx.unbind(name);
432         else
433             throw new NoInitialContextException();
434     }
435 
436     /** {@inheritDoc} */
437     @Override
438     public void unbindObject(final String key) throws NamingException, RemoteException
439     {
440         if (this.defaultInitCtx != null)
441             this.defaultInitCtx.unbindObject(key);
442         else
443             throw new NoInitialContextException();
444     }
445 
446     /** {@inheritDoc} */
447     @Override
448     public void rebind(final String name, final Object object) throws NamingException, RemoteException
449     {
450         if (this.defaultInitCtx != null)
451             this.defaultInitCtx.rebind(name, object);
452         else
453             throw new NoInitialContextException();
454     }
455 
456     /** {@inheritDoc} */
457     @Override
458     public void rebindObject(final String key, final Object object) throws NamingException, RemoteException
459     {
460         if (this.defaultInitCtx != null)
461             this.defaultInitCtx.rebindObject(key, object);
462         else
463             throw new NoInitialContextException();
464     }
465 
466     /** {@inheritDoc} */
467     @Override
468     public void rename(final String oldName, final String newName) throws NamingException, RemoteException
469     {
470         if (this.defaultInitCtx != null)
471             this.defaultInitCtx.rename(oldName, newName);
472         else
473             throw new NoInitialContextException();
474     }
475 
476     /** {@inheritDoc} */
477     @Override
478     public ContextInterface createSubcontext(final String name) throws NamingException, RemoteException
479     {
480         if (this.defaultInitCtx != null)
481             return this.defaultInitCtx.createSubcontext(name);
482         else
483             throw new NoInitialContextException();
484     }
485 
486     /** {@inheritDoc} */
487     @Override
488     public void destroySubcontext(final String name) throws NamingException, RemoteException
489     {
490         if (this.defaultInitCtx != null)
491             this.defaultInitCtx.destroySubcontext(name);
492         else
493             throw new NoInitialContextException();
494     }
495 
496     /** {@inheritDoc} */
497     @Override
498     public void checkCircular(final Object newObject) throws NamingException, RemoteException
499     {
500         if (this.defaultInitCtx != null)
501             this.defaultInitCtx.checkCircular(newObject);
502         else
503             throw new NoInitialContextException();
504     }
505 
506     /** {@inheritDoc} */
507     @Override
508     public Set<String> keySet() throws RemoteException
509     {
510         if (this.defaultInitCtx != null)
511             return this.defaultInitCtx.keySet();
512         throw new RuntimeException(new NoInitialContextException());
513     }
514 
515     /** {@inheritDoc} */
516     @Override
517     public Collection<Object> values() throws RemoteException
518     {
519         if (this.defaultInitCtx != null)
520             return this.defaultInitCtx.values();
521         throw new RuntimeException(new NoInitialContextException());
522     }
523 
524     /** {@inheritDoc} */
525     @Override
526     public Map<String, Object> bindings() throws RemoteException
527     {
528         if (this.defaultInitCtx != null)
529             return this.defaultInitCtx.bindings();
530         throw new RuntimeException(new NoInitialContextException());
531     }
532 
533     /** {@inheritDoc} */
534     @Override
535     public void fireObjectChangedEventValue(final Object object)
536             throws NameNotFoundException, NullPointerException, NamingException, RemoteException
537     {
538         if (this.defaultInitCtx != null)
539             this.defaultInitCtx.fireObjectChangedEventValue(object);
540         else
541             throw new NoInitialContextException();
542     }
543 
544     /** {@inheritDoc} */
545     @Override
546     public void fireObjectChangedEventKey(final String key)
547             throws NameNotFoundException, NullPointerException, NamingException, RemoteException
548     {
549         if (this.defaultInitCtx != null)
550             this.defaultInitCtx.fireObjectChangedEventKey(key);
551         else
552             throw new NoInitialContextException();
553     }
554 
555     /** {@inheritDoc} */
556     @Override
557     public String toString()
558     {
559         if (this.defaultInitCtx != null)
560             return "InitialEventContext[" + this.defaultInitCtx.toString() + "]";
561         return "InitialEventContext[null]";
562     }
563 
564     /** {@inheritDoc} */
565     @Override
566     public String toString(final boolean verbose) throws RemoteException
567     {
568         if (!verbose)
569         {
570             return "InitialEventContext[" + getAtomicName() + "]";
571         }
572         return ContextUtil.toText(this);
573     }
574 
575     /* ***************************************************************************************************************** */
576     /* **************************************** EVENTPRODUCER IMPLEMENTATION ******************************************* */
577     /* ***************************************************************************************************************** */
578 
579     /** {@inheritDoc} */
580     @Override
581     public synchronized boolean addListener(final EventListener listener, final EventType eventType) throws RemoteException
582     {
583         if (this.defaultInitCtx != null)
584             return this.defaultInitCtx.addListener(listener, eventType);
585         throw new RuntimeException(new NoInitialContextException());
586     }
587 
588     /** {@inheritDoc} */
589     @Override
590     public synchronized boolean addListener(final EventListener listener, final EventType eventType,
591             final ReferenceType referenceType) throws RemoteException
592     {
593         if (this.defaultInitCtx != null)
594             return this.defaultInitCtx.addListener(listener, eventType, referenceType);
595         throw new RuntimeException(new NoInitialContextException());
596     }
597 
598     /** {@inheritDoc} */
599     @Override
600     public synchronized boolean addListener(final EventListener listener, final EventType eventType, final int position)
601             throws RemoteException
602     {
603         if (this.defaultInitCtx != null)
604             return this.defaultInitCtx.addListener(listener, eventType, position);
605         throw new RuntimeException(new NoInitialContextException());
606     }
607 
608     /** {@inheritDoc} */
609     @Override
610     public synchronized boolean addListener(final EventListener listener, final EventType eventType, final int position,
611             final ReferenceType referenceType) throws RemoteException
612     {
613         if (this.defaultInitCtx != null)
614             return this.defaultInitCtx.addListener(listener, eventType, position, referenceType);
615         throw new RuntimeException(new NoInitialContextException());
616     }
617 
618     /** {@inheritDoc} */
619     @Override
620     public synchronized boolean removeListener(final EventListener listener, final EventType eventType) throws RemoteException
621     {
622         if (this.defaultInitCtx != null)
623             return this.defaultInitCtx.removeListener(listener, eventType);
624         throw new RuntimeException(new NoInitialContextException());
625     }
626 
627     @Override
628     public EventListenerMap getEventListenerMap() throws RemoteException
629     {
630         if (this.defaultInitCtx != null)
631             return this.defaultInitCtx.getEventListenerMap();
632         throw new RuntimeException(new NoInitialContextException());
633     }
634 
635     /* ***************************************************************************************************************** */
636     /* *************************************** EVENTCONTEXTINTERFACE LISTENERS ***************************************** */
637     /* ***************************************************************************************************************** */
638 
639     /** {@inheritDoc} */
640     @Override
641     public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope)
642             throws RemoteException, NameNotFoundException, InvalidNameException, NotContextException, NamingException,
643             NullPointerException
644     {
645         if (this.defaultInitCtx != null)
646             return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope);
647         throw new RuntimeException(new NoInitialContextException());
648     }
649 
650     /** {@inheritDoc} */
651     @Override
652     public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope,
653             final ReferenceType referenceType) throws RemoteException, NameNotFoundException, InvalidNameException,
654             NotContextException, NamingException, NullPointerException
655     {
656         if (this.defaultInitCtx != null)
657             return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope, referenceType);
658         throw new RuntimeException(new NoInitialContextException());
659     }
660 
661     /** {@inheritDoc} */
662     @Override
663     public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope,
664             final int position) throws RemoteException, NameNotFoundException, InvalidNameException, NotContextException,
665             NamingException, NullPointerException
666     {
667         if (this.defaultInitCtx != null)
668             return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope, position);
669         throw new RuntimeException(new NoInitialContextException());
670     }
671 
672     /** {@inheritDoc} */
673     @Override
674     public boolean addListener(final EventListener listener, final String absolutePath, final ContextScope contextScope,
675             final int position, final ReferenceType referenceType) throws RemoteException, NameNotFoundException,
676             InvalidNameException, NotContextException, NamingException, NullPointerException
677     {
678         if (this.defaultInitCtx != null)
679             return this.contextEventProducerImpl.addListener(listener, absolutePath, contextScope, position, referenceType);
680         throw new RuntimeException(new NoInitialContextException());
681     }
682 
683     /** {@inheritDoc} */
684     @Override
685     public boolean removeListener(final EventListener listener, final String absolutePath, final ContextScope contextScope)
686             throws RemoteException, InvalidNameException, NullPointerException
687     {
688         if (this.defaultInitCtx != null)
689             return this.contextEventProducerImpl.removeListener(listener, absolutePath, contextScope);
690         throw new RuntimeException(new NoInitialContextException());
691     }
692 
693     /** {@inheritDoc} */
694     @Override
695     public int removeAllListeners()
696     {
697         if (this.defaultInitCtx != null)
698             return this.contextEventProducerImpl.removeAllListeners();
699         throw new RuntimeException(new NoInitialContextException());
700     }
701 
702 }