KickJava   Java API By Example, From Geeks To Geeks.

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


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.net.*;
22 import java.util.*;
23 import com.sun.slamd.job.*;
24 import com.sun.slamd.parameter.*;
25 import com.sun.slamd.stat.*;
26
27
28
29 /**
30  * This class defines a SLAMD job that interacts with a POP3 mail server. It
31  * does so by performing the following operations:
32  *
33  * <OL>
34  * <LI>Send the user name (<CODE>USER </CODE><I>{user}</I>).</LI>
35  * <LI>Send the password (<CODE>PASS </CODE><I>{password}</I>).</LI>
36  * <LI>Retrieve a list of all messages (<CODE>LIST</CODE>).</LI>
37  * <LI>Log out (<CODE>QUIT</CODE>).</LI>
38  * </OL>
39  *
40  *
41  * @author Neil A. Wilson
42  */

43 public class POPCheckRateJobClass
44        extends JobClass
45 {
46   /**
47    * The display name of the stat tracker used to count the number of POP
48    * sessions established.
49    */

50   public static final String JavaDoc STAT_TRACKER_POP_SESSIONS = "POP Sessions";
51
52
53
54   /**
55    * The display name of the stat tracker used to count the number of failed
56    * POP logins.
57    */

58   public static final String JavaDoc STAT_TRACKER_FAILURE_COUNT = "Failed Logins";
59
60
61
62   /**
63    * The display name of the stat tracker used to keep track of the number of
64    * messages contained in the inbox for each POP session.
65    */

66   public static final String JavaDoc STAT_TRACKER_MESSAGE_COUNT = "Message Count";
67
68
69
70   /**
71    * The display name of the stat tracker used to time the process of
72    * authenticating and retrieving the list of messages.
73    */

74   public static final String JavaDoc STAT_TRACKER_SESSION_DURATION =
75        "Session Duration (ms)";
76
77
78
79   /**
80    * The display name of the stat tracker used to count the number of successful
81    * POP logins.
82    */

83   public static final String JavaDoc STAT_TRACKER_SUCCESS_COUNT = "Successful Logins";
84
85
86
87   // The port number of the POP server.
88
IntegerParameter portParameter =
89        new IntegerParameter("pop_port", "POP Server Port",
90                             "The port number on which the POP server is " +
91                             "listening for requests.", true, 110, true, 1, true,
92                             65535);
93
94   // The length of time between initial requests.
95
IntegerParameter delayParameter =
96        new IntegerParameter("delay", "Time Between POP Sessions (ms)",
97                             "The length of time in milliseconds between " +
98                             "attempts to access the POP server.",
99                             true, 0, true, 0, false, 0);
100
101   // The password to use when authenticating.
102
PasswordParameter passwordParameter =
103        new PasswordParameter("user_pw", "User Password",
104                              "The password that will be used to authenticate " +
105                              "to the POP server.", true, "");
106
107   // A placeholder parameter that is only used for formatting.
108
PlaceholderParameter placeholder = new PlaceholderParameter();
109
110   // The address of the POP server.
111
StringParameter hostParameter =
112        new StringParameter("pop_host", "POP Server Address",
113                            "The fully-qualified domain name or IP address of " +
114                            "the system running the POP server.", true, "");
115
116   // The user ID to use when authenticating.
117
StringParameter userIDParameter =
118        new StringParameter("user_id", "User ID",
119                            "The user ID that will be used to authenticate to " +
120                            "the POP server. It may include a range of " +
121                            "numeric values chosen randomly by including " +
122                            "that range in brackets with the values separated " +
123                            "by a dash (i.e., \"user.[1-1000]\"), or a range " +
124                            "of sequentially-incrementing numeric values by " +
125                            "including that range in brackets with the values " +
126                            "separated by a colon (i.e., \"user.[1:1000]\").",
127                            true, "");
128
129
130
131   // Static variables used to hold parameter values.
132
static boolean useIDRange;
133   static boolean useSequentialID;
134   static int popPort;
135   static int delay;
136   static int nextSequentialID;
137   static int idRangeMax;
138   static int idRangeMin;
139   static int idRangeSpan;
140   static String JavaDoc popAddress;
141   static String JavaDoc password;
142   static String JavaDoc userIDInitial;
143   static String JavaDoc userIDFinal;
144
145
146   // The random number generator for the job.
147
static Random parentRandom;
148   Random random;
149
150
151
152   // The stat trackers for the job.
153
IncrementalTracker failureCounter;
154   IncrementalTracker sessionCounter;
155   IncrementalTracker successCounter;
156   IntegerValueTracker messageCountTracker;
157   TimeTracker sessionTimer;
158
159
160
161
162   /**
163    * The default constructor used to create a new instance of the job class.
164    * The only thing it should do is to invoke the superclass constructor. All
165    * other initialization should be performed in the <CODE>initialize</CODE>
166    * method.
167    */

168   public POPCheckRateJobClass()
169   {
170     super();
171   }
172
173
174
175   /**
176    * Retrieves the name of the job performed by this job thread.
177    *
178    * @return The name of the job performed by this job thread.
179    */

180   public String JavaDoc getJobName()
181   {
182     return "POP CheckRate";
183   }
184
185
186
187   /**
188    * Retrieves a description of the job performed by this job thread.
189    *
190    * @return A description of the job performed by this job thread.
191    */

192   public String JavaDoc getJobDescription()
193   {
194     return "This job can be used to repeatedly establish sessions with a " +
195            "POP3 mail server and retrieve information about messages in " +
196            "the user's inbox";
197   }
198
199
200
201   /**
202    * Retrieves the name of the category in which this job class exists. This is
203    * used to help arrange the job classes in the administrative interface.
204    *
205    * @return The name of the category in which this job class exists.
206    */

207   public String JavaDoc getJobCategoryName()
208   {
209     return "Mail";
210   }
211
212
213
214   /**
215    * Retrieve a parameter list that can be used to determine all of the
216    * customizeable options that are available for this job.
217    *
218    * @return A parameter list that can be used to determine all of the
219    * customizeable options that are available for this job.
220    */

221   public ParameterList getParameterStubs()
222   {
223     Parameter[] parameters =
224     {
225       placeholder,
226       hostParameter,
227       portParameter,
228       userIDParameter,
229       passwordParameter,
230       delayParameter
231     };
232
233     return new ParameterList(parameters);
234   }
235
236
237
238   /**
239    * Retrieves the set of stat trackers that will be maintained by this job
240    * class. The stat trackers returned by this method do not have to actually
241    * contain any statistics -- the display name and stat tracker class should
242    * be the only information that callers of this method should rely upon. Note
243    * that this list can be different from the list of statistics actually
244    * collected by the job in some cases (e.g., if the job may not return all the
245    * stat trackers it advertises in all cases, or if the job may return stat
246    * trackers that it did not advertise), but it is a possibility that only the
247    * stat trackers returned by this method will be accessible for some features
248    * in the SLAMD server.
249    *
250    * @param clientID The client ID that should be used for the
251    * returned stat trackers.
252    * @param threadID The thread ID that should be used for the
253    * returned stat trackers.
254    * @param collectionInterval The collection interval that should be used for
255    * the returned stat trackers.
256    *
257    * @return The set of stat trackers that will be maintained by this job
258    * class.
259    */

260   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
261                                            int collectionInterval)
262   {
263     return new StatTracker[]
264     {
265       new IncrementalTracker(clientID, threadID, STAT_TRACKER_POP_SESSIONS,
266                              collectionInterval),
267       new TimeTracker(clientID, threadID, STAT_TRACKER_SESSION_DURATION,
268                       collectionInterval),
269       new IntegerValueTracker(clientID, threadID, STAT_TRACKER_MESSAGE_COUNT,
270                               collectionInterval),
271       new IncrementalTracker(clientID, threadID, STAT_TRACKER_SUCCESS_COUNT,
272                              collectionInterval),
273       new IncrementalTracker(clientID, threadID, STAT_TRACKER_FAILURE_COUNT,
274                              collectionInterval)
275     };
276   }
277
278
279
280   /**
281    * Retrieves the stat trackers that are maintained for this job thread.
282    *
283    * @return The stat trackers that are maintained for this job thread.
284    */

