001 /*
002 * Copyright 2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2016 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk.experimental;
022
023
024
025 import java.util.Collections;
026 import java.util.List;
027
028 import com.unboundid.ldap.sdk.DereferencePolicy;
029 import com.unboundid.ldap.sdk.Entry;
030 import com.unboundid.ldap.sdk.Filter;
031 import com.unboundid.ldap.sdk.LDAPException;
032 import com.unboundid.ldap.sdk.OperationType;
033 import com.unboundid.ldap.sdk.ResultCode;
034 import com.unboundid.ldap.sdk.SearchRequest;
035 import com.unboundid.ldap.sdk.SearchScope;
036 import com.unboundid.util.Debug;
037 import com.unboundid.util.NotMutable;
038 import com.unboundid.util.StaticUtils;
039 import com.unboundid.util.ThreadSafety;
040 import com.unboundid.util.ThreadSafetyLevel;
041
042 import static com.unboundid.ldap.sdk.experimental.ExperimentalMessages.*;
043
044
045
046 /**
047 * This class represents an entry that holds information about a search
048 * operation processed by an LDAP server, as per the specification described in
049 * draft-chu-ldap-logschema-00.
050 */
051 @NotMutable()
052 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
053 public final class DraftChuLDAPLogSchema00SearchEntry
054 extends DraftChuLDAPLogSchema00Entry
055 {
056 /**
057 * The name of the attribute used to hold the alias dereference policy.
058 */
059 public static final String ATTR_DEREFERENCE_POLICY = "reqDerefAliases";
060
061
062
063 /**
064 * The name of the attribute used to hold the number of entries returned.
065 */
066 public static final String ATTR_ENTRIES_RETURNED = "reqEntries";
067
068
069
070 /**
071 * The name of the attribute used to hold the search filter.
072 */
073 public static final String ATTR_FILTER = "reqFilter";
074
075
076
077 /**
078 * The name of the attribute used to hold a requested attribute.
079 */
080 public static final String ATTR_REQUESTED_ATTRIBUTE = "reqAttr";
081
082
083
084 /**
085 * The name of the attribute used to hold the search scope.
086 */
087 public static final String ATTR_SCOPE = "reqScope";
088
089
090
091 /**
092 * The name of the attribute used to hold the requested size limit.
093 */
094 public static final String ATTR_SIZE_LIMIT = "reqSizeLimit";
095
096
097
098 /**
099 * The name of the attribute used to hold the requested time limit in seconds.
100 */
101 public static final String ATTR_TIME_LIMIT_SECONDS = "reqTimeLimit";
102
103
104
105 /**
106 * The name of the attribute used to hold the value of the typesOnly flag.
107 */
108 public static final String ATTR_TYPES_ONLY = "reqAttrsOnly";
109
110
111
112 /**
113 * The serial version UID for this serializable class.
114 */
115 private static final long serialVersionUID = 948178493925578134L;
116
117
118
119 // The types only flag.
120 private final boolean typesOnly;
121
122 // The alias dereference policy.
123 private final DereferencePolicy dereferencePolicy;
124
125 // The search filter.
126 private final Filter filter;
127
128 // The number of entries returned.
129 private final Integer entriesReturned;
130
131 // The requested size limit.
132 private final Integer requestedSizeLimit;
133
134 // The requested time limit in seconds.
135 private final Integer requestedTimeLimitSeconds;
136
137 // The list of requested attributes.
138 private final List<String> requestedAttributes;
139
140 // The search scope.
141 private final SearchScope scope;
142
143
144
145 /**
146 * Creates a new instance of this search access log entry from the provided
147 * entry.
148 *
149 * @param entry The entry used to create this search access log entry.
150 *
151 * @throws LDAPException If the provided entry cannot be decoded as a valid
152 * search access log entry as per the specification
153 * contained in draft-chu-ldap-logschema-00.
154 */
155 public DraftChuLDAPLogSchema00SearchEntry(final Entry entry)
156 throws LDAPException
157 {
158 super(entry, OperationType.SEARCH);
159
160
161 // Get the scope.
162 final String scopeStr = entry.getAttributeValue(ATTR_SCOPE);
163 if (scopeStr == null)
164 {
165 throw new LDAPException(ResultCode.DECODING_ERROR,
166 ERR_LOGSCHEMA_DECODE_MISSING_REQUIRED_ATTR.get(entry.getDN(),
167 ATTR_SCOPE));
168 }
169
170 final String lowerScope = StaticUtils.toLowerCase(scopeStr);
171 if (lowerScope.equals("base"))
172 {
173 scope = SearchScope.BASE;
174 }
175 else if (lowerScope.equals("one"))
176 {
177 scope = SearchScope.ONE;
178 }
179 else if (lowerScope.equals("sub"))
180 {
181 scope = SearchScope.SUB;
182 }
183 else if (lowerScope.equals("subord"))
184 {
185 scope = SearchScope.SUBORDINATE_SUBTREE;
186 }
187 else
188 {
189 throw new LDAPException(ResultCode.DECODING_ERROR,
190 ERR_LOGSCHEMA_DECODE_SEARCH_SCOPE_ERROR.get(entry.getDN(),
191 ATTR_SCOPE, scopeStr));
192 }
193
194
195 // Get the dereference policy.
196 final String derefStr = entry.getAttributeValue(ATTR_DEREFERENCE_POLICY);
197 if (derefStr == null)
198 {
199 throw new LDAPException(ResultCode.DECODING_ERROR,
200 ERR_LOGSCHEMA_DECODE_MISSING_REQUIRED_ATTR.get(entry.getDN(),
201 ATTR_DEREFERENCE_POLICY));
202 }
203
204 final String lowerDeref = StaticUtils.toLowerCase(derefStr);
205 if (lowerDeref.equals("never"))
206 {
207 dereferencePolicy = DereferencePolicy.NEVER;
208 }
209 else if (lowerDeref.equals("searching"))
210 {
211 dereferencePolicy = DereferencePolicy.SEARCHING;
212 }
213 else if (lowerDeref.equals("finding"))
214 {
215 dereferencePolicy = DereferencePolicy.FINDING;
216 }
217 else if (lowerDeref.equals("always"))
218 {
219 dereferencePolicy = DereferencePolicy.ALWAYS;
220 }
221 else
222 {
223 throw new LDAPException(ResultCode.DECODING_ERROR,
224 ERR_LOGSCHEMA_DECODE_SEARCH_DEREF_ERROR.get(entry.getDN(),
225 ATTR_DEREFERENCE_POLICY, derefStr));
226 }
227
228
229 // Get the typesOnly flag.
230 final String typesOnlyStr = entry.getAttributeValue(ATTR_TYPES_ONLY);
231 if (typesOnlyStr == null)
232 {
233 throw new LDAPException(ResultCode.DECODING_ERROR,
234 ERR_LOGSCHEMA_DECODE_MISSING_REQUIRED_ATTR.get(entry.getDN(),
235 ATTR_TYPES_ONLY));
236 }
237
238 final String lowerTypesOnly = StaticUtils.toLowerCase(typesOnlyStr);
239 if (lowerTypesOnly.equals("true"))
240 {
241 typesOnly = true;
242 }
243 else if (lowerTypesOnly.equals("false"))
244 {
245 typesOnly = false;
246 }
247 else
248 {
249 throw new LDAPException(ResultCode.DECODING_ERROR,
250 ERR_LOGSCHEMA_DECODE_SEARCH_TYPES_ONLY_ERROR.get(entry.getDN(),
251 ATTR_TYPES_ONLY, typesOnlyStr));
252 }
253
254
255 // Get the filter. For some strange reason, this is allowed to be
256 // undefined.
257 final String filterStr = entry.getAttributeValue(ATTR_FILTER);
258 if (filterStr == null)
259 {
260 filter = null;
261 }
262 else
263 {
264 try
265 {
266 filter = Filter.create(filterStr);
267 }
268 catch (final Exception e)
269 {
270 Debug.debugException(e);
271 throw new LDAPException(ResultCode.DECODING_ERROR,
272 ERR_LOGSCHEMA_DECODE_SEARCH_FILTER_ERROR.get(entry.getDN(),
273 ATTR_FILTER, filterStr),
274 e);
275 }
276 }
277
278
279 // Get the set of requested attributes.
280 final String[] requestedAttrArray =
281 entry.getAttributeValues(ATTR_REQUESTED_ATTRIBUTE);
282 if ((requestedAttrArray == null) || (requestedAttrArray.length == 0))
283 {
284 requestedAttributes = Collections.emptyList();
285 }
286 else
287 {
288 requestedAttributes =
289 Collections.unmodifiableList(StaticUtils.toList(requestedAttrArray));
290 }
291
292
293 // Get the requested size limit.
294 final String sizeLimitStr = entry.getAttributeValue(ATTR_SIZE_LIMIT);
295 if (sizeLimitStr == null)
296 {
297 requestedSizeLimit = null;
298 }
299 else
300 {
301 try
302 {
303 requestedSizeLimit = Integer.parseInt(sizeLimitStr);
304 }
305 catch (final Exception e)
306 {
307 Debug.debugException(e);
308 throw new LDAPException(ResultCode.DECODING_ERROR,
309 ERR_LOGSCHEMA_DECODE_SEARCH_INT_ERROR.get(entry.getDN(),
310 ATTR_SIZE_LIMIT, sizeLimitStr),
311 e);
312 }
313 }
314
315
316 // Get the requested time limit.
317 final String timeLimitStr =
318 entry.getAttributeValue(ATTR_TIME_LIMIT_SECONDS);
319 if (timeLimitStr == null)
320 {
321 requestedTimeLimitSeconds = null;
322 }
323 else
324 {
325 try
326 {
327 requestedTimeLimitSeconds = Integer.parseInt(timeLimitStr);
328 }
329 catch (final Exception e)
330 {
331 Debug.debugException(e);
332 throw new LDAPException(ResultCode.DECODING_ERROR,
333 ERR_LOGSCHEMA_DECODE_SEARCH_INT_ERROR.get(entry.getDN(),
334 ATTR_TIME_LIMIT_SECONDS, timeLimitStr),
335 e);
336 }
337 }
338
339
340 // Get the number of entries returned.
341 final String entriesReturnedStr =
342 entry.getAttributeValue(ATTR_ENTRIES_RETURNED);
343 if (entriesReturnedStr == null)
344 {
345 entriesReturned = null;
346 }
347 else
348 {
349 try
350 {
351 entriesReturned = Integer.parseInt(entriesReturnedStr);
352 }
353 catch (final Exception e)
354 {
355 Debug.debugException(e);
356 throw new LDAPException(ResultCode.DECODING_ERROR,
357 ERR_LOGSCHEMA_DECODE_SEARCH_INT_ERROR.get(entry.getDN(),
358 ATTR_ENTRIES_RETURNED, entriesReturnedStr),
359 e);
360 }
361 }
362 }
363
364
365
366 /**
367 * Retrieves the scope for the search request described by this search access
368 * log entry.
369 *
370 * @return The scope for the search request described by this search access
371 * log entry.
372 */
373 public SearchScope getScope()
374 {
375 return scope;
376 }
377
378
379
380 /**
381 * Retrieves the alias dereference policy for the search request described by
382 * this search access log entry.
383 *
384 * @return The alias dereference policy for the search request described by
385 * this search access log entry.
386 */
387 public DereferencePolicy getDereferencePolicy()
388 {
389 return dereferencePolicy;
390 }
391
392
393
394 /**
395 * Retrieves the value of the typesOnly flag for the search request described
396 * by this search access log entry.
397 *
398 * @return The value of the typesOnly flag for the search request described
399 * by this search access log entry.
400 */
401 public boolean typesOnly()
402 {
403 return typesOnly;
404 }
405
406
407
408 /**
409 * Retrieves the filter for the search request described by this search access
410 * log entry, if available.
411 *
412 * @return The filter for the search request described by this search access
413 * log entry, or {@code null} if no filter was included in the access
414 * log entry.
415 */
416 public Filter getFilter()
417 {
418 return filter;
419 }
420
421
422
423 /**
424 * Retrieves the requested size limit for the search request described by this
425 * search access log entry, if available.
426 *
427 * @return The requested size limit for the search request described by this
428 * search access log entry, or {@code null} if no size limit was
429 * included in the access log entry.
430 */
431 public Integer getRequestedSizeLimit()
432 {
433 return requestedSizeLimit;
434 }
435
436
437
438 /**
439 * Retrieves the requested time limit (in seconds) for the search request
440 * described by this search access log entry, if available.
441 *
442 * @return The requested time limit (in seconds) for the search request
443 * described by this search access log entry, or {@code null} if no
444 * time limit was included in the access log entry.
445 */
446 public Integer getRequestedTimeLimitSeconds()
447 {
448 return requestedTimeLimitSeconds;
449 }
450
451
452
453 /**
454 * Retrieves the requested attributes for the search request described by this
455 * search access log entry, if available.
456 *
457 * @return The requested attributes for the search request described by this
458 * search access log entry, or an empty list if no requested
459 * attributes were included in the access log entry.
460 */
461 public List<String> getRequestedAttributes()
462 {
463 return requestedAttributes;
464 }
465
466
467
468 /**
469 * Retrieves the number of entries returned to the client in response to the
470 * search request described by this search access log entry, if available.
471 *
472 * @return The number of entries returned to the client in response to the
473 * search request described by this search access log entry, or
474 * {@code null} if the number of entries returned was not included in
475 * the access log entry.
476 */
477 public Integer getEntriesReturned()
478 {
479 return entriesReturned;
480 }
481
482
483
484 /**
485 * Retrieves a {@code SearchRequest} created from this search access log
486 * entry. If the size limit or time limit was not present in the entry, a
487 * default of zero will be used. If the filter was not present in the entry,
488 * a default of "(objectClass=*)" will be used.
489 *
490 * @return The {@code SearchRequest} created from this search access log
491 * entry.
492 */
493 public SearchRequest toSearchRequest()
494 {
495 final int sizeLimit =
496 ((requestedSizeLimit == null)
497 ? 0
498 : requestedSizeLimit);
499 final int timeLimit =
500 ((requestedTimeLimitSeconds == null)
501 ? 0
502 : requestedTimeLimitSeconds);
503 final Filter f =
504 ((filter == null)
505 ? Filter.createPresenceFilter("objectClass")
506 : filter);
507
508 final String[] attrArray =
509 requestedAttributes.toArray(StaticUtils.NO_STRINGS);
510
511 final SearchRequest searchRequest = new SearchRequest(getTargetEntryDN(),
512 scope, dereferencePolicy, sizeLimit, timeLimit, typesOnly, f,
513 attrArray);
514 searchRequest.setControls(getRequestControlArray());
515 return searchRequest;
516 }
517 }