1 /* 2 * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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.rmi.registry; 27 28 29 import java.util.Enumeration; 30 import java.util.Hashtable; 31 32 import javax.naming.*; 33 import javax.naming.spi.*; 34 35 import com.sun.jndi.url.rmi.rmiURLContextFactory; 36 37 /** 38 * A RegistryContextFactory takes an RMI registry reference, and 39 * creates the corresponding RMI object or registry context. In 40 * addition, it serves as the initial context factory when using an 41 * RMI registry as an initial context. 42 *<p> 43 * When an initial context is being created, the environment 44 * property "java.naming.provider.url" should contain the RMI URL of 45 * the appropriate registry. Otherwise, the default URL "rmi:" is used. 46 *<p> 47 * An RMI registry reference contains one or more StringRefAddrs of 48 * type "URL", each containing a single RMI URL. Other addresses 49 * are ignored. Multiple URLs represent alternative addresses for the 50 * same logical resource. The order of the addresses is not significant. 51 * 52 * @author Scott Seligman 53 */ 54 55 56 public class RegistryContextFactory 57 implements ObjectFactory, InitialContextFactory 58 { 59 /** 60 * The type of each address in an RMI registry reference. 61 */ 62 public final static String ADDRESS_TYPE = "URL"; 63 64 public Context getInitialContext(Hashtable<?,?> env) throws NamingException { 65 66 if (env != null) { 67 env = (Hashtable) env.clone(); 68 } 69 return URLToContext(getInitCtxURL(env), env); 70 } 71 72 public Object getObjectInstance(Object ref, Name name, Context nameCtx, 73 Hashtable<?,?> env) 74 throws NamingException 75 { 76 if (!isRegistryRef(ref)) { 77 return null; 78 } 79 /* 80 * No need to clone env here. If getObjectInstance() 81 * returns something other than a RegistryContext (which 82 * happens if you're looking up an object bound in the 83 * registry, as opposed to looking up the registry itself), 84 * then the context is GCed right away and there's no need to 85 * clone the environment. If getObjectInstance() returns a 86 * RegistryContext, then it still goes through 87 * GenericURLContext, which calls RegistryContext.lookup() 88 * with an empty name, which clones the environment. 89 */ 90 Object obj = URLsToObject(getURLs((Reference)ref), env); 91 if (obj instanceof RegistryContext) { 92 RegistryContext ctx = (RegistryContext)obj; 93 ctx.reference = (Reference)ref; 94 } 95 return obj; 96 } 97 98 private static Context URLToContext(String url, Hashtable<?,?> env) 99 throws NamingException 100 { 101 rmiURLContextFactory factory = new rmiURLContextFactory(); 102 Object obj = factory.getObjectInstance(url, null, null, env); 103 104 if (obj instanceof Context) { 105 return (Context)obj; 106 } else { 107 throw (new NotContextException(url)); 108 } 109 } 110 111 private static Object URLsToObject(String[] urls, Hashtable<?,?> env) 112 throws NamingException 113 { 114 rmiURLContextFactory factory = new rmiURLContextFactory(); 115 return factory.getObjectInstance(urls, null, null, env); 116 } 117 118 /** 119 * Reads environment to find URL of initial context. 120 * The default URL is "rmi:". 121 */ 122 private static String getInitCtxURL(Hashtable<?,?> env) { 123 124 final String defaultURL = "rmi:"; 125 126 String url = null; 127 if (env != null) { 128 url = (String)env.get(Context.PROVIDER_URL); 129 } 130 return ((url != null) ? url : defaultURL); 131 } 132 133 /** 134 * Returns true if argument is an RMI registry reference. 135 */ 136 private static boolean isRegistryRef(Object obj) { 137 138 if (!(obj instanceof Reference)) { 139 return false; 140 } 141 String thisClassName = RegistryContextFactory.class.getName(); 142 Reference ref = (Reference)obj; 143 144 return thisClassName.equals(ref.getFactoryClassName()); 145 } 146 147 /** 148 * Returns the URLs contained within an RMI registry reference. 149 */ 150 private static String[] getURLs(Reference ref) throws NamingException { 151 152 int size = 0; // number of URLs 153 String[] urls = new String[ref.size()]; 154 155 Enumeration<RefAddr> addrs = ref.getAll(); 156 while (addrs.hasMoreElements()) { 157 RefAddr addr = addrs.nextElement(); 158 159 if ((addr instanceof StringRefAddr) && 160 addr.getType().equals(ADDRESS_TYPE)) { 161 162 urls[size++] = (String)addr.getContent(); 163 } 164 } 165 if (size == 0) { 166 throw (new ConfigurationException( 167 "Reference contains no valid addresses")); 168 } 169 170 // Trim URL array down to size. 171 if (size == ref.size()) { 172 return urls; 173 } 174 String[] urls2 = new String[size]; 175 System.arraycopy(urls, 0, urls2, 0, size); 176 return urls2; 177 } 178 }