1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19 package org.apache.naming.resources;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.Hashtable;
25
26 import javax.naming.Context;
27 import javax.naming.Name;
28 import javax.naming.NameNotFoundException;
29 import javax.naming.NameParser;
30 import javax.naming.NamingEnumeration;
31 import javax.naming.NamingException;
32 import javax.naming.directory.Attributes;
33 import javax.naming.directory.DirContext;
34 import javax.naming.directory.ModificationItem;
35 import javax.naming.directory.SearchControls;
36
37 import org.apache.naming.StringManager;
38
39 /**
40 * Proxy Directory Context implementation.
41 *
42 * @author Remy Maucherat
43 * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
44 */
45
46 public class ProxyDirContext implements DirContext {
47
48
49 // -------------------------------------------------------------- Constants
50
51
52 public static final String CONTEXT = "context";
53 public static final String HOST = "host";
54
55
56 // ----------------------------------------------------------- Constructors
57
58
59 /**
60 * Builds a proxy directory context using the given environment.
61 */
62 public ProxyDirContext(Hashtable env, DirContext dirContext) {
63 this.env = env;
64 this.dirContext = dirContext;
65 if (dirContext instanceof BaseDirContext) {
66 // Initialize parameters based on the associated dir context, like
67 // the caching policy.
68 BaseDirContext baseDirContext = (BaseDirContext) dirContext;
69 if (baseDirContext.isCached()) {
70 try {
71 cache = (ResourceCache)
72 Class.forName(cacheClassName).newInstance();
73 } catch (Exception e) {
74 //FIXME
75 e.printStackTrace();
76 }
77 cache.setCacheMaxSize(baseDirContext.getCacheMaxSize());
78 cacheTTL = baseDirContext.getCacheTTL();
79 cacheObjectMaxSize = baseDirContext.getCacheMaxSize() / 20;
80 }
81 }
82 hostName = (String) env.get(HOST);
83 contextName = (String) env.get(CONTEXT);
84 }
85
86
87 /**
88 * Builds a clone of this proxy dir context, wrapping the given directory
89 * context, and sharing the same cache.
90 */
91 // TODO: Refactor using the proxy field
92 /*
93 protected ProxyDirContext(ProxyDirContext proxyDirContext,
94 DirContext dirContext, String vPath) {
95 this.env = proxyDirContext.env;
96 this.dirContext = dirContext;
97 this.vPath = vPath;
98 this.cache = proxyDirContext.cache;
99 this.cacheMaxSize = proxyDirContext.cacheMaxSize;
100 this.cacheSize = proxyDirContext.cacheSize;
101 this.cacheTTL = proxyDirContext.cacheTTL;
102 this.cacheObjectMaxSize = proxyDirContext.cacheObjectMaxSize;
103 this.notFoundCache = proxyDirContext.notFoundCache;
104 this.hostName = proxyDirContext.hostName;
105 this.contextName = proxyDirContext.contextName;
106 }
107 */
108
109
110 // ----------------------------------------------------- Instance Variables
111
112
113 /**
114 * Proxy DirContext (either this or the real proxy).
115 */
116 protected ProxyDirContext proxy = this;
117
118
119 /**
120 * Environment.
121 */
122 protected Hashtable env;
123
124
125 /**
126 * The string manager for this package.
127 */
128 protected StringManager sm = StringManager.getManager(Constants.Package);
129
130
131 /**
132 * Associated DirContext.
133 */
134 protected DirContext dirContext;
135
136
137 /**
138 * Virtual path.
139 */
140 protected String vPath = null;
141
142
143 /**
144 * Host name.
145 */
146 protected String hostName;
147
148
149 /**
150 * Context name.
151 */
152 protected String contextName;
153
154
155 /**
156 * Cache class.
157 */
158 protected String cacheClassName =
159 "org.apache.naming.resources.ResourceCache";
160
161
162 /**
163 * Cache.
164 */
165 protected ResourceCache cache = null;
166
167
168 /**
169 * Cache TTL.
170 */
171 protected int cacheTTL = 5000; // 5s
172
173
174 /**
175 * Max size of resources which will have their content cached.
176 */
177 protected int cacheObjectMaxSize = 512; // 512 KB
178
179
180 /**
181 * Immutable name not found exception.
182 */
183 protected NameNotFoundException notFoundException =
184 new ImmutableNameNotFoundException();
185
186
187 /**
188 * Non cacheable resources.
189 */
190 protected String[] nonCacheable = { "/WEB-INF/lib/", "/WEB-INF/classes/" };
191
192
193 // --------------------------------------------------------- Public Methods
194
195
196 /**
197 * Get the cache used for this context.
198 */
199 public ResourceCache getCache() {
200 return cache;
201 }
202
203
204 /**
205 * Return the actual directory context we are wrapping.
206 */
207 public DirContext getDirContext() {
208 return this.dirContext;
209 }
210
211
212 /**
213 * Return the document root for this component.
214 */
215 public String getDocBase() {
216 if (dirContext instanceof BaseDirContext)
217 return ((BaseDirContext) dirContext).getDocBase();
218 else
219 return "";
220 }
221
222
223 /**
224 * Return the host name.
225 */
226 public String getHostName() {
227 return this.hostName;
228 }
229
230
231 /**
232 * Return the context name.
233 */
234 public String getContextName() {
235 return this.contextName;
236 }
237
238
239 // -------------------------------------------------------- Context Methods
240
241
242 /**
243 * Retrieves the named object. If name is empty, returns a new instance
244 * of this context (which represents the same naming context as this
245 * context, but its environment may be modified independently and it may
246 * be accessed concurrently).
247 *
248 * @param name the name of the object to look up
249 * @return the object bound to name
250 * @exception NamingException if a naming exception is encountered
251 */
252 public Object lookup(Name name)
253 throws NamingException {
254 CacheEntry entry = cacheLookup(name.toString());
255 if (entry != null) {
256 if (!entry.exists) {
257 throw notFoundException;
258 }
259 if (entry.resource != null) {
260 // Check content caching.
261 return entry.resource;
262 } else {
263 return entry.context;
264 }
265 }
266 Object object = dirContext.lookup(parseName(name));
267 if (object instanceof InputStream)
268 return new Resource((InputStream) object);
269 else
270 return object;
271 }
272
273
274 /**
275 * Retrieves the named object.
276 *
277 * @param name the name of the object to look up
278 * @return the object bound to name
279 * @exception NamingException if a naming exception is encountered
280 */
281 public Object lookup(String name)
282 throws NamingException {
283 CacheEntry entry = cacheLookup(name);
284 if (entry != null) {
285 if (!entry.exists) {
286 throw notFoundException;
287 }
288 if (entry.resource != null) {
289 return entry.resource;
290 } else {
291 return entry.context;
292 }
293 }
294 Object object = dirContext.lookup(parseName(name));
295 if (object instanceof InputStream) {
296 return new Resource((InputStream) object);
297 } else if (object instanceof DirContext) {
298 return object;
299 } else if (object instanceof Resource) {
300 return object;
301 } else {
302 return new Resource(new ByteArrayInputStream
303 (object.toString().getBytes()));
304 }
305 }
306
307
308 /**
309 * Binds a name to an object. All intermediate contexts and the target
310 * context (that named by all but terminal atomic component of the name)
311 * must already exist.
312 *
313 * @param name the name to bind; may not be empty
314 * @param obj the object to bind; possibly null
315 * @exception NameAlreadyBoundException if name is already bound
316 * @exception InvalidAttributesException if object did not supply all
317 * mandatory attributes
318 * @exception NamingException if a naming exception is encountered
319 */
320 public void bind(Name name, Object obj)
321 throws NamingException {
322 dirContext.bind(parseName(name), obj);
323 cacheUnload(name.toString());
324 }
325
326
327 /**
328 * Binds a name to an object.
329 *
330 * @param name the name to bind; may not be empty
331 * @param obj the object to bind; possibly null
332 * @exception NameAlreadyBoundException if name is already bound
333 * @exception InvalidAttributesException if object did not supply all
334 * mandatory attributes
335 * @exception NamingException if a naming exception is encountered
336 */
337 public void bind(String name, Object obj)
338 throws NamingException {
339 dirContext.bind(parseName(name), obj);
340 cacheUnload(name);
341 }
342
343
344 /**
345 * Binds a name to an object, overwriting any existing binding. All
346 * intermediate contexts and the target context (that named by all but
347 * terminal atomic component of the name) must already exist.
348 * <p>
349 * If the object is a DirContext, any existing attributes associated with
350 * the name are replaced with those of the object. Otherwise, any
351 * existing attributes associated with the name remain unchanged.
352 *
353 * @param name the name to bind; may not be empty
354 * @param obj the object to bind; possibly null
355 * @exception InvalidAttributesException if object did not supply all
356 * mandatory attributes
357 * @exception NamingException if a naming exception is encountered
358 */
359 public void rebind(Name name, Object obj)
360 throws NamingException {
361 dirContext.rebind(parseName(name), obj);
362 cacheUnload(name.toString());
363 }
364
365
366 /**
367 * Binds a name to an object, overwriting any existing binding.
368 *
369 * @param name the name to bind; may not be empty
370 * @param obj the object to bind; possibly null
371 * @exception InvalidAttributesException if object did not supply all
372 * mandatory attributes
373 * @exception NamingException if a naming exception is encountered
374 */
375 public void rebind(String name, Object obj)
376 throws NamingException {
377 dirContext.rebind(parseName(name), obj);
378 cacheUnload(name);
379 }
380
381
382 /**
383 * Unbinds the named object. Removes the terminal atomic name in name
384 * from the target context--that named by all but the terminal atomic
385 * part of name.
386 * <p>
387 * This method is idempotent. It succeeds even if the terminal atomic
388 * name is not bound in the target context, but throws
389 * NameNotFoundException if any of the intermediate contexts do not exist.
390 *
391 * @param name the name to bind; may not be empty
392 * @exception NameNotFoundException if an intermediate context does not
393 * exist
394 * @exception NamingException if a naming exception is encountered
395 */
396 public void unbind(Name name)
397 throws NamingException {
398 dirContext.unbind(parseName(name));
399 cacheUnload(name.toString());
400 }
401
402
403 /**
404 * Unbinds the named object.
405 *
406 * @param name the name to bind; may not be empty
407 * @exception NameNotFoundException if an intermediate context does not
408 * exist
409 * @exception NamingException if a naming exception is encountered
410 */
411 public void unbind(String name)
412 throws NamingException {
413 dirContext.unbind(parseName(name));
414 cacheUnload(name);
415 }
416
417
418 /**
419 * Binds a new name to the object bound to an old name, and unbinds the
420 * old name. Both names are relative to this context. Any attributes
421 * associated with the old name become associated with the new name.
422 * Intermediate contexts of the old name are not changed.
423 *
424 * @param oldName the name of the existing binding; may not be empty
425 * @param newName the name of the new binding; may not be empty
426 * @exception NameAlreadyBoundException if newName is already bound
427 * @exception NamingException if a naming exception is encountered
428 */
429 public void rename(Name oldName, Name newName)
430 throws NamingException {
431 dirContext.rename(parseName(oldName), parseName(newName));
432 cacheUnload(oldName.toString());
433 }
434
435
436 /**
437 * Binds a new name to the object bound to an old name, and unbinds the
438 * old name.
439 *
440 * @param oldName the name of the existing binding; may not be empty
441 * @param newName the name of the new binding; may not be empty
442 * @exception NameAlreadyBoundException if newName is already bound
443 * @exception NamingException if a naming exception is encountered
444 */
445 public void rename(String oldName, String newName)
446 throws NamingException {
447 dirContext.rename(parseName(oldName), parseName(newName));
448 cacheUnload(oldName);
449 }
450
451
452 /**
453 * Enumerates the names bound in the named context, along with the class
454 * names of objects bound to them. The contents of any subcontexts are
455 * not included.
456 * <p>
457 * If a binding is added to or removed from this context, its effect on
458 * an enumeration previously returned is undefined.
459 *
460 * @param name the name of the context to list
461 * @return an enumeration of the names and class names of the bindings in
462 * this context. Each element of the enumeration is of type NameClassPair.
463 * @exception NamingException if a naming exception is encountered
464 */
465 public NamingEnumeration list(Name name)
466 throws NamingException {
467 return dirContext.list(parseName(name));
468 }
469
470
471 /**
472 * Enumerates the names bound in the named context, along with the class
473 * names of objects bound to them.
474 *
475 * @param name the name of the context to list
476 * @return an enumeration of the names and class names of the bindings in
477 * this context. Each element of the enumeration is of type NameClassPair.
478 * @exception NamingException if a naming exception is encountered
479 */
480 public NamingEnumeration list(String name)
481 throws NamingException {
482 return dirContext.list(parseName(name));
483 }
484
485
486 /**
487 * Enumerates the names bound in the named context, along with the
488 * objects bound to them. The contents of any subcontexts are not
489 * included.
490 * <p>
491 * If a binding is added to or removed from this context, its effect on
492 * an enumeration previously returned is undefined.
493 *
494 * @param name the name of the context to list
495 * @return an enumeration of the bindings in this context.
496 * Each element of the enumeration is of type Binding.
497 * @exception NamingException if a naming exception is encountered
498 */
499 public NamingEnumeration listBindings(Name name)
500 throws NamingException {
501 return dirContext.listBindings(parseName(name));
502 }
503
504
505 /**
506 * Enumerates the names bound in the named context, along with the
507 * objects bound to them.
508 *
509 * @param name the name of the context to list
510 * @return an enumeration of the bindings in this context.
511 * Each element of the enumeration is of type Binding.
512 * @exception NamingException if a naming exception is encountered
513 */
514 public NamingEnumeration listBindings(String name)
515 throws NamingException {
516 return dirContext.listBindings(parseName(name));
517 }
518
519
520 /**
521 * Destroys the named context and removes it from the namespace. Any
522 * attributes associated with the name are also removed. Intermediate
523 * contexts are not destroyed.
524 * <p>
525 * This method is idempotent. It succeeds even if the terminal atomic
526 * name is not bound in the target context, but throws
527 * NameNotFoundException if any of the intermediate contexts do not exist.
528 *
529 * In a federated naming system, a context from one naming system may be
530 * bound to a name in another. One can subsequently look up and perform
531 * operations on the foreign context using a composite name. However, an
532 * attempt destroy the context using this composite name will fail with
533 * NotContextException, because the foreign context is not a "subcontext"
534 * of the context in which it is bound. Instead, use unbind() to remove
535 * the binding of the foreign context. Destroying the foreign context
536 * requires that the destroySubcontext() be performed on a context from
537 * the foreign context's "native" naming system.
538 *
539 * @param name the name of the context to be destroyed; may not be empty
540 * @exception NameNotFoundException if an intermediate context does not
541 * exist
542 * @exception NotContextException if the name is bound but does not name
543 * a context, or does not name a context of the appropriate type
544 */
545 public void destroySubcontext(Name name)
546 throws NamingException {
547 dirContext.destroySubcontext(parseName(name));
548 cacheUnload(name.toString());
549 }
550
551
552 /**
553 * Destroys the named context and removes it from the namespace.
554 *
555 * @param name the name of the context to be destroyed; may not be empty
556 * @exception NameNotFoundException if an intermediate context does not
557 * exist
558 * @exception NotContextException if the name is bound but does not name
559 * a context, or does not name a context of the appropriate type
560 */
561 public void destroySubcontext(String name)
562 throws NamingException {
563 dirContext.destroySubcontext(parseName(name));
564 cacheUnload(name);
565 }
566
567
568 /**
569 * Creates and binds a new context. Creates a new context with the given
570 * name and binds it in the target context (that named by all but
571 * terminal atomic component of the name). All intermediate contexts and
572 * the target context must already exist.
573 *
574 * @param name the name of the context to create; may not be empty
575 * @return the newly created context
576 * @exception NameAlreadyBoundException if name is already bound
577 * @exception InvalidAttributesException if creation of the subcontext
578 * requires specification of mandatory attributes
579 * @exception NamingException if a naming exception is encountered
580 */
581 public Context createSubcontext(Name name)
582 throws NamingException {
583 Context context = dirContext.createSubcontext(parseName(name));
584 cacheUnload(name.toString());
585 return context;
586 }
587
588
589 /**
590 * Creates and binds a new context.
591 *
592 * @param name the name of the context to create; may not be empty
593 * @return the newly created context
594 * @exception NameAlreadyBoundException if name is already bound
595 * @exception InvalidAttributesException if creation of the subcontext
596 * requires specification of mandatory attributes
597 * @exception NamingException if a naming exception is encountered
598 */
599 public Context createSubcontext(String name)
600 throws NamingException {
601 Context context = dirContext.createSubcontext(parseName(name));
602 cacheUnload(name);
603 return context;
604 }
605
606
607 /**
608 * Retrieves the named object, following links except for the terminal
609 * atomic component of the name. If the object bound to name is not a
610 * link, returns the object itself.
611 *
612 * @param name the name of the object to look up
613 * @return the object bound to name, not following the terminal link
614 * (if any).
615 * @exception NamingException if a naming exception is encountered
616 */
617 public Object lookupLink(Name name)
618 throws NamingException {
619 return dirContext.lookupLink(parseName(name));
620 }
621
622
623 /**
624 * Retrieves the named object, following links except for the terminal
625 * atomic component of the name.
626 *
627 * @param name the name of the object to look up
628 * @return the object bound to name, not following the terminal link
629 * (if any).
630 * @exception NamingException if a naming exception is encountered
631 */
632 public Object lookupLink(String name)
633 throws NamingException {
634 return dirContext.lookupLink(parseName(name));
635 }
636
637
638 /**
639 * Retrieves the parser associated with the named context. In a
640 * federation of namespaces, different naming systems will parse names
641 * differently. This method allows an application to get a parser for
642 * parsing names into their atomic components using the naming convention
643 * of a particular naming system. Within any single naming system,
644 * NameParser objects returned by this method must be equal (using the
645 * equals() test).
646 *
647 * @param name the name of the context from which to get the parser
648 * @return a name parser that can parse compound names into their atomic
649 * components
650 * @exception NamingException if a naming exception is encountered
651 */
652 public NameParser getNameParser(Name name)
653 throws NamingException {
654 return dirContext.getNameParser(parseName(name));
655 }
656
657
658 /**
659 * Retrieves the parser associated with the named context.
660 *
661 * @param name the name of the context from which to get the parser
662 * @return a name parser that can parse compound names into their atomic
663 * components
664 * @exception NamingException if a naming exception is encountered
665 */
666 public NameParser getNameParser(String name)
667 throws NamingException {
668 return dirContext.getNameParser(parseName(name));
669 }
670
671
672 /**
673 * Composes the name of this context with a name relative to this context.
674 * <p>
675 * Given a name (name) relative to this context, and the name (prefix)
676 * of this context relative to one of its ancestors, this method returns
677 * the composition of the two names using the syntax appropriate for the
678 * naming system(s) involved. That is, if name names an object relative
679 * to this context, the result is the name of the same object, but
680 * relative to the ancestor context. None of the names may be null.
681 *
682 * @param name a name relative to this context
683 * @param prefix the name of this context relative to one of its ancestors
684 * @return the composition of prefix and name
685 * @exception NamingException if a naming exception is encountered
686 */
687 public Name composeName(Name name, Name prefix)
688 throws NamingException {
689 prefix = (Name) prefix.clone();
690 return prefix.addAll(name);
691 }
692
693
694 /**
695 * Composes the name of this context with a name relative to this context.
696 *
697 * @param name a name relative to this context
698 * @param prefix the name of this context relative to one of its ancestors
699 * @return the composition of prefix and name
700 * @exception NamingException if a naming exception is encountered
701 */
702 public String composeName(String name, String prefix)
703 throws NamingException {
704 return prefix + "/" + name;
705 }
706
707
708 /**
709 * Adds a new environment property to the environment of this context. If
710 * the property already exists, its value is overwritten.
711 *
712 * @param propName the name of the environment property to add; may not
713 * be null
714 * @param propVal the value of the property to add; may not be null
715 * @exception NamingException if a naming exception is encountered
716 */
717 public Object addToEnvironment(String propName, Object propVal)
718 throws NamingException {
719 return dirContext.addToEnvironment(propName, propVal);
720 }
721
722
723 /**
724 * Removes an environment property from the environment of this context.
725 *
726 * @param propName the name of the environment property to remove;
727 * may not be null
728 * @exception NamingException if a naming exception is encountered
729 */
730 public Object removeFromEnvironment(String propName)
731 throws NamingException {
732 return dirContext.removeFromEnvironment(propName);
733 }
734
735
736 /**
737 * Retrieves the environment in effect for this context. See class
738 * description for more details on environment properties.
739 * The caller should not make any changes to the object returned: their
740 * effect on the context is undefined. The environment of this context
741 * may be changed using addToEnvironment() and removeFromEnvironment().
742 *
743 * @return the environment of this context; never null
744 * @exception NamingException if a naming exception is encountered
745 */
746 public Hashtable getEnvironment()
747 throws NamingException {
748 return dirContext.getEnvironment();
749 }
750
751
752 /**
753 * Closes this context. This method releases this context's resources
754 * immediately, instead of waiting for them to be released automatically
755 * by the garbage collector.
756 * This method is idempotent: invoking it on a context that has already
757 * been closed has no effect. Invoking any other method on a closed
758 * context is not allowed, and results in undefined behaviour.
759 *
760 * @exception NamingException if a naming exception is encountered
761 */
762 public void close()
763 throws NamingException {
764 dirContext.close();
765 }
766
767
768 /**
769 * Retrieves the full name of this context within its own namespace.
770 * <p>
771 * Many naming services have a notion of a "full name" for objects in
772 * their respective namespaces. For example, an LDAP entry has a
773 * distinguished name, and a DNS record has a fully qualified name. This
774 * method allows the client application to retrieve this name. The string
775 * returned by this method is not a JNDI composite name and should not be
776 * passed directly to context methods. In naming systems for which the
777 * notion of full name does not make sense,
778 * OperationNotSupportedException is thrown.
779 *
780 * @return this context's name in its own namespace; never null
781 * @exception OperationNotSupportedException if the naming system does
782 * not have the notion of a full name
783 * @exception NamingException if a naming exception is encountered
784 */
785 public String getNameInNamespace()
786 throws NamingException {
787 return dirContext.getNameInNamespace();
788 }
789
790
791 // ----------------------------------------------------- DirContext Methods
792
793
794 /**
795 * Retrieves all of the attributes associated with a named object.
796 *
797 * @return the set of attributes associated with name.
798 * Returns an empty attribute set if name has no attributes; never null.
799 * @param name the name of the object from which to retrieve attributes
800 * @exception NamingException if a naming exception is encountered
801 */
802 public Attributes getAttributes(Name name)
803 throws NamingException {
804 CacheEntry entry = cacheLookup(name.toString());
805 if (entry != null) {
806 if (!entry.exists) {
807 throw notFoundException;
808 }
809 return entry.attributes;
810 }
811 Attributes attributes = dirContext.getAttributes(parseName(name));
812 if (!(attributes instanceof ResourceAttributes)) {
813 attributes = new ResourceAttributes(attributes);
814 }
815 return attributes;
816 }
817
818
819 /**
820 * Retrieves all of the attributes associated with a named object.
821 *
822 * @return the set of attributes associated with name
823 * @param name the name of the object from which to retrieve attributes
824 * @exception NamingException if a naming exception is encountered
825 */
826 public Attributes getAttributes(String name)
827 throws NamingException {
828 CacheEntry entry = cacheLookup(name);
829 if (entry != null) {
830 if (!entry.exists) {
831 throw notFoundException;
832 }
833 return entry.attributes;
834 }
835 Attributes attributes = dirContext.getAttributes(parseName(name));
836 if (!(attributes instanceof ResourceAttributes)) {
837 attributes = new ResourceAttributes(attributes);
838 }
839 return attributes;
840 }
841
842
843 /**
844 * Retrieves selected attributes associated with a named object.
845 * See the class description regarding attribute models, attribute type
846 * names, and operational attributes.
847 *
848 * @return the requested attributes; never null
849 * @param name the name of the object from which to retrieve attributes
850 * @param attrIds the identifiers of the attributes to retrieve. null
851 * indicates that all attributes should be retrieved; an empty array
852 * indicates that none should be retrieved
853 * @exception NamingException if a naming exception is encountered
854 */
855 public Attributes getAttributes(Name name, String[] attrIds)
856 throws NamingException {
857 Attributes attributes =
858 dirContext.getAttributes(parseName(name), attrIds);
859 if (!(attributes instanceof ResourceAttributes)) {
860 attributes = new ResourceAttributes(attributes);
861 }
862 return attributes;
863 }
864
865
866 /**
867 * Retrieves selected attributes associated with a named object.
868 *
869 * @return the requested attributes; never null
870 * @param name the name of the object from which to retrieve attributes
871 * @param attrIds the identifiers of the attributes to retrieve. null
872 * indicates that all attributes should be retrieved; an empty array
873 * indicates that none should be retrieved
874 * @exception NamingException if a naming exception is encountered
875 */
876 public Attributes getAttributes(String name, String[] attrIds)
877 throws NamingException {
878 Attributes attributes =
879 dirContext.getAttributes(parseName(name), attrIds);
880 if (!(attributes instanceof ResourceAttributes)) {
881 attributes = new ResourceAttributes(attributes);
882 }
883 return attributes;
884 }
885
886
887 /**
888 * Modifies the attributes associated with a named object. The order of
889 * the modifications is not specified. Where possible, the modifications
890 * are performed atomically.
891 *
892 * @param name the name of the object whose attributes will be updated
893 * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
894 * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
895 * @param attrs the attributes to be used for the modification; may not
896 * be null
897 * @exception AttributeModificationException if the modification cannot be
898 * completed successfully
899 * @exception NamingException if a naming exception is encountered
900 */
901 public void modifyAttributes(Name name, int mod_op, Attributes attrs)
902 throws NamingException {
903 dirContext.modifyAttributes(parseName(name), mod_op, attrs);
904 cacheUnload(name.toString());
905 }
906
907
908 /**
909 * Modifies the attributes associated with a named object.
910 *
911 * @param name the name of the object whose attributes will be updated
912 * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
913 * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
914 * @param attrs the attributes to be used for the modification; may not
915 * be null
916 * @exception AttributeModificationException if the modification cannot be
917 * completed successfully
918 * @exception NamingException if a naming exception is encountered
919 */
920 public void modifyAttributes(String name, int mod_op, Attributes attrs)
921 throws NamingException {
922 dirContext.modifyAttributes(parseName(name), mod_op, attrs);
923 cacheUnload(name);
924 }
925
926
927 /**
928 * Modifies the attributes associated with a named object using an an
929 * ordered list of modifications. The modifications are performed in the
930 * order specified. Each modification specifies a modification operation
931 * code and an attribute on which to operate. Where possible, the
932 * modifications are performed atomically.
933 *
934 * @param name the name of the object whose attributes will be updated
935 * @param mods an ordered sequence of modifications to be performed; may
936 * not be null
937 * @exception AttributeModificationException if the modification cannot be
938 * completed successfully
939 * @exception NamingException if a naming exception is encountered
940 */
941 public void modifyAttributes(Name name, ModificationItem[] mods)
942 throws NamingException {
943 dirContext.modifyAttributes(parseName(name), mods);
944 cacheUnload(name.toString());
945 }
946
947
948 /**
949 * Modifies the attributes associated with a named object using an an
950 * ordered list of modifications.
951 *
952 * @param name the name of the object whose attributes will be updated
953 * @param mods an ordered sequence of modifications to be performed; may
954 * not be null
955 * @exception AttributeModificationException if the modification cannot be
956 * completed successfully
957 * @exception NamingException if a naming exception is encountered
958 */
959 public void modifyAttributes(String name, ModificationItem[] mods)
960 throws NamingException {
961 dirContext.modifyAttributes(parseName(name), mods);
962 cacheUnload(name);
963 }
964
965
966 /**
967 * Binds a name to an object, along with associated attributes. If attrs
968 * is null, the resulting binding will have the attributes associated
969 * with obj if obj is a DirContext, and no attributes otherwise. If attrs
970 * is non-null, the resulting binding will have attrs as its attributes;
971 * any attributes associated with obj are ignored.
972 *
973 * @param name the name to bind; may not be empty
974 * @param obj the object to bind; possibly null
975 * @param attrs the attributes to associate with the binding
976 * @exception NameAlreadyBoundException if name is already bound
977 * @exception InvalidAttributesException if some "mandatory" attributes
978 * of the binding are not supplied
979 * @exception NamingException if a naming exception is encountered
980 */
981 public void bind(Name name, Object obj, Attributes attrs)
982 throws NamingException {
983 dirContext.bind(parseName(name), obj, attrs);
984 cacheUnload(name.toString());
985 }
986
987
988 /**
989 * Binds a name to an object, along with associated attributes.
990 *
991 * @param name the name to bind; may not be empty
992 * @param obj the object to bind; possibly null
993 * @param attrs the attributes to associate with the binding
994 * @exception NameAlreadyBoundException if name is already bound
995 * @exception InvalidAttributesException if some "mandatory" attributes
996 * of the binding are not supplied
997 * @exception NamingException if a naming exception is encountered
998 */
999 public void bind(String name, Object obj, Attributes attrs)
1000 throws NamingException {
1001 dirContext.bind(parseName(name), obj, attrs);
1002 cacheUnload(name);
1003 }
1004
1005
1006 /**
1007 * Binds a name to an object, along with associated attributes,
1008 * overwriting any existing binding. If attrs is null and obj is a
1009 * DirContext, the attributes from obj are used. If attrs is null and obj
1010 * is not a DirContext, any existing attributes associated with the object
1011 * already bound in the directory remain unchanged. If attrs is non-null,
1012 * any existing attributes associated with the object already bound in
1013 * the directory are removed and attrs is associated with the named
1014 * object. If obj is a DirContext and attrs is non-null, the attributes
1015 * of obj are ignored.
1016 *
1017 * @param name the name to bind; may not be empty
1018 * @param obj the object to bind; possibly null
1019 * @param attrs the attributes to associate with the binding
1020 * @exception InvalidAttributesException if some "mandatory" attributes
1021 * of the binding are not supplied
1022 * @exception NamingException if a naming exception is encountered
1023 */
1024 public void rebind(Name name, Object obj, Attributes attrs)
1025 throws NamingException {
1026 dirContext.rebind(parseName(name), obj, attrs);
1027 cacheUnload(name.toString());
1028 }
1029
1030
1031 /**
1032 * Binds a name to an object, along with associated attributes,
1033 * overwriting any existing binding.
1034 *
1035 * @param name the name to bind; may not be empty
1036 * @param obj the object to bind; possibly null
1037 * @param attrs the attributes to associate with the binding
1038 * @exception InvalidAttributesException if some "mandatory" attributes
1039 * of the binding are not supplied
1040 * @exception NamingException if a naming exception is encountered
1041 */
1042 public void rebind(String name, Object obj, Attributes attrs)
1043 throws NamingException {
1044 dirContext.rebind(parseName(name), obj, attrs);
1045 cacheUnload(name);
1046 }
1047
1048
1049 /**
1050 * Creates and binds a new context, along with associated attributes.
1051 * This method creates a new subcontext with the given name, binds it in
1052 * the target context (that named by all but terminal atomic component of
1053 * the name), and associates the supplied attributes with the newly
1054 * created object. All intermediate and target contexts must already
1055 * exist. If attrs is null, this method is equivalent to
1056 * Context.createSubcontext().
1057 *
1058 * @param name the name of the context to create; may not be empty
1059 * @param attrs the attributes to associate with the newly created context
1060 * @return the newly created context
1061 * @exception NameAlreadyBoundException if the name is already bound
1062 * @exception InvalidAttributesException if attrs does not contain all
1063 * the mandatory attributes required for creation
1064 * @exception NamingException if a naming exception is encountered
1065 */
1066 public DirContext createSubcontext(Name name, Attributes attrs)
1067 throws NamingException {
1068 DirContext context =
1069 dirContext.createSubcontext(parseName(name), attrs);
1070 cacheUnload(name.toString());
1071 return context;
1072 }
1073
1074
1075 /**
1076 * Creates and binds a new context, along with associated attributes.
1077 *
1078 * @param name the name of the context to create; may not be empty
1079 * @param attrs the attributes to associate with the newly created context
1080 * @return the newly created context
1081 * @exception NameAlreadyBoundException if the name is already bound
1082 * @exception InvalidAttributesException if attrs does not contain all
1083 * the mandatory attributes required for creation
1084 * @exception NamingException if a naming exception is encountered
1085 */
1086 public DirContext createSubcontext(String name, Attributes attrs)
1087 throws NamingException {
1088 DirContext context =
1089 dirContext.createSubcontext(parseName(name), attrs);
1090 cacheUnload(name);
1091 return context;
1092 }
1093
1094
1095 /**
1096 * Retrieves the schema associated with the named object. The schema
1097 * describes rules regarding the structure of the namespace and the
1098 * attributes stored within it. The schema specifies what types of
1099 * objects can be added to the directory and where they can be added;
1100 * what mandatory and optional attributes an object can have. The range
1101 * of support for schemas is directory-specific.
1102 *
1103 * @param name the name of the object whose schema is to be retrieved
1104 * @return the schema associated with the context; never null
1105 * @exception OperationNotSupportedException if schema not supported
1106 * @exception NamingException if a naming exception is encountered
1107 */
1108 public DirContext getSchema(Name name)
1109 throws NamingException {
1110 return dirContext.getSchema(parseName(name));
1111 }
1112
1113
1114 /**
1115 * Retrieves the schema associated with the named object.
1116 *
1117 * @param name the name of the object whose schema is to be retrieved
1118 * @return the schema associated with the context; never null
1119 * @exception OperationNotSupportedException if schema not supported
1120 * @exception NamingException if a naming exception is encountered
1121 */
1122 public DirContext getSchema(String name)
1123 throws NamingException {
1124 return dirContext.getSchema(parseName(name));
1125 }
1126
1127
1128 /**
1129 * Retrieves a context containing the schema objects of the named
1130 * object's class definitions.
1131 *
1132 * @param name the name of the object whose object class definition is to
1133 * be retrieved
1134 * @return the DirContext containing the named object's class
1135 * definitions; never null
1136 * @exception OperationNotSupportedException if schema not supported
1137 * @exception NamingException if a naming exception is encountered
1138 */
1139 public DirContext getSchemaClassDefinition(Name name)
1140 throws NamingException {
1141 return dirContext.getSchemaClassDefinition(parseName(name));
1142 }
1143
1144
1145 /**
1146 * Retrieves a context containing the schema objects of the named
1147 * object's class definitions.
1148 *
1149 * @param name the name of the object whose object class definition is to
1150 * be retrieved
1151 * @return the DirContext containing the named object's class
1152 * definitions; never null
1153 * @exception OperationNotSupportedException if schema not supported
1154 * @exception NamingException if a naming exception is encountered
1155 */
1156 public DirContext getSchemaClassDefinition(String name)
1157 throws NamingException {
1158 return dirContext.getSchemaClassDefinition(parseName(name));
1159 }
1160
1161
1162 /**
1163 * Searches in a single context for objects that contain a specified set
1164 * of attributes, and retrieves selected attributes. The search is
1165 * performed using the default SearchControls settings.
1166 *
1167 * @param name the name of the context to search
1168 * @param matchingAttributes the attributes to search for. If empty or
1169 * null, all objects in the target context are returned.
1170 * @param attributesToReturn the attributes to return. null indicates
1171 * that all attributes are to be returned; an empty array indicates that
1172 * none are to be returned.
1173 * @return a non-null enumeration of SearchResult objects. Each
1174 * SearchResult contains the attributes identified by attributesToReturn
1175 * and the name of the corresponding object, named relative to the
1176 * context named by name.
1177 * @exception NamingException if a naming exception is encountered
1178 */
1179 public NamingEnumeration search(Name name, Attributes matchingAttributes,
1180 String[] attributesToReturn)
1181 throws NamingException {
1182 return dirContext.search(parseName(name), matchingAttributes,
1183 attributesToReturn);
1184 }
1185
1186
1187 /**
1188 * Searches in a single context for objects that contain a specified set
1189 * of attributes, and retrieves selected attributes.
1190 *
1191 * @param name the name of the context to search
1192 * @param matchingAttributes the attributes to search for. If empty or
1193 * null, all objects in the target context are returned.
1194 * @param attributesToReturn the attributes to return. null indicates
1195 * that all attributes are to be returned; an empty array indicates that
1196 * none are to be returned.
1197 * @return a non-null enumeration of SearchResult objects. Each
1198 * SearchResult contains the attributes identified by attributesToReturn
1199 * and the name of the corresponding object, named relative to the
1200 * context named by name.
1201 * @exception NamingException if a naming exception is encountered
1202 */
1203 public NamingEnumeration search(String name, Attributes matchingAttributes,
1204 String[] attributesToReturn)
1205 throws NamingException {
1206 return dirContext.search(parseName(name), matchingAttributes,
1207 attributesToReturn);
1208 }
1209
1210
1211 /**
1212 * Searches in a single context for objects that contain a specified set
1213 * of attributes. This method returns all the attributes of such objects.
1214 * It is equivalent to supplying null as the atributesToReturn parameter
1215 * to the method search(Name, Attributes, String[]).
1216 *
1217 * @param name the name of the context to search
1218 * @param matchingAttributes the attributes to search for. If empty or
1219 * null, all objects in the target context are returned.
1220 * @return a non-null enumeration of SearchResult objects. Each
1221 * SearchResult contains the attributes identified by attributesToReturn
1222 * and the name of the corresponding object, named relative to the
1223 * context named by name.
1224 * @exception NamingException if a naming exception is encountered
1225 */
1226 public NamingEnumeration search(Name name, Attributes matchingAttributes)
1227 throws NamingException {
1228 return dirContext.search(parseName(name), matchingAttributes);
1229 }
1230
1231
1232 /**
1233 * Searches in a single context for objects that contain a specified set
1234 * of attributes.
1235 *
1236 * @param name the name of the context to search
1237 * @param matchingAttributes the attributes to search for. If empty or
1238 * null, all objects in the target context are returned.
1239 * @return a non-null enumeration of SearchResult objects. Each
1240 * SearchResult contains the attributes identified by attributesToReturn
1241 * and the name of the corresponding object, named relative to the
1242 * context named by name.
1243 * @exception NamingException if a naming exception is encountered
1244 */
1245 public NamingEnumeration search(String name, Attributes matchingAttributes)
1246 throws NamingException {
1247 return dirContext.search(parseName(name), matchingAttributes);
1248 }
1249
1250
1251 /**
1252 * Searches in the named context or object for entries that satisfy the
1253 * given search filter. Performs the search as specified by the search
1254 * controls.
1255 *
1256 * @param name the name of the context or object to search
1257 * @param filter the filter expression to use for the search; may not be
1258 * null
1259 * @param cons the search controls that control the search. If null,
1260 * the default search controls are used (equivalent to
1261 * (new SearchControls())).
1262 * @return an enumeration of SearchResults of the objects that satisfy
1263 * the filter; never null
1264 * @exception InvalidSearchFilterException if the search filter specified
1265 * is not supported or understood by the underlying directory
1266 * @exception InvalidSearchControlsException if the search controls
1267 * contain invalid settings
1268 * @exception NamingException if a naming exception is encountered
1269 */
1270 public NamingEnumeration search(Name name, String filter,
1271 SearchControls cons)
1272 throws NamingException {
1273 return dirContext.search(parseName(name), filter, cons);
1274 }
1275
1276
1277 /**
1278 * Searches in the named context or object for entries that satisfy the
1279 * given search filter. Performs the search as specified by the search
1280 * controls.
1281 *
1282 * @param name the name of the context or object to search
1283 * @param filter the filter expression to use for the search; may not be
1284 * null
1285 * @param cons the search controls that control the search. If null,
1286 * the default search controls are used (equivalent to
1287 * (new SearchControls())).
1288 * @return an enumeration of SearchResults of the objects that satisfy
1289 * the filter; never null
1290 * @exception InvalidSearchFilterException if the search filter
1291 * specified is not supported or understood by the underlying directory
1292 * @exception InvalidSearchControlsException if the search controls
1293 * contain invalid settings
1294 * @exception NamingException if a naming exception is encountered
1295 */
1296 public NamingEnumeration search(String name, String filter,
1297 SearchControls cons)
1298 throws NamingException {
1299 return dirContext.search(parseName(name), filter, cons);
1300 }
1301
1302
1303 /**
1304 * Searches in the named context or object for entries that satisfy the
1305 * given search filter. Performs the search as specified by the search
1306 * controls.
1307 *
1308 * @param name the name of the context or object to search
1309 * @param filterExpr the filter expression to use for the search.
1310 * The expression may contain variables of the form "{i}" where i is a
1311 * nonnegative integer. May not be null.
1312 * @param filterArgs the array of arguments to substitute for the
1313 * variables in filterExpr. The value of filterArgs[i] will replace each
1314 * occurrence of "{i}". If null, equivalent to an empty array.
1315 * @param cons the search controls that control the search. If null, the
1316 * default search controls are used (equivalent to (new SearchControls())).
1317 * @return an enumeration of SearchResults of the objects that satisy the
1318 * filter; never null
1319 * @exception ArrayIndexOutOfBoundsException if filterExpr contains {i}
1320 * expressions where i is outside the bounds of the array filterArgs
1321 * @exception InvalidSearchControlsException if cons contains invalid
1322 * settings
1323 * @exception InvalidSearchFilterException if filterExpr with filterArgs
1324 * represents an invalid search filter
1325 * @exception NamingException if a naming exception is encountered
1326 */
1327 public NamingEnumeration search(Name name, String filterExpr,
1328 Object[] filterArgs, SearchControls cons)
1329 throws NamingException {
1330 return dirContext.search(parseName(name), filterExpr, filterArgs,
1331 cons);
1332 }
1333
1334
1335 /**
1336 * Searches in the named context or object for entries that satisfy the
1337 * given search filter. Performs the search as specified by the search
1338 * controls.
1339 *
1340 * @param name the name of the context or object to search
1341 * @param filterExpr the filter expression to use for the search.
1342 * The expression may contain variables of the form "{i}" where i is a
1343 * nonnegative integer. May not be null.
1344 * @param filterArgs the array of arguments to substitute for the
1345 * variables in filterExpr. The value of filterArgs[i] will replace each
1346 * occurrence of "{i}". If null, equivalent to an empty array.
1347 * @param cons the search controls that control the search. If null, the
1348 * default search controls are used (equivalent to (new SearchControls())).
1349 * @return an enumeration of SearchResults of the objects that satisy the
1350 * filter; never null
1351 * @exception ArrayIndexOutOfBoundsException if filterExpr contains {i}
1352 * expressions where i is outside the bounds of the array filterArgs
1353 * @exception InvalidSearchControlsException if cons contains invalid
1354 * settings
1355 * @exception InvalidSearchFilterException if filterExpr with filterArgs
1356 * represents an invalid search filter
1357 * @exception NamingException if a naming exception is encountered
1358 */
1359 public NamingEnumeration search(String name, String filterExpr,
1360 Object[] filterArgs, SearchControls cons)
1361 throws NamingException {
1362 return dirContext.search(parseName(name), filterExpr, filterArgs,
1363 cons);
1364 }
1365
1366
1367 // --------------------------------------------------------- Public Methods
1368
1369
1370 /**
1371 * Retrieves the named object as a cache entry, without any exception.
1372 *
1373 * @param name the name of the object to look up
1374 * @return the cache entry bound to name
1375 */
1376 public CacheEntry lookupCache(String name) {
1377 CacheEntry entry = cacheLookup(name);
1378 if (entry == null) {
1379 entry = new CacheEntry();
1380 entry.name = name;
1381 try {
1382 Object object = dirContext.lookup(parseName(name));
1383 if (object instanceof InputStream) {
1384 entry.resource = new Resource((InputStream) object);
1385 } else if (object instanceof DirContext) {
1386 entry.context = (DirContext) object;
1387 } else if (object instanceof Resource) {
1388 entry.resource = (Resource) object;
1389 } else {
1390 entry.resource = new Resource(new ByteArrayInputStream
1391 (object.toString().getBytes()));
1392 }
1393 Attributes attributes = dirContext.getAttributes(parseName(name));
1394 if (!(attributes instanceof ResourceAttributes)) {
1395 attributes = new ResourceAttributes(attributes);
1396 }
1397 entry.attributes = (ResourceAttributes) attributes;
1398 } catch (NamingException e) {
1399 entry.exists = false;
1400 }
1401 }
1402 return entry;
1403 }
1404
1405
1406 // ------------------------------------------------------ Protected Methods
1407
1408
1409 /**
1410 * Parses a name.
1411 *
1412 * @return the parsed name
1413 */
1414 protected String parseName(String name)
1415 throws NamingException {
1416 return name;
1417 }
1418
1419
1420 /**
1421 * Parses a name.
1422 *
1423 * @return the parsed name
1424 */
1425 protected Name parseName(Name name)
1426 throws NamingException {
1427 return name;
1428 }
1429
1430
1431 /**
1432 * Lookup in cache.
1433 */
1434 protected CacheEntry cacheLookup(String name) {
1435 if (cache == null)
1436 return (null);
1437 if (name == null)
1438 name = "";
1439 for (int i = 0; i < nonCacheable.length; i++) {
1440 if (name.startsWith(nonCacheable[i])) {
1441 return (null);
1442 }
1443 }
1444 CacheEntry cacheEntry = cache.lookup(name);
1445 if (cacheEntry == null) {
1446 cacheEntry = new CacheEntry();
1447 cacheEntry.name = name;
1448 // Load entry
1449 cacheLoad(cacheEntry);
1450 } else {
1451 if (!validate(cacheEntry)) {
1452 if (!revalidate(cacheEntry)) {
1453 cacheUnload(cacheEntry.name);
1454 return (null);
1455 } else {
1456 cacheEntry.timestamp =
1457 System.currentTimeMillis() + cacheTTL;
1458 }
1459 }
1460 cacheEntry.accessCount++;
1461 }
1462 return (cacheEntry);
1463 }
1464
1465
1466 /**
1467 * Validate entry.
1468 */
1469 protected boolean validate(CacheEntry entry) {
1470 if (((!entry.exists)
1471 || (entry.context != null)
1472 || ((entry.resource != null)
1473 && (entry.resource.getContent() != null)))
1474 && (System.currentTimeMillis() < entry.timestamp)) {
1475 return true;
1476 }
1477 return false;
1478 }
1479
1480
1481 /**
1482 * Revalidate entry.
1483 */
1484 protected boolean revalidate(CacheEntry entry) {
1485 // Get the attributes at the given path, and check the last
1486 // modification date
1487 if (!entry.exists)
1488 return false;
1489 if (entry.attributes == null)
1490 return false;
1491 long lastModified = entry.attributes.getLastModified();
1492 long contentLength = entry.attributes.getContentLength();
1493 if (lastModified <= 0)
1494 return false;
1495 try {
1496 Attributes tempAttributes = dirContext.getAttributes(entry.name);
1497 ResourceAttributes attributes = null;
1498 if (!(tempAttributes instanceof ResourceAttributes)) {
1499 attributes = new ResourceAttributes(tempAttributes);
1500 } else {
1501 attributes = (ResourceAttributes) tempAttributes;
1502 }
1503 long lastModified2 = attributes.getLastModified();
1504 long contentLength2 = attributes.getContentLength();
1505 return (lastModified == lastModified2)
1506 && (contentLength == contentLength2);
1507 } catch (NamingException e) {
1508 return false;
1509 }
1510 }
1511
1512
1513 /**
1514 * Load entry into cache.
1515 */
1516 protected void cacheLoad(CacheEntry entry) {
1517
1518 String name = entry.name;
1519
1520 // Retrieve missing info
1521 boolean exists = true;
1522
1523 // Retrieving attributes
1524 if (entry.attributes == null) {
1525 try {
1526 Attributes attributes = dirContext.getAttributes(entry.name);
1527 if (!(attributes instanceof ResourceAttributes)) {
1528 entry.attributes =
1529 new ResourceAttributes(attributes);
1530 } else {
1531 entry.attributes = (ResourceAttributes) attributes;
1532 }
1533 } catch (NamingException e) {
1534 exists = false;
1535 }
1536 }
1537
1538 // Retriving object
1539 if ((exists) && (entry.resource == null) && (entry.context == null)) {
1540 try {
1541 Object object = dirContext.lookup(name);
1542 if (object instanceof InputStream) {
1543 entry.resource = new Resource((InputStream) object);
1544 } else if (object instanceof DirContext) {
1545 entry.context = (DirContext) object;
1546 } else if (object instanceof Resource) {
1547 entry.resource = (Resource) object;
1548 } else {
1549 entry.resource = new Resource(new ByteArrayInputStream
1550 (object.toString().getBytes()));
1551 }
1552 } catch (NamingException e) {
1553 exists = false;
1554 }
1555 }
1556
1557 // Load object content
1558 if ((exists) && (entry.resource != null)
1559 && (entry.resource.getContent() == null)
1560 && (entry.attributes.getContentLength() >= 0)
1561 && (entry.attributes.getContentLength() <
1562 (cacheObjectMaxSize * 1024))) {
1563 int length = (int) entry.attributes.getContentLength();
1564 // The entry size is 1 + the resource size in KB, if it will be
1565 // cached
1566 entry.size += (entry.attributes.getContentLength() / 1024);
1567 InputStream is = null;
1568 try {
1569 is = entry.resource.streamContent();
1570 int pos = 0;
1571 byte[] b = new byte[length];
1572 while (pos < length) {
1573 int n = is.read(b, pos, length - pos);
1574 if (n < 0)
1575 break;
1576 pos = pos + n;
1577 }
1578 entry.resource.setContent(b);
1579 } catch (IOException e) {
1580 ; // Ignore
1581 } finally {
1582 try {
1583 if (is != null)
1584 is.close();
1585 } catch (IOException e) {
1586 ; // Ignore
1587 }
1588 }
1589 }
1590
1591 // Set existence flag
1592 entry.exists = exists;
1593
1594 // Set timestamp
1595 entry.timestamp = System.currentTimeMillis() + cacheTTL;
1596
1597 // Add new entry to cache
1598 synchronized (cache) {
1599 // Check cache size, and remove elements if too big
1600 if ((cache.lookup(name) == null) && cache.allocate(entry.size)) {
1601 cache.load(entry);
1602 }
1603 }
1604
1605 }
1606
1607
1608 /**
1609 * Remove entry from cache.
1610 */
1611 protected boolean cacheUnload(String name) {
1612 if (cache == null)
1613 return false;
1614 synchronized (cache) {
1615 return cache.unload(name);
1616 }
1617 }
1618
1619
1620 }
1621