author | prappo |
Fri, 01 Aug 2014 22:32:51 +0100 | |
changeset 25808 | e113d0a0fde0 |
parent 23010 | 6dadb192ad81 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
21278
diff
changeset
|
2 |
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
package com.sun.jndi.ldap; |
|
27 |
||
28 |
import javax.naming.*; |
|
29 |
import javax.naming.directory.*; |
|
30 |
import javax.naming.spi.*; |
|
31 |
import javax.naming.event.*; |
|
32 |
import javax.naming.ldap.*; |
|
33 |
import javax.naming.ldap.LdapName; |
|
34 |
import javax.naming.ldap.Rdn; |
|
35 |
||
10369
e9d2e59e53f0
7059542: JNDI name operations should be locale independent
xuelei
parents:
10324
diff
changeset
|
36 |
import java.util.Locale; |
2 | 37 |
import java.util.Vector; |
38 |
import java.util.Hashtable; |
|
39 |
import java.util.List; |
|
40 |
import java.util.StringTokenizer; |
|
41 |
import java.util.Enumeration; |
|
42 |
||
43 |
import java.io.IOException; |
|
44 |
import java.io.OutputStream; |
|
45 |
||
46 |
import com.sun.jndi.toolkit.ctx.*; |
|
47 |
import com.sun.jndi.toolkit.dir.HierMemDirCtx; |
|
48 |
import com.sun.jndi.toolkit.dir.SearchFilter; |
|
49 |
import com.sun.jndi.ldap.ext.StartTlsResponseImpl; |
|
50 |
||
51 |
/** |
|
52 |
* The LDAP context implementation. |
|
53 |
* |
|
54 |
* Implementation is not thread-safe. Caller must sync as per JNDI spec. |
|
55 |
* Members that are used directly or indirectly by internal worker threads |
|
56 |
* (Connection, EventQueue, NamingEventNotifier) must be thread-safe. |
|
57 |
* Connection - calls LdapClient.processUnsolicited(), which in turn calls |
|
58 |
* LdapCtx.convertControls() and LdapCtx.fireUnsolicited(). |
|
59 |
* convertControls() - no sync; reads envprops and 'this' |
|
60 |
* fireUnsolicited() - sync on eventSupport for all references to 'unsolicited' |
|
61 |
* (even those in other methods); don't sync on LdapCtx in case caller |
|
62 |
* is already sync'ing on it - this would prevent Unsol events from firing |
|
63 |
* and the Connection thread to block (thus preventing any other data |
|
64 |
* from being read from the connection) |
|
65 |
* References to 'eventSupport' need not be sync'ed because these |
|
66 |
* methods can only be called after eventSupport has been set first |
|
67 |
* (via addNamingListener()). |
|
68 |
* EventQueue - no direct or indirect calls to LdapCtx |
|
69 |
* NamingEventNotifier - calls newInstance() to get instance for run() to use; |
|
70 |
* no sync needed for methods invoked on new instance; |
|
71 |
* |
|
72 |
* LdapAttribute links to LdapCtx in order to process getAttributeDefinition() |
|
73 |
* and getAttributeSyntaxDefinition() calls. It invokes LdapCtx.getSchema(), |
|
74 |
* which uses schemaTrees (a Hashtable - already sync). Potential conflict |
|
75 |
* of duplicating construction of tree for same subschemasubentry |
|
76 |
* but no inconsistency problems. |
|
77 |
* |
|
78 |
* NamingEnumerations link to LdapCtx for the following: |
|
79 |
* 1. increment/decrement enum count so that ctx doesn't close the |
|
80 |
* underlying connection |
|
81 |
* 2. LdapClient handle to get next batch of results |
|
82 |
* 3. Sets LdapCtx's response controls |
|
83 |
* 4. Process return code |
|
84 |
* 5. For narrowing response controls (using ctx's factories) |
|
85 |
* Since processing of NamingEnumeration by client is treated the same as method |
|
86 |
* invocation on LdapCtx, caller is responsible for locking. |
|
87 |
* |
|
88 |
* @author Vincent Ryan |
|
89 |
* @author Rosanna Lee |
|
90 |
*/ |
|
91 |
||
92 |
final public class LdapCtx extends ComponentDirContext |
|
93 |
implements EventDirContext, LdapContext { |
|
94 |
||
95 |
/* |
|
96 |
* Used to store arguments to the search method. |
|
97 |
*/ |
|
98 |
final static class SearchArgs { |
|
99 |
Name name; |
|
100 |
String filter; |
|
101 |
SearchControls cons; |
|
102 |
String[] reqAttrs; // those attributes originally requested |
|
103 |
||
104 |
SearchArgs(Name name, String filter, SearchControls cons, String[] ra) { |
|
105 |
this.name = name; |
|
106 |
this.filter = filter; |
|
107 |
this.cons = cons; |
|
108 |
this.reqAttrs = ra; |
|
109 |
} |
|
110 |
} |
|
111 |
||
112 |
private static final boolean debug = false; |
|
113 |
||
114 |
private static final boolean HARD_CLOSE = true; |
|
115 |
private static final boolean SOFT_CLOSE = false; |
|
116 |
||
117 |
// ----------------- Constants ----------------- |
|
118 |
||
119 |
public static final int DEFAULT_PORT = 389; |
|
120 |
public static final int DEFAULT_SSL_PORT = 636; |
|
121 |
public static final String DEFAULT_HOST = "localhost"; |
|
122 |
||
123 |
private static final boolean DEFAULT_DELETE_RDN = true; |
|
124 |
private static final boolean DEFAULT_TYPES_ONLY = false; |
|
125 |
private static final int DEFAULT_DEREF_ALIASES = 3; // always deref |
|
126 |
private static final int DEFAULT_LDAP_VERSION = LdapClient.LDAP_VERSION3_VERSION2; |
|
127 |
private static final int DEFAULT_BATCH_SIZE = 1; |
|
128 |
private static final int DEFAULT_REFERRAL_MODE = LdapClient.LDAP_REF_IGNORE; |
|
129 |
private static final char DEFAULT_REF_SEPARATOR = '#'; |
|
130 |
||
131 |
// Used by LdapPoolManager |
|
132 |
static final String DEFAULT_SSL_FACTORY = |
|
133 |
"javax.net.ssl.SSLSocketFactory"; // use Sun's SSL |
|
134 |
private static final int DEFAULT_REFERRAL_LIMIT = 10; |
|
135 |
private static final String STARTTLS_REQ_OID = "1.3.6.1.4.1.1466.20037"; |
|
136 |
||
137 |
// schema operational and user attributes |
|
138 |
private static final String[] SCHEMA_ATTRIBUTES = |
|
139 |
{ "objectClasses", "attributeTypes", "matchingRules", "ldapSyntaxes" }; |
|
140 |
||
141 |
// --------------- Environment property names ---------- |
|
142 |
||
143 |
// LDAP protocol version: "2", "3" |
|
144 |
private static final String VERSION = "java.naming.ldap.version"; |
|
145 |
||
146 |
// Binary-valued attributes. Space separated string of attribute names. |
|
147 |
private static final String BINARY_ATTRIBUTES = |
|
148 |
"java.naming.ldap.attributes.binary"; |
|
149 |
||
150 |
// Delete old RDN during modifyDN: "true", "false" |
|
151 |
private static final String DELETE_RDN = "java.naming.ldap.deleteRDN"; |
|
152 |
||
153 |
// De-reference aliases: "never", "searching", "finding", "always" |
|
154 |
private static final String DEREF_ALIASES = "java.naming.ldap.derefAliases"; |
|
155 |
||
156 |
// Return only attribute types (no values) |
|
157 |
private static final String TYPES_ONLY = "java.naming.ldap.typesOnly"; |
|
158 |
||
159 |
// Separator character for encoding Reference's RefAddrs; default is '#' |
|
160 |
private static final String REF_SEPARATOR = "java.naming.ldap.ref.separator"; |
|
161 |
||
162 |
// Socket factory |
|
163 |
private static final String SOCKET_FACTORY = "java.naming.ldap.factory.socket"; |
|
164 |
||
165 |
// Bind Controls (used by LdapReferralException) |
|
166 |
static final String BIND_CONTROLS = "java.naming.ldap.control.connect"; |
|
167 |
||
168 |
private static final String REFERRAL_LIMIT = |
|
169 |
"java.naming.ldap.referral.limit"; |
|
170 |
||
171 |
// trace BER (java.io.OutputStream) |
|
172 |
private static final String TRACE_BER = "com.sun.jndi.ldap.trace.ber"; |
|
173 |
||
174 |
// Get around Netscape Schema Bugs |
|
175 |
private static final String NETSCAPE_SCHEMA_BUG = |
|
176 |
"com.sun.jndi.ldap.netscape.schemaBugs"; |
|
177 |
// deprecated |
|
178 |
private static final String OLD_NETSCAPE_SCHEMA_BUG = |
|
21278 | 179 |
"com.sun.naming.netscape.schemaBugs"; // for backward compatibility |
2 | 180 |
|
181 |
// Timeout for socket connect |
|
182 |
private static final String CONNECT_TIMEOUT = |
|
183 |
"com.sun.jndi.ldap.connect.timeout"; |
|
184 |
||
185 |
// Timeout for reading responses |
|
186 |
private static final String READ_TIMEOUT = |
|
187 |
"com.sun.jndi.ldap.read.timeout"; |
|
188 |
||
189 |
// Environment property for connection pooling |
|
190 |
private static final String ENABLE_POOL = "com.sun.jndi.ldap.connect.pool"; |
|
191 |
||
192 |
// Environment property for the domain name (derived from this context's DN) |
|
193 |
private static final String DOMAIN_NAME = "com.sun.jndi.ldap.domainname"; |
|
194 |
||
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
195 |
// Block until the first search reply is received |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
196 |
private static final String WAIT_FOR_REPLY = |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
197 |
"com.sun.jndi.ldap.search.waitForReply"; |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
198 |
|
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
199 |
// Size of the queue of unprocessed search replies |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
200 |
private static final String REPLY_QUEUE_SIZE = |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
201 |
"com.sun.jndi.ldap.search.replyQueueSize"; |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
202 |
|
2 | 203 |
// ----------------- Fields that don't change ----------------------- |
204 |
private static final NameParser parser = new LdapNameParser(); |
|
205 |
||
206 |
// controls that Provider needs |
|
207 |
private static final ControlFactory myResponseControlFactory = |
|
208 |
new DefaultResponseControlFactory(); |
|
209 |
private static final Control manageReferralControl = |
|
210 |
new ManageReferralControl(false); |
|
211 |
||
212 |
private static final HierMemDirCtx EMPTY_SCHEMA = new HierMemDirCtx(); |
|
213 |
static { |
|
214 |
EMPTY_SCHEMA.setReadOnly( |
|
215 |
new SchemaViolationException("Cannot update schema object")); |
|
216 |
} |
|
217 |
||
218 |
// ------------ Package private instance variables ---------------- |
|
219 |
// Cannot be private; used by enums |
|
220 |
||
221 |
// ------- Inherited by derived context instances |
|
222 |
||
223 |
int port_number; // port number of server |
|
224 |
String hostname = null; // host name of server (no brackets |
|
225 |
// for IPv6 literals) |
|
226 |
LdapClient clnt = null; // connection handle |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
227 |
Hashtable<String, java.lang.Object> envprops = null; // environment properties of context |
2 | 228 |
int handleReferrals = DEFAULT_REFERRAL_MODE; // how referral is handled |
229 |
boolean hasLdapsScheme = false; // true if the context was created |
|
230 |
// using an LDAPS URL. |
|
231 |
||
232 |
// ------- Not inherited by derived context instances |
|
233 |
||
234 |
String currentDN; // DN of this context |
|
235 |
Name currentParsedDN; // DN of this context |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
236 |
Vector<Control> respCtls = null; // Response controls read |
2 | 237 |
Control[] reqCtls = null; // Controls to be sent with each request |
238 |
||
239 |
||
240 |
// ------------- Private instance variables ------------------------ |
|
241 |
||
242 |
// ------- Inherited by derived context instances |
|
243 |
||
244 |
private OutputStream trace = null; // output stream for BER debug output |
|
245 |
private boolean netscapeSchemaBug = false; // workaround |
|
246 |
private Control[] bindCtls = null; // Controls to be sent with LDAP "bind" |
|
247 |
private int referralHopLimit = DEFAULT_REFERRAL_LIMIT; // max referral |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
248 |
private Hashtable<String, DirContext> schemaTrees = null; // schema root of this context |
2 | 249 |
private int batchSize = DEFAULT_BATCH_SIZE; // batch size for search results |
250 |
private boolean deleteRDN = DEFAULT_DELETE_RDN; // delete the old RDN when modifying DN |
|
251 |
private boolean typesOnly = DEFAULT_TYPES_ONLY; // return attribute types (no values) |
|
252 |
private int derefAliases = DEFAULT_DEREF_ALIASES;// de-reference alias entries during searching |
|
253 |
private char addrEncodingSeparator = DEFAULT_REF_SEPARATOR; // encoding RefAddr |
|
254 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
255 |
private Hashtable<String, Boolean> binaryAttrs = null; // attr values returned as byte[] |
2 | 256 |
private int connectTimeout = -1; // no timeout value |
257 |
private int readTimeout = -1; // no timeout value |
|
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
258 |
private boolean waitForReply = true; // wait for search response |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
259 |
private int replyQueueSize = -1; // unlimited queue size |
2 | 260 |
private boolean useSsl = false; // true if SSL protocol is active |
261 |
private boolean useDefaultPortNumber = false; // no port number was supplied |
|
262 |
||
263 |
// ------- Not inherited by derived context instances |
|
264 |
||
265 |
// True if this context was created by another LdapCtx. |
|
266 |
private boolean parentIsLdapCtx = false; // see composeName() |
|
267 |
||
268 |
private int hopCount = 1; // current referral hop count |
|
269 |
private String url = null; // URL of context; see getURL() |
|
270 |
private EventSupport eventSupport; // Event support helper for this ctx |
|
271 |
private boolean unsolicited = false; // if there unsolicited listeners |
|
272 |
private boolean sharable = true; // can share connection with other ctx |
|
273 |
||
274 |
// -------------- Constructors ----------------------------------- |
|
275 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
276 |
@SuppressWarnings("unchecked") |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
277 |
public LdapCtx(String dn, String host, int port_number, |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
278 |
Hashtable<?,?> props, |
2 | 279 |
boolean useSsl) throws NamingException { |
280 |
||
281 |
this.useSsl = this.hasLdapsScheme = useSsl; |
|
282 |
||
283 |
if (props != null) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
284 |
envprops = (Hashtable<String, java.lang.Object>) props.clone(); |
2 | 285 |
|
286 |
// SSL env prop overrides the useSsl argument |
|
287 |
if ("ssl".equals(envprops.get(Context.SECURITY_PROTOCOL))) { |
|
288 |
this.useSsl = true; |
|
289 |
} |
|
290 |
||
291 |
// %%% These are only examined when the context is created |
|
292 |
// %%% because they are only for debugging or workaround purposes. |
|
293 |
trace = (OutputStream)envprops.get(TRACE_BER); |
|
294 |
||
295 |
if (props.get(NETSCAPE_SCHEMA_BUG) != null || |
|
296 |
props.get(OLD_NETSCAPE_SCHEMA_BUG) != null) { |
|
297 |
netscapeSchemaBug = true; |
|
298 |
} |
|
299 |
} |
|
300 |
||
301 |
currentDN = (dn != null) ? dn : ""; |
|
302 |
currentParsedDN = parser.parse(currentDN); |
|
303 |
||
304 |
hostname = (host != null && host.length() > 0) ? host : DEFAULT_HOST; |
|
305 |
if (hostname.charAt(0) == '[') { |
|
306 |
hostname = hostname.substring(1, hostname.length() - 1); |
|
307 |
} |
|
308 |
||
309 |
if (port_number > 0) { |
|
310 |
this.port_number = port_number; |
|
311 |
} else { |
|
312 |
this.port_number = this.useSsl ? DEFAULT_SSL_PORT : DEFAULT_PORT; |
|
313 |
this.useDefaultPortNumber = true; |
|
314 |
} |
|
315 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
316 |
schemaTrees = new Hashtable<>(11, 0.75f); |
2 | 317 |
initEnv(); |
2605
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
318 |
try { |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
319 |
connect(false); |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
320 |
} catch (NamingException e) { |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
321 |
try { |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
322 |
close(); |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
323 |
} catch (Exception e2) { |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
324 |
// Nothing |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
325 |
} |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
326 |
throw e; |
e8d0473c25e8
6717680: LdapCtx does not close the connection if initialization fails
weijun
parents:
2
diff
changeset
|
327 |
} |
2 | 328 |
} |
329 |
||
330 |
LdapCtx(LdapCtx existing, String newDN) throws NamingException { |
|
331 |
useSsl = existing.useSsl; |
|
332 |
hasLdapsScheme = existing.hasLdapsScheme; |
|
333 |
useDefaultPortNumber = existing.useDefaultPortNumber; |
|
334 |
||
335 |
hostname = existing.hostname; |
|
336 |
port_number = existing.port_number; |
|
337 |
currentDN = newDN; |
|
338 |
if (existing.currentDN == currentDN) { |
|
339 |
currentParsedDN = existing.currentParsedDN; |
|
340 |
} else { |
|
341 |
currentParsedDN = parser.parse(currentDN); |
|
342 |
} |
|
343 |
||
344 |
envprops = existing.envprops; |
|
345 |
schemaTrees = existing.schemaTrees; |
|
346 |
||
347 |
clnt = existing.clnt; |
|
348 |
clnt.incRefCount(); |
|
349 |
||
350 |
parentIsLdapCtx = ((newDN == null || newDN.equals(existing.currentDN)) |
|
351 |
? existing.parentIsLdapCtx |
|
352 |
: true); |
|
353 |
||
354 |
// inherit these debugging/workaround flags |
|
355 |
trace = existing.trace; |
|
356 |
netscapeSchemaBug = existing.netscapeSchemaBug; |
|
357 |
||
358 |
initEnv(); |
|
359 |
} |
|
360 |
||
361 |
public LdapContext newInstance(Control[] reqCtls) throws NamingException { |
|
362 |
||
363 |
LdapContext clone = new LdapCtx(this, currentDN); |
|
364 |
||
365 |
// Connection controls are inherited from environment |
|
366 |
||
367 |
// Set clone's request controls |
|
368 |
// setRequestControls() will clone reqCtls |
|
369 |
clone.setRequestControls(reqCtls); |
|
370 |
return clone; |
|
371 |
} |
|
372 |
||
373 |
// --------------- Namespace Updates --------------------- |
|
374 |
// -- bind/rebind/unbind |
|
375 |
// -- rename |
|
376 |
// -- createSubcontext/destroySubcontext |
|
377 |
||
378 |
protected void c_bind(Name name, Object obj, Continuation cont) |
|
379 |
throws NamingException { |
|
380 |
c_bind(name, obj, null, cont); |
|
381 |
} |
|
382 |
||
383 |
/* |
|
384 |
* attrs == null |
|
385 |
* if obj is DirContext, attrs = obj.getAttributes() |
|
386 |
* if attrs == null && obj == null |
|
387 |
* disallow (cannot determine objectclass to use) |
|
388 |
* if obj == null |
|
389 |
* just create entry using attrs |
|
390 |
* else |
|
391 |
* objAttrs = create attributes for representing obj |
|
392 |
* attrs += objAttrs |
|
393 |
* create entry using attrs |
|
394 |
*/ |
|
395 |
protected void c_bind(Name name, Object obj, Attributes attrs, |
|
396 |
Continuation cont) |
|
397 |
throws NamingException { |
|
398 |
||
399 |
cont.setError(this, name); |
|
400 |
||
401 |
Attributes inputAttrs = attrs; // Attributes supplied by caller |
|
402 |
try { |
|
403 |
ensureOpen(); |
|
404 |
||
405 |
if (obj == null) { |
|
406 |
if (attrs == null) { |
|
407 |
throw new IllegalArgumentException( |
|
408 |
"cannot bind null object with no attributes"); |
|
409 |
} |
|
410 |
} else { |
|
411 |
attrs = Obj.determineBindAttrs(addrEncodingSeparator, obj, attrs, |
|
412 |
false, name, this, envprops); // not cloned |
|
413 |
} |
|
414 |
||
415 |
String newDN = fullyQualifiedName(name); |
|
416 |
attrs = addRdnAttributes(newDN, attrs, inputAttrs != attrs); |
|
417 |
LdapEntry entry = new LdapEntry(newDN, attrs); |
|
418 |
||
419 |
LdapResult answer = clnt.add(entry, reqCtls); |
|
420 |
respCtls = answer.resControls; // retrieve response controls |
|
421 |
||
422 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
423 |
processReturnCode(answer, name); |
|
424 |
} |
|
425 |
||
426 |
} catch (LdapReferralException e) { |
|
427 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
428 |
throw cont.fillInException(e); |
|
429 |
||
430 |
// process the referrals sequentially |
|
431 |
while (true) { |
|
432 |
||
433 |
LdapReferralContext refCtx = |
|
434 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
435 |
||
436 |
// repeat the original operation at the new context |
|
437 |
try { |
|
438 |
||
439 |
refCtx.bind(name, obj, inputAttrs); |
|
440 |
return; |
|
441 |
||
442 |
} catch (LdapReferralException re) { |
|
443 |
e = re; |
|
444 |
continue; |
|
445 |
||
446 |
} finally { |
|
447 |
// Make sure we close referral context |
|
448 |
refCtx.close(); |
|
449 |
} |
|
450 |
} |
|
451 |
||
452 |
} catch (IOException e) { |
|
453 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
454 |
e2.setRootCause(e); |
|
455 |
throw cont.fillInException(e2); |
|
456 |
||
457 |
} catch (NamingException e) { |
|
458 |
throw cont.fillInException(e); |
|
459 |
} |
|
460 |
} |
|
461 |
||
462 |
protected void c_rebind(Name name, Object obj, Continuation cont) |
|
463 |
throws NamingException { |
|
464 |
c_rebind(name, obj, null, cont); |
|
465 |
} |
|
466 |
||
467 |
||
468 |
/* |
|
469 |
* attrs == null |
|
470 |
* if obj is DirContext, attrs = obj.getAttributes(). |
|
471 |
* if attrs == null |
|
472 |
* leave any existing attributes alone |
|
473 |
* (set attrs = {objectclass=top} if object doesn't exist) |
|
474 |
* else |
|
475 |
* replace all existing attributes with attrs |
|
476 |
* if obj == null |
|
477 |
* just create entry using attrs |
|
478 |
* else |
|
479 |
* objAttrs = create attributes for representing obj |
|
480 |
* attrs += objAttrs |
|
481 |
* create entry using attrs |
|
482 |
*/ |
|
483 |
protected void c_rebind(Name name, Object obj, Attributes attrs, |
|
484 |
Continuation cont) throws NamingException { |
|
485 |
||
486 |
cont.setError(this, name); |
|
487 |
||
488 |
Attributes inputAttrs = attrs; |
|
489 |
||
490 |
try { |
|
491 |
Attributes origAttrs = null; |
|
492 |
||
493 |
// Check if name is bound |
|
494 |
try { |
|
495 |
origAttrs = c_getAttributes(name, null, cont); |
|
496 |
} catch (NameNotFoundException e) {} |
|
497 |
||
498 |
// Name not bound, just add it |
|
499 |
if (origAttrs == null) { |
|
500 |
c_bind(name, obj, attrs, cont); |
|
501 |
return; |
|
502 |
} |
|
503 |
||
504 |
// there's an object there already, need to figure out |
|
505 |
// what to do about its attributes |
|
506 |
||
507 |
if (attrs == null && obj instanceof DirContext) { |
|
508 |
attrs = ((DirContext)obj).getAttributes(""); |
|
509 |
} |
|
510 |
Attributes keepAttrs = (Attributes)origAttrs.clone(); |
|
511 |
||
512 |
if (attrs == null) { |
|
513 |
// we're not changing any attrs, leave old attributes alone |
|
514 |
||
515 |
// Remove Java-related object classes from objectclass attribute |
|
516 |
Attribute origObjectClass = |
|
517 |
origAttrs.get(Obj.JAVA_ATTRIBUTES[Obj.OBJECT_CLASS]); |
|
518 |
||
519 |
if (origObjectClass != null) { |
|
520 |
// clone so that keepAttrs is not affected |
|
521 |
origObjectClass = (Attribute)origObjectClass.clone(); |
|
522 |
for (int i = 0; i < Obj.JAVA_OBJECT_CLASSES.length; i++) { |
|
523 |
origObjectClass.remove(Obj.JAVA_OBJECT_CLASSES_LOWER[i]); |
|
524 |
origObjectClass.remove(Obj.JAVA_OBJECT_CLASSES[i]); |
|
525 |
} |
|
526 |
// update; |
|
527 |
origAttrs.put(origObjectClass); |
|
528 |
} |
|
529 |
||
530 |
// remove all Java-related attributes except objectclass |
|
531 |
for (int i = 1; i < Obj.JAVA_ATTRIBUTES.length; i++) { |
|
532 |
origAttrs.remove(Obj.JAVA_ATTRIBUTES[i]); |
|
533 |
} |
|
534 |
||
535 |
attrs = origAttrs; |
|
536 |
} |
|
537 |
if (obj != null) { |
|
538 |
attrs = |
|
539 |
Obj.determineBindAttrs(addrEncodingSeparator, obj, attrs, |
|
540 |
inputAttrs != attrs, name, this, envprops); |
|
541 |
} |
|
542 |
||
543 |
String newDN = fullyQualifiedName(name); |
|
544 |
// remove entry |
|
545 |
LdapResult answer = clnt.delete(newDN, reqCtls); |
|
546 |
respCtls = answer.resControls; // retrieve response controls |
|
547 |
||
548 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
549 |
processReturnCode(answer, name); |
|
550 |
return; |
|
551 |
} |
|
552 |
||
553 |
Exception addEx = null; |
|
554 |
try { |
|
555 |
attrs = addRdnAttributes(newDN, attrs, inputAttrs != attrs); |
|
556 |
||
557 |
// add it back using updated attrs |
|
558 |
LdapEntry entry = new LdapEntry(newDN, attrs); |
|
559 |
answer = clnt.add(entry, reqCtls); |
|
560 |
if (answer.resControls != null) { |
|
561 |
respCtls = appendVector(respCtls, answer.resControls); |
|
562 |
} |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
563 |
} catch (NamingException | IOException ae) { |
2 | 564 |
addEx = ae; |
565 |
} |
|
566 |
||
567 |
if ((addEx != null && !(addEx instanceof LdapReferralException)) || |
|
568 |
answer.status != LdapClient.LDAP_SUCCESS) { |
|
569 |
// Attempt to restore old entry |
|
570 |
LdapResult answer2 = |
|
571 |
clnt.add(new LdapEntry(newDN, keepAttrs), reqCtls); |
|
572 |
if (answer2.resControls != null) { |
|
573 |
respCtls = appendVector(respCtls, answer2.resControls); |
|
574 |
} |
|
575 |
||
576 |
if (addEx == null) { |
|
577 |
processReturnCode(answer, name); |
|
578 |
} |
|
579 |
} |
|
580 |
||
581 |
// Rethrow exception |
|
582 |
if (addEx instanceof NamingException) { |
|
583 |
throw (NamingException)addEx; |
|
584 |
} else if (addEx instanceof IOException) { |
|
585 |
throw (IOException)addEx; |
|
586 |
} |
|
587 |
||
588 |
} catch (LdapReferralException e) { |
|
589 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
590 |
throw cont.fillInException(e); |
|
591 |
||
592 |
// process the referrals sequentially |
|
593 |
while (true) { |
|
594 |
||
595 |
LdapReferralContext refCtx = |
|
596 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
597 |
||
598 |
// repeat the original operation at the new context |
|
599 |
try { |
|
600 |
||
601 |
refCtx.rebind(name, obj, inputAttrs); |
|
602 |
return; |
|
603 |
||
604 |
} catch (LdapReferralException re) { |
|
605 |
e = re; |
|
606 |
continue; |
|
607 |
||
608 |
} finally { |
|
609 |
// Make sure we close referral context |
|
610 |
refCtx.close(); |
|
611 |
} |
|
612 |
} |
|
613 |
||
614 |
} catch (IOException e) { |
|
615 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
616 |
e2.setRootCause(e); |
|
617 |
throw cont.fillInException(e2); |
|
618 |
||
619 |
} catch (NamingException e) { |
|
620 |
throw cont.fillInException(e); |
|
621 |
} |
|
622 |
} |
|
623 |
||
624 |
protected void c_unbind(Name name, Continuation cont) |
|
625 |
throws NamingException { |
|
626 |
cont.setError(this, name); |
|
627 |
||
628 |
try { |
|
629 |
ensureOpen(); |
|
630 |
||
631 |
String fname = fullyQualifiedName(name); |
|
632 |
LdapResult answer = clnt.delete(fname, reqCtls); |
|
633 |
respCtls = answer.resControls; // retrieve response controls |
|
634 |
||
635 |
adjustDeleteStatus(fname, answer); |
|
636 |
||
637 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
638 |
processReturnCode(answer, name); |
|
639 |
} |
|
640 |
||
641 |
} catch (LdapReferralException e) { |
|
642 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
643 |
throw cont.fillInException(e); |
|
644 |
||
645 |
// process the referrals sequentially |
|
646 |
while (true) { |
|
647 |
||
648 |
LdapReferralContext refCtx = |
|
649 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
650 |
||
651 |
// repeat the original operation at the new context |
|
652 |
try { |
|
653 |
||
654 |
refCtx.unbind(name); |
|
655 |
return; |
|
656 |
||
657 |
} catch (LdapReferralException re) { |
|
658 |
e = re; |
|
659 |
continue; |
|
660 |
||
661 |
} finally { |
|
662 |
// Make sure we close referral context |
|
663 |
refCtx.close(); |
|
664 |
} |
|
665 |
} |
|
666 |
||
667 |
} catch (IOException e) { |
|
668 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
669 |
e2.setRootCause(e); |
|
670 |
throw cont.fillInException(e2); |
|
671 |
||
672 |
} catch (NamingException e) { |
|
673 |
throw cont.fillInException(e); |
|
674 |
} |
|
675 |
} |
|
676 |
||
677 |
protected void c_rename(Name oldName, Name newName, Continuation cont) |
|
678 |
throws NamingException |
|
679 |
{ |
|
680 |
Name oldParsed, newParsed; |
|
681 |
Name oldParent, newParent; |
|
682 |
String newRDN = null; |
|
683 |
String newSuperior = null; |
|
684 |
||
685 |
// assert (oldName instanceOf CompositeName); |
|
686 |
||
687 |
cont.setError(this, oldName); |
|
688 |
||
689 |
try { |
|
690 |
ensureOpen(); |
|
691 |
||
692 |
// permit oldName to be empty (for processing referral contexts) |
|
693 |
if (oldName.isEmpty()) { |
|
694 |
oldParent = parser.parse(""); |
|
695 |
} else { |
|
696 |
oldParsed = parser.parse(oldName.get(0)); // extract DN & parse |
|
697 |
oldParent = oldParsed.getPrefix(oldParsed.size() - 1); |
|
698 |
} |
|
699 |
||
700 |
if (newName instanceof CompositeName) { |
|
701 |
newParsed = parser.parse(newName.get(0)); // extract DN & parse |
|
702 |
} else { |
|
703 |
newParsed = newName; // CompoundName/LdapName is already parsed |
|
704 |
} |
|
705 |
newParent = newParsed.getPrefix(newParsed.size() - 1); |
|
706 |
||
707 |
if(!oldParent.equals(newParent)) { |
|
708 |
if (!clnt.isLdapv3) { |
|
709 |
throw new InvalidNameException( |
|
710 |
"LDAPv2 doesn't support changing " + |
|
711 |
"the parent as a result of a rename"); |
|
712 |
} else { |
|
713 |
newSuperior = fullyQualifiedName(newParent.toString()); |
|
714 |
} |
|
715 |
} |
|
716 |
||
717 |
newRDN = newParsed.get(newParsed.size() - 1); |
|
718 |
||
719 |
LdapResult answer = clnt.moddn(fullyQualifiedName(oldName), |
|
720 |
newRDN, |
|
721 |
deleteRDN, |
|
722 |
newSuperior, |
|
723 |
reqCtls); |
|
724 |
respCtls = answer.resControls; // retrieve response controls |
|
725 |
||
726 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
727 |
processReturnCode(answer, oldName); |
|
728 |
} |
|
729 |
||
730 |
} catch (LdapReferralException e) { |
|
731 |
||
732 |
// Record the new RDN (for use after the referral is followed). |
|
733 |
e.setNewRdn(newRDN); |
|
734 |
||
735 |
// Cannot continue when a referral has been received and a |
|
736 |
// newSuperior name was supplied (because the newSuperior is |
|
737 |
// relative to a naming context BEFORE the referral is followed). |
|
738 |
if (newSuperior != null) { |
|
739 |
PartialResultException pre = new PartialResultException( |
|
740 |
"Cannot continue referral processing when newSuperior is " + |
|
741 |
"nonempty: " + newSuperior); |
|
742 |
pre.setRootCause(cont.fillInException(e)); |
|
743 |
throw cont.fillInException(pre); |
|
744 |
} |
|
745 |
||
746 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
747 |
throw cont.fillInException(e); |
|
748 |
||
749 |
// process the referrals sequentially |
|
750 |
while (true) { |
|
751 |
||
752 |
LdapReferralContext refCtx = |
|
753 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
754 |
||
755 |
// repeat the original operation at the new context |
|
756 |
try { |
|
757 |
||
758 |
refCtx.rename(oldName, newName); |
|
759 |
return; |
|
760 |
||
761 |
} catch (LdapReferralException re) { |
|
762 |
e = re; |
|
763 |
continue; |
|
764 |
||
765 |
} finally { |
|
766 |
// Make sure we close referral context |
|
767 |
refCtx.close(); |
|
768 |
} |
|
769 |
} |
|
770 |
||
771 |
} catch (IOException e) { |
|
772 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
773 |
e2.setRootCause(e); |
|
774 |
throw cont.fillInException(e2); |
|
775 |
||
776 |
} catch (NamingException e) { |
|
777 |
throw cont.fillInException(e); |
|
778 |
} |
|
779 |
} |
|
780 |
||
781 |
protected Context c_createSubcontext(Name name, Continuation cont) |
|
782 |
throws NamingException { |
|
783 |
return c_createSubcontext(name, null, cont); |
|
784 |
} |
|
785 |
||
786 |
protected DirContext c_createSubcontext(Name name, Attributes attrs, |
|
787 |
Continuation cont) |
|
788 |
throws NamingException { |
|
789 |
cont.setError(this, name); |
|
790 |
||
791 |
Attributes inputAttrs = attrs; |
|
792 |
try { |
|
793 |
ensureOpen(); |
|
794 |
if (attrs == null) { |
|
795 |
// add structural objectclass; name needs to have "cn" |
|
796 |
Attribute oc = new BasicAttribute( |
|
797 |
Obj.JAVA_ATTRIBUTES[Obj.OBJECT_CLASS], |
|
798 |
Obj.JAVA_OBJECT_CLASSES[Obj.STRUCTURAL]); |
|
799 |
oc.add("top"); |
|
800 |
attrs = new BasicAttributes(true); // case ignore |
|
801 |
attrs.put(oc); |
|
802 |
} |
|
803 |
String newDN = fullyQualifiedName(name); |
|
804 |
attrs = addRdnAttributes(newDN, attrs, inputAttrs != attrs); |
|
805 |
||
806 |
LdapEntry entry = new LdapEntry(newDN, attrs); |
|
807 |
||
808 |
LdapResult answer = clnt.add(entry, reqCtls); |
|
809 |
respCtls = answer.resControls; // retrieve response controls |
|
810 |
||
811 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
812 |
processReturnCode(answer, name); |
|
813 |
return null; |
|
814 |
} |
|
815 |
||
816 |
// creation successful, get back live object |
|
817 |
return new LdapCtx(this, newDN); |
|
818 |
||
819 |
} catch (LdapReferralException e) { |
|
820 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
821 |
throw cont.fillInException(e); |
|
822 |
||
823 |
// process the referrals sequentially |
|
824 |
while (true) { |
|
825 |
||
826 |
LdapReferralContext refCtx = |
|
827 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
828 |
||
829 |
// repeat the original operation at the new context |
|
830 |
try { |
|
831 |
||
832 |
return refCtx.createSubcontext(name, inputAttrs); |
|
833 |
||
834 |
} catch (LdapReferralException re) { |
|
835 |
e = re; |
|
836 |
continue; |
|
837 |
||
838 |
} finally { |
|
839 |
// Make sure we close referral context |
|
840 |
refCtx.close(); |
|
841 |
} |
|
842 |
} |
|
843 |
||
844 |
} catch (IOException e) { |
|
845 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
846 |
e2.setRootCause(e); |
|
847 |
throw cont.fillInException(e2); |
|
848 |
||
849 |
} catch (NamingException e) { |
|
850 |
throw cont.fillInException(e); |
|
851 |
} |
|
852 |
} |
|
853 |
||
854 |
protected void c_destroySubcontext(Name name, Continuation cont) |
|
855 |
throws NamingException { |
|
856 |
cont.setError(this, name); |
|
857 |
||
858 |
try { |
|
859 |
ensureOpen(); |
|
860 |
||
861 |
String fname = fullyQualifiedName(name); |
|
862 |
LdapResult answer = clnt.delete(fname, reqCtls); |
|
863 |
respCtls = answer.resControls; // retrieve response controls |
|
864 |
||
865 |
adjustDeleteStatus(fname, answer); |
|
866 |
||
867 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
868 |
processReturnCode(answer, name); |
|
869 |
} |
|
870 |
||
871 |
} catch (LdapReferralException e) { |
|
872 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
873 |
throw cont.fillInException(e); |
|
874 |
||
875 |
// process the referrals sequentially |
|
876 |
while (true) { |
|
877 |
||
878 |
LdapReferralContext refCtx = |
|
879 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
880 |
||
881 |
// repeat the original operation at the new context |
|
882 |
try { |
|
883 |
||
884 |
refCtx.destroySubcontext(name); |
|
885 |
return; |
|
886 |
} catch (LdapReferralException re) { |
|
887 |
e = re; |
|
888 |
continue; |
|
889 |
} finally { |
|
890 |
// Make sure we close referral context |
|
891 |
refCtx.close(); |
|
892 |
} |
|
893 |
} |
|
894 |
} catch (IOException e) { |
|
895 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
896 |
e2.setRootCause(e); |
|
897 |
throw cont.fillInException(e2); |
|
898 |
} catch (NamingException e) { |
|
899 |
throw cont.fillInException(e); |
|
900 |
} |
|
901 |
} |
|
902 |
||
903 |
/** |
|
904 |
* Adds attributes from RDN to attrs if not already present. |
|
905 |
* Note that if attrs already contains an attribute by the same name, |
|
906 |
* or if the distinguished name is empty, then leave attrs unchanged. |
|
907 |
* |
|
908 |
* @param dn The non-null DN of the entry to add |
|
909 |
* @param attrs The non-null attributes of entry to add |
|
910 |
* @param directUpdate Whether attrs can be updated directly |
|
911 |
* @returns Non-null attributes with attributes from the RDN added |
|
912 |
*/ |
|
913 |
private static Attributes addRdnAttributes(String dn, Attributes attrs, |
|
914 |
boolean directUpdate) throws NamingException { |
|
915 |
||
916 |
// Handle the empty name |
|
917 |
if (dn.equals("")) { |
|
918 |
return attrs; |
|
919 |
} |
|
920 |
||
921 |
// Parse string name into list of RDNs |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
922 |
List<Rdn> rdnList = (new LdapName(dn)).getRdns(); |
2 | 923 |
|
924 |
// Get leaf RDN |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
925 |
Rdn rdn = rdnList.get(rdnList.size() - 1); |
2 | 926 |
Attributes nameAttrs = rdn.toAttributes(); |
927 |
||
928 |
// Add attributes of RDN to attrs if not already there |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
929 |
NamingEnumeration<? extends Attribute> enum_ = nameAttrs.getAll(); |
2 | 930 |
Attribute nameAttr; |
931 |
while (enum_.hasMore()) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
932 |
nameAttr = enum_.next(); |
2 | 933 |
|
934 |
// If attrs already has the attribute, don't change or add to it |
|
935 |
if (attrs.get(nameAttr.getID()) == null) { |
|
936 |
||
937 |
/** |
|
938 |
* When attrs.isCaseIgnored() is false, attrs.get() will |
|
939 |
* return null when the case mis-matches for otherwise |
|
940 |
* equal attrIDs. |
|
941 |
* As the attrIDs' case is irrelevant for LDAP, ignore |
|
942 |
* the case of attrIDs even when attrs.isCaseIgnored() is |
|
943 |
* false. This is done by explicitly comparing the elements in |
|
944 |
* the enumeration of IDs with their case ignored. |
|
945 |
*/ |
|
946 |
if (!attrs.isCaseIgnored() && |
|
947 |
containsIgnoreCase(attrs.getIDs(), nameAttr.getID())) { |
|
948 |
continue; |
|
949 |
} |
|
950 |
||
951 |
if (!directUpdate) { |
|
952 |
attrs = (Attributes)attrs.clone(); |
|
953 |
directUpdate = true; |
|
954 |
} |
|
955 |
attrs.put(nameAttr); |
|
956 |
} |
|
957 |
} |
|
958 |
||
959 |
return attrs; |
|
960 |
} |
|
961 |
||
962 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
963 |
private static boolean containsIgnoreCase(NamingEnumeration<String> enumStr, |
2 | 964 |
String str) throws NamingException { |
965 |
String strEntry; |
|
966 |
||
967 |
while (enumStr.hasMore()) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
968 |
strEntry = enumStr.next(); |
2 | 969 |
if (strEntry.equalsIgnoreCase(str)) { |
970 |
return true; |
|
971 |
} |
|
972 |
} |
|
973 |
return false; |
|
974 |
} |
|
975 |
||
976 |
||
977 |
private void adjustDeleteStatus(String fname, LdapResult answer) { |
|
978 |
if (answer.status == LdapClient.LDAP_NO_SUCH_OBJECT && |
|
979 |
answer.matchedDN != null) { |
|
980 |
try { |
|
981 |
// %%% RL: are there any implications for referrals? |
|
982 |
||
983 |
Name orig = parser.parse(fname); |
|
984 |
Name matched = parser.parse(answer.matchedDN); |
|
985 |
if ((orig.size() - matched.size()) == 1) |
|
986 |
answer.status = LdapClient.LDAP_SUCCESS; |
|
987 |
} catch (NamingException e) {} |
|
988 |
} |
|
989 |
} |
|
990 |
||
991 |
/* |
|
992 |
* Append the the second Vector onto the first Vector |
|
993 |
* (v2 must be non-null) |
|
994 |
*/ |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
995 |
private static <T> Vector<T> appendVector(Vector<T> v1, Vector<T> v2) { |
2 | 996 |
if (v1 == null) { |
997 |
v1 = v2; |
|
998 |
} else { |
|
999 |
for (int i = 0; i < v2.size(); i++) { |
|
1000 |
v1.addElement(v2.elementAt(i)); |
|
1001 |
} |
|
1002 |
} |
|
1003 |
return v1; |
|
1004 |
} |
|
1005 |
||
1006 |
// ------------- Lookups and Browsing ------------------------- |
|
1007 |
// lookup/lookupLink |
|
1008 |
// list/listBindings |
|
1009 |
||
1010 |
protected Object c_lookupLink(Name name, Continuation cont) |
|
1011 |
throws NamingException { |
|
1012 |
return c_lookup(name, cont); |
|
1013 |
} |
|
1014 |
||
1015 |
protected Object c_lookup(Name name, Continuation cont) |
|
1016 |
throws NamingException { |
|
1017 |
cont.setError(this, name); |
|
1018 |
Object obj = null; |
|
1019 |
Attributes attrs; |
|
1020 |
||
1021 |
try { |
|
1022 |
SearchControls cons = new SearchControls(); |
|
1023 |
cons.setSearchScope(SearchControls.OBJECT_SCOPE); |
|
1024 |
cons.setReturningAttributes(null); // ask for all attributes |
|
1025 |
cons.setReturningObjFlag(true); // need values to construct obj |
|
1026 |
||
1027 |
LdapResult answer = doSearchOnce(name, "(objectClass=*)", cons, true); |
|
1028 |
respCtls = answer.resControls; // retrieve response controls |
|
1029 |
||
1030 |
// should get back 1 SearchResponse and 1 SearchResult |
|
1031 |
||
1032 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
1033 |
processReturnCode(answer, name); |
|
1034 |
} |
|
1035 |
||
1036 |
if (answer.entries == null || answer.entries.size() != 1) { |
|
1037 |
// found it but got no attributes |
|
1038 |
attrs = new BasicAttributes(LdapClient.caseIgnore); |
|
1039 |
} else { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1040 |
LdapEntry entry = answer.entries.elementAt(0); |
2 | 1041 |
attrs = entry.attributes; |
1042 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1043 |
Vector<Control> entryCtls = entry.respCtls; // retrieve entry controls |
2 | 1044 |
if (entryCtls != null) { |
1045 |
appendVector(respCtls, entryCtls); // concatenate controls |
|
1046 |
} |
|
1047 |
} |
|
1048 |
||
1049 |
if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) { |
|
1050 |
// serialized object or object reference |
|
1051 |
obj = Obj.decodeObject(attrs); |
|
1052 |
} |
|
1053 |
if (obj == null) { |
|
1054 |
obj = new LdapCtx(this, fullyQualifiedName(name)); |
|
1055 |
} |
|
1056 |
} catch (LdapReferralException e) { |
|
1057 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1058 |
throw cont.fillInException(e); |
|
1059 |
||
1060 |
// process the referrals sequentially |
|
1061 |
while (true) { |
|
1062 |
||
1063 |
LdapReferralContext refCtx = |
|
1064 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
1065 |
// repeat the original operation at the new context |
|
1066 |
try { |
|
1067 |
||
1068 |
return refCtx.lookup(name); |
|
1069 |
||
1070 |
} catch (LdapReferralException re) { |
|
1071 |
e = re; |
|
1072 |
continue; |
|
1073 |
||
1074 |
} finally { |
|
1075 |
// Make sure we close referral context |
|
1076 |
refCtx.close(); |
|
1077 |
} |
|
1078 |
} |
|
1079 |
||
1080 |
} catch (NamingException e) { |
|
1081 |
throw cont.fillInException(e); |
|
1082 |
} |
|
1083 |
||
1084 |
try { |
|
1085 |
return DirectoryManager.getObjectInstance(obj, name, |
|
1086 |
this, envprops, attrs); |
|
1087 |
||
1088 |
} catch (NamingException e) { |
|
1089 |
throw cont.fillInException(e); |
|
1090 |
||
1091 |
} catch (Exception e) { |
|
1092 |
NamingException e2 = new NamingException( |
|
1093 |
"problem generating object using object factory"); |
|
1094 |
e2.setRootCause(e); |
|
1095 |
throw cont.fillInException(e2); |
|
1096 |
} |
|
1097 |
} |
|
1098 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1099 |
protected NamingEnumeration<NameClassPair> c_list(Name name, Continuation cont) |
2 | 1100 |
throws NamingException { |
1101 |
SearchControls cons = new SearchControls(); |
|
1102 |
String[] classAttrs = new String[2]; |
|
1103 |
||
1104 |
classAttrs[0] = Obj.JAVA_ATTRIBUTES[Obj.OBJECT_CLASS]; |
|
1105 |
classAttrs[1] = Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]; |
|
1106 |
cons.setReturningAttributes(classAttrs); |
|
1107 |
||
1108 |
// set this flag to override the typesOnly flag |
|
1109 |
cons.setReturningObjFlag(true); |
|
1110 |
||
1111 |
cont.setError(this, name); |
|
1112 |
||
1113 |
LdapResult answer = null; |
|
1114 |
||
1115 |
try { |
|
1116 |
answer = doSearch(name, "(objectClass=*)", cons, true, true); |
|
1117 |
||
1118 |
// list result may contain continuation references |
|
1119 |
if ((answer.status != LdapClient.LDAP_SUCCESS) || |
|
1120 |
(answer.referrals != null)) { |
|
1121 |
processReturnCode(answer, name); |
|
1122 |
} |
|
1123 |
||
1124 |
return new LdapNamingEnumeration(this, answer, name, cont); |
|
1125 |
||
1126 |
} catch (LdapReferralException e) { |
|
1127 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1128 |
throw cont.fillInException(e); |
|
1129 |
||
1130 |
// process the referrals sequentially |
|
1131 |
while (true) { |
|
1132 |
||
1133 |
LdapReferralContext refCtx = |
|
1134 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
1135 |
||
1136 |
// repeat the original operation at the new context |
|
1137 |
try { |
|
1138 |
||
1139 |
return refCtx.list(name); |
|
1140 |
||
1141 |
} catch (LdapReferralException re) { |
|
1142 |
e = re; |
|
1143 |
continue; |
|
1144 |
||
1145 |
} finally { |
|
1146 |
// Make sure we close referral context |
|
1147 |
refCtx.close(); |
|
1148 |
} |
|
1149 |
} |
|
1150 |
||
1151 |
} catch (LimitExceededException e) { |
|
1152 |
LdapNamingEnumeration res = |
|
1153 |
new LdapNamingEnumeration(this, answer, name, cont); |
|
1154 |
||
1155 |
res.setNamingException( |
|
1156 |
(LimitExceededException)cont.fillInException(e)); |
|
1157 |
return res; |
|
1158 |
||
1159 |
} catch (PartialResultException e) { |
|
1160 |
LdapNamingEnumeration res = |
|
1161 |
new LdapNamingEnumeration(this, answer, name, cont); |
|
1162 |
||
1163 |
res.setNamingException( |
|
1164 |
(PartialResultException)cont.fillInException(e)); |
|
1165 |
return res; |
|
1166 |
||
1167 |
} catch (NamingException e) { |
|
1168 |
throw cont.fillInException(e); |
|
1169 |
} |
|
1170 |
} |
|
1171 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1172 |
protected NamingEnumeration<Binding> c_listBindings(Name name, Continuation cont) |
2 | 1173 |
throws NamingException { |
1174 |
||
1175 |
SearchControls cons = new SearchControls(); |
|
1176 |
cons.setReturningAttributes(null); // ask for all attributes |
|
1177 |
cons.setReturningObjFlag(true); // need values to construct obj |
|
1178 |
||
1179 |
cont.setError(this, name); |
|
1180 |
||
1181 |
LdapResult answer = null; |
|
1182 |
||
1183 |
try { |
|
1184 |
answer = doSearch(name, "(objectClass=*)", cons, true, true); |
|
1185 |
||
1186 |
// listBindings result may contain continuation references |
|
1187 |
if ((answer.status != LdapClient.LDAP_SUCCESS) || |
|
1188 |
(answer.referrals != null)) { |
|
1189 |
processReturnCode(answer, name); |
|
1190 |
} |
|
1191 |
||
1192 |
return new LdapBindingEnumeration(this, answer, name, cont); |
|
1193 |
||
1194 |
} catch (LdapReferralException e) { |
|
1195 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1196 |
throw cont.fillInException(e); |
|
1197 |
||
1198 |
// process the referrals sequentially |
|
1199 |
while (true) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1200 |
@SuppressWarnings("unchecked") |
2 | 1201 |
LdapReferralContext refCtx = |
1202 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
1203 |
||
1204 |
// repeat the original operation at the new context |
|
1205 |
try { |
|
1206 |
||
1207 |
return refCtx.listBindings(name); |
|
1208 |
||
1209 |
} catch (LdapReferralException re) { |
|
1210 |
e = re; |
|
1211 |
continue; |
|
1212 |
||
1213 |
} finally { |
|
1214 |
// Make sure we close referral context |
|
1215 |
refCtx.close(); |
|
1216 |
} |
|
1217 |
} |
|
1218 |
} catch (LimitExceededException e) { |
|
1219 |
LdapBindingEnumeration res = |
|
1220 |
new LdapBindingEnumeration(this, answer, name, cont); |
|
1221 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1222 |
res.setNamingException(cont.fillInException(e)); |
2 | 1223 |
return res; |
1224 |
||
1225 |
} catch (PartialResultException e) { |
|
1226 |
LdapBindingEnumeration res = |
|
1227 |
new LdapBindingEnumeration(this, answer, name, cont); |
|
1228 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1229 |
res.setNamingException(cont.fillInException(e)); |
2 | 1230 |
return res; |
1231 |
||
1232 |
} catch (NamingException e) { |
|
1233 |
throw cont.fillInException(e); |
|
1234 |
} |
|
1235 |
} |
|
1236 |
||
1237 |
// --------------- Name-related Methods ----------------------- |
|
1238 |
// -- getNameParser/getNameInNamespace/composeName |
|
1239 |
||
1240 |
protected NameParser c_getNameParser(Name name, Continuation cont) |
|
1241 |
throws NamingException |
|
1242 |
{ |
|
1243 |
// ignore name, always return same parser |
|
1244 |
cont.setSuccess(); |
|
1245 |
return parser; |
|
1246 |
} |
|
1247 |
||
1248 |
public String getNameInNamespace() { |
|
1249 |
return currentDN; |
|
1250 |
} |
|
1251 |
||
1252 |
public Name composeName(Name name, Name prefix) |
|
1253 |
throws NamingException |
|
1254 |
{ |
|
1255 |
Name result; |
|
1256 |
||
1257 |
// Handle compound names. A pair of LdapNames is an easy case. |
|
1258 |
if ((name instanceof LdapName) && (prefix instanceof LdapName)) { |
|
1259 |
result = (Name)(prefix.clone()); |
|
1260 |
result.addAll(name); |
|
1261 |
return new CompositeName().add(result.toString()); |
|
1262 |
} |
|
1263 |
if (!(name instanceof CompositeName)) { |
|
1264 |
name = new CompositeName().add(name.toString()); |
|
1265 |
} |
|
1266 |
if (!(prefix instanceof CompositeName)) { |
|
1267 |
prefix = new CompositeName().add(prefix.toString()); |
|
1268 |
} |
|
1269 |
||
1270 |
int prefixLast = prefix.size() - 1; |
|
1271 |
||
1272 |
if (name.isEmpty() || prefix.isEmpty() || |
|
1273 |
name.get(0).equals("") || prefix.get(prefixLast).equals("")) { |
|
1274 |
return super.composeName(name, prefix); |
|
1275 |
} |
|
1276 |
||
1277 |
result = (Name)(prefix.clone()); |
|
1278 |
result.addAll(name); |
|
1279 |
||
1280 |
if (parentIsLdapCtx) { |
|
1281 |
String ldapComp = concatNames(result.get(prefixLast + 1), |
|
1282 |
result.get(prefixLast)); |
|
1283 |
result.remove(prefixLast + 1); |
|
1284 |
result.remove(prefixLast); |
|
1285 |
result.add(prefixLast, ldapComp); |
|
1286 |
} |
|
1287 |
return result; |
|
1288 |
} |
|
1289 |
||
1290 |
private String fullyQualifiedName(Name rel) { |
|
1291 |
return rel.isEmpty() |
|
1292 |
? currentDN |
|
1293 |
: fullyQualifiedName(rel.get(0)); |
|
1294 |
} |
|
1295 |
||
1296 |
private String fullyQualifiedName(String rel) { |
|
1297 |
return (concatNames(rel, currentDN)); |
|
1298 |
} |
|
1299 |
||
1300 |
// used by LdapSearchEnumeration |
|
1301 |
private static String concatNames(String lesser, String greater) { |
|
1302 |
if (lesser == null || lesser.equals("")) { |
|
1303 |
return greater; |
|
1304 |
} else if (greater == null || greater.equals("")) { |
|
1305 |
return lesser; |
|
1306 |
} else { |
|
1307 |
return (lesser + "," + greater); |
|
1308 |
} |
|
1309 |
} |
|
1310 |
||
1311 |
// --------------- Reading and Updating Attributes |
|
1312 |
// getAttributes/modifyAttributes |
|
1313 |
||
1314 |
protected Attributes c_getAttributes(Name name, String[] attrIds, |
|
1315 |
Continuation cont) |
|
1316 |
throws NamingException { |
|
1317 |
cont.setError(this, name); |
|
1318 |
||
1319 |
SearchControls cons = new SearchControls(); |
|
1320 |
cons.setSearchScope(SearchControls.OBJECT_SCOPE); |
|
1321 |
cons.setReturningAttributes(attrIds); |
|
1322 |
||
1323 |
try { |
|
1324 |
LdapResult answer = |
|
1325 |
doSearchOnce(name, "(objectClass=*)", cons, true); |
|
1326 |
respCtls = answer.resControls; // retrieve response controls |
|
1327 |
||
1328 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
1329 |
processReturnCode(answer, name); |
|
1330 |
} |
|
1331 |
||
1332 |
if (answer.entries == null || answer.entries.size() != 1) { |
|
1333 |
return new BasicAttributes(LdapClient.caseIgnore); |
|
1334 |
} |
|
1335 |
||
1336 |
// get attributes from result |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1337 |
LdapEntry entry = answer.entries.elementAt(0); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1338 |
|
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1339 |
Vector<Control> entryCtls = entry.respCtls; // retrieve entry controls |
2 | 1340 |
if (entryCtls != null) { |
1341 |
appendVector(respCtls, entryCtls); // concatenate controls |
|
1342 |
} |
|
1343 |
||
1344 |
// do this so attributes can find their schema |
|
1345 |
setParents(entry.attributes, (Name) name.clone()); |
|
1346 |
||
1347 |
return (entry.attributes); |
|
1348 |
||
1349 |
} catch (LdapReferralException e) { |
|
1350 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1351 |
throw cont.fillInException(e); |
|
1352 |
||
1353 |
// process the referrals sequentially |
|
1354 |
while (true) { |
|
1355 |
||
1356 |
LdapReferralContext refCtx = |
|
1357 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
1358 |
||
1359 |
// repeat the original operation at the new context |
|
1360 |
try { |
|
1361 |
||
1362 |
return refCtx.getAttributes(name, attrIds); |
|
1363 |
||
1364 |
} catch (LdapReferralException re) { |
|
1365 |
e = re; |
|
1366 |
continue; |
|
1367 |
||
1368 |
} finally { |
|
1369 |
// Make sure we close referral context |
|
1370 |
refCtx.close(); |
|
1371 |
} |
|
1372 |
} |
|
1373 |
||
1374 |
} catch (NamingException e) { |
|
1375 |
throw cont.fillInException(e); |
|
1376 |
} |
|
1377 |
} |
|
1378 |
||
1379 |
protected void c_modifyAttributes(Name name, int mod_op, Attributes attrs, |
|
1380 |
Continuation cont) |
|
1381 |
throws NamingException { |
|
1382 |
||
1383 |
cont.setError(this, name); |
|
1384 |
||
1385 |
try { |
|
1386 |
ensureOpen(); |
|
1387 |
||
1388 |
if (attrs == null || attrs.size() == 0) { |
|
1389 |
return; // nothing to do |
|
1390 |
} |
|
1391 |
String newDN = fullyQualifiedName(name); |
|
1392 |
int jmod_op = convertToLdapModCode(mod_op); |
|
1393 |
||
1394 |
// construct mod list |
|
1395 |
int[] jmods = new int[attrs.size()]; |
|
1396 |
Attribute[] jattrs = new Attribute[attrs.size()]; |
|
1397 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1398 |
NamingEnumeration<? extends Attribute> ae = attrs.getAll(); |
2 | 1399 |
for(int i = 0; i < jmods.length && ae.hasMore(); i++) { |
1400 |
jmods[i] = jmod_op; |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1401 |
jattrs[i] = ae.next(); |
2 | 1402 |
} |
1403 |
||
1404 |
LdapResult answer = clnt.modify(newDN, jmods, jattrs, reqCtls); |
|
1405 |
respCtls = answer.resControls; // retrieve response controls |
|
1406 |
||
1407 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
1408 |
processReturnCode(answer, name); |
|
1409 |
return; |
|
1410 |
} |
|
1411 |
||
1412 |
} catch (LdapReferralException e) { |
|
1413 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1414 |
throw cont.fillInException(e); |
|
1415 |
||
1416 |
// process the referrals sequentially |
|
1417 |
while (true) { |
|
1418 |
||
1419 |
LdapReferralContext refCtx = |
|
1420 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
1421 |
||
1422 |
// repeat the original operation at the new context |
|
1423 |
try { |
|
1424 |
||
1425 |
refCtx.modifyAttributes(name, mod_op, attrs); |
|
1426 |
return; |
|
1427 |
||
1428 |
} catch (LdapReferralException re) { |
|
1429 |
e = re; |
|
1430 |
continue; |
|
1431 |
||
1432 |
} finally { |
|
1433 |
// Make sure we close referral context |
|
1434 |
refCtx.close(); |
|
1435 |
} |
|
1436 |
} |
|
1437 |
||
1438 |
} catch (IOException e) { |
|
1439 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
1440 |
e2.setRootCause(e); |
|
1441 |
throw cont.fillInException(e2); |
|
1442 |
||
1443 |
} catch (NamingException e) { |
|
1444 |
throw cont.fillInException(e); |
|
1445 |
} |
|
1446 |
} |
|
1447 |
||
1448 |
protected void c_modifyAttributes(Name name, ModificationItem[] mods, |
|
1449 |
Continuation cont) |
|
1450 |
throws NamingException { |
|
1451 |
cont.setError(this, name); |
|
1452 |
||
1453 |
try { |
|
1454 |
ensureOpen(); |
|
1455 |
||
1456 |
if (mods == null || mods.length == 0) { |
|
1457 |
return; // nothing to do |
|
1458 |
} |
|
1459 |
String newDN = fullyQualifiedName(name); |
|
1460 |
||
1461 |
// construct mod list |
|
1462 |
int[] jmods = new int[mods.length]; |
|
1463 |
Attribute[] jattrs = new Attribute[mods.length]; |
|
1464 |
ModificationItem mod; |
|
1465 |
for (int i = 0; i < jmods.length; i++) { |
|
1466 |
mod = mods[i]; |
|
1467 |
jmods[i] = convertToLdapModCode(mod.getModificationOp()); |
|
1468 |
jattrs[i] = mod.getAttribute(); |
|
1469 |
} |
|
1470 |
||
1471 |
LdapResult answer = clnt.modify(newDN, jmods, jattrs, reqCtls); |
|
1472 |
respCtls = answer.resControls; // retrieve response controls |
|
1473 |
||
1474 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
1475 |
processReturnCode(answer, name); |
|
1476 |
} |
|
1477 |
||
1478 |
} catch (LdapReferralException e) { |
|
1479 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1480 |
throw cont.fillInException(e); |
|
1481 |
||
1482 |
// process the referrals sequentially |
|
1483 |
while (true) { |
|
1484 |
||
1485 |
LdapReferralContext refCtx = |
|
1486 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
1487 |
||
1488 |
// repeat the original operation at the new context |
|
1489 |
try { |
|
1490 |
||
1491 |
refCtx.modifyAttributes(name, mods); |
|
1492 |
return; |
|
1493 |
||
1494 |
} catch (LdapReferralException re) { |
|
1495 |
e = re; |
|
1496 |
continue; |
|
1497 |
||
1498 |
} finally { |
|
1499 |
// Make sure we close referral context |
|
1500 |
refCtx.close(); |
|
1501 |
} |
|
1502 |
} |
|
1503 |
||
1504 |
} catch (IOException e) { |
|
1505 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
1506 |
e2.setRootCause(e); |
|
1507 |
throw cont.fillInException(e2); |
|
1508 |
||
1509 |
} catch (NamingException e) { |
|
1510 |
throw cont.fillInException(e); |
|
1511 |
} |
|
1512 |
} |
|
1513 |
||
1514 |
private static int convertToLdapModCode(int mod_op) { |
|
1515 |
switch (mod_op) { |
|
1516 |
case DirContext.ADD_ATTRIBUTE: |
|
1517 |
return(LdapClient.ADD); |
|
1518 |
||
1519 |
case DirContext.REPLACE_ATTRIBUTE: |
|
1520 |
return (LdapClient.REPLACE); |
|
1521 |
||
1522 |
case DirContext.REMOVE_ATTRIBUTE: |
|
1523 |
return (LdapClient.DELETE); |
|
1524 |
||
1525 |
default: |
|
1526 |
throw new IllegalArgumentException("Invalid modification code"); |
|
1527 |
} |
|
1528 |
} |
|
1529 |
||
1530 |
// ------------------- Schema ----------------------- |
|
1531 |
||
1532 |
protected DirContext c_getSchema(Name name, Continuation cont) |
|
1533 |
throws NamingException { |
|
1534 |
cont.setError(this, name); |
|
1535 |
try { |
|
1536 |
return getSchemaTree(name); |
|
1537 |
||
1538 |
} catch (NamingException e) { |
|
1539 |
throw cont.fillInException(e); |
|
1540 |
} |
|
1541 |
} |
|
1542 |
||
1543 |
protected DirContext c_getSchemaClassDefinition(Name name, |
|
1544 |
Continuation cont) |
|
1545 |
throws NamingException { |
|
1546 |
cont.setError(this, name); |
|
1547 |
||
1548 |
try { |
|
1549 |
// retrieve the objectClass attribute from LDAP |
|
1550 |
Attribute objectClassAttr = c_getAttributes(name, |
|
1551 |
new String[]{"objectclass"}, cont).get("objectclass"); |
|
1552 |
if (objectClassAttr == null || objectClassAttr.size() == 0) { |
|
1553 |
return EMPTY_SCHEMA; |
|
1554 |
} |
|
1555 |
||
1556 |
// retrieve the root of the ObjectClass schema tree |
|
1557 |
Context ocSchema = (Context) c_getSchema(name, cont).lookup( |
|
1558 |
LdapSchemaParser.OBJECTCLASS_DEFINITION_NAME); |
|
1559 |
||
1560 |
// create a context to hold the schema objects representing the object |
|
1561 |
// classes |
|
1562 |
HierMemDirCtx objectClassCtx = new HierMemDirCtx(); |
|
1563 |
DirContext objectClassDef; |
|
1564 |
String objectClassName; |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1565 |
for (Enumeration<?> objectClasses = objectClassAttr.getAll(); |
2 | 1566 |
objectClasses.hasMoreElements(); ) { |
1567 |
objectClassName = (String)objectClasses.nextElement(); |
|
1568 |
// %%% Should we fail if not found, or just continue? |
|
1569 |
objectClassDef = (DirContext)ocSchema.lookup(objectClassName); |
|
1570 |
objectClassCtx.bind(objectClassName, objectClassDef); |
|
1571 |
} |
|
1572 |
||
1573 |
// Make context read-only |
|
1574 |
objectClassCtx.setReadOnly( |
|
1575 |
new SchemaViolationException("Cannot update schema object")); |
|
1576 |
return (DirContext)objectClassCtx; |
|
1577 |
||
1578 |
} catch (NamingException e) { |
|
1579 |
throw cont.fillInException(e); |
|
1580 |
} |
|
1581 |
} |
|
1582 |
||
1583 |
/* |
|
1584 |
* getSchemaTree first looks to see if we have already built a |
|
1585 |
* schema tree for the given entry. If not, it builds a new one and |
|
1586 |
* stores it in our private hash table |
|
1587 |
*/ |
|
1588 |
private DirContext getSchemaTree(Name name) throws NamingException { |
|
1589 |
String subschemasubentry = getSchemaEntry(name, true); |
|
1590 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1591 |
DirContext schemaTree = schemaTrees.get(subschemasubentry); |
2 | 1592 |
|
1593 |
if(schemaTree==null) { |
|
1594 |
if(debug){System.err.println("LdapCtx: building new schema tree " + this);} |
|
1595 |
schemaTree = buildSchemaTree(subschemasubentry); |
|
1596 |
schemaTrees.put(subschemasubentry, schemaTree); |
|
1597 |
} |
|
1598 |
||
1599 |
return schemaTree; |
|
1600 |
} |
|
1601 |
||
1602 |
/* |
|
1603 |
* buildSchemaTree builds the schema tree corresponding to the |
|
1604 |
* given subschemasubentree |
|
1605 |
*/ |
|
1606 |
private DirContext buildSchemaTree(String subschemasubentry) |
|
1607 |
throws NamingException { |
|
1608 |
||
1609 |
// get the schema entry itself |
|
1610 |
// DO ask for return object here because we need it to |
|
1611 |
// create context. Since asking for all attrs, we won't |
|
1612 |
// be transmitting any specific attrIDs (like Java-specific ones). |
|
1613 |
SearchControls constraints = new |
|
1614 |
SearchControls(SearchControls.OBJECT_SCOPE, |
|
1615 |
0, 0, /* count and time limits */ |
|
1616 |
SCHEMA_ATTRIBUTES /* return schema attrs */, |
|
1617 |
true /* return obj */, |
|
1618 |
false /*deref link */ ); |
|
1619 |
||
1620 |
Name sse = (new CompositeName()).add(subschemasubentry); |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1621 |
NamingEnumeration<SearchResult> results = |
2 | 1622 |
searchAux(sse, "(objectClass=subschema)", constraints, |
1623 |
false, true, new Continuation()); |
|
1624 |
||
1625 |
if(!results.hasMore()) { |
|
1626 |
throw new OperationNotSupportedException( |
|
1627 |
"Cannot get read subschemasubentry: " + subschemasubentry); |
|
1628 |
} |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1629 |
SearchResult result = results.next(); |
2 | 1630 |
results.close(); |
1631 |
||
1632 |
Object obj = result.getObject(); |
|
1633 |
if(!(obj instanceof LdapCtx)) { |
|
1634 |
throw new NamingException( |
|
1635 |
"Cannot get schema object as DirContext: " + subschemasubentry); |
|
1636 |
} |
|
1637 |
||
1638 |
return LdapSchemaCtx.createSchemaTree(envprops, subschemasubentry, |
|
1639 |
(LdapCtx)obj /* schema entry */, |
|
1640 |
result.getAttributes() /* schema attributes */, |
|
1641 |
netscapeSchemaBug); |
|
1642 |
} |
|
1643 |
||
1644 |
/* |
|
1645 |
* getSchemaEntree returns the DN of the subschemasubentree for the |
|
1646 |
* given entree. It first looks to see if the given entry has |
|
1647 |
* a subschema different from that of the root DIT (by looking for |
|
1648 |
* a "subschemasubentry" attribute). If it doesn't find one, it returns |
|
1649 |
* the one for the root of the DIT (by looking for the root's |
|
1650 |
* "subschemasubentry" attribute). |
|
1651 |
* |
|
1652 |
* This function is called regardless of the server's version, since |
|
1653 |
* an administrator may have setup the server to support client schema |
|
25808 | 1654 |
* queries. If this function tries a search on a v2 server that |
2 | 1655 |
* doesn't support schema, one of these two things will happen: |
1656 |
* 1) It will get an exception when querying the root DSE |
|
1657 |
* 2) It will not find a subschemasubentry on the root DSE |
|
1658 |
* If either of these things occur and the server is not v3, we |
|
1659 |
* throw OperationNotSupported. |
|
1660 |
* |
|
1661 |
* the relative flag tells whether the given name is relative to this |
|
1662 |
* context. |
|
1663 |
*/ |
|
1664 |
private String getSchemaEntry(Name name, boolean relative) |
|
1665 |
throws NamingException { |
|
1666 |
||
1667 |
// Asks for operational attribute "subschemasubentry" |
|
1668 |
SearchControls constraints = new SearchControls(SearchControls.OBJECT_SCOPE, |
|
1669 |
0, 0, /* count and time limits */ |
|
1670 |
new String[]{"subschemasubentry"} /* attr to return */, |
|
1671 |
false /* returning obj */, |
|
1672 |
false /* deref link */); |
|
1673 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1674 |
NamingEnumeration<SearchResult> results; |
2 | 1675 |
try { |
1676 |
results = searchAux(name, "objectclass=*", constraints, relative, |
|
1677 |
true, new Continuation()); |
|
1678 |
||
1679 |
} catch (NamingException ne) { |
|
1680 |
if (!clnt.isLdapv3 && currentDN.length() == 0 && name.isEmpty()) { |
|
1681 |
// we got an error looking for a root entry on an ldapv2 |
|
1682 |
// server. The server must not support schema. |
|
1683 |
throw new OperationNotSupportedException( |
|
1684 |
"Cannot get schema information from server"); |
|
1685 |
} else { |
|
1686 |
throw ne; |
|
1687 |
} |
|
1688 |
} |
|
1689 |
||
1690 |
if (!results.hasMoreElements()) { |
|
1691 |
throw new ConfigurationException( |
|
1692 |
"Requesting schema of nonexistent entry: " + name); |
|
1693 |
} |
|
1694 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1695 |
SearchResult result = results.next(); |
2 | 1696 |
results.close(); |
1697 |
||
1698 |
Attribute schemaEntryAttr = |
|
1699 |
result.getAttributes().get("subschemasubentry"); |
|
1700 |
//System.err.println("schema entry attrs: " + schemaEntryAttr); |
|
1701 |
||
1702 |
if (schemaEntryAttr == null || schemaEntryAttr.size() < 0) { |
|
1703 |
if (currentDN.length() == 0 && name.isEmpty()) { |
|
1704 |
// the server doesn't have a subschemasubentry in its root DSE. |
|
1705 |
// therefore, it doesn't support schema. |
|
1706 |
throw new OperationNotSupportedException( |
|
1707 |
"Cannot read subschemasubentry of root DSE"); |
|
1708 |
} else { |
|
1709 |
return getSchemaEntry(new CompositeName(), false); |
|
1710 |
} |
|
1711 |
} |
|
1712 |
||
1713 |
return (String)(schemaEntryAttr.get()); // return schema entry name |
|
1714 |
} |
|
1715 |
||
1716 |
// package-private; used by search enum. |
|
1717 |
// Set attributes to point to this context in case some one |
|
1718 |
// asked for their schema |
|
1719 |
void setParents(Attributes attrs, Name name) throws NamingException { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1720 |
NamingEnumeration<? extends Attribute> ae = attrs.getAll(); |
2 | 1721 |
while(ae.hasMore()) { |
1722 |
((LdapAttribute) ae.next()).setParent(this, name); |
|
1723 |
} |
|
1724 |
} |
|
1725 |
||
1726 |
/* |
|
1727 |
* Returns the URL associated with this context; used by LdapAttribute |
|
1728 |
* after deserialization to get pointer to this context. |
|
1729 |
*/ |
|
1730 |
String getURL() { |
|
1731 |
if (url == null) { |
|
1732 |
url = LdapURL.toUrlString(hostname, port_number, currentDN, |
|
1733 |
hasLdapsScheme); |
|
1734 |
} |
|
1735 |
||
1736 |
return url; |
|
1737 |
} |
|
1738 |
||
1739 |
// --------------------- Searches ----------------------------- |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1740 |
protected NamingEnumeration<SearchResult> c_search(Name name, |
2 | 1741 |
Attributes matchingAttributes, |
1742 |
Continuation cont) |
|
1743 |
throws NamingException { |
|
1744 |
return c_search(name, matchingAttributes, null, cont); |
|
1745 |
} |
|
1746 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1747 |
protected NamingEnumeration<SearchResult> c_search(Name name, |
2 | 1748 |
Attributes matchingAttributes, |
1749 |
String[] attributesToReturn, |
|
1750 |
Continuation cont) |
|
1751 |
throws NamingException { |
|
1752 |
SearchControls cons = new SearchControls(); |
|
1753 |
cons.setReturningAttributes(attributesToReturn); |
|
1754 |
String filter; |
|
1755 |
try { |
|
1756 |
filter = SearchFilter.format(matchingAttributes); |
|
1757 |
} catch (NamingException e) { |
|
1758 |
cont.setError(this, name); |
|
1759 |
throw cont.fillInException(e); |
|
1760 |
} |
|
1761 |
return c_search(name, filter, cons, cont); |
|
1762 |
} |
|
1763 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1764 |
protected NamingEnumeration<SearchResult> c_search(Name name, |
2 | 1765 |
String filter, |
1766 |
SearchControls cons, |
|
1767 |
Continuation cont) |
|
1768 |
throws NamingException { |
|
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
1769 |
return searchAux(name, filter, cloneSearchControls(cons), true, |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
1770 |
waitForReply, cont); |
2 | 1771 |
} |
1772 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1773 |
protected NamingEnumeration<SearchResult> c_search(Name name, |
2 | 1774 |
String filterExpr, |
1775 |
Object[] filterArgs, |
|
1776 |
SearchControls cons, |
|
1777 |
Continuation cont) |
|
1778 |
throws NamingException { |
|
1779 |
String strfilter; |
|
1780 |
try { |
|
1781 |
strfilter = SearchFilter.format(filterExpr, filterArgs); |
|
1782 |
} catch (NamingException e) { |
|
1783 |
cont.setError(this, name); |
|
1784 |
throw cont.fillInException(e); |
|
1785 |
} |
|
1786 |
return c_search(name, strfilter, cons, cont); |
|
1787 |
} |
|
1788 |
||
1789 |
// Used by NamingNotifier |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1790 |
NamingEnumeration<SearchResult> searchAux(Name name, |
2 | 1791 |
String filter, |
1792 |
SearchControls cons, |
|
1793 |
boolean relative, |
|
1794 |
boolean waitForReply, Continuation cont) throws NamingException { |
|
1795 |
||
1796 |
LdapResult answer = null; |
|
1797 |
String[] tokens = new String[2]; // stores ldap compare op. values |
|
1798 |
String[] reqAttrs; // remember what was asked |
|
1799 |
||
1800 |
if (cons == null) { |
|
1801 |
cons = new SearchControls(); |
|
1802 |
} |
|
1803 |
reqAttrs = cons.getReturningAttributes(); |
|
1804 |
||
1805 |
// if objects are requested then request the Java attributes too |
|
1806 |
// so that the objects can be constructed |
|
1807 |
if (cons.getReturningObjFlag()) { |
|
1808 |
if (reqAttrs != null) { |
|
1809 |
||
1810 |
// check for presence of "*" (user attributes wildcard) |
|
1811 |
boolean hasWildcard = false; |
|
1812 |
for (int i = reqAttrs.length - 1; i >= 0; i--) { |
|
1813 |
if (reqAttrs[i].equals("*")) { |
|
1814 |
hasWildcard = true; |
|
1815 |
break; |
|
1816 |
} |
|
1817 |
} |
|
1818 |
if (! hasWildcard) { |
|
1819 |
String[] totalAttrs = |
|
1820 |
new String[reqAttrs.length +Obj.JAVA_ATTRIBUTES.length]; |
|
1821 |
System.arraycopy(reqAttrs, 0, totalAttrs, 0, |
|
1822 |
reqAttrs.length); |
|
1823 |
System.arraycopy(Obj.JAVA_ATTRIBUTES, 0, totalAttrs, |
|
1824 |
reqAttrs.length, Obj.JAVA_ATTRIBUTES.length); |
|
1825 |
||
1826 |
cons.setReturningAttributes(totalAttrs); |
|
1827 |
} |
|
1828 |
} |
|
1829 |
} |
|
1830 |
||
1831 |
LdapCtx.SearchArgs args = |
|
1832 |
new LdapCtx.SearchArgs(name, filter, cons, reqAttrs); |
|
1833 |
||
1834 |
cont.setError(this, name); |
|
1835 |
try { |
|
1836 |
// see if this can be done as a compare, otherwise do a search |
|
1837 |
if (searchToCompare(filter, cons, tokens)){ |
|
1838 |
//System.err.println("compare triggered"); |
|
1839 |
answer = compare(name, tokens[0], tokens[1]); |
|
1840 |
if (! (answer.compareToSearchResult(fullyQualifiedName(name)))){ |
|
1841 |
processReturnCode(answer, name); |
|
1842 |
} |
|
1843 |
} else { |
|
1844 |
answer = doSearch(name, filter, cons, relative, waitForReply); |
|
1845 |
// search result may contain referrals |
|
1846 |
processReturnCode(answer, name); |
|
1847 |
} |
|
1848 |
return new LdapSearchEnumeration(this, answer, |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1849 |
fullyQualifiedName(name), |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1850 |
args, cont); |
2 | 1851 |
|
1852 |
} catch (LdapReferralException e) { |
|
1853 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
1854 |
throw cont.fillInException(e); |
|
1855 |
||
1856 |
// process the referrals sequentially |
|
1857 |
while (true) { |
|
1858 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1859 |
@SuppressWarnings("unchecked") |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1860 |
LdapReferralContext refCtx = (LdapReferralContext) |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
1861 |
e.getReferralContext(envprops, bindCtls); |
2 | 1862 |
|
1863 |
// repeat the original operation at the new context |
|
1864 |
try { |
|
1865 |
||
1866 |
return refCtx.search(name, filter, cons); |
|
1867 |
||
1868 |
} catch (LdapReferralException re) { |
|
1869 |
e = re; |
|
1870 |
continue; |
|
1871 |
||
1872 |
} finally { |
|
1873 |
// Make sure we close referral context |
|
1874 |
refCtx.close(); |
|
1875 |
} |
|
1876 |
} |
|
1877 |
||
1878 |
} catch (LimitExceededException e) { |
|
1879 |
LdapSearchEnumeration res = |
|
1880 |
new LdapSearchEnumeration(this, answer, fullyQualifiedName(name), |
|
1881 |
args, cont); |
|
1882 |
res.setNamingException(e); |
|
1883 |
return res; |
|
1884 |
||
1885 |
} catch (PartialResultException e) { |
|
1886 |
LdapSearchEnumeration res = |
|
1887 |
new LdapSearchEnumeration(this, answer, fullyQualifiedName(name), |
|
1888 |
args, cont); |
|
1889 |
||
1890 |
res.setNamingException(e); |
|
1891 |
return res; |
|
1892 |
||
1893 |
} catch (IOException e) { |
|
1894 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
1895 |
e2.setRootCause(e); |
|
1896 |
throw cont.fillInException(e2); |
|
1897 |
||
1898 |
} catch (NamingException e) { |
|
1899 |
throw cont.fillInException(e); |
|
1900 |
} |
|
1901 |
} |
|
1902 |
||
1903 |
||
1904 |
LdapResult getSearchReply(LdapClient eClnt, LdapResult res) |
|
1905 |
throws NamingException { |
|
1906 |
// ensureOpen() won't work here because |
|
1907 |
// session was associated with previous connection |
|
1908 |
||
1909 |
// %%% RL: we can actually allow the enumeration to continue |
|
1910 |
// using the old handle but other weird things might happen |
|
1911 |
// when we hit a referral |
|
1912 |
if (clnt != eClnt) { |
|
1913 |
throw new CommunicationException( |
|
1914 |
"Context's connection changed; unable to continue enumeration"); |
|
1915 |
} |
|
1916 |
||
1917 |
try { |
|
1918 |
return eClnt.getSearchReply(batchSize, res, binaryAttrs); |
|
1919 |
} catch (IOException e) { |
|
1920 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
1921 |
e2.setRootCause(e); |
|
1922 |
throw e2; |
|
1923 |
} |
|
1924 |
} |
|
1925 |
||
1926 |
// Perform a search. Expect 1 SearchResultEntry and the SearchResultDone. |
|
1927 |
private LdapResult doSearchOnce(Name name, String filter, |
|
1928 |
SearchControls cons, boolean relative) throws NamingException { |
|
1929 |
||
1930 |
int savedBatchSize = batchSize; |
|
1931 |
batchSize = 2; // 2 protocol elements |
|
1932 |
||
1933 |
LdapResult answer = doSearch(name, filter, cons, relative, true); |
|
1934 |
||
1935 |
batchSize = savedBatchSize; |
|
1936 |
return answer; |
|
1937 |
} |
|
1938 |
||
1939 |
private LdapResult doSearch(Name name, String filter, SearchControls cons, |
|
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
1940 |
boolean relative, boolean waitForReply) throws NamingException { |
2 | 1941 |
ensureOpen(); |
1942 |
try { |
|
1943 |
int scope; |
|
1944 |
||
1945 |
switch (cons.getSearchScope()) { |
|
1946 |
case SearchControls.OBJECT_SCOPE: |
|
1947 |
scope = LdapClient.SCOPE_BASE_OBJECT; |
|
1948 |
break; |
|
1949 |
default: |
|
1950 |
case SearchControls.ONELEVEL_SCOPE: |
|
1951 |
scope = LdapClient.SCOPE_ONE_LEVEL; |
|
1952 |
break; |
|
1953 |
case SearchControls.SUBTREE_SCOPE: |
|
1954 |
scope = LdapClient.SCOPE_SUBTREE; |
|
1955 |
break; |
|
1956 |
} |
|
1957 |
||
1958 |
// If cons.getReturningObjFlag() then caller should already |
|
1959 |
// have make sure to request the appropriate attrs |
|
1960 |
||
1961 |
String[] retattrs = cons.getReturningAttributes(); |
|
1962 |
if (retattrs != null && retattrs.length == 0) { |
|
1963 |
// Ldap treats null and empty array the same |
|
1964 |
// need to replace with single element array |
|
1965 |
retattrs = new String[1]; |
|
1966 |
retattrs[0] = "1.1"; |
|
1967 |
} |
|
1968 |
||
1969 |
String nm = (relative |
|
1970 |
? fullyQualifiedName(name) |
|
1971 |
: (name.isEmpty() |
|
1972 |
? "" |
|
1973 |
: name.get(0))); |
|
1974 |
||
1975 |
// JNDI unit is milliseconds, LDAP unit is seconds. |
|
1976 |
// Zero means no limit. |
|
1977 |
int msecLimit = cons.getTimeLimit(); |
|
1978 |
int secLimit = 0; |
|
1979 |
||
1980 |
if (msecLimit > 0) { |
|
1981 |
secLimit = (msecLimit / 1000) + 1; |
|
1982 |
} |
|
1983 |
||
1984 |
LdapResult answer = |
|
1985 |
clnt.search(nm, |
|
1986 |
scope, |
|
1987 |
derefAliases, |
|
1988 |
(int)cons.getCountLimit(), |
|
1989 |
secLimit, |
|
1990 |
cons.getReturningObjFlag() ? false : typesOnly, |
|
1991 |
retattrs, |
|
1992 |
filter, |
|
1993 |
batchSize, |
|
1994 |
reqCtls, |
|
1995 |
binaryAttrs, |
|
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
1996 |
waitForReply, |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
1997 |
replyQueueSize); |
2 | 1998 |
respCtls = answer.resControls; // retrieve response controls |
1999 |
return answer; |
|
2000 |
||
2001 |
} catch (IOException e) { |
|
2002 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
2003 |
e2.setRootCause(e); |
|
2004 |
throw e2; |
|
2005 |
} |
|
2006 |
} |
|
2007 |
||
2008 |
||
2009 |
/* |
|
2010 |
* Certain simple JNDI searches are automatically converted to |
|
2011 |
* LDAP compare operations by the LDAP service provider. A search |
|
2012 |
* is converted to a compare iff: |
|
2013 |
* |
|
2014 |
* - the scope is set to OBJECT_SCOPE |
|
2015 |
* - the filter string contains a simple assertion: "<type>=<value>" |
|
2016 |
* - the returning attributes list is present but empty |
|
2017 |
*/ |
|
2018 |
||
25808 | 2019 |
// returns true if a search can be carried out as a compare, and sets |
2 | 2020 |
// tokens[0] and tokens[1] to the type and value respectively. |
2021 |
// e.g. filter "cn=Jon Ruiz" becomes, type "cn" and value "Jon Ruiz" |
|
2022 |
// This function uses the documents JNDI Compare example as a model |
|
2023 |
// for when to turn a search into a compare. |
|
2024 |
||
2025 |
private static boolean searchToCompare( |
|
2026 |
String filter, |
|
2027 |
SearchControls cons, |
|
2028 |
String tokens[]) { |
|
2029 |
||
2030 |
// if scope is not object-scope, it's really a search |
|
2031 |
if (cons.getSearchScope() != SearchControls.OBJECT_SCOPE) { |
|
2032 |
return false; |
|
2033 |
} |
|
2034 |
||
2035 |
// if attributes are to be returned, it's really a search |
|
2036 |
String[] attrs = cons.getReturningAttributes(); |
|
2037 |
if (attrs == null || attrs.length != 0) { |
|
2038 |
return false; |
|
2039 |
} |
|
2040 |
||
2041 |
// if the filter not a simple assertion, it's really a search |
|
2042 |
if (! filterToAssertion(filter, tokens)) { |
|
2043 |
return false; |
|
2044 |
} |
|
2045 |
||
2046 |
// it can be converted to a compare |
|
2047 |
return true; |
|
2048 |
} |
|
2049 |
||
2050 |
// If the supplied filter is a simple assertion i.e. "<type>=<value>" |
|
2051 |
// (enclosing parentheses are permitted) then |
|
2052 |
// filterToAssertion will return true and pass the type and value as |
|
2053 |
// the first and second elements of tokens respectively. |
|
2054 |
// precondition: tokens[] must be initialized and be at least of size 2. |
|
2055 |
||
2056 |
private static boolean filterToAssertion(String filter, String tokens[]) { |
|
2057 |
||
2058 |
// find the left and right half of the assertion |
|
2059 |
StringTokenizer assertionTokenizer = new StringTokenizer(filter, "="); |
|
2060 |
||
2061 |
if (assertionTokenizer.countTokens() != 2) { |
|
2062 |
return false; |
|
2063 |
} |
|
2064 |
||
2065 |
tokens[0] = assertionTokenizer.nextToken(); |
|
2066 |
tokens[1] = assertionTokenizer.nextToken(); |
|
2067 |
||
2068 |
// make sure the value does not contain a wildcard |
|
2069 |
if (tokens[1].indexOf('*') != -1) { |
|
2070 |
return false; |
|
2071 |
} |
|
2072 |
||
2073 |
// test for enclosing parenthesis |
|
2074 |
boolean hasParens = false; |
|
2075 |
int len = tokens[1].length(); |
|
2076 |
||
2077 |
if ((tokens[0].charAt(0) == '(') && |
|
2078 |
(tokens[1].charAt(len - 1) == ')')) { |
|
2079 |
hasParens = true; |
|
2080 |
||
2081 |
} else if ((tokens[0].charAt(0) == '(') || |
|
2082 |
(tokens[1].charAt(len - 1) == ')')) { |
|
2083 |
return false; // unbalanced |
|
2084 |
} |
|
2085 |
||
25808 | 2086 |
// make sure the left and right half are not expressions themselves |
2 | 2087 |
StringTokenizer illegalCharsTokenizer = |
2088 |
new StringTokenizer(tokens[0], "()&|!=~><*", true); |
|
2089 |
||
2090 |
if (illegalCharsTokenizer.countTokens() != (hasParens ? 2 : 1)) { |
|
2091 |
return false; |
|
2092 |
} |
|
2093 |
||
2094 |
illegalCharsTokenizer = |
|
2095 |
new StringTokenizer(tokens[1], "()&|!=~><*", true); |
|
2096 |
||
2097 |
if (illegalCharsTokenizer.countTokens() != (hasParens ? 2 : 1)) { |
|
2098 |
return false; |
|
2099 |
} |
|
2100 |
||
2101 |
// strip off enclosing parenthesis, if present |
|
2102 |
if (hasParens) { |
|
2103 |
tokens[0] = tokens[0].substring(1); |
|
2104 |
tokens[1] = tokens[1].substring(0, len - 1); |
|
2105 |
} |
|
2106 |
||
2107 |
return true; |
|
2108 |
} |
|
2109 |
||
2110 |
private LdapResult compare(Name name, String type, String value) |
|
2111 |
throws IOException, NamingException { |
|
2112 |
||
2113 |
ensureOpen(); |
|
2114 |
String nm = fullyQualifiedName(name); |
|
2115 |
||
2116 |
LdapResult answer = clnt.compare(nm, type, value, reqCtls); |
|
2117 |
respCtls = answer.resControls; // retrieve response controls |
|
2118 |
||
2119 |
return answer; |
|
2120 |
} |
|
2121 |
||
2122 |
private static SearchControls cloneSearchControls(SearchControls cons) { |
|
2123 |
if (cons == null) { |
|
2124 |
return null; |
|
2125 |
} |
|
2126 |
String[] retAttrs = cons.getReturningAttributes(); |
|
2127 |
if (retAttrs != null) { |
|
2128 |
String[] attrs = new String[retAttrs.length]; |
|
2129 |
System.arraycopy(retAttrs, 0, attrs, 0, retAttrs.length); |
|
2130 |
retAttrs = attrs; |
|
2131 |
} |
|
2132 |
return new SearchControls(cons.getSearchScope(), |
|
2133 |
cons.getCountLimit(), |
|
2134 |
cons.getTimeLimit(), |
|
2135 |
retAttrs, |
|
2136 |
cons.getReturningObjFlag(), |
|
2137 |
cons.getDerefLinkFlag()); |
|
2138 |
} |
|
2139 |
||
2140 |
// -------------- Environment Properties ------------------ |
|
2141 |
||
2142 |
/** |
|
2143 |
* Override with noncloning version. |
|
2144 |
*/ |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2145 |
protected Hashtable<String, Object> p_getEnvironment() { |
2 | 2146 |
return envprops; |
2147 |
} |
|
2148 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2149 |
@SuppressWarnings("unchecked") // clone() |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2150 |
public Hashtable<String, Object> getEnvironment() throws NamingException { |
2 | 2151 |
return (envprops == null |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2152 |
? new Hashtable<String, Object>(5, 0.75f) |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2153 |
: (Hashtable<String, Object>)envprops.clone()); |
2 | 2154 |
} |
2155 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2156 |
@SuppressWarnings("unchecked") // clone() |
2 | 2157 |
public Object removeFromEnvironment(String propName) |
2158 |
throws NamingException { |
|
2159 |
||
2160 |
// not there; just return |
|
2161 |
if (envprops == null || envprops.get(propName) == null) { |
|
2162 |
return null; |
|
2163 |
} |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2164 |
switch (propName) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2165 |
case REF_SEPARATOR: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2166 |
addrEncodingSeparator = DEFAULT_REF_SEPARATOR; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2167 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2168 |
case TYPES_ONLY: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2169 |
typesOnly = DEFAULT_TYPES_ONLY; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2170 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2171 |
case DELETE_RDN: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2172 |
deleteRDN = DEFAULT_DELETE_RDN; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2173 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2174 |
case DEREF_ALIASES: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2175 |
derefAliases = DEFAULT_DEREF_ALIASES; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2176 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2177 |
case Context.BATCHSIZE: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2178 |
batchSize = DEFAULT_BATCH_SIZE; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2179 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2180 |
case REFERRAL_LIMIT: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2181 |
referralHopLimit = DEFAULT_REFERRAL_LIMIT; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2182 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2183 |
case Context.REFERRAL: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2184 |
setReferralMode(null, true); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2185 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2186 |
case BINARY_ATTRIBUTES: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2187 |
setBinaryAttributes(null); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2188 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2189 |
case CONNECT_TIMEOUT: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2190 |
connectTimeout = -1; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2191 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2192 |
case READ_TIMEOUT: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2193 |
readTimeout = -1; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2194 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2195 |
case WAIT_FOR_REPLY: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2196 |
waitForReply = true; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2197 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2198 |
case REPLY_QUEUE_SIZE: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2199 |
replyQueueSize = -1; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2200 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2201 |
|
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2202 |
// The following properties affect the connection |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2203 |
|
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2204 |
case Context.SECURITY_PROTOCOL: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2205 |
closeConnection(SOFT_CLOSE); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2206 |
// De-activate SSL and reset the context's url and port number |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2207 |
if (useSsl && !hasLdapsScheme) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2208 |
useSsl = false; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2209 |
url = null; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2210 |
if (useDefaultPortNumber) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2211 |
port_number = DEFAULT_PORT; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2212 |
} |
2 | 2213 |
} |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2214 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2215 |
case VERSION: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2216 |
case SOCKET_FACTORY: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2217 |
closeConnection(SOFT_CLOSE); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2218 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2219 |
case Context.SECURITY_AUTHENTICATION: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2220 |
case Context.SECURITY_PRINCIPAL: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2221 |
case Context.SECURITY_CREDENTIALS: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2222 |
sharable = false; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2223 |
break; |
2 | 2224 |
} |
2225 |
||
2226 |
// Update environment; reconnection will use new props |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2227 |
envprops = (Hashtable<String, Object>)envprops.clone(); |
2 | 2228 |
return envprops.remove(propName); |
2229 |
} |
|
2230 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2231 |
@SuppressWarnings("unchecked") // clone() |
2 | 2232 |
public Object addToEnvironment(String propName, Object propVal) |
2233 |
throws NamingException { |
|
2234 |
||
2235 |
// If adding null, call remove |
|
2236 |
if (propVal == null) { |
|
2237 |
return removeFromEnvironment(propName); |
|
2238 |
} |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2239 |
switch (propName) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2240 |
case REF_SEPARATOR: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2241 |
setRefSeparator((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2242 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2243 |
case TYPES_ONLY: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2244 |
setTypesOnly((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2245 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2246 |
case DELETE_RDN: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2247 |
setDeleteRDN((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2248 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2249 |
case DEREF_ALIASES: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2250 |
setDerefAliases((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2251 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2252 |
case Context.BATCHSIZE: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2253 |
setBatchSize((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2254 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2255 |
case REFERRAL_LIMIT: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2256 |
setReferralLimit((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2257 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2258 |
case Context.REFERRAL: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2259 |
setReferralMode((String)propVal, true); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2260 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2261 |
case BINARY_ATTRIBUTES: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2262 |
setBinaryAttributes((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2263 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2264 |
case CONNECT_TIMEOUT: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2265 |
setConnectTimeout((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2266 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2267 |
case READ_TIMEOUT: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2268 |
setReadTimeout((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2269 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2270 |
case WAIT_FOR_REPLY: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2271 |
setWaitForReply((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2272 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2273 |
case REPLY_QUEUE_SIZE: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2274 |
setReplyQueueSize((String)propVal); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2275 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2276 |
|
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2277 |
// The following properties affect the connection |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2278 |
|
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2279 |
case Context.SECURITY_PROTOCOL: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2280 |
closeConnection(SOFT_CLOSE); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2281 |
// Activate SSL and reset the context's url and port number |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2282 |
if ("ssl".equals(propVal)) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2283 |
useSsl = true; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2284 |
url = null; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2285 |
if (useDefaultPortNumber) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2286 |
port_number = DEFAULT_SSL_PORT; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2287 |
} |
2 | 2288 |
} |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2289 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2290 |
case VERSION: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2291 |
case SOCKET_FACTORY: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2292 |
closeConnection(SOFT_CLOSE); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2293 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2294 |
case Context.SECURITY_AUTHENTICATION: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2295 |
case Context.SECURITY_PRINCIPAL: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2296 |
case Context.SECURITY_CREDENTIALS: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2297 |
sharable = false; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2298 |
break; |
2 | 2299 |
} |
2300 |
||
2301 |
// Update environment; reconnection will use new props |
|
2302 |
envprops = (envprops == null |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2303 |
? new Hashtable<String, Object>(5, 0.75f) |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2304 |
: (Hashtable<String, Object>)envprops.clone()); |
2 | 2305 |
return envprops.put(propName, propVal); |
2306 |
} |
|
2307 |
||
2308 |
/** |
|
2309 |
* Sets the URL that created the context in the java.naming.provider.url |
|
2310 |
* property. |
|
2311 |
*/ |
|
2312 |
void setProviderUrl(String providerUrl) { // called by LdapCtxFactory |
|
2313 |
if (envprops != null) { |
|
2314 |
envprops.put(Context.PROVIDER_URL, providerUrl); |
|
2315 |
} |
|
2316 |
} |
|
2317 |
||
2318 |
/** |
|
2319 |
* Sets the domain name for the context in the com.sun.jndi.ldap.domainname |
|
2320 |
* property. |
|
2321 |
* Used for hostname verification by Start TLS |
|
2322 |
*/ |
|
2323 |
void setDomainName(String domainName) { // called by LdapCtxFactory |
|
2324 |
if (envprops != null) { |
|
2325 |
envprops.put(DOMAIN_NAME, domainName); |
|
2326 |
} |
|
2327 |
} |
|
2328 |
||
2329 |
private void initEnv() throws NamingException { |
|
2330 |
if (envprops == null) { |
|
2331 |
// Make sure that referrals are to their default |
|
2332 |
setReferralMode(null, false); |
|
2333 |
return; |
|
2334 |
} |
|
2335 |
||
2336 |
// Set batch size |
|
2337 |
setBatchSize((String)envprops.get(Context.BATCHSIZE)); |
|
2338 |
||
2339 |
// Set separator used for encoding RefAddr |
|
2340 |
setRefSeparator((String)envprops.get(REF_SEPARATOR)); |
|
2341 |
||
2342 |
// Set whether RDN is removed when renaming object |
|
2343 |
setDeleteRDN((String)envprops.get(DELETE_RDN)); |
|
2344 |
||
2345 |
// Set whether types are returned only |
|
2346 |
setTypesOnly((String)envprops.get(TYPES_ONLY)); |
|
2347 |
||
2348 |
// Set how aliases are dereferenced |
|
2349 |
setDerefAliases((String)envprops.get(DEREF_ALIASES)); |
|
2350 |
||
2351 |
// Set the limit on referral chains |
|
2352 |
setReferralLimit((String)envprops.get(REFERRAL_LIMIT)); |
|
2353 |
||
2354 |
setBinaryAttributes((String)envprops.get(BINARY_ATTRIBUTES)); |
|
2355 |
||
2356 |
bindCtls = cloneControls((Control[]) envprops.get(BIND_CONTROLS)); |
|
2357 |
||
2358 |
// set referral handling |
|
2359 |
setReferralMode((String)envprops.get(Context.REFERRAL), false); |
|
2360 |
||
2361 |
// Set the connect timeout |
|
2362 |
setConnectTimeout((String)envprops.get(CONNECT_TIMEOUT)); |
|
2363 |
||
2364 |
// Set the read timeout |
|
2365 |
setReadTimeout((String)envprops.get(READ_TIMEOUT)); |
|
2366 |
||
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2367 |
// Set the flag that controls whether to block until the first reply |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2368 |
// is received |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2369 |
setWaitForReply((String)envprops.get(WAIT_FOR_REPLY)); |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2370 |
|
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2371 |
// Set the size of the queue of unprocessed search replies |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2372 |
setReplyQueueSize((String)envprops.get(REPLY_QUEUE_SIZE)); |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2373 |
|
2 | 2374 |
// When connection is created, it will use these and other |
2375 |
// properties from the environment |
|
2376 |
} |
|
2377 |
||
2378 |
private void setDeleteRDN(String deleteRDNProp) { |
|
2379 |
if ((deleteRDNProp != null) && |
|
2380 |
(deleteRDNProp.equalsIgnoreCase("false"))) { |
|
2381 |
deleteRDN = false; |
|
2382 |
} else { |
|
2383 |
deleteRDN = DEFAULT_DELETE_RDN; |
|
2384 |
} |
|
2385 |
} |
|
2386 |
||
2387 |
private void setTypesOnly(String typesOnlyProp) { |
|
2388 |
if ((typesOnlyProp != null) && |
|
2389 |
(typesOnlyProp.equalsIgnoreCase("true"))) { |
|
2390 |
typesOnly = true; |
|
2391 |
} else { |
|
2392 |
typesOnly = DEFAULT_TYPES_ONLY; |
|
2393 |
} |
|
2394 |
} |
|
2395 |
||
2396 |
/** |
|
2397 |
* Sets the batch size of this context; |
|
2398 |
*/ |
|
2399 |
private void setBatchSize(String batchSizeProp) { |
|
2400 |
// set batchsize |
|
2401 |
if (batchSizeProp != null) { |
|
2402 |
batchSize = Integer.parseInt(batchSizeProp); |
|
2403 |
} else { |
|
2404 |
batchSize = DEFAULT_BATCH_SIZE; |
|
2405 |
} |
|
2406 |
} |
|
2407 |
||
2408 |
/** |
|
2409 |
* Sets the referral mode of this context to 'follow', 'throw' or 'ignore'. |
|
2410 |
* If referral mode is 'ignore' then activate the manageReferral control. |
|
2411 |
*/ |
|
2412 |
private void setReferralMode(String ref, boolean update) { |
|
2413 |
// First determine the referral mode |
|
2414 |
if (ref != null) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2415 |
switch (ref) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2416 |
case "follow": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2417 |
handleReferrals = LdapClient.LDAP_REF_FOLLOW; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2418 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2419 |
case "throw": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2420 |
handleReferrals = LdapClient.LDAP_REF_THROW; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2421 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2422 |
case "ignore": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2423 |
handleReferrals = LdapClient.LDAP_REF_IGNORE; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2424 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2425 |
default: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2426 |
throw new IllegalArgumentException( |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2427 |
"Illegal value for " + Context.REFERRAL + " property."); |
2 | 2428 |
} |
2429 |
} else { |
|
2430 |
handleReferrals = DEFAULT_REFERRAL_MODE; |
|
2431 |
} |
|
2432 |
||
2433 |
if (handleReferrals == LdapClient.LDAP_REF_IGNORE) { |
|
2434 |
// If ignoring referrals, add manageReferralControl |
|
2435 |
reqCtls = addControl(reqCtls, manageReferralControl); |
|
2436 |
||
2437 |
} else if (update) { |
|
2438 |
||
2439 |
// If we're update an existing context, remove the control |
|
2440 |
reqCtls = removeControl(reqCtls, manageReferralControl); |
|
2441 |
||
2442 |
} // else, leave alone; need not update |
|
2443 |
} |
|
2444 |
||
2445 |
/** |
|
25808 | 2446 |
* Set whether aliases are dereferenced during resolution and searches. |
2 | 2447 |
*/ |
2448 |
private void setDerefAliases(String deref) { |
|
2449 |
if (deref != null) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2450 |
switch (deref) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2451 |
case "never": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2452 |
derefAliases = 0; // never de-reference aliases |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2453 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2454 |
case "searching": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2455 |
derefAliases = 1; // de-reference aliases during searching |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2456 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2457 |
case "finding": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2458 |
derefAliases = 2; // de-reference during name resolution |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2459 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2460 |
case "always": |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2461 |
derefAliases = 3; // always de-reference aliases |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2462 |
break; |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2463 |
default: |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2464 |
throw new IllegalArgumentException("Illegal value for " + |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2465 |
DEREF_ALIASES + " property."); |
2 | 2466 |
} |
2467 |
} else { |
|
2468 |
derefAliases = DEFAULT_DEREF_ALIASES; |
|
2469 |
} |
|
2470 |
} |
|
2471 |
||
2472 |
private void setRefSeparator(String sepStr) throws NamingException { |
|
2473 |
if (sepStr != null && sepStr.length() > 0) { |
|
2474 |
addrEncodingSeparator = sepStr.charAt(0); |
|
2475 |
} else { |
|
2476 |
addrEncodingSeparator = DEFAULT_REF_SEPARATOR; |
|
2477 |
} |
|
2478 |
} |
|
2479 |
||
2480 |
/** |
|
2481 |
* Sets the limit on referral chains |
|
2482 |
*/ |
|
2483 |
private void setReferralLimit(String referralLimitProp) { |
|
2484 |
// set referral limit |
|
2485 |
if (referralLimitProp != null) { |
|
2486 |
referralHopLimit = Integer.parseInt(referralLimitProp); |
|
2487 |
||
2488 |
// a zero setting indicates no limit |
|
2489 |
if (referralHopLimit == 0) |
|
2490 |
referralHopLimit = Integer.MAX_VALUE; |
|
2491 |
} else { |
|
2492 |
referralHopLimit = DEFAULT_REFERRAL_LIMIT; |
|
2493 |
} |
|
2494 |
} |
|
2495 |
||
2496 |
// For counting referral hops |
|
2497 |
void setHopCount(int hopCount) { |
|
2498 |
this.hopCount = hopCount; |
|
2499 |
} |
|
2500 |
||
2501 |
/** |
|
2502 |
* Sets the connect timeout value |
|
2503 |
*/ |
|
2504 |
private void setConnectTimeout(String connectTimeoutProp) { |
|
2505 |
if (connectTimeoutProp != null) { |
|
2506 |
connectTimeout = Integer.parseInt(connectTimeoutProp); |
|
2507 |
} else { |
|
2508 |
connectTimeout = -1; |
|
2509 |
} |
|
2510 |
} |
|
2511 |
||
2512 |
/** |
|
8564
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2513 |
* Sets the size of the queue of unprocessed search replies |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2514 |
*/ |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2515 |
private void setReplyQueueSize(String replyQueueSizeProp) { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2516 |
if (replyQueueSizeProp != null) { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2517 |
replyQueueSize = Integer.parseInt(replyQueueSizeProp); |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2518 |
// disallow an empty queue |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2519 |
if (replyQueueSize <= 0) { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2520 |
replyQueueSize = -1; // unlimited |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2521 |
} |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2522 |
} else { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2523 |
replyQueueSize = -1; // unlimited |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2524 |
} |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2525 |
} |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2526 |
|
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2527 |
/** |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2528 |
* Sets the flag that controls whether to block until the first search |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2529 |
* reply is received |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2530 |
*/ |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2531 |
private void setWaitForReply(String waitForReplyProp) { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2532 |
if (waitForReplyProp != null && |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2533 |
(waitForReplyProp.equalsIgnoreCase("false"))) { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2534 |
waitForReply = false; |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2535 |
} else { |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2536 |
waitForReply = true; |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2537 |
} |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2538 |
} |
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2539 |
|
d99f879a35ab
6750362: Very large LDAP requests throw a OOM on LDAP servers which aren't aware of Paged Results Controls
coffeys
parents:
5506
diff
changeset
|
2540 |
/** |
2 | 2541 |
* Sets the read timeout value |
2542 |
*/ |
|
2543 |
private void setReadTimeout(String readTimeoutProp) { |
|
2544 |
if (readTimeoutProp != null) { |
|
2545 |
readTimeout = Integer.parseInt(readTimeoutProp); |
|
2546 |
} else { |
|
2547 |
readTimeout = -1; |
|
2548 |
} |
|
2549 |
} |
|
2550 |
||
2551 |
/* |
|
2552 |
* Extract URLs from a string. The format of the string is: |
|
2553 |
* |
|
2554 |
* <urlstring > ::= "Referral:" <ldapurls> |
|
2555 |
* <ldapurls> ::= <separator> <ldapurl> | <ldapurls> |
|
2556 |
* <separator> ::= ASCII linefeed character (0x0a) |
|
2557 |
* <ldapurl> ::= LDAP URL format (RFC 1959) |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2558 |
* |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2559 |
* Returns a Vector of single-String Vectors. |
2 | 2560 |
*/ |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2561 |
private static Vector<Vector<String>> extractURLs(String refString) { |
2 | 2562 |
|
2563 |
int separator = 0; |
|
2564 |
int urlCount = 0; |
|
2565 |
||
2566 |
// count the number of URLs |
|
2567 |
while ((separator = refString.indexOf('\n', separator)) >= 0) { |
|
2568 |
separator++; |
|
2569 |
urlCount++; |
|
2570 |
} |
|
2571 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2572 |
Vector<Vector<String>> referrals = new Vector<>(urlCount); |
2 | 2573 |
int iURL; |
2574 |
int i = 0; |
|
2575 |
||
2576 |
separator = refString.indexOf('\n'); |
|
2577 |
iURL = separator + 1; |
|
2578 |
while ((separator = refString.indexOf('\n', iURL)) >= 0) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2579 |
Vector<String> referral = new Vector<>(1); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2580 |
referral.addElement(refString.substring(iURL, separator)); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2581 |
referrals.addElement(referral); |
2 | 2582 |
iURL = separator + 1; |
2583 |
} |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2584 |
Vector<String> referral = new Vector<>(1); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2585 |
referral.addElement(refString.substring(iURL)); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2586 |
referrals.addElement(referral); |
2 | 2587 |
|
2588 |
return referrals; |
|
2589 |
} |
|
2590 |
||
2591 |
/* |
|
2592 |
* Argument is a space-separated list of attribute IDs |
|
2593 |
* Converts attribute IDs to lowercase before adding to built-in list. |
|
2594 |
*/ |
|
2595 |
private void setBinaryAttributes(String attrIds) { |
|
2596 |
if (attrIds == null) { |
|
2597 |
binaryAttrs = null; |
|
2598 |
} else { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2599 |
binaryAttrs = new Hashtable<>(11, 0.75f); |
2 | 2600 |
StringTokenizer tokens = |
10369
e9d2e59e53f0
7059542: JNDI name operations should be locale independent
xuelei
parents:
10324
diff
changeset
|
2601 |
new StringTokenizer(attrIds.toLowerCase(Locale.ENGLISH), " "); |
2 | 2602 |
|
2603 |
while (tokens.hasMoreTokens()) { |
|
2604 |
binaryAttrs.put(tokens.nextToken(), Boolean.TRUE); |
|
2605 |
} |
|
2606 |
} |
|
2607 |
} |
|
2608 |
||
2609 |
// ----------------- Connection --------------------- |
|
2610 |
||
2611 |
protected void finalize() { |
|
2612 |
try { |
|
2613 |
close(); |
|
2614 |
} catch (NamingException e) { |
|
2615 |
// ignore failures |
|
2616 |
} |
|
2617 |
} |
|
2618 |
||
2619 |
synchronized public void close() throws NamingException { |
|
2620 |
if (debug) { |
|
2621 |
System.err.println("LdapCtx: close() called " + this); |
|
2622 |
(new Throwable()).printStackTrace(); |
|
2623 |
} |
|
2624 |
||
2625 |
// Event (normal and unsolicited) |
|
2626 |
if (eventSupport != null) { |
|
2627 |
eventSupport.cleanup(); // idempotent |
|
2628 |
removeUnsolicited(); |
|
2629 |
} |
|
2630 |
||
2631 |
// Enumerations that are keeping the connection alive |
|
2632 |
if (enumCount > 0) { |
|
2633 |
if (debug) |
|
2634 |
System.err.println("LdapCtx: close deferred"); |
|
2635 |
closeRequested = true; |
|
2636 |
return; |
|
2637 |
} |
|
2638 |
closeConnection(SOFT_CLOSE); |
|
2639 |
||
2640 |
// %%%: RL: There is no need to set these to null, as they're just |
|
2641 |
// variables whose contents and references will automatically |
|
2642 |
// be cleaned up when they're no longer referenced. |
|
2643 |
// Also, setting these to null creates problems for the attribute |
|
2644 |
// schema-related methods, which need these to work. |
|
2645 |
/* |
|
2646 |
schemaTrees = null; |
|
2647 |
envprops = null; |
|
2648 |
*/ |
|
2649 |
} |
|
2650 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2651 |
@SuppressWarnings("unchecked") // clone() |
2 | 2652 |
public void reconnect(Control[] connCtls) throws NamingException { |
2653 |
// Update environment |
|
2654 |
envprops = (envprops == null |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2655 |
? new Hashtable<String, Object>(5, 0.75f) |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2656 |
: (Hashtable<String, Object>)envprops.clone()); |
2 | 2657 |
|
2658 |
if (connCtls == null) { |
|
2659 |
envprops.remove(BIND_CONTROLS); |
|
2660 |
bindCtls = null; |
|
2661 |
} else { |
|
2662 |
envprops.put(BIND_CONTROLS, bindCtls = cloneControls(connCtls)); |
|
2663 |
} |
|
2664 |
||
2665 |
sharable = false; // can't share with existing contexts |
|
2666 |
ensureOpen(); // open or reauthenticated |
|
2667 |
} |
|
2668 |
||
2669 |
private void ensureOpen() throws NamingException { |
|
2670 |
ensureOpen(false); |
|
2671 |
} |
|
2672 |
||
2673 |
private void ensureOpen(boolean startTLS) throws NamingException { |
|
2674 |
||
2675 |
try { |
|
2676 |
if (clnt == null) { |
|
2677 |
if (debug) { |
|
2678 |
System.err.println("LdapCtx: Reconnecting " + this); |
|
2679 |
} |
|
2680 |
||
2681 |
// reset the cache before a new connection is established |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2682 |
schemaTrees = new Hashtable<>(11, 0.75f); |
2 | 2683 |
connect(startTLS); |
2684 |
||
2685 |
} else if (!sharable || startTLS) { |
|
2686 |
||
2687 |
synchronized (clnt) { |
|
2688 |
if (!clnt.isLdapv3 |
|
2689 |
|| clnt.referenceCount > 1 |
|
2690 |
|| clnt.usingSaslStreams()) { |
|
2691 |
closeConnection(SOFT_CLOSE); |
|
2692 |
} |
|
2693 |
} |
|
2694 |
// reset the cache before a new connection is established |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2695 |
schemaTrees = new Hashtable<>(11, 0.75f); |
2 | 2696 |
connect(startTLS); |
2697 |
} |
|
2698 |
||
2699 |
} finally { |
|
2700 |
sharable = true; // connection is now either new or single-use |
|
2701 |
// OK for others to start sharing again |
|
2702 |
} |
|
2703 |
} |
|
2704 |
||
2705 |
private void connect(boolean startTLS) throws NamingException { |
|
2706 |
if (debug) { System.err.println("LdapCtx: Connecting " + this); } |
|
2707 |
||
2708 |
String user = null; // authenticating user |
|
2709 |
Object passwd = null; // password for authenticating user |
|
2710 |
String secProtocol = null; // security protocol (e.g. "ssl") |
|
2711 |
String socketFactory = null; // socket factory |
|
2712 |
String authMechanism = null; // authentication mechanism |
|
2713 |
String ver = null; |
|
2714 |
int ldapVersion; // LDAP protocol version |
|
2715 |
boolean usePool = false; // enable connection pooling |
|
2716 |
||
2717 |
if (envprops != null) { |
|
2718 |
user = (String)envprops.get(Context.SECURITY_PRINCIPAL); |
|
2719 |
passwd = envprops.get(Context.SECURITY_CREDENTIALS); |
|
2720 |
ver = (String)envprops.get(VERSION); |
|
2721 |
secProtocol = |
|
2722 |
useSsl ? "ssl" : (String)envprops.get(Context.SECURITY_PROTOCOL); |
|
2723 |
socketFactory = (String)envprops.get(SOCKET_FACTORY); |
|
2724 |
authMechanism = |
|
2725 |
(String)envprops.get(Context.SECURITY_AUTHENTICATION); |
|
2726 |
||
2727 |
usePool = "true".equalsIgnoreCase((String)envprops.get(ENABLE_POOL)); |
|
2728 |
} |
|
2729 |
||
2730 |
if (socketFactory == null) { |
|
2731 |
socketFactory = |
|
2732 |
"ssl".equals(secProtocol) ? DEFAULT_SSL_FACTORY : null; |
|
2733 |
} |
|
2734 |
||
2735 |
if (authMechanism == null) { |
|
2736 |
authMechanism = (user == null) ? "none" : "simple"; |
|
2737 |
} |
|
2738 |
||
2739 |
try { |
|
2740 |
boolean initial = (clnt == null); |
|
2741 |
||
2742 |
if (initial) { |
|
2743 |
ldapVersion = (ver != null) ? Integer.parseInt(ver) : |
|
2744 |
DEFAULT_LDAP_VERSION; |
|
2745 |
||
2746 |
clnt = LdapClient.getInstance( |
|
2747 |
usePool, // Whether to use connection pooling |
|
2748 |
||
2749 |
// Required for LdapClient constructor |
|
2750 |
hostname, |
|
2751 |
port_number, |
|
2752 |
socketFactory, |
|
2753 |
connectTimeout, |
|
2754 |
readTimeout, |
|
2755 |
trace, |
|
2756 |
||
2757 |
// Required for basic client identity |
|
2758 |
ldapVersion, |
|
2759 |
authMechanism, |
|
2760 |
bindCtls, |
|
2761 |
secProtocol, |
|
2762 |
||
2763 |
// Required for simple client identity |
|
2764 |
user, |
|
2765 |
passwd, |
|
2766 |
||
2767 |
// Required for SASL client identity |
|
2768 |
envprops); |
|
2769 |
||
2770 |
||
2771 |
/** |
|
2772 |
* Pooled connections are preauthenticated; |
|
2773 |
* newly created ones are not. |
|
2774 |
*/ |
|
2775 |
if (clnt.authenticateCalled()) { |
|
2776 |
return; |
|
2777 |
} |
|
2778 |
||
2779 |
} else if (sharable && startTLS) { |
|
2780 |
return; // no authentication required |
|
2781 |
||
2782 |
} else { |
|
2783 |
// reauthenticating over existing connection; |
|
2784 |
// only v3 supports this |
|
2785 |
ldapVersion = LdapClient.LDAP_VERSION3; |
|
2786 |
} |
|
2787 |
||
2788 |
LdapResult answer = clnt.authenticate(initial, |
|
2789 |
user, passwd, ldapVersion, authMechanism, bindCtls, envprops); |
|
2790 |
||
2791 |
respCtls = answer.resControls; // retrieve (bind) response controls |
|
2792 |
||
2793 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
2794 |
if (initial) { |
|
2795 |
closeConnection(HARD_CLOSE); // hard close |
|
2796 |
} |
|
2797 |
processReturnCode(answer); |
|
2798 |
} |
|
2799 |
||
2800 |
} catch (LdapReferralException e) { |
|
2801 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
2802 |
throw e; |
|
2803 |
||
2804 |
String referral; |
|
2805 |
LdapURL url; |
|
2806 |
NamingException saved_ex = null; |
|
2807 |
||
2808 |
// Process the referrals sequentially (top level) and |
|
2809 |
// recursively (per referral) |
|
2810 |
while (true) { |
|
2811 |
||
2812 |
if ((referral = e.getNextReferral()) == null) { |
|
2813 |
// No more referrals to follow |
|
2814 |
||
2815 |
if (saved_ex != null) { |
|
2816 |
throw (NamingException)(saved_ex.fillInStackTrace()); |
|
2817 |
} else { |
|
2818 |
// No saved exception, something must have gone wrong |
|
2819 |
throw new NamingException( |
|
2820 |
"Internal error processing referral during connection"); |
|
2821 |
} |
|
2822 |
} |
|
2823 |
||
2824 |
// Use host/port number from referral |
|
2825 |
url = new LdapURL(referral); |
|
2826 |
hostname = url.getHost(); |
|
2827 |
if ((hostname != null) && (hostname.charAt(0) == '[')) { |
|
2828 |
hostname = hostname.substring(1, hostname.length() - 1); |
|
2829 |
} |
|
2830 |
port_number = url.getPort(); |
|
2831 |
||
2832 |
// Try to connect again using new host/port number |
|
2833 |
try { |
|
2834 |
connect(startTLS); |
|
2835 |
break; |
|
2836 |
||
2837 |
} catch (NamingException ne) { |
|
2838 |
saved_ex = ne; |
|
2839 |
continue; // follow another referral |
|
2840 |
} |
|
2841 |
} |
|
2842 |
} |
|
2843 |
} |
|
2844 |
||
2845 |
private void closeConnection(boolean hardclose) { |
|
2846 |
removeUnsolicited(); // idempotent |
|
2847 |
||
2848 |
if (clnt != null) { |
|
2849 |
if (debug) { |
|
2850 |
System.err.println("LdapCtx: calling clnt.close() " + this); |
|
2851 |
} |
|
2852 |
clnt.close(reqCtls, hardclose); |
|
2853 |
clnt = null; |
|
2854 |
} |
|
2855 |
} |
|
2856 |
||
2857 |
// Used by Enum classes to track whether it still needs context |
|
2858 |
private int enumCount = 0; |
|
2859 |
private boolean closeRequested = false; |
|
2860 |
||
2861 |
synchronized void incEnumCount() { |
|
2862 |
++enumCount; |
|
2863 |
if (debug) System.err.println("LdapCtx: " + this + " enum inc: " + enumCount); |
|
2864 |
} |
|
2865 |
||
2866 |
synchronized void decEnumCount() { |
|
2867 |
--enumCount; |
|
2868 |
if (debug) System.err.println("LdapCtx: " + this + " enum dec: " + enumCount); |
|
2869 |
||
2870 |
if (enumCount == 0 && closeRequested) { |
|
2871 |
try { |
|
2872 |
close(); |
|
2873 |
} catch (NamingException e) { |
|
2874 |
// ignore failures |
|
2875 |
} |
|
2876 |
} |
|
2877 |
} |
|
2878 |
||
2879 |
||
2880 |
// ------------ Return code and Error messages ----------------------- |
|
2881 |
||
2882 |
protected void processReturnCode(LdapResult answer) throws NamingException { |
|
2883 |
processReturnCode(answer, null, this, null, envprops, null); |
|
2884 |
} |
|
2885 |
||
2886 |
void processReturnCode(LdapResult answer, Name remainName) |
|
2887 |
throws NamingException { |
|
2888 |
processReturnCode(answer, |
|
2889 |
(new CompositeName()).add(currentDN), |
|
2890 |
this, |
|
2891 |
remainName, |
|
2892 |
envprops, |
|
2893 |
fullyQualifiedName(remainName)); |
|
2894 |
} |
|
2895 |
||
2896 |
protected void processReturnCode(LdapResult res, Name resolvedName, |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2897 |
Object resolvedObj, Name remainName, Hashtable<?,?> envprops, String fullDN) |
2 | 2898 |
throws NamingException { |
2899 |
||
2900 |
String msg = LdapClient.getErrorMessage(res.status, res.errorMessage); |
|
2901 |
NamingException e; |
|
2902 |
LdapReferralException r = null; |
|
2903 |
||
2904 |
switch (res.status) { |
|
2905 |
||
2906 |
case LdapClient.LDAP_SUCCESS: |
|
2907 |
||
2908 |
// handle Search continuation references |
|
2909 |
if (res.referrals != null) { |
|
2910 |
||
2911 |
msg = "Unprocessed Continuation Reference(s)"; |
|
2912 |
||
2913 |
if (handleReferrals == LdapClient.LDAP_REF_IGNORE) { |
|
2914 |
e = new PartialResultException(msg); |
|
2915 |
break; |
|
2916 |
} |
|
2917 |
||
2918 |
// handle multiple sets of URLs |
|
2919 |
int contRefCount = res.referrals.size(); |
|
2920 |
LdapReferralException head = null; |
|
2921 |
LdapReferralException ptr = null; |
|
2922 |
||
2923 |
msg = "Continuation Reference"; |
|
2924 |
||
2925 |
// make a chain of LdapReferralExceptions |
|
2926 |
for (int i = 0; i < contRefCount; i++) { |
|
2927 |
||
2928 |
r = new LdapReferralException(resolvedName, resolvedObj, |
|
2929 |
remainName, msg, envprops, fullDN, handleReferrals, |
|
2930 |
reqCtls); |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2931 |
r.setReferralInfo(res.referrals.elementAt(i), true); |
2 | 2932 |
|
2933 |
if (hopCount > 1) { |
|
2934 |
r.setHopCount(hopCount); |
|
2935 |
} |
|
2936 |
||
2937 |
if (head == null) { |
|
2938 |
head = ptr = r; |
|
2939 |
} else { |
|
2940 |
ptr.nextReferralEx = r; // append ex. to end of chain |
|
2941 |
ptr = r; |
|
2942 |
} |
|
2943 |
} |
|
2944 |
res.referrals = null; // reset |
|
2945 |
||
2946 |
if (res.refEx == null) { |
|
2947 |
res.refEx = head; |
|
2948 |
||
2949 |
} else { |
|
2950 |
ptr = res.refEx; |
|
2951 |
||
2952 |
while (ptr.nextReferralEx != null) { |
|
2953 |
ptr = ptr.nextReferralEx; |
|
2954 |
} |
|
2955 |
ptr.nextReferralEx = head; |
|
2956 |
} |
|
2957 |
||
2958 |
// check the hop limit |
|
2959 |
if (hopCount > referralHopLimit) { |
|
2960 |
NamingException lee = |
|
2961 |
new LimitExceededException("Referral limit exceeded"); |
|
2962 |
lee.setRootCause(r); |
|
2963 |
throw lee; |
|
2964 |
} |
|
2965 |
} |
|
2966 |
return; |
|
2967 |
||
2968 |
case LdapClient.LDAP_REFERRAL: |
|
2969 |
||
2970 |
if (handleReferrals == LdapClient.LDAP_REF_IGNORE) { |
|
2971 |
e = new PartialResultException(msg); |
|
2972 |
break; |
|
2973 |
} |
|
2974 |
||
2975 |
r = new LdapReferralException(resolvedName, resolvedObj, remainName, |
|
2976 |
msg, envprops, fullDN, handleReferrals, reqCtls); |
|
2977 |
// only one set of URLs is present |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
2978 |
r.setReferralInfo(res.referrals.elementAt(0), false); |
2 | 2979 |
|
2980 |
if (hopCount > 1) { |
|
2981 |
r.setHopCount(hopCount); |
|
2982 |
} |
|
2983 |
||
2984 |
// check the hop limit |
|
2985 |
if (hopCount > referralHopLimit) { |
|
2986 |
NamingException lee = |
|
2987 |
new LimitExceededException("Referral limit exceeded"); |
|
2988 |
lee.setRootCause(r); |
|
2989 |
e = lee; |
|
2990 |
||
2991 |
} else { |
|
2992 |
e = r; |
|
2993 |
} |
|
2994 |
break; |
|
2995 |
||
2996 |
/* |
|
2997 |
* Handle SLAPD-style referrals. |
|
2998 |
* |
|
2999 |
* Referrals received during name resolution should be followed |
|
3000 |
* until one succeeds - the target entry is located. An exception |
|
3001 |
* is thrown now to handle these. |
|
3002 |
* |
|
3003 |
* Referrals received during a search operation point to unexplored |
|
3004 |
* parts of the directory and each should be followed. An exception |
|
3005 |
* is thrown later (during results enumeration) to handle these. |
|
3006 |
*/ |
|
3007 |
||
3008 |
case LdapClient.LDAP_PARTIAL_RESULTS: |
|
3009 |
||
3010 |
if (handleReferrals == LdapClient.LDAP_REF_IGNORE) { |
|
3011 |
e = new PartialResultException(msg); |
|
3012 |
break; |
|
3013 |
} |
|
3014 |
||
3015 |
// extract SLAPD-style referrals from errorMessage |
|
3016 |
if ((res.errorMessage != null) && (!res.errorMessage.equals(""))) { |
|
3017 |
res.referrals = extractURLs(res.errorMessage); |
|
3018 |
} else { |
|
3019 |
e = new PartialResultException(msg); |
|
3020 |
break; |
|
3021 |
} |
|
3022 |
||
3023 |
// build exception |
|
3024 |
r = new LdapReferralException(resolvedName, |
|
3025 |
resolvedObj, |
|
3026 |
remainName, |
|
3027 |
msg, |
|
3028 |
envprops, |
|
3029 |
fullDN, |
|
3030 |
handleReferrals, |
|
3031 |
reqCtls); |
|
3032 |
||
3033 |
if (hopCount > 1) { |
|
3034 |
r.setHopCount(hopCount); |
|
3035 |
} |
|
3036 |
/* |
|
3037 |
* %%% |
|
3038 |
* SLAPD-style referrals received during name resolution |
|
3039 |
* cannot be distinguished from those received during a |
|
3040 |
* search operation. Since both must be handled differently |
|
3041 |
* the following rule is applied: |
|
3042 |
* |
|
3043 |
* If 1 referral and 0 entries is received then |
|
3044 |
* assume name resolution has not yet completed. |
|
3045 |
*/ |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3046 |
if (((res.entries == null) || (res.entries.isEmpty())) && |
2 | 3047 |
(res.referrals.size() == 1)) { |
3048 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3049 |
r.setReferralInfo(res.referrals, false); |
2 | 3050 |
|
3051 |
// check the hop limit |
|
3052 |
if (hopCount > referralHopLimit) { |
|
3053 |
NamingException lee = |
|
3054 |
new LimitExceededException("Referral limit exceeded"); |
|
3055 |
lee.setRootCause(r); |
|
3056 |
e = lee; |
|
3057 |
||
3058 |
} else { |
|
3059 |
e = r; |
|
3060 |
} |
|
3061 |
||
3062 |
} else { |
|
3063 |
r.setReferralInfo(res.referrals, true); |
|
3064 |
res.refEx = r; |
|
3065 |
return; |
|
3066 |
} |
|
3067 |
break; |
|
3068 |
||
3069 |
case LdapClient.LDAP_INVALID_DN_SYNTAX: |
|
3070 |
case LdapClient.LDAP_NAMING_VIOLATION: |
|
3071 |
||
3072 |
if (remainName != null) { |
|
3073 |
e = new |
|
3074 |
InvalidNameException(remainName.toString() + ": " + msg); |
|
3075 |
} else { |
|
3076 |
e = new InvalidNameException(msg); |
|
3077 |
} |
|
3078 |
break; |
|
3079 |
||
3080 |
default: |
|
3081 |
e = mapErrorCode(res.status, res.errorMessage); |
|
3082 |
break; |
|
3083 |
} |
|
3084 |
e.setResolvedName(resolvedName); |
|
3085 |
e.setResolvedObj(resolvedObj); |
|
3086 |
e.setRemainingName(remainName); |
|
3087 |
throw e; |
|
3088 |
} |
|
3089 |
||
3090 |
/** |
|
3091 |
* Maps an LDAP error code to an appropriate NamingException. |
|
3092 |
* %%% public; used by controls |
|
3093 |
* |
|
3094 |
* @param errorCode numeric LDAP error code |
|
3095 |
* @param errorMessage textual description of the LDAP error. May be null. |
|
3096 |
* |
|
3097 |
* @return A NamingException or null if the error code indicates success. |
|
3098 |
*/ |
|
3099 |
public static NamingException mapErrorCode(int errorCode, |
|
3100 |
String errorMessage) { |
|
3101 |
||
3102 |
if (errorCode == LdapClient.LDAP_SUCCESS) |
|
3103 |
return null; |
|
3104 |
||
3105 |
NamingException e = null; |
|
3106 |
String message = LdapClient.getErrorMessage(errorCode, errorMessage); |
|
3107 |
||
3108 |
switch (errorCode) { |
|
3109 |
||
3110 |
case LdapClient.LDAP_ALIAS_DEREFERENCING_PROBLEM: |
|
3111 |
e = new NamingException(message); |
|
3112 |
break; |
|
3113 |
||
3114 |
case LdapClient.LDAP_ALIAS_PROBLEM: |
|
3115 |
e = new NamingException(message); |
|
3116 |
break; |
|
3117 |
||
3118 |
case LdapClient.LDAP_ATTRIBUTE_OR_VALUE_EXISTS: |
|
3119 |
e = new AttributeInUseException(message); |
|
3120 |
break; |
|
3121 |
||
3122 |
case LdapClient.LDAP_AUTH_METHOD_NOT_SUPPORTED: |
|
3123 |
case LdapClient.LDAP_CONFIDENTIALITY_REQUIRED: |
|
3124 |
case LdapClient.LDAP_STRONG_AUTH_REQUIRED: |
|
3125 |
case LdapClient.LDAP_INAPPROPRIATE_AUTHENTICATION: |
|
3126 |
e = new AuthenticationNotSupportedException(message); |
|
3127 |
break; |
|
3128 |
||
3129 |
case LdapClient.LDAP_ENTRY_ALREADY_EXISTS: |
|
3130 |
e = new NameAlreadyBoundException(message); |
|
3131 |
break; |
|
3132 |
||
3133 |
case LdapClient.LDAP_INVALID_CREDENTIALS: |
|
3134 |
case LdapClient.LDAP_SASL_BIND_IN_PROGRESS: |
|
3135 |
e = new AuthenticationException(message); |
|
3136 |
break; |
|
3137 |
||
3138 |
case LdapClient.LDAP_INAPPROPRIATE_MATCHING: |
|
3139 |
e = new InvalidSearchFilterException(message); |
|
3140 |
break; |
|
3141 |
||
3142 |
case LdapClient.LDAP_INSUFFICIENT_ACCESS_RIGHTS: |
|
3143 |
e = new NoPermissionException(message); |
|
3144 |
break; |
|
3145 |
||
3146 |
case LdapClient.LDAP_INVALID_ATTRIBUTE_SYNTAX: |
|
3147 |
case LdapClient.LDAP_CONSTRAINT_VIOLATION: |
|
3148 |
e = new InvalidAttributeValueException(message); |
|
3149 |
break; |
|
3150 |
||
3151 |
case LdapClient.LDAP_LOOP_DETECT: |
|
3152 |
e = new NamingException(message); |
|
3153 |
break; |
|
3154 |
||
3155 |
case LdapClient.LDAP_NO_SUCH_ATTRIBUTE: |
|
3156 |
e = new NoSuchAttributeException(message); |
|
3157 |
break; |
|
3158 |
||
3159 |
case LdapClient.LDAP_NO_SUCH_OBJECT: |
|
3160 |
e = new NameNotFoundException(message); |
|
3161 |
break; |
|
3162 |
||
3163 |
case LdapClient.LDAP_OBJECT_CLASS_MODS_PROHIBITED: |
|
3164 |
case LdapClient.LDAP_OBJECT_CLASS_VIOLATION: |
|
3165 |
case LdapClient.LDAP_NOT_ALLOWED_ON_RDN: |
|
3166 |
e = new SchemaViolationException(message); |
|
3167 |
break; |
|
3168 |
||
3169 |
case LdapClient.LDAP_NOT_ALLOWED_ON_NON_LEAF: |
|
3170 |
e = new ContextNotEmptyException(message); |
|
3171 |
break; |
|
3172 |
||
3173 |
case LdapClient.LDAP_OPERATIONS_ERROR: |
|
3174 |
// %%% need new exception ? |
|
3175 |
e = new NamingException(message); |
|
3176 |
break; |
|
3177 |
||
3178 |
case LdapClient.LDAP_OTHER: |
|
3179 |
e = new NamingException(message); |
|
3180 |
break; |
|
3181 |
||
3182 |
case LdapClient.LDAP_PROTOCOL_ERROR: |
|
3183 |
e = new CommunicationException(message); |
|
3184 |
break; |
|
3185 |
||
3186 |
case LdapClient.LDAP_SIZE_LIMIT_EXCEEDED: |
|
3187 |
e = new SizeLimitExceededException(message); |
|
3188 |
break; |
|
3189 |
||
3190 |
case LdapClient.LDAP_TIME_LIMIT_EXCEEDED: |
|
3191 |
e = new TimeLimitExceededException(message); |
|
3192 |
break; |
|
3193 |
||
3194 |
case LdapClient.LDAP_UNAVAILABLE_CRITICAL_EXTENSION: |
|
3195 |
e = new OperationNotSupportedException(message); |
|
3196 |
break; |
|
3197 |
||
3198 |
case LdapClient.LDAP_UNAVAILABLE: |
|
3199 |
case LdapClient.LDAP_BUSY: |
|
3200 |
e = new ServiceUnavailableException(message); |
|
3201 |
break; |
|
3202 |
||
3203 |
case LdapClient.LDAP_UNDEFINED_ATTRIBUTE_TYPE: |
|
3204 |
e = new InvalidAttributeIdentifierException(message); |
|
3205 |
break; |
|
3206 |
||
3207 |
case LdapClient.LDAP_UNWILLING_TO_PERFORM: |
|
3208 |
e = new OperationNotSupportedException(message); |
|
3209 |
break; |
|
3210 |
||
3211 |
case LdapClient.LDAP_COMPARE_FALSE: |
|
3212 |
case LdapClient.LDAP_COMPARE_TRUE: |
|
3213 |
case LdapClient.LDAP_IS_LEAF: |
|
3214 |
// these are really not exceptions and this code probably |
|
3215 |
// never gets executed |
|
3216 |
e = new NamingException(message); |
|
3217 |
break; |
|
3218 |
||
3219 |
case LdapClient.LDAP_ADMIN_LIMIT_EXCEEDED: |
|
3220 |
e = new LimitExceededException(message); |
|
3221 |
break; |
|
3222 |
||
3223 |
case LdapClient.LDAP_REFERRAL: |
|
3224 |
e = new NamingException(message); |
|
3225 |
break; |
|
3226 |
||
3227 |
case LdapClient.LDAP_PARTIAL_RESULTS: |
|
3228 |
e = new NamingException(message); |
|
3229 |
break; |
|
3230 |
||
3231 |
case LdapClient.LDAP_INVALID_DN_SYNTAX: |
|
3232 |
case LdapClient.LDAP_NAMING_VIOLATION: |
|
3233 |
e = new InvalidNameException(message); |
|
3234 |
break; |
|
3235 |
||
3236 |
default: |
|
3237 |
e = new NamingException(message); |
|
3238 |
break; |
|
3239 |
} |
|
3240 |
||
3241 |
return e; |
|
3242 |
} |
|
3243 |
||
3244 |
// ----------------- Extensions and Controls ------------------- |
|
3245 |
||
3246 |
public ExtendedResponse extendedOperation(ExtendedRequest request) |
|
3247 |
throws NamingException { |
|
3248 |
||
3249 |
boolean startTLS = (request.getID().equals(STARTTLS_REQ_OID)); |
|
3250 |
ensureOpen(startTLS); |
|
3251 |
||
3252 |
try { |
|
3253 |
||
3254 |
LdapResult answer = |
|
3255 |
clnt.extendedOp(request.getID(), request.getEncodedValue(), |
|
3256 |
reqCtls, startTLS); |
|
3257 |
respCtls = answer.resControls; // retrieve response controls |
|
3258 |
||
3259 |
if (answer.status != LdapClient.LDAP_SUCCESS) { |
|
3260 |
processReturnCode(answer, new CompositeName()); |
|
3261 |
} |
|
3262 |
// %%% verify request.getID() == answer.extensionId |
|
3263 |
||
3264 |
int len = (answer.extensionValue == null) ? |
|
3265 |
0 : |
|
3266 |
answer.extensionValue.length; |
|
3267 |
||
3268 |
ExtendedResponse er = |
|
3269 |
request.createExtendedResponse(answer.extensionId, |
|
3270 |
answer.extensionValue, 0, len); |
|
3271 |
||
3272 |
if (er instanceof StartTlsResponseImpl) { |
|
3273 |
// Pass the connection handle to StartTlsResponseImpl |
|
3274 |
String domainName = (String) |
|
3275 |
(envprops != null ? envprops.get(DOMAIN_NAME) : null); |
|
3276 |
((StartTlsResponseImpl)er).setConnection(clnt.conn, domainName); |
|
3277 |
} |
|
3278 |
return er; |
|
3279 |
||
3280 |
} catch (LdapReferralException e) { |
|
3281 |
||
3282 |
if (handleReferrals == LdapClient.LDAP_REF_THROW) |
|
3283 |
throw e; |
|
3284 |
||
3285 |
// process the referrals sequentially |
|
3286 |
while (true) { |
|
3287 |
||
3288 |
LdapReferralContext refCtx = |
|
3289 |
(LdapReferralContext)e.getReferralContext(envprops, bindCtls); |
|
3290 |
||
3291 |
// repeat the original operation at the new context |
|
3292 |
try { |
|
3293 |
||
3294 |
return refCtx.extendedOperation(request); |
|
3295 |
||
3296 |
} catch (LdapReferralException re) { |
|
3297 |
e = re; |
|
3298 |
continue; |
|
3299 |
||
3300 |
} finally { |
|
3301 |
// Make sure we close referral context |
|
3302 |
refCtx.close(); |
|
3303 |
} |
|
3304 |
} |
|
3305 |
||
3306 |
} catch (IOException e) { |
|
3307 |
NamingException e2 = new CommunicationException(e.getMessage()); |
|
3308 |
e2.setRootCause(e); |
|
3309 |
throw e2; |
|
3310 |
} |
|
3311 |
} |
|
3312 |
||
3313 |
public void setRequestControls(Control[] reqCtls) throws NamingException { |
|
3314 |
if (handleReferrals == LdapClient.LDAP_REF_IGNORE) { |
|
3315 |
this.reqCtls = addControl(reqCtls, manageReferralControl); |
|
3316 |
} else { |
|
3317 |
this.reqCtls = cloneControls(reqCtls); |
|
3318 |
} |
|
3319 |
} |
|
3320 |
||
3321 |
public Control[] getRequestControls() throws NamingException { |
|
3322 |
return cloneControls(reqCtls); |
|
3323 |
} |
|
3324 |
||
3325 |
public Control[] getConnectControls() throws NamingException { |
|
3326 |
return cloneControls(bindCtls); |
|
3327 |
} |
|
3328 |
||
3329 |
public Control[] getResponseControls() throws NamingException { |
|
3330 |
return (respCtls != null)? convertControls(respCtls) : null; |
|
3331 |
} |
|
3332 |
||
3333 |
/** |
|
3334 |
* Narrow controls using own default factory and ControlFactory. |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3335 |
* @param ctls A non-null Vector<Control> |
2 | 3336 |
*/ |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3337 |
Control[] convertControls(Vector<Control> ctls) throws NamingException { |
2 | 3338 |
int count = ctls.size(); |
3339 |
||
3340 |
if (count == 0) { |
|
3341 |
return null; |
|
3342 |
} |
|
3343 |
||
3344 |
Control[] controls = new Control[count]; |
|
3345 |
||
3346 |
for (int i = 0; i < count; i++) { |
|
3347 |
// Try own factory first |
|
3348 |
controls[i] = myResponseControlFactory.getControlInstance( |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3349 |
ctls.elementAt(i)); |
2 | 3350 |
|
3351 |
// Try assigned factories if own produced null |
|
3352 |
if (controls[i] == null) { |
|
3353 |
controls[i] = ControlFactory.getControlInstance( |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3354 |
ctls.elementAt(i), this, envprops); |
2 | 3355 |
} |
3356 |
} |
|
3357 |
return controls; |
|
3358 |
} |
|
3359 |
||
3360 |
private static Control[] addControl(Control[] prevCtls, Control addition) { |
|
3361 |
if (prevCtls == null) { |
|
3362 |
return new Control[]{addition}; |
|
3363 |
} |
|
3364 |
||
3365 |
// Find it |
|
3366 |
int found = findControl(prevCtls, addition); |
|
3367 |
if (found != -1) { |
|
3368 |
return prevCtls; // no need to do it again |
|
3369 |
} |
|
3370 |
||
3371 |
Control[] newCtls = new Control[prevCtls.length+1]; |
|
3372 |
System.arraycopy(prevCtls, 0, newCtls, 0, prevCtls.length); |
|
3373 |
newCtls[prevCtls.length] = addition; |
|
3374 |
return newCtls; |
|
3375 |
} |
|
3376 |
||
3377 |
private static int findControl(Control[] ctls, Control target) { |
|
3378 |
for (int i = 0; i < ctls.length; i++) { |
|
3379 |
if (ctls[i] == target) { |
|
3380 |
return i; |
|
3381 |
} |
|
3382 |
} |
|
3383 |
return -1; |
|
3384 |
} |
|
3385 |
||
3386 |
private static Control[] removeControl(Control[] prevCtls, Control target) { |
|
3387 |
if (prevCtls == null) { |
|
3388 |
return null; |
|
3389 |
} |
|
3390 |
||
3391 |
// Find it |
|
3392 |
int found = findControl(prevCtls, target); |
|
3393 |
if (found == -1) { |
|
3394 |
return prevCtls; // not there |
|
3395 |
} |
|
3396 |
||
3397 |
// Remove it |
|
3398 |
Control[] newCtls = new Control[prevCtls.length-1]; |
|
3399 |
System.arraycopy(prevCtls, 0, newCtls, 0, found); |
|
3400 |
System.arraycopy(prevCtls, found+1, newCtls, found, |
|
3401 |
prevCtls.length-found-1); |
|
3402 |
return newCtls; |
|
3403 |
} |
|
3404 |
||
3405 |
private static Control[] cloneControls(Control[] ctls) { |
|
3406 |
if (ctls == null) { |
|
3407 |
return null; |
|
3408 |
} |
|
3409 |
Control[] copiedCtls = new Control[ctls.length]; |
|
3410 |
System.arraycopy(ctls, 0, copiedCtls, 0, ctls.length); |
|
3411 |
return copiedCtls; |
|
3412 |
} |
|
3413 |
||
3414 |
// -------------------- Events ------------------------ |
|
3415 |
/* |
|
3416 |
* Access to eventSupport need not be synchronized even though the |
|
3417 |
* Connection thread can access it asynchronously. It is |
|
3418 |
* impossible for a race condition to occur because |
|
3419 |
* eventSupport.addNamingListener() must have been called before |
|
3420 |
* the Connection thread can call back to this ctx. |
|
3421 |
*/ |
|
3422 |
public void addNamingListener(Name nm, int scope, NamingListener l) |
|
3423 |
throws NamingException { |
|
3424 |
addNamingListener(getTargetName(nm), scope, l); |
|
3425 |
} |
|
3426 |
||
3427 |
public void addNamingListener(String nm, int scope, NamingListener l) |
|
3428 |
throws NamingException { |
|
3429 |
if (eventSupport == null) |
|
3430 |
eventSupport = new EventSupport(this); |
|
3431 |
eventSupport.addNamingListener(getTargetName(new CompositeName(nm)), |
|
3432 |
scope, l); |
|
3433 |
||
3434 |
// If first time asking for unsol |
|
3435 |
if (l instanceof UnsolicitedNotificationListener && !unsolicited) { |
|
3436 |
addUnsolicited(); |
|
3437 |
} |
|
3438 |
} |
|
3439 |
||
3440 |
public void removeNamingListener(NamingListener l) throws NamingException { |
|
3441 |
if (eventSupport == null) |
|
3442 |
return; // no activity before, so just return |
|
3443 |
||
3444 |
eventSupport.removeNamingListener(l); |
|
3445 |
||
3446 |
// If removing an Unsol listener and it is the last one, let clnt know |
|
3447 |
if (l instanceof UnsolicitedNotificationListener && |
|
3448 |
!eventSupport.hasUnsolicited()) { |
|
3449 |
removeUnsolicited(); |
|
3450 |
} |
|
3451 |
} |
|
3452 |
||
3453 |
public void addNamingListener(String nm, String filter, SearchControls ctls, |
|
3454 |
NamingListener l) throws NamingException { |
|
3455 |
if (eventSupport == null) |
|
3456 |
eventSupport = new EventSupport(this); |
|
3457 |
eventSupport.addNamingListener(getTargetName(new CompositeName(nm)), |
|
3458 |
filter, cloneSearchControls(ctls), l); |
|
3459 |
||
3460 |
// If first time asking for unsol |
|
3461 |
if (l instanceof UnsolicitedNotificationListener && !unsolicited) { |
|
3462 |
addUnsolicited(); |
|
3463 |
} |
|
3464 |
} |
|
3465 |
||
3466 |
public void addNamingListener(Name nm, String filter, SearchControls ctls, |
|
3467 |
NamingListener l) throws NamingException { |
|
3468 |
addNamingListener(getTargetName(nm), filter, ctls, l); |
|
3469 |
} |
|
3470 |
||
3471 |
public void addNamingListener(Name nm, String filter, Object[] filterArgs, |
|
3472 |
SearchControls ctls, NamingListener l) throws NamingException { |
|
3473 |
addNamingListener(getTargetName(nm), filter, filterArgs, ctls, l); |
|
3474 |
} |
|
3475 |
||
3476 |
public void addNamingListener(String nm, String filterExpr, Object[] filterArgs, |
|
3477 |
SearchControls ctls, NamingListener l) throws NamingException { |
|
3478 |
String strfilter = SearchFilter.format(filterExpr, filterArgs); |
|
3479 |
addNamingListener(getTargetName(new CompositeName(nm)), strfilter, ctls, l); |
|
3480 |
} |
|
3481 |
||
3482 |
public boolean targetMustExist() { |
|
3483 |
return true; |
|
3484 |
} |
|
3485 |
||
3486 |
/** |
|
3487 |
* Retrieves the target name for which the listener is registering. |
|
3488 |
* If nm is a CompositeName, use its first and only component. It |
|
3489 |
* cannot have more than one components because a target be outside of |
|
3490 |
* this namespace. If nm is not a CompositeName, then treat it as a |
|
3491 |
* compound name. |
|
3492 |
* @param nm The non-null target name. |
|
3493 |
*/ |
|
3494 |
private static String getTargetName(Name nm) throws NamingException { |
|
3495 |
if (nm instanceof CompositeName) { |
|
3496 |
if (nm.size() > 1) { |
|
3497 |
throw new InvalidNameException( |
|
3498 |
"Target cannot span multiple namespaces: " + nm); |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
8564
diff
changeset
|
3499 |
} else if (nm.isEmpty()) { |
2 | 3500 |
return ""; |
3501 |
} else { |
|
3502 |
return nm.get(0); |
|
3503 |
} |
|
3504 |
} else { |
|
3505 |
// treat as compound name |
|
3506 |
return nm.toString(); |
|
3507 |
} |
|
3508 |
} |
|
3509 |
||
3510 |
// ------------------ Unsolicited Notification --------------- |
|
3511 |
// package private methods for handling unsolicited notification |
|
3512 |
||
3513 |
/** |
|
3514 |
* Registers this context with the underlying LdapClient. |
|
3515 |
* When the underlying LdapClient receives an unsolicited notification, |
|
3516 |
* it will invoke LdapCtx.fireUnsolicited() so that this context |
|
3517 |
* can (using EventSupport) notified any registered listeners. |
|
3518 |
* This method is called by EventSupport when an unsolicited listener |
|
3519 |
* first registers with this context (should be called just once). |
|
3520 |
* @see #removeUnsolicited |
|
3521 |
* @see #fireUnsolicited |
|
3522 |
*/ |
|
3523 |
private void addUnsolicited() throws NamingException { |
|
3524 |
if (debug) { |
|
3525 |
System.out.println("LdapCtx.addUnsolicited: " + this); |
|
3526 |
} |
|
3527 |
||
3528 |
// addNamingListener must have created EventSupport already |
|
3529 |
ensureOpen(); |
|
3530 |
synchronized (eventSupport) { |
|
3531 |
clnt.addUnsolicited(this); |
|
3532 |
unsolicited = true; |
|
3533 |
} |
|
3534 |
} |
|
3535 |
||
3536 |
/** |
|
3537 |
* Removes this context from registering interest in unsolicited |
|
3538 |
* notifications from the underlying LdapClient. This method is called |
|
3539 |
* under any one of the following conditions: |
|
3540 |
* <ul> |
|
3541 |
* <li>All unsolicited listeners have been removed. (see removingNamingListener) |
|
3542 |
* <li>This context is closed. |
|
3543 |
* <li>This context's underlying LdapClient changes. |
|
3544 |
*</ul> |
|
3545 |
* After this method has been called, this context will not pass |
|
3546 |
* on any events related to unsolicited notifications to EventSupport and |
|
3547 |
* and its listeners. |
|
3548 |
*/ |
|
3549 |
||
3550 |
private void removeUnsolicited() { |
|
3551 |
if (debug) { |
|
3552 |
System.out.println("LdapCtx.removeUnsolicited: " + unsolicited); |
|
3553 |
} |
|
3554 |
if (eventSupport == null) { |
|
3555 |
return; |
|
3556 |
} |
|
3557 |
||
3558 |
// addNamingListener must have created EventSupport already |
|
3559 |
synchronized(eventSupport) { |
|
3560 |
if (unsolicited && clnt != null) { |
|
3561 |
clnt.removeUnsolicited(this); |
|
3562 |
} |
|
3563 |
unsolicited = false; |
|
3564 |
} |
|
3565 |
} |
|
3566 |
||
3567 |
/** |
|
3568 |
* Uses EventSupport to fire an event related to an unsolicited notification. |
|
3569 |
* Called by LdapClient when LdapClient receives an unsolicited notification. |
|
3570 |
*/ |
|
3571 |
void fireUnsolicited(Object obj) { |
|
3572 |
if (debug) { |
|
3573 |
System.out.println("LdapCtx.fireUnsolicited: " + obj); |
|
3574 |
} |
|
3575 |
// addNamingListener must have created EventSupport already |
|
3576 |
synchronized(eventSupport) { |
|
3577 |
if (unsolicited) { |
|
3578 |
eventSupport.fireUnsolicited(obj); |
|
3579 |
||
3580 |
if (obj instanceof NamingException) { |
|
3581 |
unsolicited = false; |
|
3582 |
// No need to notify clnt because clnt is the |
|
3583 |
// only one that can fire a NamingException to |
|
3584 |
// unsol listeners and it will handle its own cleanup |
|
3585 |
} |
|
3586 |
} |
|
3587 |
} |
|
3588 |
} |
|
3589 |
} |