285   public StatTracker[] getStatTrackers()
286   {
287     return new StatTracker[]
288     {
289       sessionCounter,
290       sessionTimer,
291       messageCountTracker,
292       successCounter,
293       failureCounter
294     };
295   }
296
297
298
299   /**
300    * Indicates whether this job class implements logic that makes it possible to
301    * test the validity of job parameters before scheduling the job for execution
302    * (e.g., to see if the server is reachable using the information provided).
303    *
304    * @return <CODE>true</CODE> if this job provides a means of testing the job
305    * parameters, or <CODE>false</CODE> if not.
306    */

307   public boolean providesParameterTest()
308   {
309     return true;
310   }
311
312
313
314   /**
315    * Provides a means of testing the provided job parameters to determine
316    * whether they are valid (e.g., to see if the server is reachable) before
317    * scheduling the job for execution. This method will be executed by the
318    * SLAMD server system itself and not by any of the clients.
319    *
320    * @param parameters The job parameters to be tested.
321    * @param outputMessages The lines of output that were generated as part of
322    * the testing process. Each line of output should
323    * be added to this list as a separate string, and
324    * empty strings (but not <CODE>null</CODE> values)
325    * are allowed to provide separation between
326    * different messages. No formatting should be
327    * provided for these messages, however, since they
328    * may be displayed in either an HTML or plain text
329    * interface.
330    *
331    * @return <CODE>true</CODE> if the test completed successfully, or
332    * <CODE>false</CODE> if not. Note that even if the test did not
333    * complete successfully, the user will be presented with a warning
334    * but will still be allowed to schedule the job using the provided
335    * parameters. This is necessary because the parameters may still be
336    * valid even if the server couldn't validate them at the time the
337    * job was scheduled (e.g., if the server wasn't running or could not
338    * be reached by the SLAMD server even though it could be by the
339    * clients).
340    */

