0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.naming.resources;
0019:
0020: import java.io.ByteArrayInputStream;
0021: import java.io.IOException;
0022: import java.io.InputStream;
0023: import java.util.Hashtable;
0024:
0025: import javax.naming.Context;
0026: import javax.naming.Name;
0027: import javax.naming.NameNotFoundException;
0028: import javax.naming.NameParser;
0029: import javax.naming.NamingEnumeration;
0030: import javax.naming.NamingException;
0031: import javax.naming.directory.Attributes;
0032: import javax.naming.directory.DirContext;
0033: import javax.naming.directory.ModificationItem;
0034: import javax.naming.directory.SearchControls;
0035:
0036: import org.apache.naming.StringManager;
0037:
0038: /**
0039: * Proxy Directory Context implementation.
0040: *
0041: * @author Remy Maucherat
0042: * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
0043: */
0044:
0045: public class ProxyDirContext implements DirContext {
0046:
0047: // -------------------------------------------------------------- Constants
0048:
0049: public static final String CONTEXT = "context";
0050: public static final String HOST = "host";
0051:
0052: // ----------------------------------------------------------- Constructors
0053:
0054: /**
0055: * Builds a proxy directory context using the given environment.
0056: */
0057: public ProxyDirContext(Hashtable env, DirContext dirContext) {
0058: this .env = env;
0059: this .dirContext = dirContext;
0060: if (dirContext instanceof BaseDirContext) {
0061: // Initialize parameters based on the associated dir context, like
0062: // the caching policy.
0063: BaseDirContext baseDirContext = (BaseDirContext) dirContext;
0064: if (baseDirContext.isCached()) {
0065: try {
0066: cache = (ResourceCache) Class.forName(
0067: cacheClassName).newInstance();
0068: } catch (Exception e) {
0069: //FIXME
0070: e.printStackTrace();
0071: }
0072: cache.setCacheMaxSize(baseDirContext.getCacheMaxSize());
0073: cacheTTL = baseDirContext.getCacheTTL();
0074: cacheObjectMaxSize = baseDirContext.getCacheMaxSize() / 20;
0075: }
0076: }
0077: hostName = (String) env.get(HOST);
0078: contextName = (String) env.get(CONTEXT);
0079: }
0080:
0081: /**
0082: * Builds a clone of this proxy dir context, wrapping the given directory
0083: * context, and sharing the same cache.
0084: */
0085: // TODO: Refactor using the proxy field
0086: /*
0087: protected ProxyDirContext(ProxyDirContext proxyDirContext,
0088: DirContext dirContext, String vPath) {
0089: this.env = proxyDirContext.env;
0090: this.dirContext = dirContext;
0091: this.vPath = vPath;
0092: this.cache = proxyDirContext.cache;
0093: this.cacheMaxSize = proxyDirContext.cacheMaxSize;
0094: this.cacheSize = proxyDirContext.cacheSize;
0095: this.cacheTTL = proxyDirContext.cacheTTL;
0096: this.cacheObjectMaxSize = proxyDirContext.cacheObjectMaxSize;
0097: this.notFoundCache = proxyDirContext.notFoundCache;
0098: this.hostName = proxyDirContext.hostName;
0099: this.contextName = proxyDirContext.contextName;
0100: }
0101: */
0102:
0103: // ----------------------------------------------------- Instance Variables
0104:
0105: /**
0106: * Proxy DirContext (either this or the real proxy).
0107: */
0108: protected ProxyDirContext proxy = this ;
0109:
0110: /**
0111: * Environment.
0112: */
0113: protected Hashtable env;
0114:
0115: /**
0116: * The string manager for this package.
0117: */
0118: protected StringManager sm = StringManager
0119: .getManager(Constants.Package);
0120:
0121: /**
0122: * Associated DirContext.
0123: */
0124: protected DirContext dirContext;
0125:
0126: /**
0127: * Virtual path.
0128: */
0129: protected String vPath = null;
0130:
0131: /**
0132: * Host name.
0133: */
0134: protected String hostName;
0135:
0136: /**
0137: * Context name.
0138: */
0139: protected String contextName;
0140:
0141: /**
0142: * Cache class.
0143: */
0144: protected String cacheClassName = "org.apache.naming.resources.ResourceCache";
0145:
0146: /**
0147: * Cache.
0148: */
0149: protected ResourceCache cache = null;
0150:
0151: /**
0152: * Cache TTL.
0153: */
0154: protected int cacheTTL = 5000; // 5s
0155:
0156: /**
0157: * Max size of resources which will have their content cached.
0158: */
0159: protected int cacheObjectMaxSize = 512; // 512 KB
0160:
0161: /**
0162: * Immutable name not found exception.
0163: */
0164: protected NameNotFoundException notFoundException = new ImmutableNameNotFoundException();
0165:
0166: /**
0167: * Non cacheable resources.
0168: */
0169: protected String[] nonCacheable = { "/WEB-INF/lib/",
0170: "/WEB-INF/classes/" };
0171:
0172: // --------------------------------------------------------- Public Methods
0173:
0174: /**
0175: * Get the cache used for this context.
0176: */
0177: public ResourceCache getCache() {
0178: return cache;
0179: }
0180:
0181: /**
0182: * Return the actual directory context we are wrapping.
0183: */
0184: public DirContext getDirContext() {
0185: return this .dirContext;
0186: }
0187:
0188: /**
0189: * Return the document root for this component.
0190: */
0191: public String getDocBase() {
0192: if (dirContext instanceof BaseDirContext)
0193: return ((BaseDirContext) dirContext).getDocBase();
0194: else
0195: return "";
0196: }
0197:
0198: /**
0199: * Return the host name.
0200: */
0201: public String getHostName() {
0202: return this .hostName;
0203: }
0204:
0205: /**
0206: * Return the context name.
0207: */
0208: public String getContextName() {
0209: return this .contextName;
0210: }
0211:
0212: // -------------------------------------------------------- Context Methods
0213:
0214: /**
0215: * Retrieves the named object. If name is empty, returns a new instance
0216: * of this context (which represents the same naming context as this
0217: * context, but its environment may be modified independently and it may
0218: * be accessed concurrently).
0219: *
0220: * @param name the name of the object to look up
0221: * @return the object bound to name
0222: * @exception NamingException if a naming exception is encountered
0223: */
0224: public Object lookup(Name name) throws NamingException {
0225: CacheEntry entry = cacheLookup(name.toString());
0226: if (entry != null) {
0227: if (!entry.exists) {
0228: throw notFoundException;
0229: }
0230: if (entry.resource != null) {
0231: // Check content caching.
0232: return entry.resource;
0233: } else {
0234: return entry.context;
0235: }
0236: }
0237: Object object = dirContext.lookup(parseName(name));
0238: if (object instanceof InputStream)
0239: return new Resource((InputStream) object);
0240: else
0241: return object;
0242: }
0243:
0244: /**
0245: * Retrieves the named object.
0246: *
0247: * @param name the name of the object to look up
0248: * @return the object bound to name
0249: * @exception NamingException if a naming exception is encountered
0250: */
0251: public Object lookup(String name) throws NamingException {
0252: CacheEntry entry = cacheLookup(name);
0253: if (entry != null) {
0254: if (!entry.exists) {
0255: throw notFoundException;
0256: }
0257: if (entry.resource != null) {
0258: return entry.resource;
0259: } else {
0260: return entry.context;
0261: }
0262: }
0263: Object object = dirContext.lookup(parseName(name));
0264: if (object instanceof InputStream) {
0265: return new Resource((InputStream) object);
0266: } else if (object instanceof DirContext) {
0267: return object;
0268: } else if (object instanceof Resource) {
0269: return object;
0270: } else {
0271: return new Resource(new ByteArrayInputStream(object
0272: .toString().getBytes()));
0273: }
0274: }
0275:
0276: /**
0277: * Binds a name to an object. All intermediate contexts and the target
0278: * context (that named by all but terminal atomic component of the name)
0279: * must already exist.
0280: *
0281: * @param name the name to bind; may not be empty
0282: * @param obj the object to bind; possibly null
0283: * @exception NameAlreadyBoundException if name is already bound
0284: * @exception InvalidAttributesException if object did not supply all
0285: * mandatory attributes
0286: * @exception NamingException if a naming exception is encountered
0287: */
0288: public void bind(Name name, Object obj) throws NamingException {
0289: dirContext.bind(parseName(name), obj);
0290: cacheUnload(name.toString());
0291: }
0292:
0293: /**
0294: * Binds a name to an object.
0295: *
0296: * @param name the name to bind; may not be empty
0297: * @param obj the object to bind; possibly null
0298: * @exception NameAlreadyBoundException if name is already bound
0299: * @exception InvalidAttributesException if object did not supply all
0300: * mandatory attributes
0301: * @exception NamingException if a naming exception is encountered
0302: */
0303: public void bind(String name, Object obj) throws NamingException {
0304: dirContext.bind(parseName(name), obj);
0305: cacheUnload(name);
0306: }
0307:
0308: /**
0309: * Binds a name to an object, overwriting any existing binding. All
0310: * intermediate contexts and the target context (that named by all but
0311: * terminal atomic component of the name) must already exist.
0312: * <p>
0313: * If the object is a DirContext, any existing attributes associated with
0314: * the name are replaced with those of the object. Otherwise, any
0315: * existing attributes associated with the name remain unchanged.
0316: *
0317: * @param name the name to bind; may not be empty
0318: * @param obj the object to bind; possibly null
0319: * @exception InvalidAttributesException if object did not supply all
0320: * mandatory attributes
0321: * @exception NamingException if a naming exception is encountered
0322: */
0323: public void rebind(Name name, Object obj) throws NamingException {
0324: dirContext.rebind(parseName(name), obj);
0325: cacheUnload(name.toString());
0326: }
0327:
0328: /**
0329: * Binds a name to an object, overwriting any existing binding.
0330: *
0331: * @param name the name to bind; may not be empty
0332: * @param obj the object to bind; possibly null
0333: * @exception InvalidAttributesException if object did not supply all
0334: * mandatory attributes
0335: * @exception NamingException if a naming exception is encountered
0336: */
0337: public void rebind(String name, Object obj) throws NamingException {
0338: dirContext.rebind(parseName(name), obj);
0339: cacheUnload(name);
0340: }
0341:
0342: /**
0343: * Unbinds the named object. Removes the terminal atomic name in name
0344: * from the target context--that named by all but the terminal atomic
0345: * part of name.
0346: * <p>
0347: * This method is idempotent. It succeeds even if the terminal atomic
0348: * name is not bound in the target context, but throws
0349: * NameNotFoundException if any of the intermediate contexts do not exist.
0350: *
0351: * @param name the name to bind; may not be empty
0352: * @exception NameNotFoundException if an intermediate context does not
0353: * exist
0354: * @exception NamingException if a naming exception is encountered
0355: */
0356: public void unbind(Name name) throws NamingException {
0357: dirContext.unbind(parseName(name));
0358: cacheUnload(name.toString());
0359: }
0360:
0361: /**
0362: * Unbinds the named object.
0363: *
0364: * @param name the name to bind; may not be empty
0365: * @exception NameNotFoundException if an intermediate context does not
0366: * exist
0367: * @exception NamingException if a naming exception is encountered
0368: */
0369: public void unbind(String name) throws NamingException {
0370: dirContext.unbind(parseName(name));
0371: cacheUnload(name);
0372: }
0373:
0374: /**
0375: * Binds a new name to the object bound to an old name, and unbinds the
0376: * old name. Both names are relative to this context. Any attributes
0377: * associated with the old name become associated with the new name.
0378: * Intermediate contexts of the old name are not changed.
0379: *
0380: * @param oldName the name of the existing binding; may not be empty
0381: * @param newName the name of the new binding; may not be empty
0382: * @exception NameAlreadyBoundException if newName is already bound
0383: * @exception NamingException if a naming exception is encountered
0384: */
0385: public void rename(Name oldName, Name newName)
0386: throws NamingException {
0387: dirContext.rename(parseName(oldName), parseName(newName));
0388: cacheUnload(oldName.toString());
0389: }
0390:
0391: /**
0392: * Binds a new name to the object bound to an old name, and unbinds the
0393: * old name.
0394: *
0395: * @param oldName the name of the existing binding; may not be empty
0396: * @param newName the name of the new binding; may not be empty
0397: * @exception NameAlreadyBoundException if newName is already bound
0398: * @exception NamingException if a naming exception is encountered
0399: */
0400: public void rename(String oldName, String newName)
0401: throws NamingException {
0402: dirContext.rename(parseName(oldName), parseName(newName));
0403: cacheUnload(oldName);
0404: }
0405:
0406: /**
0407: * Enumerates the names bound in the named context, along with the class
0408: * names of objects bound to them. The contents of any subcontexts are
0409: * not included.
0410: * <p>
0411: * If a binding is added to or removed from this context, its effect on
0412: * an enumeration previously returned is undefined.
0413: *
0414: * @param name the name of the context to list
0415: * @return an enumeration of the names and class names of the bindings in
0416: * this context. Each element of the enumeration is of type NameClassPair.
0417: * @exception NamingException if a naming exception is encountered
0418: */
0419: public NamingEnumeration list(Name name) throws NamingException {
0420: return dirContext.list(parseName(name));
0421: }
0422:
0423: /**
0424: * Enumerates the names bound in the named context, along with the class
0425: * names of objects bound to them.
0426: *
0427: * @param name the name of the context to list
0428: * @return an enumeration of the names and class names of the bindings in
0429: * this context. Each element of the enumeration is of type NameClassPair.
0430: * @exception NamingException if a naming exception is encountered
0431: */
0432: public NamingEnumeration list(String name) throws NamingException {
0433: return dirContext.list(parseName(name));
0434: }
0435:
0436: /**
0437: * Enumerates the names bound in the named context, along with the
0438: * objects bound to them. The contents of any subcontexts are not
0439: * included.
0440: * <p>
0441: * If a binding is added to or removed from this context, its effect on
0442: * an enumeration previously returned is undefined.
0443: *
0444: * @param name the name of the context to list
0445: * @return an enumeration of the bindings in this context.
0446: * Each element of the enumeration is of type Binding.
0447: * @exception NamingException if a naming exception is encountered
0448: */
0449: public NamingEnumeration listBindings(Name name)
0450: throws NamingException {
0451: return dirContext.listBindings(parseName(name));
0452: }
0453:
0454: /**
0455: * Enumerates the names bound in the named context, along with the
0456: * objects bound to them.
0457: *
0458: * @param name the name of the context to list
0459: * @return an enumeration of the bindings in this context.
0460: * Each element of the enumeration is of type Binding.
0461: * @exception NamingException if a naming exception is encountered
0462: */
0463: public NamingEnumeration listBindings(String name)
0464: throws NamingException {
0465: return dirContext.listBindings(parseName(name));
0466: }
0467:
0468: /**
0469: * Destroys the named context and removes it from the namespace. Any
0470: * attributes associated with the name are also removed. Intermediate
0471: * contexts are not destroyed.
0472: * <p>
0473: * This method is idempotent. It succeeds even if the terminal atomic
0474: * name is not bound in the target context, but throws
0475: * NameNotFoundException if any of the intermediate contexts do not exist.
0476: *
0477: * In a federated naming system, a context from one naming system may be
0478: * bound to a name in another. One can subsequently look up and perform
0479: * operations on the foreign context using a composite name. However, an
0480: * attempt destroy the context using this composite name will fail with
0481: * NotContextException, because the foreign context is not a "subcontext"
0482: * of the context in which it is bound. Instead, use unbind() to remove
0483: * the binding of the foreign context. Destroying the foreign context
0484: * requires that the destroySubcontext() be performed on a context from
0485: * the foreign context's "native" naming system.
0486: *
0487: * @param name the name of the context to be destroyed; may not be empty
0488: * @exception NameNotFoundException if an intermediate context does not
0489: * exist
0490: * @exception NotContextException if the name is bound but does not name
0491: * a context, or does not name a context of the appropriate type
0492: */
0493: public void destroySubcontext(Name name) throws NamingException {
0494: dirContext.destroySubcontext(parseName(name));
0495: cacheUnload(name.toString());
0496: }
0497:
0498: /**
0499: * Destroys the named context and removes it from the namespace.
0500: *
0501: * @param name the name of the context to be destroyed; may not be empty
0502: * @exception NameNotFoundException if an intermediate context does not
0503: * exist
0504: * @exception NotContextException if the name is bound but does not name
0505: * a context, or does not name a context of the appropriate type
0506: */
0507: public void destroySubcontext(String name) throws NamingException {
0508: dirContext.destroySubcontext(parseName(name));
0509: cacheUnload(name);
0510: }
0511:
0512: /**
0513: * Creates and binds a new context. Creates a new context with the given
0514: * name and binds it in the target context (that named by all but
0515: * terminal atomic component of the name). All intermediate contexts and
0516: * the target context must already exist.
0517: *
0518: * @param name the name of the context to create; may not be empty
0519: * @return the newly created context
0520: * @exception NameAlreadyBoundException if name is already bound
0521: * @exception InvalidAttributesException if creation of the subcontext
0522: * requires specification of mandatory attributes
0523: * @exception NamingException if a naming exception is encountered
0524: */
0525: public Context createSubcontext(Name name) throws NamingException {
0526: Context context = dirContext.createSubcontext(parseName(name));
0527: cacheUnload(name.toString());
0528: return context;
0529: }
0530:
0531: /**
0532: * Creates and binds a new context.
0533: *
0534: * @param name the name of the context to create; may not be empty
0535: * @return the newly created context
0536: * @exception NameAlreadyBoundException if name is already bound
0537: * @exception InvalidAttributesException if creation of the subcontext
0538: * requires specification of mandatory attributes
0539: * @exception NamingException if a naming exception is encountered
0540: */
0541: public Context createSubcontext(String name) throws NamingException {
0542: Context context = dirContext.createSubcontext(parseName(name));
0543: cacheUnload(name);
0544: return context;
0545: }
0546:
0547: /**
0548: * Retrieves the named object, following links except for the terminal
0549: * atomic component of the name. If the object bound to name is not a
0550: * link, returns the object itself.
0551: *
0552: * @param name the name of the object to look up
0553: * @return the object bound to name, not following the terminal link
0554: * (if any).
0555: * @exception NamingException if a naming exception is encountered
0556: */
0557: public Object lookupLink(Name name) throws NamingException {
0558: return dirContext.lookupLink(parseName(name));
0559: }
0560:
0561: /**
0562: * Retrieves the named object, following links except for the terminal
0563: * atomic component of the name.
0564: *
0565: * @param name the name of the object to look up
0566: * @return the object bound to name, not following the terminal link
0567: * (if any).
0568: * @exception NamingException if a naming exception is encountered
0569: */
0570: public Object lookupLink(String name) throws NamingException {
0571: return dirContext.lookupLink(parseName(name));
0572: }
0573:
0574: /**
0575: * Retrieves the parser associated with the named context. In a
0576: * federation of namespaces, different naming systems will parse names
0577: * differently. This method allows an application to get a parser for
0578: * parsing names into their atomic components using the naming convention
0579: * of a particular naming system. Within any single naming system,
0580: * NameParser objects returned by this method must be equal (using the
0581: * equals() test).
0582: *
0583: * @param name the name of the context from which to get the parser
0584: * @return a name parser that can parse compound names into their atomic
0585: * components
0586: * @exception NamingException if a naming exception is encountered
0587: */
0588: public NameParser getNameParser(Name name) throws NamingException {
0589: return dirContext.getNameParser(parseName(name));
0590: }
0591:
0592: /**
0593: * Retrieves the parser associated with the named context.
0594: *
0595: * @param name the name of the context from which to get the parser
0596: * @return a name parser that can parse compound names into their atomic
0597: * components
0598: * @exception NamingException if a naming exception is encountered
0599: */
0600: public NameParser getNameParser(String name) throws NamingException {
0601: return dirContext.getNameParser(parseName(name));
0602: }
0603:
0604: /**
0605: * Composes the name of this context with a name relative to this context.
0606: * <p>
0607: * Given a name (name) relative to this context, and the name (prefix)
0608: * of this context relative to one of its ancestors, this method returns
0609: * the composition of the two names using the syntax appropriate for the
0610: * naming system(s) involved. That is, if name names an object relative
0611: * to this context, the result is the name of the same object, but
0612: * relative to the ancestor context. None of the names may be null.
0613: *
0614: * @param name a name relative to this context
0615: * @param prefix the name of this context relative to one of its ancestors
0616: * @return the composition of prefix and name
0617: * @exception NamingException if a naming exception is encountered
0618: */
0619: public Name composeName(Name name, Name prefix)
0620: throws NamingException {
0621: prefix = (Name) prefix.clone();
0622: return prefix.addAll(name);
0623: }
0624:
0625: /**
0626: * Composes the name of this context with a name relative to this context.
0627: *
0628: * @param name a name relative to this context
0629: * @param prefix the name of this context relative to one of its ancestors
0630: * @return the composition of prefix and name
0631: * @exception NamingException if a naming exception is encountered
0632: */
0633: public String composeName(String name, String prefix)
0634: throws NamingException {
0635: return prefix + "/" + name;
0636: }
0637:
0638: /**
0639: * Adds a new environment property to the environment of this context. If
0640: * the property already exists, its value is overwritten.
0641: *
0642: * @param propName the name of the environment property to add; may not
0643: * be null
0644: * @param propVal the value of the property to add; may not be null
0645: * @exception NamingException if a naming exception is encountered
0646: */
0647: public Object addToEnvironment(String propName, Object propVal)
0648: throws NamingException {
0649: return dirContext.addToEnvironment(propName, propVal);
0650: }
0651:
0652: /**
0653: * Removes an environment property from the environment of this context.
0654: *
0655: * @param propName the name of the environment property to remove;
0656: * may not be null
0657: * @exception NamingException if a naming exception is encountered
0658: */
0659: public Object removeFromEnvironment(String propName)
0660: throws NamingException {
0661: return dirContext.removeFromEnvironment(propName);
0662: }
0663:
0664: /**
0665: * Retrieves the environment in effect for this context. See class
0666: * description for more details on environment properties.
0667: * The caller should not make any changes to the object returned: their
0668: * effect on the context is undefined. The environment of this context
0669: * may be changed using addToEnvironment() and removeFromEnvironment().
0670: *
0671: * @return the environment of this context; never null
0672: * @exception NamingException if a naming exception is encountered
0673: */
0674: public Hashtable getEnvironment() throws NamingException {
0675: return dirContext.getEnvironment();
0676: }
0677:
0678: /**
0679: * Closes this context. This method releases this context's resources
0680: * immediately, instead of waiting for them to be released automatically
0681: * by the garbage collector.
0682: * This method is idempotent: invoking it on a context that has already
0683: * been closed has no effect. Invoking any other method on a closed
0684: * context is not allowed, and results in undefined behaviour.
0685: *
0686: * @exception NamingException if a naming exception is encountered
0687: */
0688: public void close() throws NamingException {
0689: dirContext.close();
0690: }
0691:
0692: /**
0693: * Retrieves the full name of this context within its own namespace.
0694: * <p>
0695: * Many naming services have a notion of a "full name" for objects in
0696: * their respective namespaces. For example, an LDAP entry has a
0697: * distinguished name, and a DNS record has a fully qualified name. This
0698: * method allows the client application to retrieve this name. The string
0699: * returned by this method is not a JNDI composite name and should not be
0700: * passed directly to context methods. In naming systems for which the
0701: * notion of full name does not make sense,
0702: * OperationNotSupportedException is thrown.
0703: *
0704: * @return this context's name in its own namespace; never null
0705: * @exception OperationNotSupportedException if the naming system does
0706: * not have the notion of a full name
0707: * @exception NamingException if a naming exception is encountered
0708: */
0709: public String getNameInNamespace() throws NamingException {
0710: return dirContext.getNameInNamespace();
0711: }
0712:
0713: // ----------------------------------------------------- DirContext Methods
0714:
0715: /**
0716: * Retrieves all of the attributes associated with a named object.
0717: *
0718: * @return the set of attributes associated with name.
0719: * Returns an empty attribute set if name has no attributes; never null.
0720: * @param name the name of the object from which to retrieve attributes
0721: * @exception NamingException if a naming exception is encountered
0722: */
0723: public Attributes getAttributes(Name name) throws NamingException {
0724: CacheEntry entry = cacheLookup(name.toString());
0725: if (entry != null) {
0726: if (!entry.exists) {
0727: throw notFoundException;
0728: }
0729: return entry.attributes;
0730: }
0731: Attributes attributes = dirContext
0732: .getAttributes(parseName(name));
0733: if (!(attributes instanceof ResourceAttributes)) {
0734: attributes = new ResourceAttributes(attributes);
0735: }
0736: return attributes;
0737: }
0738:
0739: /**
0740: * Retrieves all of the attributes associated with a named object.
0741: *
0742: * @return the set of attributes associated with name
0743: * @param name the name of the object from which to retrieve attributes
0744: * @exception NamingException if a naming exception is encountered
0745: */
0746: public Attributes getAttributes(String name) throws NamingException {
0747: CacheEntry entry = cacheLookup(name);
0748: if (entry != null) {
0749: if (!entry.exists) {
0750: throw notFoundException;
0751: }
0752: return entry.attributes;
0753: }
0754: Attributes attributes = dirContext
0755: .getAttributes(parseName(name));
0756: if (!(attributes instanceof ResourceAttributes)) {
0757: attributes = new ResourceAttributes(attributes);
0758: }
0759: return attributes;
0760: }
0761:
0762: /**
0763: * Retrieves selected attributes associated with a named object.
0764: * See the class description regarding attribute models, attribute type
0765: * names, and operational attributes.
0766: *
0767: * @return the requested attributes; never null
0768: * @param name the name of the object from which to retrieve attributes
0769: * @param attrIds the identifiers of the attributes to retrieve. null
0770: * indicates that all attributes should be retrieved; an empty array
0771: * indicates that none should be retrieved
0772: * @exception NamingException if a naming exception is encountered
0773: */
0774: public Attributes getAttributes(Name name, String[] attrIds)
0775: throws NamingException {
0776: Attributes attributes = dirContext.getAttributes(
0777: parseName(name), attrIds);
0778: if (!(attributes instanceof ResourceAttributes)) {
0779: attributes = new ResourceAttributes(attributes);
0780: }
0781: return attributes;
0782: }
0783:
0784: /**
0785: * Retrieves selected attributes associated with a named object.
0786: *
0787: * @return the requested attributes; never null
0788: * @param name the name of the object from which to retrieve attributes
0789: * @param attrIds the identifiers of the attributes to retrieve. null
0790: * indicates that all attributes should be retrieved; an empty array
0791: * indicates that none should be retrieved
0792: * @exception NamingException if a naming exception is encountered
0793: */
0794: public Attributes getAttributes(String name, String[] attrIds)
0795: throws NamingException {
0796: Attributes attributes = dirContext.getAttributes(
0797: parseName(name), attrIds);
0798: if (!(attributes instanceof ResourceAttributes)) {
0799: attributes = new ResourceAttributes(attributes);
0800: }
0801: return attributes;
0802: }
0803:
0804: /**
0805: * Modifies the attributes associated with a named object. The order of
0806: * the modifications is not specified. Where possible, the modifications
0807: * are performed atomically.
0808: *
0809: * @param name the name of the object whose attributes will be updated
0810: * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
0811: * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
0812: * @param attrs the attributes to be used for the modification; may not
0813: * be null
0814: * @exception AttributeModificationException if the modification cannot be
0815: * completed successfully
0816: * @exception NamingException if a naming exception is encountered
0817: */
0818: public void modifyAttributes(Name name, int mod_op, Attributes attrs)
0819: throws NamingException {
0820: dirContext.modifyAttributes(parseName(name), mod_op, attrs);
0821: cacheUnload(name.toString());
0822: }
0823:
0824: /**
0825: * Modifies the attributes associated with a named object.
0826: *
0827: * @param name the name of the object whose attributes will be updated
0828: * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
0829: * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
0830: * @param attrs the attributes to be used for the modification; may not
0831: * be null
0832: * @exception AttributeModificationException if the modification cannot be
0833: * completed successfully
0834: * @exception NamingException if a naming exception is encountered
0835: */
0836: public void modifyAttributes(String name, int mod_op,
0837: Attributes attrs) throws NamingException {
0838: dirContext.modifyAttributes(parseName(name), mod_op, attrs);
0839: cacheUnload(name);
0840: }
0841:
0842: /**
0843: * Modifies the attributes associated with a named object using an an
0844: * ordered list of modifications. The modifications are performed in the
0845: * order specified. Each modification specifies a modification operation
0846: * code and an attribute on which to operate. Where possible, the
0847: * modifications are performed atomically.
0848: *
0849: * @param name the name of the object whose attributes will be updated
0850: * @param mods an ordered sequence of modifications to be performed; may
0851: * not be null
0852: * @exception AttributeModificationException if the modification cannot be
0853: * completed successfully
0854: * @exception NamingException if a naming exception is encountered
0855: */
0856: public void modifyAttributes(Name name, ModificationItem[] mods)
0857: throws NamingException {
0858: dirContext.modifyAttributes(parseName(name), mods);
0859: cacheUnload(name.toString());
0860: }
0861:
0862: /**
0863: * Modifies the attributes associated with a named object using an an
0864: * ordered list of modifications.
0865: *
0866: * @param name the name of the object whose attributes will be updated
0867: * @param mods an ordered sequence of modifications to be performed; may
0868: * not be null
0869: * @exception AttributeModificationException if the modification cannot be
0870: * completed successfully
0871: * @exception NamingException if a naming exception is encountered
0872: */
0873: public void modifyAttributes(String name, ModificationItem[] mods)
0874: throws NamingException {
0875: dirContext.modifyAttributes(parseName(name), mods);
0876: cacheUnload(name);
0877: }
0878:
0879: /**
0880: * Binds a name to an object, along with associated attributes. If attrs
0881: * is null, the resulting binding will have the attributes associated
0882: * with obj if obj is a DirContext, and no attributes otherwise. If attrs
0883: * is non-null, the resulting binding will have attrs as its attributes;
0884: * any attributes associated with obj are ignored.
0885: *
0886: * @param name the name to bind; may not be empty
0887: * @param obj the object to bind; possibly null
0888: * @param attrs the attributes to associate with the binding
0889: * @exception NameAlreadyBoundException if name is already bound
0890: * @exception InvalidAttributesException if some "mandatory" attributes
0891: * of the binding are not supplied
0892: * @exception NamingException if a naming exception is encountered
0893: */
0894: public void bind(Name name, Object obj, Attributes attrs)
0895: throws NamingException {
0896: dirContext.bind(parseName(name), obj, attrs);
0897: cacheUnload(name.toString());
0898: }
0899:
0900: /**
0901: * Binds a name to an object, along with associated attributes.
0902: *
0903: * @param name the name to bind; may not be empty
0904: * @param obj the object to bind; possibly null
0905: * @param attrs the attributes to associate with the binding
0906: * @exception NameAlreadyBoundException if name is already bound
0907: * @exception InvalidAttributesException if some "mandatory" attributes
0908: * of the binding are not supplied
0909: * @exception NamingException if a naming exception is encountered
0910: */
0911: public void bind(String name, Object obj, Attributes attrs)
0912: throws NamingException {
0913: dirContext.bind(parseName(name), obj, attrs);
0914: cacheUnload(name);
0915: }
0916:
0917: /**
0918: * Binds a name to an object, along with associated attributes,
0919: * overwriting any existing binding. If attrs is null and obj is a
0920: * DirContext, the attributes from obj are used. If attrs is null and obj
0921: * is not a DirContext, any existing attributes associated with the object
0922: * already bound in the directory remain unchanged. If attrs is non-null,
0923: * any existing attributes associated with the object already bound in
0924: * the directory are removed and attrs is associated with the named
0925: * object. If obj is a DirContext and attrs is non-null, the attributes
0926: * of obj are ignored.
0927: *
0928: * @param name the name to bind; may not be empty
0929: * @param obj the object to bind; possibly null
0930: * @param attrs the attributes to associate with the binding
0931: * @exception InvalidAttributesException if some "mandatory" attributes
0932: * of the binding are not supplied
0933: * @exception NamingException if a naming exception is encountered
0934: */
0935: public void rebind(Name name, Object obj, Attributes attrs)
0936: throws NamingException {
0937: dirContext.rebind(parseName(name), obj, attrs);
0938: cacheUnload(name.toString());
0939: }
0940:
0941: /**
0942: * Binds a name to an object, along with associated attributes,
0943: * overwriting any existing binding.
0944: *
0945: * @param name the name to bind; may not be empty
0946: * @param obj the object to bind; possibly null
0947: * @param attrs the attributes to associate with the binding
0948: * @exception InvalidAttributesException if some "mandatory" attributes
0949: * of the binding are not supplied
0950: * @exception NamingException if a naming exception is encountered
0951: */
0952: public void rebind(String name, Object obj, Attributes attrs)
0953: throws NamingException {
0954: dirContext.rebind(parseName(name), obj, attrs);
0955: cacheUnload(name);
0956: }
0957:
0958: /**
0959: * Creates and binds a new context, along with associated attributes.
0960: * This method creates a new subcontext with the given name, binds it in
0961: * the target context (that named by all but terminal atomic component of
0962: * the name), and associates the supplied attributes with the newly
0963: * created object. All intermediate and target contexts must already
0964: * exist. If attrs is null, this method is equivalent to
0965: * Context.createSubcontext().
0966: *
0967: * @param name the name of the context to create; may not be empty
0968: * @param attrs the attributes to associate with the newly created context
0969: * @return the newly created context
0970: * @exception NameAlreadyBoundException if the name is already bound
0971: * @exception InvalidAttributesException if attrs does not contain all
0972: * the mandatory attributes required for creation
0973: * @exception NamingException if a naming exception is encountered
0974: */
0975: public DirContext createSubcontext(Name name, Attributes attrs)
0976: throws NamingException {
0977: DirContext context = dirContext.createSubcontext(
0978: parseName(name), attrs);
0979: cacheUnload(name.toString());
0980: return context;
0981: }
0982:
0983: /**
0984: * Creates and binds a new context, along with associated attributes.
0985: *
0986: * @param name the name of the context to create; may not be empty
0987: * @param attrs the attributes to associate with the newly created context
0988: * @return the newly created context
0989: * @exception NameAlreadyBoundException if the name is already bound
0990: * @exception InvalidAttributesException if attrs does not contain all
0991: * the mandatory attributes required for creation
0992: * @exception NamingException if a naming exception is encountered
0993: */
0994: public DirContext createSubcontext(String name, Attributes attrs)
0995: throws NamingException {
0996: DirContext context = dirContext.createSubcontext(
0997: parseName(name), attrs);
0998: cacheUnload(name);
0999: return context;
1000: }
1001:
1002: /**
1003: * Retrieves the schema associated with the named object. The schema
1004: * describes rules regarding the structure of the namespace and the
1005: * attributes stored within it. The schema specifies what types of
1006: * objects can be added to the directory and where they can be added;
1007: * what mandatory and optional attributes an object can have. The range
1008: * of support for schemas is directory-specific.
1009: *
1010: * @param name the name of the object whose schema is to be retrieved
1011: * @return the schema associated with the context; never null
1012: * @exception OperationNotSupportedException if schema not supported
1013: * @exception NamingException if a naming exception is encountered
1014: */
1015: public DirContext getSchema(Name name) throws NamingException {
1016: return dirContext.getSchema(parseName(name));
1017: }
1018:
1019: /**
1020: * Retrieves the schema associated with the named object.
1021: *
1022: * @param name the name of the object whose schema is to be retrieved
1023: * @return the schema associated with the context; never null
1024: * @exception OperationNotSupportedException if schema not supported
1025: * @exception NamingException if a naming exception is encountered
1026: */
1027: public DirContext getSchema(String name) throws NamingException {
1028: return dirContext.getSchema(parseName(name));
1029: }
1030:
1031: /**
1032: * Retrieves a context containing the schema objects of the named
1033: * object's class definitions.
1034: *
1035: * @param name the name of the object whose object class definition is to
1036: * be retrieved
1037: * @return the DirContext containing the named object's class
1038: * definitions; never null
1039: * @exception OperationNotSupportedException if schema not supported
1040: * @exception NamingException if a naming exception is encountered
1041: */
1042: public DirContext getSchemaClassDefinition(Name name)
1043: throws NamingException {
1044: return dirContext.getSchemaClassDefinition(parseName(name));
1045: }
1046:
1047: /**
1048: * Retrieves a context containing the schema objects of the named
1049: * object's class definitions.
1050: *
1051: * @param name the name of the object whose object class definition is to
1052: * be retrieved
1053: * @return the DirContext containing the named object's class
1054: * definitions; never null
1055: * @exception OperationNotSupportedException if schema not supported
1056: * @exception NamingException if a naming exception is encountered
1057: */
1058: public DirContext getSchemaClassDefinition(String name)
1059: throws NamingException {
1060: return dirContext.getSchemaClassDefinition(parseName(name));
1061: }
1062:
1063: /**
1064: * Searches in a single context for objects that contain a specified set
1065: * of attributes, and retrieves selected attributes. The search is
1066: * performed using the default SearchControls settings.
1067: *
1068: * @param name the name of the context to search
1069: * @param matchingAttributes the attributes to search for. If empty or
1070: * null, all objects in the target context are returned.
1071: * @param attributesToReturn the attributes to return. null indicates
1072: * that all attributes are to be returned; an empty array indicates that
1073: * none are to be returned.
1074: * @return a non-null enumeration of SearchResult objects. Each
1075: * SearchResult contains the attributes identified by attributesToReturn
1076: * and the name of the corresponding object, named relative to the
1077: * context named by name.
1078: * @exception NamingException if a naming exception is encountered
1079: */
1080: public NamingEnumeration search(Name name,
1081: Attributes matchingAttributes, String[] attributesToReturn)
1082: throws NamingException {
1083: return dirContext.search(parseName(name), matchingAttributes,
1084: attributesToReturn);
1085: }
1086:
1087: /**
1088: * Searches in a single context for objects that contain a specified set
1089: * of attributes, and retrieves selected attributes.
1090: *
1091: * @param name the name of the context to search
1092: * @param matchingAttributes the attributes to search for. If empty or
1093: * null, all objects in the target context are returned.
1094: * @param attributesToReturn the attributes to return. null indicates
1095: * that all attributes are to be returned; an empty array indicates that
1096: * none are to be returned.
1097: * @return a non-null enumeration of SearchResult objects. Each
1098: * SearchResult contains the attributes identified by attributesToReturn
1099: * and the name of the corresponding object, named relative to the
1100: * context named by name.
1101: * @exception NamingException if a naming exception is encountered
1102: */
1103: public NamingEnumeration search(String name,
1104: Attributes matchingAttributes, String[] attributesToReturn)
1105: throws NamingException {
1106: return dirContext.search(parseName(name), matchingAttributes,
1107: attributesToReturn);
1108: }
1109:
1110: /**
1111: * Searches in a single context for objects that contain a specified set
1112: * of attributes. This method returns all the attributes of such objects.
1113: * It is equivalent to supplying null as the atributesToReturn parameter
1114: * to the method search(Name, Attributes, String[]).
1115: *
1116: * @param name the name of the context to search
1117: * @param matchingAttributes the attributes to search for. If empty or
1118: * null, all objects in the target context are returned.
1119: * @return a non-null enumeration of SearchResult objects. Each
1120: * SearchResult contains the attributes identified by attributesToReturn
1121: * and the name of the corresponding object, named relative to the
1122: * context named by name.
1123: * @exception NamingException if a naming exception is encountered
1124: */
1125: public NamingEnumeration search(Name name,
1126: Attributes matchingAttributes) throws NamingException {
1127: return dirContext.search(parseName(name), matchingAttributes);
1128: }
1129:
1130: /**
1131: * Searches in a single context for objects that contain a specified set
1132: * of attributes.
1133: *
1134: * @param name the name of the context to search
1135: * @param matchingAttributes the attributes to search for. If empty or
1136: * null, all objects in the target context are returned.
1137: * @return a non-null enumeration of SearchResult objects. Each
1138: * SearchResult contains the attributes identified by attributesToReturn
1139: * and the name of the corresponding object, named relative to the
1140: * context named by name.
1141: * @exception NamingException if a naming exception is encountered
1142: */
1143: public NamingEnumeration search(String name,
1144: Attributes matchingAttributes) throws NamingException {
1145: return dirContext.search(parseName(name), matchingAttributes);
1146: }
1147:
1148: /**
1149: * Searches in the named context or object for entries that satisfy the
1150: * given search filter. Performs the search as specified by the search
1151: * controls.
1152: *
1153: * @param name the name of the context or object to search
1154: * @param filter the filter expression to use for the search; may not be
1155: * null
1156: * @param cons the search controls that control the search. If null,
1157: * the default search controls are used (equivalent to
1158: * (new SearchControls())).
1159: * @return an enumeration of SearchResults of the objects that satisfy
1160: * the filter; never null
1161: * @exception InvalidSearchFilterException if the search filter specified
1162: * is not supported or understood by the underlying directory
1163: * @exception InvalidSearchControlsException if the search controls
1164: * contain invalid settings
1165: * @exception NamingException if a naming exception is encountered
1166: */
1167: public NamingEnumeration search(Name name, String filter,
1168: SearchControls cons) throws NamingException {
1169: return dirContext.search(parseName(name), filter, cons);
1170: }
1171:
1172: /**
1173: * Searches in the named context or object for entries that satisfy the
1174: * given search filter. Performs the search as specified by the search
1175: * controls.
1176: *
1177: * @param name the name of the context or object to search
1178: * @param filter the filter expression to use for the search; may not be
1179: * null
1180: * @param cons the search controls that control the search. If null,
1181: * the default search controls are used (equivalent to
1182: * (new SearchControls())).
1183: * @return an enumeration of SearchResults of the objects that satisfy
1184: * the filter; never null
1185: * @exception InvalidSearchFilterException if the search filter
1186: * specified is not supported or understood by the underlying directory
1187: * @exception InvalidSearchControlsException if the search controls
1188: * contain invalid settings
1189: * @exception NamingException if a naming exception is encountered
1190: */
1191: public NamingEnumeration search(String name, String filter,
1192: SearchControls cons) throws NamingException {
1193: return dirContext.search(parseName(name), filter, cons);
1194: }
1195:
1196: /**
1197: * Searches in the named context or object for entries that satisfy the
1198: * given search filter. Performs the search as specified by the search
1199: * controls.
1200: *
1201: * @param name the name of the context or object to search
1202: * @param filterExpr the filter expression to use for the search.
1203: * The expression may contain variables of the form "{i}" where i is a
1204: * nonnegative integer. May not be null.
1205: * @param filterArgs the array of arguments to substitute for the
1206: * variables in filterExpr. The value of filterArgs[i] will replace each
1207: * occurrence of "{i}". If null, equivalent to an empty array.
1208: * @param cons the search controls that control the search. If null, the
1209: * default search controls are used (equivalent to (new SearchControls())).
1210: * @return an enumeration of SearchResults of the objects that satisy the
1211: * filter; never null
1212: * @exception ArrayIndexOutOfBoundsException if filterExpr contains {i}
1213: * expressions where i is outside the bounds of the array filterArgs
1214: * @exception InvalidSearchControlsException if cons contains invalid
1215: * settings
1216: * @exception InvalidSearchFilterException if filterExpr with filterArgs
1217: * represents an invalid search filter
1218: * @exception NamingException if a naming exception is encountered
1219: */
1220: public NamingEnumeration search(Name name, String filterExpr,
1221: Object[] filterArgs, SearchControls cons)
1222: throws NamingException {
1223: return dirContext.search(parseName(name), filterExpr,
1224: filterArgs, cons);
1225: }
1226:
1227: /**
1228: * Searches in the named context or object for entries that satisfy the
1229: * given search filter. Performs the search as specified by the search
1230: * controls.
1231: *
1232: * @param name the name of the context or object to search
1233: * @param filterExpr the filter expression to use for the search.
1234: * The expression may contain variables of the form "{i}" where i is a
1235: * nonnegative integer. May not be null.
1236: * @param filterArgs the array of arguments to substitute for the
1237: * variables in filterExpr. The value of filterArgs[i] will replace each
1238: * occurrence of "{i}". If null, equivalent to an empty array.
1239: * @param cons the search controls that control the search. If null, the
1240: * default search controls are used (equivalent to (new SearchControls())).
1241: * @return an enumeration of SearchResults of the objects that satisy the
1242: * filter; never null
1243: * @exception ArrayIndexOutOfBoundsException if filterExpr contains {i}
1244: * expressions where i is outside the bounds of the array filterArgs
1245: * @exception InvalidSearchControlsException if cons contains invalid
1246: * settings
1247: * @exception InvalidSearchFilterException if filterExpr with filterArgs
1248: * represents an invalid search filter
1249: * @exception NamingException if a naming exception is encountered
1250: */
1251: public NamingEnumeration search(String name, String filterExpr,
1252: Object[] filterArgs, SearchControls cons)
1253: throws NamingException {
1254: return dirContext.search(parseName(name), filterExpr,
1255: filterArgs, cons);
1256: }
1257:
1258: // --------------------------------------------------------- Public Methods
1259:
1260: /**
1261: * Retrieves the named object as a cache entry, without any exception.
1262: *
1263: * @param name the name of the object to look up
1264: * @return the cache entry bound to name
1265: */
1266: public CacheEntry lookupCache(String name) {
1267: CacheEntry entry = cacheLookup(name);
1268: if (entry == null) {
1269: entry = new CacheEntry();
1270: entry.name = name;
1271: try {
1272: Object object = dirContext.lookup(parseName(name));
1273: if (object instanceof InputStream) {
1274: entry.resource = new Resource((InputStream) object);
1275: } else if (object instanceof DirContext) {
1276: entry.context = (DirContext) object;
1277: } else if (object instanceof Resource) {
1278: entry.resource = (Resource) object;
1279: } else {
1280: entry.resource = new Resource(
1281: new ByteArrayInputStream(object.toString()
1282: .getBytes()));
1283: }
1284: Attributes attributes = dirContext
1285: .getAttributes(parseName(name));
1286: if (!(attributes instanceof ResourceAttributes)) {
1287: attributes = new ResourceAttributes(attributes);
1288: }
1289: entry.attributes = (ResourceAttributes) attributes;
1290: } catch (NamingException e) {
1291: entry.exists = false;
1292: }
1293: }
1294: return entry;
1295: }
1296:
1297: // ------------------------------------------------------ Protected Methods
1298:
1299: /**
1300: * Parses a name.
1301: *
1302: * @return the parsed name
1303: */
1304: protected String parseName(String name) throws NamingException {
1305: return name;
1306: }
1307:
1308: /**
1309: * Parses a name.
1310: *
1311: * @return the parsed name
1312: */
1313: protected Name parseName(Name name) throws NamingException {
1314: return name;
1315: }
1316:
1317: /**
1318: * Lookup in cache.
1319: */
1320: protected CacheEntry cacheLookup(String name) {
1321: if (cache == null)
1322: return (null);
1323: if (name == null)
1324: name = "";
1325: for (int i = 0; i < nonCacheable.length; i++) {
1326: if (name.startsWith(nonCacheable[i])) {
1327: return (null);
1328: }
1329: }
1330: CacheEntry cacheEntry = cache.lookup(name);
1331: if (cacheEntry == null) {
1332: cacheEntry = new CacheEntry();
1333: cacheEntry.name = name;
1334: // Load entry
1335: cacheLoad(cacheEntry);
1336: } else {
1337: if (!validate(cacheEntry)) {
1338: if (!revalidate(cacheEntry)) {
1339: cacheUnload(cacheEntry.name);
1340: return (null);
1341: } else {
1342: cacheEntry.timestamp = System.currentTimeMillis()
1343: + cacheTTL;
1344: }
1345: }
1346: cacheEntry.accessCount++;
1347: }
1348: return (cacheEntry);
1349: }
1350:
1351: /**
1352: * Validate entry.
1353: */
1354: protected boolean validate(CacheEntry entry) {
1355: if (((!entry.exists) || (entry.context != null) || ((entry.resource != null) && (entry.resource
1356: .getContent() != null)))
1357: && (System.currentTimeMillis() < entry.timestamp)) {
1358: return true;
1359: }
1360: return false;
1361: }
1362:
1363: /**
1364: * Revalidate entry.
1365: */
1366: protected boolean revalidate(CacheEntry entry) {
1367: // Get the attributes at the given path, and check the last
1368: // modification date
1369: if (!entry.exists)
1370: return false;
1371: if (entry.attributes == null)
1372: return false;
1373: long lastModified = entry.attributes.getLastModified();
1374: long contentLength = entry.attributes.getContentLength();
1375: if (lastModified <= 0)
1376: return false;
1377: try {
1378: Attributes tempAttributes = dirContext
1379: .getAttributes(entry.name);
1380: ResourceAttributes attributes = null;
1381: if (!(tempAttributes instanceof ResourceAttributes)) {
1382: attributes = new ResourceAttributes(tempAttributes);
1383: } else {
1384: attributes = (ResourceAttributes) tempAttributes;
1385: }
1386: long lastModified2 = attributes.getLastModified();
1387: long contentLength2 = attributes.getContentLength();
1388: return (lastModified == lastModified2)
1389: && (contentLength == contentLength2);
1390: } catch (NamingException e) {
1391: return false;
1392: }
1393: }
1394:
1395: /**
1396: * Load entry into cache.
1397: */
1398: protected void cacheLoad(CacheEntry entry) {
1399:
1400: String name = entry.name;
1401:
1402: // Retrieve missing info
1403: boolean exists = true;
1404:
1405: // Retrieving attributes
1406: if (entry.attributes == null) {
1407: try {
1408: Attributes attributes = dirContext
1409: .getAttributes(entry.name);
1410: if (!(attributes instanceof ResourceAttributes)) {
1411: entry.attributes = new ResourceAttributes(
1412: attributes);
1413: } else {
1414: entry.attributes = (ResourceAttributes) attributes;
1415: }
1416: } catch (NamingException e) {
1417: exists = false;
1418: }
1419: }
1420:
1421: // Retriving object
1422: if ((exists) && (entry.resource == null)
1423: && (entry.context == null)) {
1424: try {
1425: Object object = dirContext.lookup(name);
1426: if (object instanceof InputStream) {
1427: entry.resource = new Resource((InputStream) object);
1428: } else if (object instanceof DirContext) {
1429: entry.context = (DirContext) object;
1430: } else if (object instanceof Resource) {
1431: entry.resource = (Resource) object;
1432: } else {
1433: entry.resource = new Resource(
1434: new ByteArrayInputStream(object.toString()
1435: .getBytes()));
1436: }
1437: } catch (NamingException e) {
1438: exists = false;
1439: }
1440: }
1441:
1442: // Load object content
1443: if ((exists)
1444: && (entry.resource != null)
1445: && (entry.resource.getContent() == null)
1446: && (entry.attributes.getContentLength() >= 0)
1447: && (entry.attributes.getContentLength() < (cacheObjectMaxSize * 1024))) {
1448: int length = (int) entry.attributes.getContentLength();
1449: // The entry size is 1 + the resource size in KB, if it will be
1450: // cached
1451: entry.size += (entry.attributes.getContentLength() / 1024);
1452: InputStream is = null;
1453: try {
1454: is = entry.resource.streamContent();
1455: int pos = 0;
1456: byte[] b = new byte[length];
1457: while (pos < length) {
1458: int n = is.read(b, pos, length - pos);
1459: if (n < 0)
1460: break;
1461: pos = pos + n;
1462: }
1463: entry.resource.setContent(b);
1464: } catch (IOException e) {
1465: ; // Ignore
1466: } finally {
1467: try {
1468: if (is != null)
1469: is.close();
1470: } catch (IOException e) {
1471: ; // Ignore
1472: }
1473: }
1474: }
1475:
1476: // Set existence flag
1477: entry.exists = exists;
1478:
1479: // Set timestamp
1480: entry.timestamp = System.currentTimeMillis() + cacheTTL;
1481:
1482: // Add new entry to cache
1483: synchronized (cache) {
1484: // Check cache size, and remove elements if too big
1485: if ((cache.lookup(name) == null)
1486: && cache.allocate(entry.size)) {
1487: cache.load(entry);
1488: }
1489: }
1490:
1491: }
1492:
1493: /**
1494: * Remove entry from cache.
1495: */
1496: protected boolean cacheUnload(String name) {
1497: if (cache == null)
1498: return false;
1499: synchronized (cache) {
1500: return cache.unload(name);
1501: }
1502: }
1503:
1504: }
|