KickJava   Java API By Example, From Geeks To Geeks.

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


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.controls.*;
25 import netscape.ldap.factory.*;
26 import com.sun.slamd.job.*;
27 import com.sun.slamd.parameter.*;
28 import com.sun.slamd.stat.*;
29
30
31
32 /**
33  * This class implements a SLAMD job class for performing repeated modifications
34  * against an LDAP directory server. The modifications can be separated into
35  * two categories, with a percentage used to specify how frequently each kind
36  * of entry will be modified. All of the configuration for this job thread can
37  * be provided through parameters.
38  *
39  *
40  * @author Neil A. Wilson
41  */

42 public class WeightedModRateJobClass
43        extends JobClass
44        implements LDAPRebind
45 {
46   /**
47    * The system property used to specify the location of the JSSE key store.
48    */

49   public static final String JavaDoc SSL_KEY_STORE_PROPERTY =
50        "javax.net.ssl.keyStore";
51
52
53
54   /**
55    * The system property used to specify the password for the JSSE key store.
56    */

57   public static final String JavaDoc SSL_KEY_PASSWORD_PROPERTY =
58        "javax.net.ssl.keyStorePassword";
59
60
61
62   /**
63    * The system property used to specify the location of the JSSE trust store.
64    */

65   public static final String JavaDoc SSL_TRUST_STORE_PROPERTY =
66        "javax.net.ssl.trustStore";
67
68
69
70   /**
71    * The system property used to specify the password for the JSSE trust store.
72    */

73   public static final String JavaDoc SSL_TRUST_PASSWORD_PROPERTY =
74        "javax.net.ssl.trustStorePassword";
75
76
77
78   /**
79    * The display name for the stat tracker that will be used to track the time
80    * required to perform the first kind of modification.
81    */

82   public static final String JavaDoc STAT_TRACKER_MOD_1_TIME = "Modify DN 1 Time (ms)";
83
84
85
86   /**
87    * The display name for the stat tracker that will be used to track the time
88    * required to perform the second kind of modification.
89    */

90   public static final String JavaDoc STAT_TRACKER_MOD_2_TIME = "Modify DN 2 Time (ms)";
91
92
93
94   /**
95    * The display name for the stat tracker that will be used to track the time
96    * required to perform either kind of modification.
97    */

98   public static final String JavaDoc STAT_TRACKER_MOD_OVERALL_TIME =
99        "Overall Modify Time (ms)";
100
101
102
103   /**
104    * The display name for the stat tracker that will be used to track the number
105    * of the first kind of modifications performed.
106    */

107   public static final String JavaDoc STAT_TRACKER_MOD_1_COUNT =
108        "DN 1 Modifications Performed";
109
110
111
112   /**
113    * The display name for the stat tracker that will be used to track the number
114    * of the second kind of modifications performed.
115    */

116   public static final String JavaDoc STAT_TRACKER_MOD_2_COUNT =
117        "DN 2 Modifications Performed";
118
119
120
121   /**
122    * The display name for the stat tracker that will be used to track the number
123    * of either kind of modifications performed.
124    */

125   public static final String JavaDoc STAT_TRACKER_MOD_OVERALL_COUNT =
126        "Overall Modifications Performed";
127
128
129
130   /**
131    * The display name for the stat tracker that will be used to track the number
132    * of exceptions caught.
133    */

134   public static final String JavaDoc STAT_TRACKER_EXCEPTIONS_CAUGHT =
135        "Exceptions Caught";
136
137
138
139   /**
140    * The display name of the stat tracker that will be used to categorize the
141    * types of modifications performed.
142    */

143   public static final String JavaDoc STAT_TRACKER_MOD_CATEGORIES =
144        "Modifications by Category";
145
146
147
148   /**
149    * The characters that are available for use in the randomly-generated values.
150    */

151   public static final char[] ALPHABET =
152        "abcdefghijklmnopqrstuvwxyz".toCharArray();
153
154
155
156
157
158   // The parameter that indicates whether the client should trust any SSL cert.
159
BooleanParameter blindTrustParameter =
160     new BooleanParameter("blind_trust", "Blindly Trust Any Certificate",
161                          "Indicates whether the client should blindly trust " +
162                          "any certificate presented by the server, or " +
163                          "whether the key and trust stores should be used.",
164                          true);
165
166   // The parameter that indicates whether to disconnect after each modify
167
BooleanParameter disconnectParameter =
168        new BooleanParameter("disconnect", "Always Disconnect",
169                             "Indicates whether to close the connection after " +
170                             "each modification", false);
171
172   // The parameter that indicates whether referrals are to be followed or not
173
BooleanParameter followReferralsParameter =
174        new BooleanParameter("followreferrals", "Follow Referrals",
175                             "Indicates whether to follow referrals received " +
176                             "while making modifications", false);
177
178   // The parameter that indicates whether the connection should use SSL
179
BooleanParameter useSSLParameter =
180     new BooleanParameter("usessl", "Use SSL",
181                          "Indicates whether SSL should be used for all " +
182                          "communication with the directory server", false);
183
184   // The parmeter that specifies the cool-down time in seconds.
185
IntegerParameter coolDownParameter =
186        new IntegerParameter("cool_down", "Cool Down Time",
187                             "The time in seconds that the job should " +
188                             "continue modifying after ending statistics " +
189                             "collection.", true, 0, true, 0, false, 0);
190
191   // The parameter that indicates the delay that should be used between each
192
// request sent by a thread.
193
IntegerParameter delayParameter =
194        new IntegerParameter("delay", "Time Between Requests (ms)",
195                             "Specifies the length of time in milliseconds " +
196                             "each thread should wait between modify " +
197                             "requests. Note that this delay will be " +
198                             "between consecutive requests and not between " +
199                             "the response of one operation and the request " +
200                             "for the next. If a modify takes longer than " +
201                             "this length of time, then there will be no delay.",
202                             true, 0, true, 0, false, 0);
203
204   // The parameter that indicates the number of times the modify should be
205
// performed
206
IntegerParameter iterationsParameter =
207        new IntegerParameter("iterations", "Number of Iterations",
208                             "The number of modifications that should be " +
209                             "performed by each thread", false, -1);
210
211   // The parameter that indicates the number of characters that should be
212
// included in the replacement value used in the modify.
213
IntegerParameter lengthParameter =
214        new IntegerParameter("length", "Value Length",
215                             "The length that should be used for the new " +
216                             "value of the modified attribute.", true, 80,
217                             true, 1, false, 0);
218
219   // The parameter that indicates the port number for the directory server
220
IntegerParameter portParameter =
221        new IntegerParameter("ldapport", "Directory Server Port",
222                             "The port number for the LDAP directory server",
223                             true, 389, true, 1, true, 65535);
224
225   // The parameter that indicates the maximum time limit for modify operations.
226
IntegerParameter timeLimitParameter =
227        new IntegerParameter("time_limit", "Modify Time Limit",
228                             "The maximum length of time in seconds that the " +
229                             "thread should wait for a modify operation to be " +
230                             "performed before cancelling it and trying " +
231                             "another.", false, 0, true, 0, false, 0);
232
233   // The parmeter that specifies the cool-down time in seconds.
234
IntegerParameter warmUpParameter =
235        new IntegerParameter("warm_up", "Warm Up Time",
236                             "The time in seconds that the job should " +
237                             "modify before beginning statistics collection.",
238                             true, 0, true, 0, false, 0);
239
240   // The parameter that specifies the percentage of the time that the first DN
241
// will be used in the modification.
242
IntegerParameter weightParameter =
243        new IntegerParameter("weight", "DN 1 Percentage",
244                             "The percentage of the time that a DN should be " +
245                             "selected according to the value provided for " +
246                             "the Entry DN 1 parameter.", true, 50, true, 0,
247                             true, 100);
248
249   // The parameter that specifies the attribute to modify
250
MultiLineTextParameter attributeParameter =
251        new MultiLineTextParameter("attribute", "Attribute(s) to Modify",
252                                   "The set of attribute to modify in the " +
253                                   "entry. If multiple attributes are to be " +
254                                   "modified, then a separate attribute " +
255                                   "should be listed per line. Each will be " +
256                                   "given the same value.",
257                                   new String JavaDoc[] { "description" }, true);
258
259   // The placeholder parameter used as a spacer in the admin interface.
260
PlaceholderParameter placeholder = new PlaceholderParameter();
261
262   // The parameter that indicates the DN to use when binding to the server
263
StringParameter bindDNParameter =
264        new StringParameter("binddn", "Bind DN",
265                            "The DN to use to bind to the server", false, "");
266
267   // The parameter that indicates the DN or DN range to use for the first set.
268
StringParameter entryDN1Parameter =
269        new StringParameter("entrydn1", "Entry DN 1",
270                            "The DN or DN range of the first entry to modify",
271                            true, "");
272
273   // The parameter that indicates the DN or DN range to use for the second set.
274
StringParameter entryDN2Parameter =
275        new StringParameter("entrydn2", "Entry DN 2",
276                            "The DN or DN range of the second entry to modify",
277                            true, "");
278
279   // The parameter that indicates the address of the directory server
280
StringParameter hostParameter =
281        new StringParameter("ldaphost", "Directory Server Host",
282                            "The DNS hostname or IP address of the LDAP " +
283                            "directory server", true, "");
284
285   // The parameter that indicates the DN to use to proxy the modifications.
286
StringParameter proxyAsDNParameter =
287        new StringParameter("proxy_as_dn", "Proxy As DN",
288                            "The DN of the user whose credentials should be " +
289                            "used to perform the modification through the use " +
290                            "of the proxied authorization control.", false, "");
291
292   // The parameter that specifies the location of the SSL key store
293
StringParameter keyStoreParameter =
294     new StringParameter("sslkeystore", "SSL Key Store",
295                         "The path to the JSSE key store to use for an " +
296                         "SSL-based connection", false, "");
297
298   // The parameter that specifies the location of the SSL trust store
299
StringParameter trustStoreParameter =
300     new StringParameter("ssltruststore", "SSL Trust Store",
301                         "The path to the JSSE trust store to use for an " +
302                         "SSL-based connection", false, "");
303
304   // The parameter that indicates the bind password
305
PasswordParameter bindPWParameter =
306        new PasswordParameter("bindpw", "Bind Password",
307                              "The password for the bind DN", false, "");
308
309   // The parameter that specifies the password for the SSL key store
310
PasswordParameter keyPWParameter =
311     new PasswordParameter("sslkeypw", "SSL Key Store Password",
312                           "The password for the JSSE key store", false, "");
313
314   // The parameter that specifies the password for the SSL key store
315
PasswordParameter trustPWParameter =
316     new PasswordParameter("ssltrustpw", "SSL Trust Store Password",
317                           "The password for the JSSE trust store", false, "");
318
319
320   // Instance variables that correspond to the parameter values
321
static boolean alwaysDisconnect;
322   static boolean blindTrust;
323   static boolean followReferrals;
324   static boolean useDN1Range;
325   static boolean useDN2Range;
326   static boolean useProxyAuth;
327   static boolean useDN1Sequential;
328   static boolean useDN2Sequential;
329   static boolean useSSL;
330   static int coolDownTime;
331   static int dn1RangeMax;
332   static int dn1RangeMin;
333   static int dn1RangeSpan;
334   static int dn1Weight;
335   static int dn2RangeMax;
336   static int dn2RangeMin;
337   static int dn2RangeSpan;
338   static int iterations;
339   static int ldapPort;
340   static int length;
341   static int sequentialCounter1;
342   static int sequentialCounter2;
343   static int timeLimit;
344   static int warmUpTime;
345   static long delay;
346   static String JavaDoc bindDN;
347   static String JavaDoc bindPassword;
348   static String JavaDoc dn1Initial;
349   static String JavaDoc dn1Final;
350   static String JavaDoc dn2Initial;
351   static String JavaDoc dn2Final;
352   static String JavaDoc ldapHost;
353   static String JavaDoc proxyAsDN;
354   static String JavaDoc sslKeyStore;
355   static String JavaDoc sslKeyPassword;
356   static String JavaDoc sslTrustStore;
357   static String JavaDoc sslTrustPassword;
358   static String JavaDoc[] modifyAttrs;
359
360
361   // The connection to the directory to use to perform the modifies.
362
LDAPConnection conn;
363
364
365   // Variables used for status counters
366
CategoricalTracker modCategories;
367   IncrementalTracker exceptionsCaught;
368   IncrementalTracker mod1Count;
369   IncrementalTracker mod2Count;
370   IncrementalTracker modOverallCount;
371   TimeTracker mod1Time;
372   TimeTracker mod2Time;
373   TimeTracker modOverallTime;
374
375
376   // One random number generator for use throughout the client and another to
377
// use for only the current thread.
378
static Random parentRandom;
379   Random random;
380
381
382
383
384   /**
385    * The default constructor used to create a new instance of the modify thread.
386    * The only thing it should do is to invoke the superclass constructor. All
387    * other initialization should be performed in the <CODE>initialize</CODE>
388    * method.
389    */

390   public WeightedModRateJobClass()
391   {
392     super();
393   }
394
395
396
397   /**
398    * Retrieves the name of the job performed by this job thread.
399    *
400    * @return The name of the job performed by this job thread.
401    */

402   public String JavaDoc getJobName()
403   {
404     return "LDAP Weighted ModRate";
405   }
406
407
408
409   /**
410    * Retrieves a description of the job performed by this job thread.
411    *
412    * @return A description of the job performed by this job thread.
413    */

414   public String JavaDoc getJobDescription()
415   {
416     return "This job can be used to perform repeated modifications against " +
417            "an LDAP directory server to generate load and measure " +
418            "performance. It can do so to two different DN ranges with a " +
419            "varying percentage between each range.";
420   }
421
422
423
424   /**
425    * Retrieves the name of the category in which this job class exists. This is
426    * used to help arrange the job classes in the administrative interface.
427    *
428    * @return The name of the category in which this job class exists.
429    */

430   public String JavaDoc getJobCategoryName()
431   {
432     return "LDAP";
433   }
434
435
436
437   /**
438    * Retrieve a parameter list that can be used to determine all of the
439    * customizeable options that are available for this job.
440    *
441    * @return A parameter list that can be used to determine all of the
442    * customizeable options that are available for this job.
443    */

444   public ParameterList getParameterStubs()
445   {
446     Parameter[] parameters = new Parameter[]
447     {
448       placeholder,
449       hostParameter,
450       portParameter,
451       bindDNParameter,
452       bindPWParameter,
453       proxyAsDNParameter,
454       placeholder,
455       entryDN1Parameter,
456       entryDN2Parameter,
457       weightParameter,
458       placeholder,
459       attributeParameter,
460       lengthParameter,
461       placeholder,
462       warmUpParameter,
463       coolDownParameter,
464       timeLimitParameter,
465       delayParameter,
466       placeholder,
467       useSSLParameter,
468       blindTrustParameter,
469       keyStoreParameter,
470       keyPWParameter,
471       trustStoreParameter,
472       trustPWParameter,
473       placeholder,
474       iterationsParameter,
475       disconnectParameter,
476       followReferralsParameter
477     };
478
479     return new ParameterList(parameters);
480   }
481
482
483
484   /**
485    * Retrieves the set of stat trackers that will be maintained by this job
486    * class. The stat trackers returned by this method do not have to actually
487    * contain any statistics -- the display name and stat tracker class should
488    * be the only information that callers of this method should rely upon. Note
489    * that this list can be different from the list of statistics actually
490    * collected by the job in some cases (e.g., if the job may not return all the
491    * stat trackers it advertises in all cases, or if the job may return stat
492    * trackers that it did not advertise), but it is a possibility that only the
493    * stat trackers returned by this method will be accessible for some features
494    * in the SLAMD server.
495    *
496    * @param clientID The client ID that should be used for the
497    * returned stat trackers.
498    * @param threadID The thread ID that should be used for the
499    * returned stat trackers.
500    * @param collectionInterval The collection interval that should be used for
501    * the returned stat trackers.
502    *
503    * @return The set of stat trackers that will be maintained by this job
504    * class.
505    */

506   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
507                                            int collectionInterval)
508   {
509     return new StatTracker[]
510     {
511       new IncrementalTracker(clientID, threadID, STAT_TRACKER_MOD_OVERALL_COUNT,
512                              collectionInterval),
513       new IncrementalTracker(clientID, threadID, STAT_TRACKER_MOD_1_COUNT,
514                              collectionInterval),
515       new IncrementalTracker(clientID, threadID, STAT_TRACKER_MOD_2_COUNT,
516                              collectionInterval),
517       new TimeTracker(clientID, threadID, STAT_TRACKER_MOD_OVERALL_TIME,
518                       collectionInterval),
519       new TimeTracker(clientID, threadID, STAT_TRACKER_MOD_1_TIME,
520                       collectionInterval),
521       new TimeTracker(clientID, threadID, STAT_TRACKER_MOD_2_TIME,
522                       collectionInterval),
523       new IncrementalTracker(clientID, threadID, STAT_TRACKER_EXCEPTIONS_CAUGHT,
524                              collectionInterval),
525       new CategoricalTracker(clientID, threadID, STAT_TRACKER_MOD_CATEGORIES,
526                              collectionInterval)
527     };
528   }
529
530
531
532   /**
533    * Retrieves the stat trackers that are maintained for this job thread.
534    *
535    * @return The stat trackers that are maintained for this job thread.
536    */

