8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.ldap; 27 28 import java.util.Hashtable; 29 import java.util.Vector; 30 import java.util.Enumeration; 31 32 import javax.naming.*; 33 import javax.naming.directory.*; 34 import javax.naming.spi.ObjectFactory; 35 import javax.naming.spi.InitialContextFactory; 36 import javax.naming.ldap.Control; 37 38 import com.sun.jndi.url.ldap.ldapURLContextFactory; 39 40 final public class LdapCtxFactory implements ObjectFactory, InitialContextFactory { 41 /** 42 * The type of each address in an LDAP reference. 43 */ 44 public final static String ADDRESS_TYPE = "URL"; 45 46 // ----------------- ObjectFactory interface -------------------- 47 48 public Object getObjectInstance(Object ref, Name name, Context nameCtx, 49 Hashtable<?,?> env) throws Exception { 50 51 if (!isLdapRef(ref)) { 52 return null; 53 } 141 System.arraycopy(urls, 0, urls2, 0, size); 142 return urls2; 143 } 144 145 // ------------ Utilities used by other classes ---------------- 146 147 public static DirContext getLdapCtxInstance(Object urlInfo, Hashtable<?,?> env) 148 throws NamingException { 149 150 if (urlInfo instanceof String) { 151 return getUsingURL((String)urlInfo, env); 152 } else if (urlInfo instanceof String[]) { 153 return getUsingURLs((String[])urlInfo, env); 154 } else { 155 throw new IllegalArgumentException( 156 "argument must be an LDAP URL String or array of them"); 157 } 158 } 159 160 private static DirContext getUsingURL(String url, Hashtable<?,?> env) 161 throws NamingException { 162 DirContext ctx = null; 163 LdapURL ldapUrl = new LdapURL(url); 164 String dn = ldapUrl.getDN(); 165 String host = ldapUrl.getHost(); 166 int port = ldapUrl.getPort(); 167 String[] hostports; 168 String domainName = null; 169 170 // handle a URL with no hostport (ldap:/// or ldaps:///) 171 // locate the LDAP service using the URL's distinguished name 172 if (host == null && 173 port == -1 && 174 dn != null && 175 (domainName = ServiceLocator.mapDnToDomainName(dn)) != null && 176 (hostports = ServiceLocator.getLdapService(domainName, env)) 177 != null) { 178 // Generate new URLs that include the discovered hostports. 179 // Reuse the original URL scheme. 180 String scheme = ldapUrl.getScheme() + "://"; 181 String[] newUrls = new String[hostports.length]; 182 String query = ldapUrl.getQuery(); 183 String urlSuffix = ldapUrl.getPath() + (query != null ? query : ""); 184 for (int i = 0; i < hostports.length; i++) { 185 newUrls[i] = scheme + hostports[i] + urlSuffix; 186 } 187 ctx = getUsingURLs(newUrls, env); 188 // Associate the derived domain name with the context 189 ((LdapCtx)ctx).setDomainName(domainName); 190 191 } else { 192 ctx = new LdapCtx(dn, host, port, env, ldapUrl.useSsl()); 193 // Record the URL that created the context 194 ((LdapCtx)ctx).setProviderUrl(url); 195 } 196 return ctx; 197 } 198 199 /* 200 * Try each URL until one of them succeeds. 201 * If all URLs fail, throw one of the exceptions arbitrarily. 202 * Not pretty, but potentially more informative than returning null. 203 */ 204 private static DirContext getUsingURLs(String[] urls, Hashtable<?,?> env) 205 throws NamingException { 206 NamingException ne = null; 207 DirContext ctx = null; 208 for (int i = 0; i < urls.length; i++) { 209 try { 210 return getUsingURL(urls[i], env); 211 } catch (AuthenticationException e) { 212 throw e; 213 } catch (NamingException e) { 214 ne = e; 215 } 216 } 217 throw ne; 218 } 219 220 /** 221 * Used by Obj and obj/RemoteToAttrs too so must be public 222 */ 223 public static Attribute createTypeNameAttr(Class<?> cl) { 224 Vector<String> v = new Vector<>(10); 225 String[] types = getTypeNames(cl, v); 226 if (types.length > 0) { 227 BasicAttribute tAttr = 228 new BasicAttribute(Obj.JAVA_ATTRIBUTES[Obj.TYPENAME]); 229 for (int i = 0; i < types.length; i++) { 230 tAttr.add(types[i]); 231 } 232 return tAttr; 233 } 234 return null; 235 } 236 237 private static String[] getTypeNames(Class<?> currentClass, Vector<String> v) { | 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.ldap; 27 28 import java.util.*; 29 30 import javax.naming.*; 31 import javax.naming.directory.*; 32 import javax.naming.ldap.LdapDnsProviderResult; 33 import javax.naming.spi.ObjectFactory; 34 import javax.naming.spi.InitialContextFactory; 35 import javax.naming.ldap.Control; 36 37 import com.sun.jndi.url.ldap.ldapURLContextFactory; 38 39 final public class LdapCtxFactory implements ObjectFactory, InitialContextFactory { 40 /** 41 * The type of each address in an LDAP reference. 42 */ 43 public final static String ADDRESS_TYPE = "URL"; 44 45 // ----------------- ObjectFactory interface -------------------- 46 47 public Object getObjectInstance(Object ref, Name name, Context nameCtx, 48 Hashtable<?,?> env) throws Exception { 49 50 if (!isLdapRef(ref)) { 51 return null; 52 } 140 System.arraycopy(urls, 0, urls2, 0, size); 141 return urls2; 142 } 143 144 // ------------ Utilities used by other classes ---------------- 145 146 public static DirContext getLdapCtxInstance(Object urlInfo, Hashtable<?,?> env) 147 throws NamingException { 148 149 if (urlInfo instanceof String) { 150 return getUsingURL((String)urlInfo, env); 151 } else if (urlInfo instanceof String[]) { 152 return getUsingURLs((String[])urlInfo, env); 153 } else { 154 throw new IllegalArgumentException( 155 "argument must be an LDAP URL String or array of them"); 156 } 157 } 158 159 private static DirContext getUsingURL(String url, Hashtable<?,?> env) 160 throws NamingException 161 { 162 try { 163 LdapDnsProviderResult r = 164 LdapDnsProviderService.getInstance().lookupEndpoints(url, env); 165 LdapCtx ctx = null; 166 NamingException lastException = null; 167 168 /* 169 * Prior to this change we had been assuming that the url.getDN() 170 * should be converted to a domain name via 171 * ServiceLocator.mapDnToDomainName(url.getDN()) 172 * 173 * However this is incorrect as we can't assume that the supplied 174 * url.getDN() is the same as the dns domain for the directory 175 * server. 176 * 177 * This means that we depend on the dnsProvider to return both 178 * the list of urls of individual hosts from which we attempt to 179 * create an LdapCtx from *AND* the domain name that they serve 180 * 181 * In order to do this the dnsProvider must return an 182 * {@link LdapDnsProviderResult}. 183 * 184 */ 185 for (String u : r.getEndpoints()) { 186 try { 187 ctx = getLdapCtxFromUrl( 188 r.getDomainName(), new LdapURL(u), env); 189 } catch (NamingException e) { 190 // try the next element 191 lastException = e; 192 } 193 } 194 195 if (lastException != null) { 196 throw lastException; 197 } 198 199 if (ctx == null) { 200 // we have resolved them, but they are not valid 201 throw new NamingException("Could not resolve a valid ldap host"); 202 } 203 204 // Record the URL that created the context 205 ctx.setProviderUrl(url); 206 return ctx; 207 } catch (NamingException e) { 208 // getDnsUrls(url, env) may throw a NamingException, which there is 209 // no need to wrap. 210 throw e; 211 } catch (Exception e) { 212 NamingException ex = new NamingException(); 213 ex.setRootCause(e); 214 throw ex; 215 } 216 } 217 218 private static LdapCtx getLdapCtxFromUrl(String domain, 219 LdapURL url, 220 Hashtable<?,?> env) 221 throws NamingException 222 { 223 String dn = url.getDN(); 224 String host = url.getHost(); 225 int port = url.getPort(); 226 LdapCtx ctx = new LdapCtx(dn, host, port, env, url.useSsl()); 227 ctx.setDomainName(domain); 228 return ctx; 229 } 230 231 /* 232 * Try each URL until one of them succeeds. 233 * If all URLs fail, throw one of the exceptions arbitrarily. 234 * Not pretty, but potentially more informative than returning null. 235 */ 236 private static DirContext getUsingURLs(String[] urls, Hashtable<?,?> env) 237 throws NamingException 238 { 239 NamingException ex = null; 240 for (String u : urls) { 241 try { 242 return getUsingURL(u, env); 243 } catch (NamingException e) { 244 ex = e; 245 } 246 } 247 throw ex; 248 } 249 250 /** 251 * Used by Obj and obj/RemoteToAttrs too so must be public 252 */ 253 public static Attribute createTypeNameAttr(Class<?> cl) { 254 Vector<String> v = new Vector<>(10); 255 String[] types = getTypeNames(cl, v); 256 if (types.length > 0) { 257 BasicAttribute tAttr = 258 new BasicAttribute(Obj.JAVA_ATTRIBUTES[Obj.TYPENAME]); 259 for (int i = 0; i < types.length; i++) { 260 tAttr.add(types[i]); 261 } 262 return tAttr; 263 } 264 return null; 265 } 266 267 private static String[] getTypeNames(Class<?> currentClass, Vector<String> v) { |