Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » naming » resources » [javadoc | source]
    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   

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » naming » resources » [javadoc | source]