KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > slamd > example > WeightedSiteMinderWithReplicaLatencyJobClass


1 /*
2  * Sun Public License
3  *
4  * The contents of this file are subject to the Sun Public License Version
5  * 1.0 (the "License"). You may not use this file except in compliance with
6  * the License. A copy of the License is available at http://www.sun.com/
7  *
8  * The Original Code is the SLAMD Distributed Load Generation Engine.
9  * The Initial Developer of the Original Code is Neil A. Wilson.
10  * Portions created by Neil A. Wilson are Copyright (C) 2004.
11  * Some preexisting portions Copyright (C) 2002-2004 Sun Microsystems, Inc.
12  * All Rights Reserved.
13  *
14  * Contributor(s): Neil A. Wilson
15  */

16 package com.sun.slamd.example;
17
18
19
20 import java.util.*;
21 import netscape.ldap.*;
22 import com.sun.slamd.job.*;
23 import com.sun.slamd.parameter.*;
24 import com.sun.slamd.stat.*;
25
26
27
28 /**
29  * This class defines a SLAMD job that simulates the load that SiteMinder can
30  * place on an LDAP directory server using a weighted access pattern. It can
31  * also measure the latency associated with replicating the modifications made
32  * as part of the authentication process. The load that it uses is based on the
33  * following (rather inefficient) sequence of events:
34  *
35  * <OL>
36  * <LI>Perform a subtree search from the directory suffix to find the user's
37  * entry based on a login ID.</LI>
38  * <LI>Perform a base-level search on the user's entry to retrieve the
39  * objectClass attribute.</LI>
40  * <LI>Perform a bind as the user. This is done on a different connection
41  * than all of the other steps.</LI>
42  * <LI>Perform a base-level search on the user's entry to retrieve a given
43  * user-specified attribute (attr1).</LI>
44  * <LI>Perform a base-level search on the user's entry to retrieve a second
45  * user-specified attribute (attr2).</LI>
46  * <LI>Perform a base-level search on the user's entry to retrieve the first
47  * attribute (attr1).</LI>
48  * <LI>Perform a modification on the user's entry.</LI>
49  * <LI>Perform a base-level search on the user's entry to retrieve the first
50  * attribute again.</LI>
51  * <LI>Perform a base-level search on the user's entry to retrieve the first
52  * attribute again.</LI>
53  * <LI>Perform a base-level search on the user's entry to retrieve a third
54  * attribute (attr3).</LI>
55  * </OL>
56  *
57  *
58  * @author Neil A. Wilson
59  */

