blob: 114ac6cfdde44fe074bbb29a98da98421bac7ca2 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.jndi.rmi.registry;
27
28
29import java.util.Enumeration;
30import java.util.Hashtable;
31
32import javax.naming.*;
33import javax.naming.spi.*;
34
35import 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
56public 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 addrs = ref.getAll();
156 while (addrs.hasMoreElements()) {
157 RefAddr addr = (RefAddr)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}