Path: blob/master/src/java.naming/share/classes/javax/naming/InitialContext.java
41152 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.naming;2627import java.util.Hashtable;28import javax.naming.spi.NamingManager;29import com.sun.naming.internal.ResourceManager;3031/**32* This class is the starting context for performing naming operations.33*<p>34* All naming operations are relative to a context.35* The initial context implements the Context interface and36* provides the starting point for resolution of names.37*<p>38* <a id=ENVIRONMENT></a>39* When the initial context is constructed, its environment40* is initialized with properties defined in the environment parameter41* passed to the constructor, and in any42* <a href=Context.html#RESOURCEFILES>application resource files</a>.43*<p>44* JNDI determines each property's value by merging45* the values from the following two sources, in order:46* <ol>47* <li>48* The first occurrence of the property from the constructor's49* environment parameter and system properties.50* <li>51* The application resource files ({@code jndi.properties}).52* </ol>53* For each property found in both of these two sources, or in54* more than one application resource file, the property's value55* is determined as follows. If the property is56* one of the standard JNDI properties that specify a list of JNDI57* factories (see <a href=Context.html#LISTPROPS>{@code Context}</a>),58* all of the values are59* concatenated into a single colon-separated list. For other60* properties, only the first value found is used.61*62*<p>63* The initial context implementation is determined at runtime.64* The default policy uses the environment property65* "{@link Context#INITIAL_CONTEXT_FACTORY java.naming.factory.initial}",66* which contains the class name of the initial context factory.67* An exception to this policy is made when resolving URL strings, as described68* below.69*<p>70* When a URL string (a {@code String} of the form71* <em>scheme_id:rest_of_name</em>) is passed as a name parameter to72* any method, a URL context factory for handling that scheme is73* located and used to resolve the URL. If no such factory is found,74* the initial context specified by75* {@code "java.naming.factory.initial"} is used. Similarly, when a76* {@code CompositeName} object whose first component is a URL string is77* passed as a name parameter to any method, a URL context factory is78* located and used to resolve the first name component.79* See {@link NamingManager#getURLContext80* NamingManager.getURLContext()} for a description of how URL81* context factories are located.82*<p>83* This default policy of locating the initial context and URL context84* factories may be overridden85* by calling86* {@code NamingManager.setInitialContextFactoryBuilder()}.87*<p>88* NoInitialContextException is thrown when an initial context cannot89* be instantiated. This exception can be thrown during any interaction90* with the InitialContext, not only when the InitialContext is constructed.91* For example, the implementation of the initial context might lazily92* retrieve the context only when actual methods are invoked on it.93* The application should not have any dependency on when the existence94* of an initial context is determined.95*<p>96* When the environment property "java.naming.factory.initial" is97* non-null, the InitialContext constructor will attempt to create the98* initial context specified therein. At that time, the initial context factory99* involved might throw an exception if a problem is encountered. However,100* it is provider implementation-dependent when it verifies and indicates101* to the users of the initial context any environment property- or102* connection- related problems. It can do so lazily--delaying until103* an operation is performed on the context, or eagerly, at the time104* the context is constructed.105*<p>106* An InitialContext instance is not synchronized against concurrent107* access by multiple threads. Multiple threads each manipulating a108* different InitialContext instance need not synchronize.109* Threads that need to access a single InitialContext instance110* concurrently should synchronize amongst themselves and provide the111* necessary locking.112*113* @author Rosanna Lee114* @author Scott Seligman115*116* @see Context117* @see NamingManager#setInitialContextFactoryBuilder118* NamingManager.setInitialContextFactoryBuilder119* @since 1.3, JNDI 1.1120*/121122public class InitialContext implements Context {123124/**125* The environment associated with this InitialContext.126* It is initialized to null and is updated by the constructor127* that accepts an environment or by the {@code init()} method.128* @see #addToEnvironment129* @see #removeFromEnvironment130* @see #getEnvironment131*/132protected Hashtable<Object,Object> myProps = null;133134/**135* Field holding the result of calling NamingManager.getInitialContext().136* It is set by getDefaultInitCtx() the first time getDefaultInitCtx()137* is called. Subsequent invocations of getDefaultInitCtx() return138* the value of defaultInitCtx.139* @see #getDefaultInitCtx140*/141protected Context defaultInitCtx = null;142143/**144* Field indicating whether the initial context has been obtained145* by calling NamingManager.getInitialContext().146* If true, its result is in <code>defaultInitCtx</code>.147*/148protected boolean gotDefault = false;149150/**151* Constructs an initial context with the option of not152* initializing it. This may be used by a constructor in153* a subclass when the value of the environment parameter154* is not yet known at the time the {@code InitialContext}155* constructor is called. The subclass's constructor will156* call this constructor, compute the value of the environment,157* and then call {@code init()} before returning.158*159* @param lazy160* true means do not initialize the initial context; false161* is equivalent to calling {@code new InitialContext()}162* @throws NamingException if a naming exception is encountered163*164* @see #init(Hashtable)165* @since 1.3166*/167protected InitialContext(boolean lazy) throws NamingException {168if (!lazy) {169init(null);170}171}172173/**174* Constructs an initial context.175* No environment properties are supplied.176* Equivalent to {@code new InitialContext(null)}.177*178* @throws NamingException if a naming exception is encountered179*180* @see #InitialContext(Hashtable)181*/182public InitialContext() throws NamingException {183init(null);184}185186/**187* Constructs an initial context using the supplied environment.188* Environment properties are discussed in the class description.189*190* <p> This constructor will not modify {@code environment}191* or save a reference to it, but may save a clone.192* Caller should not modify mutable keys and values in193* {@code environment} after it has been passed to the constructor.194*195* @param environment196* environment used to create the initial context.197* Null indicates an empty environment.198*199* @throws NamingException if a naming exception is encountered200*/201public InitialContext(Hashtable<?,?> environment)202throws NamingException203{204if (environment != null) {205environment = (Hashtable)environment.clone();206}207init(environment);208}209210/**211* Initializes the initial context using the supplied environment.212* Environment properties are discussed in the class description.213*214* <p> This method will modify {@code environment} and save215* a reference to it. The caller may no longer modify it.216*217* @param environment218* environment used to create the initial context.219* Null indicates an empty environment.220*221* @throws NamingException if a naming exception is encountered222*223* @see #InitialContext(boolean)224* @since 1.3225*/226@SuppressWarnings("unchecked")227protected void init(Hashtable<?,?> environment)228throws NamingException229{230myProps = (Hashtable<Object,Object>)231ResourceManager.getInitialEnvironment(environment);232233if (myProps.get(Context.INITIAL_CONTEXT_FACTORY) != null) {234// user has specified initial context factory; try to get it235getDefaultInitCtx();236}237}238239/**240* A static method to retrieve the named object.241* This is a shortcut method equivalent to invoking:242* <p>243* <code>244* InitialContext ic = new InitialContext();245* Object obj = ic.lookup();246* </code>247* <p> If {@code name} is empty, returns a new instance of this context248* (which represents the same naming context as this context, but its249* environment may be modified independently and it may be accessed250* concurrently).251*252* @param <T> the type of the returned object253* @param name254* the name of the object to look up255* @return the object bound to {@code name}256* @throws NamingException if a naming exception is encountered257*258* @see #doLookup(String)259* @see #lookup(Name)260* @since 1.6261*/262@SuppressWarnings("unchecked")263public static <T> T doLookup(Name name)264throws NamingException {265return (T) (new InitialContext()).lookup(name);266}267268/**269* A static method to retrieve the named object.270* See {@link #doLookup(Name)} for details.271* @param <T> the type of the returned object272* @param name273* the name of the object to look up274* @return the object bound to {@code name}275* @throws NamingException if a naming exception is encountered276* @since 1.6277*/278@SuppressWarnings("unchecked")279public static <T> T doLookup(String name)280throws NamingException {281return (T) (new InitialContext()).lookup(name);282}283284private static String getURLScheme(String str) {285int colon_posn = str.indexOf(':');286int slash_posn = str.indexOf('/');287288if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))289return str.substring(0, colon_posn);290return null;291}292293/**294* Retrieves the initial context by calling295* <code>NamingManager.getInitialContext()</code>296* and cache it in defaultInitCtx.297* Set <code>gotDefault</code> so that we know we've tried this before.298* @return The non-null cached initial context.299* @throws NoInitialContextException If cannot find an initial context.300* @throws NamingException If a naming exception was encountered.301*/302protected Context getDefaultInitCtx() throws NamingException{303if (!gotDefault) {304defaultInitCtx = NamingManager.getInitialContext(myProps);305gotDefault = true;306}307if (defaultInitCtx == null)308throw new NoInitialContextException();309310return defaultInitCtx;311}312313/**314* Retrieves a context for resolving the string name <code>name</code>.315* If <code>name</code> name is a URL string, then attempt316* to find a URL context for it. If none is found, or if317* <code>name</code> is not a URL string, then return318* <code>getDefaultInitCtx()</code>.319*<p>320* See getURLOrDefaultInitCtx(Name) for description321* of how a subclass should use this method.322* @param name The non-null name for which to get the context.323* @return A URL context for <code>name</code> or the cached324* initial context. The result cannot be null.325* @throws NoInitialContextException If cannot find an initial context.326* @throws NamingException In a naming exception is encountered.327* @see javax.naming.spi.NamingManager#getURLContext328*/329protected Context getURLOrDefaultInitCtx(String name)330throws NamingException {331if (NamingManager.hasInitialContextFactoryBuilder()) {332return getDefaultInitCtx();333}334String scheme = getURLScheme(name);335if (scheme != null) {336Context ctx = NamingManager.getURLContext(scheme, myProps);337if (ctx != null) {338return ctx;339}340}341return getDefaultInitCtx();342}343344/**345* Retrieves a context for resolving <code>name</code>.346* If the first component of <code>name</code> name is a URL string,347* then attempt to find a URL context for it. If none is found, or if348* the first component of <code>name</code> is not a URL string,349* then return <code>getDefaultInitCtx()</code>.350*<p>351* When creating a subclass of InitialContext, use this method as352* follows.353* Define a new method that uses this method to get an initial354* context of the desired subclass.355* <blockquote><pre>356* protected XXXContext getURLOrDefaultInitXXXCtx(Name name)357* throws NamingException {358* Context answer = getURLOrDefaultInitCtx(name);359* if (!(answer instanceof XXXContext)) {360* if (answer == null) {361* throw new NoInitialContextException();362* } else {363* throw new NotContextException("Not an XXXContext");364* }365* }366* return (XXXContext)answer;367* }368* </pre></blockquote>369* When providing implementations for the new methods in the subclass,370* use this newly defined method to get the initial context.371* <blockquote><pre>372* public Object XXXMethod1(Name name, ...) {373* throws NamingException {374* return getURLOrDefaultInitXXXCtx(name).XXXMethod1(name, ...);375* }376* </pre></blockquote>377*378* @param name The non-null name for which to get the context.379* @return A URL context for <code>name</code> or the cached380* initial context. The result cannot be null.381* @throws NoInitialContextException If cannot find an initial context.382* @throws NamingException In a naming exception is encountered.383*384* @see javax.naming.spi.NamingManager#getURLContext385*/386protected Context getURLOrDefaultInitCtx(Name name)387throws NamingException {388if (NamingManager.hasInitialContextFactoryBuilder()) {389return getDefaultInitCtx();390}391if (name.size() > 0) {392String first = name.get(0);393String scheme = getURLScheme(first);394if (scheme != null) {395Context ctx = NamingManager.getURLContext(scheme, myProps);396if (ctx != null) {397return ctx;398}399}400}401return getDefaultInitCtx();402}403404// Context methods405// Most Javadoc is deferred to the Context interface.406407public Object lookup(String name) throws NamingException {408return getURLOrDefaultInitCtx(name).lookup(name);409}410411public Object lookup(Name name) throws NamingException {412return getURLOrDefaultInitCtx(name).lookup(name);413}414415public void bind(String name, Object obj) throws NamingException {416getURLOrDefaultInitCtx(name).bind(name, obj);417}418419public void bind(Name name, Object obj) throws NamingException {420getURLOrDefaultInitCtx(name).bind(name, obj);421}422423public void rebind(String name, Object obj) throws NamingException {424getURLOrDefaultInitCtx(name).rebind(name, obj);425}426427public void rebind(Name name, Object obj) throws NamingException {428getURLOrDefaultInitCtx(name).rebind(name, obj);429}430431public void unbind(String name) throws NamingException {432getURLOrDefaultInitCtx(name).unbind(name);433}434435public void unbind(Name name) throws NamingException {436getURLOrDefaultInitCtx(name).unbind(name);437}438439public void rename(String oldName, String newName) throws NamingException {440getURLOrDefaultInitCtx(oldName).rename(oldName, newName);441}442443public void rename(Name oldName, Name newName)444throws NamingException445{446getURLOrDefaultInitCtx(oldName).rename(oldName, newName);447}448449public NamingEnumeration<NameClassPair> list(String name)450throws NamingException451{452return (getURLOrDefaultInitCtx(name).list(name));453}454455public NamingEnumeration<NameClassPair> list(Name name)456throws NamingException457{458return (getURLOrDefaultInitCtx(name).list(name));459}460461public NamingEnumeration<Binding> listBindings(String name)462throws NamingException {463return getURLOrDefaultInitCtx(name).listBindings(name);464}465466public NamingEnumeration<Binding> listBindings(Name name)467throws NamingException {468return getURLOrDefaultInitCtx(name).listBindings(name);469}470471public void destroySubcontext(String name) throws NamingException {472getURLOrDefaultInitCtx(name).destroySubcontext(name);473}474475public void destroySubcontext(Name name) throws NamingException {476getURLOrDefaultInitCtx(name).destroySubcontext(name);477}478479public Context createSubcontext(String name) throws NamingException {480return getURLOrDefaultInitCtx(name).createSubcontext(name);481}482483public Context createSubcontext(Name name) throws NamingException {484return getURLOrDefaultInitCtx(name).createSubcontext(name);485}486487public Object lookupLink(String name) throws NamingException {488return getURLOrDefaultInitCtx(name).lookupLink(name);489}490491public Object lookupLink(Name name) throws NamingException {492return getURLOrDefaultInitCtx(name).lookupLink(name);493}494495public NameParser getNameParser(String name) throws NamingException {496return getURLOrDefaultInitCtx(name).getNameParser(name);497}498499public NameParser getNameParser(Name name) throws NamingException {500return getURLOrDefaultInitCtx(name).getNameParser(name);501}502503/**504* Composes the name of this context with a name relative to505* this context.506* Since an initial context may never be named relative507* to any context other than itself, the value of the508* {@code prefix} parameter must be an empty name ({@code ""}).509*/510public String composeName(String name, String prefix)511throws NamingException {512return name;513}514515/**516* Composes the name of this context with a name relative to517* this context.518* Since an initial context may never be named relative519* to any context other than itself, the value of the520* {@code prefix} parameter must be an empty name.521*/522public Name composeName(Name name, Name prefix)523throws NamingException524{525return (Name)name.clone();526}527528public Object addToEnvironment(String propName, Object propVal)529throws NamingException {530myProps.put(propName, propVal);531return getDefaultInitCtx().addToEnvironment(propName, propVal);532}533534public Object removeFromEnvironment(String propName)535throws NamingException {536myProps.remove(propName);537return getDefaultInitCtx().removeFromEnvironment(propName);538}539540public Hashtable<?,?> getEnvironment() throws NamingException {541return getDefaultInitCtx().getEnvironment();542}543544public void close() throws NamingException {545myProps = null;546if (defaultInitCtx != null) {547defaultInitCtx.close();548defaultInitCtx = null;549}550gotDefault = false;551}552553public String getNameInNamespace() throws NamingException {554return getDefaultInitCtx().getNameInNamespace();555}556};557558559