60 public class WeightedSiteMinderWithReplicaLatencyJobClass
61        extends ReplicaLatencyCheckJobClass
62 {
63   /**
64    * The set of characters that will be used to generate random values for the
65    * modifications.
66    */

67   public static final char[] ALPHABET =
68        "abcdefghijklmnopqrstuvwxyz".toCharArray();
69
70
71
72   /**
73    * The default value for the first attribute to retrieve during the
74    * authentication process.
75    */

76   public static final String JavaDoc DEFAULT_ATTR1 = "givenName";
77
78
79
80   /**
81    * The default value for the second attribute to retrieve during the
82    * authentication process.
83    */

84   public static final String JavaDoc DEFAULT_ATTR2 = "sn";
85
86
87
88   /**
89    * The default value for the third attribute to retrieve during the
90    * authentication process.
91    */

92   public static final String JavaDoc DEFAULT_ATTR3= "cn";
93
94
95
96   /**
97    * The default attribute used as the login ID.
98    */

99   public static final String JavaDoc DEFAULT_LOG_ID_ATTR = "uid";
100
101
102
103   /**
104    * The name of the stat tracker that will be used to count the number of
105    * overall authentication attempts.
106    */

107   public static final String JavaDoc STAT_TRACKER_OVERALL_AUTHENTICATION_ATTEMPTS =
108        "Overall Authentication Attempts";
109
110
111
112   /**
113    * The name of the stat tracker that will be used to count the number of
114    * authentication attempts based on the first user criteria.
115    */

116   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_1_ATTEMPTS =
117        "Authentication 1 Attempts";
118
119
120
121   /**
122    * The name of the stat tracker that will be used to count the number of
123    * authentication attempts based on the second user criteria.
124    */

125   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_2_ATTEMPTS =
126        "Authentication 2 Attempts";
127
128
129
130   /**
131    * The name of the stat tracker that will be used to keep track of the overall
132    * time required to perform each authentication.
133    */

134   public static final String JavaDoc STAT_TRACKER_OVERALL_AUTHENTICATION_TIME =
135        "Overall Authentication Time (ms)";
136
137
138
139   /**
140    * The name of the stat tracker that will be used to keep track of the time
141    * required to perform each authentication based on the first user criteria.
142    */

143   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_1_TIME =
144        "Authentication 1 Time (ms)";
145
146
147
148   /**
149    * The name of the stat tracker that will be used to keep track of the time
150    * required to perform each authentication based on the second user criteria.
151    */

152   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_2_TIME =
153        "Authentication 2 Time (ms)";
154
155
156
157   /**
158    * The name of the stat tracker that will be used to count the number of
159    * overall failed authentications.
160    */

161   public static final String JavaDoc STAT_TRACKER_OVERALL_FAILED_AUTHENTICATIONS =
162        "Overall Failed Authentications";
163
164
165
166   /**
167    * The name of the stat tracker that will be used to count the number of
168    * failed authentications based on the first user criteria.
169    */

170   public static final String JavaDoc STAT_TRACKER_FAILED_AUTHENTICATIONS_1 =
171        "Failed Authentications 1";
172
173
174
175   /**
176    * The name of the stat tracker that will be used to count the number of
177    * failed authentications based on the second user criteria.
178    */

179   public static final String JavaDoc STAT_TRACKER_FAILED_AUTHENTICATIONS_2 =
180        "Failed Authentications 2";
181
182
183
184   /**
185    * The name of the stat tracker that will be used to categorize the reasons
186    * for the failed auths.
187    */

188   public static final String JavaDoc STAT_TRACKER_FAIL_REASON = "Failure Reason";
189
190
191
192   /**
193    * The name of the stat tracker that will be used to count the overall number
194    * of successful authentications.
195    */

196   public static final String JavaDoc STAT_TRACKER_OVERALL_SUCCESSFUL_AUTHENTICATIONS =
197        "Overall Successful Authentications";
198
199
200
201   /**
202    * The name of the stat tracker that will be used to count the number of
203    * successful authentications based on the first user criteria.
204    */

205   public static final String JavaDoc STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_1 =
206        "Successful Authentications 1";
207
208
209
210   /**
211    * The name of the stat tracker that will be used to count the number of
212    * successful authentications based on the second user criteria.
213    */

214   public static final String JavaDoc STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_2 =
215        "Successful Authentications 2";
216
217
218
219   /**
220    * The name of the stat tracker that will be used to track replication
221    * latency.
222    */

223   public static final String JavaDoc STAT_TRACKER_REPLICATION_LATENCY =
224        "Replication Latency (ms)";
225
226
227
228   /**
229    * The name of the stat tracker that will be used to categorize latency.
230    */

231   public static final String JavaDoc STAT_TRACKER_CATEGORIZED_LATENCY =
232        "Categorized Latency";
233
234
235
236   /**
237    * The default set of attributes to include in the modification.
238    */

239   public static final String JavaDoc[] DEFAULT_ATTRS_TO_MODIFY = new String JavaDoc[]
240   {
241     "description"
242   };
243
244
245
246   // Indicates whether bind failures because of invalid credentials will be
247
// ignored (so you don't actually have to know user passwords).
248
static boolean ignoreInvalidCredentials;
249
250   // Indicates whether a thread has been chosen to manage latency checking.
251
static boolean latencyTrackerChosen;
252
253   // Indicates whether the bind should be attempted or skipped.
254
static boolean skipBind;
255
256   // Indicates whether the first login ID should be interpreted as a range.
257
static boolean useLoginIDRange1;
258
259   // Indicates whether the second login ID should be interpreted as a range.
260
static boolean useLoginIDRange2;
261
262   // Indicates whether the first login ID value should increment sequentially.
263
static boolean useSequential1;
264
265   // Indicates whether the second login ID value should increment sequentially.
266
static boolean useSequential2;
267
268   // Indicates whether all threads will used a shared set of connections or if
269
// each thread will have its own connection.
270
static boolean useSharedConnections;
271
272   // The time to keep working after stopping statistics collection.
273
static int coolDownTime;
274
275   // The length of time in milliseconds to allow between latency checks.
276
static int latencyDelay;
277
278   // The percentage of the time that the first login ID should be used.
279
static int loginID1Percent;
280
281   // The maximum value to use in the first range of login IDs.
282
static int loginIDMax1;
283
284   // The maximum value to use in the second range of login IDs.
285
static int loginIDMax2;
286
287   // The minimum value to use in the first range of login IDs.
288
static int loginIDMin1;
289
290   // The minimum value to use in the second range of login IDs.
291
static int loginIDMin2;
292
293   // The span to use for the first range of login IDs.
294
static int loginIDSpan1;
295
296   // The span to use for the second range of login IDs.
297
static int loginIDSpan2;
298
299   // The port number of the master directory server.
300
static int masterPort;
301
302   // The port number of the replica directory server.
303
static int replicaPort;
304
305   // The next sequential value that should be used in the first login ID value.
306
static int sequentialCounter1;
307
308   // The next sequential value that should be used in the second login ID value.
309
static int sequentialCounter2;
310
311   // The maximum length of time that any single LDAP operation will be allowed
312
// to take before it is cancelled.
313
static int timeLimit;
314
315   // The time to start working before beginning statistics collection.
316
static int warmUpTime;
317
318   // The delay in milliseconds between authentication attempts.
319
static long delay;
320
321   // The LDAP connection that will be used for shared authentication operations.
322
static LDAPConnection sharedAuthConnection;
323
324   // The LDAP connection that will be used for shared bind operations.
325
static LDAPConnection sharedBindConnection;
326
327   // The random number generator that will seed the thread-specific random
328
// number generators.
329
static Random parentRandom;
330
331   // The DN to use to bind to the directory when performing the search and
332
// modify operations.
333
static String JavaDoc bindDN;
334
335   // The password for the bind DN.
336
static String JavaDoc bindPW;
337
338   // The search filter to use when searching on the first attribute.
339
static String JavaDoc filter1;
340
341   // The search filter to use when searching on the second attribute.
342
static String JavaDoc filter2;
343
344   // The search filter to use when searching on the third attribute.
345
static String JavaDoc filter3;
346
347   // The name of the attribute that will be used to initially find the user's
348
// entry (the login ID attribute).
349
static String JavaDoc loginIDAttr;
350
351   // The text to include after the numeric part of the first login ID.
352
static String JavaDoc loginIDFinal1;
353
354   // The text to include after the numeric part of the second login ID.
355
static String JavaDoc loginIDFinal2;
356
357   // The text to include before the numeric part of the first login ID.
358
static String JavaDoc loginIDInitial1;
359
360   // The text to include before the numeric part of the second login ID.
361
static String JavaDoc loginIDInitial2;
362
363   // The password to use when authenticating.
364
static String JavaDoc loginPassword;
365
366   // The address of the master directory server.
367
static String JavaDoc masterHost;
368
369   // The DN of the entry to use for latency checking.
370
static String JavaDoc replicaEntryDN;
371
372   // The address of the replica directory server.
373
static String JavaDoc replicaHost;
374
375   // The name of the first attribute to retrieve.
376
static String JavaDoc searchAttr1;
377
378   // The name of the second attribute to retrieve.
379
static String JavaDoc searchAttr2;
380
381   // The name of the third attribute to retrieve.
382
static String JavaDoc searchAttr3;
383
384   // The DN to use as the search base when trying to find user entries in the
385
// directory.
386
static String JavaDoc searchBase;
387
388   // The names of the attributes to alter in the modification.
389
static String JavaDoc[] modAttrs;
390
391   // The set of attributes to return when retrieving the first attribute.
392
static String JavaDoc[] returnAttrs1;
393
394   // The set of attributes to return when retrieving the second attribute.
395
static String JavaDoc[] returnAttrs2;
396
397   // The set of attributes to return when retrieving the third attribute.
398
static String JavaDoc[] returnAttrs3;
399
400   // The set of attributes to return when retrieving the set of objectclasses.
401
static String JavaDoc[] returnAttrsOC;
402
403
404
405   // The parameter used to indicate whether invalid credential results are
406
// ignored.
407
BooleanParameter ignoreInvCredParameter =
408        new BooleanParameter("ignore_49", "Ignore Invalid Credentials Errors",
409                             "Indicates whether bind failures because of " +
410                             "invalid credentials (err=49). This makes it " +
411                             "possible to use this job without actually " +
412                             "know user passwords.", false);
413
414   // The parameter used to indicate whether connections are shared.
415
BooleanParameter shareConnsParameter =
416        new BooleanParameter("share_conns", "Share Connections between Threads",
417                             "Indicates whether the connections to the " +
418                             "directory server will be shared between threads " +
419                             "or if each client thread will have its own " +
420                             "connections.", true);
421
422   // The parameter used to indicate whether to skip the bind operation.
423
BooleanParameter skipBindParameter =
424        new BooleanParameter("skip_bind", "Skip Bind Operation",
425                             "Indicates whether the bind attempt should be " +
426                             "skipped as part of the authentication process.",
427                             false);
428
429   // The parmeter that specifies the cool-down time in seconds.
430
IntegerParameter coolDownParameter =
431        new IntegerParameter("cool_down", "Cool Down Time",
432                             "The time in seconds that the job should " +
433                             "continue searching after ending statistics " +
434                             "collection.", true, 0, true, 0, false, 0);
435
436   // The parameter that indicates the delay that should be used between each
437
// authentication attempt.
438
IntegerParameter delayParameter =
439        new IntegerParameter("delay", "Time Between Authentications (ms)",
440                             "Specifies the length of time in milliseconds " +
441                             "each thread should wait between authentication " +
442                             "attempts. Note that this delay will be " +
443                             "between the starts of consecutive attempts and " +
444                             "not between the end of one attempt and the " +
445                             "beginning of the next. If an authentication " +
446                             "takes longer than this length of time, then " +
447                             "there will be no delay.", true, 0, true, 0, false,
448                             0);
449
450   // The parameter that indicates the minimum length of time to sleep between
451
// modifications of the latency check entry.
452
IntegerParameter replicaDelayParameter =
453        new IntegerParameter("latency_delay", "Time Between Latency Checks (ms)",
454                             "Specifies the minimum length of time in " +
455                             "milliseconds that should pass between latency " +
456                             "checks. If a replicated operation takes longer " +
457                             "than this length of time, then there will be no " +
458                             "delay.", true, 0, true, 0, false, 0);
459
460   // The parameter that indicates the port number for the master directory.
461
IntegerParameter masterPortParameter =
462        new IntegerParameter("master_port", "Master Directory Port",
463                             "The port number for the master directory server",
464                             true, 389, true, 1, true, 65535);
465
466   // The parameter that indicates the port number for the replica directory.
467
IntegerParameter replicaPortParameter =
468        new IntegerParameter("replica_port", "Replica Directory Port",
469                             "The port number for the replica directory server",
470                             true, 389, true, 1, true, 65535);
471
472   // The parameter used to indicate the maximum length of time that any single
473
// LDAP operation will be allowed to take.
474
IntegerParameter timeLimitParameter =
475        new IntegerParameter("time_limit", "Operation Time Limit",
476                             "The maximum length of time in seconds that any " +
477                             "single LDAP operation will be allowed to take " +
478                             "before it is cancelled.", true, 0, true, 0, false,
479                             0);
480
481   // The parmeter that specifies the cool-down time in seconds.
482
IntegerParameter warmUpParameter =
483        new IntegerParameter("warm_up", "Warm Up Time",
484                             "The time in seconds that the job should " +
485                             "search before beginning statistics collection.",
486                             true, 0, true, 0, false, 0);
487
488   // The parameter that specifies the percentage of the time that the first user
489
// criteria will be used in the modification.
490
IntegerParameter weightParameter =
491        new IntegerParameter("weight", "Login ID 1 Percentage",
492                             "The percentage of the time that a login ID " +
493                             "should be selected according to the value " +
494                             "provided for the Login ID Value 1 parameter.",
495                             true, 50, true, 0, true, 100);
496
497   // The parameter used to indicate the attributes to modify.
498
MultiLineTextParameter modAttrsParameter =
499        new MultiLineTextParameter("mod_attrs", "Attributes to Modify",
500                                   "The set of attributes to modify.",
501                                   DEFAULT_ATTRS_TO_MODIFY, false);
502
503   // The parameter used to indicate the password for the bind DN.
504
PasswordParameter bindPWParameter =
505        new PasswordParameter("bindpw", "Directory Bind Password",
506                              "The password to use when binding to the " +
507                              "directory server to perform search and modify " +
508                              "operations.", false, "");
509
510   // The parameter used to indicate the password to use when authenticating to
511
// the directory.
512
PasswordParameter loginPasswordParameter =
513        new PasswordParameter("login_id_pw", "Login Password",
514                              "The password to use when authenticating to the " +
515                              "directory for user authentications.", false, "");
516
517   // The placeholder parameter used as a spacer in the admin interface.
518
PlaceholderParameter placeholder = new PlaceholderParameter();
519
520   // The parameter used to indicate the first attribute to retrieve.
521
StringParameter attr1Parameter =
522        new StringParameter("attr1", "First Attribute to Retrieve",
523                            "The first attribute to retrieve from the user's " +
524                            "entry as part of the authentication process.",
525                            true, DEFAULT_ATTR1);
526
527   // The parameter used to indicate the first attribute to retrieve.
528
StringParameter attr2Parameter =
529        new StringParameter("attr2", "Second Attribute to Retrieve",
530                            "The second attribute to retrieve from the user's " +
531                            "entry as part of the authentication process.",
532                            true, DEFAULT_ATTR2);
533
534   // The parameter used to indicate the first attribute to retrieve.
535
StringParameter attr3Parameter =
536        new StringParameter("attr3", "Third Attribute to Retrieve",
537                            "The third attribute to retrieve from the user's " +
538                            "entry as part of the authentication process.",
539                            true, DEFAULT_ATTR3);
540
541   // The parameter used to indicate the bind DN.
542
StringParameter bindDNParameter =
543        new StringParameter("binddn", "Directory Bind DN",
544                            "The DN to use when binding to the directory " +
545                            "server to perform search and modify operations.",
546                            false, "");
547
548   // The parameter used to indicate the attribute to use for the login ID.
549
StringParameter loginIDParameter =
550        new StringParameter("login_id_attr", "Login ID Attribute",
551                            "The attribute to use as the login ID to find the " +
552                            "user's entry.", true, DEFAULT_LOG_ID_ATTR);
553
554   // The parameter used to indicate the first login ID value or value pattern.
555
StringParameter loginIDValue1Parameter =
556        new StringParameter("login_id_value_1", "Login ID Value 1",
557                            "The text to use as the value of the login ID " +
558                            "attribute in search filters created using the " +
559                            "first set of user criteria. The value may " +
560                            "contain a range of numbers in square brackets.",
561                            true, "");
562
563   // The parameter used to indicate the second login ID value or value pattern.
564
StringParameter loginIDValue2Parameter =
565        new StringParameter("login_id_value_2", "Login ID Value 2",
566                            "The text to use as the value of the login ID " +
567                            "attribute in search filters created using the " +
568                            "second set of user criteria. The value may " +
569                            "contain a range of numbers in square brackets.",
570                            true, "");
571
572   // The parameter that indicates the address of the master directory server
573
StringParameter masterHostParameter =
574        new StringParameter("masterhost", "Master Directory Host",
575                            "The DNS hostname or IP address of the master " +
576                            "directory server", true, "");
577
578   // The parameter that specifies the DN of the entry to watch for replication
579
// latency.
580
StringParameter replicaEntryDNParameter =
581        new StringParameter("replica_entrydn", "Latency Check Entry DN",
582                            "The DN of the entry that should be periodically " +
583                            "modified to measure the latency of replication. " +
584                            "Note that this DN must not be the same as " +
585                            "the DN of any of the entries to modify, nor " +
586                            "should this entry be modified by any external " +
587                            "process during the test.", true, "");
588
589   // The parameter that indicates the address of the replica directory server
590
StringParameter replicaHostParameter =
591        new StringParameter("replicahost", "Replica Directory Host",
592                            "The DNS hostname or IP address of the replica " +
593                            "directory server", true, "");
594
595   // The parameter used to indicate the search base for the directory.
596
StringParameter searchBaseParameter =
597     new StringParameter("search_base", "User Search Base",
598                         "The DN in the directory server under which user " +
599                         "entries may be found.", true, "");
600
601   // Indicates whether this thread should report latency statistics.
602
boolean reportLatencyTracker;
603
604   // The stat tracker that will categorize the reasons for auth failures.
605
CategoricalTracker failureReasonTracker;
606
607   // The stat trackers that will count the numbers of authentication attempts.
608
IncrementalTracker overallAttemptCounter;
609   IncrementalTracker attemptCounter1;
610   IncrementalTracker attemptCounter2;
611
612   // The stat trackers that will count the numbers of failed authentications.
613
IncrementalTracker overallFailureCounter;
614   IncrementalTracker failureCounter1;
615   IncrementalTracker failureCounter2;
616
617   // The stat trackers that will count the numbers of successful
618
// authentications.
619
IncrementalTracker overallSuccessCounter;
620   IncrementalTracker successCounter1;
621   IncrementalTracker successCounter2;
622
623   // The thread used for performing changes on the master server.
624
LatencyCheckMasterThread masterThread;
625
626   // The thread used for detecting changes on the replica server.
627
LatencyCheckReplicaThread replicaThread;
628
629   // The LDAP connection that will be used for authentication operations by this
630
// thread.
631
LDAPConnection authConnection;
632
633   // The LDAP connection that will be used for bind operations by this thread.
634
LDAPConnection bindConnection;
635
636   // The set of constraints that will be used for non-search/bind operations.
637
LDAPConstraints authConstraints;
638
639   // The set of constraints that will be used for bind operations.
640
LDAPConstraints bindConstraints;
641
642   // The set of constraints that will be used for search operations.
643
LDAPSearchConstraints authSearchConstraints;
644
645   // The random number generator for this thread.
646
Random random;
647
648   // The stat trackers that will time each authentication.
649
TimeTracker overallAuthTimer;
650   TimeTracker authTimer1;
651   TimeTracker authTimer2;
652
653
654
655   /**
656    * Creates a new instance of this job thread. This constructor does not need
657    * to do anything other than invoke the constructor for the superclass.
658    */

659   public WeightedSiteMinderWithReplicaLatencyJobClass()
660   {
661     super();
662   }
663
664
665
666   /**
667    * Returns the user-friendly name that is to be used for this job class in the
668    * administrative interface.
669    *
670    * @return The user-friendly name for this job class.
671    */

672   public String JavaDoc getJobName()
673   {
674     return "LDAP Weighted SiteMinder Load Simulator with Replication Latency";
675   }
676
677
678
679   /**
680    * Returns a description of this job that can be seen in the administrative
681    * interface.
682    *
683    * @return A description of this job class.
684    */

685   public String JavaDoc getJobDescription()
686   {
687     return "This job simulates the load that SiteMinder can place on the " +
688            "directory server when it is performing authentications. It uses " +
689            "a weighted access pattern to more accurately simulate real-world " +
690            "behavior.";
691   }
692
693
694
695   /**
696    * Retrieves the name of the category in which this job class exists. This is
697    * used to help arrange the job classes in the administrative interface.
698    *
699    * @return The name of the category in which this job class exists.
700    */

701   public String JavaDoc getJobCategoryName()
702   {
703     return "LDAP";
704   }
705
706
707
708   /**
709    * Returns the set of parameters whose value may be specified by the end user.
710    *
711    * @return The set of configurable parameters for this job class.
712    */

713   public ParameterList getParameterStubs()
714   {
715     Parameter[] parameterArray = new Parameter[]
716     {
717       placeholder,
718       masterHostParameter,
719       masterPortParameter,
720       bindDNParameter,
721       bindPWParameter,
722       placeholder,
723       replicaHostParameter,
724       replicaPortParameter,
725       replicaEntryDNParameter,
726       replicaDelayParameter,
727       placeholder,
728       searchBaseParameter,
729       loginIDValue1Parameter,
730       loginIDValue2Parameter,
731       weightParameter,
732       loginPasswordParameter,
733       loginIDParameter,
734       placeholder,
735       attr1Parameter,
736       attr2Parameter,
737       attr3Parameter,
738       modAttrsParameter,
739       placeholder,
740       warmUpParameter,
741       coolDownParameter,
742       timeLimitParameter,
743       delayParameter,
744       placeholder,
745       skipBindParameter,
746       ignoreInvCredParameter,
747       shareConnsParameter
748     };
749
750     return new ParameterList(parameterArray);
751   }
752
753
754
755   /**
756    * Retrieves the set of stat trackers that will be maintained by this job
757    * class. The stat trackers returned by this method do not have to actually
758    * contain any statistics -- the display name and stat tracker class should
759    * be the only information that callers of this method should rely upon. Note
760    * that this list can be different from the list of statistics actually
761    * collected by the job in some cases (e.g., if the job may not return all the
762    * stat trackers it advertises in all cases, or if the job may return stat
763    * trackers that it did not advertise), but it is a possibility that only the
764    * stat trackers returned by this method will be accessible for some features
765    * in the SLAMD server.
766    *
767    * @param clientID The client ID that should be used for the
768    * returned stat trackers.
769    * @param threadID The thread ID that should be used for the
770    * returned stat trackers.
771    * @param collectionInterval The collection interval that should be used for
772    * the returned stat trackers.
773    *
774    * @return The set of stat trackers that will be maintained by this job
775    * class.
776    */

777   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
778                                            int collectionInterval)
779   {
780     return new StatTracker[]
781     {
782       new IncrementalTracker(clientID, threadID,
783                              STAT_TRACKER_OVERALL_AUTHENTICATION_ATTEMPTS,
784                              collectionInterval),
785       new IncrementalTracker(clientID, threadID,
786                              STAT_TRACKER_AUTHENTICATION_1_ATTEMPTS,
787                              collectionInterval),
788       new IncrementalTracker(clientID, threadID,
789                              STAT_TRACKER_AUTHENTICATION_2_ATTEMPTS,
790                              collectionInterval),
791       new IncrementalTracker(clientID, threadID,
792                              STAT_TRACKER_OVERALL_SUCCESSFUL_AUTHENTICATIONS,
793                              collectionInterval),
794       new IncrementalTracker(clientID, threadID,
795                              STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_1,
796                              collectionInterval),
797       new IncrementalTracker(clientID, threadID,
798                              STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_2,
799                              collectionInterval),
800       new IncrementalTracker(clientID, threadID,
801                              STAT_TRACKER_OVERALL_FAILED_AUTHENTICATIONS,
802                              collectionInterval),
803       new IncrementalTracker(clientID, threadID,
804                              STAT_TRACKER_FAILED_AUTHENTICATIONS_1,
805                              collectionInterval),
806       new IncrementalTracker(clientID, threadID,
807                              STAT_TRACKER_FAILED_AUTHENTICATIONS_2,
808                              collectionInterval),
809       new TimeTracker(clientID, threadID,
810                       STAT_TRACKER_OVERALL_AUTHENTICATION_TIME,
811                       collectionInterval),
812       new TimeTracker(clientID, threadID, STAT_TRACKER_AUTHENTICATION_1_TIME,
813                       collectionInterval),
814       new TimeTracker(clientID, threadID, STAT_TRACKER_AUTHENTICATION_2_TIME,
815                       collectionInterval),
816       new CategoricalTracker(clientID, threadID, STAT_TRACKER_FAIL_REASON,
817                              collectionInterval),
818       new TimeTracker(clientID, threadID, STAT_TRACKER_REPLICATION_LATENCY,
819                       collectionInterval),
820       new CategoricalTracker(clientID, threadID,
821                              STAT_TRACKER_CATEGORIZED_LATENCY,
822                              collectionInterval)
823     };
824   }
825
826
827
828   /**
829    * Retrieves the set of stat trackers that are maintained by this job class.
830    *
831    * @return The set of stat trackers for this job class.
832    */