341   public boolean testJobParameters(ParameterList parameters,
342                                    ArrayList outputMessages)
343   {
344     // Get the parameters necessary to perform the test.
345
StringParameter hostParam =
346          parameters.getStringParameter(hostParameter.getName());
347     if ((hostParam == null) || (! hostParam.hasValue()))
348     {
349       outputMessages.add("ERROR: No POP server address was provided.");
350       return false;
351     }
352     String JavaDoc host = hostParam.getStringValue();
353
354
355     IntegerParameter portParam =
356          parameters.getIntegerParameter(portParameter.getName());
357     if ((portParam == null) || (! portParam.hasValue()))
358     {
359       outputMessages.add("ERROR: No POP server port was provided.");
360       return false;
361     }
362     int port = portParam.getIntValue();
363
364
365     StringParameter userIDParam =
366          parameters.getStringParameter(userIDParameter.getName());
367     if ((userIDParam == null) || (! userIDParam.hasValue()))
368     {
369       outputMessages.add("ERROR: No user ID was provided.");
370       return false;
371     }
372     String JavaDoc userID = userIDParam.getStringValue();
373
374
375     PasswordParameter pwParam =
376          parameters.getPasswordParameter(passwordParameter.getName());
377     if ((pwParam == null) || (! pwParam.hasValue()))
378     {
379       outputMessages.add("ERROR: No user password was provided.");
380       return false;
381     }
382     String JavaDoc userPW = pwParam.getStringValue();
383
384
385     // Try to establish a connection to the POP server.
386
Socket socket;
387     BufferedReader reader;
388     BufferedWriter writer;
389     try
390     {
391       outputMessages.add("Trying to establish a connection to POP server " +
392                          host + ":" + port + "....");
393
394       socket = new Socket(host, port);
395       reader = new BufferedReader(new InputStreamReader(
396                                            socket.getInputStream()));
397       writer = new BufferedWriter(new OutputStreamWriter(
398                                            socket.getOutputStream()));
399
400       outputMessages.add("Connected successfully.");
401       outputMessages.add("");
402     }
403     catch (Exception JavaDoc e)
404     {
405       outputMessages.add("ERROR: Unable to connect: " +
406                          stackTraceToString(e));
407       return false;
408     }
409
410
411     // Read the initial response line from the server.
412
try
413     {
414       outputMessages.add("Trying to read the hello string from the server....");
415
416       String JavaDoc line = reader.readLine();
417
418       outputMessages.add("Hello string was '" + line + "'.");
419       outputMessages.add("");
420     }
421     catch (Exception JavaDoc e)
422     {
423       outputMessages.add("ERROR: Unable to read the hello string: " +
424                          stackTraceToString(e));
425
426       try
427       {
428         reader.close();
429       } catch (Exception JavaDoc e2) {}
430
431       try
432       {
433         writer.close();
434       } catch (Exception JavaDoc e2) {}
435
436       try
437       {
438         socket.close();
439       } catch (Exception JavaDoc e2) {}
440
441       return false;
442     }
443
444
445     // Send the user request.
446
try
447     {
448       outputMessages.add("Trying to send the USER request to the server....");
449
450       writer.write("USER " + userID);
451       writer.newLine();
452       writer.flush();
453
454       outputMessages.add("Successfully sent the USER request.");
455       outputMessages.add("");
456     }
457     catch (Exception JavaDoc e)
458     {
459       outputMessages.add("ERROR: Unable to send the USER request: " +
460                          stackTraceToString(e));
461
462       try
463       {
464         reader.close();
465       } catch (Exception JavaDoc e2) {}
466
467       try
468       {
469         writer.close();
470       } catch (Exception JavaDoc e2) {}
471
472       try
473       {
474         socket.close();
475       } catch (Exception JavaDoc e2) {}
476
477       return false;
478     }
479
480
481     // Read the user response.
482
boolean loginSuccessful = false;
483     try
484     {
485       outputMessages.add("Trying to read the USER response from the " +
486                          "server....");
487
488       String JavaDoc line = reader.readLine();
489       if (line.startsWith("+"))
490       {
491         loginSuccessful = true;
492       }
493
494       outputMessages.add("Read a USER response of '" + line + "'.");
495       outputMessages.add("");
496     }
497     catch (Exception JavaDoc e)
498     {
499       outputMessages.add("ERROR: Unable to read the USER response: " +
500                          stackTraceToString(e));
501
502       try
503       {
504         reader.close();
505       } catch (Exception JavaDoc e2) {}
506
507       try
508       {
509         writer.close();
510       } catch (Exception JavaDoc e2) {}
511
512       try
513       {
514         socket.close();
515       } catch (Exception JavaDoc e2) {}
516
517       return false;
518     }
519
520
521     // Send the pass request.
522
if (loginSuccessful)
523     {
524       try
525       {
526         outputMessages.add("Trying to send the PASS request to the server....");
527
528         writer.write("PASS " + userPW);
529         writer.newLine();
530         writer.flush();
531
532         outputMessages.add("Successfully sent the PASS request.");
533         outputMessages.add("");
534       }
535       catch (Exception JavaDoc e)
536       {
537         outputMessages.add("ERROR: Unable to send the PASS request: " +
538                            stackTraceToString(e));
539
540         try
541         {
542           reader.close();
543         } catch (Exception JavaDoc e2) {}
544
545         try
546         {
547           writer.close();
548         } catch (Exception JavaDoc e2) {}
549
550         try
551         {
552           socket.close();
553         } catch (Exception JavaDoc e2) {}
554
555         return false;
556       }
557
558
559       // Read the pass response.
560
loginSuccessful = false;
561       try
562       {
563         outputMessages.add("Trying to read the PASS response from the " +
564                            "server....");
565
566         String JavaDoc line = reader.readLine();
567         if (line.startsWith("+"))
568         {
569           loginSuccessful = true;
570         }
571
572         outputMessages.add("Read a PASS response of '" + line + "'.");
573         outputMessages.add("");
574       }
575       catch (Exception JavaDoc e)
576       {
577         outputMessages.add("ERROR: Unable to read the PASS response: " +
578                            stackTraceToString(e));
579
580         try
581         {
582           reader.close();
583         } catch (Exception JavaDoc e2) {}
584
585         try
586         {
587           writer.close();
588         } catch (Exception JavaDoc e2) {}
589
590         try
591         {
592           socket.close();
593         } catch (Exception JavaDoc e2) {}
594
595         return false;
596       }
597     }
598
599
600     // If we've gotten here, then everything seems to be OK. Close the
601
// connection and return whether the login was successful.
602
try
603     {
604       outputMessages.add("Sending the QUIT request to the server.");
605       outputMessages.add("");
606
607       writer.write("QUIT");
608       writer.newLine();
609       writer.flush();
610     } catch (Exception JavaDoc e) {}
611
612     try
613     {
614       reader.close();
615     } catch (Exception JavaDoc e) {}
616
617     try
618     {
619       writer.close();
620     } catch (Exception JavaDoc e) {}
621
622     try
623     {
624       socket.close();
625     } catch (Exception JavaDoc e) {}
626
627
628     outputMessages.add("All tests completed.");
629     return loginSuccessful;
630   }
631
632
633
634   /**
635    * Performs initialization for this job on each client immediately before each
636    * thread is created to actually run the job.
637    *
638    * @param clientID The ID assigned to the client running this job.
639    * @param parameters The set of parameters provided to this job that can be
640    * used to customize its behavior.
641    *
642    * @throws UnableToRunException If the client initialization could not be
643    * completed successfully and the job is unable
644    * to run.
645    */