537   public StatTracker[] getStatTrackers()
538   {
539     return new StatTracker[]
540     {
541       modOverallCount,
542       mod1Count,
543       mod2Count,
544       modOverallTime,
545       mod1Time,
546       mod2Time,
547       exceptionsCaught,
548       modCategories
549     };
550   }
551
552
553
554   /**
555    * Indicates whether this job class implements logic that makes it possible to
556    * test the validity of job parameters before scheduling the job for execution
557    * (e.g., to see if the server is reachable using the information provided).
558    *
559    * @return <CODE>true</CODE> if this job provides a means of testing the job
560    * parameters, or <CODE>false</CODE> if not.
561    */

562   public boolean providesParameterTest()
563   {
564     return true;
565   }
566
567
568
569   /**
570    * Provides a means of testing the provided job parameters to determine
571    * whether they are valid (e.g., to see if the server is reachable) before
572    * scheduling the job for execution. This method will be executed by the
573    * SLAMD server system itself and not by any of the clients.
574    *
575    * @param parameters The job parameters to be tested.
576    * @param outputMessages The lines of output that were generated as part of
577    * the testing process. Each line of output should
578    * be added to this list as a separate string, and
579    * empty strings (but not <CODE>null</CODE> values)
580    * are allowed to provide separation between
581    * different messages. No formatting should be
582    * provided for these messages, however, since they
583    * may be displayed in either an HTML or plain text
584    * interface.
585    *
586    * @return <CODE>true</CODE> if the test completed successfully, or
587    * <CODE>false</CODE> if not. Note that even if the test did not
588    * complete successfully, the user will be presented with a warning
589    * but will still be allowed to schedule the job using the provided
590    * parameters. This is necessary because the parameters may still be
591    * valid even if the server couldn't validate them at the time the
592    * job was scheduled (e.g., if the server wasn't running or could not
593    * be reached by the SLAMD server even though it could be by the
594    * clients).
595    */