833   public StatTracker[] getStatTrackers()
834   {
835     if (reportLatencyTracker)
836     {
837       return new StatTracker[]
838       {
839         overallAttemptCounter,
840         attemptCounter1,
841         attemptCounter2,
842         overallSuccessCounter,
843         successCounter1,
844         successCounter2,
845         overallFailureCounter,
846         failureCounter1,
847         failureCounter2,
848         overallAuthTimer,
849         authTimer1,
850         authTimer2,
851         failureReasonTracker,
852         latencyTime,
853         latencyCategories
854       };
855     }
856     else
857     {
858       return new StatTracker[]
859       {
860         overallAttemptCounter,
861         attemptCounter1,
862         attemptCounter2,
863         overallSuccessCounter,
864         successCounter1,
865         successCounter2,
866         overallFailureCounter,
867         failureCounter1,
868         failureCounter2,
869         overallAuthTimer,
870         authTimer1,
871         authTimer2,
872         failureReasonTracker
873       };
874     }
875   }
876
877
878
879   /**
880    * Indicates whether this job class implements logic that makes it possible to
881    * test the validity of job parameters before scheduling the job for execution
882    * (e.g., to see if the server is reachable using the information provided).
883    *
884    * @return <CODE>true</CODE> if this job provides a means of testing the job
885    * parameters, or <CODE>false</CODE> if not.
886    */

887   public boolean providesParameterTest()
888   {
889     return true;
890   }
891
892
893
894   /**
895    * Provides a means of testing the provided job parameters to determine
896    * whether they are valid (e.g., to see if the server is reachable) before
897    * scheduling the job for execution. This method will be executed by the
898    * SLAMD server system itself and not by any of the clients.
899    *
900    * @param parameters The job parameters to be tested.
901    * @param outputMessages The lines of output that were generated as part of
902    * the testing process. Each line of output should
903    * be added to this list as a separate string, and
904    * empty strings (but not <CODE>null</CODE> values)
905    * are allowed to provide separation between
906    * different messages. No formatting should be
907    * provided for these messages, however, since they
908    * may be displayed in either an HTML or plain text
909    * interface.
910    *
911    * @return <CODE>true</CODE> if the test completed successfully, or
912    * <CODE>false</CODE> if not. Note that even if the test did not
913    * complete successfully, the user will be presented with a warning
914    * but will still be allowed to schedule the job using the provided
915    * parameters. This is necessary because the parameters may still be
916    * valid even if the server couldn't validate them at the time the
917    * job was scheduled (e.g., if the server wasn't running or could not
918    * be reached by the SLAMD server even though it could be by the
919    * clients).
920    */

