10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.jndi.ldap;
27
28 import javax.naming.*;
29 import javax.naming.directory.*;
30 import javax.naming.spi.*;
31
32 import com.sun.jndi.toolkit.ctx.Continuation;
33 import java.util.NoSuchElementException;
34 import java.util.Vector;
35 import javax.naming.ldap.LdapName;
36
37 /**
38 * Basic enumeration for NameClassPair, Binding, and SearchResults.
39 */
40
41 class LdapNamingEnumeration implements NamingEnumeration, ReferralEnumeration {
42 protected Name listArg;
43
44 private boolean cleaned = false;
45 private LdapResult res;
46 private LdapClient enumClnt;
47 private Continuation cont; // used to fill in exceptions
48 private Vector entries = null;
49 private int limit = 0;
50 private int posn = 0;
51 protected LdapCtx homeCtx;
52 private LdapReferralException refEx = null;
53 private NamingException errEx = null;
54
55 private static final String defaultClassName = DirContext.class.getName();
56
57 /*
58 * Record the next set of entries and/or referrals.
59 */
60 LdapNamingEnumeration(LdapCtx homeCtx, LdapResult answer, Name listArg,
61 Continuation cont) throws NamingException {
62
63 // These checks are to accommodate referrals and limit exceptions
64 // which will generate an enumeration and defer the exception
65 // to be thrown at the end of the enumeration.
66 // All other exceptions are thrown immediately.
67 // Exceptions shouldn't be thrown here anyhow because
68 // process_return_code() is called before the constructor
84 }
85
86 // otherwise continue
87
88 res = answer;
89 entries = answer.entries;
90 limit = (entries == null) ? 0 : entries.size(); // handle empty set
91 this.listArg = listArg;
92 this.cont = cont;
93
94 if (answer.refEx != null) {
95 refEx = answer.refEx;
96 }
97
98 // Ensures that context won't get closed from underneath us
99 this.homeCtx = homeCtx;
100 homeCtx.incEnumCount();
101 enumClnt = homeCtx.clnt; // remember
102 }
103
104 public Object nextElement() {
105 try {
106 return next();
107 } catch (NamingException e) {
108 // can't throw exception
109 cleanup();
110 return null;
111 }
112 }
113
114 public boolean hasMoreElements() {
115 try {
116 return hasMore();
117 } catch (NamingException e) {
118 // can't throw exception
119 cleanup();
120 return false;
121 }
122 }
123
124 /*
129 res = homeCtx.getSearchReply(enumClnt, res);
130 if (res == null) {
131 limit = posn = 0;
132 return;
133 }
134
135 entries = res.entries;
136 limit = (entries == null) ? 0 : entries.size(); // handle empty set
137 posn = 0; // reset
138
139 // mimimize the number of calls to processReturnCode()
140 // (expensive when batchSize is small and there are many results)
141 if ((res.status != LdapClient.LDAP_SUCCESS) ||
142 ((res.status == LdapClient.LDAP_SUCCESS) &&
143 (res.referrals != null))) {
144
145 try {
146 // convert referrals into a chain of LdapReferralException
147 homeCtx.processReturnCode(res, listArg);
148
149 } catch (LimitExceededException e) {
150 setNamingException(e);
151
152 } catch (PartialResultException e) {
153 setNamingException(e);
154 }
155 }
156
157 // merge any newly received referrals with any current referrals
158 if (res.refEx != null) {
159 if (refEx == null) {
160 refEx = res.refEx;
161 } else {
162 refEx = refEx.appendUnprocessedReferrals(res.refEx);
163 }
164 res.refEx = null; // reset
165 }
166
167 if (res.resControls != null) {
168 homeCtx.respCtls = res.resControls;
169 }
170 }
171
172 private boolean more = true; // assume we have something to start with
173 private boolean hasMoreCalled = false;
176 * Test if unprocessed entries or referrals exist.
177 */
178 public boolean hasMore() throws NamingException {
179
180 if (hasMoreCalled) {
181 return more;
182 }
183
184 hasMoreCalled = true;
185
186 if (!more) {
187 return false;
188 } else {
189 return (more = hasMoreImpl());
190 }
191 }
192
193 /*
194 * Retrieve the next entry.
195 */
196 public Object next() throws NamingException {
197
198 if (!hasMoreCalled) {
199 hasMore();
200 }
201 hasMoreCalled = false;
202 return nextImpl();
203 }
204
205 /*
206 * Test if unprocessed entries or referrals exist.
207 */
208 private boolean hasMoreImpl() throws NamingException {
209 // when page size is supported, this
210 // might generate an exception while attempting
211 // to fetch the next batch to determine
212 // whether there are any more elements
213
214 // test if the current set of entries has been processed
215 if (posn == limit) {
216 getNextBatch();
217 }
218
219 // test if any unprocessed entries exist
220 if (posn < limit) {
221 return true;
222 } else {
223
224 try {
225 // try to process another referral
226 return hasMoreReferrals();
227
228 } catch (LdapReferralException e) {
229 cleanup();
230 throw e;
231
232 } catch (LimitExceededException e) {
233 cleanup();
234 throw e;
235
236 } catch (PartialResultException e) {
237 cleanup();
238 throw e;
239
240 } catch (NamingException e) {
241 cleanup();
242 PartialResultException pre = new PartialResultException();
243 pre.setRootCause(e);
244 throw pre;
245 }
246 }
247 }
248
249 /*
250 * Retrieve the next entry.
251 */
252 private Object nextImpl() throws NamingException {
253 try {
254 return nextAux();
255 } catch (NamingException e) {
256 cleanup();
257 throw cont.fillInException(e);
258 }
259 }
260
261 private Object nextAux() throws NamingException {
262 if (posn == limit) {
263 getNextBatch(); // updates posn and limit
264 }
265
266 if (posn >= limit) {
267 cleanup();
268 throw new NoSuchElementException("invalid enumeration handle");
269 }
270
271 LdapEntry result = (LdapEntry)entries.elementAt(posn++);
272
273 // gets and outputs DN from the entry
274 return createItem(result.DN, result.attributes, result.respCtls);
275 }
276
277 protected String getAtom(String dn) {
278 String atom;
279 // need to strip off all but lowest component of dn
280 // so that is relative to current context (currentDN)
281 try {
282 Name parsed = new LdapName(dn);
283 return parsed.get(parsed.size() - 1);
284 } catch (NamingException e) {
285 return dn;
286 }
287 }
288
289 protected NameClassPair createItem(String dn, Attributes attrs,
290 Vector respCtls) throws NamingException {
291
292 Attribute attr;
293 String className = null;
294
295 // use the Java classname if present
296 if ((attr = attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME])) != null) {
297 className = (String)attr.get();
298 } else {
299 className = defaultClassName;
300 }
301 CompositeName cn = new CompositeName();
302 cn.add(getAtom(dn));
303
304 NameClassPair ncp;
305 if (respCtls != null) {
306 ncp = new NameClassPairWithControls(
307 cn.toString(), className,
308 homeCtx.convertControls(respCtls));
309 } else {
310 ncp = new NameClassPair(cn.toString(), className);
|
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.jndi.ldap;
27
28 import javax.naming.*;
29 import javax.naming.directory.*;
30
31 import com.sun.jndi.toolkit.ctx.Continuation;
32 import java.util.NoSuchElementException;
33 import java.util.Vector;
34 import javax.naming.ldap.Control;
35 import javax.naming.ldap.LdapName;
36
37 /**
38 * Basic enumeration for NameClassPair, Binding, and SearchResults.
39 */
40
41 class LdapNamingEnumeration implements NamingEnumeration<NameClassPair>,
42 ReferralEnumeration<NameClassPair> {
43 protected Name listArg;
44
45 private boolean cleaned = false;
46 private LdapResult res;
47 private LdapClient enumClnt;
48 private Continuation cont; // used to fill in exceptions
49 private Vector<LdapEntry> entries = null;
50 private int limit = 0;
51 private int posn = 0;
52 protected LdapCtx homeCtx;
53 private LdapReferralException refEx = null;
54 private NamingException errEx = null;
55
56 private static final String defaultClassName = DirContext.class.getName();
57
58 /*
59 * Record the next set of entries and/or referrals.
60 */
61 LdapNamingEnumeration(LdapCtx homeCtx, LdapResult answer, Name listArg,
62 Continuation cont) throws NamingException {
63
64 // These checks are to accommodate referrals and limit exceptions
65 // which will generate an enumeration and defer the exception
66 // to be thrown at the end of the enumeration.
67 // All other exceptions are thrown immediately.
68 // Exceptions shouldn't be thrown here anyhow because
69 // process_return_code() is called before the constructor
85 }
86
87 // otherwise continue
88
89 res = answer;
90 entries = answer.entries;
91 limit = (entries == null) ? 0 : entries.size(); // handle empty set
92 this.listArg = listArg;
93 this.cont = cont;
94
95 if (answer.refEx != null) {
96 refEx = answer.refEx;
97 }
98
99 // Ensures that context won't get closed from underneath us
100 this.homeCtx = homeCtx;
101 homeCtx.incEnumCount();
102 enumClnt = homeCtx.clnt; // remember
103 }
104
105 public NameClassPair nextElement() {
106 try {
107 return next();
108 } catch (NamingException e) {
109 // can't throw exception
110 cleanup();
111 return null;
112 }
113 }
114
115 public boolean hasMoreElements() {
116 try {
117 return hasMore();
118 } catch (NamingException e) {
119 // can't throw exception
120 cleanup();
121 return false;
122 }
123 }
124
125 /*
130 res = homeCtx.getSearchReply(enumClnt, res);
131 if (res == null) {
132 limit = posn = 0;
133 return;
134 }
135
136 entries = res.entries;
137 limit = (entries == null) ? 0 : entries.size(); // handle empty set
138 posn = 0; // reset
139
140 // mimimize the number of calls to processReturnCode()
141 // (expensive when batchSize is small and there are many results)
142 if ((res.status != LdapClient.LDAP_SUCCESS) ||
143 ((res.status == LdapClient.LDAP_SUCCESS) &&
144 (res.referrals != null))) {
145
146 try {
147 // convert referrals into a chain of LdapReferralException
148 homeCtx.processReturnCode(res, listArg);
149
150 } catch (LimitExceededException | PartialResultException e) {
151 setNamingException(e);
152
153 }
154 }
155
156 // merge any newly received referrals with any current referrals
157 if (res.refEx != null) {
158 if (refEx == null) {
159 refEx = res.refEx;
160 } else {
161 refEx = refEx.appendUnprocessedReferrals(res.refEx);
162 }
163 res.refEx = null; // reset
164 }
165
166 if (res.resControls != null) {
167 homeCtx.respCtls = res.resControls;
168 }
169 }
170
171 private boolean more = true; // assume we have something to start with
172 private boolean hasMoreCalled = false;
175 * Test if unprocessed entries or referrals exist.
176 */
177 public boolean hasMore() throws NamingException {
178
179 if (hasMoreCalled) {
180 return more;
181 }
182
183 hasMoreCalled = true;
184
185 if (!more) {
186 return false;
187 } else {
188 return (more = hasMoreImpl());
189 }
190 }
191
192 /*
193 * Retrieve the next entry.
194 */
195 public NameClassPair next() throws NamingException {
196
197 if (!hasMoreCalled) {
198 hasMore();
199 }
200 hasMoreCalled = false;
201 return nextImpl();
202 }
203
204 /*
205 * Test if unprocessed entries or referrals exist.
206 */
207 private boolean hasMoreImpl() throws NamingException {
208 // when page size is supported, this
209 // might generate an exception while attempting
210 // to fetch the next batch to determine
211 // whether there are any more elements
212
213 // test if the current set of entries has been processed
214 if (posn == limit) {
215 getNextBatch();
216 }
217
218 // test if any unprocessed entries exist
219 if (posn < limit) {
220 return true;
221 } else {
222
223 try {
224 // try to process another referral
225 return hasMoreReferrals();
226
227 } catch (LdapReferralException |
228 LimitExceededException |
229 PartialResultException e) {
230 cleanup();
231 throw e;
232
233 } catch (NamingException e) {
234 cleanup();
235 PartialResultException pre = new PartialResultException();
236 pre.setRootCause(e);
237 throw pre;
238 }
239 }
240 }
241
242 /*
243 * Retrieve the next entry.
244 */
245 private NameClassPair nextImpl() throws NamingException {
246 try {
247 return nextAux();
248 } catch (NamingException e) {
249 cleanup();
250 throw cont.fillInException(e);
251 }
252 }
253
254 private NameClassPair nextAux() throws NamingException {
255 if (posn == limit) {
256 getNextBatch(); // updates posn and limit
257 }
258
259 if (posn >= limit) {
260 cleanup();
261 throw new NoSuchElementException("invalid enumeration handle");
262 }
263
264 LdapEntry result = entries.elementAt(posn++);
265
266 // gets and outputs DN from the entry
267 return createItem(result.DN, result.attributes, result.respCtls);
268 }
269
270 protected String getAtom(String dn) {
271 String atom;
272 // need to strip off all but lowest component of dn
273 // so that is relative to current context (currentDN)
274 try {
275 Name parsed = new LdapName(dn);
276 return parsed.get(parsed.size() - 1);
277 } catch (NamingException e) {
278 return dn;
279 }
280 }
281
282 protected NameClassPair createItem(String dn, Attributes attrs,
283 Vector<Control> respCtls) throws NamingException {
284
285 Attribute attr;
286 String className = null;
287
288 // use the Java classname if present
289 if ((attr = attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME])) != null) {
290 className = (String)attr.get();
291 } else {
292 className = defaultClassName;
293 }
294 CompositeName cn = new CompositeName();
295 cn.add(getAtom(dn));
296
297 NameClassPair ncp;
298 if (respCtls != null) {
299 ncp = new NameClassPairWithControls(
300 cn.toString(), className,
301 homeCtx.convertControls(respCtls));
302 } else {
303 ncp = new NameClassPair(cn.toString(), className);
|