Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/naming/spi/NamingManager.java
38918 views
/*1* Copyright (c) 1999, 2012, 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.spi;2627import java.util.Enumeration;28import java.util.Hashtable;29import java.util.StringTokenizer;30import java.net.MalformedURLException;3132import javax.naming.*;3334import com.sun.naming.internal.ObjectFactoriesFilter;35import com.sun.naming.internal.VersionHelper;36import com.sun.naming.internal.ResourceManager;37import com.sun.naming.internal.FactoryEnumeration;3839/**40* This class contains methods for creating context objects41* and objects referred to by location information in the naming42* or directory service.43*<p>44* This class cannot be instantiated. It has only static methods.45*<p>46* The mention of URL in the documentation for this class refers to47* a URL string as defined by RFC 1738 and its related RFCs. It is48* any string that conforms to the syntax described therein, and49* may not always have corresponding support in the java.net.URL50* class or Web browsers.51*<p>52* NamingManager is safe for concurrent access by multiple threads.53*<p>54* Except as otherwise noted,55* a <tt>Name</tt> or environment parameter56* passed to any method is owned by the caller.57* The implementation will not modify the object or keep a reference58* to it, although it may keep a reference to a clone or copy.59*60* @author Rosanna Lee61* @author Scott Seligman62* @since 1.363*/6465public class NamingManager {6667/*68* Disallow anyone from creating one of these.69* Made package private so that DirectoryManager can subclass.70*/7172NamingManager() {}7374// should be protected and package private75static final VersionHelper helper = VersionHelper.getVersionHelper();7677// --------- object factory stuff7879/**80* Package-private; used by DirectoryManager and NamingManager.81*/82private static ObjectFactoryBuilder object_factory_builder = null;8384/**85* The ObjectFactoryBuilder determines the policy used when86* trying to load object factories.87* See getObjectInstance() and class ObjectFactory for a description88* of the default policy.89* setObjectFactoryBuilder() overrides this default policy by installing90* an ObjectFactoryBuilder. Subsequent object factories will91* be loaded and created using the installed builder.92*<p>93* The builder can only be installed if the executing thread is allowed94* (by the security manager's checkSetFactory() method) to do so.95* Once installed, the builder cannot be replaced.96*<p>97* @param builder The factory builder to install. If null, no builder98* is installed.99* @exception SecurityException builder cannot be installed100* for security reasons.101* @exception NamingException builder cannot be installed for102* a non-security-related reason.103* @exception IllegalStateException If a factory has already been installed.104* @see #getObjectInstance105* @see ObjectFactory106* @see ObjectFactoryBuilder107* @see java.lang.SecurityManager#checkSetFactory108*/109public static synchronized void setObjectFactoryBuilder(110ObjectFactoryBuilder builder) throws NamingException {111if (object_factory_builder != null)112throw new IllegalStateException("ObjectFactoryBuilder already set");113114SecurityManager security = System.getSecurityManager();115if (security != null) {116security.checkSetFactory();117}118object_factory_builder = builder;119}120121/**122* Used for accessing object factory builder.123*/124static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {125return object_factory_builder;126}127128129/**130* Retrieves the ObjectFactory for the object identified by a reference,131* using the reference's factory class name and factory codebase132* to load in the factory's class.133* @param ref The non-null reference to use.134* @param factoryName The non-null class name of the factory.135* @return The object factory for the object identified by ref; null136* if unable to load the factory.137*/138static ObjectFactory getObjectFactoryFromReference(139Reference ref, String factoryName)140throws IllegalAccessException,141InstantiationException,142MalformedURLException {143Class<?> clas = null;144145// Try to use current class loader146try {147clas = helper.loadClassWithoutInit(factoryName);148// Validate factory's class with the objects factory serial filter149if (!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) {150return null;151}152} catch (ClassNotFoundException e) {153// ignore and continue154// e.printStackTrace();155}156// All other exceptions are passed up.157158// Not in class path; try to use codebase159String codebase;160if (clas == null &&161(codebase = ref.getFactoryClassLocation()) != null) {162try {163clas = helper.loadClass(factoryName, codebase);164// Validate factory's class with the objects factory serial filter165if (clas == null ||166!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) {167return null;168}169} catch (ClassNotFoundException e) {170}171}172173return (clas != null) ? (ObjectFactory) clas.newInstance() : null;174}175176177/**178* Creates an object using the factories specified in the179* <tt>Context.OBJECT_FACTORIES</tt> property of the environment180* or of the provider resource file associated with <tt>nameCtx</tt>.181*182* @return factory created; null if cannot create183*/184private static Object createObjectFromFactories(Object obj, Name name,185Context nameCtx, Hashtable<?,?> environment) throws Exception {186187FactoryEnumeration factories = ResourceManager.getFactories(188Context.OBJECT_FACTORIES, environment, nameCtx);189190if (factories == null)191return null;192193// Try each factory until one succeeds194ObjectFactory factory;195Object answer = null;196while (answer == null && factories.hasMore()) {197factory = (ObjectFactory)factories.next();198answer = factory.getObjectInstance(obj, name, nameCtx, environment);199}200return answer;201}202203private static String getURLScheme(String str) {204int colon_posn = str.indexOf(':');205int slash_posn = str.indexOf('/');206207if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))208return str.substring(0, colon_posn);209return null;210}211212/**213* Creates an instance of an object for the specified object214* and environment.215* <p>216* If an object factory builder has been installed, it is used to217* create a factory for creating the object.218* Otherwise, the following rules are used to create the object:219*<ol>220* <li>If <code>refInfo</code> is a <code>Reference</code>221* or <code>Referenceable</code> containing a factory class name,222* use the named factory to create the object.223* Return <code>refInfo</code> if the factory cannot be created.224* Under JDK 1.1, if the factory class must be loaded from a location225* specified in the reference, a <tt>SecurityManager</tt> must have226* been installed or the factory creation will fail.227* If an exception is encountered while creating the factory,228* it is passed up to the caller.229* <li>If <tt>refInfo</tt> is a <tt>Reference</tt> or230* <tt>Referenceable</tt> with no factory class name,231* and the address or addresses are <tt>StringRefAddr</tt>s with232* address type "URL",233* try the URL context factory corresponding to each URL's scheme id234* to create the object (see <tt>getURLContext()</tt>).235* If that fails, continue to the next step.236* <li> Use the object factories specified in237* the <tt>Context.OBJECT_FACTORIES</tt> property of the environment,238* and of the provider resource file associated with239* <tt>nameCtx</tt>, in that order.240* The value of this property is a colon-separated list of factory241* class names that are tried in order, and the first one that succeeds242* in creating an object is the one used.243* If none of the factories can be loaded,244* return <code>refInfo</code>.245* If an exception is encountered while creating the object, the246* exception is passed up to the caller.247*</ol>248*<p>249* Service providers that implement the <tt>DirContext</tt>250* interface should use251* <tt>DirectoryManager.getObjectInstance()</tt>, not this method.252* Service providers that implement only the <tt>Context</tt>253* interface should use this method.254* <p>255* Note that an object factory (an object that implements the ObjectFactory256* interface) must be public and must have a public constructor that257* accepts no arguments.258* <p>259* The <code>name</code> and <code>nameCtx</code> parameters may260* optionally be used to specify the name of the object being created.261* <code>name</code> is the name of the object, relative to context262* <code>nameCtx</code>. This information could be useful to the object263* factory or to the object implementation.264* If there are several possible contexts from which the object265* could be named -- as will often be the case -- it is up to266* the caller to select one. A good rule of thumb is to select the267* "deepest" context available.268* If <code>nameCtx</code> is null, <code>name</code> is relative269* to the default initial context. If no name is being specified, the270* <code>name</code> parameter should be null.271*272* @param refInfo The possibly null object for which to create an object.273* @param name The name of this object relative to <code>nameCtx</code>.274* Specifying a name is optional; if it is275* omitted, <code>name</code> should be null.276* @param nameCtx The context relative to which the <code>name</code>277* parameter is specified. If null, <code>name</code> is278* relative to the default initial context.279* @param environment The possibly null environment to280* be used in the creation of the object factory and the object.281* @return An object created using <code>refInfo</code>; or282* <code>refInfo</code> if an object cannot be created using283* the algorithm described above.284* @exception NamingException if a naming exception was encountered285* while attempting to get a URL context, or if one of the286* factories accessed throws a NamingException.287* @exception Exception if one of the factories accessed throws an288* exception, or if an error was encountered while loading289* and instantiating the factory and object classes.290* A factory should only throw an exception if it does not want291* other factories to be used in an attempt to create an object.292* See ObjectFactory.getObjectInstance().293* @see #getURLContext294* @see ObjectFactory295* @see ObjectFactory#getObjectInstance296*/297public static Object298getObjectInstance(Object refInfo, Name name, Context nameCtx,299Hashtable<?,?> environment)300throws Exception301{302303ObjectFactory factory;304305// Use builder if installed306ObjectFactoryBuilder builder = getObjectFactoryBuilder();307if (builder != null) {308// builder must return non-null factory309factory = builder.createObjectFactory(refInfo, environment);310return factory.getObjectInstance(refInfo, name, nameCtx,311environment);312}313314// Use reference if possible315Reference ref = null;316if (refInfo instanceof Reference) {317ref = (Reference) refInfo;318} else if (refInfo instanceof Referenceable) {319ref = ((Referenceable)(refInfo)).getReference();320}321322Object answer;323324if (ref != null) {325String f = ref.getFactoryClassName();326if (f != null) {327// if reference identifies a factory, use exclusively328329factory = getObjectFactoryFromReference(ref, f);330if (factory != null) {331return factory.getObjectInstance(ref, name, nameCtx,332environment);333}334// No factory found, so return original refInfo.335// Will reach this point if factory class is not in336// class path and reference does not contain a URL for it337return refInfo;338339} else {340// if reference has no factory, check for addresses341// containing URLs342343answer = processURLAddrs(ref, name, nameCtx, environment);344if (answer != null) {345return answer;346}347}348}349350// try using any specified factories351answer =352createObjectFromFactories(refInfo, name, nameCtx, environment);353return (answer != null) ? answer : refInfo;354}355356/*357* Ref has no factory. For each address of type "URL", try its URL358* context factory. Returns null if unsuccessful in creating and359* invoking a factory.360*/361static Object processURLAddrs(Reference ref, Name name, Context nameCtx,362Hashtable<?,?> environment)363throws NamingException {364365for (int i = 0; i < ref.size(); i++) {366RefAddr addr = ref.get(i);367if (addr instanceof StringRefAddr &&368addr.getType().equalsIgnoreCase("URL")) {369370String url = (String)addr.getContent();371Object answer = processURL(url, name, nameCtx, environment);372if (answer != null) {373return answer;374}375}376}377return null;378}379380private static Object processURL(Object refInfo, Name name,381Context nameCtx, Hashtable<?,?> environment)382throws NamingException {383Object answer;384385// If refInfo is a URL string, try to use its URL context factory386// If no context found, continue to try object factories.387if (refInfo instanceof String) {388String url = (String)refInfo;389String scheme = getURLScheme(url);390if (scheme != null) {391answer = getURLObject(scheme, refInfo, name, nameCtx,392environment);393if (answer != null) {394return answer;395}396}397}398399// If refInfo is an array of URL strings,400// try to find a context factory for any one of its URLs.401// If no context found, continue to try object factories.402if (refInfo instanceof String[]) {403String[] urls = (String[])refInfo;404for (int i = 0; i <urls.length; i++) {405String scheme = getURLScheme(urls[i]);406if (scheme != null) {407answer = getURLObject(scheme, refInfo, name, nameCtx,408environment);409if (answer != null)410return answer;411}412}413}414return null;415}416417418/**419* Retrieves a context identified by <code>obj</code>, using the specified420* environment.421* Used by ContinuationContext.422*423* @param obj The object identifying the context.424* @param name The name of the context being returned, relative to425* <code>nameCtx</code>, or null if no name is being426* specified.427* See the <code>getObjectInstance</code> method for428* details.429* @param nameCtx The context relative to which <code>name</code> is430* specified, or null for the default initial context.431* See the <code>getObjectInstance</code> method for432* details.433* @param environment Environment specifying characteristics of the434* resulting context.435* @return A context identified by <code>obj</code>.436*437* @see #getObjectInstance438*/439static Context getContext(Object obj, Name name, Context nameCtx,440Hashtable<?,?> environment) throws NamingException {441Object answer;442443if (obj instanceof Context) {444// %%% Ignore environment for now. OK since method not public.445return (Context)obj;446}447448try {449answer = getObjectInstance(obj, name, nameCtx, environment);450} catch (NamingException e) {451throw e;452} catch (Exception e) {453NamingException ne = new NamingException();454ne.setRootCause(e);455throw ne;456}457458return (answer instanceof Context)459? (Context)answer460: null;461}462463// Used by ContinuationContext464static Resolver getResolver(Object obj, Name name, Context nameCtx,465Hashtable<?,?> environment) throws NamingException {466Object answer;467468if (obj instanceof Resolver) {469// %%% Ignore environment for now. OK since method not public.470return (Resolver)obj;471}472473try {474answer = getObjectInstance(obj, name, nameCtx, environment);475} catch (NamingException e) {476throw e;477} catch (Exception e) {478NamingException ne = new NamingException();479ne.setRootCause(e);480throw ne;481}482483return (answer instanceof Resolver)484? (Resolver)answer485: null;486}487488489/***************** URL Context implementations ***************/490491/**492* Creates a context for the given URL scheme id.493* <p>494* The resulting context is for resolving URLs of the495* scheme <code>scheme</code>. The resulting context is not tied496* to a specific URL. It is able to handle arbitrary URLs with497* the specified scheme.498*<p>499* The class name of the factory that creates the resulting context500* has the naming convention <i>scheme-id</i>URLContextFactory501* (e.g. "ftpURLContextFactory" for the "ftp" scheme-id),502* in the package specified as follows.503* The <tt>Context.URL_PKG_PREFIXES</tt> environment property (which504* may contain values taken from applet parameters, system properties,505* or application resource files)506* contains a colon-separated list of package prefixes.507* Each package prefix in508* the property is tried in the order specified to load the factory class.509* The default package prefix is "com.sun.jndi.url" (if none of the510* specified packages work, this default is tried).511* The complete package name is constructed using the package prefix,512* concatenated with the scheme id.513*<p>514* For example, if the scheme id is "ldap", and the515* <tt>Context.URL_PKG_PREFIXES</tt> property516* contains "com.widget:com.wiz.jndi",517* the naming manager would attempt to load the following classes518* until one is successfully instantiated:519*<ul>520* <li>com.widget.ldap.ldapURLContextFactory521* <li>com.wiz.jndi.ldap.ldapURLContextFactory522* <li>com.sun.jndi.url.ldap.ldapURLContextFactory523*</ul>524* If none of the package prefixes work, null is returned.525*<p>526* If a factory is instantiated, it is invoked with the following527* parameters to produce the resulting context.528* <p>529* <code>factory.getObjectInstance(null, environment);</code>530* <p>531* For example, invoking getObjectInstance() as shown above532* on a LDAP URL context factory would return a533* context that can resolve LDAP urls534* (e.g. "ldap://ldap.wiz.com/o=wiz,c=us",535* "ldap://ldap.umich.edu/o=umich,c=us", ...).536*<p>537* Note that an object factory (an object that implements the ObjectFactory538* interface) must be public and must have a public constructor that539* accepts no arguments.540*541* @param scheme The non-null scheme-id of the URLs supported by the context.542* @param environment The possibly null environment properties to be543* used in the creation of the object factory and the context.544* @return A context for resolving URLs with the545* scheme id <code>scheme</code>;546* <code>null</code> if the factory for creating the547* context is not found.548* @exception NamingException If a naming exception occurs while creating549* the context.550* @see #getObjectInstance551* @see ObjectFactory#getObjectInstance552*/553public static Context getURLContext(String scheme,554Hashtable<?,?> environment)555throws NamingException556{557// pass in 'null' to indicate creation of generic context for scheme558// (i.e. not specific to a URL).559560Object answer = getURLObject(scheme, null, null, null, environment);561if (answer instanceof Context) {562return (Context)answer;563} else {564return null;565}566}567568private static final String defaultPkgPrefix = "com.sun.jndi.url";569570/**571* Creates an object for the given URL scheme id using572* the supplied urlInfo.573* <p>574* If urlInfo is null, the result is a context for resolving URLs575* with the scheme id 'scheme'.576* If urlInfo is a URL, the result is a context named by the URL.577* Names passed to this context is assumed to be relative to this578* context (i.e. not a URL). For example, if urlInfo is579* "ldap://ldap.wiz.com/o=Wiz,c=us", the resulting context will580* be that pointed to by "o=Wiz,c=us" on the server 'ldap.wiz.com'.581* Subsequent names that can be passed to this context will be582* LDAP names relative to this context (e.g. cn="Barbs Jensen").583* If urlInfo is an array of URLs, the URLs are assumed584* to be equivalent in terms of the context to which they refer.585* The resulting context is like that of the single URL case.586* If urlInfo is of any other type, that is handled by the587* context factory for the URL scheme.588* @param scheme the URL scheme id for the context589* @param urlInfo information used to create the context590* @param name name of this object relative to <code>nameCtx</code>591* @param nameCtx Context whose provider resource file will be searched592* for package prefix values (or null if none)593* @param environment Environment properties for creating the context594* @see javax.naming.InitialContext595*/596private static Object getURLObject(String scheme, Object urlInfo,597Name name, Context nameCtx,598Hashtable<?,?> environment)599throws NamingException {600601// e.g. "ftpURLContextFactory"602ObjectFactory factory = (ObjectFactory)ResourceManager.getFactory(603Context.URL_PKG_PREFIXES, environment, nameCtx,604"." + scheme + "." + scheme + "URLContextFactory", defaultPkgPrefix);605606if (factory == null)607return null;608609// Found object factory610try {611return factory.getObjectInstance(urlInfo, name, nameCtx, environment);612} catch (NamingException e) {613throw e;614} catch (Exception e) {615NamingException ne = new NamingException();616ne.setRootCause(e);617throw ne;618}619620}621622623// ------------ Initial Context Factory Stuff624private static InitialContextFactoryBuilder initctx_factory_builder = null;625626/**627* Use this method for accessing initctx_factory_builder while628* inside an unsynchronized method.629*/630private static synchronized InitialContextFactoryBuilder631getInitialContextFactoryBuilder() {632return initctx_factory_builder;633}634635/**636* Creates an initial context using the specified environment637* properties.638*<p>639* If an InitialContextFactoryBuilder has been installed,640* it is used to create the factory for creating the initial context.641* Otherwise, the class specified in the642* <tt>Context.INITIAL_CONTEXT_FACTORY</tt> environment property is used.643* Note that an initial context factory (an object that implements the644* InitialContextFactory interface) must be public and must have a645* public constructor that accepts no arguments.646*647* @param env The possibly null environment properties used when648* creating the context.649* @return A non-null initial context.650* @exception NoInitialContextException If the651* <tt>Context.INITIAL_CONTEXT_FACTORY</tt> property652* is not found or names a nonexistent653* class or a class that cannot be instantiated,654* or if the initial context could not be created for some other655* reason.656* @exception NamingException If some other naming exception was encountered.657* @see javax.naming.InitialContext658* @see javax.naming.directory.InitialDirContext659*/660public static Context getInitialContext(Hashtable<?,?> env)661throws NamingException {662InitialContextFactory factory;663664InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder();665if (builder == null) {666// No factory installed, use property667// Get initial context factory class name668669String className = env != null ?670(String)env.get(Context.INITIAL_CONTEXT_FACTORY) : null;671if (className == null) {672NoInitialContextException ne = new NoInitialContextException(673"Need to specify class name in environment or system " +674"property, or as an applet parameter, or in an " +675"application resource file: " +676Context.INITIAL_CONTEXT_FACTORY);677throw ne;678}679680try {681factory = (InitialContextFactory)682helper.loadClass(className).newInstance();683} catch(Exception e) {684NoInitialContextException ne =685new NoInitialContextException(686"Cannot instantiate class: " + className);687ne.setRootCause(e);688throw ne;689}690} else {691factory = builder.createInitialContextFactory(env);692}693694return factory.getInitialContext(env);695}696697698/**699* Sets the InitialContextFactory builder to be builder.700*701*<p>702* The builder can only be installed if the executing thread is allowed by703* the security manager to do so. Once installed, the builder cannot704* be replaced.705* @param builder The initial context factory builder to install. If null,706* no builder is set.707* @exception SecurityException builder cannot be installed for security708* reasons.709* @exception NamingException builder cannot be installed for710* a non-security-related reason.711* @exception IllegalStateException If a builder was previous installed.712* @see #hasInitialContextFactoryBuilder713* @see java.lang.SecurityManager#checkSetFactory714*/715public static synchronized void setInitialContextFactoryBuilder(716InitialContextFactoryBuilder builder)717throws NamingException {718if (initctx_factory_builder != null)719throw new IllegalStateException(720"InitialContextFactoryBuilder already set");721722SecurityManager security = System.getSecurityManager();723if (security != null) {724security.checkSetFactory();725}726initctx_factory_builder = builder;727}728729/**730* Determines whether an initial context factory builder has731* been set.732* @return true if an initial context factory builder has733* been set; false otherwise.734* @see #setInitialContextFactoryBuilder735*/736public static boolean hasInitialContextFactoryBuilder() {737return (getInitialContextFactoryBuilder() != null);738}739740// ----- Continuation Context Stuff741742/**743* Constant that holds the name of the environment property into744* which <tt>getContinuationContext()</tt> stores the value of its745* <tt>CannotProceedException</tt> parameter.746* This property is inherited by the continuation context, and may747* be used by that context's service provider to inspect the748* fields of the exception.749*<p>750* The value of this constant is "java.naming.spi.CannotProceedException".751*752* @see #getContinuationContext753* @since 1.3754*/755public static final String CPE = "java.naming.spi.CannotProceedException";756757/**758* Creates a context in which to continue a context operation.759*<p>760* In performing an operation on a name that spans multiple761* namespaces, a context from one naming system may need to pass762* the operation on to the next naming system. The context763* implementation does this by first constructing a764* <code>CannotProceedException</code> containing information765* pinpointing how far it has proceeded. It then obtains a766* continuation context from JNDI by calling767* <code>getContinuationContext</code>. The context768* implementation should then resume the context operation by769* invoking the same operation on the continuation context, using770* the remainder of the name that has not yet been resolved.771*<p>772* Before making use of the <tt>cpe</tt> parameter, this method773* updates the environment associated with that object by setting774* the value of the property <a href="#CPE"><tt>CPE</tt></a>775* to <tt>cpe</tt>. This property will be inherited by the776* continuation context, and may be used by that context's777* service provider to inspect the fields of this exception.778*779* @param cpe780* The non-null exception that triggered this continuation.781* @return A non-null Context object for continuing the operation.782* @exception NamingException If a naming exception occurred.783*/784@SuppressWarnings("unchecked")785public static Context getContinuationContext(CannotProceedException cpe)786throws NamingException {787788Hashtable<Object,Object> env = (Hashtable<Object,Object>)cpe.getEnvironment();789if (env == null) {790env = new Hashtable<>(7);791} else {792// Make a (shallow) copy of the environment.793env = (Hashtable<Object,Object>)env.clone();794}795env.put(CPE, cpe);796797ContinuationContext cctx = new ContinuationContext(cpe, env);798return cctx.getTargetContext();799}800801// ------------ State Factory Stuff802803/**804* Retrieves the state of an object for binding.805* <p>806* Service providers that implement the <tt>DirContext</tt> interface807* should use <tt>DirectoryManager.getStateToBind()</tt>, not this method.808* Service providers that implement only the <tt>Context</tt> interface809* should use this method.810*<p>811* This method uses the specified state factories in812* the <tt>Context.STATE_FACTORIES</tt> property from the environment813* properties, and from the provider resource file associated with814* <tt>nameCtx</tt>, in that order.815* The value of this property is a colon-separated list of factory816* class names that are tried in order, and the first one that succeeds817* in returning the object's state is the one used.818* If no object's state can be retrieved in this way, return the819* object itself.820* If an exception is encountered while retrieving the state, the821* exception is passed up to the caller.822* <p>823* Note that a state factory824* (an object that implements the StateFactory825* interface) must be public and must have a public constructor that826* accepts no arguments.827* <p>828* The <code>name</code> and <code>nameCtx</code> parameters may829* optionally be used to specify the name of the object being created.830* See the description of "Name and Context Parameters" in831* {@link ObjectFactory#getObjectInstance832* ObjectFactory.getObjectInstance()}833* for details.834* <p>835* This method may return a <tt>Referenceable</tt> object. The836* service provider obtaining this object may choose to store it837* directly, or to extract its reference (using838* <tt>Referenceable.getReference()</tt>) and store that instead.839*840* @param obj The non-null object for which to get state to bind.841* @param name The name of this object relative to <code>nameCtx</code>,842* or null if no name is specified.843* @param nameCtx The context relative to which the <code>name</code>844* parameter is specified, or null if <code>name</code> is845* relative to the default initial context.846* @param environment The possibly null environment to847* be used in the creation of the state factory and848* the object's state.849* @return The non-null object representing <tt>obj</tt>'s state for850* binding. It could be the object (<tt>obj</tt>) itself.851* @exception NamingException If one of the factories accessed throws an852* exception, or if an error was encountered while loading853* and instantiating the factory and object classes.854* A factory should only throw an exception if it does not want855* other factories to be used in an attempt to create an object.856* See <tt>StateFactory.getStateToBind()</tt>.857* @see StateFactory858* @see StateFactory#getStateToBind859* @see DirectoryManager#getStateToBind860* @since 1.3861*/862public static Object863getStateToBind(Object obj, Name name, Context nameCtx,864Hashtable<?,?> environment)865throws NamingException866{867868FactoryEnumeration factories = ResourceManager.getFactories(869Context.STATE_FACTORIES, environment, nameCtx);870871if (factories == null) {872return obj;873}874875// Try each factory until one succeeds876StateFactory factory;877Object answer = null;878while (answer == null && factories.hasMore()) {879factory = (StateFactory)factories.next();880answer = factory.getStateToBind(obj, name, nameCtx, environment);881}882883return (answer != null) ? answer : obj;884}885}886887888