596   public boolean testJobParameters(ParameterList parameters,
597                                    ArrayList outputMessages)
598   {
599     // Get all the parameters that we might need to perform the test.
600
StringParameter hostParam =
601          parameters.getStringParameter(hostParameter.getName());
602     if ((hostParam == null) || (! hostParam.hasValue()))
603     {
604       outputMessages.add("ERROR: No directory server address was provided.");
605       return false;
606     }
607     String JavaDoc host = hostParam.getStringValue();
608
609
610     IntegerParameter portParam =
611          parameters.getIntegerParameter(portParameter.getName());
612     if ((portParam == null) || (! hostParam.hasValue()))
613     {
614       outputMessages.add("ERROR: No directory server port was provided.");
615       return false;
616     }
617     int port = portParam.getIntValue();
618
619
620     boolean useSSL = false;
621     BooleanParameter useSSLParam =
622          parameters.getBooleanParameter(useSSLParameter.getName());
623     if (useSSLParam != null)
624     {
625       useSSL = useSSLParam.getBooleanValue();
626     }
627
628
629     boolean blindTrust = true;
630     BooleanParameter blindTrustParam =
631          parameters.getBooleanParameter(blindTrustParameter.getName());
632     if (blindTrustParam != null)
633     {
634       blindTrust = blindTrustParam.getBooleanValue();
635     }
636
637
638     String JavaDoc keyStore = null;
639     StringParameter keyStoreParam =
640          parameters.getStringParameter(keyStoreParameter.getName());
641     if ((keyStoreParam != null) && keyStoreParam.hasValue())
642     {
643       keyStore = keyStoreParam.getStringValue();
644       File keyStoreFile = new File(keyStore);
645       if (useSSL && (! blindTrust) && (! keyStoreFile.exists()))
646       {
647         outputMessages.add("WARNING: Key store file \"" + keyStore +
648                            "\" not found on SLAMD server system. This test " +
649                            "will blindly trust any SSL certificate " +
650                            "presented by the directory server.");
651         outputMessages.add("");
652         blindTrust = true;
653       }
654       else
655       {
656         System.setProperty(SSL_KEY_STORE_PROPERTY, keyStore);
657       }
658     }
659
660
661     String JavaDoc keyStorePassword = "";
662     StringParameter keyPassParam =
663          parameters.getStringParameter(keyPWParameter.getName());
664     if ((keyPassParam != null) && keyPassParam.hasValue())
665     {
666       keyStorePassword = keyPassParam.getStringValue();
667       System.setProperty(SSL_KEY_PASSWORD_PROPERTY, keyStorePassword);
668     }
669
670
671     String JavaDoc trustStore = null;
672     StringParameter trustStoreParam =
673          parameters.getStringParameter(trustStoreParameter.getName());
674     if ((trustStoreParam != null) && trustStoreParam.hasValue())
675     {
676       trustStore = trustStoreParam.getStringValue();
677       File trustStoreFile = new File(trustStore);
678       if (useSSL && (! blindTrust) && (! trustStoreFile.exists()))
679       {
680         outputMessages.add("WARNING: trust store file \"" + trustStore +
681                            "\" not found on SLAMD server system. This test " +
682                            "will blindly trust any SSL certificate " +
683                            "presented by the directory server.");
684         outputMessages.add("");
685         blindTrust = true;
686       }
687       else
688       {
689         System.setProperty(SSL_TRUST_STORE_PROPERTY, trustStore);
690       }
691     }
692
693
694     String JavaDoc trustStorePassword = "";
695     StringParameter trustPassParam =
696          parameters.getStringParameter(trustPWParameter.getName());
697     if ((trustPassParam != null) && trustPassParam.hasValue())
698     {
699       trustStorePassword = trustPassParam.getStringValue();
700       System.setProperty(SSL_TRUST_PASSWORD_PROPERTY, trustStorePassword);
701     }
702
703
704     String JavaDoc bindDN = "";
705     StringParameter bindDNParam =
706          parameters.getStringParameter(bindDNParameter.getName());
707     if ((bindDNParam != null) && bindDNParam.hasValue())
708     {
709       bindDN = bindDNParam.getStringValue();
710     }
711
712
713     String JavaDoc bindPassword = "";
714     PasswordParameter bindPWParam =
715          parameters.getPasswordParameter(bindPWParameter.getName());
716     if ((bindPWParam != null) && bindPWParam.hasValue())
717     {
718       bindPassword = bindPWParam.getStringValue();
719     }
720
721
722     String JavaDoc proxyAsDN = null;
723     StringParameter proxyAsDNParam =
724          parameters.getStringParameter(proxyAsDNParameter.getName());
725     if ((proxyAsDNParam != null) && proxyAsDNParam.hasValue())
726     {
727       proxyAsDN = proxyAsDNParam.getStringValue();
728     }
729
730
731     // Create the LDAPConnection object that we will use to communicate with the
732
// directory server.
733
LDAPConnection conn;
734     if (useSSL)
735     {
736       if (blindTrust)
737       {
738         try
739         {
740           conn = new LDAPConnection(new JSSEBlindTrustSocketFactory());
741         }
742         catch (Exception JavaDoc e)
743         {
744           outputMessages.add("ERROR: Unable to instantiate the blind trust " +
745                              "socket factory for use in creating the SSL " +
746                              "connection: " + stackTraceToString(e));
747           return false;
748         }
749       }
750       else
751       {
752         conn = new LDAPConnection(new JSSESocketFactory(null));
753       }
754     }
755     else
756     {
757       conn = new LDAPConnection();
758     }
759
760
761     // Attempt to establish a connection to the directory server.
762
try
763     {
764       if (useSSL)
765       {
766         outputMessages.add("Attempting to establish an SSL-based connection " +
767                            "to " + host + ":" + port + "....");
768       }
769       else
770       {
771         outputMessages.add("Attempting to establish a connection to " + host +
772                            ":" + port + "....");
773       }
774       conn.connect(host, port);
775       outputMessages.add("Connected successfully.");
776       outputMessages.add("");
777     }
778     catch (Exception JavaDoc e)
779     {
780       outputMessages.add("ERROR: Unable to connect to the directory " +
781                          "server: " + stackTraceToString(e));
782       return false;
783     }
784
785
786     // Attempt to bind to the directory server using the bind DN and password.
787
try
788     {
789       outputMessages.add("Attempting to perform an LDAPv3 bind to the " +
790                          "directory server with a DN of '" + bindDN + "'....");
791       conn.bind(3, bindDN, bindPassword);
792       outputMessages.add("Bound successfully.");
793       outputMessages.add("");
794     }
795     catch (Exception JavaDoc e)
796     {
797       try
798       {
799         conn.disconnect();
800       } catch (Exception JavaDoc e2) {}
801
802       outputMessages.add("ERROR: Unable to bind to the directory server: " +
803                          stackTraceToString(e));
804       return false;
805     }
806
807
808     // If a proxy user was specified, make sure that it exists.
809
if (proxyAsDN != null)
810     {
811       try
812       {
813         outputMessages.add("Checking to make sure that the proxied user '" +
814                            proxyAsDN + "' exists in the directory....");
815         LDAPEntry proxyUserEntry = conn.read(proxyAsDN, new String JavaDoc[] { "1.1" });
816         if (proxyUserEntry == null)
817         {
818           try
819           {
820             conn.disconnect();
821           } catch (Exception JavaDoc e2) {}
822
823           outputMessages.add("ERROR: Unable to retrieve the proxied user's " +
824                              "entry.");
825           return false;
826         }
827         else
828         {
829           outputMessages.add("Successfully read the proxied user's entry.");
830           outputMessages.add("");
831         }
832       }
833       catch (Exception JavaDoc e)
834       {
835         try
836         {
837           conn.disconnect();
838         } catch (Exception JavaDoc e2) {}
839
840         outputMessages.add("ERROR: Unable to retrieve the proxied user's " +
841                            "entry: " + stackTraceToString(e));
842         return false;
843       }
844     }
845
846
847     // At this point, all tests have passed. Close the connection and return
848
// true.
849
try
850     {
851       conn.disconnect();
852     } catch (Exception JavaDoc e) {}
853
854     outputMessages.add("All tests completed successfully.");
855     return true;
856   }
857
858
859
860   /**
861    * Initializes all of the instance variables that correspond to job
862    * parameters.
863    *
864    * @param clientID The client ID for the current client.
865    * @param parameters The set of parameters that have been defined for this
866    * job.
867    *
868    * @throws UnableToRunException If any part of the initialization fails.
869    */

