KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.*;
21 import java.security.*;
22 import java.util.*;
23 import netscape.ldap.*;
24 import netscape.ldap.factory.*;
25 import com.sun.slamd.job.*;
26 import com.sun.slamd.parameter.*;
27 import com.sun.slamd.stat.*;
28
29
30
31 /**
32  * This class defines a SLAMD job that repeatedly performs authentications
33  * against an LDAP directory server. It will find the user's entry based on a
34  * login ID, attempt to bind as that user, and optionally verify whether that
35  * user is a member of a static group, dynamic group, or role. The query to
36  * find the user may be weighted to more accurately simulate production usage.
37  *
38  *
39  * @author Neil A. Wilson
40  */

41 public class WeightedAuthRateJobClass
42        extends JobClass
43 {
44   /**
45    * The value used to indicate that no membership determination will be made.
46    */

47   public static final int MEMBERSHIP_TYPE_NONE = 0;
48
49
50
51   /**
52    * The value used to indicate that an attempt will be made to determine
53    * whether the user is a member of a static group.
54    */

55   public static final int MEMBERSHIP_TYPE_STATIC = 1;
56
57
58
59   /**
60    * The value used to indicate that an attempt will be made to determine
61    * whether the user is a member of a dynamic group.
62    */

63   public static final int MEMBERSHIP_TYPE_DYNAMIC = 2;
64
65
66
67   /**
68    * The value used to indicate that an attempt will be made to determine
69    * whether the user is a member of a role.
70    */

71   public static final int MEMBERSHIP_TYPE_ROLE = 3;
72
73
74
75   /**
76    * The default attribute used as the login ID.
77    */

78   public static final String JavaDoc DEFAULT_LOG_ID_ATTR = "uid";
79
80
81
82   /**
83    * The name of the LDAP attribute that contains the DNs of the roles to which
84    * a user belongs.
85    */

86   public static final String JavaDoc ROLE_ATTR = "nsRole";
87
88
89
90   /**
91    * The system property used to specify the location of the JSSE key store.
92    */

93   public static final String JavaDoc SSL_KEY_STORE_PROPERTY =
94        "javax.net.ssl.keyStore";
95
96
97
98   /**
99    * The system property used to specify the password for the JSSE key store.
100    */

101   public static final String JavaDoc SSL_KEY_PASSWORD_PROPERTY =
102        "javax.net.ssl.keyStorePassword";
103
104
105
106   /**
107    * The system property used to specify the location of the JSSE trust store.
108    */

109   public static final String JavaDoc SSL_TRUST_STORE_PROPERTY =
110        "javax.net.ssl.trustStore";
111
112
113
114   /**
115    * The system property used to specify the password for the JSSE trust store.
116    */

117   public static final String JavaDoc SSL_TRUST_PASSWORD_PROPERTY =
118        "javax.net.ssl.trustStorePassword";
119
120
121
122   /**
123    * The name of the stat tracker that will be used to count the overall number
124    * of authentication attempts.
125    */

126   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_ATTEMPTS_OVERALL =
127        "Overall Authentication Attempts";
128
129
130
131   /**
132    * The name of the stat tracker that will be used to count the number of
133    * authentication attempts using login ID value 1.
134    */

135   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_ATTEMPTS_1 =
136        "Authentication 1 Attempts";
137
138
139
140   /**
141    * The name of the stat tracker that will be used to count the number of
142    * authentication attempts using login ID value 2.
143    */

144   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_ATTEMPTS_2 =
145        "Authentication 2 Attempts";
146
147
148
149   /**
150    * The categorized number of authentication attempts.
151    */

152   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_CATEGORIES =
153        "Authentication Categories";
154
155
156
157   /**
158    * The name of the stat tracker that will be used to keep track of the overall
159    * time required to perform each authentication.
160    */

161   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_TIME_OVERALL =
162        "Overall Authentication Time";
163
164
165
166   /**
167    * The name of the stat tracker that will be used to keep track of the time
168    * required to perform each authentication using login ID value 1.
169    */

170   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_TIME_1 =
171        "Authentication 1 Time";
172
173
174
175   /**
176    * The name of the stat tracker that will be used to keep track of the time
177    * required to perform each authentication using login ID value 2.
178    */

179   public static final String JavaDoc STAT_TRACKER_AUTHENTICATION_TIME_2 =
180        "Authentication 2 Time";
181
182
183
184   /**
185    * The name of the stat tracker that will be used to count the overall number
186    * of failed authentications.
187    */

188   public static final String JavaDoc STAT_TRACKER_FAILED_AUTHENTICATIONS_OVERALL =
189        "Overall Failed Authentications";
190
191
192
193   /**
194    * The name of the stat tracker that will be used to count the number of
195    * failed authentications using login ID value 1.
196    */

197   public static final String JavaDoc STAT_TRACKER_FAILED_AUTHENTICATIONS_1 =
198        "Failed Authentication 1 Attempts";
199
200
201
202   /**
203    * The name of the stat tracker that will be used to count the number of
204    * failed authentications using login ID value 2.
205    */

206   public static final String JavaDoc STAT_TRACKER_FAILED_AUTHENTICATIONS_2 =
207        "Failed Authentication 2 Attempts";
208
209
210
211   /**
212    * The name of the stat tracker that will be used to count the overall number
213    * of successful authentications.
214    */

215   public static final String JavaDoc STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_OVERALL =
216        "Overall Successful Authentications";
217
218
219
220   /**
221    * The name of the stat tracker that will be used to count the number of
222    * successful authentications using login ID value 1.
223    */

224   public static final String JavaDoc STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_1 =
225        "Successful Authentication 1 Attempts";
226
227
228
229   /**
230    * The name of the stat tracker that will be used to count the number of
231    * successful authentications using login ID value 2.
232    */

233   public static final String JavaDoc STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_2 =
234        "Successful Authentication 2 Attempts";
235
236
237
238   /**
239    * The set of attributes to retrieve if there aren't any attributes to
240    * retrieve.
241    */

242   public static final String JavaDoc[] NO_ATTRS = new String JavaDoc[] { "1.1" };
243
244
245
246   // Indicates whether to blindly trust any SSl certificate.
247
static boolean blindTrust;
248
249   // Indicates whether bind failures because of invalid credentials will be
250
// ignored (so you don't actually have to know user passwords).
251
static boolean ignoreInvalidCredentials;
252
253   // Indicates whether the first login ID value should be interpreted as a
254
// range.
255
static boolean useLoginIDRange1;
256
257   // Indicates whether the second login ID value should be interpreted as a
258
// range.
259
static boolean useLoginIDRange2;
260
261   // Indicates whether the first login ID value should be incremented
262
// sequentially.
263
static boolean useSequential1;
264
265   // Indicates whether the second login ID value should be incremented
266
// sequentially.
267
static boolean useSequential2;
268
269   // Indicate whether to use SSL when communicating with the directory server.
270
static boolean useSSL;
271
272   // Indicates whether all threads will used a shared set of connections or if
273
// each thread will have its own connection.
274
static boolean useSharedConnections;
275
276   // The time to keep working after stopping statistics collection.
277
static int coolDownTime;
278
279   // The port number of the directory server.
280
static int directoryPort;
281
282   // The maximum number of iterations per thread.
283
static int iterations;
284
285   // The maximum value to use in the first range of login IDs.
286
static int loginIDMax1;
287
288   // The maximum value to use in the second range of login IDs.
289
static int loginIDMax2;
290
291   // The minimum value to use in the first range of login IDs.
292
static int loginIDMin1;
293
294   // The minimum value to use in the second range of login IDs.
295
static int loginIDMin2;
296
297   // The maximum value to use in the first range of login IDs.
298
static int loginIDSpan1;
299
300   // The maximum value to use in the second range of login IDs.
301
static int loginIDSpan2;
302
303   // The weight associated with the first login ID value.
304
static int loginIDWeight;
305
306   // The type of membership to check when performing an authentication.
307
static int membershipType;
308
309   // The next value that should be used for sequentially incrementing the first
310
// set of login IDs.
311
static int sequentialCounter1;
312
313   // The next value that should be used for sequentially incrementing the second
314
// set of login IDs.
315
static int sequentialCounter2;
316
317   // The maximum length of time that any single LDAP operation will be allowed
318
// to take before it is cancelled.
319
static int timeLimit;
320
321   // The time to start working before beginning statistics collection.
322
static int warmUpTime;
323
324   // The delay in milliseconds between authentication attempts.
325
static long delay;
326
327   // The LDAP connection that will be used for shared authentication operations.
328
static LDAPConnection sharedAuthConnection;
329
330   // The LDAP connection that will be used for shared bind operations.
331
static LDAPConnection sharedBindConnection;
332
333   // The random number generator that will seed the thread-specific random
334
// number generators.
335
static Random parentRandom;
336
337   // The DN to use to bind to the directory when performing the search and
338
// modify operations.
339
static String JavaDoc bindDN;
340
341   // The password for the bind DN.
342
static String JavaDoc bindPW;
343
344   // The address of the directory server.
345
static String JavaDoc directoryHost;
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 DN of the entry for which to determine membership.
367
static String JavaDoc membershipDN;
368
369   // The search base to use if dynamic group membership is to be determined.
370
static String JavaDoc membershipURLBase;
371
372   // The search filter to use if dynamic group membership is to be determined.
373
static String JavaDoc membershipURLFilter;
374
375   // The name of the attribute from which to read the value for the user's
376
// password.
377
static String JavaDoc readPassFromAttr;
378
379   // The DN to use as the search base when trying to find user entries in the
380
// directory.
381
static String JavaDoc searchBase;
382
383   // The path of the JSSE key store to use for SSL.
384
static String JavaDoc sslKeyStore;
385
386   // The password used to access the JSSE key store.
387
static String JavaDoc sslKeyPassword;
388
389   // The path of the JSSE trust store to use for SSL.
390
static String JavaDoc sslTrustStore;
391
392   // The password used to access the JSSE trust store.
393
static String JavaDoc sslTrustPassword;
394
395
396
397   // The parameter that indicates whether the client should trust any SSL cert.
398
BooleanParameter blindTrustParameter =
399     new BooleanParameter("blind_trust", "Blindly Trust Any Certificate",
400                          "Indicates whether the client should blindly trust " +
401                          "any certificate presented by the server, or " +
402                          "whether the key and trust stores should be used.",
403                          true);
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 that indicates whether the connection should use SSL
423
BooleanParameter useSSLParameter =
424     new BooleanParameter("usessl", "Use SSL",
425                          "Indicates whether SSL should be used for all " +
426                          "communication with the directory server", false);
427
428   // The parmeter that specifies the cool-down time in seconds.
429
IntegerParameter coolDownParameter =
430        new IntegerParameter("cool_down", "Cool Down Time",
431                             "The time in seconds that the job should " +
432                             "continue searching after ending statistics " +
433                             "collection.", true, 0, true, 0, false, 0);
434
435   // The parameter that indicates the delay that should be used between each
436
// authentication attempt.
437
IntegerParameter delayParameter =
438        new IntegerParameter("delay", "Time Between Authentications (ms)",
439                             "Specifies the length of time in milliseconds " +
440                             "each thread should wait between authentication " +
441                             "attempts. Note that this delay will be " +
442                             "between the starts of consecutive attempts and " +
443                             "not between the end of one attempt and the " +
444                             "beginning of the next. If an authentication " +
445                             "takes longer than this length of time, then " +
446                             "there will be no delay.", true, 0, true, 0, false,
447                             0);
448
449   // The parameter that indicates the number of iterations to perform.
450
IntegerParameter iterationsParameter =
451        new IntegerParameter("num_iterations", "Number of Iterations",
452                             "The number of authentications that should be " +
453                             "performed by each thread", false, -1);
454
455   // The parameter used to indicate the port number for the directory server.
456
IntegerParameter portParameter =
457        new IntegerParameter("ldap_port", "Directory Server Port",
458                             "The port number for the directory server.", true,
459                             389, true, 1, true, 65535);
460
461   // The parameter used to indicate the maximum length of time that any single
462
// LDAP operation will be allowed to take.
463
IntegerParameter timeLimitParameter =
464        new IntegerParameter("time_limit", "Operation Time Limit",
465                             "The maximum length of time in seconds that any " +
466                             "single LDAP operation will be allowed to take " +
467                             "before it is cancelled.", true, 0, true, 0, false,
468                             0);
469
470   // The parmeter that specifies the cool-down time in seconds.
471
IntegerParameter warmUpParameter =
472        new IntegerParameter("warm_up", "Warm Up Time",
473                             "The time in seconds that the job should " +
474                             "search before beginning statistics collection.",
475                             true, 0, true, 0, false, 0);
476
477   // The parameter that specifies the percentage of the time that the first DN
478
// will be used in the modification.
479
IntegerParameter weightParameter =
480        new IntegerParameter("weight", "Login ID 1 Percentage",
481                             "The percentage of the time that a login ID " +
482                             "should be selected according to the value " +
483                             "provided for the Login ID Value 1 parameter.",
484                             true, 50, true, 0, true, 100);
485
486   // The parameter used to indicate the password for the bind DN.
487
PasswordParameter bindPWParameter =
488        new PasswordParameter("bindpw", "Directory Bind Password",
489                              "The password to use when binding to the " +
490                              "directory server to perform search and modify " +
491                              "operations.", false, "");
492
493   // The parameter used to indicate the password to use when authenticating to
494
// the directory.
495
PasswordParameter loginPasswordParameter =
496        new PasswordParameter("login_id_pw", "Login Password",
497                              "The password to use when authenticating to the " +
498                              "directory for user authentications.", false, "");
499
500   // The parameter that specifies the password for the SSL key store
501
PasswordParameter keyPWParameter =
502     new PasswordParameter("sslkeypw", "SSL Key Store Password",
503                           "The password for the JSSE key store", false, "");
504
505   // The parameter that specifies the password for the SSL key store
506
PasswordParameter trustPWParameter =
507     new PasswordParameter("ssltrustpw", "SSL Trust Store Password",
508                           "The password for the JSSE trust store", false, "");
509
510   // The placeholder parameter used as a spacer in the admin interface.
511
PlaceholderParameter placeholder = new PlaceholderParameter();
512
513   // The parameter used to indicate the bind DN.
514
StringParameter bindDNParameter =
515        new StringParameter("binddn", "Directory Bind DN",
516                            "The DN to use when binding to the directory " +
517                            "server to perform search and modify operations.",
518                            false, "");
519
520   // The parameter used to indicate the address of the directory server.
521
StringParameter hostParameter =
522        new StringParameter("ldap_host", "Directory Server Address",
523                            "The address for the directory server.", true, "");
524
525   // The parameter that specifies the location of the SSL key store
526
StringParameter keyStoreParameter =
527     new StringParameter("sslkeystore", "SSL Key Store",
528                         "The path to the JSSE key store to use for an " +
529                         "SSL-based connection", false, "");
530
531   // The parameter used to indicate the attribute to use for the login ID.
532
StringParameter loginIDParameter =
533        new StringParameter("login_id_attr", "Login ID Attribute",
534                            "The attribute to use as the login ID to find the " +
535                            "user's entry.", true, DEFAULT_LOG_ID_ATTR);
536
537   // The parameter used to indicate the login ID value or value pattern.
538
StringParameter loginIDValue1Parameter =
539        new StringParameter("login_id_value_1", "Login ID Value 1",
540                            "The text to use as the value of the first login " +
541                            "ID attribute in search filters. The value may " +
542                            "contain a range of numbers in square brackets.",
543                            true, "");
544
545   // The parameter used to indicate the login ID value or value pattern.
546
StringParameter loginIDValue2Parameter =
547        new StringParameter("login_id_value_2", "Login ID Value 2",
548                            "The text to use as the value of the second login " +
549                            "ID attribute in search filters. The value may " +
550                            "contain a range of numbers in square brackets.",
551                            true, "");
552
553   // The parameter used to specify the DN of the entry in which to check whether
554
// the user is a member.
555
StringParameter membershipDNParameter =
556        new StringParameter("membership_dn", "Membership DN",
557                            "The DN of a static group, dynamic group, or role " +
558                            "for which to determine whether the user is a " +
559                            "member.", false, "");
560
561   // The parameter that allows the user to specify an attribute containing the
562
// clear-text value of the user's password.
563
StringParameter readPassFromAttrParameter =
564        new StringParameter("read_pass_from_attr",
565                            "Read Password from Attribute",
566                            "The name of the LDAP attribute from which the " +
567                            "user's password should be read, rather than " +
568                            "using the same static password for every user.",
569                            false, null);
570
571   // The parameter used to indicate the search base for the directory.
572
StringParameter searchBaseParameter =
573     new StringParameter("search_base", "User Search Base",
574                         "The DN in the directory server under which user " +
575                         "entries may be found.", true, "");
576
577   // The parameter that specifies the location of the SSL trust store
578
StringParameter trustStoreParameter =
579     new StringParameter("ssltruststore", "SSL Trust Store",
580                         "The path to the JSSE trust store to use for an " +
581                         "SSL-based connection", false, "");
582
583   // The stat tracker that will be used to categorize the kinds of
584
// authentications performed by the server.
585
CategoricalTracker authenticationTypes;
586
587   // The stat tracker that will count the number of overall authentication
588
// attempts.
589
IncrementalTracker attemptOverallCounter;
590
591   // The stat tracker that will count the number of authentication 1 attempts.
592
IncrementalTracker attempt1Counter;
593
594   // The stat tracker that will count the number of authentication 2 attempts.
595
IncrementalTracker attempt2Counter;
596
597   // The stat tracker that will count the overall number of failed
598
// authentications.
599
IncrementalTracker failureOverallCounter;
600
601   // The stat tracker that will count the number of failed authentication 1
602
// attempts.
603
IncrementalTracker failure1Counter;
604
605   // The stat tracker that will count the number of failed authentication 2
606
// attempts.
607
IncrementalTracker failure2Counter;
608
609   // The stat tracker that will count the overall number of successful
610
// authentications.
611
IncrementalTracker successOverallCounter;
612
613   // Thet stat tracker that will count the number of successful authentication 1
614
// attempts.
615
IncrementalTracker success1Counter;
616
617   // Thet stat tracker that will count the number of successful authentication 2
618
// attempts.
619
IncrementalTracker success2Counter;
620
621   // The LDAP connection that will be used for authentication operations by this
622
// thread.
623
LDAPConnection authConnection;
624
625   // The LDAP connection that will be used for bind operations by this thread.
626
LDAPConnection bindConnection;
627
628   // The set of constraints that will be used for non-search/bind operations.
629
LDAPConstraints authConstraints;
630
631   // The set of constraints that will be used for bind operations.
632
LDAPConstraints bindConstraints;
633
634   // The set of constraints that will be used for search operations.
635
LDAPSearchConstraints authSearchConstraints;
636
637   // The random number generator for this thread.
638
Random random;
639
640   // The stat tracker that will time each authentication.
641
TimeTracker authOverallTimer;
642
643   // The stat tracker that will time each authentication using login ID 1.
644
TimeTracker auth1Timer;
645
646   // The stat tracker that will time each authentication using login ID 2.
647
TimeTracker auth2Timer;
648
649
650
651   /**
652    * Creates a new instance of this job thread. This constructor does not need
653    * to do anything other than invoke the constructor for the superclass.
654    */

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

668   public String JavaDoc getJobName()
669   {
670     return "LDAP Weighted Auth Rate";
671   }
672
673
674
675   /**
676    * Returns a description of this job that can be seen in the administrative
677    * interface.
678    *
679    * @return A description of this job class.
680    */

681   public String JavaDoc getJobDescription()
682   {
683     return "This job performs repeated authentications against an LDAP " +
684            "directory server, optionally including a lookup to verify that " +
685            "the user is a member of an indicated group or role. The login " +
686            "ID values used in the lookups can be chosen from two weighted " +
687            "cataegories.";
688   }
689
690
691
692   /**
693    * Retrieves the name of the category in which this job class exists. This is
694    * used to help arrange the job classes in the administrative interface.
695    *
696    * @return The name of the category in which this job class exists.
697    */

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

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

773   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
774                                            int collectionInterval)
775   {
776     return new StatTracker[]
777     {
778       new IncrementalTracker(clientID, threadID,
779                              STAT_TRACKER_AUTHENTICATION_ATTEMPTS_OVERALL,
780                              collectionInterval),
781       new IncrementalTracker(clientID, threadID,
782                              STAT_TRACKER_AUTHENTICATION_ATTEMPTS_1,
783                              collectionInterval),
784       new IncrementalTracker(clientID, threadID,
785                              STAT_TRACKER_AUTHENTICATION_ATTEMPTS_2,
786                              collectionInterval),
787       new IncrementalTracker(clientID, threadID,
788                              STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_OVERALL,
789                              collectionInterval),
790       new IncrementalTracker(clientID, threadID,
791                              STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_1,
792                              collectionInterval),
793       new IncrementalTracker(clientID, threadID,
794                              STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_2,
795                              collectionInterval),
796       new IncrementalTracker(clientID, threadID,
797                              STAT_TRACKER_FAILED_AUTHENTICATIONS_OVERALL,
798                              collectionInterval),
799       new IncrementalTracker(clientID, threadID,
800                              STAT_TRACKER_FAILED_AUTHENTICATIONS_1,
801                              collectionInterval),
802       new IncrementalTracker(clientID, threadID,
803                              STAT_TRACKER_FAILED_AUTHENTICATIONS_2,
804                              collectionInterval),
805       new TimeTracker(clientID, threadID,
806                       STAT_TRACKER_AUTHENTICATION_TIME_OVERALL,
807                       collectionInterval),
808       new TimeTracker(clientID, threadID, STAT_TRACKER_AUTHENTICATION_TIME_1,
809                       collectionInterval),
810       new TimeTracker(clientID, threadID, STAT_TRACKER_AUTHENTICATION_TIME_2,
811                       collectionInterval),
812       new CategoricalTracker(clientID, threadID,
813                              STAT_TRACKER_AUTHENTICATION_CATEGORIES,
814                              collectionInterval)
815     };
816   }
817
818
819
820   /**
821    * Retrieves the set of stat trackers that are maintained by this job class.
822    *
823    * @return The set of stat trackers for this job class.
824    */