646   public void initializeClient(String JavaDoc clientID, ParameterList parameters)
647          throws UnableToRunException
648   {
649     // Get the address of the POP server.
650
hostParameter = parameters.getStringParameter(hostParameter.getName());
651     if (hostParameter != null)
652     {
653       popAddress = hostParameter.getStringValue();
654     }
655
656     // Get the port for the POP server.
657
portParameter = parameters.getIntegerParameter(portParameter.getName());
658     if (portParameter != null)
659     {
660       popPort = portParameter.getIntValue();
661     }
662
663     // Get the user ID. See if it should be a range of values.
664
useIDRange = false;
665     useSequentialID = false;
666     userIDParameter = parameters.getStringParameter(userIDParameter.getName());
667     if (userIDParameter != null)
668     {
669       String JavaDoc value = userIDParameter.getStringValue();
670       int openPos = value.indexOf('[');
671       if (openPos < 0)
672       {
673         userIDInitial = value;
674       }
675       else
676       {
677         int closePos = value.indexOf(']', openPos);
678         if (closePos > 0)
679         {
680           int dashPos = value.indexOf('-', openPos);
681           if ((dashPos > 0) && (dashPos < closePos))
682           {
683             useIDRange = true;
684             idRangeMin = Integer.parseInt(value.substring(openPos+1, dashPos));
685             idRangeMax = Integer.parseInt(value.substring(dashPos+1, closePos));
686             idRangeSpan = idRangeMax - idRangeMin + 1;
687             userIDInitial = value.substring(0, openPos);
688             userIDFinal = value.substring(closePos+1);
689           }
690           else
691           {
692             dashPos = value.indexOf(':', openPos);
693             if ((dashPos > 0) && (dashPos < closePos))
694             {
695               useIDRange = true;
696               useSequentialID = true;
697               idRangeMin = Integer.parseInt(value.substring(openPos+1,
698                                                             dashPos));
699               idRangeMax = Integer.parseInt(value.substring(dashPos+1,
700                                                             closePos));
701               userIDInitial = value.substring(0, openPos);
702               userIDFinal = value.substring(closePos+1);
703               nextSequentialID = idRangeMin;
704             }
705             else
706             {
707               userIDInitial = value;
708             }
709           }
710         }
711         else
712         {
713           userIDInitial = value;
714         }
715       }
716     }
717
718     // Get the password.
719
passwordParameter =
720          parameters.getPasswordParameter(passwordParameter.getName());
721     if (passwordParameter != null)
722     {
723       password = passwordParameter.getStringValue();
724     }
725
726
727     // Get the delay between requests.
728
delayParameter = parameters.getIntegerParameter(delayParameter.getName());
729     if (delayParameter != null)
730     {
731       delay = delayParameter.getIntValue();
732     }
733
734
735     // Seed the parent random number generator.
736
parentRandom = new Random();
737   }
738
739
740
741   /**
742    * Initializes this job thread to be used to actually run the job on the
743    * client. The provided parameter list should be processed to customize the
744    * behavior of this job thread, and any other initialization that needs to be
745    * done in order for the job to run should be performed here as well.
746    *
747    * @param clientID The client ID for this job thread.
748    * @param threadID The thread ID for this job thread.
749    * @param collectionInterval The length of time in seconds to use as the
750    * statistics collection interval.
751    * @param parameters The set of parameters provided to this job that
752    * can be used to customize its behavior.
753    *
754    * @throws UnableToRunException If a problem occurs that prevents the thread
755    * from being able to run properly.
756    */