921   public boolean testJobParameters(ParameterList parameters,
922                                    ArrayList outputMessages)
923   {
924     // Get all the parameters that we might need to perform the test.
925
StringParameter masterHostParam =
926          parameters.getStringParameter(masterHostParameter.getName());
927     if ((masterHostParam == null) || (! masterHostParam.hasValue()))
928     {
929       outputMessages.add("ERROR: No master directory server address was " +
930                          "provided.");
931       return false;
932     }
933     String JavaDoc masterHost = masterHostParam.getStringValue();
934
935
936     IntegerParameter masterPortParam =
937          parameters.getIntegerParameter(masterPortParameter.getName());
938     if ((masterPortParam == null) || (! masterPortParam.hasValue()))
939     {
940       outputMessages.add("ERROR: No master directory server port was " +
941                          "provided.");
942       return false;
943     }
944     int masterPort = masterPortParam.getIntValue();
945
946
947     StringParameter replicaHostParam =
948          parameters.getStringParameter(replicaHostParameter.getName());
949     if ((replicaHostParam == null) || (! replicaHostParam.hasValue()))
950     {
951       outputMessages.add("ERROR: No replica directory server address was " +
952                          "provided.");
953       return false;
954     }
955     String JavaDoc replicaHost = replicaHostParam.getStringValue();
956
957
958     IntegerParameter replicaPortParam =
959          parameters.getIntegerParameter(replicaPortParameter.getName());
960     if ((replicaPortParam == null) || (! replicaPortParam.hasValue()))
961     {
962       outputMessages.add("ERROR: No replica directory server port was " +
963                          "provided.");
964       return false;
965     }
966     int replicaPort = replicaPortParam.getIntValue();
967
968
969     String JavaDoc bindDN = "";
970     StringParameter bindDNParam =
971          parameters.getStringParameter(bindDNParameter.getName());
972     if ((bindDNParam != null) && bindDNParam.hasValue())
973     {
974       bindDN = bindDNParam.getStringValue();
975     }
976
977
978     String JavaDoc bindPassword = "";
979     PasswordParameter bindPWParam =
980          parameters.getPasswordParameter(bindPWParameter.getName());
981     if ((bindPWParam != null) && bindPWParam.hasValue())
982     {
983       bindPassword = bindPWParam.getStringValue();
984     }
985
986
987     StringParameter baseDNParam =
988          parameters.getStringParameter(searchBaseParameter.getName());
989     if ((baseDNParam == null) || (! baseDNParam.hasValue()))
990     {
991       outputMessages.add("ERROR: No base DN was provided.");
992       return false;
993     }
994     String JavaDoc baseDN = baseDNParam.getStringValue();
995
996
997     StringParameter replicaEntryDNParam =
998          parameters.getStringParameter(replicaEntryDNParameter.getName());
999     if ((replicaEntryDNParam == null) || (! replicaEntryDNParam.hasValue()))
1000    {
1001      outputMessages.add("ERROR: No replica check entry DN was provided.");
1002      return false;
1003    }
1004    String JavaDoc replicaEntryDN = replicaEntryDNParam.getStringValue();
1005
1006
1007    // Create the LDAPConnection object that we will use to communicate with the
1008
// directory server.
1009
LDAPConnection conn = new LDAPConnection();
1010
1011
1012    // Attempt to establish a connection to the master server.
1013
try
1014    {
1015      outputMessages.add("Attempting to establish a connection to master " +
1016                         masterHost + ":" + masterPort + "....");
1017      conn.connect(masterHost, masterPort);
1018      outputMessages.add("Connected successfully.");
1019      outputMessages.add("");
1020    }
1021    catch (Exception JavaDoc e)
1022    {
1023      outputMessages.add("ERROR: Unable to connect to the master server: " +
1024                         stackTraceToString(e));
1025      return false;
1026    }
1027
1028
1029    // Attempt to bind to the master server using the bind DN and password.
1030
try
1031    {
1032      outputMessages.add("Attempting to perform an LDAPv3 bind to the " +
1033                         "master server with a DN of '" + bindDN + "'....");
1034      conn.bind(3, bindDN, bindPassword);
1035      outputMessages.add("Bound successfully.");
1036      outputMessages.add("");
1037    }
1038    catch (Exception JavaDoc e)
1039    {
1040      try
1041      {
1042        conn.disconnect();
1043      } catch (Exception JavaDoc e2) {}
1044
1045      outputMessages.add("ERROR: Unable to bind to the master server: " +
1046                         stackTraceToString(e));
1047      return false;
1048    }
1049
1050
1051    // Make sure that the entry specified as the base DN exists.
1052
try
1053    {
1054      outputMessages.add("Checking to make sure that the base DN entry '" +
1055                         baseDN + "' exists in the master....");
1056      LDAPEntry baseDNEntry = conn.read(baseDN, new String JavaDoc[] { "1.1" });
1057      if (baseDNEntry == null)
1058      {
1059        try
1060        {
1061          conn.disconnect();
1062        } catch (Exception JavaDoc e2) {}
1063
1064        outputMessages.add("ERROR: Unable to retrieve the base DN entry.");
1065        return false;
1066      }
1067      else
1068      {
1069        outputMessages.add("Successfully read the base DN entry.");
1070        outputMessages.add("");
1071      }
1072    }
1073    catch (Exception JavaDoc e)
1074    {
1075      try
1076      {
1077        conn.disconnect();
1078      } catch (Exception JavaDoc e2) {}
1079
1080      outputMessages.add("ERROR: Unable to retrieve the base DN entry: " +
1081                         stackTraceToString(e));
1082      return false;
1083    }
1084
1085
1086    // Make sure that the entry specified as the replica check entry exists.
1087
try
1088    {
1089      outputMessages.add("Checking to make sure that the replica check " +
1090                         "entry '" + replicaEntryDN +
1091                         "' exists in the master....");
1092      LDAPEntry baseDNEntry = conn.read(replicaEntryDN, new String JavaDoc[] { "1.1" });
1093      if (baseDNEntry == null)
1094      {
1095        try
1096        {
1097          conn.disconnect();
1098        } catch (Exception JavaDoc e2) {}
1099
1100        outputMessages.add("ERROR: Unable to retrieve the replica check " +
1101                           "entry.");
1102        return false;
1103      }
1104      else
1105      {
1106        outputMessages.add("Successfully read the replica check entry.");
1107        outputMessages.add("");
1108      }
1109    }
1110    catch (Exception JavaDoc e)
1111    {
1112      try
1113      {
1114        conn.disconnect();
1115      } catch (Exception JavaDoc e2) {}
1116
1117      outputMessages.add("ERROR: Unable to retrieve the replica check " +
1118                         "entry: " + stackTraceToString(e));
1119      return false;
1120    }
1121
1122
1123    // At this point, all tests on the master have passed. Close the connection
1124
// and prepare to start on the replica.
1125
try
1126    {
1127      conn.disconnect();
1128    } catch (Exception JavaDoc e) {}
1129
1130
1131    // Attempt to establish a connection to the replica server.
1132
try
1133    {
1134      outputMessages.add("Attempting to establish a connection to replica " +
1135                         replicaHost + ":" + replicaPort + "....");
1136      conn.connect(replicaHost, replicaPort);
1137      outputMessages.add("Connected successfully.");
1138      outputMessages.add("");
1139    }
1140    catch (Exception JavaDoc e)
1141    {
1142      outputMessages.add("ERROR: Unable to connect to the replica server: " +
1143                         stackTraceToString(e));
1144      return false;
1145    }
1146
1147
1148    // Attempt to bind to the replica server using the bind DN and password.
1149
try
1150    {
1151      outputMessages.add("Attempting to perform an LDAPv3 bind to the " +
1152                         "replica server with a DN of '" + bindDN + "'....");
1153      conn.bind(3, bindDN, bindPassword);
1154      outputMessages.add("Bound successfully.");
1155      outputMessages.add("");
1156    }
1157    catch (Exception JavaDoc e)
1158    {
1159      try
1160      {
1161        conn.disconnect();
1162      } catch (Exception JavaDoc e2) {}
1163
1164      outputMessages.add("ERROR: Unable to bind to the replica server: " +
1165                         stackTraceToString(e));
1166      return false;
1167    }
1168
1169
1170    // Make sure that the entry specified as the base DN exists.
1171
try
1172    {
1173      outputMessages.add("Checking to make sure that the base DN entry '" +
1174                         baseDN + "' exists in the replica....");
1175      LDAPEntry baseDNEntry = conn.read(baseDN, new String JavaDoc[] { "1.1" });
1176      if (baseDNEntry == null)
1177      {
1178        try
1179        {
1180          conn.disconnect();
1181        } catch (Exception JavaDoc e2) {}
1182
1183        outputMessages.add("ERROR: Unable to retrieve the base DN entry.");
1184        return false;
1185      }
1186      else
1187      {
1188        outputMessages.add("Successfully read the base DN entry.");
1189        outputMessages.add("");
1190      }
1191    }
1192    catch (Exception JavaDoc e)
1193    {
1194      try
1195      {
1196        conn.disconnect();
1197      } catch (Exception JavaDoc e2) {}
1198
1199      outputMessages.add("ERROR: Unable to retrieve the base DN entry: " +
1200                         stackTraceToString(e));
1201      return false;
1202    }
1203
1204
1205    // Make sure that the entry specified as the replica check entry exists.
1206
try
1207    {
1208      outputMessages.add("Checking to make sure that the replica check " +
1209                         "entry '" + replicaEntryDN +
1210                         "' exists in the replica....");
1211      LDAPEntry baseDNEntry = conn.read(replicaEntryDN, new String JavaDoc[] { "1.1" });
1212      if (baseDNEntry == null)
1213      {
1214        try
1215        {
1216          conn.disconnect();
1217        } catch (Exception JavaDoc e2) {}
1218
1219        outputMessages.add("ERROR: Unable to retrieve the replica check " +
1220                           "entry.");
1221        return false;
1222      }
1223      else
1224      {
1225        outputMessages.add("Successfully read the replica check entry.");
1226        outputMessages.add("");
1227      }
1228    }
1229    catch (Exception JavaDoc e)
1230    {
1231      try
1232      {
1233        conn.disconnect();
1234      } catch (Exception JavaDoc e2) {}
1235
1236      outputMessages.add("ERROR: Unable to retrieve the replica check " +
1237                         "entry: " + stackTraceToString(e));
1238      return false;
1239    }
1240
1241
1242    // At this point, all tests on the replica have passed. Close the
1243
// connection and return true.
1244
try
1245    {
1246      conn.disconnect();
1247    } catch (Exception JavaDoc e) {}
1248
1249
1250    outputMessages.add("All tests completed successfully.");
1251    return true;
1252  }
1253
1254
1255
1256  /**
1257   * Performs initialization for this job on each client immediately before each
1258   * thread is created to actually run the job.
1259   *
1260   * @param clientID The ID assigned to the client running this job.
1261   * @param parameters The set of parameters provided to this job that can be
1262   * used to customize its behavior.
1263   *
1264   * @throws UnableToRunException If the client initialization could not be
1265   * completed successfully and the job is unable
1266   * to run.
1267   */