825   public StatTracker[] getStatTrackers()
826   {
827     return new StatTracker[]
828     {
829       attemptOverallCounter,
830       attempt1Counter,
831       attempt2Counter,
832       successOverallCounter,
833       success1Counter,
834       success2Counter,
835       failureOverallCounter,
836       failure1Counter,
837       failure2Counter,
838       authOverallTimer,
839       auth1Timer,
840       auth2Timer,
841       authenticationTypes
842     };
843   }
844
845
846
847   /**
848    * Provides a means of validating the information used to schedule the job,
849    * including the scheduling information and list of parameters.
850    *
851    * @param numClients The number of clients that should be used to
852    * run the job.
853    * @param threadsPerClient The number of threads that should be created on
854    * each client to run the job.
855    * @param threadStartupDelay The delay in milliseconds that should be used
856    * when starting the client threads.
857    * @param startTime The time that the job should start running.
858    * @param stopTime The time that the job should stop running.
859    * @param duration The maximum length of time in seconds that the
860    * job should be allowed to run.
861    * @param collectionInterval The collection interval that should be used
862    * when gathering statistics for the job.
863    * @param parameters The set of parameters provided to this job that
864    * can be used to customize its behavior.
865    *
866    * @throws InvalidValueException If the provided information is not
867    * appropriate for running this job.
868    */