870   public void initializeClient(String JavaDoc clientID, ParameterList parameters)
871          throws UnableToRunException
872   {
873     // Get the address of the target directory server
874
ldapHost = null;
875     hostParameter = parameters.getStringParameter(hostParameter.getName());
876     if (hostParameter != null)
877     {
878       ldapHost = hostParameter.getStringValue();
879     }
880
881     // Get the port for the target directory server
882
ldapPort = 389;
883     portParameter = parameters.getIntegerParameter(portParameter.getName());
884     if (portParameter != null)
885     {
886       ldapPort = portParameter.getIntValue();
887     }
888
889     // Get the bind DN for the target directory server
890
bindDN = "";
891     bindDNParameter = parameters.getStringParameter(bindDNParameter.getName());
892     if (bindDNParameter != null)
893     {
894       bindDN = bindDNParameter.getStringValue();
895     }
896
897     // Get the bind password for the target directory server
898
bindPassword = "";
899     bindPWParameter =
900          parameters.getPasswordParameter(bindPWParameter.getName());
901     if (bindPWParameter != null)
902     {
903       bindPassword = bindPWParameter.getStringValue();
904     }
905
906     // Get the DN of the proxy as user.
907
useProxyAuth = false;
908     proxyAsDNParameter =
909          parameters.getStringParameter(proxyAsDNParameter.getName());
910     if ((proxyAsDNParameter != null) && (proxyAsDNParameter.hasValue()))
911     {
912       useProxyAuth = true;
913       proxyAsDN = proxyAsDNParameter.getStringValue();
914     }
915
916     // Get the DN of the first entry to modify
917
entryDN1Parameter =
918          parameters.getStringParameter(entryDN1Parameter.getName());
919     if (entryDN1Parameter != null)
920     {
921       String JavaDoc entryDN = entryDN1Parameter.getStringValue();
922       useDN1Range = true;
923       useDN1Sequential = false;
924
925       try
926       {
927         int openPos = entryDN.indexOf('[');
928         int dashPos = entryDN.indexOf('-', openPos);
929         if (dashPos < 0)
930         {
931           dashPos = entryDN.indexOf(':', openPos);
932           useDN1Sequential = true;
933         }
934         int closePos = entryDN.indexOf(']', dashPos);
935
936         dn1Initial = entryDN.substring(0, openPos);
937         dn1Final = entryDN.substring(closePos+1);
938
939         dn1RangeMin = Integer.parseInt(entryDN.substring(openPos+1, dashPos));
940         dn1RangeMax = Integer.parseInt(entryDN.substring(dashPos+1, closePos));
941         dn1RangeSpan = dn1RangeMax - dn1RangeMin + 1;
942         sequentialCounter1 = dn1RangeMin;
943       }
944       catch (Exception JavaDoc e)
945       {
946         useDN1Range = false;
947         dn1Initial = entryDN;
948       }
949     }
950
951     // Get the DN of the second entry to modify
952
entryDN2Parameter =
953          parameters.getStringParameter(entryDN2Parameter.getName());
954     if (entryDN2Parameter != null)
955     {
956       String JavaDoc entryDN = entryDN2Parameter.getStringValue();
957       useDN2Range = true;
958       useDN2Sequential = false;
959
960       try
961       {
962         int openPos = entryDN.indexOf('[');
963         int dashPos = entryDN.indexOf('-', openPos);
964         if (dashPos < 0)
965         {
966           dashPos = entryDN.indexOf(':', openPos);
967           useDN2Sequential = true;
968         }
969         int closePos = entryDN.indexOf(']', dashPos);
970
971         dn2Initial = entryDN.substring(0, openPos);
972         dn2Final = entryDN.substring(closePos+1);
973
974         dn2RangeMin = Integer.parseInt(entryDN.substring(openPos+1, dashPos));
975         dn2RangeMax = Integer.parseInt(entryDN.substring(dashPos+1, closePos));
976         dn2RangeSpan = dn2RangeMax - dn2RangeMin + 1;
977         sequentialCounter2 = dn2RangeMin;
978       }
979       catch (Exception JavaDoc e)
980       {
981         useDN2Range = false;
982         dn2Initial = entryDN;
983       }
984     }
985
986     // Get the weight to use when choosing between DN 1 and DN 2.
987
dn1Weight = 50;
988     weightParameter = parameters.getIntegerParameter(weightParameter.getName());
989     if (weightParameter != null)
990     {
991       dn1Weight = weightParameter.getIntValue();
992     }
993
994     // Get the attribute to modify.
995
attributeParameter =
996          parameters.getMultiLineTextParameter(attributeParameter.getName());
997     if (attributeParameter != null)
998     {
999       modifyAttrs = attributeParameter.getNonBlankLines();
1000    }
1001
1002    // Get the length to use in the modification.
1003
length = 80;
1004    lengthParameter =
1005         parameters.getIntegerParameter(lengthParameter.getName());
1006    if (lengthParameter != null)
1007    {
1008      length = lengthParameter.getIntValue();
1009    }
1010
1011    // Get the warm up time.
1012
warmUpTime = 0;
1013    warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName());
1014    if (warmUpParameter != null)
1015    {
1016      warmUpTime = warmUpParameter.getIntValue();
1017    }
1018
1019    // Get the cool down time.
1020
coolDownTime = 0;
1021    coolDownParameter =
1022         parameters.getIntegerParameter(coolDownParameter.getName());
1023    if (coolDownParameter != null)
1024    {
1025      coolDownTime = coolDownParameter.getIntValue();
1026    }
1027
1028    // Get the maximum modify time limit.
1029
timeLimit = 0;
1030    timeLimitParameter =
1031         parameters.getIntegerParameter(timeLimitParameter.getName());
1032    if (timeLimitParameter != null)
1033    {
1034      timeLimit = timeLimitParameter.getIntValue();
1035    }
1036
1037    // Get the delay between requests.
1038
delay = 0;
1039    delayParameter = parameters.getIntegerParameter(delayParameter.getName());
1040    if (delayParameter != null)
1041    {
1042      delay = delayParameter.getIntValue();
1043    }
1044
1045    // Get the number of iterations to perform
1046
iterations = -1;
1047    iterationsParameter =
1048         parameters.getIntegerParameter(iterationsParameter.getName());
1049    if (iterationsParameter != null)
1050    {
1051      iterations = iterationsParameter.getIntValue();
1052    }
1053
1054    // Get the flag indicating whether we should use SSL or not
1055
useSSL = false;
1056    useSSLParameter = parameters.getBooleanParameter(useSSLParameter.getName());
1057    if (useSSLParameter != null)
1058    {
1059      useSSL = useSSLParameter.getBooleanValue();
1060    }
1061
1062    // If we are to use SSL, then get all the other SSL-related info
1063
if (useSSL)
1064    {
1065      // Whether to blindly trust any SSL certificate
1066
blindTrustParameter =
1067           parameters.getBooleanParameter(blindTrustParameter.getName());
1068      if (blindTrustParameter != null)
1069      {
1070        blindTrust = blindTrustParameter.getBooleanValue();
1071      }
1072
1073      // The location of the JSSE key store
1074
sslKeyStore = null;
1075      keyStoreParameter =
1076           parameters.getStringParameter(keyStoreParameter.getName());
1077      if ((keyStoreParameter != null) && (keyStoreParameter.hasValue()))
1078      {
1079        sslKeyStore = keyStoreParameter.getStringValue();
1080        System.setProperty(SSL_KEY_STORE_PROPERTY, sslKeyStore);
1081      }
1082
1083      // The JSSE key store password
1084
sslKeyPassword = null;
1085      keyPWParameter =
1086           parameters.getPasswordParameter(keyPWParameter.getName());
1087      if ((keyPWParameter != null) && (keyPWParameter.hasValue()))
1088      {
1089        sslKeyPassword = keyPWParameter.getStringValue();
1090        System.setProperty(SSL_KEY_PASSWORD_PROPERTY, sslKeyPassword);
1091      }
1092
1093      // The location of the JSSE trust store
1094
sslTrustStore = null;
1095      trustStoreParameter =
1096           parameters.getStringParameter(trustStoreParameter.getName());
1097      if ((trustStoreParameter != null) && (trustStoreParameter.hasValue()))
1098      {
1099        sslTrustStore = trustStoreParameter.getStringValue();
1100        System.setProperty(SSL_TRUST_STORE_PROPERTY, sslTrustStore);
1101      }
1102
1103      // The JSSE trust store password
1104
sslTrustPassword = null;
1105      trustPWParameter =
1106           parameters.getPasswordParameter(trustPWParameter.getName());
1107      if ((trustPWParameter != null) && (trustPWParameter.hasValue()))
1108      {
1109        sslTrustPassword = trustPWParameter.getStringValue();
1110        System.setProperty(SSL_TRUST_PASSWORD_PROPERTY, sslTrustPassword);
1111      }
1112    }
1113
1114    // Get the flag indicating whether we should disconnect after each modify
1115
alwaysDisconnect = false;
1116    disconnectParameter =
1117         parameters.getBooleanParameter(disconnectParameter.getName());
1118    if (disconnectParameter != null)
1119    {
1120      alwaysDisconnect = disconnectParameter.getBooleanValue();
1121    }
1122
1123    // Get the flag indicating whether we should follow referrals
1124
followReferrals = false;
1125    followReferralsParameter =
1126         parameters.getBooleanParameter(followReferralsParameter.getName());
1127    if (followReferralsParameter != null)
1128    {
1129      followReferrals = followReferralsParameter.getBooleanValue();
1130    }
1131
1132
1133    // Initialize the parent random number generator
1134
parentRandom = new Random();
1135  }
1136
1137
1138
1139  /**
1140   * Initializes this job thread to be used to actually run the job on the
1141   * client. The provided parameter list should be processed to customize the
1142   * behavior of this job thread, and any other initialization that needs to be
1143   * done in order for the job to run should be performed here as well.
1144   *
1145   * @param clientID The client ID for this job thread.
1146   * @param threadID The thread ID for this job thread.
1147   * @param collectionInterval The length of time in seconds to use as the
1148   * statistics collection interval.
1149   * @param parameters The set of parameters provided to this job that
1150   * can be used to customize its behavior.
1151   *
1152   * @throws UnableToRunException If a problem occurs that prevents the thread
1153   * from being able to run properly.
1154   */

