KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > naming > modules > cache > ProxyDirContext


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.naming.modules.cache;
18
19 import java.util.Collections JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import javax.naming.Context JavaDoc;
24 import javax.naming.Name JavaDoc;
25 import javax.naming.NameParser JavaDoc;
26 import javax.naming.NamingEnumeration JavaDoc;
27 import javax.naming.NamingException JavaDoc;
28 import javax.naming.directory.Attributes JavaDoc;
29 import javax.naming.directory.DirContext JavaDoc;
30 import javax.naming.directory.ModificationItem JavaDoc;
31 import javax.naming.directory.SearchControls JavaDoc;
32
33 import org.apache.commons.collections.LRUMap;
34 import org.apache.naming.core.BaseDirContext;
35 import org.apache.naming.util.AttributeHelper;
36 import org.apache.tomcat.util.res.StringManager;
37
38 /* Changes( costin ): The goal is to make it a generic JNDI cache, not specific
39    to file system.
40
41   - no more wrapping in Resource and ResourceAttributes.
42    We just cache, and the caller can use tools to do the wrapping or operate on atts.
43   - we use only lastModified ( not contentLength ).
44   -
45
46   TODO:
47   - add a special CacheInputStream - that will save the byte[] in the cache entry.
48   - 2 TTL: one will prevent accessing the dir ( even for lastModified ), one will
49     expire the entry regardless. The first should be very short ( .1 sec ? ), for
50     to avoid very frequent accesses to the same entry.
51     Alternative ( probably the best ): use a background thread to check 'lastModified',
52     like we do in 3.3 for class reloading.
53 */

54
55
56
57 /**
58  * Proxy Directory Context implementation.
59  *
60  * Will cache directory entries - attributes and content. This can be used
61  * to eliminate expensive dir access and to avoid keeping large directories in memory.
62  *
63  * @author Remy Maucherat
64  * @author Costin Manolache
65  */