757   public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
758                                int collectionInterval, ParameterList parameters)
759          throws UnableToRunException
760   {
761     // Create the stat trackers for this thread.
762
sessionCounter = new IncrementalTracker(clientID, threadID,
763                                             STAT_TRACKER_POP_SESSIONS,
764                                             collectionInterval);
765     sessionTimer = new TimeTracker(clientID, threadID,
766                                    STAT_TRACKER_SESSION_DURATION,
767                                    collectionInterval);
768     messageCountTracker = new IntegerValueTracker(clientID, threadID,
769                                                   STAT_TRACKER_MESSAGE_COUNT,
770                                                   collectionInterval);
771     successCounter = new IncrementalTracker(clientID, threadID,
772                                             STAT_TRACKER_SUCCESS_COUNT,
773                                             collectionInterval);
774     failureCounter = new IncrementalTracker(clientID, threadID,
775                                             STAT_TRACKER_FAILURE_COUNT,
776                                             collectionInterval);
777
778
779     // Enable real-time reporting of the data for these stat trackers.
780
RealTimeStatReporter statReporter = getStatReporter();
781     if (statReporter != null)
782     {
783       String JavaDoc jobID = getJobID();
784       sessionCounter.enableRealTimeStats(statReporter, jobID);
785       sessionTimer.enableRealTimeStats(statReporter, jobID);
786       messageCountTracker.enableRealTimeStats(statReporter, jobID);
787       successCounter.enableRealTimeStats(statReporter, jobID);
788       failureCounter.enableRealTimeStats(statReporter, jobID);
789     }
790
791
792     // Seed the random number generator for this thread.
793
random = new Random(parentRandom.nextLong());
794   }
795
796
797
798   /**
799    * Perform the work of this job thread by executing the specified command.
800    */