1155  public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
1156                               int collectionInterval, ParameterList parameters)
1157         throws UnableToRunException
1158  {
1159    // Set up the stat trackers
1160
modOverallCount = new IncrementalTracker(clientID, threadID,
1161                                             STAT_TRACKER_MOD_OVERALL_COUNT,
1162                                             collectionInterval);
1163    mod1Count = new IncrementalTracker(clientID, threadID,
1164                                       STAT_TRACKER_MOD_1_COUNT,
1165                                       collectionInterval);
1166    mod2Count = new IncrementalTracker(clientID, threadID,
1167                                       STAT_TRACKER_MOD_2_COUNT,
1168                                       collectionInterval);
1169    modOverallTime = new TimeTracker(clientID, threadID,
1170                                     STAT_TRACKER_MOD_OVERALL_TIME,
1171                                     collectionInterval);
1172    mod1Time = new TimeTracker(clientID, threadID, STAT_TRACKER_MOD_1_TIME,
1173                               collectionInterval);
1174    mod2Time = new TimeTracker(clientID, threadID, STAT_TRACKER_MOD_2_TIME,
1175                               collectionInterval);
1176    exceptionsCaught = new IncrementalTracker(clientID, threadID,
1177                                              STAT_TRACKER_EXCEPTIONS_CAUGHT,
1178                                              collectionInterval);
1179    modCategories = new CategoricalTracker(clientID, threadID,
1180                                           STAT_TRACKER_MOD_CATEGORIES,
1181                                           collectionInterval);
1182
1183
1184    // Enable real-time reporting of the data for these stat trackers.
1185
RealTimeStatReporter statReporter = getStatReporter();
1186    if (statReporter != null)
1187    {
1188      String JavaDoc jobID = getJobID();
1189      modOverallCount.enableRealTimeStats(statReporter, jobID);
1190      mod1Count.enableRealTimeStats(statReporter, jobID);
1191      mod2Count.enableRealTimeStats(statReporter, jobID);
1192      modOverallTime.enableRealTimeStats(statReporter, jobID);
1193      mod1Time.enableRealTimeStats(statReporter, jobID);
1194      mod2Time.enableRealTimeStats(statReporter, jobID);
1195      exceptionsCaught.enableRealTimeStats(statReporter, jobID);
1196    }
1197
1198
1199    // Initialize the random number generator for this thread.
1200
random = new Random(parentRandom.nextLong());
1201
1202
1203    // If the connection is to use SSL, then establish a preliminary connection
1204
// now. The first connection can take a significant amount of time to
1205
// establish, and we want to get it out of the way early before the timer
1206
// starts (if a duration is specified). Don't worry about any exceptions
1207
// that may get thrown here because there's no easy way to report them back
1208
// but they will be repeated and handled when the job starts running anyway,
1209
// so no big deal.
1210
if (useSSL)
1211    {
1212      try
1213      {
1214        LDAPConnection conn;
1215        if (blindTrust)
1216        {
1217          try
1218          {
1219            conn = new LDAPConnection(new JSSEBlindTrustSocketFactory());
1220          }
1221          catch (LDAPException le)
1222          {
1223            throw new UnableToRunException(le.getMessage(), le);
1224          }
1225        }
1226        else
1227        {
1228          conn = new LDAPConnection(new JSSESocketFactory(null));
1229        }
1230        conn.connect(3, ldapHost, ldapPort, bindDN, bindPassword);
1231        conn.disconnect();
1232      }
1233      catch (Exception JavaDoc e) {}
1234    }
1235  }
1236
1237
1238
1239  /**
1240   * Perform the work of this job thread by establishing the connection(s) to
1241   * the directory server and issuing all the appropriate queries. The job will
1242   * continue until the specified number of iterations have been performed, the
1243   * stop time has been reached, the maximum duration has been reached, or the
1244   * SLAMD server indicates that a stop has been requested.
1245   */

