001/* 002 * Copyright 2016-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2016-2017 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 */ 021package com.unboundid.ldap.sdk.experimental; 022 023 024 025import java.util.Collections; 026import java.util.List; 027 028import com.unboundid.ldap.sdk.DereferencePolicy; 029import com.unboundid.ldap.sdk.Entry; 030import com.unboundid.ldap.sdk.Filter; 031import com.unboundid.ldap.sdk.LDAPException; 032import com.unboundid.ldap.sdk.OperationType; 033import com.unboundid.ldap.sdk.ResultCode; 034import com.unboundid.ldap.sdk.SearchRequest; 035import com.unboundid.ldap.sdk.SearchScope; 036import com.unboundid.util.Debug; 037import com.unboundid.util.NotMutable; 038import com.unboundid.util.StaticUtils; 039import com.unboundid.util.ThreadSafety; 040import com.unboundid.util.ThreadSafetyLevel; 041 042import 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) 053public 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}