869   public void validateJobInfo(int numClients, int threadsPerClient,
870                               int threadStartupDelay, Date startTime,
871                               Date stopTime, int duration,
872                               int collectionInterval, ParameterList parameters)
873          throws InvalidValueException
874   {
875     // Make sure that either a password was specified, or that the user provided
876
// the name of an attribute from which to retrieve the password.
877
PasswordParameter loginPWParameter =
878          parameters.getPasswordParameter(loginPasswordParameter.getName());
879     StringParameter pwAttrParameter =
880          parameters.getStringParameter(readPassFromAttrParameter.getName());
881
882     if (((loginPWParameter == null) || (! loginPWParameter.hasValue())) &&
883         ((pwAttrParameter == null) || (! pwAttrParameter.hasValue())))
884     {
885       throw new InvalidValueException("If no login data file is provided, " +
886                                       "then you must provide a password " +
887                                       "or the name of an attribute from " +
888                                       "which to read the password.");
889     }
890   }
891
892
893
894   /**
895    * Indicates whether this job class implements logic that makes it possible to
896    * test the validity of job parameters before scheduling the job for execution
897    * (e.g., to see if the server is reachable using the information provided).
898    *
899    * @return <CODE>true</CODE> if this job provides a means of testing the job
900    * parameters, or <CODE>false</CODE> if not.
901    */

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