1268  public void initializeClient(String JavaDoc clientID, ParameterList parameters)
1269         throws UnableToRunException
1270  {
1271    // Indicate that no latency tracker thread has yet been chosen.
1272
latencyTrackerChosen = false;
1273
1274
1275    // Get the master directory server address
1276
masterHostParameter =
1277         parameters.getStringParameter(masterHostParameter.getName());
1278    if (masterHostParameter == null)
1279    {
1280      throw new UnableToRunException("No master directory server host " +
1281                                     "provided.");
1282    }
1283    else
1284    {
1285      masterHost = masterHostParameter.getStringValue();
1286    }
1287
1288
1289    // Get the master server port
1290
masterPortParameter =
1291         parameters.getIntegerParameter(masterPortParameter.getName());
1292    if (masterPortParameter != null)
1293    {
1294      masterPort = masterPortParameter.getIntValue();
1295    }
1296
1297
1298    // Get the address of the replica directory server
1299
replicaHost = null;
1300    replicaHostParameter =
1301         parameters.getStringParameter(replicaHostParameter.getName());
1302    if (replicaHostParameter != null)
1303    {
1304      replicaHost = replicaHostParameter.getStringValue();
1305    }
1306
1307
1308    // Get the port for the replica directory server
1309
replicaPort = 389;
1310    replicaPortParameter =
1311         parameters.getIntegerParameter(replicaPortParameter.getName());
1312    if (replicaPortParameter != null)
1313    {
1314      replicaPort = replicaPortParameter.getIntValue();
1315    }
1316
1317
1318    // Get the DN of the entry to use in the latency checks.
1319
replicaEntryDN = null;
1320    replicaEntryDNParameter =
1321         parameters.getStringParameter(replicaEntryDNParameter.getName());
1322    if (replicaEntryDNParameter != null)
1323    {
1324      replicaEntryDN = replicaEntryDNParameter.getStringValue();
1325    }
1326
1327
1328    // Get the delay between latency checks.
1329
latencyDelay = 0;
1330    replicaDelayParameter =
1331         parameters.getIntegerParameter(replicaDelayParameter.getName());
1332    if (replicaDelayParameter != null)
1333    {
1334      latencyDelay = replicaDelayParameter.getIntValue();
1335    }
1336
1337
1338    // Get the DN to use to bind to the directory server.
1339
bindDNParameter = parameters.getStringParameter(bindDNParameter.getName());
1340    if (bindDNParameter == null)
1341    {
1342      bindDN = "";
1343    }
1344    else
1345    {
1346      bindDN = bindDNParameter.getStringValue();
1347    }
1348
1349    // Get the password to use to bind to the directory server.
1350
bindPWParameter =
1351         parameters.getPasswordParameter(bindPWParameter.getName());
1352    if (bindPWParameter == null)
1353    {
1354      bindPW = "";
1355    }
1356    else
1357    {
1358      bindPW = bindPWParameter.getStringValue();
1359    }
1360
1361    // Get the search base
1362
searchBaseParameter =
1363         parameters.getStringParameter(searchBaseParameter.getName());
1364    if (searchBaseParameter != null)
1365    {
1366      searchBase = searchBaseParameter.getStringValue();
1367    }
1368
1369
1370    // Get the password to use when authenticating to the directory.
1371
loginPasswordParameter =
1372         parameters.getPasswordParameter(loginPasswordParameter.getName());
1373    if ((loginPasswordParameter != null) &&
1374          (loginPasswordParameter.hasValue()))
1375    {
1376      loginPassword = loginPasswordParameter.getStringValue();
1377    }
1378
1379
1380    // Get the login ID value for the first user criteria.
1381
loginIDValue1Parameter =
1382         parameters.getStringParameter(loginIDValue1Parameter.getName());
1383    useLoginIDRange1 = true;
1384    useSequential1 = false;
1385    String JavaDoc loginIDValue1 = loginIDValue1Parameter.getStringValue();
1386    try
1387    {
1388      int openPos = loginIDValue1.indexOf('[');
1389      int closePos = loginIDValue1.indexOf(']', openPos);
1390      loginIDInitial1 = loginIDValue1.substring(0, openPos);
1391      loginIDFinal1 = loginIDValue1.substring(closePos+1);
1392
1393      int dashPos = loginIDValue1.indexOf('-', openPos);
1394      if (dashPos < 0)
1395      {
1396        dashPos = loginIDValue1.indexOf(':', openPos);
1397        useSequential1 = true;
1398      }
1399
1400      loginIDMin1 = Integer.parseInt(loginIDValue1.substring(openPos+1,
1401                                                              dashPos));
1402      loginIDMax1 = Integer.parseInt(loginIDValue1.substring(dashPos+1,
1403                                                              closePos));
1404      loginIDSpan1 = loginIDMax1 - loginIDMin1 + 1;
1405      sequentialCounter1 = loginIDMin1;
1406    }
1407    catch (Exception JavaDoc e)
1408    {
1409      useLoginIDRange1 = false;
1410      loginIDInitial1 = loginIDValue1;
1411    }
1412
1413
1414    // Get the login ID value for the first user criteria.
1415
loginIDValue2Parameter =
1416         parameters.getStringParameter(loginIDValue2Parameter.getName());
1417    useLoginIDRange2 = true;
1418    useSequential2 = false;
1419    String JavaDoc loginIDValue2 = loginIDValue2Parameter.getStringValue();
1420    try
1421    {
1422      int openPos = loginIDValue2.indexOf('[');
1423      int closePos = loginIDValue2.indexOf(']', openPos);
1424      loginIDInitial2 = loginIDValue2.substring(0, openPos);
1425      loginIDFinal2 = loginIDValue2.substring(closePos+1);
1426
1427      int dashPos = loginIDValue2.indexOf('-', openPos);
1428      if (dashPos < 0)
1429      {
1430        dashPos = loginIDValue2.indexOf(':', openPos);
1431        useSequential2 = true;
1432      }
1433
1434      loginIDMin2 = Integer.parseInt(loginIDValue2.substring(openPos+1,
1435                                                              dashPos));
1436      loginIDMax2 = Integer.parseInt(loginIDValue2.substring(dashPos+1,
1437                                                              closePos));
1438      loginIDSpan2 = loginIDMax2 - loginIDMin2 + 1;
1439      sequentialCounter2 = loginIDMin2;
1440    }
1441    catch (Exception JavaDoc e)
1442    {
1443      useLoginIDRange2 = false;
1444      loginIDInitial2 = loginIDValue2;
1445    }
1446
1447
1448    // Get the weight.
1449
weightParameter = parameters.getIntegerParameter(weightParameter.getName());
1450    if ((weightParameter != null) && (weightParameter.hasValue()))
1451    {
1452      loginID1Percent = weightParameter.getIntValue();
1453    }
1454
1455
1456    // Get the login ID attribute.
1457
loginIDParameter =
1458         parameters.getStringParameter(loginIDParameter.getName());
1459    if (loginIDParameter != null)
1460    {
1461      loginIDAttr = loginIDParameter.getStringValue();
1462    }
1463
1464
1465    // Get the attributes to retrieve.
1466
attr1Parameter = parameters.getStringParameter(attr1Parameter.getName());
1467    if (attr1Parameter != null)
1468    {
1469      searchAttr1 = attr1Parameter.getStringValue();
1470      filter1 = "(" + searchAttr1 + "=*)";
1471      returnAttrs1 = new String JavaDoc[] { searchAttr1 };
1472    }
1473
1474    attr2Parameter = parameters.getStringParameter(attr2Parameter.getName());
1475    if (attr2Parameter != null)
1476    {
1477      searchAttr2 = attr2Parameter.getStringValue();
1478      filter2 = "(" + searchAttr2 + "=*)";
1479      returnAttrs2 = new String JavaDoc[] { searchAttr2 };
1480    }
1481
1482    attr3Parameter = parameters.getStringParameter(attr3Parameter.getName());
1483    if (attr3Parameter != null)
1484    {
1485      searchAttr3 = attr3Parameter.getStringValue();
1486      filter3 = "(" + searchAttr3 + "=*)";
1487      returnAttrs3 = new String JavaDoc[] { searchAttr3 };
1488    }
1489
1490    returnAttrsOC = new String JavaDoc[] { "objectClass" };
1491
1492
1493    // Get the attributes to modify.
1494
modAttrs = null;
1495    modAttrsParameter =
1496         parameters.getMultiLineTextParameter(modAttrsParameter.getName());
1497    if ((modAttrsParameter != null) && (modAttrsParameter.hasValue()))
1498    {
1499      modAttrs = modAttrsParameter.getNonBlankLines();
1500    }
1501
1502    // Determine whether to skip the bind attempt.
1503
skipBind = false;
1504    skipBindParameter =
1505         parameters.getBooleanParameter(skipBindParameter.getName());
1506    if (skipBindParameter != null)
1507    {
1508      skipBind = skipBindParameter.getBooleanValue();
1509    }
1510
1511    // Get the warm up time.
1512
warmUpTime = 0;
1513    warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName());
1514    if (warmUpParameter != null)
1515    {
1516      warmUpTime = warmUpParameter.getIntValue();
1517    }
1518
1519    // Get the cool down time.
1520
coolDownTime = 0;
1521    coolDownParameter =
1522         parameters.getIntegerParameter(coolDownParameter.getName());
1523    if (coolDownParameter != null)
1524    {
1525      coolDownTime = coolDownParameter.getIntValue();
1526    }
1527
1528    // Get the max operation time limit.
1529
timeLimitParameter =
1530         parameters.getIntegerParameter(timeLimitParameter.getName());
1531    if (timeLimitParameter != null)
1532    {
1533      timeLimit = timeLimitParameter.getIntValue();
1534    }
1535
1536    // Get the delay between authentication attempts.
1537
delay = 0;
1538    delayParameter = parameters.getIntegerParameter(delayParameter.getName());
1539    if (delayParameter != null)
1540    {
1541      delay = delayParameter.getIntValue();
1542    }
1543
1544
1545    // Get the indicator that specifies whether to ignore invalid credentials
1546
// errors.
1547
ignoreInvCredParameter =
1548         parameters.getBooleanParameter(ignoreInvCredParameter.getName());
1549    if (ignoreInvCredParameter != null)
1550    {
1551      ignoreInvalidCredentials = ignoreInvCredParameter.getBooleanValue();
1552    }
1553
1554    // Get the indicator that specifies whether to use shared connections.
1555
shareConnsParameter =
1556         parameters.getBooleanParameter(shareConnsParameter.getName());
1557    if (shareConnsParameter != null)
1558    {
1559      useSharedConnections = shareConnsParameter.getBooleanValue();
1560    }
1561
1562
1563    // If we are to use shared connections, then establish them now.
1564
if (useSharedConnections)
1565    {
1566      sharedAuthConnection = new LDAPConnection();
1567      sharedBindConnection = new LDAPConnection();
1568
1569      try
1570      {
1571        sharedAuthConnection.connect(3, masterHost, masterPort, bindDN,
1572                                     bindPW);
1573        sharedBindConnection.connect(3, masterHost, masterPort, "", "");
1574      }
1575      catch (Exception JavaDoc e)
1576      {
1577        throw new UnableToRunException("Could not establish shared " +
1578                                       "connections to the directory: " + e,
1579                                       e);
1580      }
1581    }
1582
1583
1584    // Seed the parent random number generator.
1585
parentRandom = new Random();
1586  }
1587
1588
1589
1590  /**
1591   * Initializes this job class with the information that it will use when
1592   * actually running the job. This will also initialize the stat trackers used
1593   * by the job.
1594   *
1595   * @param clientID The thread ID for this thread.
1596   * @param threadID The thread ID for this thread.
1597   * @param collectionInterval The collection interval to use for gathering
1598   * statistics while processing the job.
1599   * @param parameters The st of parameters that contain the
1600   * information used to customize the way this job
1601   * is processed.
1602   *
1603   * @throws UnableToRunException If a problem occurs that prevents the thread
1604   * from being able to run properly.
1605   */

