1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: ORBRemoteContext.java,v 1.1 2005/11/18 03:29:41 tanderson Exp $
44 */
45 package org.exolab.jms.jndi;
46
47 import java.util.Hashtable;
48 import java.util.NoSuchElementException;
49 import javax.naming.Binding;
50 import javax.naming.Context;
51 import javax.naming.Name;
52 import javax.naming.NameParser;
53 import javax.naming.NamingEnumeration;
54 import javax.naming.NamingException;
55
56 import org.codehaus.spice.jndikit.RemoteContext;
57 import org.exolab.jms.net.proxy.Proxy;
58
59
60 /***
61 * <code>Context</code> implementation that reference counts the
62 * underlying provider.
63 *
64 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
65 * @version $Revision: 1.1 $ $Date: 2005/11/18 03:29:41 $
66 */
67 class ORBRemoteContext implements Context {
68
69 /***
70 * Environment key for the naming provider reference counter.
71 */
72 private static String REFERENCE_KEY = "NamingProviderReferenceCounter";
73
74 /***
75 * The context.
76 */
77 private RemoteContext _context;
78
79
80 /***
81 * Construct a new <code>ORBRemoteContext</code>.
82 *
83 * @param context the context to delegate requests to
84 * @throws NamingException for any error
85 */
86 public ORBRemoteContext(RemoteContext context) throws NamingException {
87 _context = context;
88 reference();
89 }
90
91 /***
92 * Retrieves the named object.
93 *
94 * @param name the name of the object to look up
95 * @return the object bound to <tt>name</tt>
96 * @throws NamingException if a naming exception is encountered
97 */
98 public Object lookup(Name name) throws NamingException {
99 return wrap(_context.lookup(name));
100 }
101
102 /***
103 * Retrieves the named object.
104 *
105 * @param name the name of the object to look up
106 * @return the object bound to <tt>name</tt>
107 * @throws NamingException if a naming exception is encountered
108 */
109 public Object lookup(String name) throws NamingException {
110 return wrap(_context.lookup(name));
111 }
112
113 /***
114 * Binds a name to an object.
115 *
116 * @param name the name to bind; may not be empty
117 * @param obj the object to bind; possibly null
118 * @throws NamingException if a naming exception is encountered
119 */
120 public void bind(Name name, Object obj) throws NamingException {
121 _context.bind(name, obj);
122 }
123
124 /***
125 * Binds a name to an object.
126 *
127 * @param name the name to bind; may not be empty
128 * @param obj the object to bind; possibly null
129 * @throws NamingException if a naming exception is encountered
130 */
131 public void bind(String name, Object obj) throws NamingException {
132 _context.bind(name, obj);
133 }
134
135 /***
136 * Binds a name to an object, overwriting any existing binding.
137 *
138 * @param name the name to bind; may not be empty
139 * @param obj the object to bind; possibly null
140 * @throws NamingException if a naming exception is encountered
141 */
142 public void rebind(Name name, Object obj) throws NamingException {
143 _context.rebind(name, obj);
144 }
145
146 /***
147 * Binds a name to an object, overwriting any existing binding.
148 *
149 * @param name the name to bind; may not be empty
150 * @param obj the object to bind; possibly null
151 * @throws NamingException if a naming exception is encountered
152 */
153 public void rebind(String name, Object obj) throws NamingException {
154 _context.rebind(name, obj);
155 }
156
157 /***
158 * Unbinds the named object.
159 *
160 * @param name the name to unbind; may not be empty
161 * @throws NamingException if a naming exception is encountered
162 */
163 public void unbind(Name name) throws NamingException {
164 _context.unbind(name);
165 }
166
167 /***
168 * Unbinds the named object.
169 *
170 * @param name the name to unbind; may not be empty
171 * @throws NamingException if a naming exception is encountered
172 */
173 public void unbind(String name) throws NamingException {
174 _context.unbind(name);
175 }
176
177 /***
178 * Binds a new name to the object bound to an old name, and unbinds
179 * the old name.
180 *
181 * @param oldName the name of the existing binding; may not be empty
182 * @param newName the name of the new binding; may not be empty
183 * @throws NamingException if a naming exception is encountered
184 */
185 public void rename(Name oldName, Name newName) throws NamingException {
186 _context.rename(oldName, newName);
187 }
188
189 /***
190 * Binds a new name to the object bound to an old name, and unbinds
191 * the old name.
192 *
193 * @param oldName the name of the existing binding; may not be empty
194 * @param newName the name of the new binding; may not be empty
195 * @throws NamingException if a naming exception is encountered
196 */
197 public void rename(String oldName, String newName) throws NamingException {
198 _context.rename(oldName, newName);
199 }
200
201 /***
202 * Enumerates the names bound in the named context, along with the
203 * class names of objects bound to them.
204 *
205 * @param name the name of the context to list
206 * @return an enumeration of the names and class names of the
207 * bindings in this context. Each element of the
208 * enumeration is of type <tt>NameClassPair</tt>.
209 * @throws NamingException if a naming exception is encountered
210 */
211 public NamingEnumeration list(Name name) throws NamingException {
212 return _context.list(name);
213 }
214
215 /***
216 * Enumerates the names bound in the named context, along with the
217 * class names of objects bound to them.
218 *
219 * @param name the name of the context to list
220 * @return an enumeration of the names and class names of the
221 * bindings in this context. Each element of the
222 * enumeration is of type <tt>NameClassPair</tt>.
223 * @throws NamingException if a naming exception is encountered
224 */
225 public NamingEnumeration list(String name) throws NamingException {
226 return _context.list(name);
227 }
228
229 /***
230 * Enumerates the names bound in the named context, along with the
231 * objects bound to them.
232 *
233 * @param name the name of the context to list
234 * @return an enumeration of the bindings in this context.
235 * Each element of the enumeration is of type
236 * <tt>Binding</tt>.
237 * @throws NamingException if a naming exception is encountered
238 */
239 public NamingEnumeration listBindings(Name name) throws NamingException {
240 return new ORBNamingEnumeration(_context.listBindings(name));
241 }
242
243 /***
244 * Enumerates the names bound in the named context, along with the
245 * objects bound to them.
246 *
247 * @param name the name of the context to list
248 * @return an enumeration of the bindings in this context.
249 * Each element of the enumeration is of type
250 * <tt>Binding</tt>.
251 * @throws NamingException if a naming exception is encountered
252 */
253 public NamingEnumeration listBindings(String name) throws NamingException {
254 return _context.listBindings(name);
255 }
256
257 /***
258 * Destroys the named context and removes it from the namespace.
259 *
260 * @param name the name of the context to be destroyed; may not be empty
261 * @throws NamingException if a naming exception is encountered
262 */
263 public void destroySubcontext(Name name) throws NamingException {
264 _context.destroySubcontext(name);
265 }
266
267 /***
268 * Destroys the named context and removes it from the namespace.
269 *
270 * @param name the name of the context to be destroyed; may not be empty
271 * @throws NamingException if a naming exception is encountered
272 */
273 public void destroySubcontext(String name) throws NamingException {
274 _context.destroySubcontext(name);
275 }
276
277 /***
278 * Creates and binds a new context.
279 *
280 * @param name the name of the context to create; may not be empty
281 * @return the newly created context
282 * @throws NamingException if a naming exception is encountered
283 */
284 public Context createSubcontext(Name name) throws NamingException {
285 return (Context) wrap(_context.createSubcontext(name));
286 }
287
288 /***
289 * Creates and binds a new context.
290 *
291 * @param name the name of the context to create; may not be empty
292 * @return the newly created context
293 * @throws NamingException if a naming exception is encountered
294 */
295 public Context createSubcontext(String name) throws NamingException {
296 return (Context) wrap(_context.createSubcontext(name));
297 }
298
299 /***
300 * Retrieves the named object, following links except
301 * for the terminal atomic component of the name.
302 *
303 * @param name the name of the object to look up
304 * @return the object bound to <tt>name</tt>, not following the
305 * terminal link (if any).
306 * @throws NamingException if a naming exception is encountered
307 */
308 public Object lookupLink(Name name) throws NamingException {
309 return wrap(_context.lookupLink(name));
310 }
311
312 /***
313 * Retrieves the named object, following links except
314 * for the terminal atomic component of the name.
315 *
316 * @param name the name of the object to look up
317 * @return the object bound to <tt>name</tt>, not following the
318 * terminal link (if any)
319 * @throws NamingException if a naming exception is encountered
320 */
321 public Object lookupLink(String name) throws NamingException {
322 return wrap(_context.lookupLink(name));
323 }
324
325 /***
326 * Retrieves the parser associated with the named context.
327 *
328 * @param name the name of the context from which to get the parser
329 * @return a name parser that can parse compound names into their atomic
330 * components
331 * @throws NamingException if a naming exception is encountered
332 */
333 public NameParser getNameParser(Name name) throws NamingException {
334 return _context.getNameParser(name);
335 }
336
337 /***
338 * Retrieves the parser associated with the named context.
339 *
340 * @param name the name of the context from which to get the parser
341 * @return a name parser that can parse compound names into their atomic
342 * components
343 * @throws NamingException if a naming exception is encountered
344 */
345 public NameParser getNameParser(String name) throws NamingException {
346 return _context.getNameParser(name);
347 }
348
349 /***
350 * Composes the name of this context with a name relative to
351 * this context.
352 *
353 * @param name a name relative to this context
354 * @param prefix the name of this context relative to one of its ancestors
355 * @return the composition of <code>prefix</code> and <code>name</code>
356 * @throws NamingException if a naming exception is encountered
357 */
358 public Name composeName(Name name, Name prefix) throws NamingException {
359 return _context.composeName(name, prefix);
360 }
361
362 /***
363 * Composes the name of this context with a name relative to
364 * this context.
365 *
366 * @param name a name relative to this context
367 * @param prefix the name of this context relative to one of its ancestors
368 * @return the composition of <code>prefix</code> and <code>name</code>
369 * @throws NamingException if a naming exception is encountered
370 */
371 public String composeName(String name, String prefix)
372 throws NamingException {
373 return _context.composeName(name, prefix);
374 }
375
376 /***
377 * Adds a new environment property to the environment of this
378 * context. If the property already exists, its value is overwritten.
379 *
380 * @param propName the name of the environment property to add; may not be null
381 * @param propVal the value of the property to add; may not be null
382 * @return the previous value of the property, or null if the property was
383 * not in the environment before
384 * @throws NamingException if a naming exception is encountered
385 */
386 public Object addToEnvironment(String propName, Object propVal)
387 throws NamingException {
388 return _context.addToEnvironment(propName, propVal);
389 }
390
391 /***
392 * Removes an environment property from the environment of this
393 * context. See class description for more details on environment
394 * properties.
395 *
396 * @param propName the name of the environment property to remove; may not be null
397 * @return the previous value of the property, or null if the property was
398 * not in the environment
399 * @throws NamingException if a naming exception is encountered
400 */
401 public Object removeFromEnvironment(String propName)
402 throws NamingException {
403 return _context.removeFromEnvironment(propName);
404 }
405
406 /***
407 * Retrieves the environment in effect for this context.
408 *
409 * @return the environment of this context; never null
410 * @throws NamingException if a naming exception is encountered
411 */
412 public Hashtable getEnvironment() throws NamingException {
413 return _context.getEnvironment();
414 }
415
416 /***
417 * Closes this context.
418 *
419 * @throws NamingException if a naming exception is encountered
420 */
421 public void close() throws NamingException {
422 if (_context != null) {
423 if (dereference() <= 0) {
424 Object provider = getEnvironment().get(
425 RemoteContext.NAMING_PROVIDER);
426 if (provider instanceof Proxy) {
427 ((Proxy) provider).disposeProxy();
428 }
429 }
430 _context.close();
431 _context = null;
432 }
433 }
434
435 /***
436 * Retrieves the full name of this context within its own namespace.
437 *
438 * @return this context's name in its own namespace; never null
439 * @throws NamingException if a naming exception is encountered
440 */
441 public String getNameInNamespace() throws NamingException {
442 return _context.getNameInNamespace();
443 }
444
445 /***
446 * Called by the garbage collector on an object when garbage collection
447 * determines that there are no more references to the object.
448 *
449 * @throws Throwable the <code>Exception</code> raised by this method
450 */
451 protected void finalize() throws Throwable {
452 close();
453 }
454
455 /***
456 * Wrap the supplied object in an <code>ORBRemoteContext</code> iff it
457 * is an instance of <code>RemoteContext</code>, otherwise returns the
458 * object unchanged.
459 *
460 * @param object the object to wrap
461 * @return the supplied object in an <code>ORBRemoteContext</code> iff it
462 * is an instance of <code>RemoteContext</code>, otherwise returns the
463 * object unchanged.
464 * @throws NamingException if a naming exception is encountered
465 */
466 private Object wrap(Object object) throws NamingException {
467 if (object instanceof RemoteContext) {
468 return new ORBRemoteContext((RemoteContext) object);
469 }
470 return object;
471 }
472
473 /***
474 * Increment the reference count of the provider. This is the number
475 * of <code>Context</code> instances that refer to it.
476 *
477 * @throws NamingException for any naming error
478 */
479 private void reference() throws NamingException {
480 Ref ref = (Ref) _context.getEnvironment().get(REFERENCE_KEY);
481 if (ref == null) {
482 ref = new Ref();
483 _context.addToEnvironment(REFERENCE_KEY, ref);
484 }
485 ref.inc();
486 }
487
488 /***
489 * Dereference the reference count of the provider.
490 *
491 * @return the number of references
492 * @throws NamingException for any naming error
493 */
494 private int dereference() throws NamingException {
495 Ref ref = (Ref) _context.getEnvironment().get(REFERENCE_KEY);
496 return (ref != null) ? ref.dec() : 0;
497 }
498
499
500 /***
501 * Helper to wrap any <code>RemoteContext</code> instances returned
502 * by a <code>NamingEnumeration</code> in <code>ORBRemoteContext</code>
503 * instances.
504 */
505 private static class ORBNamingEnumeration implements NamingEnumeration {
506
507 /***
508 * The enumeration.
509 */
510 private final NamingEnumeration _iterator;
511
512 /***
513 * Construct a new <code>ORBNamingEnumeration</code>.
514 *
515 * @param iterator the enumeration to delegate to
516 */
517 private ORBNamingEnumeration(NamingEnumeration iterator) {
518 _iterator = iterator;
519 }
520
521 /***
522 * Retrieves the next element in the enumeration.
523 *
524 * @return the next element in the enumeration.
525 * @throws NamingException for any naming error
526 * @throws java.util.NoSuchElementException If attempting to get the next element when none is available.
527 */
528 public Object next() throws NamingException {
529 return wrap(_iterator.next());
530 }
531
532 /***
533 * Determines whether there are any more elements in the enumeration.
534 *
535 * @throws NamingException for any naming error.
536 * @return true if there is more in the enumeration; false otherwise.
537 */
538 public boolean hasMore() throws NamingException {
539 return _iterator.hasMore();
540 }
541
542 /***
543 * Closes this enumeration.
544 *
545 * @throws NamingException for any naming error
546 */
547 public void close() throws NamingException {
548 _iterator.close();
549 }
550
551 /***
552 * Tests if this enumeration contains more elements.
553 *
554 * @return <code>true</code> if and only if this enumeration object
555 * contains at least one more element to provide;
556 * <code>false</code> otherwise.
557 */
558 public boolean hasMoreElements() {
559 return _iterator.hasMoreElements();
560 }
561
562 /***
563 * Returns the next element of this enumeration if this enumeration
564 * object has at least one more element to provide.
565 *
566 * @return the next element of this enumeration.
567 * @throws java.util.NoSuchElementException if no more elements exist.
568 */
569 public Object nextElement() {
570 try {
571 return wrap(_iterator.nextElement());
572 } catch (NamingException exception) {
573 throw new NoSuchElementException(exception.getMessage());
574 }
575 }
576
577 /***
578 * Wraps any <code>Context</code> instances in <code>ORBRemoteContext</code>.
579 *
580 * @param obj the object
581 * @return obj
582 * @throws NamingException for any naming error
583 */
584 private Object wrap(Object obj) throws NamingException {
585 if (obj instanceof Binding) {
586 Binding binding = (Binding) obj;
587 Object bound = binding.getObject();
588 if (bound instanceof RemoteContext) {
589 binding.setObject(
590 new ORBRemoteContext((RemoteContext) bound));
591 }
592 }
593 return obj;
594 }
595 }
596
597 /***
598 * Helper to maintain a reference count.
599 */
600 private static class Ref {
601
602 /***
603 * The reference count.
604 */
605 private int _count;
606
607 /***
608 * Increment the reference count.
609 *
610 * @return the reference count
611 */
612 public synchronized int inc() {
613 return ++_count;
614 }
615
616 /***
617 * Decrement the reference count.
618 *
619 * @return the reference count
620 */
621 public synchronized int dec() {
622 return --_count;
623 }
624
625 }
626
627 }