/** * Destroys the named context and removes it from the namespace. Any attributes associated with * the name are also removed. Intermediate contexts are not destroyed. * * <p>This method is idempotent. It succeeds even if the terminal atomic name is not bound in the * target context, but throws NameNotFoundException if any of the intermediate contexts do not * exist. * * <p>In a federated naming system, a context from one naming system may be bound to a name in * another. One can subsequently look up and perform operations on the foreign context using a * composite name. However, an attempt destroy the context using this composite name will fail * with NotContextException, because the foreign context is not a "subcontext" of the context in * which it is bound. Instead, use unbind() to remove the binding of the foreign context. * Destroying the foreign context requires that the destroySubcontext() be performed on a context * from the foreign context's "native" naming system. * * @param name the name of the context to be destroyed; may not be empty * @exception NameNotFoundException if an intermediate context does not exist * @exception NotContextException if the name is bound but does not name a context, or does not * name a context of the appropriate type */ @Override public void destroySubcontext(Name name) throws NamingException { if (!checkWritable()) { return; } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) throw new NamingException(sm.getString("namingContext.invalidName")); NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).destroySubcontext(name.getSuffix(1)); } else { throw new NamingException(sm.getString("namingContext.contextExpected")); } } else { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).close(); bindings.remove(name.get(0)); } else { throw new NotContextException(sm.getString("namingContext.contextExpected")); } } }
/** * Retrieves the named object. * * @param name the name of the object to look up * @param resolveLinks If true, the links will be resolved * @return the object bound to name * @exception NamingException if a naming exception is encountered */ protected Object lookup(Name name, boolean resolveLinks) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) { // If name is empty, a newly allocated naming context is returned return new NamingContext(env, this.name, bindings); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { // If the size of the name is greater that 1, then we go through a // number of subcontexts. if (entry.type != NamingEntry.CONTEXT) { throw new NamingException(sm.getString("namingContext.contextExpected")); } return ((Context) entry.value).lookup(name.getSuffix(1)); } else { if ((resolveLinks) && (entry.type == NamingEntry.LINK_REF)) { String link = ((LinkRef) entry.value).getLinkName(); if (link.startsWith(".")) { // Link relative to this context return lookup(link.substring(1)); } else { return (new InitialContext(env)).lookup(link); } } else if (entry.type == NamingEntry.REFERENCE) { try { // TODO ÐèѧϰNamingManager Object obj = NamingManager.getObjectInstance(entry.value, name, this, env); if (entry.value instanceof ResourceRef) { boolean singleton = Boolean.parseBoolean( (String) ((ResourceRef) entry.value).get("singleton").getContent()); if (singleton) { entry.type = NamingEntry.ENTRY; entry.value = obj; } } return obj; } catch (NamingException e) { throw e; } catch (Exception e) { log.warn(sm.getString("namingContext.failResolvingReference"), e); throw new NamingException(e.getMessage()); } } else { return entry.value; } } }
/** * Binds a name to an object. All intermediate contexts and the target context (that named by all * but terminal atomic component of the name) must already exist. * * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @param rebind if true, then perform a rebind (ie, overwrite) * @exception NameAlreadyBoundException if name is already bound * @exception javax.naming.directory.InvalidAttributesException if object did not supply all * mandatory attributes * @exception NamingException if a naming exception is encountered */ protected void bind(Name name, Object obj, boolean rebind) throws NamingException { if (!checkWritable()) { return; } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) throw new NamingException(sm.getString("namingContext.invalidName")); NamingEntry entry = bindings.get(name.get(0)); if (name.size() > 1) { if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type == NamingEntry.CONTEXT) { if (rebind) { ((Context) entry.value).rebind(name.getSuffix(1), obj); } else { ((Context) entry.value).bind(name.getSuffix(1), obj); } } else { throw new NamingException(sm.getString("namingContext.contextExpected")); } } else { if ((!rebind) && (entry != null)) { throw new NameAlreadyBoundException( sm.getString("namingContext.alreadyBound", name.get(0))); } else { // Getting the type of the object and wrapping it within a new // NamingEntry Object toBind = NamingManager.getStateToBind(obj, name, this, env); if (toBind instanceof Context) { entry = new NamingEntry(name.get(0), toBind, NamingEntry.CONTEXT); } else if (toBind instanceof LinkRef) { entry = new NamingEntry(name.get(0), toBind, NamingEntry.LINK_REF); } else if (toBind instanceof Reference) { entry = new NamingEntry(name.get(0), toBind, NamingEntry.REFERENCE); } else if (toBind instanceof Referenceable) { toBind = ((Referenceable) toBind).getReference(); entry = new NamingEntry(name.get(0), toBind, NamingEntry.REFERENCE); } else { entry = new NamingEntry(name.get(0), toBind, NamingEntry.ENTRY); } bindings.put(name.get(0), entry); } } }
public Message readMessage(int offset) { Message r = new Message(); int t = readShort(offset + 8); r.end = (t == 0) ? null : strings.get(t); t = readShort(offset + 6); r.start = (t == 0) ? null : strings.get(t); r.brief = strings.get(readShort(offset + 12)); r.full = strings.get(readShort(offset + 14)); return r; }
public String ld() { try { return strings.get(readShort(attributesEnd + 0xc) + id().length() + 1); } catch (Exception e) { return "hw1"; } }
private String[] readAttributeList(int offset) { int pos = offset + attributesStart; int cnt = readShort(pos); String[] tab = new String[cnt]; int p = pos + 2; for (int i = 0; i < cnt; i++, p += 2) tab[i] = strings.get(readShort(p)); return tab; }
/** Throws a naming exception is Context is not writable. */ protected boolean checkWritable() throws NamingException { if (isWritable()) { return true; } else { if (exceptionOnFailedWrite) { throw new javax.naming.OperationNotSupportedException( sm.getString("namingContext.readOnly")); } } return false; }
/** * Enumerates the names bound in the named context, along with the objects bound to them. The * contents of any subcontexts are not included. * * <p>If a binding is added to or removed from this context, its effect on an enumeration * previously returned is undefined. * * @param name the name of the context to list * @return an enumeration of the bindings in this context. Each element of the enumeration is of * type Binding. * @exception NamingException if a naming exception is encountered */ @Override public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) { return new NamingContextBindingsEnumeration(bindings.values().iterator(), this); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type != NamingEntry.CONTEXT) { throw new NamingException(sm.getString("namingContext.contextExpected")); } return ((Context) entry.value).listBindings(name.getSuffix(1)); }
private void readStations() { stations = new Station[(attributesStart - stationsStart) / StationSize]; for (int i = 0, pos = stationsStart; pos < attributesStart; pos += StationSize, i++) { stations[i] = new Station(); stations[i].name = strings.get(readShort(pos)); stations[i].id = readLong(pos + 2); stations[i].x = readLong(pos + 6); stations[i].y = readLong(pos + 10); } }
private Station readHeaderStation(int offset) { int nameLoc = readShort(offset); if (nameLoc == 0) return null; Station ret = new Station(); ret.name = strings.get(nameLoc); ret.x = readLong(offset + 6); ret.y = readLong(offset + 10); return ret; }
Train readTrain(int pos) { Train r = new Train(); r.offset = pos; r.deptime = new PLNTimestamp(readShort(pos)); r.depstation = stations[readShort(pos + 2)]; r.arrtime = new PLNTimestamp(readShort(pos + 4)); r.arrstation = stations[readShort(pos + 6)]; r.number = strings.get(readShort(pos + 10)); r.attributesOffset = readShort(pos + 18); return r; }
/** * Retrieves the parser associated with the named context. In a federation of namespaces, * different naming systems will parse names differently. This method allows an application to get * a parser for parsing names into their atomic components using the naming convention of a * particular naming system. Within any single naming system, NameParser objects returned by this * method must be equal (using the equals() test). * * @param name the name of the context from which to get the parser * @return a name parser that can parse compound names into their atomic components * @exception NamingException if a naming exception is encountered */ @Override public NameParser getNameParser(Name name) throws NamingException { while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) return nameParser; if (name.size() > 1) { Object obj = bindings.get(name.get(0)); if (obj instanceof Context) { return ((Context) obj).getNameParser(name.getSuffix(1)); } else { throw new NotContextException(sm.getString("namingContext.contextExpected")); } } return nameParser; }
private TrainChange readTrainChanges(int offset) { int rd = readShort(offset); int ra = readShort(offset + 2); int rdp = readShort(offset + 4); int rap = readShort(offset + 6); if (ra == 0xffff && rd == 0xffff && rdp == 0 && rap == 0) return null; delayInfo = true; TrainChange tc = new TrainChange(); tc.realdeptime = (rd == 0xffff) ? null : new PLNTimestamp(rd); tc.realarrtime = (ra == 0xffff) ? null : new PLNTimestamp(ra); tc.realdepplatform = (rdp == 0) ? null : strings.get(rdp); tc.realarrplatform = (rap == 0) ? null : strings.get(rap); return tc; }
/** * Retrieves the full name of this context within its own namespace. * * <p>Many naming services have a notion of a "full name" for objects in their respective * namespaces. For example, an LDAP entry has a distinguished name, and a DNS record has a fully * qualified name. This method allows the client application to retrieve this name. The string * returned by this method is not a JNDI composite name and should not be passed directly to * context methods. In naming systems for which the notion of full name does not make sense, * OperationNotSupportedException is thrown. * * @return this context's name in its own namespace; never null * @exception OperationNotSupportedException if the naming system does not have the notion of a * full name * @exception NamingException if a naming exception is encountered */ @Override public String getNameInNamespace() throws NamingException { throw new OperationNotSupportedException(sm.getString("namingContext.noAbsoluteName")); // FIXME ? }
/** * Catalina JNDI Context implementation. * * @author Remy Maucherat * @version $Id: NamingContext.java 1298123 2012-03-07 21:13:08Z markt $ */ public class NamingContext implements Context { // -------------------------------------------------------------- Constants /** Name parser for this context. */ protected static final NameParser nameParser = new NameParserImpl(); private static final org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(NamingContext.class); // ----------------------------------------------------------- Constructors /** Builds a naming context using the given environment. */ public NamingContext(Hashtable<String, Object> env, String name) throws NamingException { this.bindings = new HashMap<String, NamingEntry>(); this.env = new Hashtable<String, Object>(); // FIXME ? Could be put in the environment ? this.name = name; // Populating the environment hashtable if (env != null) { Enumeration<String> envEntries = env.keys(); while (envEntries.hasMoreElements()) { String entryName = envEntries.nextElement(); addToEnvironment(entryName, env.get(entryName)); } } } /** Builds a naming context using the given environment. */ public NamingContext( Hashtable<String, Object> env, String name, HashMap<String, NamingEntry> bindings) throws NamingException { this(env, name); this.bindings = bindings; } // ----------------------------------------------------- Instance Variables /** Environment. */ protected Hashtable<String, Object> env; /** The string manager for this package. */ protected static final StringManager sm = StringManager.getManager(Constants.Package); /** Bindings in this Context. */ protected HashMap<String, NamingEntry> bindings; /** Name of the associated Catalina Context. */ protected String name; /** * Determines if an attempt to write to a read-only context results in an exception or if the * request is ignored. */ private boolean exceptionOnFailedWrite = true; public boolean getExceptionOnFailedWrite() { return exceptionOnFailedWrite; } public void setExceptionOnFailedWrite(boolean exceptionOnFailedWrite) { this.exceptionOnFailedWrite = exceptionOnFailedWrite; } // -------------------------------------------------------- Context Methods /** * Retrieves the named object. If name is empty, returns a new instance of this context (which * represents the same naming context as this context, but its environment may be modified * independently and it may be accessed concurrently). * * @param name the name of the object to look up * @return the object bound to name * @exception NamingException if a naming exception is encountered */ @Override public Object lookup(Name name) throws NamingException { return lookup(name, true); } /** * Retrieves the named object. * * @param name the name of the object to look up * @return the object bound to name * @exception NamingException if a naming exception is encountered */ @Override public Object lookup(String name) throws NamingException { return lookup(new CompositeName(name), true); } /** * Binds a name to an object. All intermediate contexts and the target context (that named by all * but terminal atomic component of the name) must already exist. * * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @exception NameAlreadyBoundException if name is already bound * @exception javax.naming.directory.InvalidAttributesException if object did not supply all * mandatory attributes * @exception NamingException if a naming exception is encountered */ @Override public void bind(Name name, Object obj) throws NamingException { bind(name, obj, false); } /** * Binds a name to an object. * * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @exception NameAlreadyBoundException if name is already bound * @exception javax.naming.directory.InvalidAttributesException if object did not supply all * mandatory attributes * @exception NamingException if a naming exception is encountered */ @Override public void bind(String name, Object obj) throws NamingException { bind(new CompositeName(name), obj); } /** * Binds a name to an object, overwriting any existing binding. All intermediate contexts and the * target context (that named by all but terminal atomic component of the name) must already * exist. * * <p>If the object is a DirContext, any existing attributes associated with the name are replaced * with those of the object. Otherwise, any existing attributes associated with the name remain * unchanged. * * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @exception javax.naming.directory.InvalidAttributesException if object did not supply all * mandatory attributes * @exception NamingException if a naming exception is encountered */ @Override public void rebind(Name name, Object obj) throws NamingException { bind(name, obj, true); } /** * Binds a name to an object, overwriting any existing binding. * * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @exception javax.naming.directory.InvalidAttributesException if object did not supply all * mandatory attributes * @exception NamingException if a naming exception is encountered */ @Override public void rebind(String name, Object obj) throws NamingException { rebind(new CompositeName(name), obj); } /** * Unbinds the named object. Removes the terminal atomic name in name from the target * context--that named by all but the terminal atomic part of name. * * <p>This method is idempotent. It succeeds even if the terminal atomic name is not bound in the * target context, but throws NameNotFoundException if any of the intermediate contexts do not * exist. * * @param name the name to bind; may not be empty * @exception NameNotFoundException if an intermediate context does not exist * @exception NamingException if a naming exception is encountered */ @Override public void unbind(Name name) throws NamingException { if (!checkWritable()) { return; } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) throw new NamingException(sm.getString("namingContext.invalidName")); NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).unbind(name.getSuffix(1)); } else { throw new NamingException(sm.getString("namingContext.contextExpected")); } } else { bindings.remove(name.get(0)); } } /** * Unbinds the named object. * * @param name the name to bind; may not be empty * @exception NameNotFoundException if an intermediate context does not exist * @exception NamingException if a naming exception is encountered */ @Override public void unbind(String name) throws NamingException { unbind(new CompositeName(name)); } /** * Binds a new name to the object bound to an old name, and unbinds the old name. Both names are * relative to this context. Any attributes associated with the old name become associated with * the new name. Intermediate contexts of the old name are not changed. * * @param oldName the name of the existing binding; may not be empty * @param newName the name of the new binding; may not be empty * @exception NameAlreadyBoundException if newName is already bound * @exception NamingException if a naming exception is encountered */ @Override public void rename(Name oldName, Name newName) throws NamingException { Object value = lookup(oldName); bind(newName, value); unbind(oldName); } /** * Binds a new name to the object bound to an old name, and unbinds the old name. * * @param oldName the name of the existing binding; may not be empty * @param newName the name of the new binding; may not be empty * @exception NameAlreadyBoundException if newName is already bound * @exception NamingException if a naming exception is encountered */ @Override public void rename(String oldName, String newName) throws NamingException { rename(new CompositeName(oldName), new CompositeName(newName)); } /** * Enumerates the names bound in the named context, along with the class names of objects bound to * them. The contents of any subcontexts are not included. * * <p>If a binding is added to or removed from this context, its effect on an enumeration * previously returned is undefined. * * @param name the name of the context to list * @return an enumeration of the names and class names of the bindings in this context. Each * element of the enumeration is of type NameClassPair. * @exception NamingException if a naming exception is encountered */ @Override public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) { return new NamingContextEnumeration(bindings.values().iterator()); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type != NamingEntry.CONTEXT) { throw new NamingException(sm.getString("namingContext.contextExpected")); } return ((Context) entry.value).list(name.getSuffix(1)); } /** * Enumerates the names bound in the named context, along with the class names of objects bound to * them. * * @param name the name of the context to list * @return an enumeration of the names and class names of the bindings in this context. Each * element of the enumeration is of type NameClassPair. * @exception NamingException if a naming exception is encountered */ @Override public NamingEnumeration<NameClassPair> list(String name) throws NamingException { return list(new CompositeName(name)); } /** * Enumerates the names bound in the named context, along with the objects bound to them. The * contents of any subcontexts are not included. * * <p>If a binding is added to or removed from this context, its effect on an enumeration * previously returned is undefined. * * @param name the name of the context to list * @return an enumeration of the bindings in this context. Each element of the enumeration is of * type Binding. * @exception NamingException if a naming exception is encountered */ @Override public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) { return new NamingContextBindingsEnumeration(bindings.values().iterator(), this); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type != NamingEntry.CONTEXT) { throw new NamingException(sm.getString("namingContext.contextExpected")); } return ((Context) entry.value).listBindings(name.getSuffix(1)); } /** * Enumerates the names bound in the named context, along with the objects bound to them. * * @param name the name of the context to list * @return an enumeration of the bindings in this context. Each element of the enumeration is of * type Binding. * @exception NamingException if a naming exception is encountered */ @Override public NamingEnumeration<Binding> listBindings(String name) throws NamingException { return listBindings(new CompositeName(name)); } /** * Destroys the named context and removes it from the namespace. Any attributes associated with * the name are also removed. Intermediate contexts are not destroyed. * * <p>This method is idempotent. It succeeds even if the terminal atomic name is not bound in the * target context, but throws NameNotFoundException if any of the intermediate contexts do not * exist. * * <p>In a federated naming system, a context from one naming system may be bound to a name in * another. One can subsequently look up and perform operations on the foreign context using a * composite name. However, an attempt destroy the context using this composite name will fail * with NotContextException, because the foreign context is not a "subcontext" of the context in * which it is bound. Instead, use unbind() to remove the binding of the foreign context. * Destroying the foreign context requires that the destroySubcontext() be performed on a context * from the foreign context's "native" naming system. * * @param name the name of the context to be destroyed; may not be empty * @exception NameNotFoundException if an intermediate context does not exist * @exception NotContextException if the name is bound but does not name a context, or does not * name a context of the appropriate type */ @Override public void destroySubcontext(Name name) throws NamingException { if (!checkWritable()) { return; } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) throw new NamingException(sm.getString("namingContext.invalidName")); NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).destroySubcontext(name.getSuffix(1)); } else { throw new NamingException(sm.getString("namingContext.contextExpected")); } } else { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).close(); bindings.remove(name.get(0)); } else { throw new NotContextException(sm.getString("namingContext.contextExpected")); } } } /** * Destroys the named context and removes it from the namespace. * * @param name the name of the context to be destroyed; may not be empty * @exception NameNotFoundException if an intermediate context does not exist * @exception NotContextException if the name is bound but does not name a context, or does not * name a context of the appropriate type */ @Override public void destroySubcontext(String name) throws NamingException { destroySubcontext(new CompositeName(name)); } /** * Creates and binds a new context. Creates a new context with the given name and binds it in the * target context (that named by all but terminal atomic component of the name). All intermediate * contexts and the target context must already exist. * * @param name the name of the context to create; may not be empty * @return the newly created context * @exception NameAlreadyBoundException if name is already bound * @exception javax.naming.directory.InvalidAttributesException if creation of the sub-context * requires specification of mandatory attributes * @exception NamingException if a naming exception is encountered */ @Override public Context createSubcontext(Name name) throws NamingException { if (!checkWritable()) { return null; } NamingContext newContext = new NamingContext(env, this.name); bind(name, newContext); newContext.setExceptionOnFailedWrite(getExceptionOnFailedWrite()); return newContext; } /** * Creates and binds a new context. * * @param name the name of the context to create; may not be empty * @return the newly created context * @exception NameAlreadyBoundException if name is already bound * @exception javax.naming.directory.InvalidAttributesException if creation of the sub-context * requires specification of mandatory attributes * @exception NamingException if a naming exception is encountered */ @Override public Context createSubcontext(String name) throws NamingException { return createSubcontext(new CompositeName(name)); } /** * Retrieves the named object, following links except for the terminal atomic component of the * name. If the object bound to name is not a link, returns the object itself. * * @param name the name of the object to look up * @return the object bound to name, not following the terminal link (if any). * @exception NamingException if a naming exception is encountered */ @Override public Object lookupLink(Name name) throws NamingException { return lookup(name, false); } /** * Retrieves the named object, following links except for the terminal atomic component of the * name. * * @param name the name of the object to look up * @return the object bound to name, not following the terminal link (if any). * @exception NamingException if a naming exception is encountered */ @Override public Object lookupLink(String name) throws NamingException { return lookup(new CompositeName(name), false); } /** * Retrieves the parser associated with the named context. In a federation of namespaces, * different naming systems will parse names differently. This method allows an application to get * a parser for parsing names into their atomic components using the naming convention of a * particular naming system. Within any single naming system, NameParser objects returned by this * method must be equal (using the equals() test). * * @param name the name of the context from which to get the parser * @return a name parser that can parse compound names into their atomic components * @exception NamingException if a naming exception is encountered */ @Override public NameParser getNameParser(Name name) throws NamingException { while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) return nameParser; if (name.size() > 1) { Object obj = bindings.get(name.get(0)); if (obj instanceof Context) { return ((Context) obj).getNameParser(name.getSuffix(1)); } else { throw new NotContextException(sm.getString("namingContext.contextExpected")); } } return nameParser; } /** * Retrieves the parser associated with the named context. * * @param name the name of the context from which to get the parser * @return a name parser that can parse compound names into their atomic components * @exception NamingException if a naming exception is encountered */ @Override public NameParser getNameParser(String name) throws NamingException { return getNameParser(new CompositeName(name)); } /** * Composes the name of this context with a name relative to this context. * * <p>Given a name (name) relative to this context, and the name (prefix) of this context relative * to one of its ancestors, this method returns the composition of the two names using the syntax * appropriate for the naming system(s) involved. That is, if name names an object relative to * this context, the result is the name of the same object, but relative to the ancestor context. * None of the names may be null. * * @param name a name relative to this context * @param prefix the name of this context relative to one of its ancestors * @return the composition of prefix and name * @exception NamingException if a naming exception is encountered */ @Override public Name composeName(Name name, Name prefix) throws NamingException { prefix = (Name) prefix.clone(); return prefix.addAll(name); } /** * Composes the name of this context with a name relative to this context. * * @param name a name relative to this context * @param prefix the name of this context relative to one of its ancestors * @return the composition of prefix and name * @exception NamingException if a naming exception is encountered */ @Override public String composeName(String name, String prefix) throws NamingException { return prefix + "/" + name; } /** * Adds a new environment property to the environment of this context. If the property already * exists, its value is overwritten. * * @param propName the name of the environment property to add; may not be null * @param propVal the value of the property to add; may not be null * @exception NamingException if a naming exception is encountered */ @Override public Object addToEnvironment(String propName, Object propVal) throws NamingException { return env.put(propName, propVal); } /** * Removes an environment property from the environment of this context. * * @param propName the name of the environment property to remove; may not be null * @exception NamingException if a naming exception is encountered */ @Override public Object removeFromEnvironment(String propName) throws NamingException { return env.remove(propName); } /** * Retrieves the environment in effect for this context. See class description for more details on * environment properties. The caller should not make any changes to the object returned: their * effect on the context is undefined. The environment of this context may be changed using * addToEnvironment() and removeFromEnvironment(). * * @return the environment of this context; never null * @exception NamingException if a naming exception is encountered */ @Override public Hashtable<?, ?> getEnvironment() throws NamingException { return env; } /** * Closes this context. This method releases this context's resources immediately, instead of * waiting for them to be released automatically by the garbage collector. This method is * idempotent: invoking it on a context that has already been closed has no effect. Invoking any * other method on a closed context is not allowed, and results in undefined behaviour. * * @exception NamingException if a naming exception is encountered */ @Override public void close() throws NamingException { if (!checkWritable()) { return; } env.clear(); } /** * Retrieves the full name of this context within its own namespace. * * <p>Many naming services have a notion of a "full name" for objects in their respective * namespaces. For example, an LDAP entry has a distinguished name, and a DNS record has a fully * qualified name. This method allows the client application to retrieve this name. The string * returned by this method is not a JNDI composite name and should not be passed directly to * context methods. In naming systems for which the notion of full name does not make sense, * OperationNotSupportedException is thrown. * * @return this context's name in its own namespace; never null * @exception OperationNotSupportedException if the naming system does not have the notion of a * full name * @exception NamingException if a naming exception is encountered */ @Override public String getNameInNamespace() throws NamingException { throw new OperationNotSupportedException(sm.getString("namingContext.noAbsoluteName")); // FIXME ? } // ------------------------------------------------------ Protected Methods /** * Retrieves the named object. * * @param name the name of the object to look up * @param resolveLinks If true, the links will be resolved * @return the object bound to name * @exception NamingException if a naming exception is encountered */ protected Object lookup(Name name, boolean resolveLinks) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) { // If name is empty, a newly allocated naming context is returned return new NamingContext(env, this.name, bindings); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { // If the size of the name is greater that 1, then we go through a // number of subcontexts. if (entry.type != NamingEntry.CONTEXT) { throw new NamingException(sm.getString("namingContext.contextExpected")); } return ((Context) entry.value).lookup(name.getSuffix(1)); } else { if ((resolveLinks) && (entry.type == NamingEntry.LINK_REF)) { String link = ((LinkRef) entry.value).getLinkName(); if (link.startsWith(".")) { // Link relative to this context return lookup(link.substring(1)); } else { return (new InitialContext(env)).lookup(link); } } else if (entry.type == NamingEntry.REFERENCE) { try { // TODO ÐèѧϰNamingManager Object obj = NamingManager.getObjectInstance(entry.value, name, this, env); if (entry.value instanceof ResourceRef) { boolean singleton = Boolean.parseBoolean( (String) ((ResourceRef) entry.value).get("singleton").getContent()); if (singleton) { entry.type = NamingEntry.ENTRY; entry.value = obj; } } return obj; } catch (NamingException e) { throw e; } catch (Exception e) { log.warn(sm.getString("namingContext.failResolvingReference"), e); throw new NamingException(e.getMessage()); } } else { return entry.value; } } } /** * Binds a name to an object. All intermediate contexts and the target context (that named by all * but terminal atomic component of the name) must already exist. * * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @param rebind if true, then perform a rebind (ie, overwrite) * @exception NameAlreadyBoundException if name is already bound * @exception javax.naming.directory.InvalidAttributesException if object did not supply all * mandatory attributes * @exception NamingException if a naming exception is encountered */ protected void bind(Name name, Object obj, boolean rebind) throws NamingException { if (!checkWritable()) { return; } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); if (name.isEmpty()) throw new NamingException(sm.getString("namingContext.invalidName")); NamingEntry entry = bindings.get(name.get(0)); if (name.size() > 1) { if (entry == null) { throw new NameNotFoundException( sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type == NamingEntry.CONTEXT) { if (rebind) { ((Context) entry.value).rebind(name.getSuffix(1), obj); } else { ((Context) entry.value).bind(name.getSuffix(1), obj); } } else { throw new NamingException(sm.getString("namingContext.contextExpected")); } } else { if ((!rebind) && (entry != null)) { throw new NameAlreadyBoundException( sm.getString("namingContext.alreadyBound", name.get(0))); } else { // Getting the type of the object and wrapping it within a new // NamingEntry Object toBind = NamingManager.getStateToBind(obj, name, this, env); if (toBind instanceof Context) { entry = new NamingEntry(name.get(0), toBind, NamingEntry.CONTEXT); } else if (toBind instanceof LinkRef) { entry = new NamingEntry(name.get(0), toBind, NamingEntry.LINK_REF); } else if (toBind instanceof Reference) { entry = new NamingEntry(name.get(0), toBind, NamingEntry.REFERENCE); } else if (toBind instanceof Referenceable) { toBind = ((Referenceable) toBind).getReference(); entry = new NamingEntry(name.get(0), toBind, NamingEntry.REFERENCE); } else { entry = new NamingEntry(name.get(0), toBind, NamingEntry.ENTRY); } bindings.put(name.get(0), entry); } } } /** Returns true if writing is allowed on this context. */ protected boolean isWritable() { return ContextAccessController.isWritable(name); } /** Throws a naming exception is Context is not writable. */ protected boolean checkWritable() throws NamingException { if (isWritable()) { return true; } else { if (exceptionOnFailedWrite) { throw new javax.naming.OperationNotSupportedException( sm.getString("namingContext.readOnly")); } } return false; } }
/** * Context represent a Web Application as specified by Servlet Specs. The implementation is a * repository for all the properties defined in web.xml and tomcat specific properties. * * @author James Duncan Davidson [[email protected]] * @author James Todd [[email protected]] * @author Jason Hunter [[email protected]] * @author Harish Prabandham * @author [email protected] * @author Gal Shachor [email protected] * @author Arieh Markel [[email protected]] */ public class Context { private static StringManager sm = StringManager.getManager("org.apache.tomcat.core"); // -------------------- internal properties // context "id" private String path = ""; private String docBase; // Absolute path to docBase if file-system based private String absPath; // internal state / related objects private ContextManager contextM; private ServletContext contextFacade; private boolean crossContext = true; private ServletLoader servletL; boolean reloadable = true; // XXX change default to false after testing private Hashtable attributes = new Hashtable(); private File workDir; // Security Permissions for webapps and jsp for this context Object perms = null; Object protectionDomain; // private RequestSecurityProvider rsProvider; // Servlets loaded by this context( String->ServletWrapper ) private Hashtable servlets = new Hashtable(); // -------------------- from web.xml private Hashtable initializationParameters = new Hashtable(); // all welcome files that are added are treated as "system default" private boolean expectUserWelcomeFiles = false; private Vector welcomeFiles = new Vector(); private Hashtable errorPages = new Hashtable(); private String description = null; private boolean isDistributable = false; private MimeMap mimeTypes = new MimeMap(); private int sessionTimeOut = -1; // taglibs Hashtable tagLibs = new Hashtable(); // Env entries Hashtable envEntryTypes = new Hashtable(); Hashtable envEntryValues = new Hashtable(); // Maps specified in web.xml ( String url -> ServletWrapper ) private Hashtable mappings = new Hashtable(); Hashtable constraints = new Hashtable(); Hashtable containers = new Hashtable(); Container defaultContainer = null; // generalization, will replace most of the // functionality. By using a default container we avoid a lot of checkings // and speed up searching, and we can get rid of special properties. private ServletWrapper defaultServlet = null; // Authentication properties String authMethod; String realmName; String formLoginPage; String formErrorPage; int debug = 0; // are servlets allowed to access internal objects? boolean trusted = false; String vhost = null; Vector vhostAliases = new Vector(); FacadeManager facadeM; public Context() { defaultContainer = new Container(); defaultContainer.setContext(this); defaultContainer.setPath(null); // default container } /** Every context is associated with a facade */ public ServletContext getFacade() { if (contextFacade == null) contextFacade = getFacadeManager().createServletContextFacade(this); return contextFacade; } // -------------------- Settable context properties -------------------- // -------------------- Required properties public ContextManager getContextManager() { return contextM; } public void setContextManager(ContextManager cm) { contextM = cm; } public boolean getCrossContext() { return (this.crossContext); } public void setCrossContext(boolean crossContext) { this.crossContext = crossContext; } public FacadeManager getFacadeManager() { if (facadeM == null) { /* XXX make it configurable */ facadeM = new SimpleFacadeManager(this); } return facadeM; } /** Base URL for this context */ public String getPath() { return path; } /** Base URL for this context */ public void setPath(String path) { // config believes that the root path is called "/", // if ("/".equals(path)) path = ""; this.path = path; } /** * DocBase points to the web application files. * * <p>There is no restriction on the syntax and content of DocBase, it's up to the various modules * to interpret this and use it. For example, to serve from a war file you can use war: protocol, * and set up War interceptors. * * <p>"Basic" tomcat treats it as a file ( either absolute or relative to the CM home ). * * <p>If docBase is relative assume it is relative to the context manager home. */ public void setDocBase(String docB) { this.docBase = docB; } public String getDocBase() { return docBase; } /** Return the absolute path for the docBase, if we are file-system based, null otherwise. */ public String getAbsolutePath() { if (absPath != null) return absPath; if (FileUtil.isAbsolute(docBase)) absPath = docBase; else absPath = contextM.getHome() + File.separator + docBase; try { absPath = new File(absPath).getCanonicalPath(); } catch (IOException npe) { } return absPath; } // -------------------- Tomcat specific properties // workaround for XmlMapper unable to set anything but strings public void setReloadable(String s) { reloadable = new Boolean(s).booleanValue(); } public void setReloadable(boolean b) { reloadable = b; } /** Should we reload servlets ? */ public boolean getReloadable() { return reloadable; } // -------------------- Web.xml properties -------------------- public Enumeration getWelcomeFiles() { return welcomeFiles.elements(); } /** * @deprecated It is used as a hack to allow web.xml override default welcome files. Tomcat will * first load the "default" web.xml and then this file. */ public void removeWelcomeFiles() { if (!this.welcomeFiles.isEmpty()) this.welcomeFiles.removeAllElements(); } /** * If any new welcome file is added, remove the old list of welcome files and start a new one. * This is used as a hack to allow a default web.xml file to specifiy welcome files. We should use * a better mechanism! */ public void expectUserWelcomeFiles() { expectUserWelcomeFiles = true; } public void addWelcomeFile(String s) { // user specified at least one user welcome file, remove the system // files if (s == null) return; s = s.trim(); if (s.length() == 0) return; if (expectUserWelcomeFiles) { removeWelcomeFiles(); expectUserWelcomeFiles = false; } welcomeFiles.addElement(s); } /** Add a taglib declaration for this context */ public void addTaglib(String uri, String location) { // System.out.println("Add taglib " + uri + " " + location ); tagLibs.put(uri, location); } public String getTaglibLocation(String uri) { return (String) tagLibs.get(uri); } public Enumeration getTaglibs() { return tagLibs.keys(); } /** Add Env-entry to this context */ public void addEnvEntry(String name, String type, String value, String description) { System.out.println("Add env-entry " + name + " " + type + " " + value + " " + description); if (name == null || type == null) throw new IllegalArgumentException(); envEntryTypes.put(name, type); if (value != null) envEntryValues.put(name, value); } public String getEnvEntryType(String name) { return (String) envEntryTypes.get(name); } public String getEnvEntryValue(String name) { return (String) envEntryValues.get(name); } public Enumeration getEnvEntries() { return envEntryTypes.keys(); } public String getInitParameter(String name) { return (String) initializationParameters.get(name); } /** @deprecated use addInitParameter */ public void setInitParameter(String name, String value) { initializationParameters.put(name, value); } public void addInitParameter(String name, String value) { initializationParameters.put(name, value); } public Enumeration getInitParameterNames() { return initializationParameters.keys(); } public Object getAttribute(String name) { if (name.startsWith("org.apache.tomcat")) { // XXX XXX XXX XXX Security - servlets may get too much access !!! // right now we don't check because we need JspServlet to // be able to access classloader and classpath if (name.equals("org.apache.tomcat.jsp_classpath")) { String cp = getServletLoader().getClassPath(); return cp; } if (name.equals("org.apache.tomcat.protection_domain")) { return getProtectionDomain(); } if (name.equals("org.apache.tomcat.classloader")) { return this.getServletLoader().getClassLoader(); } if (name.equals(FacadeManager.FACADE_ATTRIBUTE)) { if (!allowAttribute(name)) return null; return this.getFacadeManager(); } return null; // org.apache.tomcat namespace is reserved in tomcat } else { Object o = attributes.get(name); return attributes.get(name); } } public Enumeration getAttributeNames() { return attributes.keys(); } public void setAttribute(String name, Object object) { attributes.put(name, object); } public void removeAttribute(String name) { attributes.remove(name); } public String getDescription() { return this.description; } public void setDescription(String description) { this.description = description; } public void setIcon(String icon) {} public boolean isDistributable() { return this.isDistributable; } public void setDistributable(boolean isDistributable) { this.isDistributable = isDistributable; } public void setDistributable(String s) { // XXX } public int getSessionTimeOut() { return this.sessionTimeOut; } public void setSessionTimeOut(int sessionTimeOut) { this.sessionTimeOut = sessionTimeOut; } public FileNameMap getMimeMap() { return mimeTypes; } public void addContentType(String ext, String type) { mimeTypes.addContentType(ext, type); } public String getErrorPage(int errorCode) { return getErrorPage(String.valueOf(errorCode)); } public void addErrorPage(String errorType, String value) { this.errorPages.put(errorType, value); } public String getErrorPage(String errorCode) { return (String) errorPages.get(errorCode); } /** Authentication method, if any specified */ public String getAuthMethod() { return authMethod; } /** Realm to be used */ public String getRealmName() { return realmName; } public String getFormLoginPage() { return formLoginPage; } public String getFormErrorPage() { return formErrorPage; } public void setFormLoginPage(String page) { formLoginPage = page; } public void setFormErrorPage(String page) { formErrorPage = page; } public void setLoginConfig( String authMethod, String realmName, String formLoginPage, String formErrorPage) { // System.out.println("Login config: " + authMethod + " " + realmName + " " + // formLoginPage + " " + formErrorPage); this.authMethod = authMethod; this.realmName = realmName; this.formLoginPage = formLoginPage; this.formErrorPage = formErrorPage; } // -------------------- Mappings -------------------- /** * Maps a named servlet to a particular path or extension. If the named servlet is unregistered, * it will be added and subsequently mapped. * * <p>Note that the order of resolution to handle a request is: * * <p>exact mapped servlet (eg /catalog) prefix mapped servlets (eg /foo/bar/*) extension mapped * servlets (eg *jsp) default servlet */ public void addServletMapping(String path, String servletName) throws TomcatException { if (mappings.get(path) != null) { log("Removing duplicate " + path + " -> " + mappings.get(path)); mappings.remove(path); Container ct = (Container) containers.get(path); removeContainer(ct); } ServletWrapper sw = (ServletWrapper) servlets.get(servletName); if (sw == null) { // Workaround for frequent "bug" in web.xmls // Declare a default mapping log("Mapping with unregistered servlet " + servletName); sw = addServlet(servletName, servletName); } if ("/".equals(path)) defaultServlet = sw; mappings.put(path, sw); Container map = new Container(); map.setContext(this); map.setHandler(sw); map.setPath(path); contextM.addContainer(map); containers.put(path, map); } /** * Will add a new security constraint: For all paths: if( match(path) && match(method) && match( * transport ) ) then require("roles") * * <p>This is equivalent with adding a Container with the path, method and transport. If the * container will be matched, the request will have to pass the security constraints. */ public void addSecurityConstraint( String path[], String methods[], String roles[], String transport) throws TomcatException { for (int i = 0; i < path.length; i++) { Container ct = new Container(); ct.setContext(this); ct.setTransport(transport); ct.setRoles(roles); ct.setPath(path[i]); ct.setMethods(methods); // XXX check if exists, merge if true. constraints.put(path[i], ct); // contextM.addSecurityConstraint( this, path[i], ct); contextM.addContainer(ct); } } public Enumeration getContainers() { return containers.elements(); } public Enumeration getContainerLocations() { return containers.keys(); } public Container getContainer(String path) { return (Container) containers.get(path); } // return the container associated with this context - // which is also the default container public Container getContainer() { return defaultContainer; } public void removeContainer(Container ct) { containers.remove(ct.getPath()); } // public ServletWrapper getDefaultServlet() { // if( defaultServlet==null) // defaultServlet=getServletByName(Constants.DEFAULT_SERVLET_NAME ); // return defaultServlet; // } // -------------------- Servlets management -------------------- // XXX do we need that ?? /** Remove the servlet with a specific name */ public void removeServletByName(String servletName) throws TomcatException { servlets.remove(servletName); } public ServletWrapper getServletByName(String servletName) { return (ServletWrapper) servlets.get(servletName); } /** * Add a servlet with the given name to the container. The servlet will be loaded by the * container's class loader and instantiated using the given class name. * * <p>Called to add a new servlet from web.xml */ public void addServlet(ServletWrapper wrapper) throws TomcatException { wrapper.setContext(this); String name = wrapper.getServletName(); // System.out.println("Adding servlet " + name + " " + wrapper); // check for duplicates if (servlets.get(name) != null) { log("Removing duplicate servlet " + name + " " + wrapper); removeServletByName(name); // getServletByName(name).destroy(); } servlets.put(name, wrapper); } public ServletWrapper addServlet(String name, String classN) throws TomcatException { ServletWrapper sw = new ServletWrapper(); sw.setContext(this); sw.setServletName(name); if (classN.startsWith("/")) { sw.setPath(classN); } else { sw.setServletClass(classN); } addServlet(sw); return sw; } public Enumeration getServletNames() { return servlets.keys(); } // -------------------- Loading and sessions -------------------- public void setServletLoader(ServletLoader loader) { this.servletL = loader; } public ServletLoader getServletLoader() { return servletL; } /* -------------------- Utils -------------------- */ public void setDebug(int level) { if (level > 0) log("Set debug to " + level); debug = level; } public void setDebug(String level) { try { setDebug(Integer.parseInt(level)); } catch (Exception e) { log("Trying to set debug to '" + level + "':", e, Logger.ERROR); } } public int getDebug() { return debug; } // ------------------- Logging --------------- LogHelper loghelper = new LogHelper("tc_log", this); LogHelper loghelperServlet = new LogHelper("servlet_log", null); /** Internal log method */ public final void log(String msg) { loghelper.log(msg); } /** Internal log method */ public void log(String msg, Throwable t) { loghelper.log(msg, t); } /** Internal log method */ public void log(String msg, Throwable t, int level) { loghelper.log(msg, t, level); } /** User-level log method ( called from a servlet) */ public void logServlet(String msg, Throwable t) { msg = ("path=\"" + path + "\" :" + msg); loghelperServlet.log(msg, t); } public String toString() { return "Ctx( " + (vhost == null ? "" : vhost + ":") + path + " )"; } // -------------------- Facade methods -------------------- public Context getContext(String path) { if (!path.startsWith("/")) { return null; // according to spec, null is returned // if we can't return a servlet, so it's more probable // servlets will check for null than IllegalArgument } // Return null if cross context lookups are not allowed if (!crossContext) return null; // absolute path Request lr = contextM.createRequest(path); if (vhost != null) lr.setServerName(vhost); getContextManager().processRequest(lr); return lr.getContext(); } /** * Implements getResource() See getRealPath(), it have to be local to the current Context - and * can't go to a sub-context. That means we don't need any overhead. */ public URL getResource(String rpath) throws MalformedURLException { if (rpath == null) return null; if (URLUtil.hasEscape(rpath)) return null; URL url = null; String absPath = getAbsolutePath(); if ("".equals(rpath)) return new URL("file", null, 0, absPath); if (!rpath.startsWith("/")) rpath = "/" + rpath; String realPath = FileUtil.safePath(absPath, rpath); if (realPath == null) { log("Unsafe path " + absPath + " " + rpath); return null; } try { url = new URL("file", null, 0, realPath); if (debug > 9) log("getResourceURL=" + url + " request=" + rpath); return url; } catch (IOException ex) { ex.printStackTrace(); return null; } } /** * According to Servlet 2.2 the real path is interpreted as relative to the current web app and * _cannot_ go outside the box. If your intention is different or want the "other" behavior you'll * have to first call getContext(path) and call getRealPath() on the result context ( if any - the * server may disable that from security reasons !). XXX find out how can we find the context path * in order to remove it from the path - that's the only way a user can do that unless he have * prior knowledge of the mappings ! */ public String getRealPath(String path) { String base = getAbsolutePath(); if (path == null) path = ""; String realPath = FileUtil.safePath(base, path); // No need for a sub-request, that's a great simplification // in servlet space. // Important: that's different from what some people might // expect and how other server APIs work, but that's how it's // specified in 2.2. From a security point of view that's very // good, it keeps inter-webapp communication under control. if (debug > 5) { log("Get real path " + path + " " + realPath + " " + base); } return realPath; } /** * method to return the Localized version of the file whose name is passed as an argument. This * corresponds to "file" type localization resource lookup mechanism. * * <p>The method performs a resource lookup in a manner similar to the one specified by * java.util.ResourceBundle. * * <p>In the case of 'typed' files (files whose name is [file].[ftype]) search for localized * versions of the file are looked for: * * <p>file + "_" + language1 + "_" + country1 + "_" + variant1 + "." + ftype file + "_" + * language1 + "_" + country1 + "." + ftype file + "_" + language1 + "." + ftype file + "_" + * language2 + "_" + country2 + "_" + variant2 "." + ftype file + "_" + language2 + "_" + country2 * "." + ftype file + "_" + language2 + "." + ftype file + "." + ftype * * <p>Where language1, country1, variant1 are associated with the Locale passed as an argument and * language2, country2, variant are associated with the default Locale passed as argument. * * <p>For example, if the preferred Locale is <CODE>es_AR_POSIX</CODE> and the default Locale * passed is <CODE>fr_CA_WIN</CODE>, and the requested pathname is <CODE>/foo/bar/index.html * </CODE>, then a search for the following localized versions of that file will be done, in * order: * * <UL> * <LI>/foo/bar/index_es_AR_POSIX.html * <LI>/foo/bar/index_es_AR.html * <LI>/foo/bar/index_es.html * <LI>/foo/bar/index_fr_CA_WIN.html * <LI>/foo/bar/index_fr.html * <LI>/foo/bar/index.html * </UL> * * If the resource passed has no 'ftype' component, then the same rules above apply, with the * exception that '.' + ftype are not concatenated. * * @param path the pathname for the resource whose localized version we are seeking * @param loc the Locale we are interested in. * @param fbLoc the fallback Locale to use if unsuccessful * @return a String with the path of the "best localized match" for the file whose path has been * passed as argument. */ public String getRealPath(String path, Locale reqLocale, Locale fbLocale) { return getRealPath(path, reqLocale, fbLocale, "file"); } /** * method to return the Localized version of the file whose name is passed as an argument. The * localization is done based on localization subdirectories under the docBase. * * <p>The method performs a resource lookup in a manner similar to the one used for JavaHelp * resources. * * <p>Search for localized versions of the file are looked for: * * <p><docBase> + "/" + language1 + "_" + country1 + "_" + variant1 + file <docBase> + "/" + * language1 + "_" + country1 + file <docBase> + "/" + language1 + file <docBase> + "/" + * language2 + "_" + country2 + "_" + variant1 + file <docBase> + "/" + language2 + "_" + country2 * + file <docBase> + "/" + language2 + file <docBase> + file * * <p>Where language1, country1, variant1 are associated with the Locale passed as an argument and * language2, country2, variant are associated with the fallback Locale passed as argument. * * @param path the pathname for the resource whose localized version we are seeking * @param loc the Locale we are interested in. * @param fbLoc the fallback Locale to use if unsuccessful * @param locType the type of localization required "file", "docbase" * @return a String with the path of the "best localized match" for the file whose path has been * passed as argument. */ public String getRealPath(String path, Locale reqLocale, Locale fbLocale, String locType) { String base = getAbsolutePath(); if (path == null) path = ""; String realPath = null; if ("file".equals(locType)) realPath = FileUtil.getLocalizedFile(base, path, reqLocale, fbLocale); else if ("docbase".equals(locType)) realPath = FileUtil.getDocBaseLocalizedFile(base, path, reqLocale, fbLocale); if (debug > 5) { log( "Get real path " + path + " " + realPath + " " + base + reqLocale.toString() + " " + fbLocale.toString()); } return realPath; } // -------------------- Deprecated // tomcat specific properties private boolean isWorkDirPersistent = false; private String engineHeader = null; private URL documentBase; private URL servletBase = null; private boolean isInvokerEnabled = false; // for serving WARs directly private File warDir = null; private boolean isWARExpanded = false; private boolean isWARValidated = false; /** @deprecated */ public boolean isInvokerEnabled() { return isInvokerEnabled; } /** @deprecated */ public void setInvokerEnabled(boolean isInvokerEnabled) { this.isInvokerEnabled = isInvokerEnabled; } /** @deprecated */ public boolean isWorkDirPersistent() { return this.isWorkDirPersistent; } /** @deprecated */ public void setWorkDirPersistent(boolean b) { isWorkDirPersistent = b; } /** @deprecated */ public File getWorkDir() { return workDir; } /** @deprecated */ public void setWorkDir(File workDir) { this.workDir = workDir; } /** * Set work dir using a String property * * @deprecated */ public void setWorkDirPath(String workDir) { this.workDir = new File(workDir); } /** @deprecated */ public String getEngineHeader() { return engineHeader; } /** @deprecated */ public void setEngineHeader(String s) { engineHeader = s; } // /** @deprecated // */ // public void setRequestSecurityProvider(RequestSecurityProvider rsProvider) { // this.rsProvider = rsProvider; // } // /** @deprecated // */ // public RequestSecurityProvider getRequestSecurityProvider() { // return this.rsProvider; // } /** @deprecated */ public File getWARDir() { return this.warDir; } /** @deprecated */ public void setWARDir(File f) { warDir = f; } /** @deprecated */ public boolean isWARExpanded() { return this.isWARExpanded; } /** @deprecated */ public void setIsWARExpanded(boolean isWARExpanded) { this.isWARExpanded = isWARExpanded; } /** @deprecated */ public boolean isWARValidated() { return this.isWARValidated; } /** @deprecated */ public void setIsWARValidated(boolean isWARValidated) { this.isWARValidated = isWARValidated; } /** @deprecated */ public void addContextInterceptor(ContextInterceptor ci) { getContainer().addContextInterceptor(ci); } /** @deprecated */ public ContextInterceptor[] getContextInterceptors() { return getContainer().getContextInterceptors(); } /** @deprecated */ public void addRequestInterceptor(RequestInterceptor ci) { getContainer().addRequestInterceptor(ci); } /** @deprecated */ public RequestInterceptor[] getRequestInterceptors() { return getContainer().getRequestInterceptors(); } /** Get the SecurityManager Permissions for this Context. */ public Object getPermissions() { return perms; } public void setPermissions(Object o) { perms = o; } public Object getProtectionDomain() { return protectionDomain; } public void setProtectionDomain(Object o) { protectionDomain = o; } /** * @deprecated - use getDocBase and URLUtil if you need it as URL NOT USED INSIDE TOMCAT - ONLY IN * OLD J2EE CONNECTORS ! */ public URL getDocumentBase() { if (documentBase == null) { if (docBase == null) return null; try { String absPath = docBase; // detect absolute path ( use the same logic in all tomcat ) if (FileUtil.isAbsolute(docBase)) absPath = docBase; else absPath = contextM.getHome() + File.separator + docBase; try { absPath = new File(absPath).getCanonicalPath(); } catch (IOException npe) { } documentBase = new URL("file", "", absPath); } catch (MalformedURLException ex) { ex.printStackTrace(); } } return documentBase; } /** @deprecated - use setDocBase */ public void setDocumentBase(URL s) { // Used only by startup, will be removed this.documentBase = s; } // -------------------- Virtual host support -------------------- /** Make this context visible as part of a virtual host */ public void setHost(String h) { vhost = h; } /** Return the virtual host name, or null if we are in the default context */ public String getHost() { return vhost; } /** * Virtual host support - this context will be part of a virtual host with the specified name. You * should set all the aliases. XXX Not implemented */ public void addHostAlias(String alias) { vhostAliases.addElement(alias); } public Enumeration getHostAliases() { return vhostAliases.elements(); } // -------------------- Security - trusted code -------------------- public void setTrusted(boolean t) { trusted = t; } public boolean isTrusted() { return trusted; } public boolean allowAttribute(String name) { // check if we can access this attribute. if (isTrusted()) return true; log("Illegal access to internal attribute ", null, Logger.ERROR); return false; } }
public String id() { return strings.get(readShort(attributesEnd + 0xc)); }