1246  public void runJob()
1247  {
1248    // Determine the range of time for which we should collect statistics.
1249
long currentTime = System.currentTimeMillis();
1250    boolean collectingStats = false;
1251    long startCollectingTime = currentTime + (1000 * warmUpTime);
1252    long stopCollectingTime = Long.MAX_VALUE;
1253    if ((coolDownTime > 0) && (getShouldStopTime() > 0))
1254    {
1255      stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime);
1256    }
1257
1258    // Set a variable that we can use to determine if the connection is alive or
1259
// not
1260
boolean connected = false;
1261
1262    // Set a variable that can be used to determine how long we should sleep
1263
// between modifications.
1264
long modStartTime = 0;
1265
1266    // First, see if this should operate "infinitely" (i.e., not a fixed number
1267
// of iterations
1268
boolean infinite = (iterations <= 0);
1269
1270    // Create a variable that we will use for the LDAP connection
1271
if (useSSL)
1272    {
1273      if (blindTrust)
1274      {
1275        try
1276        {
1277          conn = new LDAPConnection(new JSSEBlindTrustSocketFactory());
1278        }
1279        catch (LDAPException le)
1280        {
1281          logMessage(le.getMessage());
1282          indicateStoppedDueToError();
1283          return;
1284        }
1285      }
1286      else
1287      {
1288        conn = new LDAPConnection(new JSSESocketFactory(null));
1289      }
1290    }
1291    else
1292    {
1293      conn = new LDAPConnection();
1294    }
1295
1296
1297    // Create a loop that will run until it needs to stop
1298
for (int i=0; ((! shouldStop()) && ((infinite || (i < iterations)))); i++)
1299    {
1300      currentTime = System.currentTimeMillis();
1301      if ((! collectingStats) && (currentTime >= startCollectingTime) &&
1302          (currentTime < stopCollectingTime))
1303      {
1304        // Tell the stat trackers that they should start tracking now
1305
modOverallCount.startTracker();
1306        mod1Count.startTracker();
1307        mod2Count.startTracker();
1308        modOverallTime.startTracker();
1309        mod1Time.startTracker();
1310        mod2Time.startTracker();
1311        exceptionsCaught.startTracker();
1312        modCategories.startTracker();
1313        collectingStats = true;
1314      }
1315      else if ((collectingStats) && (currentTime >= stopCollectingTime))
1316      {
1317        modOverallCount.stopTracker();
1318        mod1Count.stopTracker();
1319        mod2Count.stopTracker();
1320        modOverallTime.stopTracker();
1321        mod1Time.stopTracker();
1322        mod2Time.stopTracker();
1323        exceptionsCaught.stopTracker();
1324        modCategories.stopTracker();
1325        collectingStats = false;
1326      }
1327
1328      // If the connection is currently not connected, then establish it
1329
if (! connected)
1330      {
1331        try
1332        {
1333          conn.connect(3, ldapHost, ldapPort, bindDN, bindPassword);
1334          connected = true;
1335        }
1336        catch (LDAPException le)
1337        {
1338          logMessage("ERROR -- Could not connect to " + ldapHost + ":" +
1339                           ldapPort + " (" + le + ") -- aborting thread");
1340          if (collectingStats)
1341          {
1342            exceptionsCaught.increment();
1343          }
1344          indicateStoppedDueToError();
1345          break;
1346        }
1347      }
1348
1349      LDAPConstraints constraints = conn.getConstraints();
1350      if (useProxyAuth)
1351      {
1352        LDAPProxiedAuthControl proxyAuthControl =
1353             new LDAPProxiedAuthControl(proxyAsDN, true);
1354        constraints.setServerControls(proxyAuthControl);
1355        constraints.setTimeLimit(1000 * timeLimit);
1356        constraints.setReferrals(followReferrals);
1357        constraints.setRebindProc(this);
1358      }
1359
1360
1361      // Create a flag used to determine if the modification was successful.
1362
boolean successfulMod = false;
1363
1364
1365      // Determine which modification we need to perform.
1366
int randVal = (random.nextInt() & 0x7FFFFFFF) % 100;
1367      if (randVal < dn1Weight)
1368      {
1369        // Record the current time as the start of the modify
1370
if (collectingStats)
1371        {
1372          modOverallTime.startTimer();
1373          mod1Time.startTimer();
1374        }
1375        if (delay > 0)
1376        {
1377          modStartTime = System.currentTimeMillis();
1378        }
1379
1380
1381        // Perform the modification.
1382
try
1383        {
1384          String JavaDoc attrValue = getRandomString(length);
1385          LDAPModification[] mods = new LDAPModification[modifyAttrs.length];
1386          for (int j=0; j < modifyAttrs.length; j++)
1387          {
1388            LDAPAttribute attr = new LDAPAttribute(modifyAttrs[j], attrValue);
1389            mods[j] = new LDAPModification(LDAPModification.REPLACE, attr);
1390          }
1391          conn.modify(getRandomDN1(), mods, constraints);
1392          successfulMod = true;
1393        }
1394        catch (LDAPException le)
1395        {
1396          writeVerbose("ERROR while performing modification -- " + le);
1397          if (collectingStats)
1398          {
1399            exceptionsCaught.increment();
1400          }
1401          indicateCompletedWithErrors();
1402        }
1403
1404
1405        // Record the current time as the end of the modification
1406
if (collectingStats)
1407        {
1408          modOverallTime.stopTimer();
1409          mod1Time.stopTimer();
1410        }
1411
1412
1413        // Update the appropriate status counters
1414
if (successfulMod && collectingStats)
1415        {
1416          modOverallCount.increment();
1417          mod1Count.increment();
1418          modCategories.increment("DN 1");
1419        }
1420      }
1421      else
1422      {
1423        // Record the current time as the start of the modify
1424
if (collectingStats)
1425        {
1426          modOverallTime.startTimer();
1427          mod2Time.startTimer();
1428        }
1429        if (delay > 0)
1430        {
1431          modStartTime = System.currentTimeMillis();
1432        }
1433
1434
1435        // Perform the modification.
1436
try
1437        {
1438          String JavaDoc attrValue = getRandomString(length);
1439          LDAPModification[] mods = new LDAPModification[modifyAttrs.length];
1440          for (int j=0; j < modifyAttrs.length; j++)
1441          {
1442            LDAPAttribute attr = new LDAPAttribute(modifyAttrs[j], attrValue);
1443            mods[j] = new LDAPModification(LDAPModification.REPLACE, attr);
1444          }
1445          conn.modify(getRandomDN2(), mods, constraints);
1446          successfulMod = true;
1447        }
1448        catch (LDAPException le)
1449        {
1450          writeVerbose("ERROR while performing modification -- " + le);
1451          if (collectingStats)
1452          {
1453            exceptionsCaught.increment();
1454          }
1455          indicateCompletedWithErrors();
1456        }
1457
1458
1459        // Record the current time as the end of the modification
1460
if (collectingStats)
1461        {
1462          modOverallTime.stopTimer();
1463          mod2Time.stopTimer();
1464        }
1465
1466
1467        // Update the appropriate status counters
1468
if (successfulMod && collectingStats)
1469        {
1470          modOverallCount.increment();
1471          mod2Count.increment();
1472          modCategories.increment("DN 2");
1473        }
1474      }
1475
1476      // If the connection should be broken, then do so
1477
if (alwaysDisconnect)
1478      {
1479        try
1480        {
1481          conn.disconnect();
1482        } catch (LDAPException le) {}
1483        connected = false;
1484      }
1485
1486      // If we need to sleep, then do so
1487
if ((delay > 0) && (! shouldStop()))
1488      {
1489        long now = System.currentTimeMillis();
1490        long sleepTime = delay - (now - modStartTime);
1491        if (sleepTime > 0)
1492        {
1493          try
1494          {
1495            Thread.sleep(sleepTime);
1496          } catch (InterruptedException JavaDoc ie) {}
1497        }
1498      }
1499    }
1500
1501
1502    // If the connection is still established, then close it
1503
try
1504    {
1505      conn.disconnect();
1506    } catch (LDAPException le) {}
1507
1508
1509    // Tell the stat trackers that they should stop tracking
1510
if (collectingStats)
1511    {
1512      modOverallCount.stopTracker();
1513      mod1Count.stopTracker();
1514      mod2Count.stopTracker();
1515      modOverallTime.stopTracker();
1516      mod1Time.stopTracker();
1517      mod2Time.stopTracker();
1518      exceptionsCaught.stopTracker();
1519      modCategories.stopTracker();
1520    }
1521  }
1522
1523
1524
1525  /**
1526   * Attempts to force this thread to exit by closing the connection to the
1527   * directory server and setting it to <CODE>null</CODE>.
1528   */

