001 /*
002 * Copyright 2009-2015 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2015 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.unboundidds.logs;
022
023
024
025 import java.util.Collections;
026 import java.util.LinkedList;
027 import java.util.List;
028 import java.util.StringTokenizer;
029
030 import com.unboundid.ldap.sdk.ResultCode;
031 import com.unboundid.ldap.sdk.unboundidds.controls.AssuredReplicationLocalLevel;
032 import com.unboundid.ldap.sdk.unboundidds.controls.
033 AssuredReplicationRemoteLevel;
034 import com.unboundid.util.NotExtensible;
035 import com.unboundid.util.NotMutable;
036 import com.unboundid.util.ThreadSafety;
037 import com.unboundid.util.ThreadSafetyLevel;
038
039
040
041 /**
042 * <BLOCKQUOTE>
043 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID
044 * LDAP SDK for Java. It is not available for use in applications that
045 * include only the Standard Edition of the LDAP SDK, and is not supported for
046 * use in conjunction with non-UnboundID products.
047 * </BLOCKQUOTE>
048 * This class provides a data structure that holds information about a log
049 * message that may appear in the Directory Server access log about the result
050 * of a modify operation processed by the Directory Server.
051 */
052 @NotExtensible()
053 @NotMutable()
054 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
055 public class ModifyResultAccessLogMessage
056 extends ModifyRequestAccessLogMessage
057 implements OperationResultAccessLogMessage
058 {
059 /**
060 * The serial version UID for this serializable class.
061 */
062 private static final long serialVersionUID = -4950863829060893245L;
063
064
065
066 // The assured replication level to use for local servers.
067 private final AssuredReplicationLocalLevel assuredReplicationLocalLevel;
068
069 // The assured replication level to use for remote servers.
070 private final AssuredReplicationRemoteLevel assuredReplicationRemoteLevel;
071
072 // Indicates whether the response was known to be delayed by replication
073 // assurance processing.
074 private final Boolean responseDelayedByAssurance;
075
076 // Indicates whether the delete operation targeted a soft-deleted entry.
077 private final Boolean changeToSoftDeletedEntry;
078
079 // Indicates whether the any uncached data was accessed in the course of
080 // processing this operation.
081 private final Boolean uncachedDataAccessed;
082
083 // The processing time for the operation.
084 private final Double processingTime;
085
086 // The queue time for the operation.
087 private final Double queueTime;
088
089 // The port of the backend server to which the request has been forwarded.
090 private final Integer targetPort;
091
092 // The list of privileges required for processing the operation that the
093 // requester did not have.
094 private final List<String> missingPrivileges;
095
096 // The list of privileges used during the course of processing the operation
097 // before an alternate authorization identity was assigned.
098 private final List<String> preAuthZUsedPrivileges;
099
100 // The list of referral URLs for the operation.
101 private final List<String> referralURLs;
102
103 // The list of response control OIDs for the operation.
104 private final List<String> responseControlOIDs;
105
106 // The list of servers accessed while processing the operation.
107 private final List<String> serversAccessed;
108
109 // The list of privileges used during the course of processing the operation.
110 private final List<String> usedPrivileges;
111
112 // The assured replication timeout, in milliseconds.
113 private final Long assuredReplicationTimeoutMillis;
114
115 // The number of intermediate response messages returned to the client.
116 private final Long intermediateResponsesReturned;
117
118 // The result code for the operation.
119 private final ResultCode resultCode;
120
121 // Additional information about the operation result.
122 private final String additionalInformation;
123
124 // The alternate authorization DN for the operation.
125 private final String authzDN;
126
127 // The diagnostic message for the operation.
128 private final String diagnosticMessage;
129
130 // The intermediate client result for the operation.
131 private final String intermediateClientResult;
132
133 // The matched DN for the operation.
134 private final String matchedDN;
135
136 // The replication change ID for the operation.
137 private final String replicationChangeID;
138
139 // The address of the backend server to which the request has been forwarded.
140 private final String targetHost;
141
142 // The protocol used to forward the request to the backend server.
143 private final String targetProtocol;
144
145
146
147 /**
148 * Creates a new modify result access log message from the provided message
149 * string.
150 *
151 * @param s The string to be parsed as a modify result access log message.
152 *
153 * @throws LogException If the provided string cannot be parsed as a valid
154 * log message.
155 */
156 public ModifyResultAccessLogMessage(final String s)
157 throws LogException
158 {
159 this(new LogMessage(s));
160 }
161
162
163
164 /**
165 * Creates a new modify result access log message from the provided log
166 * message.
167 *
168 * @param m The log message to be parsed as a modify result access log
169 * message.
170 */
171 public ModifyResultAccessLogMessage(final LogMessage m)
172 {
173 super(m);
174
175 diagnosticMessage = getNamedValue("message");
176 additionalInformation = getNamedValue("additionalInfo");
177 matchedDN = getNamedValue("matchedDN");
178 processingTime = getNamedValueAsDouble("etime");
179 queueTime = getNamedValueAsDouble("qtime");
180 intermediateClientResult = getNamedValue("from");
181 authzDN = getNamedValue("authzDN");
182 replicationChangeID = getNamedValue("replicationChangeID");
183 targetHost = getNamedValue("targetHost");
184 targetPort = getNamedValueAsInteger("targetPort");
185 targetProtocol = getNamedValue("targetProtocol");
186
187 changeToSoftDeletedEntry =
188 getNamedValueAsBoolean("changeToSoftDeletedEntry");
189 intermediateResponsesReturned =
190 getNamedValueAsLong("intermediateResponsesReturned");
191
192 final Integer rcInteger = getNamedValueAsInteger("resultCode");
193 if (rcInteger == null)
194 {
195 resultCode = null;
196 }
197 else
198 {
199 resultCode = ResultCode.valueOf(rcInteger);
200 }
201
202 final String refStr = getNamedValue("referralURLs");
203 if ((refStr == null) || (refStr.length() == 0))
204 {
205 referralURLs = Collections.emptyList();
206 }
207 else
208 {
209 final LinkedList<String> refs = new LinkedList<String>();
210 int startPos = 0;
211 while (true)
212 {
213 final int commaPos = refStr.indexOf(",ldap", startPos);
214 if (commaPos < 0)
215 {
216 refs.add(refStr.substring(startPos));
217 break;
218 }
219 else
220 {
221 refs.add(refStr.substring(startPos, commaPos));
222 startPos = commaPos+1;
223 }
224 }
225 referralURLs = Collections.unmodifiableList(refs);
226 }
227
228 final String controlStr = getNamedValue("responseControls");
229 if (controlStr == null)
230 {
231 responseControlOIDs = Collections.emptyList();
232 }
233 else
234 {
235 final LinkedList<String> controlList = new LinkedList<String>();
236 final StringTokenizer t = new StringTokenizer(controlStr, ",");
237 while (t.hasMoreTokens())
238 {
239 controlList.add(t.nextToken());
240 }
241 responseControlOIDs = Collections.unmodifiableList(controlList);
242 }
243
244 final String serversAccessedStr = getNamedValue("serversAccessed");
245 if ((serversAccessedStr == null) || (serversAccessedStr.length() == 0))
246 {
247 serversAccessed = Collections.emptyList();
248 }
249 else
250 {
251 final LinkedList<String> servers = new LinkedList<String>();
252 final StringTokenizer tokenizer =
253 new StringTokenizer(serversAccessedStr, ",");
254 while (tokenizer.hasMoreTokens())
255 {
256 servers.add(tokenizer.nextToken());
257 }
258 serversAccessed = Collections.unmodifiableList(servers);
259 }
260
261 uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed");
262
263
264 final String localLevelStr = getNamedValue("localAssuranceLevel");
265 if (localLevelStr == null)
266 {
267 assuredReplicationLocalLevel = null;
268 }
269 else
270 {
271 assuredReplicationLocalLevel =
272 AssuredReplicationLocalLevel.valueOf(localLevelStr);
273 }
274
275 final String remoteLevelStr = getNamedValue("remoteAssuranceLevel");
276 if (remoteLevelStr == null)
277 {
278 assuredReplicationRemoteLevel = null;
279 }
280 else
281 {
282 assuredReplicationRemoteLevel =
283 AssuredReplicationRemoteLevel.valueOf(remoteLevelStr);
284 }
285
286 assuredReplicationTimeoutMillis =
287 getNamedValueAsLong("assuranceTimeoutMillis");
288 responseDelayedByAssurance =
289 getNamedValueAsBoolean("responseDelayedByAssurance");
290
291 final String usedPrivilegesStr = getNamedValue("usedPrivileges");
292 if ((usedPrivilegesStr == null) || (usedPrivilegesStr.length() == 0))
293 {
294 usedPrivileges = Collections.emptyList();
295 }
296 else
297 {
298 final LinkedList<String> privileges = new LinkedList<String>();
299 final StringTokenizer tokenizer =
300 new StringTokenizer(usedPrivilegesStr, ",");
301 while (tokenizer.hasMoreTokens())
302 {
303 privileges.add(tokenizer.nextToken());
304 }
305 usedPrivileges = Collections.unmodifiableList(privileges);
306 }
307
308 final String preAuthZUsedPrivilegesStr =
309 getNamedValue("preAuthZUsedPrivileges");
310 if ((preAuthZUsedPrivilegesStr == null) ||
311 (preAuthZUsedPrivilegesStr.length() == 0))
312 {
313 preAuthZUsedPrivileges = Collections.emptyList();
314 }
315 else
316 {
317 final LinkedList<String> privileges = new LinkedList<String>();
318 final StringTokenizer tokenizer =
319 new StringTokenizer(preAuthZUsedPrivilegesStr, ",");
320 while (tokenizer.hasMoreTokens())
321 {
322 privileges.add(tokenizer.nextToken());
323 }
324 preAuthZUsedPrivileges = Collections.unmodifiableList(privileges);
325 }
326
327 final String missingPrivilegesStr = getNamedValue("missingPrivileges");
328 if ((missingPrivilegesStr == null) || (missingPrivilegesStr.length() == 0))
329 {
330 missingPrivileges = Collections.emptyList();
331 }
332 else
333 {
334 final LinkedList<String> privileges = new LinkedList<String>();
335 final StringTokenizer tokenizer =
336 new StringTokenizer(missingPrivilegesStr, ",");
337 while (tokenizer.hasMoreTokens())
338 {
339 privileges.add(tokenizer.nextToken());
340 }
341 missingPrivileges = Collections.unmodifiableList(privileges);
342 }
343 }
344
345
346
347 /**
348 * Retrieves the result code for the operation.
349 *
350 * @return The result code for the operation, or {@code null} if it is not
351 * included in the log message.
352 */
353 public ResultCode getResultCode()
354 {
355 return resultCode;
356 }
357
358
359
360 /**
361 * Retrieves the diagnostic message for the operation.
362 *
363 * @return The diagnostic message for the operation, or {@code null} if it is
364 * not included in the log message.
365 */
366 public String getDiagnosticMessage()
367 {
368 return diagnosticMessage;
369 }
370
371
372
373 /**
374 * Retrieves a message with additional information about the result of the
375 * operation.
376 *
377 * @return A message with additional information about the result of the
378 * operation, or {@code null} if it is not included in the log
379 * message.
380 */
381 public String getAdditionalInformation()
382 {
383 return additionalInformation;
384 }
385
386
387
388 /**
389 * Retrieves the matched DN for the operation.
390 *
391 * @return The matched DN for the operation, or {@code null} if it is not
392 * included in the log message.
393 */
394 public String getMatchedDN()
395 {
396 return matchedDN;
397 }
398
399
400
401 /**
402 * Retrieves the list of referral URLs for the operation.
403 *
404 * @return The list of referral URLs for the operation, or an empty list if
405 * it is not included in the log message.
406 */
407 public List<String> getReferralURLs()
408 {
409 return referralURLs;
410 }
411
412
413
414 /**
415 * Retrieves the number of intermediate response messages returned in the
416 * course of processing the operation.
417 *
418 * @return The number of intermediate response messages returned to the
419 * client in the course of processing the operation, or {@code null}
420 * if it is not included in the log message.
421 */
422 public Long getIntermediateResponsesReturned()
423 {
424 return intermediateResponsesReturned;
425 }
426
427
428
429 /**
430 * Retrieves the length of time in milliseconds required to process the
431 * operation.
432 *
433 * @return The length of time in milliseconds required to process the
434 * operation, or {@code null} if it is not included in the log
435 * message.
436 */
437 public Double getProcessingTimeMillis()
438 {
439 return processingTime;
440 }
441
442
443
444 /**
445 * Retrieves the length of time in milliseconds the operation was required to
446 * wait on the work queue.
447 *
448 * @return The length of time in milliseconds the operation was required to
449 * wait on the work queue, or {@code null} if it is not included in
450 * the log message.
451 */
452 public Double getQueueTimeMillis()
453 {
454 return queueTime;
455 }
456
457
458
459 /**
460 * Retrieves the OIDs of any response controls contained in the log message.
461 *
462 * @return The OIDs of any response controls contained in the log message, or
463 * an empty list if it is not included in the log message.
464 */
465 public List<String> getResponseControlOIDs()
466 {
467 return responseControlOIDs;
468 }
469
470
471
472 /**
473 * Retrieves a list of the additional servers that were accessed in the course
474 * of processing the operation. For example, if the access log message is
475 * from a Directory Proxy Server instance, then this may contain a list of the
476 * backend servers used to process the operation.
477 *
478 * @return A list of the additional servers that were accessed in the course
479 * of processing the operation, or an empty list if it is not
480 * included in the log message.
481 */
482 public List<String> getServersAccessed()
483 {
484 return serversAccessed;
485 }
486
487
488
489 /**
490 * Indicates whether the server accessed any uncached data in the course of
491 * processing the operation.
492 *
493 * @return {@code true} if the server was known to access uncached data in
494 * the course of processing the operation, {@code false} if the
495 * server was known not to access uncached data, or {@code null} if
496 * it is not included in the log message (and the server likely did
497 * not access uncached data).
498 */
499 public Boolean getUncachedDataAccessed()
500 {
501 return uncachedDataAccessed;
502 }
503
504
505
506 /**
507 * Retrieves the content of the intermediate client result for the
508 * operation.
509 *
510 * @return The content of the intermediate client result for the operation,
511 * or {@code null} if it is not included in the log message.
512 */
513 public String getIntermediateClientResult()
514 {
515 return intermediateClientResult;
516 }
517
518
519
520 /**
521 * Retrieves the alternate authorization DN for the operation.
522 *
523 * @return The alternate authorization DN for the operation, or {@code null}
524 * if it is not included in the log message.
525 */
526 public String getAlternateAuthorizationDN()
527 {
528 return authzDN;
529 }
530
531
532
533 /**
534 * Retrieves the replication change ID for the operation, if available.
535 *
536 * @return The replication change ID for the operation, or {@code null} if it
537 * is not included in the log message.
538 */
539 public String getReplicationChangeID()
540 {
541 return replicationChangeID;
542 }
543
544
545
546 /**
547 * Indicates whether the modify operation targeted a soft-deleted entry.
548 *
549 * @return {@code true} if the modify operation was known to target a
550 * soft-deleted entry, {@code false} if it was known to target a
551 * non-soft-deleted entry, or {@code null} if it is not included in
552 * the log message (and likely did not target a soft-deleted entry).
553 */
554 public Boolean getChangeToSoftDeletedEntry()
555 {
556 return changeToSoftDeletedEntry;
557 }
558
559
560
561 /**
562 * Retrieves the address of the backend server to which the request has been
563 * forwarded.
564 *
565 * @return The address of the backend server to which the request has been
566 * forwarded, or {@code null} if it is not included in the log
567 * message.
568 */
569 public String getTargetHost()
570 {
571 return targetHost;
572 }
573
574
575
576 /**
577 * Retrieves the port of the backend server to which the request has been
578 * forwarded.
579 *
580 * @return The port of the backend server to which the request has been
581 * forwarded, or {@code null} if it is not included in the log
582 * message.
583 */
584 public Integer getTargetPort()
585 {
586 return targetPort;
587 }
588
589
590
591 /**
592 * Retrieves the protocol used to forward the request to the backend server.
593 *
594 * @return The protocol used to forward the request to the backend server, or
595 * {@code null} if it is not included in the log message.
596 */
597 public String getTargetProtocol()
598 {
599 return targetProtocol;
600 }
601
602
603
604 /**
605 * Retrieves the local level that will be used for assured replication
606 * processing, if available.
607 *
608 * @return The local level that will be used for assured replication
609 * processing, or {@code null} if this is not included in the log
610 * message (e.g., because assured replication will not be performed
611 * for the operation).
612 */
613 public AssuredReplicationLocalLevel getAssuredReplicationLocalLevel()
614 {
615 return assuredReplicationLocalLevel;
616 }
617
618
619
620 /**
621 * Retrieves the remote level that will be used for assured replication
622 * processing, if available.
623 *
624 * @return The remote level that will be used for assured replication
625 * processing, or {@code null} if this is not included in the log
626 * message (e.g., because assured replication will not be performed
627 * for the operation).
628 */
629 public AssuredReplicationRemoteLevel getAssuredReplicationRemoteLevel()
630 {
631 return assuredReplicationRemoteLevel;
632 }
633
634
635
636 /**
637 * Retrieves the maximum length of time in milliseconds that the server will
638 * delay the response to the client while waiting for the replication
639 * assurance requirement to be satisfied.
640 *
641 * @return The maximum length of time in milliseconds that the server will
642 * delay the response to the client while waiting for the replication
643 * assurance requirement to be satisfied, or {@code null} if this is
644 * not included in the log message (e.g., because assured replication
645 * will not be performed for the operation).
646 */
647 public Long getAssuredReplicationTimeoutMillis()
648 {
649 return assuredReplicationTimeoutMillis;
650 }
651
652
653
654 /**
655 * Indicates whether the operation response to the client will be delayed
656 * until replication assurance has been satisfied or the timeout has occurred.
657 *
658 * @return {@code true} if the operation response to the client will be
659 * delayed until replication assurance has been satisfied,
660 * {@code false} if the response will not be delayed by assurance
661 * processing, or {@code null} if this was not included in the
662 * log message (e.g., because assured replication will not be
663 * performed for the operation)
664 */
665 public Boolean getResponseDelayedByAssurance()
666 {
667 return responseDelayedByAssurance;
668 }
669
670
671
672 /**
673 * Retrieves the names of any privileges used during the course of processing
674 * the operation.
675 *
676 * @return The names of any privileges used during the course of processing
677 * the operation, or an empty list if no privileges were used or this
678 * is not included in the log message.
679 */
680 public List<String> getUsedPrivileges()
681 {
682 return usedPrivileges;
683 }
684
685
686
687 /**
688 * Retrieves the names of any privileges used during the course of processing
689 * the operation before an alternate authorization identity was assigned.
690 *
691 * @return The names of any privileges used during the course of processing
692 * the operation before an alternate authorization identity was
693 * assigned, or an empty list if no privileges were used or this is
694 * not included in the log message.
695 */
696 public List<String> getPreAuthorizationUsedPrivileges()
697 {
698 return preAuthZUsedPrivileges;
699 }
700
701
702
703 /**
704 * Retrieves the names of any privileges that would have been required for
705 * processing the operation but that the requester did not have.
706 *
707 * @return The names of any privileges that would have been required for
708 * processing the operation but that the requester did not have, or
709 * an empty list if there were no missing privileges or this is not
710 * included in the log message.
711 */
712 public List<String> getMissingPrivileges()
713 {
714 return missingPrivileges;
715 }
716
717
718
719 /**
720 * {@inheritDoc}
721 */
722 @Override()
723 public AccessLogMessageType getMessageType()
724 {
725 return AccessLogMessageType.RESULT;
726 }
727 }