936   public boolean testJobParameters(ParameterList parameters,
937                                    ArrayList outputMessages)
938   {
939     // Get all the parameters that we might need to perform the test.
940
StringParameter hostParam =
941          parameters.getStringParameter(hostParameter.getName());
942     if ((hostParam == null) || (! hostParam.hasValue()))
943     {
944       outputMessages.add("ERROR: No directory server address was provided.");
945       return false;
946     }
947     String JavaDoc host = hostParam.getStringValue();
948
949
950     IntegerParameter portParam =
951          parameters.getIntegerParameter(portParameter.getName());
952     if ((portParam == null) || (! hostParam.hasValue()))
953     {
954       outputMessages.add("ERROR: No directory server port was provided.");
955       return false;
956     }
957     int port = portParam.getIntValue();
958
959
960     boolean useSSL = false;
961     BooleanParameter useSSLParam =
962          parameters.getBooleanParameter(useSSLParameter.getName());
963     if (useSSLParam != null)
964     {
965       useSSL = useSSLParam.getBooleanValue();
966     }
967
968
969     boolean blindTrust = true;
970     BooleanParameter blindTrustParam =
971          parameters.getBooleanParameter(blindTrustParameter.getName());
972     if (blindTrustParam != null)
973     {
974       blindTrust = blindTrustParam.getBooleanValue();
975     }
976
977
978     String JavaDoc keyStore = null;
979     StringParameter keyStoreParam =
980          parameters.getStringParameter(keyStoreParameter.getName());
981     if ((keyStoreParam != null) && keyStoreParam.hasValue())
982     {
983       keyStore = keyStoreParam.getStringValue();
984       File keyStoreFile = new File(keyStore);
985       if (useSSL && (! blindTrust) && (! keyStoreFile.exists()))
986       {
987         outputMessages.add("WARNING: Key store file \"" + keyStore +
988                            "\" not found on SLAMD server system. This test " +
989                            "will blindly trust any SSL certificate " +
990                            "presented by the directory server.");
991         outputMessages.add("");
992         blindTrust = true;
993       }
994       else
995       {
996         System.setProperty(SSL_KEY_STORE_PROPERTY, keyStore);
997       }
998     }
999
1000
1001    String JavaDoc keyStorePassword = "";
1002    StringParameter keyPassParam =
1003         parameters.getStringParameter(keyPWParameter.getName());
1004    if ((keyPassParam != null) && keyPassParam.hasValue())
1005    {
1006      keyStorePassword = keyPassParam.getStringValue();
1007      System.setProperty(SSL_KEY_PASSWORD_PROPERTY, keyStorePassword);
1008    }
1009
1010
1011    String JavaDoc trustStore = null;
1012    StringParameter trustStoreParam =
1013         parameters.getStringParameter(trustStoreParameter.getName());
1014    if ((trustStoreParam != null) && trustStoreParam.hasValue())
1015    {
1016      trustStore = trustStoreParam.getStringValue();
1017      File trustStoreFile = new File(trustStore);
1018      if (useSSL && (! blindTrust) && (! trustStoreFile.exists()))
1019      {
1020        outputMessages.add("WARNING: trust store file \"" + trustStore +
1021                           "\" not found on SLAMD server system. This test " +
1022                           "will blindly trust any SSL certificate " +
1023                           "presented by the directory server.");
1024        outputMessages.add("");
1025        blindTrust = true;
1026      }
1027      else
1028      {
1029        System.setProperty(SSL_TRUST_STORE_PROPERTY, trustStore);
1030      }
1031    }
1032
1033
1034    String JavaDoc trustStorePassword = "";
1035    StringParameter trustPassParam =
1036         parameters.getStringParameter(trustPWParameter.getName());
1037    if ((trustPassParam != null) && trustPassParam.hasValue())
1038    {
1039      trustStorePassword = trustPassParam.getStringValue();
1040      System.setProperty(SSL_TRUST_PASSWORD_PROPERTY, trustStorePassword);
1041    }
1042
1043
1044    String JavaDoc bindDN = "";
1045    StringParameter bindDNParam =
1046         parameters.getStringParameter(bindDNParameter.getName());
1047    if ((bindDNParam != null) && bindDNParam.hasValue())
1048    {
1049      bindDN = bindDNParam.getStringValue();
1050    }
1051
1052
1053    String JavaDoc bindPassword = "";
1054    PasswordParameter bindPWParam =
1055         parameters.getPasswordParameter(bindPWParameter.getName());
1056    if ((bindPWParam != null) && bindPWParam.hasValue())
1057    {
1058      bindPassword = bindPWParam.getStringValue();
1059    }
1060
1061
1062    StringParameter baseDNParam =
1063         parameters.getStringParameter(searchBaseParameter.getName());
1064    if ((baseDNParam == null) || (! baseDNParam.hasValue()))
1065    {
1066      outputMessages.add("ERROR: No base DN was provided.");
1067      return false;
1068    }
1069    String JavaDoc baseDN = baseDNParam.getStringValue();
1070
1071
1072    // Create the LDAPConnection object that we will use to communicate with the
1073
// directory server.
1074
LDAPConnection conn;
1075    if (useSSL)
1076    {
1077      if (blindTrust)
1078      {
1079        try
1080        {
1081          conn = new LDAPConnection(new JSSEBlindTrustSocketFactory());
1082        }
1083        catch (Exception JavaDoc e)
1084        {
1085          outputMessages.add("ERROR: Unable to instantiate the blind trust " +
1086                             "socket factory for use in creating the SSL " +
1087                             "connection: " + stackTraceToString(e));
1088          return false;
1089        }
1090      }
1091      else
1092      {
1093        conn = new LDAPConnection(new JSSESocketFactory(null));
1094      }
1095    }
1096    else
1097    {
1098      conn = new LDAPConnection();
1099    }
1100
1101
1102    // Attempt to establish a connection to the directory server.
1103
try
1104    {
1105      if (useSSL)
1106      {
1107        outputMessages.add("Attempting to establish an SSL-based connection " +
1108                           "to " + host + ":" + port + "....");
1109      }
1110      else
1111      {
1112        outputMessages.add("Attempting to establish a connection to " + host +
1113                           ":" + port + "....");
1114      }
1115      conn.connect(host, port);
1116      outputMessages.add("Connected successfully.");
1117      outputMessages.add("");
1118    }
1119    catch (Exception JavaDoc e)
1120    {
1121      outputMessages.add("ERROR: Unable to connect to the directory " +
1122                         "server: " + stackTraceToString(e));
1123      return false;
1124    }
1125
1126
1127    // Attempt to bind to the directory server using the bind DN and password.
1128
try
1129    {
1130      outputMessages.add("Attempting to perform an LDAPv3 bind to the " +
1131                         "directory server with a DN of '" + bindDN + "'....");
1132      conn.bind(3, bindDN, bindPassword);
1133      outputMessages.add("Bound successfully.");
1134      outputMessages.add("");
1135    }
1136    catch (Exception JavaDoc e)
1137    {
1138      try
1139      {
1140        conn.disconnect();
1141      } catch (Exception JavaDoc e2) {}
1142
1143      outputMessages.add("ERROR: Unable to bind to the directory server: " +
1144                         stackTraceToString(e));
1145      return false;
1146    }
1147
1148
1149    // Make sure that the entry specified as the base DN exists.
1150
try
1151    {
1152      outputMessages.add("Checking to make sure that the base DN entry '" +
1153                         baseDN + "' exists in the directory....");
1154      LDAPEntry baseDNEntry = conn.read(baseDN, new String JavaDoc[] { "1.1" });
1155      if (baseDNEntry == null)
1156      {
1157        try
1158        {
1159          conn.disconnect();
1160        } catch (Exception JavaDoc e2) {}
1161
1162        outputMessages.add("ERROR: Unable to retrieve the base DN entry.");
1163        return false;
1164      }
1165      else
1166      {
1167        outputMessages.add("Successfully read the base DN entry.");
1168        outputMessages.add("");
1169      }
1170    }
1171    catch (Exception JavaDoc e)
1172    {
1173      try
1174      {
1175        conn.disconnect();
1176      } catch (Exception JavaDoc e2) {}
1177
1178      outputMessages.add("ERROR: Unable to retrieve the base DN entry: " +
1179                         stackTraceToString(e));
1180      return false;
1181    }
1182
1183
1184    // At this point, all tests have passed. Close the connection and return
1185
// true.
1186
try
1187    {
1188      conn.disconnect();
1189    } catch (Exception JavaDoc e) {}
1190
1191    outputMessages.add("All tests completed successfully.");
1192    return true;
1193  }
1194
1195
1196
1197  /**
1198   * Performs initialization for this job on each client immediately before each
1199   * thread is created to actually run the job.
1200   *
1201   * @param clientID The ID assigned to the client running this job.
1202   * @param parameters The set of parameters provided to this job that can be
1203   * used to customize its behavior.
1204   *
1205   * @throws UnableToRunException If the client initialization could not be
1206   * completed successfully and the job is unable
1207   * to run.
1208   */