66 public class ProxyDirContext implements DirContext JavaDoc {
67       private static org.apache.commons.logging.Log log=
68          org.apache.commons.logging.LogFactory.getLog( ProxyDirContext.class );
69
70
71     // ----------------------------------------------------------- Constructors
72

73
74     /**
75      * Builds a proxy directory context using the given environment.
76      */

77     public ProxyDirContext(Hashtable JavaDoc env, DirContext JavaDoc dirContext) {
78         this.env = env;
79         this.dirContext = dirContext;
80         if (dirContext instanceof BaseDirContext) {
81             // Initialize parameters based on the associated dir context, like
82
// the caching policy.
83
if (((BaseDirContext) dirContext).isCached()) {
84                 cache = Collections.synchronizedMap(new LRUMap(cacheSize));
85                 cacheTTL = ((BaseDirContext) dirContext).getCacheTTL();
86                 cacheObjectMaxSize =
87                     ((BaseDirContext) dirContext).getCacheObjectMaxSize();
88             }
89         }
90     }
91
92     /**
93      * Builds a clone of this proxy dir context, wrapping the given directory
94      * context, and sharing the same cache.
95      */

96     protected ProxyDirContext(ProxyDirContext proxyDirContext,
97                               DirContext JavaDoc dirContext) {
98         this.env = proxyDirContext.env;
99         this.dirContext = dirContext;
100         this.cache = proxyDirContext.cache;
101         this.cacheSize = proxyDirContext.cacheSize;
102         this.cacheTTL = proxyDirContext.cacheTTL;
103         this.cacheObjectMaxSize = proxyDirContext.cacheObjectMaxSize;
104     }
105
106
107     // ----------------------------------------------------- Instance Variables
108

109
110     /**
111      * Environment.
112      */

113     protected Hashtable JavaDoc env;
114
115
116     /**
117      * The string manager for this package.
118      */

119     protected StringManager sm = StringManager.getManager("org.apache.naming.res");
120
121
122     /**
123      * Associated DirContext.
124      */

125     protected DirContext JavaDoc dirContext;
126
127
128     /**
129      * Cache.
130      * Path -> Cache entry.
131      */

132     protected Map JavaDoc cache = null;
133
134
135     /**
136      * Cache size
137      */

138     protected int cacheSize = 1000;
139
140
141     /**
142      * Cache TTL.
143      */

144     protected int cacheTTL = 5000; // 5s
145

146
147     /**
148      * Max size of resources which will have their content cached.
149      */

150     protected int cacheObjectMaxSize = 32768; // 32 KB
151

152
153     // --------------------------------------------------------- Public Methods
154

155
156     /**
157      * Return the actual directory context we are wrapping.
158      */

159     public DirContext JavaDoc getDirContext() {
160         return this.dirContext;
161     }
162
163
164     // -------------------------------------------------------- Context Methods
165

166
167     /**
168      * Retrieves the named object. If name is empty, returns a new instance
169      * of this context (which represents the same naming context as this
170      * context, but its environment may be modified independently and it may
171      * be accessed concurrently).
172      *
173      * @param name the name of the object to look up
174      * @return the object bound to name
175      * @exception NamingException if a naming exception is encountered
176      */

177     public Object JavaDoc lookup(Name JavaDoc name)
178         throws NamingException JavaDoc {
179         CacheEntry entry = cacheLookupAndLoad(name.toString());
180         if (entry != null) {
181             if (entry.resource != null) {
182                 // Check content caching.
183

184                 return entry.resource;
185             } else {
186                 return entry.context;
187             }
188         }
189         log.info("Strange, entry was no loadeded " + name );
190         Object JavaDoc object = dirContext.lookup(parseName(name));
191 // if (object instanceof InputStream)
192
// return new Resource((InputStream) object);
193
// else
194
return object;
195     }
196
197
198     /**
199      * Retrieves the named object.
200      *
201      * @param name the name of the object to look up
202      * @return the object bound to name
203      * @exception NamingException if a naming exception is encountered
204      */

205     public Object JavaDoc lookup(String JavaDoc name)
206         throws NamingException JavaDoc {
207         CacheEntry entry = cacheLookupAndLoad(name);
208         if (entry != null) {
209             if (entry.resource != null) {
210                 return entry.resource;
211             } else {
212                 return entry.context;
213             }
214         }
215         log.info("Strange, entry was no loadeded " + name );
216        
217         Object JavaDoc object = dirContext.lookup(parseName(name));
218 // if (object instanceof InputStream) {
219
// return new Resource((InputStream) object);
220
// } else if (object instanceof DirContext) {
221
// return object;
222
// } else if (object instanceof Resource) {
223
// return object;
224
// } else {
225
// return new Resource(new ByteArrayInputStream
226
// (object.toString().getBytes()));
227
// }
228
return object;
229     }
230
231
232     /**
233      * Binds a name to an object. All intermediate contexts and the target
234      * context (that named by all but terminal atomic component of the name)
235      * must already exist.
236      *
237      * @param name the name to bind; may not be empty
238      * @param obj the object to bind; possibly null
239      * @exception NameAlreadyBoundException if name is already bound
240      * @exception InvalidAttributesException if object did not supply all
241      * mandatory attributes
242      * @exception NamingException if a naming exception is encountered
243      */

244     public void bind(Name JavaDoc name, Object JavaDoc obj)
245         throws NamingException JavaDoc {
246         dirContext.bind(parseName(name), obj);
247         cacheUnload(name.toString());
248     }
249
250
251     /**
252      * Binds a name to an object.
253      *
254      * @param name the name to bind; may not be empty
255      * @param obj the object to bind; possibly null
256      * @exception NameAlreadyBoundException if name is already bound
257      * @exception InvalidAttributesException if object did not supply all
258      * mandatory attributes
259      * @exception NamingException if a naming exception is encountered
260      */

261     public void bind(String JavaDoc name, Object JavaDoc obj)
262         throws NamingException JavaDoc {
263         dirContext.bind(parseName(name), obj);
264         cacheUnload(name);
265     }
266
267
268     /**
269      * Binds a name to an object, overwriting any existing binding. All
270      * intermediate contexts and the target context (that named by all but
271      * terminal atomic component of the name) must already exist.
272      * <p>
273      * If the object is a DirContext, any existing attributes associated with
274      * the name are replaced with those of the object. Otherwise, any
275      * existing attributes associated with the name remain unchanged.
276      *
277      * @param name the name to bind; may not be empty
278      * @param obj the object to bind; possibly null
279      * @exception InvalidAttributesException if object did not supply all
280      * mandatory attributes
281      * @exception NamingException if a naming exception is encountered
282      */

283     public void rebind(Name JavaDoc name, Object JavaDoc obj)
284         throws NamingException JavaDoc {
285         dirContext.rebind(parseName(name), obj);
286         cacheUnload(name.toString());
287     }
288
289
290     /**
291      * Binds a name to an object, overwriting any existing binding.
292      *
293      * @param name the name to bind; may not be empty
294      * @param obj the object to bind; possibly null
295      * @exception InvalidAttributesException if object did not supply all
296      * mandatory attributes
297      * @exception NamingException if a naming exception is encountered
298      */

299     public void rebind(String JavaDoc name, Object JavaDoc obj)
300         throws NamingException JavaDoc {
301         dirContext.rebind(parseName(name), obj);
302         cacheUnload(name);
303     }
304
305
306     /**
307      * Unbinds the named object. Removes the terminal atomic name in name
308      * from the target context--that named by all but the terminal atomic
309      * part of name.
310      * <p>
311      * This method is idempotent. It succeeds even if the terminal atomic
312      * name is not bound in the target context, but throws
313      * NameNotFoundException if any of the intermediate contexts do not exist.
314      *
315      * @param name the name to bind; may not be empty
316      * @exception NameNotFoundException if an intermediate context does not
317      * exist
318      * @exception NamingException if a naming exception is encountered
319      */

320     public void unbind(Name JavaDoc name)
321         throws NamingException JavaDoc {
322         dirContext.unbind(parseName(name));
323         cacheUnload(name.toString());
324     }
325
326
327     /**
328      * Unbinds the named object.
329      *
330      * @param name the name to bind; may not be empty
331      * @exception NameNotFoundException if an intermediate context does not
332      * exist
333      * @exception NamingException if a naming exception is encountered
334      */

335     public void unbind(String JavaDoc name)
336         throws NamingException JavaDoc {
337         dirContext.unbind(parseName(name));
338         cacheUnload(name);
339     }
340
341
342     /**
343      * Binds a new name to the object bound to an old name, and unbinds the
344      * old name. Both names are relative to this context. Any attributes
345      * associated with the old name become associated with the new name.
346      * Intermediate contexts of the old name are not changed.
347      *
348      * @param oldName the name of the existing binding; may not be empty
349      * @param newName the name of the new binding; may not be empty
350      * @exception NameAlreadyBoundException if newName is already bound
351      * @exception NamingException if a naming exception is encountered
352      */

353     public void rename(Name JavaDoc oldName, Name JavaDoc newName)
354         throws NamingException JavaDoc {
355         dirContext.rename(parseName(oldName), parseName(newName));
356         cacheUnload(oldName.toString());
357     }
358
359
360     /**
361      * Binds a new name to the object bound to an old name, and unbinds the
362      * old name.
363      *
364      * @param oldName the name of the existing binding; may not be empty
365      * @param newName the name of the new binding; may not be empty
366      * @exception NameAlreadyBoundException if newName is already bound
367      * @exception NamingException if a naming exception is encountered
368      */

369     public void rename(String JavaDoc oldName, String JavaDoc newName)
370         throws NamingException JavaDoc {
371         dirContext.rename(parseName(oldName), parseName(newName));
372         cacheUnload(oldName);
373     }
374
375
376     /**
377      * Enumerates the names bound in the named context, along with the class
378      * names of objects bound to them. The contents of any subcontexts are
379      * not included.
380      * <p>
381      * If a binding is added to or removed from this context, its effect on
382      * an enumeration previously returned is undefined.
383      *
384      * @param name the name of the context to list
385      * @return an enumeration of the names and class names of the bindings in
386      * this context. Each element of the enumeration is of type NameClassPair.
387      * @exception NamingException if a naming exception is encountered
388      */

389     public NamingEnumeration JavaDoc list(Name JavaDoc name)
390         throws NamingException JavaDoc {
391         return dirContext.list(parseName(name));
392     }
393
394
395     /**
396      * Enumerates the names bound in the named context, along with the class
397      * names of objects bound to them.
398      *
399      * @param name the name of the context to list
400      * @return an enumeration of the names and class names of the bindings in
401      * this context. Each element of the enumeration is of type NameClassPair.
402      * @exception NamingException if a naming exception is encountered
403      */

404     public NamingEnumeration JavaDoc list(String JavaDoc name)
405         throws NamingException JavaDoc {
406         return dirContext.list(parseName(name));
407     }
408
409
410     /**
411      * Enumerates the names bound in the named context, along with the
412      * objects bound to them. The contents of any subcontexts are not
413      * included.
414      * <p>
415      * If a binding is added to or removed from this context, its effect on
416      * an enumeration previously returned is undefined.
417      *
418      * @param name the name of the context to list
419      * @return an enumeration of the bindings in this context.
420      * Each element of the enumeration is of type Binding.
421      * @exception NamingException if a naming exception is encountered
422      */

423     public NamingEnumeration JavaDoc listBindings(Name JavaDoc name)
424         throws NamingException JavaDoc {
425         return dirContext.listBindings(parseName(name));
426     }
427
428
429     /**
430      * Enumerates the names bound in the named context, along with the
431      * objects bound to them.
432      *
433      * @param name the name of the context to list
434      * @return an enumeration of the bindings in this context.
435      * Each element of the enumeration is of type Binding.
436      * @exception NamingException if a naming exception is encountered
437      */

438     public NamingEnumeration JavaDoc listBindings(String JavaDoc name)
439         throws NamingException JavaDoc {
440         return dirContext.listBindings(parseName(name));
441     }
442
443
444     /**
445      * Destroys the named context and removes it from the namespace. Any
446      * attributes associated with the name are also removed. Intermediate
447      * contexts are not destroyed.
448      * <p>
449      * This method is idempotent. It succeeds even if the terminal atomic
450      * name is not bound in the target context, but throws
451      * NameNotFoundException if any of the intermediate contexts do not exist.
452      *
453      * In a federated naming system, a context from one naming system may be
454      * bound to a name in another. One can subsequently look up and perform
455      * operations on the foreign context using a composite name. However, an
456      * attempt destroy the context using this composite name will fail with
457      * NotContextException, because the foreign context is not a "subcontext"
458      * of the context in which it is bound. Instead, use unbind() to remove
459      * the binding of the foreign context. Destroying the foreign context
460      * requires that the destroySubcontext() be performed on a context from
461      * the foreign context's "native" naming system.
462      *
463      * @param name the name of the context to be destroyed; may not be empty
464      * @exception NameNotFoundException if an intermediate context does not
465      * exist
466      * @exception NotContextException if the name is bound but does not name
467      * a context, or does not name a context of the appropriate type
468      */

469     public void destroySubcontext(Name JavaDoc name)
470         throws NamingException JavaDoc {
471         dirContext.destroySubcontext(parseName(name));
472         cacheUnload(name.toString());
473     }
474
475
476     /**
477      * Destroys the named context and removes it from the namespace.
478      *
479      * @param name the name of the context to be destroyed; may not be empty
480      * @exception NameNotFoundException if an intermediate context does not
481      * exist
482      * @exception NotContextException if the name is bound but does not name
483      * a context, or does not name a context of the appropriate type
484      */

485     public void destroySubcontext(String JavaDoc name)
486         throws NamingException JavaDoc {
487         dirContext.destroySubcontext(parseName(name));
488         cacheUnload(name);
489     }
490
491
492     /**
493      * Creates and binds a new context. Creates a new context with the given
494      * name and binds it in the target context (that named by all but
495      * terminal atomic component of the name). All intermediate contexts and
496      * the target context must already exist.
497      *
498      * @param name the name of the context to create; may not be empty
499      * @return the newly created context
500      * @exception NameAlreadyBoundException if name is already bound
501      * @exception InvalidAttributesException if creation of the subcontext
502      * requires specification of mandatory attributes
503      * @exception NamingException if a naming exception is encountered
504      */

505     public Context JavaDoc createSubcontext(Name JavaDoc name)
506         throws NamingException JavaDoc {
507         return dirContext.createSubcontext(parseName(name));
508     }
509
510
511     /**
512      * Creates and binds a new context.
513      *
514      * @param name the name of the context to create; may not be empty
515      * @return the newly created context
516      * @exception NameAlreadyBoundException if name is already bound
517      * @exception InvalidAttributesException if creation of the subcontext
518      * requires specification of mandatory attributes
519      * @exception NamingException if a naming exception is encountered
520      */

521     public Context JavaDoc createSubcontext(String JavaDoc name)
522         throws NamingException JavaDoc {
523         return dirContext.createSubcontext(parseName(name));
524     }
525
526
527     /**
528      * Retrieves the named object, following links except for the terminal
529      * atomic component of the name. If the object bound to name is not a
530      * link, returns the object itself.
531      *
532      * @param name the name of the object to look up
533      * @return the object bound to name, not following the terminal link
534      * (if any).
535      * @exception NamingException if a naming exception is encountered
536      */

537     public Object JavaDoc lookupLink(Name JavaDoc name)
538         throws NamingException JavaDoc {
539         return dirContext.lookupLink(parseName(name));
540     }
541
542
543     /**
544      * Retrieves the named object, following links except for the terminal
545      * atomic component of the name.
546      *
547      * @param name the name of the object to look up
548      * @return the object bound to name, not following the terminal link
549      * (if any).
550      * @exception NamingException if a naming exception is encountered
551      */

552     public Object JavaDoc lookupLink(String JavaDoc name)
553         throws NamingException JavaDoc {
554         return dirContext.lookupLink(parseName(name));
555     }
556
557
558     /**
559      * Retrieves the parser associated with the named context. In a
560      * federation of namespaces, different naming systems will parse names
561      * differently. This method allows an application to get a parser for
562      * parsing names into their atomic components using the naming convention
563      * of a particular naming system. Within any single naming system,
564      * NameParser objects returned by this method must be equal (using the
565      * equals() test).
566      *
567      * @param name the name of the context from which to get the parser
568      * @return a name parser that can parse compound names into their atomic
569      * components
570      * @exception NamingException if a naming exception is encountered
571      */

572     public NameParser JavaDoc getNameParser(Name JavaDoc name)
573         throws NamingException JavaDoc {
574         return dirContext.getNameParser(parseName(name));
575     }
576
577
578     /**
579      * Retrieves the parser associated with the named context.
580      *
581      * @param name the name of the context from which to get the parser
582      * @return a name parser that can parse compound names into their atomic
583      * components
584      * @exception NamingException if a naming exception is encountered
585      */

586     public NameParser JavaDoc getNameParser(String JavaDoc name)
587         throws NamingException JavaDoc {
588         return dirContext.getNameParser(parseName(name));
589     }
590
591
592     /**
593      * Composes the name of this context with a name relative to this context.
594      * <p>
595      * Given a name (name) relative to this context, and the name (prefix)
596      * of this context relative to one of its ancestors, this method returns
597      * the composition of the two names using the syntax appropriate for the
598      * naming system(s) involved. That is, if name names an object relative
599      * to this context, the result is the name of the same object, but
600      * relative to the ancestor context. None of the names may be null.
601      *
602      * @param name a name relative to this context
603      * @param prefix the name of this context relative to one of its ancestors
604      * @return the composition of prefix and name
605      * @exception NamingException if a naming exception is encountered
606      */

607     public Name JavaDoc composeName(Name JavaDoc name, Name JavaDoc prefix)
608         throws NamingException JavaDoc {
609         prefix = (Name JavaDoc) name.clone();
610     return prefix.addAll(name);
611     }
612
613
614     /**
615      * Composes the name of this context with a name relative to this context.
616      *
617      * @param name a name relative to this context
618      * @param prefix the name of this context relative to one of its ancestors
619      * @return the composition of prefix and name
620      * @exception NamingException if a naming exception is encountered
621      */

622     public String JavaDoc composeName(String JavaDoc name, String JavaDoc prefix)
623         throws NamingException JavaDoc {
624         return prefix + "/" + name;
625     }
626
627
628     /**
629      * Adds a new environment property to the environment of this context. If
630      * the property already exists, its value is overwritten.
631      *
632      * @param propName the name of the environment property to add; may not
633      * be null
634      * @param propVal the value of the property to add; may not be null
635      * @exception NamingException if a naming exception is encountered
636      */

637     public Object JavaDoc addToEnvironment(String JavaDoc propName, Object JavaDoc propVal)
638         throws NamingException JavaDoc {
639         return dirContext.addToEnvironment(propName, propVal);
640     }
641
642
643     /**
644      * Removes an environment property from the environment of this context.
645      *
646      * @param propName the name of the environment property to remove;
647      * may not be null
648      * @exception NamingException if a naming exception is encountered
649      */

650     public Object JavaDoc removeFromEnvironment(String JavaDoc propName)
651         throws NamingException JavaDoc {
652         return dirContext.removeFromEnvironment(propName);
653     }
654
655
656     /**
657      * Retrieves the environment in effect for this context. See class
658      * description for more details on environment properties.
659      * The caller should not make any changes to the object returned: their
660      * effect on the context is undefined. The environment of this context
661      * may be changed using addToEnvironment() and removeFromEnvironment().
662      *
663      * @return the environment of this context; never null
664      * @exception NamingException if a naming exception is encountered
665      */

666     public Hashtable JavaDoc getEnvironment()
667         throws NamingException JavaDoc {
668         return dirContext.getEnvironment();
669     }
670
671
672     /**
673      * Closes this context. This method releases this context's resources
674      * immediately, instead of waiting for them to be released automatically
675      * by the garbage collector.
676      * This method is idempotent: invoking it on a context that has already
677      * been closed has no effect. Invoking any other method on a closed
678      * context is not allowed, and results in undefined behaviour.
679      *
680      * @exception NamingException if a naming exception is encountered
681      */

682     public void close()
683         throws NamingException JavaDoc {
684         dirContext.close();
685     }
686
687
688     /**
689      * Retrieves the full name of this context within its own namespace.
690      * <p>
691      * Many naming services have a notion of a "full name" for objects in
692      * their respective namespaces. For example, an LDAP entry has a
693      * distinguished name, and a DNS record has a fully qualified name. This
694      * method allows the client application to retrieve this name. The string
695      * returned by this method is not a JNDI composite name and should not be
696      * passed directly to context methods. In naming systems for which the
697      * notion of full name does not make sense,
698      * OperationNotSupportedException is thrown.
699      *
700      * @return this context's name in its own namespace; never null
701      * @exception OperationNotSupportedException if the naming system does
702      * not have the notion of a full name
703      * @exception NamingException if a naming exception is encountered
704      */

705     public String JavaDoc getNameInNamespace()
706         throws NamingException JavaDoc {
707         return dirContext.getNameInNamespace();
708     }
709
710
711     // ----------------------------------------------------- DirContext Methods
712

713
714     /**
715      * Retrieves all of the attributes associated with a named object.
716      *
717      * @return the set of attributes associated with name.
718      * Returns an empty attribute set if name has no attributes; never null.
719      * @param name the name of the object from which to retrieve attributes
720      * @exception NamingException if a naming exception is encountered
721      */

722     public Attributes JavaDoc getAttributes(Name JavaDoc name)
723         throws NamingException JavaDoc {
724         CacheEntry entry = cacheLookupAndLoad(name.toString());
725         if (entry != null) {
726             return entry.attributes;
727         }
728         Attributes JavaDoc attributes = dirContext.getAttributes(parseName(name));
729
730         // TODO(costin): Why do we need to wrap it ? It may be better to use decorator
731
// if (!(attributes instanceof ResourceAttributes)) {
732
// attributes = new ResourceAttributes(attributes);
733
// }
734
return attributes;
735     }
736
737
738     /**
739      * Retrieves all of the attributes associated with a named object.
740      *
741      * @return the set of attributes associated with name
742      * @param name the name of the object from which to retrieve attributes
743      * @exception NamingException if a naming exception is encountered
744      */

745     public Attributes JavaDoc getAttributes(String JavaDoc name)
746         throws NamingException JavaDoc {
747         CacheEntry entry = cacheLookupAndLoad(name);
748         if (entry != null) {
749             return entry.attributes;
750         }
751         Attributes JavaDoc attributes = dirContext.getAttributes(parseName(name));
752 // if (!(attributes instanceof ResourceAttributes)) {
753
// attributes = new ResourceAttributes(attributes);
754
// }
755
return attributes;
756     }
757
758
759     /**
760      * Retrieves selected attributes associated with a named object.
761      * See the class description regarding attribute models, attribute type
762      * names, and operational attributes.
763      *
764      * @return the requested attributes; never null
765      * @param name the name of the object from which to retrieve attributes
766      * @param attrIds the identifiers of the attributes to retrieve. null
767      * indicates that all attributes should be retrieved; an empty array
768      * indicates that none should be retrieved
769      * @exception NamingException if a naming exception is encountered
770      */

771     public Attributes JavaDoc getAttributes(Name JavaDoc name, String JavaDoc[] attrIds)
772         throws NamingException JavaDoc {
773         Attributes JavaDoc attributes =
774             dirContext.getAttributes(parseName(name), attrIds);
775 // if (!(attributes instanceof ResourceAttributes)) {
776
// attributes = new ResourceAttributes(attributes);
777
// }
778
return attributes;
779     }
780
781
782     /**
783      * Retrieves selected attributes associated with a named object.
784      *
785      * @return the requested attributes; never null
786      * @param name the name of the object from which to retrieve attributes
787      * @param attrIds the identifiers of the attributes to retrieve. null
788      * indicates that all attributes should be retrieved; an empty array
789      * indicates that none should be retrieved
790      * @exception NamingException if a naming exception is encountered
791      */

792      public Attributes JavaDoc getAttributes(String JavaDoc name, String JavaDoc[] attrIds)
793          throws NamingException JavaDoc {
794         Attributes JavaDoc attributes =
795             dirContext.getAttributes(parseName(name), attrIds);
796 // if (!(attributes instanceof ResourceAttributes)) {
797
// attributes = new ResourceAttributes(attributes);
798
// }
799
return attributes;
800      }
801
802
803     /**
804      * Modifies the attributes associated with a named object. The order of
805      * the modifications is not specified. Where possible, the modifications
806      * are performed atomically.
807      *
808      * @param name the name of the object whose attributes will be updated
809      * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
810      * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
811      * @param attrs the attributes to be used for the modification; may not
812      * be null
813      * @exception AttributeModificationException if the modification cannot be
814      * completed successfully
815      * @exception NamingException if a naming exception is encountered
816      */

817     public void modifyAttributes(Name JavaDoc name, int mod_op, Attributes JavaDoc attrs)
818         throws NamingException JavaDoc {
819         dirContext.modifyAttributes(parseName(name), mod_op, attrs);
820     }
821
822
823     /**
824      * Modifies the attributes associated with a named object.
825      *
826      * @param name the name of the object whose attributes will be updated
827      * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
828      * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
829      * @param attrs the attributes to be used for the modification; may not
830      * be null
831      * @exception AttributeModificationException if the modification cannot be
832      * completed successfully
833      * @exception NamingException if a naming exception is encountered
834      */

835     public void modifyAttributes(String JavaDoc name, int mod_op, Attributes JavaDoc attrs)
836         throws NamingException JavaDoc {
837         dirContext.modifyAttributes(parseName(name), mod_op, attrs);
838     }
839
840
841     /**
842      * Modifies the attributes associated with a named object using an an
843      * ordered list of modifications. The modifications are performed in the
844      * order specified. Each modification specifies a modification operation
845      * code and an attribute on which to operate. Where possible, the
846      * modifications are performed atomically.
847      *
848      * @param name the name of the object whose attributes will be updated
849      * @param mods an ordered sequence of modifications to be performed; may
850      * not be null
851      * @exception AttributeModificationException if the modification cannot be
852      * completed successfully
853      * @exception NamingException if a naming exception is encountered
854      */

855     public void modifyAttributes(Name JavaDoc name, ModificationItem JavaDoc[] mods)
856         throws NamingException JavaDoc {
857         dirContext.modifyAttributes(parseName(name), mods);
858     }
859
860
861     /**
862      * Modifies the attributes associated with a named object using an an
863      * ordered list of modifications.
864      *
865      * @param name the name of the object whose attributes will be updated
866      * @param mods an ordered sequence of modifications to be performed; may
867      * not be null
868      * @exception AttributeModificationException if the modification cannot be
869      * completed successfully
870      * @exception NamingException if a naming exception is encountered
871      */

872     public void modifyAttributes(String JavaDoc name, ModificationItem JavaDoc[] mods)
873         throws NamingException JavaDoc {
874         dirContext.modifyAttributes(parseName(name), mods);
875     }
876
877
878     /**
879      * Binds a name to an object, along with associated attributes. If attrs
880      * is null, the resulting binding will have the attributes associated
881      * with obj if obj is a DirContext, and no attributes otherwise. If attrs
882      * is non-null, the resulting binding will have attrs as its attributes;
883      * any attributes associated with obj are ignored.
884      *
885      * @param name the name to bind; may not be empty
886      * @param obj the object to bind; possibly null
887      * @param attrs the attributes to associate with the binding
888      * @exception NameAlreadyBoundException if name is already bound
889      * @exception InvalidAttributesException if some "mandatory" attributes
890      * of the binding are not supplied
891      * @exception NamingException if a naming exception is encountered
892      */

893     public void bind(Name JavaDoc name, Object JavaDoc obj, Attributes JavaDoc attrs)
894         throws NamingException JavaDoc {
895         dirContext.bind(parseName(name), obj, attrs);
896     }
897
898
899     /**
900      * Binds a name to an object, along with associated attributes.
901      *
902      * @param name the name to bind; may not be empty
903      * @param obj the object to bind; possibly null
904      * @param attrs the attributes to associate with the binding
905      * @exception NameAlreadyBoundException if name is already bound
906      * @exception InvalidAttributesException if some "mandatory" attributes
907      * of the binding are not supplied
908      * @exception NamingException if a naming exception is encountered
909      */

910 <