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