1209  public void initializeClient(String JavaDoc clientID, ParameterList parameters)
1210         throws UnableToRunException
1211  {
1212    // Get the directory server address
1213
hostParameter = parameters.getStringParameter(hostParameter.getName());
1214    if (hostParameter == null)
1215    {
1216      throw new UnableToRunException("No directory server host provided.");
1217    }
1218    else
1219    {
1220      directoryHost = hostParameter.getStringValue();
1221    }
1222
1223
1224    // Get the directory server port
1225
portParameter = parameters.getIntegerParameter(portParameter.getName());
1226    if (portParameter != null)
1227    {
1228      directoryPort = portParameter.getIntValue();
1229    }
1230
1231    // Get the DN to use to bind to the directory server.
1232
bindDNParameter = parameters.getStringParameter(bindDNParameter.getName());
1233    if (bindDNParameter == null)
1234    {
1235      bindDN = "";
1236    }
1237    else
1238    {
1239      bindDN = bindDNParameter.getStringValue();
1240    }
1241
1242    // Get the password to use to bind to the directory server.
1243
bindPWParameter =
1244         parameters.getPasswordParameter(bindPWParameter.getName());
1245    if (bindPWParameter == null)
1246    {
1247      bindPW = "";
1248    }
1249    else
1250    {
1251      bindPW = bindPWParameter.getStringValue();
1252    }
1253
1254    // Get the search base
1255
searchBaseParameter =
1256         parameters.getStringParameter(searchBaseParameter.getName());
1257    if (searchBaseParameter != null)
1258    {
1259      searchBase = searchBaseParameter.getStringValue();
1260    }
1261
1262
1263    // Get the password to use.
1264
loginPasswordParameter =
1265         parameters.getPasswordParameter(loginPasswordParameter.getName());
1266    if ((loginPasswordParameter != null) &&
1267          (loginPasswordParameter.hasValue()))
1268    {
1269      loginPassword = loginPasswordParameter.getStringValue();
1270    }
1271
1272
1273    // Get the attribute from which to read the password.
1274
readPassFromAttr = null;
1275    readPassFromAttrParameter =
1276         parameters.getStringParameter(readPassFromAttrParameter.getName());
1277    if (readPassFromAttrParameter != null)
1278    {
1279      readPassFromAttr = readPassFromAttrParameter.getStringValue();
1280    }
1281
1282
1283    // Get the first set of login IDs.
1284
loginIDValue1Parameter =
1285         parameters.getStringParameter(loginIDValue1Parameter.getName());
1286    useLoginIDRange1 = true;
1287    useSequential1 = false;
1288    String JavaDoc loginIDValue1 = loginIDValue1Parameter.getStringValue();
1289    try
1290    {
1291      int openPos = loginIDValue1.indexOf('[');
1292      int closePos = loginIDValue1.indexOf(']', openPos);
1293      loginIDInitial1 = loginIDValue1.substring(0, openPos);
1294      loginIDFinal1 = loginIDValue1.substring(closePos+1);
1295
1296      int dashPos = loginIDValue1.indexOf('-', openPos);
1297      if (dashPos < 0)
1298      {
1299        dashPos = loginIDValue1.indexOf(':', openPos);
1300        useSequential1 = true;
1301      }
1302      loginIDMin1 = Integer.parseInt(loginIDValue1.substring(openPos+1,
1303                                                              dashPos));
1304      loginIDMax1 = Integer.parseInt(loginIDValue1.substring(dashPos+1,
1305                                                              closePos));
1306      loginIDSpan1 = loginIDMax1 - loginIDMin1 + 1;
1307      sequentialCounter1 = loginIDMin1;
1308    }
1309    catch (Exception JavaDoc e)
1310    {
1311      useLoginIDRange1 = false;
1312      loginIDInitial1 = loginIDValue1;
1313    }
1314
1315
1316    // Get the second set of login IDs.
1317
loginIDValue2Parameter =
1318         parameters.getStringParameter(loginIDValue2Parameter.getName());
1319    useLoginIDRange2 = true;
1320    useSequential2 = false;
1321    String JavaDoc loginIDValue2 = loginIDValue2Parameter.getStringValue();
1322    try
1323    {
1324      int openPos = loginIDValue2.indexOf('[');
1325      int closePos = loginIDValue2.indexOf(']', openPos);
1326      loginIDInitial2 = loginIDValue2.substring(0, openPos);
1327      loginIDFinal2 = loginIDValue2.substring(closePos+1);
1328
1329      int dashPos = loginIDValue2.indexOf('-', openPos);
1330      if (dashPos < 0)
1331      {
1332        dashPos = loginIDValue2.indexOf(':', openPos);
1333        useSequential2 = true;
1334      }
1335      loginIDMin2 = Integer.parseInt(loginIDValue2.substring(openPos+1,
1336                                                              dashPos));
1337      loginIDMax2 = Integer.parseInt(loginIDValue2.substring(dashPos+1,
1338                                                              closePos));
1339      loginIDSpan2 = loginIDMax2 - loginIDMin2 + 1;
1340      sequentialCounter2 = loginIDMin1;
1341    }
1342    catch (Exception JavaDoc e)
1343    {
1344      useLoginIDRange2 = false;
1345      loginIDInitial2 = loginIDValue2;
1346    }
1347
1348
1349    // Get the login ID weight;
1350
weightParameter = parameters.getIntegerParameter(weightParameter.getName());
1351    if (weightParameter != null)
1352    {
1353      loginIDWeight = weightParameter.getIntValue();
1354    }
1355
1356
1357    // Get the login ID attribute.
1358
loginIDParameter =
1359         parameters.getStringParameter(loginIDParameter.getName());
1360    if (loginIDParameter != null)
1361    {
1362      loginIDAttr = loginIDParameter.getStringValue();
1363    }
1364
1365    // Get the membership entry DN.
1366
membershipDNParameter =
1367         parameters.getStringParameter(membershipDNParameter.getName());
1368    if ((membershipDNParameter != null) && (membershipDNParameter.hasValue()))
1369    {
1370      membershipDN = membershipDNParameter.getStringValue();
1371    }
1372    else
1373    {
1374      membershipDN = null;
1375    }
1376
1377    // Get the warm up time.
1378
warmUpTime = 0;
1379    warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName());
1380    if (warmUpParameter != null)
1381    {
1382      warmUpTime = warmUpParameter.getIntValue();
1383    }
1384
1385    // Get the cool down time.
1386
coolDownTime = 0;
1387    coolDownParameter =
1388         parameters.getIntegerParameter(coolDownParameter.getName());
1389    if (coolDownParameter != null)
1390    {
1391      coolDownTime = coolDownParameter.getIntValue();
1392    }
1393
1394    // Get the max operation time limit.
1395
timeLimitParameter =
1396         parameters.getIntegerParameter(timeLimitParameter.getName());
1397    if (timeLimitParameter != null)
1398    {
1399      timeLimit = timeLimitParameter.getIntValue();
1400    }
1401
1402    // Get the delay between authentication attempts.
1403
delay = 0;
1404    delayParameter = parameters.getIntegerParameter(delayParameter.getName());
1405    if (delayParameter != null)
1406    {
1407      delay = delayParameter.getIntValue();
1408    }
1409
1410    // Get the flag indicating whether we should use SSL or not
1411
useSSL = false;
1412    useSSLParameter = parameters.getBooleanParameter(useSSLParameter.getName());
1413    if (useSSLParameter != null)
1414    {
1415      useSSL = useSSLParameter.getBooleanValue();
1416    }
1417
1418    // If we are to use SSL, then get all the other SSL-related info
1419
if (useSSL)
1420    {
1421      // Whether to blindly trust any SSL certificate.
1422
blindTrustParameter =
1423           parameters.getBooleanParameter(blindTrustParameter.getName());
1424      if (blindTrustParameter != null)
1425      {
1426        blindTrust = blindTrustParameter.getBooleanValue();
1427      }
1428
1429      // The location of the JSSE key store
1430
sslKeyStore = null;
1431      keyStoreParameter =
1432           parameters.getStringParameter(keyStoreParameter.getName());
1433      if ((keyStoreParameter != null) && (keyStoreParameter.hasValue()))
1434      {
1435        sslKeyStore = keyStoreParameter.getStringValue();
1436        System.setProperty(SSL_KEY_STORE_PROPERTY, sslKeyStore);
1437      }
1438
1439      // The JSSE key store password
1440
sslKeyPassword = null;
1441      keyPWParameter =
1442           parameters.getPasswordParameter(keyPWParameter.getName());
1443      if ((keyPWParameter != null) && (keyPWParameter.hasValue()))
1444      {
1445        sslKeyPassword = keyPWParameter.getStringValue();
1446        System.setProperty(SSL_KEY_PASSWORD_PROPERTY, sslKeyPassword);
1447      }
1448
1449      // The location of the JSSE trust store
1450
sslTrustStore = null;
1451      trustStoreParameter =
1452           parameters.getStringParameter(trustStoreParameter.getName());
1453      if ((trustStoreParameter != null) && (trustStoreParameter.hasValue()))
1454      {
1455        sslTrustStore = trustStoreParameter.getStringValue();
1456        System.setProperty(SSL_TRUST_STORE_PROPERTY, sslTrustStore);
1457      }
1458
1459      // The JSSE trust store password
1460
sslTrustPassword = null;
1461      trustPWParameter =
1462           parameters.getPasswordParameter(trustPWParameter.getName());
1463      if ((trustPWParameter != null) && (trustPWParameter.hasValue()))
1464      {
1465        sslTrustPassword = trustPWParameter.getStringValue();
1466        System.setProperty(SSL_TRUST_PASSWORD_PROPERTY, sslTrustPassword);
1467      }
1468    }
1469
1470
1471    // Get the number of iterations to perform.
1472
iterations = -1;
1473    iterationsParameter =
1474         parameters.getIntegerParameter(iterationsParameter.getName());
1475    if ((iterationsParameter != null) && (iterationsParameter.hasValue()))
1476    {
1477      iterations = iterationsParameter.getIntValue();
1478    }
1479
1480
1481    // Get the indicator that specifies whether to ignore invalid credentials
1482
// errors.
1483
ignoreInvCredParameter =
1484         parameters.getBooleanParameter(ignoreInvCredParameter.getName());
1485    if (ignoreInvCredParameter != null)
1486    {
1487      ignoreInvalidCredentials = ignoreInvCredParameter.getBooleanValue();
1488    }
1489
1490    // Get the indicator that specifies whether to use shared connections.
1491
shareConnsParameter =
1492         parameters.getBooleanParameter(shareConnsParameter.getName());
1493    if (shareConnsParameter != null)
1494    {
1495      useSharedConnections = shareConnsParameter.getBooleanValue();
1496    }
1497
1498
1499    // If we are to use shared connections, then establish them now.
1500
if (useSharedConnections)
1501    {
1502      if (useSSL)
1503      {
1504        if (blindTrust)
1505        {
1506          try
1507          {
1508            sharedAuthConnection =
1509                 new LDAPConnection(new JSSEBlindTrustSocketFactory());
1510            sharedBindConnection =
1511                 new LDAPConnection(new JSSEBlindTrustSocketFactory());
1512          }
1513          catch (LDAPException le)
1514          {
1515            throw new UnableToRunException(le.getMessage(), le);
1516          }
1517        }
1518        else
1519        {
1520          sharedAuthConnection =
1521               new LDAPConnection(new JSSESocketFactory(null));
1522          sharedBindConnection =
1523               new LDAPConnection(new JSSESocketFactory(null));
1524        }
1525      }
1526      else
1527      {
1528        sharedAuthConnection = new LDAPConnection();
1529        sharedBindConnection = new LDAPConnection();
1530      }
1531
1532      try
1533      {
1534        sharedAuthConnection.connect(3, directoryHost, directoryPort, bindDN,
1535                                     bindPW);
1536        sharedBindConnection.connect(3, directoryHost, directoryPort, "", "");
1537      }
1538      catch (Exception JavaDoc e)
1539      {
1540        throw new UnableToRunException("Could not establish shared " +
1541                                       "connections to the directory: " + e,
1542                                       e);
1543      }
1544    }
1545
1546
1547    // If we are to perform membership determination, then figure out what
1548
// needs to be done.
1549
membershipType = MEMBERSHIP_TYPE_NONE;
1550    if (membershipDN != null)
1551    {
1552      // First, get a connection to the directory.
1553
LDAPConnection conn = null;
1554      if (useSharedConnections)
1555      {
1556        conn = sharedAuthConnection;
1557      }
1558      else
1559      {
1560        try
1561        {
1562          if (useSSL)
1563          {
1564            if (blindTrust)
1565            {
1566              conn = new LDAPConnection(new JSSEBlindTrustSocketFactory());
1567            }
1568            else
1569            {
1570              conn = new LDAPConnection(new JSSESocketFactory(null));
1571            }
1572          }
1573          else
1574          {
1575            conn = new LDAPConnection();
1576          }
1577          conn.connect(3, directoryHost, directoryPort, bindDN, bindPW);
1578        }
1579        catch (Exception JavaDoc e)
1580        {
1581          throw new UnableToRunException("Could not connect to directory " +
1582                                         "server " + directoryHost + ":" +
1583                                         directoryPort +
1584                                         " to retrieve membership entry.", e);
1585        }
1586      }
1587
1588      // Retrieve the membership DN entry.
1589
String JavaDoc[] attrsToReturn = new String JavaDoc[] { "objectClass", "memberURL" };
1590      LDAPEntry entry = null;
1591      try
1592      {
1593        entry = conn.read(membershipDN, attrsToReturn);
1594      }
1595      catch (Exception JavaDoc e) {}
1596
1597      if (entry == null)
1598      {
1599        try
1600        {
1601          conn.disconnect();
1602        } catch (Exception JavaDoc e) {}
1603        throw new UnableToRunException("Could not retrieve the membership " +
1604                                       "entry '" + membershipDN + "' from " +
1605                                       "directory " + directoryHost + ":" +
1606                                       directoryPort + ".");
1607      }
1608
1609      // Look at the entry's objectclasses to determine the kind of entry it is.
1610
LDAPAttribute ocAttr = entry.getAttribute("objectClass");
1611      String JavaDoc[] ocValues = null;
1612      if ((ocAttr == null) ||
1613          ((ocValues = ocAttr.getStringValueArray()) == null) ||
1614          (ocValues.length == 0))
1615      {
1616        try
1617        {
1618          conn.disconnect();
1619        } catch (Exception JavaDoc e) {}
1620        throw new UnableToRunException("Could not retrieve objectclass " +
1621                                       "values from '" + membershipDN + "'");
1622      }
1623
1624      for (int i=0; i < ocValues.length; i++)
1625      {
1626        if (ocValues[i].equalsIgnoreCase("groupOfNames") ||
1627            ocValues[i].equalsIgnoreCase("groupOfUniqueNames"))
1628        {
1629          membershipType = MEMBERSHIP_TYPE_STATIC;
1630          break;
1631        }
1632        else if (ocValues[i].equalsIgnoreCase("groupOfURLs"))
1633        {
1634          LDAPAttribute urlAttr = entry.getAttribute("memberURL");
1635          String JavaDoc[] urlValues = null;
1636          if ((urlAttr == null) ||
1637              ((urlValues = urlAttr.getStringValueArray()) == null) ||
1638               (urlValues.length == 0))
1639          {
1640            try
1641            {
1642              conn.disconnect();
1643            } catch (Exception JavaDoc e) {}
1644
1645            throw new UnableToRunException("Could not retrieve memberURL " +
1646                                           "from dynamic group entry " +
1647                                           membershipDN);
1648          }
1649
1650          try
1651          {
1652            LDAPUrl url = new LDAPUrl(urlValues[0]);
1653            membershipURLBase = LDAPDN.normalize(url.getDN());
1654            membershipURLFilter = url.getFilter();
1655          }
1656          catch (Exception JavaDoc e)
1657          {
1658            try
1659            {
1660              conn.disconnect();
1661            } catch (Exception JavaDoc e2) {}
1662
1663            throw new UnableToRunException("Could not interpret " +
1664                                           urlValues[0] + " as an LDAP URL", e);
1665          }
1666
1667          membershipType = MEMBERSHIP_TYPE_DYNAMIC;
1668          break;
1669        }
1670        else if (ocValues[i].toLowerCase().indexOf("role") >= 0)
1671        {
1672          membershipType = MEMBERSHIP_TYPE_ROLE;
1673          membershipDN = LDAPDN.normalize(membershipDN);
1674          break;
1675        }
1676      }
1677
1678      if (membershipType == MEMBERSHIP_TYPE_NONE)
1679      {
1680        throw new UnableToRunException("Could not determine the membership " +
1681                                       "type to check for entry " +
1682                                       membershipDN);
1683      }
1684
1685      if (! useSharedConnections)
1686      {
1687        try
1688        {
1689          conn.disconnect();
1690        } catch (Exception JavaDoc e) {}
1691      }
1692    }
1693
1694    // Seed the parent random number generator.
1695
parentRandom = new Random();
1696  }
1697
1698
1699
1700  /**
1701   * Initializes this job class with the information that it will use when
1702   * actually running the job. This will also initialize the stat trackers used
1703   * by the job.
1704   *
1705   * @param clientID The thread ID for this thread.
1706   * @param threadID The thread ID for this thread.
1707   * @param collectionInterval The collection interval to use for gathering
1708   * statistics while processing the job.
1709   * @param parameters The st of parameters that contain the
1710   * information used to customize the way this job
1711   * is processed.
1712   *
1713   * @throws UnableToRunException If a problem occurs that prevents the thread
1714   * from being able to run properly.
1715   */