1606  public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
1607                               int collectionInterval, ParameterList parameters)
1608         throws UnableToRunException
1609  {
1610    // Seed the random number generator for this thread.
1611
random = new Random(parentRandom.nextLong());
1612
1613    // If we are not going to use shared connections, then create the
1614
// connections for use by this thread. Otherwise, just grab the shared
1615
// connections.
1616
if (useSharedConnections)
1617    {
1618      authConnection = sharedAuthConnection;
1619      bindConnection = sharedBindConnection;
1620    }
1621    else
1622    {
1623      authConnection = new LDAPConnection();
1624      bindConnection = new LDAPConnection();
1625
1626      try
1627      {
1628        authConnection.connect(3, masterHost, masterPort, bindDN, bindPW);
1629        bindConnection.connect(3, masterHost, masterPort, "", "");
1630      }
1631      catch (Exception JavaDoc e)
1632      {
1633        throw new UnableToRunException("Unable to establish the connections " +
1634                                       "to the directory server: " + e, e);
1635      }
1636    }
1637
1638    // Initialize the constraints.
1639
authConstraints = authConnection.getConstraints();
1640    bindConstraints = bindConnection.getConstraints();
1641    authSearchConstraints = authConnection.getSearchConstraints();
1642    authConstraints.setTimeLimit(1000*timeLimit);
1643    bindConstraints.setTimeLimit(1000*timeLimit);
1644    authSearchConstraints.setTimeLimit(1000*timeLimit);
1645    authSearchConstraints.setServerTimeLimit(timeLimit);
1646
1647
1648    // Create the stat trackers.
1649
overallAttemptCounter =
1650         new IncrementalTracker(clientID, threadID,
1651                                STAT_TRACKER_OVERALL_AUTHENTICATION_ATTEMPTS,
1652                                collectionInterval);
1653    attemptCounter1 =
1654         new IncrementalTracker(clientID, threadID,
1655                                STAT_TRACKER_AUTHENTICATION_1_ATTEMPTS,
1656                                collectionInterval);
1657    attemptCounter2 =
1658         new IncrementalTracker(clientID, threadID,
1659                                STAT_TRACKER_AUTHENTICATION_2_ATTEMPTS,
1660                                collectionInterval);
1661    overallSuccessCounter =
1662         new IncrementalTracker(clientID, threadID,
1663                                STAT_TRACKER_OVERALL_SUCCESSFUL_AUTHENTICATIONS,
1664                                collectionInterval);
1665    successCounter1 =
1666         new IncrementalTracker(clientID, threadID,
1667                                STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_1,
1668                                collectionInterval);
1669    successCounter2 =
1670         new IncrementalTracker(clientID, threadID,
1671                                STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_2,
1672                                collectionInterval);
1673    overallFailureCounter =
1674         new IncrementalTracker(clientID, threadID,
1675                                STAT_TRACKER_OVERALL_FAILED_AUTHENTICATIONS,
1676                                collectionInterval);
1677    failureCounter1 =
1678         new IncrementalTracker(clientID, threadID,
1679                                STAT_TRACKER_FAILED_AUTHENTICATIONS_1,
1680                                collectionInterval);
1681    failureCounter2 =
1682         new IncrementalTracker(clientID, threadID,
1683                                STAT_TRACKER_FAILED_AUTHENTICATIONS_2,
1684                                collectionInterval);
1685    overallAuthTimer = new TimeTracker(clientID, threadID,
1686                                       STAT_TRACKER_OVERALL_AUTHENTICATION_TIME,
1687                                       collectionInterval);
1688    authTimer1 = new TimeTracker(clientID, threadID,
1689                                 STAT_TRACKER_AUTHENTICATION_1_TIME,
1690                                 collectionInterval);
1691    authTimer2 = new TimeTracker(clientID, threadID,
1692                                 STAT_TRACKER_AUTHENTICATION_2_TIME,
1693                                 collectionInterval);
1694    failureReasonTracker = new CategoricalTracker(clientID, threadID,
1695                                                  STAT_TRACKER_FAIL_REASON,
1696                                                  collectionInterval);
1697
1698
1699    // Enable real-time reporting of the data for these stat trackers.
1700
RealTimeStatReporter statReporter = getStatReporter();
1701    if (statReporter != null)
1702    {
1703      String JavaDoc jobID = getJobID();
1704      overallAttemptCounter.enableRealTimeStats(statReporter, jobID);
1705      attemptCounter1.enableRealTimeStats(statReporter, jobID);
1706      attemptCounter2.enableRealTimeStats(statReporter, jobID);
1707      overallSuccessCounter.enableRealTimeStats(statReporter, jobID);
1708      successCounter1.enableRealTimeStats(statReporter, jobID);
1709      successCounter2.enableRealTimeStats(statReporter, jobID);
1710      overallFailureCounter.enableRealTimeStats(statReporter, jobID);
1711      failureCounter1.enableRealTimeStats(statReporter, jobID);
1712      failureCounter2.enableRealTimeStats(statReporter, jobID);
1713      overallAuthTimer.enableRealTimeStats(statReporter, jobID);
1714      authTimer1.enableRealTimeStats(statReporter, jobID);
1715      authTimer2.enableRealTimeStats(statReporter, jobID);
1716    }
1717
1718
1719    // See if this thread should be used to report the replica latency
1720
// information. If so, then start the latency check threads.
1721
if ((! latencyTrackerChosen) && (getClientNumber() == 0))
1722    {
1723      latencyCheckMutex = new Object JavaDoc();
1724      latencyTrackerChosen = true;
1725      reportLatencyTracker = true;
1726
1727      // Create the latency timer stat tracker.
1728
latencyTime = new TimeTracker(clientID, threadID,
1729                                    STAT_TRACKER_REPLICATION_LATENCY,
1730                                    collectionInterval);
1731      if (statReporter != null)
1732      {
1733        latencyTime.enableRealTimeStats(statReporter, getJobID());
1734      }
1735
1736      // Create the latency categories stat tracker.
1737
latencyCategories =
1738           new CategoricalTracker(clientID, threadID,
1739                                  STAT_TRACKER_CATEGORIZED_LATENCY,
1740                                  collectionInterval);
1741
1742      // Create the latency thread that will make changes to the master server.
1743
try
1744      {
1745        masterThread =
1746             new LatencyCheckMasterThread(this, masterHost, masterPort, bindDN,
1747                                          bindPW, replicaEntryDN,
1748                                          modAttrs[0], latencyDelay);
1749      }
1750      catch (LDAPException le)
1751      {
1752        throw new UnableToRunException("Could not create the master latency " +
1753                                       "thread: " + le, le);
1754      }
1755
1756      // Create the latency thread that will read changes from the replica.
1757
try
1758      {
1759        replicaThread =
1760             new LatencyCheckReplicaThread(this, replicaHost, replicaPort,
1761                                           bindDN, bindPW,
1762                                           replicaEntryDN);
1763      }
1764      catch (LDAPException le)
1765      {
1766        throw new UnableToRunException("Could not create the replica latency " +
1767                                       "thread: " + le, le);
1768      }
1769
1770      // Start the latency check threads.
1771
masterThread.start();
1772      replicaThread.start();
1773    }
1774    else
1775    {
1776      reportLatencyTracker = false;
1777    }
1778  }
1779
1780
1781
1782  /**
1783   * Performs the work of actually running the job. When this method completes,
1784   * the job will be done.
1785   */