801   public void runJob()
802   {
803     // Define variables that will be used throughout this method.
804
boolean keepReading;
805     BufferedReader reader;
806     BufferedWriter writer;
807     int highestUID;
808     long lastStartTime = 0;
809     Socket socket;
810     String JavaDoc line;
811     String JavaDoc lastLine;
812     String JavaDoc request;
813     String JavaDoc userID;
814
815
816     // Start the stat trackers.
817
sessionCounter.startTracker();
818     sessionTimer.startTracker();
819     messageCountTracker.startTracker();
820     successCounter.startTracker();
821     failureCounter.startTracker();
822
823
824     // Loop until it is determined that the job should stop.
825
mainLoop:
826     while (! shouldStop())
827     {
828       // If we need to sleep, then do so.
829
if (delay > 0)
830       {
831         long now = System.currentTimeMillis();
832         long prevTestTime = now - lastStartTime;
833         if (prevTestTime < delay)
834         {
835           try
836           {
837             Thread.sleep(delay - prevTestTime);
838           } catch (Exception JavaDoc e) {}
839         }
840       }
841
842       lastStartTime = System.currentTimeMillis();
843
844       // Start the attempt timer and indicate the beginning of a new attempt.
845
sessionCounter.increment();
846       sessionTimer.startTimer();
847
848
849       // Get the user ID to use in the next request.
850
userID = getUserID();
851
852
853       // Open a connection to the POP server.
854
try
855       {
856         socket = new Socket(popAddress, popPort);
857         reader = new BufferedReader(new InputStreamReader(
858                                              socket.getInputStream()));
859         writer = new BufferedWriter(new OutputStreamWriter(
860                                              socket.getOutputStream()));
861       }
862       catch (IOException ioe)
863       {
864         sessionTimer.stopTimer();
865         failureCounter.increment();
866         continue;
867       }
868
869
870       // Read the initial hello line from the server.
871
try
872       {
873         line = reader.readLine();
874       }
875       catch (IOException ioe)
876       {
877         sessionTimer.stopTimer();
878         failureCounter.increment();
879
880         try
881         {
882           reader.close();
883           writer.close();
884           socket.close();
885         } catch (Exception JavaDoc e) {}
886
887         continue;
888       }
889
890       // Send the user name.
891
request = "USER " + userID;
892       try
893       {
894         writer.write(request);
895         writer.newLine();
896         writer.flush();
897       }
898       catch (IOException ioe)
899       {
900         sessionTimer.stopTimer();
901         failureCounter.increment();
902
903         try
904         {
905           reader.close();
906           writer.close();
907           socket.close();
908         } catch (Exception JavaDoc e) {}
909
910         continue;
911       }
912
913
914       // Read the USER response. It must be a single line.
915
try
916       {
917         line = reader.readLine();
918         if (line == null)
919         {
920           // The server must have closed the connection.
921
sessionTimer.stopTimer();
922           failureCounter.increment();
923
924           try
925           {
926             reader.close();
927             writer.close();
928             socket.close();
929           } catch (Exception JavaDoc e) {}
930
931           continue mainLoop;
932         }
933         if (! line.startsWith("+"))
934         {
935           sessionTimer.stopTimer();
936           failureCounter.increment();
937
938           try
939           {
940             reader.close();
941             writer.close();
942             socket.close();
943           } catch (Exception JavaDoc e) {}
944
945           continue;
946         }
947       }
948       catch (IOException ioe)
949       {
950         sessionTimer.stopTimer();
951         failureCounter.increment();
952
953         try
954         {
955           reader.close();
956           writer.close();
957           socket.close();
958         } catch (Exception JavaDoc e) {}
959
960         continue;
961       }
962
963
964       // Send the password.
965
request = "PASS " + password;
966       try
967       {
968         writer.write(request);
969         writer.newLine();
970         writer.flush();
971       }
972       catch (IOException ioe)
973       {
974         sessionTimer.stopTimer();
975         failureCounter.increment();
976
977         try
978         {
979           reader.close();
980           writer.close();
981           socket.close();
982         } catch (Exception JavaDoc e) {}
983
984         continue;
985       }
986
987
988       // Read the PASS response. It must be a single line.
989
try
990       {
991         line = reader.readLine();
992         if (line == null)
993         {
994           // The server must have closed the connection.
995
sessionTimer.stopTimer();
996           failureCounter.increment();
997
998           try
999           {
1000            reader.close();
1001            writer.close();
1002            socket.close();
1003          } catch (Exception JavaDoc e) {}
1004
1005          continue mainLoop;
1006        }
1007        else if (! line.startsWith("+"))
1008        {
1009          sessionTimer.stopTimer();
1010          failureCounter.increment();
1011
1012          try
1013          {
1014            reader.close();
1015            writer.close();
1016            socket.close();
1017          } catch (Exception JavaDoc e) {}
1018
1019          continue;
1020        }
1021      }
1022      catch (IOException ioe)
1023      {
1024        sessionTimer.stopTimer();
1025        failureCounter.increment();
1026
1027        try
1028        {
1029          reader.close();
1030          writer.close();
1031          socket.close();
1032        } catch (Exception JavaDoc e) {}
1033
1034        continue;
1035      }
1036
1037
1038      // Send the request to get the list of messages.
1039
request = "LIST";
1040      try
1041      {
1042        writer.write(request);
1043        writer.newLine();
1044        writer.flush();
1045      }
1046      catch (IOException ioe)
1047      {
1048        sessionTimer.stopTimer();
1049        failureCounter.increment();
1050
1051        try
1052        {
1053          reader.close();
1054          writer.close();
1055          socket.close();
1056        } catch (Exception JavaDoc e) {}
1057
1058        continue;
1059      }
1060
1061
1062      // Retrieve the list of messages. It will be terminated with a "." on a
1063
// line by itself. The line immediately before it should contain the UID
1064
// of the highest message number.
1065
highestUID = 0;
1066      lastLine = null;
1067      keepReading = true;
1068      while (keepReading)
1069      {
1070        try
1071        {
1072          line = reader.readLine();
1073          if (line == null)
1074          {
1075            // The server must have closed the connection.
1076
keepReading = false;
1077            sessionTimer.stopTimer();
1078            failureCounter.increment();
1079
1080            try
1081            {
1082              reader.close();
1083              writer.close();
1084              socket.close();
1085            } catch (Exception JavaDoc e) {}
1086
1087            continue mainLoop;
1088          }
1089          else if (line.startsWith("-"))
1090          {
1091            sessionTimer.stopTimer();
1092            failureCounter.increment();
1093
1094            try
1095            {
1096              reader.close();
1097              writer.close();
1098              socket.close();
1099            } catch (Exception JavaDoc e) {}
1100
1101            continue mainLoop;
1102          }
1103          else if (line.startsWith("."))
1104          {
1105            keepReading = false;
1106          }
1107          else
1108          {
1109            lastLine = line;
1110          }
1111        }
1112        catch (IOException ioe)
1113        {
1114          sessionTimer.stopTimer();
1115          failureCounter.increment();
1116
1117          try
1118          {
1119            reader.close();
1120            writer.close();
1121            socket.close();
1122          } catch (Exception JavaDoc e) {}
1123
1124          continue;
1125        }
1126      }
1127
1128
1129      // The line immediately before the period should have the highest message
1130
// number. However, if it starts with a "+", then that means there are
1131
// no messages in the mailbox.
1132
if (lastLine != null)
1133      {
1134        if (lastLine.startsWith("+"))
1135        {
1136          messageCountTracker.addValue(0);
1137        }
1138        else
1139        {
1140          try
1141          {
1142            StringTokenizer tokenizer = new StringTokenizer(lastLine, " ");
1143            highestUID = Integer.parseInt(tokenizer.nextToken());
1144            messageCountTracker.addValue(highestUID);
1145          }
1146          catch (Exception JavaDoc e)
1147          {
1148            sessionTimer.stopTimer();
1149            failureCounter.increment();
1150
1151            try
1152            {
1153              reader.close();
1154              writer.close();
1155              socket.close();
1156            } catch (Exception JavaDoc e2) {}
1157
1158            continue;
1159          }
1160        }
1161      }
1162
1163
1164      // Log out from the server.
1165
request = "QUIT";
1166      try
1167      {
1168        writer.write(request);
1169        writer.newLine();
1170        writer.flush();
1171
1172        reader.close();
1173        writer.close();
1174        socket.close();
1175
1176        sessionTimer.stopTimer();
1177        successCounter.increment();
1178      }
1179      catch (IOException ioe)
1180      {
1181        sessionTimer.stopTimer();
1182        failureCounter.increment();
1183
1184        try
1185        {
1186          reader.close();
1187          writer.close();
1188          socket.close();
1189        } catch (Exception JavaDoc e) {}
1190
1191        continue;
1192      }
1193    }
1194
1195
1196    // Stop the stat trackers.
1197
sessionCounter.stopTracker();
1198    sessionTimer.stopTracker();
1199    messageCountTracker.stopTracker();
1200    successCounter.stopTracker();
1201    failureCounter.stopTracker();
1202  }
1203
1204
1205
1206  /**
1207   * Chooses a user ID based on the criteria provided in the job parameters.
1208   *
1209   * @return The user ID that should be used for this attempt.
1210   */

1211  public String JavaDoc getUserID()
1212  {
1213    if (useIDRange)
1214    {
1215      int value;
1216      if (useSequentialID)
1217      {
1218        value = nextSequentialID++;
1219        if (nextSequentialID > idRangeMax)
1220        {
1221          nextSequentialID = idRangeMin;
1222        }
1223      }
1224      else
1225      {
1226        value = ((random.nextInt() & 0x7FFFFFFF) % idRangeSpan) + idRangeMin;
1227      }
1228
1229      return userIDInitial + value + userIDFinal;
1230    }
1231    else
1232    {
1233      return userIDInitial;
1234    }
1235  }
1236}
1237
1238
Popular Tags