1716  public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
1717                               int collectionInterval, ParameterList parameters)
1718         throws UnableToRunException
1719  {
1720    // Seed the random number generator for this thread.
1721
random = new Random(parentRandom.nextLong());
1722
1723    // If we are not going to use shared connections, then create the
1724
// connections for use by this thread. Otherwise, just grab the shared
1725
// connections.
1726
if (useSharedConnections)
1727    {
1728      authConnection = sharedAuthConnection;
1729      bindConnection = sharedBindConnection;
1730    }
1731    else
1732    {
1733      if (useSSL)
1734      {
1735        if (blindTrust)
1736        {
1737          try
1738          {
1739            authConnection =
1740                 new LDAPConnection(new JSSEBlindTrustSocketFactory());
1741            bindConnection =
1742                 new LDAPConnection(new JSSEBlindTrustSocketFactory());
1743          }
1744          catch (LDAPException le)
1745          {
1746            throw new UnableToRunException(le.getMessage(), le);
1747          }
1748        }
1749        else
1750        {
1751          authConnection = new LDAPConnection(new JSSESocketFactory(null));
1752          bindConnection = new LDAPConnection(new JSSESocketFactory(null));
1753        }
1754      }
1755      else
1756      {
1757        authConnection = new LDAPConnection();
1758        bindConnection = new LDAPConnection();
1759      }
1760
1761      try
1762      {
1763        authConnection.connect(3, directoryHost, directoryPort, bindDN, bindPW);
1764        bindConnection.connect(3, directoryHost, directoryPort, "", "");
1765      }
1766      catch (Exception JavaDoc e)
1767      {
1768        throw new UnableToRunException("Unable to establish the connections " +
1769                                       "to the directory server: " + e, e);
1770      }
1771    }
1772
1773    // Initialize the constraints.
1774
authConstraints = authConnection.getConstraints();
1775    bindConstraints = bindConnection.getConstraints();
1776    authSearchConstraints = authConnection.getSearchConstraints();
1777    authConstraints.setTimeLimit(1000*timeLimit);
1778    bindConstraints.setTimeLimit(1000*timeLimit);
1779    authSearchConstraints.setTimeLimit(1000*timeLimit);
1780    authSearchConstraints.setServerTimeLimit(timeLimit);
1781
1782
1783    // Create the stat trackers.
1784
attemptOverallCounter =
1785         new IncrementalTracker(clientID, threadID,
1786                                STAT_TRACKER_AUTHENTICATION_ATTEMPTS_OVERALL,
1787                                collectionInterval);
1788    attempt1Counter =
1789         new IncrementalTracker(clientID, threadID,
1790                                STAT_TRACKER_AUTHENTICATION_ATTEMPTS_1,
1791                                collectionInterval);
1792    attempt2Counter =
1793         new IncrementalTracker(clientID, threadID,
1794                                STAT_TRACKER_AUTHENTICATION_ATTEMPTS_2,
1795                                collectionInterval);
1796    successOverallCounter =
1797         new IncrementalTracker(clientID, threadID,
1798                                STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_OVERALL,
1799                                collectionInterval);
1800    success1Counter =
1801         new IncrementalTracker(clientID, threadID,
1802                                STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_1,
1803                                collectionInterval);
1804    success2Counter =
1805         new IncrementalTracker(clientID, threadID,
1806                                STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS_2,
1807                                collectionInterval);
1808    failureOverallCounter =
1809         new IncrementalTracker(clientID, threadID,
1810                                STAT_TRACKER_FAILED_AUTHENTICATIONS_OVERALL,
1811                                collectionInterval);
1812    failure1Counter =
1813         new IncrementalTracker(clientID, threadID,
1814                                STAT_TRACKER_FAILED_AUTHENTICATIONS_1,
1815                                collectionInterval);
1816    failure2Counter =
1817         new IncrementalTracker(clientID, threadID,
1818                                STAT_TRACKER_FAILED_AUTHENTICATIONS_2,
1819                                collectionInterval);
1820    authOverallTimer = new TimeTracker(clientID, threadID,
1821                                       STAT_TRACKER_AUTHENTICATION_TIME_OVERALL,
1822                                       collectionInterval);
1823    auth1Timer = new TimeTracker(clientID, threadID,
1824                                 STAT_TRACKER_AUTHENTICATION_TIME_1,
1825                                 collectionInterval);
1826    auth2Timer = new TimeTracker(clientID, threadID,
1827                                 STAT_TRACKER_AUTHENTICATION_TIME_2,
1828                                 collectionInterval);
1829    authenticationTypes =
1830         new CategoricalTracker(clientID, threadID,
1831                                STAT_TRACKER_AUTHENTICATION_CATEGORIES,
1832                                collectionInterval);
1833
1834
1835    // Enable real-time reporting of the data for these stat trackers.
1836
RealTimeStatReporter statReporter = getStatReporter();
1837    if (statReporter != null)
1838    {
1839      String JavaDoc jobID = getJobID();
1840      attemptOverallCounter.enableRealTimeStats(statReporter, jobID);
1841      attempt1Counter.enableRealTimeStats(statReporter, jobID);
1842      attempt2Counter.enableRealTimeStats(statReporter, jobID);
1843      successOverallCounter.enableRealTimeStats(statReporter, jobID);
1844      success1Counter.enableRealTimeStats(statReporter, jobID);
1845      success2Counter.enableRealTimeStats(statReporter, jobID);
1846      failureOverallCounter.enableRealTimeStats(statReporter, jobID);
1847      failure1Counter.enableRealTimeStats(statReporter, jobID);
1848      failure2Counter.enableRealTimeStats(statReporter, jobID);
1849      authOverallTimer.enableRealTimeStats(statReporter, jobID);
1850      auth1Timer.enableRealTimeStats(statReporter, jobID);
1851      auth2Timer.enableRealTimeStats(statReporter, jobID);
1852    }
1853  }
1854
1855
1856
1857  /**
1858   * Performs the work of actually running the job. When this method completes,
1859   * the job will be done.
1860   */