1529  public void destroy()
1530  {
1531    if (conn != null)
1532    {
1533      try
1534      {
1535        conn.disconnect();
1536      } catch (Exception JavaDoc e) {}
1537
1538      conn = null;
1539    }
1540  }
1541
1542
1543
1544  /**
1545   * Specifies the credentials that will be used to bind to the target server if
1546   * a referral is encountered. In this case, we will always attempt the bind
1547   * using the same credentials used to bind to the original target.
1548   *
1549   * @param host The address of the directory server targeted by the referral.
1550   * @param port The port of the directory server targeted by the referral.
1551   *
1552   * @return The credentials that will be used to bind to the server targeted
1553   * by the referral.
1554   */

1555  public LDAPRebindAuth getRebindAuthentication(String JavaDoc host, int port)
1556  {
1557    return new LDAPRebindAuth(bindDN, bindPassword);
1558  }
1559
1560
1561
1562  /**
1563   * Retrieves a random DN from the list of DNs that can be modified.
1564   *
1565   * @return A randomly-chosen DN of an entry to modify.
1566   */

1567  public String JavaDoc getRandomDN1()
1568  {
1569    if (useDN1Range)
1570    {
1571      int value;
1572      if (useDN1Sequential)
1573      {
1574        value = sequentialCounter1++;
1575        if (sequentialCounter1 > dn1RangeMax)
1576        {
1577          sequentialCounter1 = dn1RangeMin;
1578        }
1579      }
1580      else
1581      {
1582        value = ((random.nextInt() & 0x7FFFFFFF) % dn1RangeSpan) +
1583                dn1RangeMin;
1584      }
1585      return dn1Initial + value + dn1Final;
1586    }
1587    else
1588    {
1589      return dn1Initial;
1590    }
1591  }
1592
1593
1594
1595  /**
1596   * Retrieves a random DN from the list of DNs that can be modified.
1597   *
1598   * @return A randomly-chosen DN of an entry to modify.
1599   */