1786  public void runJob()
1787  {
1788    // Determine the range of time for which we should collect statistics.
1789
long currentTime = System.currentTimeMillis();
1790    boolean collectingStats = false;
1791    long startCollectingTime = currentTime + (1000 * warmUpTime);
1792    long stopCollectingTime = Long.MAX_VALUE;
1793    if ((coolDownTime > 0) && (getShouldStopTime() > 0))
1794    {
1795      stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime);
1796    }
1797
1798    // Define a variable that will be used to determine how long to sleep
1799
// between attempts.
1800
long authStartTime = 0;
1801
1802
1803    // Loop until it is time to stop.
1804
while (! shouldStop())
1805    {
1806      currentTime = System.currentTimeMillis();
1807      if ((! collectingStats) && (currentTime >= startCollectingTime) &&
1808          (currentTime < stopCollectingTime))
1809      {
1810        // Start all the stat trackers.
1811
overallAttemptCounter.startTracker();
1812        attemptCounter1.startTracker();
1813        attemptCounter2.startTracker();
1814        overallSuccessCounter.startTracker();
1815        successCounter1.startTracker();
1816        successCounter2.startTracker();
1817        overallFailureCounter.startTracker();
1818        failureCounter1.startTracker();
1819        failureCounter2.startTracker();
1820        overallAuthTimer.startTracker();
1821        authTimer1.startTracker();
1822        authTimer2.startTracker();
1823        failureReasonTracker.startTracker();
1824
1825        if (reportLatencyTracker)
1826        {
1827          latencyTime.startTracker();
1828          latencyCategories.startTracker();
1829          replicaThread.startChecking();
1830          masterThread.startChecking();
1831        }
1832
1833        collectingStats = true;
1834      }
1835      else if ((collectingStats) && (currentTime >= stopCollectingTime))
1836      {
1837        overallAttemptCounter.stopTracker();
1838        attemptCounter1.stopTracker();
1839        attemptCounter2.stopTracker();
1840        overallSuccessCounter.stopTracker();
1841        successCounter1.stopTracker();
1842        successCounter2.stopTracker();
1843        overallFailureCounter.stopTracker();
1844        failureCounter1.stopTracker();
1845        failureCounter2.stopTracker();
1846        overallAuthTimer.stopTracker();
1847        authTimer1.stopTracker();
1848        authTimer2.stopTracker();
1849        failureReasonTracker.stopTracker();
1850
1851        if (reportLatencyTracker)
1852        {
1853          latencyTime.stopTracker();
1854          latencyCategories.stopTracker();
1855          replicaThread.stopAndWait();
1856          masterThread.stopAndWait();
1857        }
1858
1859        collectingStats = false;
1860      }
1861
1862      // See if we need to sleep before the next attempt
1863
if ((delay > 0) && (authStartTime > 0))
1864      {
1865        long now = System.currentTimeMillis();
1866        long sleepTime = delay - (now - authStartTime);
1867        if (sleepTime > 0)
1868        {
1869          try
1870          {
1871            Thread.sleep(sleepTime);
1872          } catch (InterruptedException JavaDoc ie) {}
1873
1874          if (shouldStop())
1875          {
1876            break;
1877          }
1878        }
1879      }
1880
1881
1882      // Get a random number between 1 and 100 to use to determine which user
1883
// criteria to use to attempt the authentication.
1884
int weight = ((random.nextInt() & 0x7FFFFFFF) % 100);
1885      if (weight < loginID1Percent)
1886      {
1887        // Get a random user number from the first range and translate that to a
1888
// login ID and password.
1889
String JavaDoc[] loginInfo = getLoginInfo1();
1890        String JavaDoc loginID = loginInfo[0];
1891        String JavaDoc password = loginInfo[1];
1892
1893
1894        // Start the auth attempt timer now.
1895
if (delay > 0)
1896        {
1897          authStartTime = System.currentTimeMillis();
1898        }
1899
1900
1901        // Increment the number of authentication attempts and start the timer
1902
if (collectingStats)
1903        {
1904          overallAttemptCounter.increment();
1905          attemptCounter1.increment();
1906          overallAuthTimer.startTimer();
1907          authTimer1.startTimer();
1908        }
1909
1910        String JavaDoc failureReason = "Search 1";
1911
1912        try
1913        {
1914          // First, issue a search to try to find the user's entry.
1915
String JavaDoc userDN = null;
1916          String JavaDoc filter = "(" + loginIDAttr + "=" + loginID + ")";
1917          LDAPSearchResults results;
1918          results = authConnection.search(searchBase, LDAPConnection.SCOPE_SUB,
1919                                          filter, returnAttrsOC, false,
1920                                          authSearchConstraints);
1921          while (results.hasMoreElements())
1922          {
1923            Object JavaDoc element = results.nextElement();
1924            if (element instanceof LDAPEntry)
1925            {
1926              userDN = ((LDAPEntry) element).getDN();
1927            }
1928          }
1929
1930          // Make sure that we got a user DN. If not, then it's a failed
1931
// attempt.
1932
if (userDN == null)
1933          {
1934            if (collectingStats)
1935            {
1936              overallFailureCounter.increment();
1937              failureCounter1.increment();
1938              overallAuthTimer.stopTimer();
1939              authTimer1.stopTimer();
1940              failureReasonTracker.increment(failureReason);
1941            }
1942            continue;
1943          }
1944
1945          // Now do a base-level search on the user's entry to retrieve the
1946
// objectClass attribute.
1947
failureReason = "Search 2";
1948          filter = "(objectClass=*)";
1949          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
1950                                          filter, returnAttrsOC, false,
1951                                          authSearchConstraints);
1952          while (results.hasMoreElements())
1953          {
1954            results.nextElement();
1955          }
1956
1957          // Now bind as the user.
1958
if (! skipBind)
1959          {
1960            failureReason = "Bind";
1961
1962            try
1963            {
1964              bindConnection.authenticate(3, userDN, password, bindConstraints);
1965            }
1966            catch (LDAPException le)
1967            {
1968              if (le.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS)
1969              {
1970                if (! ignoreInvalidCredentials)
1971                {
1972                  if (collectingStats)
1973                  {
1974                    overallFailureCounter.increment();
1975                    failureCounter1.increment();
1976                    overallAuthTimer.stopTimer();
1977                    authTimer1.stopTimer();
1978                    failureReasonTracker.increment(failureReason);
1979                  }
1980                  continue;
1981                }
1982              }
1983              else
1984              {
1985                if (collectingStats)
1986                {
1987                  overallFailureCounter.increment();
1988                  failureCounter1.increment();
1989                  overallAuthTimer.stopTimer();
1990                  authTimer1.stopTimer();
1991                  failureReasonTracker.increment(failureReason);
1992                }
1993                continue;
1994              }
1995            }
1996          }
1997
1998          // Now retrieve the "attr1" attribute from the user's entry.
1999
failureReason = "Search 3";
2000          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2001                                          filter1, returnAttrs1, false,
2002                                          authSearchConstraints);
2003          while (results.hasMoreElements())
2004          {
2005            results.nextElement();
2006          }
2007
2008          // Retrieve the "attr2" attribute from the user's entry.
2009
failureReason = "Search 4";
2010          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2011                                          filter2, returnAttrs2, false,
2012                                          authSearchConstraints);
2013          while (results.hasMoreElements())
2014          {
2015            results.nextElement();
2016          }
2017
2018          // Retrieve the first attribute again.
2019
failureReason = "Search 5";
2020          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2021                                          filter1, returnAttrs1, false,
2022                                          authSearchConstraints);
2023          while (results.hasMoreElements())
2024          {
2025            results.nextElement();
2026          }
2027
2028          // Perform a modification on the entry
2029
if ((modAttrs != null) && (modAttrs.length > 0))
2030          {
2031            failureReason = "Modify";
2032            LDAPModificationSet modSet = new LDAPModificationSet();
2033            for (int i=0; i < modAttrs.length; i++)
2034            {
2035              LDAPAttribute attr = new LDAPAttribute(modAttrs[i],
2036                                                     getRandomString(80));
2037              modSet.add(LDAPModification.REPLACE, attr);
2038            }
2039            authConnection.modify(userDN, modSet, authConstraints);
2040          }
2041
2042          // Retrieve the first attribute again.
2043
failureReason = "Search 6";
2044          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2045                                          filter1, returnAttrs1, false,
2046                                          authSearchConstraints);
2047          while (results.hasMoreElements())
2048          {
2049            results.nextElement();
2050          }
2051
2052          // Retrieve the first attribute again.
2053
failureReason = "Search 7";
2054          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2055                                          filter1, returnAttrs1, false,
2056                                          authSearchConstraints);
2057          while (results.hasMoreElements())
2058          {
2059            results.nextElement();
2060          }
2061
2062          // Retrieve the third attribute.
2063
failureReason = "Search 8";
2064          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2065                                          filter3, returnAttrs3, false,
2066                                          authSearchConstraints);
2067          while (results.hasMoreElements())
2068          {
2069            results.nextElement();
2070          }
2071        }
2072        catch (Exception JavaDoc e)
2073        {
2074
2075          if (collectingStats)
2076          {
2077            overallFailureCounter.increment();
2078            failureCounter1.increment();
2079            overallAuthTimer.stopTimer();
2080            authTimer1.stopTimer();
2081            failureReasonTracker.increment(failureReason);
2082          }
2083          continue;
2084        }
2085
2086        // If we have gotten here, then everything is done and we can consider
2087
// the authentication successful.
2088
if (collectingStats)
2089        {
2090          overallSuccessCounter.increment();
2091          successCounter1.increment();
2092          overallAuthTimer.stopTimer();
2093          authTimer1.stopTimer();
2094        }
2095      }
2096      else
2097      {
2098        // Get a random user number from the second range and translate that to
2099
// a login ID and password.
2100
String JavaDoc[] loginInfo = getLoginInfo2();
2101        String JavaDoc loginID = loginInfo[0];
2102        String JavaDoc password = loginInfo[1];
2103
2104
2105        // Start the auth attempt timer now.
2106
if (delay > 0)
2107        {
2108          authStartTime = System.currentTimeMillis();
2109        }
2110
2111
2112        // Increment the number of authentication attempts and start the timer
2113
if (collectingStats)
2114        {
2115          overallAttemptCounter.increment();
2116          attemptCounter2.increment();
2117          overallAuthTimer.startTimer();
2118          authTimer2.startTimer();
2119        }
2120
2121        String JavaDoc failureReason = "Search 1";
2122
2123        try
2124        {
2125          // First, issue a search to try to find the user's entry.
2126
String JavaDoc userDN = null;
2127          String JavaDoc filter = "(" + loginIDAttr + "=" + loginID + ")";
2128          LDAPSearchResults results;
2129          results = authConnection.search(searchBase, LDAPConnection.SCOPE_SUB,
2130                                          filter, returnAttrsOC, false,
2131                                          authSearchConstraints);
2132          while (results.hasMoreElements())
2133          {
2134            Object JavaDoc element = results.nextElement();
2135            if (element instanceof LDAPEntry)
2136            {
2137              userDN = ((LDAPEntry) element).getDN();
2138            }
2139          }
2140
2141          // Make sure that we got a user DN. If not, then it's a failed
2142
// attempt.
2143
if (userDN == null)
2144          {
2145            if (collectingStats)
2146            {
2147              overallFailureCounter.increment();
2148              failureCounter2.increment();
2149              overallAuthTimer.stopTimer();
2150              authTimer2.stopTimer();
2151              failureReasonTracker.increment(failureReason);
2152            }
2153            continue;
2154          }
2155
2156          // Now do a base-level search on the user's entry to retrieve the
2157
// objectClass attribute.
2158
failureReason = "Search 2";
2159          filter = "(objectClass=*)";
2160          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2161                                          filter, returnAttrsOC, false,
2162                                          authSearchConstraints);
2163          while (results.hasMoreElements())
2164          {
2165            results.nextElement();
2166          }
2167
2168          // Now bind as the user.
2169
if (! skipBind)
2170          {
2171            failureReason = "Bind";
2172
2173            try
2174            {
2175              bindConnection.authenticate(3, userDN, password, bindConstraints);
2176            }
2177            catch (LDAPException le)
2178            {
2179              if (le.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS)
2180              {
2181                if (! ignoreInvalidCredentials)
2182                {
2183                  if (collectingStats)
2184                  {
2185                    overallFailureCounter.increment();
2186                    failureCounter2.increment();
2187                    overallAuthTimer.stopTimer();
2188                    authTimer2.stopTimer();
2189                    failureReasonTracker.increment(failureReason);
2190                  }
2191                  continue;
2192                }
2193              }
2194              else
2195              {
2196                if (collectingStats)
2197                {
2198                  overallFailureCounter.increment();
2199                  failureCounter2.increment();
2200                  overallAuthTimer.stopTimer();
2201                  authTimer2.stopTimer();
2202                  failureReasonTracker.increment(failureReason);
2203                }
2204                continue;
2205              }
2206            }
2207          }
2208
2209          // Now retrieve the "attr1" attribute from the user's entry.
2210
failureReason = "Search 3";
2211          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2212                                          filter1, returnAttrs1, false,
2213                                          authSearchConstraints);
2214          while (results.hasMoreElements())
2215          {
2216            results.nextElement();
2217          }
2218
2219          // Retrieve the "attr2" attribute from the user's entry.
2220
failureReason = "Search 4";
2221          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2222                                          filter2, returnAttrs2, false,
2223                                          authSearchConstraints);
2224          while (results.hasMoreElements())
2225          {
2226            results.nextElement();
2227          }
2228
2229          // Retrieve the first attribute again.
2230
failureReason = "Search 5";
2231          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2232                                          filter1, returnAttrs1, false,
2233                                          authSearchConstraints);
2234          while (results.hasMoreElements())
2235          {
2236            results.nextElement();
2237          }
2238
2239          // Perform a modification on the entry
2240
if ((modAttrs != null) && (modAttrs.length > 0))
2241          {
2242            failureReason = "Modify";
2243            LDAPModificationSet modSet = new LDAPModificationSet();
2244            for (int i=0; i < modAttrs.length; i++)
2245            {
2246              LDAPAttribute attr = new LDAPAttribute(modAttrs[i],
2247                                                     getRandomString(80));
2248              modSet.add(LDAPModification.REPLACE, attr);
2249            }
2250            authConnection.modify(userDN, modSet, authConstraints);
2251          }
2252
2253          // Retrieve the first attribute again.
2254
failureReason = "Search 6";
2255          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2256                                          filter1, returnAttrs1, false,
2257                                          authSearchConstraints);
2258          while (results.hasMoreElements())
2259          {
2260            results.nextElement();
2261          }
2262
2263          // Retrieve the first attribute again.
2264
failureReason = "Search 7";
2265          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2266                                          filter1, returnAttrs1, false,
2267                                          authSearchConstraints);
2268          while (results.hasMoreElements())
2269          {
2270            results.nextElement();
2271          }
2272
2273          // Retrieve the third attribute.
2274
failureReason = "Search 8";
2275          results = authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2276                                          filter3, returnAttrs3, false,
2277                                          authSearchConstraints);
2278          while (results.hasMoreElements())
2279          {
2280            results.nextElement();
2281          }
2282        }
2283        catch (Exception JavaDoc e)
2284        {
2285
2286          if (collectingStats)
2287          {
2288            overallFailureCounter.increment();
2289            failureCounter2.increment();
2290            overallAuthTimer.stopTimer();
2291            authTimer2.stopTimer();
2292            failureReasonTracker.increment(failureReason);
2293          }
2294          continue;
2295        }
2296
2297        // If we have gotten here, then everything is done and we can consider
2298
// the authentication successful.
2299
if (collectingStats)
2300        {
2301          overallSuccessCounter.increment();
2302          successCounter2.increment();
2303          overallAuthTimer.stopTimer();
2304          authTimer2.stopTimer();
2305        }
2306      }
2307    }
2308
2309
2310    // Stop all the stat trackers.
2311
if (collectingStats)
2312    {
2313      overallAttemptCounter.stopTracker();
2314      attemptCounter1.stopTracker();
2315      attemptCounter2.stopTracker();
2316      overallSuccessCounter.stopTracker();
2317      successCounter1.stopTracker();
2318      successCounter2.stopTracker();
2319      overallFailureCounter.stopTracker();
2320      failureCounter1.stopTracker();
2321      failureCounter2.stopTracker();
2322      overallAuthTimer.stopTracker();
2323      authTimer1.stopTracker();
2324      authTimer2.stopTracker();
2325      failureReasonTracker.stopTracker();
2326
2327      if (reportLatencyTracker)
2328      {
2329        latencyTime.stopTracker();
2330        latencyCategories.stopTracker();
2331        replicaThread.stopAndWait();
2332        masterThread.stopAndWait();
2333      }
2334    }
2335
2336
2337    // Close the connections to the directory server if appropriate.
2338
if (! useSharedConnections)
2339    {
2340      try
2341      {
2342        authConnection.disconnect();
2343      } catch (Exception JavaDoc e) {}
2344
2345      try
2346      {
2347        bindConnection.disconnect();
2348      } catch (Exception JavaDoc e) {}
2349    }
2350  }
2351
2352
2353
2354  /**
2355   * Attempts to force this thread to exit by closing the connection to the
2356   * directory server and setting it to <CODE>null</CODE>.
2357   */