1861  public void runJob()
1862  {
1863    // Determine the range of time for which we should collect statistics.
1864
long currentTime = System.currentTimeMillis();
1865    boolean collectingStats = false;
1866    long startCollectingTime = currentTime + (1000 * warmUpTime);
1867    long stopCollectingTime = Long.MAX_VALUE;
1868    if ((coolDownTime > 0) && (getShouldStopTime() > 0))
1869    {
1870      stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime);
1871    }
1872
1873    // Define a variable that will be used to determine how long to sleep
1874
// between attempts.
1875
long authStartTime = 0;
1876
1877
1878    // See if this thread should operate "infinitely" (i.e., not a fixed number
1879
// of iterations)
1880
boolean infinite = (iterations <= 0);
1881
1882    // Loop until it is time to stop.
1883
for (int i=0; ((! shouldStop()) && ((infinite || (i < iterations)))); i++)
1884    {
1885      currentTime = System.currentTimeMillis();
1886      if ((! collectingStats) && (currentTime >= startCollectingTime) &&
1887          (currentTime < stopCollectingTime))
1888      {
1889        // Start all the stat trackers.
1890
attemptOverallCounter.startTracker();
1891        attempt1Counter.startTracker();
1892        attempt2Counter.startTracker();
1893        successOverallCounter.startTracker();
1894        success1Counter.startTracker();
1895        success2Counter.startTracker();
1896        failureOverallCounter.startTracker();
1897        failure1Counter.startTracker();
1898        failure2Counter.startTracker();
1899        authOverallTimer.startTracker();
1900        auth1Timer.startTracker();
1901        auth2Timer.startTracker();
1902        authenticationTypes.startTracker();
1903        collectingStats = true;
1904      }
1905      else if ((collectingStats) && (currentTime >= stopCollectingTime))
1906      {
1907        attemptOverallCounter.stopTracker();
1908        attempt1Counter.stopTracker();
1909        attempt2Counter.stopTracker();
1910        successOverallCounter.stopTracker();
1911        success1Counter.stopTracker();
1912        success2Counter.stopTracker();
1913        failureOverallCounter.stopTracker();
1914        failure1Counter.stopTracker();
1915        failure2Counter.stopTracker();
1916        authOverallTimer.stopTracker();
1917        auth1Timer.stopTracker();
1918        auth2Timer.stopTracker();
1919        authenticationTypes.stopTracker();
1920        collectingStats = false;
1921      }
1922
1923      // See if we need to sleep before the next attempt
1924
if ((delay > 0) && (authStartTime > 0))
1925      {
1926        long now = System.currentTimeMillis();
1927        long sleepTime = delay - (now - authStartTime);
1928        if (sleepTime > 0)
1929        {
1930          try
1931          {
1932            Thread.sleep(sleepTime);
1933          } catch (InterruptedException JavaDoc ie) {}
1934
1935          if (shouldStop())
1936          {
1937            break;
1938          }
1939        }
1940      }
1941
1942
1943      // Determine whether we should use a login ID from the first or second
1944
// set.
1945
int value = ((random.nextInt() & 0x7FFFFFFF) % 100);
1946      if (value < loginIDWeight)
1947      {
1948        String JavaDoc loginID = getLoginID1();
1949
1950        // Start the auth attempt timer now.
1951
if (delay > 0)
1952        {
1953          authStartTime = System.currentTimeMillis();
1954        }
1955
1956
1957        // Increment the number of authentication attempts and start the timer
1958
if (collectingStats)
1959        {
1960          attemptOverallCounter.increment();
1961          attempt1Counter.increment();
1962          authenticationTypes.increment("Login ID 1");
1963          authOverallTimer.startTimer();
1964          auth1Timer.startTimer();
1965        }
1966
1967        // First, issue a search to try to find the user's entry.
1968
String JavaDoc[] attrsToReturn;
1969        if ((membershipDN == null) || (membershipType != MEMBERSHIP_TYPE_ROLE))
1970        {
1971          if ((readPassFromAttr == null) || (readPassFromAttr.length() == 0))
1972          {
1973            attrsToReturn = NO_ATTRS;
1974          }
1975          else
1976          {
1977            attrsToReturn = new String JavaDoc[] { readPassFromAttr };
1978          }
1979        }
1980        else
1981        {
1982          if ((readPassFromAttr == null) || (readPassFromAttr.length() == 0))
1983          {
1984            attrsToReturn = new String JavaDoc[] { ROLE_ATTR };
1985          }
1986          else
1987          {
1988            attrsToReturn = new String JavaDoc[] { ROLE_ATTR, readPassFromAttr };
1989          }
1990        }
1991
1992        String JavaDoc filter = "(" + loginIDAttr + "=" + loginID + ")";
1993        LDAPSearchResults results;
1994        LDAPEntry userEntry = null;
1995        try
1996        {
1997          results = authConnection.search(searchBase, LDAPConnection.SCOPE_SUB,
1998                                          filter, attrsToReturn, false,
1999                                          authSearchConstraints);
2000          while (results.hasMoreElements())
2001          {
2002            Object JavaDoc element = results.nextElement();
2003            if (element instanceof LDAPEntry)
2004            {
2005              userEntry = (LDAPEntry) element;
2006            }
2007          }
2008        }
2009        catch (LDAPException le)
2010        {
2011          // The search failed, so update the failure counter and stop the timer.
2012
if (collectingStats)
2013          {
2014            failureOverallCounter.increment();
2015            failure1Counter.increment();
2016            authOverallTimer.stopTimer();
2017            auth1Timer.stopTimer();
2018          }
2019          continue;
2020        }
2021
2022
2023        // Make sure that we got a user entry. If not, then it's a failure.
2024
if (userEntry == null)
2025        {
2026          if (collectingStats)
2027          {
2028            failureOverallCounter.increment();
2029            failure1Counter.increment();
2030            authOverallTimer.stopTimer();
2031            auth1Timer.stopTimer();
2032          }
2033          continue;
2034        }
2035
2036
2037        // If we need to use the password from an attribute in the user's entry,
2038
// then get it.
2039
String JavaDoc password = loginPassword;
2040        if ((readPassFromAttr != null) && (readPassFromAttr.length() > 0))
2041        {
2042          LDAPAttribute attr = userEntry.getAttribute(readPassFromAttr);
2043          if (attr == null)
2044          {
2045            if (collectingStats)
2046            {
2047              failure1Counter.increment();
2048              auth1Timer.stopTimer();
2049            }
2050            continue;
2051          }
2052          else
2053          {
2054            String JavaDoc[] values = attr.getStringValueArray();
2055            if ((values == null) || (values.length == 0))
2056            {
2057              if (collectingStats)
2058              {
2059                failure1Counter.increment();
2060                auth1Timer.stopTimer();
2061              }
2062              continue;
2063            }
2064            else
2065            {
2066              password = values[0];
2067            }
2068          }
2069        }
2070
2071
2072        // Perform a bind as the user to verify that the provided password is
2073
// valid.
2074
try
2075        {
2076          bindConnection.authenticate(3, userEntry.getDN(), password);
2077        }
2078        catch (LDAPException le)
2079        {
2080          if (! (ignoreInvalidCredentials &&
2081                (le.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS)))
2082          {
2083            if (collectingStats)
2084            {
2085              failureOverallCounter.increment();
2086              failure1Counter.increment();
2087              authOverallTimer.stopTimer();
2088              auth1Timer.stopTimer();
2089            }
2090            continue;
2091          }
2092        }
2093
2094
2095        // If we are to check membership, then do so now.
2096
if (membershipDN != null)
2097        {
2098          if (isMember(userEntry))
2099          {
2100            if (collectingStats)
2101            {
2102              successOverallCounter.increment();
2103              success1Counter.increment();
2104              authOverallTimer.stopTimer();
2105              auth1Timer.stopTimer();
2106            }
2107          }
2108          else
2109          {
2110            if (collectingStats)
2111            {
2112              failureOverallCounter.increment();
2113              failure1Counter.increment();
2114              authOverallTimer.stopTimer();
2115              auth1Timer.stopTimer();
2116            }
2117          }
2118        }
2119        else
2120        {
2121          if (collectingStats)
2122          {
2123            successOverallCounter.increment();
2124            success1Counter.increment();
2125            authOverallTimer.stopTimer();
2126            auth1Timer.stopTimer();
2127          }
2128        }
2129      }
2130      else
2131      {
2132        String JavaDoc loginID = getLoginID2();
2133
2134        // Start the auth attempt timer now.
2135
if (delay > 0)
2136        {
2137          authStartTime = System.currentTimeMillis();
2138        }
2139
2140
2141        // Increment the number of authentication attempts and start the timer
2142
if (collectingStats)
2143        {
2144          attemptOverallCounter.increment();
2145          attempt2Counter.increment();
2146          authenticationTypes.increment("Login ID 2");
2147          authOverallTimer.startTimer();
2148          auth2Timer.startTimer();
2149        }
2150
2151        // First, issue a search to try to find the user's entry.
2152
String JavaDoc[] attrsToReturn;
2153        if ((membershipDN == null) || (membershipType != MEMBERSHIP_TYPE_ROLE))
2154        {
2155          if ((readPassFromAttr == null) || (readPassFromAttr.length() == 0))
2156          {
2157            attrsToReturn = NO_ATTRS;
2158          }
2159          else
2160          {
2161            attrsToReturn = new String JavaDoc[] { readPassFromAttr };
2162          }
2163        }
2164        else
2165        {
2166          if ((readPassFromAttr == null) || (readPassFromAttr.length() == 0))
2167          {
2168            attrsToReturn = new String JavaDoc[] { ROLE_ATTR };
2169          }
2170          else
2171          {
2172            attrsToReturn = new String JavaDoc[] { ROLE_ATTR, readPassFromAttr };
2173          }
2174        }
2175
2176        String JavaDoc filter = "(" + loginIDAttr + "=" + loginID + ")";
2177        LDAPSearchResults results;
2178        LDAPEntry userEntry = null;
2179        try
2180        {
2181          results = authConnection.search(searchBase, LDAPConnection.SCOPE_SUB,
2182                                          filter, attrsToReturn, false,
2183                                          authSearchConstraints);
2184          while (results.hasMoreElements())
2185          {
2186            Object JavaDoc element = results.nextElement();
2187            if (element instanceof LDAPEntry)
2188            {
2189              userEntry = (LDAPEntry) element;
2190            }
2191          }
2192        }
2193        catch (LDAPException le)
2194        {
2195          // The search failed, so update the failure counter and stop the timer.
2196
if (collectingStats)
2197          {
2198            failureOverallCounter.increment();
2199            failure2Counter.increment();
2200            authOverallTimer.stopTimer();
2201            auth2Timer.stopTimer();
2202          }
2203          continue;
2204        }
2205
2206
2207        // Make sure that we got a user entry. If not, then it's a failure.
2208
if (userEntry == null)
2209        {
2210          if (collectingStats)
2211          {
2212            failureOverallCounter.increment();
2213            failure2Counter.increment();
2214            authOverallTimer.stopTimer();
2215            auth2Timer.stopTimer();
2216          }
2217          continue;
2218        }
2219
2220        // If we need to use the password from an attribute in the user's entry,
2221
// then get it.
2222
String JavaDoc password = loginPassword;
2223        if ((readPassFromAttr != null) && (readPassFromAttr.length() > 0))
2224        {
2225          LDAPAttribute attr = userEntry.getAttribute(readPassFromAttr);
2226          if (attr == null)
2227          {
2228            if (collectingStats)
2229            {
2230              failure2Counter.increment();
2231              auth2Timer.stopTimer();
2232            }
2233            continue;
2234          }
2235          else
2236          {
2237            String JavaDoc[] values = attr.getStringValueArray();
2238            if ((values == null) || (values.length == 0))
2239            {
2240              if (collectingStats)
2241              {
2242                failure2Counter.increment();
2243                auth2Timer.stopTimer();
2244              }
2245              continue;
2246            }
2247            else
2248            {
2249              password = values[0];
2250            }
2251          }
2252        }
2253
2254
2255        // Perform a bind as the user to verify that the provided password is
2256
// valid.
2257
try
2258        {
2259          bindConnection.authenticate(3, userEntry.getDN(), password);
2260        }
2261        catch (LDAPException le)
2262        {
2263          if (! (ignoreInvalidCredentials &&
2264                (le.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS)))
2265          {
2266            if (collectingStats)
2267            {
2268              failureOverallCounter.increment();
2269              failure2Counter.increment();
2270              authOverallTimer.stopTimer();
2271              auth2Timer.stopTimer();
2272            }
2273            continue;
2274          }
2275        }
2276
2277
2278        // If we are to check membership, then do so now.
2279
if (membershipDN != null)
2280        {
2281          if (isMember(userEntry))
2282          {
2283            if (collectingStats)
2284            {
2285              successOverallCounter.increment();
2286              success2Counter.increment();
2287              authOverallTimer.stopTimer();
2288              auth2Timer.stopTimer();
2289            }
2290          }
2291          else
2292          {
2293            if (collectingStats)
2294            {
2295              failureOverallCounter.increment();
2296              failure2Counter.increment();
2297              authOverallTimer.stopTimer();
2298              auth2Timer.stopTimer();
2299            }
2300          }
2301        }
2302        else
2303        {
2304          if (collectingStats)
2305          {
2306            successOverallCounter.increment();
2307            success2Counter.increment();
2308            authOverallTimer.stopTimer();
2309            auth2Timer.stopTimer();
2310          }
2311        }
2312      }
2313    }
2314
2315
2316
2317    // Stop all the stat trackers.
2318
if (collectingStats)
2319    {
2320      attemptOverallCounter.stopTracker();
2321      attempt1Counter.stopTracker();
2322      attempt2Counter.stopTracker();
2323      successOverallCounter.stopTracker();
2324      success1Counter.stopTracker();
2325      success2Counter.stopTracker();
2326      failureOverallCounter.stopTracker();
2327      failure1Counter.stopTracker();
2328      failure2Counter.stopTracker();
2329      authOverallTimer.stopTracker();
2330      auth1Timer.stopTracker();
2331      auth2Timer.stopTracker();
2332      authenticationTypes.stopTracker();
2333    }
2334
2335
2336    // Make sure that the thread-specific connections are closed.
2337
if (! useSharedConnections)
2338    {
2339      try
2340      {
2341        authConnection.disconnect();
2342      } catch (Exception JavaDoc e) {}
2343
2344      try
2345      {
2346        bindConnection.disconnect();
2347      } catch (Exception JavaDoc e) {}
2348    }
2349  }
2350
2351
2352
2353  /**
2354   * Attempts to force this thread to exit by closing the connections to the
2355   * directory server and setting them to <CODE>null</CODE>.
2356   */

