mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-29 12:38:24 +00:00
400 lines
16 KiB
Java
400 lines
16 KiB
Java
/*
|
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package com.sun.naming.internal;
|
|
|
|
import javax.naming.Context;
|
|
import javax.naming.Name;
|
|
import javax.naming.NamingException;
|
|
import javax.naming.RefAddr;
|
|
import javax.naming.Reference;
|
|
import javax.naming.Referenceable;
|
|
import javax.naming.StringRefAddr;
|
|
import javax.naming.directory.Attributes;
|
|
import javax.naming.spi.DirObjectFactory;
|
|
import javax.naming.spi.ObjectFactory;
|
|
import javax.naming.spi.ObjectFactoryBuilder;
|
|
import java.net.MalformedURLException;
|
|
import java.util.Hashtable;
|
|
import java.util.function.Predicate;
|
|
|
|
public class NamingManagerHelper {
|
|
|
|
public static Object getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
|
Hashtable<?,?> environment,
|
|
Predicate<Class<?>> factoryFilter) throws Exception {
|
|
ObjectFactory factory;
|
|
|
|
// Use builder if installed
|
|
ObjectFactoryBuilder builder = getObjectFactoryBuilder();
|
|
if (builder != null) {
|
|
// builder must return non-null factory
|
|
factory = builder.createObjectFactory(refInfo, environment);
|
|
return factory.getObjectInstance(refInfo, name, nameCtx,
|
|
environment);
|
|
}
|
|
|
|
// Use reference if possible
|
|
Reference ref = null;
|
|
if (refInfo instanceof Reference) {
|
|
ref = (Reference) refInfo;
|
|
} else if (refInfo instanceof Referenceable) {
|
|
ref = ((Referenceable)(refInfo)).getReference();
|
|
}
|
|
|
|
Object answer;
|
|
|
|
if (ref != null) {
|
|
String f = ref.getFactoryClassName();
|
|
if (f != null) {
|
|
// if reference identifies a factory, use exclusively
|
|
|
|
factory = getObjectFactoryFromReference(ref, f, factoryFilter);
|
|
if (factory != null) {
|
|
return factory.getObjectInstance(ref, name, nameCtx,
|
|
environment);
|
|
}
|
|
// No factory found, so return original refInfo.
|
|
// That could happen if:
|
|
// - a factory class is not in a class path and reference does
|
|
// not contain a URL for it
|
|
// - a factory class is available but object factory filters
|
|
// disallow its usage
|
|
return refInfo;
|
|
|
|
} else {
|
|
// if reference has no factory, check for addresses
|
|
// containing URLs
|
|
|
|
answer = processURLAddrs(ref, name, nameCtx, environment);
|
|
if (answer != null) {
|
|
return answer;
|
|
}
|
|
}
|
|
}
|
|
|
|
// try using any specified factories
|
|
answer =
|
|
createObjectFromFactories(refInfo, name, nameCtx, environment);
|
|
return (answer != null) ? answer : refInfo;
|
|
}
|
|
|
|
|
|
public static Object getDirObjectInstance(Object refInfo, Name name, Context nameCtx,
|
|
Hashtable<?,?> environment, Attributes attrs,
|
|
Predicate<Class<?>> factoryFilter) throws Exception {
|
|
ObjectFactory factory;
|
|
|
|
ObjectFactoryBuilder builder = getObjectFactoryBuilder();
|
|
if (builder != null) {
|
|
// builder must return non-null factory
|
|
factory = builder.createObjectFactory(refInfo, environment);
|
|
if (factory instanceof DirObjectFactory) {
|
|
return ((DirObjectFactory)factory).getObjectInstance(
|
|
refInfo, name, nameCtx, environment, attrs);
|
|
} else {
|
|
return factory.getObjectInstance(refInfo, name, nameCtx,
|
|
environment);
|
|
}
|
|
}
|
|
|
|
// use reference if possible
|
|
Reference ref = null;
|
|
if (refInfo instanceof Reference) {
|
|
ref = (Reference) refInfo;
|
|
} else if (refInfo instanceof Referenceable) {
|
|
ref = ((Referenceable)(refInfo)).getReference();
|
|
}
|
|
|
|
Object answer;
|
|
|
|
if (ref != null) {
|
|
String f = ref.getFactoryClassName();
|
|
if (f != null) {
|
|
// if reference identifies a factory, use exclusively
|
|
|
|
factory = getObjectFactoryFromReference(ref, f, factoryFilter);
|
|
if (factory instanceof DirObjectFactory) {
|
|
return ((DirObjectFactory)factory).getObjectInstance(
|
|
ref, name, nameCtx, environment, attrs);
|
|
} else if (factory != null) {
|
|
return factory.getObjectInstance(ref, name, nameCtx,
|
|
environment);
|
|
}
|
|
// No factory found, so return original refInfo.
|
|
// That could happen if:
|
|
// - a factory class is not in a class path and reference does
|
|
// not contain a URL for it
|
|
// - a factory class is available but object factory filters
|
|
// disallow its usage
|
|
return refInfo;
|
|
|
|
} else {
|
|
// if reference has no factory, check for addresses
|
|
// containing URLs
|
|
// ignore name & attrs params; not used in URL factory
|
|
// RMI references from '
|
|
answer = processURLAddrs(ref, name, nameCtx, environment);
|
|
if (answer != null) {
|
|
return answer;
|
|
}
|
|
}
|
|
}
|
|
|
|
// try using any specified factories
|
|
answer = createObjectFromFactories(refInfo, name, nameCtx,
|
|
environment, attrs);
|
|
return (answer != null) ? answer : refInfo;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the ObjectFactory for the object identified by a reference,
|
|
* using the reference's factory class name and factory codebase
|
|
* to load in the factory's class.
|
|
* @param ref The non-null reference to use.
|
|
* @param factoryName The non-null class name of the factory.
|
|
* @return The object factory for the object identified by ref; null
|
|
* if unable to load the factory.
|
|
*/
|
|
static ObjectFactory getObjectFactoryFromReference(
|
|
Reference ref, String factoryName, Predicate<Class<?>> filter)
|
|
throws IllegalAccessException,
|
|
InstantiationException {
|
|
Class<?> clas;
|
|
|
|
// Try to use current class loader
|
|
try {
|
|
clas = helper.loadClassWithoutInit(factoryName);
|
|
// Validate factory's class with the objects factory serial filter
|
|
if (!filter.test(clas)) {
|
|
return null;
|
|
}
|
|
} catch (ClassNotFoundException e) {
|
|
return null;
|
|
}
|
|
assert clas != null;
|
|
@SuppressWarnings("deprecation") // Class.newInstance
|
|
ObjectFactory result = (ObjectFactory) clas.newInstance();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an object using the factories specified in the
|
|
* {@code Context.OBJECT_FACTORIES} property of the environment
|
|
* or of the provider resource file associated with {@code nameCtx}.
|
|
*
|
|
* @return factory created; null if cannot create
|
|
*/
|
|
private static Object createObjectFromFactories(Object obj, Name name,
|
|
Context nameCtx, Hashtable<?,?> environment, Attributes attrs)
|
|
throws Exception {
|
|
|
|
FactoryEnumeration factories = ResourceManager.getFactories(
|
|
Context.OBJECT_FACTORIES, environment, nameCtx);
|
|
|
|
if (factories == null)
|
|
return null;
|
|
|
|
ObjectFactory factory;
|
|
Object answer = null;
|
|
// Try each factory until one succeeds
|
|
while (answer == null && factories.hasMore()) {
|
|
factory = (ObjectFactory)factories.next();
|
|
if (factory instanceof DirObjectFactory) {
|
|
answer = ((DirObjectFactory)factory).
|
|
getObjectInstance(obj, name, nameCtx, environment, attrs);
|
|
} else {
|
|
answer =
|
|
factory.getObjectInstance(obj, name, nameCtx, environment);
|
|
}
|
|
}
|
|
return answer;
|
|
}
|
|
|
|
/*
|
|
* Ref has no factory. For each address of type "URL", try its URL
|
|
* context factory. Returns null if unsuccessful in creating and
|
|
* invoking a factory.
|
|
*/
|
|
static Object processURLAddrs(Reference ref, Name name, Context nameCtx,
|
|
Hashtable<?,?> environment)
|
|
throws NamingException {
|
|
|
|
for (int i = 0; i < ref.size(); i++) {
|
|
RefAddr addr = ref.get(i);
|
|
if (addr instanceof StringRefAddr &&
|
|
addr.getType().equalsIgnoreCase("URL")) {
|
|
|
|
String url = (String)addr.getContent();
|
|
Object answer = processURL(url, name, nameCtx, environment);
|
|
if (answer != null) {
|
|
return answer;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static Object processURL(Object refInfo, Name name,
|
|
Context nameCtx, Hashtable<?,?> environment)
|
|
throws NamingException {
|
|
Object answer;
|
|
|
|
// If refInfo is a URL string, try to use its URL context factory
|
|
// If no context found, continue to try object factories.
|
|
if (refInfo instanceof String) {
|
|
String url = (String)refInfo;
|
|
String scheme = getURLScheme(url);
|
|
if (scheme != null) {
|
|
answer = getURLObject(scheme, refInfo, name, nameCtx,
|
|
environment);
|
|
if (answer != null) {
|
|
return answer;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If refInfo is an array of URL strings,
|
|
// try to find a context factory for any one of its URLs.
|
|
// If no context found, continue to try object factories.
|
|
if (refInfo instanceof String[]) {
|
|
String[] urls = (String[])refInfo;
|
|
for (int i = 0; i <urls.length; i++) {
|
|
String scheme = getURLScheme(urls[i]);
|
|
if (scheme != null) {
|
|
answer = getURLObject(scheme, refInfo, name, nameCtx,
|
|
environment);
|
|
if (answer != null)
|
|
return answer;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static String getURLScheme(String str) {
|
|
int colon_posn = str.indexOf(':');
|
|
int slash_posn = str.indexOf('/');
|
|
|
|
if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
|
|
return str.substring(0, colon_posn);
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Creates an object for the given URL scheme id using
|
|
* the supplied urlInfo.
|
|
* <p>
|
|
* If urlInfo is null, the result is a context for resolving URLs
|
|
* with the scheme id 'scheme'.
|
|
* If urlInfo is a URL, the result is a context named by the URL.
|
|
* Names passed to this context is assumed to be relative to this
|
|
* context (i.e. not a URL). For example, if urlInfo is
|
|
* "ldap://ldap.wiz.com/o=Wiz,c=us", the resulting context will
|
|
* be that pointed to by "o=Wiz,c=us" on the server 'ldap.wiz.com'.
|
|
* Subsequent names that can be passed to this context will be
|
|
* LDAP names relative to this context (e.g. cn="Barbs Jensen").
|
|
* If urlInfo is an array of URLs, the URLs are assumed
|
|
* to be equivalent in terms of the context to which they refer.
|
|
* The resulting context is like that of the single URL case.
|
|
* If urlInfo is of any other type, that is handled by the
|
|
* context factory for the URL scheme.
|
|
* @param scheme the URL scheme id for the context
|
|
* @param urlInfo information used to create the context
|
|
* @param name name of this object relative to {@code nameCtx}
|
|
* @param nameCtx Context whose provider resource file will be searched
|
|
* for package prefix values (or null if none)
|
|
* @param environment Environment properties for creating the context
|
|
* @see javax.naming.InitialContext
|
|
*/
|
|
private static Object getURLObject(String scheme, Object urlInfo,
|
|
Name name, Context nameCtx,
|
|
Hashtable<?,?> environment)
|
|
throws NamingException {
|
|
|
|
// e.g. "ftpURLContextFactory"
|
|
ObjectFactory factory = (ObjectFactory)ResourceManager.getFactory(
|
|
Context.URL_PKG_PREFIXES, environment, nameCtx,
|
|
"." + scheme + "." + scheme + "URLContextFactory", DEFAULT_PKG_PREFIX);
|
|
|
|
if (factory == null)
|
|
return null;
|
|
|
|
// Found object factory
|
|
try {
|
|
return factory.getObjectInstance(urlInfo, name, nameCtx, environment);
|
|
} catch (NamingException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
NamingException ne = new NamingException();
|
|
ne.setRootCause(e);
|
|
throw ne;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates an object using the factories specified in the
|
|
* {@code Context.OBJECT_FACTORIES} property of the environment
|
|
* or of the provider resource file associated with {@code nameCtx}.
|
|
*
|
|
* @return factory created; null if cannot create
|
|
*/
|
|
private static Object createObjectFromFactories(Object obj, Name name,
|
|
Context nameCtx, Hashtable<?,?> environment) throws Exception {
|
|
|
|
FactoryEnumeration factories = ResourceManager.getFactories(
|
|
Context.OBJECT_FACTORIES, environment, nameCtx);
|
|
|
|
if (factories == null)
|
|
return null;
|
|
|
|
// Try each factory until one succeeds
|
|
ObjectFactory factory;
|
|
Object answer = null;
|
|
while (answer == null && factories.hasMore()) {
|
|
factory = (ObjectFactory)factories.next();
|
|
answer = factory.getObjectInstance(obj, name, nameCtx, environment);
|
|
}
|
|
return answer;
|
|
}
|
|
|
|
public static synchronized void setObjectFactoryBuilder(
|
|
ObjectFactoryBuilder builder) throws NamingException {
|
|
if (object_factory_builder != null)
|
|
throw new IllegalStateException("ObjectFactoryBuilder already set");
|
|
object_factory_builder = builder;
|
|
}
|
|
|
|
public static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {
|
|
return object_factory_builder;
|
|
}
|
|
|
|
private static final String DEFAULT_PKG_PREFIX = "com.sun.jndi.url";
|
|
static final VersionHelper helper = VersionHelper.getVersionHelper();
|
|
|
|
private static ObjectFactoryBuilder object_factory_builder = null;
|
|
|
|
}
|