2358  public void destroy()
2359  {
2360    if (authConnection != null)
2361    {
2362      try
2363      {
2364        authConnection.disconnect();
2365      } catch (Exception JavaDoc e) {}
2366
2367      authConnection = null;
2368    }
2369
2370    if (bindConnection != null)
2371    {
2372      try
2373      {
2374        bindConnection.disconnect();
2375      } catch (Exception JavaDoc e) {}
2376
2377      bindConnection = null;
2378    }
2379
2380    if (masterThread != null)
2381    {
2382      masterThread.masterThread.interrupt();
2383
2384      try
2385      {
2386        masterThread.connection.disconnect();
2387      } catch (Exception JavaDoc e) {}
2388
2389      masterThread.connection = null;
2390      masterThread = null;
2391    }
2392
2393    if (replicaThread != null)
2394    {
2395      replicaThread.replicaThread.interrupt();
2396
2397      try
2398      {
2399        replicaThread.connection.disconnect();
2400      } catch (Exception JavaDoc e) {}
2401
2402      replicaThread.connection = null;
2403      replicaThread = null;
2404    }
2405  }
2406
2407
2408
2409  /**
2410   * Performs any per-client finalization that should be done for this job. In
2411   * this case, if the job was using shared connections then those connections
2412   * will be closed.
2413   */

2414  public void finalizeClient()
2415  {
2416    // Make sure that the shared connections get closed properly.
2417
if (useSharedConnections)
2418    {
2419      try
2420      {
2421        sharedAuthConnection.disconnect();
2422      } catch (Exception JavaDoc e) {}
2423
2424      try
2425      {
2426        sharedBindConnection.disconnect();
2427      } catch (Exception JavaDoc e) {}
2428    }
2429  }
2430
2431
2432
2433  /**
2434   * Retrieves an array containing the login ID and password that should be
2435   * used to authenticate to the directory based on the first set of user
2436   * criteria.
2437   *
2438   * @return An array containing the login ID and password.
2439   */

2440  public String JavaDoc[] getLoginInfo1()
2441  {
2442    String JavaDoc[] loginInfo = new String JavaDoc[2];
2443    if (useLoginIDRange1)
2444    {
2445      int value;
2446      if (useSequential1)
2447      {
2448        value = sequentialCounter1++;
2449        if (sequentialCounter1 > loginIDMax1)
2450        {
2451          sequentialCounter1 = loginIDMax1;
2452        }
2453      }
2454      else
2455      {
2456        value = ((random.nextInt() & 0x7FFFFFFF) % loginIDSpan1) + loginIDMin1;
2457      }
2458
2459      loginInfo[0] = loginIDInitial1 + value + loginIDFinal1;
2460      loginInfo[1] = loginPassword;
2461    }
2462    else
2463    {
2464      loginInfo[0] = loginIDInitial1;
2465      loginInfo[1] = loginPassword;
2466    }
2467
2468    return loginInfo;
2469  }
2470
2471
2472
2473  /**
2474   * Retrieves an array containing the login ID and password that should be
2475   * used to authenticate to the directory based on the second set of user
2476   * criteria.
2477   *
2478   * @return An array containing the login ID and password.
2479   */

2480  public String JavaDoc[] getLoginInfo2()
2481  {
2482    String JavaDoc[] loginInfo = new String JavaDoc[2];
2483    if (useLoginIDRange2)
2484    {
2485      int value;
2486      if (useSequential2)
2487      {
2488        value = sequentialCounter2++;
2489        if (sequentialCounter2 > loginIDMax2)
2490        {
2491          sequentialCounter2 = loginIDMax2;
2492        }
2493      }
2494      else
2495      {
2496        value = ((random.nextInt() & 0x7FFFFFFF) % loginIDSpan2) + loginIDMin2;
2497      }
2498
2499      loginInfo[0] = loginIDInitial2 + value + loginIDFinal2;
2500      loginInfo[1] = loginPassword;
2501    }
2502    else
2503    {
2504      loginInfo[0] = loginIDInitial2;
2505      loginInfo[1] = loginPassword;
2506    }
2507
2508    return loginInfo;
2509  }
2510
2511
2512
2513  /**
2514   * Retrieves a string of random characters of the specified length.
2515   *
2516   * @param length The number of characters to include in the string.
2517   *
2518   * @return The generated string of random characters.
2519   */

2520  public String JavaDoc getRandomString(int length)
2521  {
2522    char[] returnArray = new char[length];
2523
2524    for (int i=0; i < returnArray.length; i++)
2525    {
2526      returnArray[i] = ALPHABET[Math.abs((random.nextInt()) & 0x7FFFFFFF) %
2527                                ALPHABET.length];
2528    }
2529
2530    return new String JavaDoc(returnArray);
2531  }
2532}
2533
2534
Popular Tags