/* * 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> 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> 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> 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 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. *

* 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; }