2357  public void destroy()
2358  {
2359    if (authConnection != null)
2360    {
2361      try
2362      {
2363        authConnection.disconnect();
2364      } catch (Exception JavaDoc e) {}
2365
2366      authConnection = null;
2367    }
2368
2369    if (bindConnection != null)
2370    {
2371      try
2372      {
2373        bindConnection.disconnect();
2374      } catch (Exception JavaDoc e) {}
2375
2376      bindConnection = null;
2377    }
2378  }
2379
2380
2381
2382  /**
2383   * Performs any per-client finalization that should be done for this job. In
2384   * this case, if the job was using shared connections then those connections
2385   * will be closed.
2386   */

2387  public void finalizeClient()
2388  {
2389    // Make sure that the shared connections get closed properly.
2390
if (useSharedConnections)
2391    {
2392      try
2393      {
2394        sharedAuthConnection.disconnect();
2395      } catch (Exception JavaDoc e) {}
2396
2397      try
2398      {
2399        sharedBindConnection.disconnect();
2400      } catch (Exception JavaDoc e) {}
2401    }
2402  }
2403
2404
2405
2406  /**
2407   * Determines whether the provided user is a member of the membership DN.
2408   *
2409   * @param userEntry The user entry for which to make the determination.
2410   *
2411   * @return <CODE>true</CODE> if it is determined that the user is a member,
2412   * or <CODE>false</CODE> if the membership could not be determined.
2413   */

2414  public boolean isMember(LDAPEntry userEntry)
2415  {
2416    switch (membershipType)
2417    {
2418      case MEMBERSHIP_TYPE_STATIC:
2419        String JavaDoc userDN = userEntry.getDN();
2420        String JavaDoc filter = "(|(&(objectclass=groupOfNames)(member=" + userDN +
2421                        "))(&(objectClass=groupOfUniqueNames)(uniqueMember=" +
2422                        userDN + ")))";
2423        try
2424        {
2425          LDAPSearchResults results =
2426               authConnection.search(membershipDN, LDAPConnection.SCOPE_BASE,
2427                                     filter, NO_ATTRS, false);
2428          while (results.hasMoreElements())
2429          {
2430            Object JavaDoc element = results.nextElement();
2431            if (element instanceof LDAPEntry)
2432            {
2433              return true;
2434            }
2435          }
2436
2437          return false;
2438        }
2439        catch (Exception JavaDoc e)
2440        {
2441          return false;
2442        }
2443      case MEMBERSHIP_TYPE_DYNAMIC:
2444        userDN = LDAPDN.normalize(userEntry.getDN());
2445        if (! userDN.endsWith(membershipURLBase))
2446        {
2447          return false;
2448        }
2449
2450        try
2451        {
2452          LDAPSearchResults results =
2453               authConnection.search(userDN, LDAPConnection.SCOPE_BASE,
2454                                     membershipURLFilter, NO_ATTRS, false);
2455          while (results.hasMoreElements())
2456          {
2457            Object JavaDoc element = results.nextElement();
2458            if (element instanceof LDAPEntry)
2459            {
2460              return true;
2461            }
2462          }
2463
2464          return false;
2465        }
2466        catch (Exception JavaDoc e)
2467        {
2468          return false;
2469        }
2470      case MEMBERSHIP_TYPE_ROLE:
2471        LDAPAttribute roleAttr = userEntry.getAttribute(ROLE_ATTR);
2472        String JavaDoc[] roleValues = null;
2473        if ((roleAttr == null) ||
2474            ((roleValues = roleAttr.getStringValueArray()) == null) ||
2475            (roleValues.length == 0))
2476        {
2477          return false;
2478        }
2479
2480        for (int i=0; i < roleValues.length; i++)
2481        {
2482          String JavaDoc roleDN = LDAPDN.normalize(roleValues[i]);
2483          if (roleDN.equals(membershipDN))
2484          {
2485            return true;
2486          }
2487        }
2488
2489        return false;
2490    }
2491
2492
2493    return false;
2494  }
2495
2496
2497
2498  /**
2499   * Retrieves a randomly-chosen login ID from the first set.
2500   *
2501   * @return A randomly-chosen login ID from the first set.
2502   */

2503  public String JavaDoc getLoginID1()
2504  {
2505    if (useLoginIDRange1)
2506    {
2507      int value;
2508      if (useSequential1)
2509      {
2510        value = sequentialCounter1++;
2511        if (sequentialCounter1 > loginIDMax1)
2512        {
2513          sequentialCounter1 = loginIDMin1;
2514        }
2515      }
2516      else
2517      {
2518        value = ((random.nextInt() & 0x7FFFFFFF) % loginIDSpan1) + loginIDMin1;
2519      }
2520
2521      return loginIDInitial1 + value + loginIDFinal1;
2522    }
2523    else
2524    {
2525      return loginIDInitial1;
2526    }
2527  }
2528
2529
2530
2531  /**
2532   * Retrieves a randomly-chosen login ID from the secondset.
2533   *
2534   * @return A randomly-chosen login ID from the second set.
2535   */

2536  public String JavaDoc getLoginID2()
2537  {
2538    if (useLoginIDRange2)
2539    {
2540      int value;
2541      if (useSequential2)
2542      {
2543        value = sequentialCounter2++;
2544        if (sequentialCounter2 > loginIDMax2)
2545        {
2546          sequentialCounter2 = loginIDMin2;
2547        }
2548      }
2549      else
2550      {
2551        value = ((random.nextInt() & 0x7FFFFFFF) % loginIDSpan2) + loginIDMin2;
2552      }
2553
2554      return loginIDInitial2 + value + loginIDFinal2;
2555    }
2556    else
2557    {
2558      return loginIDInitial2;
2559    }
2560  }
2561}
2562
2563
Popular Tags