1600  public String JavaDoc getRandomDN2()
1601  {
1602    if (useDN2Range)
1603    {
1604      int value;
1605      if (useDN2Sequential)
1606      {
1607        value = sequentialCounter2++;
1608        if (sequentialCounter2 > dn1RangeMax)
1609        {
1610          sequentialCounter2 = dn1RangeMin;
1611        }
1612      }
1613      else
1614      {
1615        value = ((random.nextInt() & 0x7FFFFFFF) % dn2RangeSpan) +
1616                dn2RangeMin;
1617      }
1618      return dn2Initial + value + dn2Final;
1619    }
1620    else
1621    {
1622      return dn2Initial;
1623    }
1624  }
1625
1626
1627
1628  /**
1629   * Retrieves a string containing the specified number of randomly-chosen
1630   * characters.
1631   *
1632   * @param length The number of characters to include in the string.
1633   *
1634   * @return A string containing the specified number of randomly-chosen
1635   * characters.
1636   */

1637  public String JavaDoc getRandomString(int length)
1638  {
1639    char[] returnChars = new char[length];
1640
1641    for (int i=0; i < length; i++)
1642    {
1643      returnChars[i] = ALPHABET[Math.abs((random.nextInt()) & 0x7FFFFFFF) %
1644                                ALPHABET.length];
1645    }
1646
1647    return new String JavaDoc(returnChars);
1648  }
1649}
1650
1651
Popular Tags