KickJava   Java API By Example, From Geeks To Geeks.

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


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 an IMAPv4 mail server. It
31  * does so by performing the following operations:
32  *
33  * <OL>
34  * <LI>Log into the server (<CODE>LOGIN</CODE> <I>{user} {password}</I>).</LI>
35  * <LI>Select the INBOX folder (<CODE>SELECT INBOX</CODE>).</LI>
36  * <LI>Retrieve a list of all messages (<CODE> FETCH
37  * 1:</CODE><I>{num}</I><CODE> (FLAGS)</CODE>).</LI>
38  * <LI>Log out (<CODE>LOGOUT</CODE>).</LI>
39  * </OL>
40  *
41  *
42  * @author Neil A. Wilson
43  */

44 public class IMAPCheckRateJobClass
45        extends JobClass
46 {
47   /**
48    * The prefix that will be placed before the incrementing message ID for each
49    * request.
50    */

51   public static final String JavaDoc REQUEST_ID_PREFIX = "imaprate";
52
53
54
55   /**
56    * The display name of the stat tracker used to count the number of IMAP
57    * sessions established.
58    */

59   public static final String JavaDoc STAT_TRACKER_IMAP_SESSIONS = "IMAP Sessions";
60
61
62
63   /**
64    * The display name of the stat tracker used to count the number of failed
65    * IMAP logins.
66    */

67   public static final String JavaDoc STAT_TRACKER_FAILURE_COUNT = "Failed Logins";
68
69
70
71   /**
72    * The display name of the stat tracker used to keep track of the number of
73    * messages contained in the inbox for each IMAP session.
74    */

75   public static final String JavaDoc STAT_TRACKER_MESSAGE_COUNT = "Message Count";
76
77
78
79   /**
80    * The display name of the stat tracker used to time the process of
81    * authenticating and retrieving the list of messages.
82    */

83   public static final String JavaDoc STAT_TRACKER_SESSION_DURATION =
84        "Session Duration (ms)";
85
86
87
88   /**
89    * The display name of the stat tracker used to count the number of successful
90    * IMAP logins.
91    */

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

177   public IMAPCheckRateJobClass()
178   {
179     super();
180   }
181
182
183
184   /**
185    * Retrieves the name of the job performed by this job thread.
186    *
187    * @return The name of the job performed by this job thread.
188    */

189   public String JavaDoc getJobName()
190   {
191     return "IMAP CheckRate";
192   }
193
194
195
196   /**
197    * Retrieves a description of the job performed by this job thread.
198    *
199    * @return A description of the job performed by this job thread.
200    */

201   public String JavaDoc getJobDescription()
202   {
203     return "This job can be used to repeatedly establish sessions with an " +
204            "IMAPv4 mail server and retrieve information about messages in " +
205            "the user's inbox";
206   }
207
208
209
210   /**
211    * Retrieves the name of the category in which this job class exists. This is
212    * used to help arrange the job classes in the administrative interface.
213    *
214    * @return The name of the category in which this job class exists.
215    */

216   public String JavaDoc getJobCategoryName()
217   {
218     return "Mail";
219   }
220
221
222
223   /**
224    * Retrieve a parameter list that can be used to determine all of the
225    * customizeable options that are available for this job.
226    *
227    * @return A parameter list that can be used to determine all of the
228    * customizeable options that are available for this job.
229    */

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

269   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
270                                            int collectionInterval)
271   {
272     return new StatTracker[]
273     {
274       new IncrementalTracker(clientID, threadID, STAT_TRACKER_IMAP_SESSIONS,
275                              collectionInterval),
276       new TimeTracker(clientID, threadID, STAT_TRACKER_SESSION_DURATION,
277                       collectionInterval),
278       new IntegerValueTracker(clientID, threadID, STAT_TRACKER_MESSAGE_COUNT,
279                               collectionInterval),
280       new IncrementalTracker(clientID, threadID, STAT_TRACKER_SUCCESS_COUNT,
281                              collectionInterval),
282       new IncrementalTracker(clientID, threadID, STAT_TRACKER_FAILURE_COUNT,
283                              collectionInterval)
284     };
285   }
286
287
288
289   /**
290    * Retrieves the stat trackers that are maintained for this job thread.
291    *
292    * @return The stat trackers that are maintained for this job thread.
293    */

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

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

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

576   public void initializeClient(String JavaDoc clientID, ParameterList parameters)
577          throws UnableToRunException
578   {
579     // Get the address of the IMAP server.
580
hostParameter = parameters.getStringParameter(hostParameter.getName());
581     if (hostParameter != null)
582     {
583       imapAddress = hostParameter.getStringValue();
584     }
585
586     // Get the port for the IMAP server.
587
portParameter = parameters.getIntegerParameter(portParameter.getName());
588     if (portParameter != null)
589     {
590       imapPort = portParameter.getIntValue();
591     }
592
593     // Get the user ID. See if it should be a range of values.
594
useIDRange = false;
595     useSequentialID = false;
596     userIDParameter = parameters.getStringParameter(userIDParameter.getName());
597     if (userIDParameter != null)
598     {
599       String JavaDoc value = userIDParameter.getStringValue();
600       int openPos = value.indexOf('[');
601       if (openPos < 0)
602       {
603         userIDInitial = value;
604       }
605       else
606       {
607         int closePos = value.indexOf(']', openPos);
608         if (closePos > 0)
609         {
610           int dashPos = value.indexOf('-', openPos);
611           if ((dashPos > 0) && (dashPos < closePos))
612           {
613             useIDRange = true;
614             idRangeMin = Integer.parseInt(value.substring(openPos+1, dashPos));
615             idRangeMax = Integer.parseInt(value.substring(dashPos+1, closePos));
616             idRangeSpan = idRangeMax - idRangeMin + 1;
617             userIDInitial = value.substring(0, openPos);
618             userIDFinal = value.substring(closePos+1);
619           }
620           else
621           {
622             dashPos = value.indexOf(':', openPos);
623             if ((dashPos > 0) && (dashPos < closePos))
624             {
625               useIDRange = true;
626               useSequentialID = true;
627               idRangeMin = Integer.parseInt(value.substring(openPos+1,
628                                                             dashPos));
629               idRangeMax = Integer.parseInt(value.substring(dashPos+1,
630                                                             closePos));
631               userIDInitial = value.substring(0, openPos);
632               userIDFinal = value.substring(closePos+1);
633               nextSequentialID = idRangeMin;
634             }
635             else
636             {
637               userIDInitial = value;
638             }
639           }
640         }
641         else
642         {
643           userIDInitial = value;
644         }
645       }
646     }
647
648     // Get the password.
649
passwordParameter =
650          parameters.getPasswordParameter(passwordParameter.getName());
651     if (passwordParameter != null)
652     {
653       password = passwordParameter.getStringValue();
654     }
655
656
657     // Get the delay between requests.
658
delayParameter = parameters.getIntegerParameter(delayParameter.getName());
659     if (delayParameter != null)
660     {
661       delay = delayParameter.getIntValue();
662     }
663
664
665     // Seed the parent random number generator.
666
parentRandom = new Random();
667   }
668
669
670
671   /**
672    * Initializes this job thread to be used to actually run the job on the
673    * client. The provided parameter list should be processed to customize the
674    * behavior of this job thread, and any other initialization that needs to be
675    * done in order for the job to run should be performed here as well.
676    *
677    * @param clientID The client ID for this job thread.
678    * @param threadID The thread ID for this job thread.
679    * @param collectionInterval The length of time in seconds to use as the
680    * statistics collection interval.
681    * @param parameters The set of parameters provided to this job that
682    * can be used to customize its behavior.
683    *
684    * @throws UnableToRunException If a problem occurs that prevents the thread
685    * from being able to run properly.
686    */

687   public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
688                                int collectionInterval, ParameterList parameters)
689          throws UnableToRunException
690   {
691     // Create the stat trackers for this thread.
692
sessionCounter = new IncrementalTracker(clientID, threadID,
693                                             STAT_TRACKER_IMAP_SESSIONS,
694                                             collectionInterval);
695     sessionTimer = new TimeTracker(clientID, threadID,
696                                    STAT_TRACKER_SESSION_DURATION,
697                                    collectionInterval);
698     messageCountTracker = new IntegerValueTracker(clientID, threadID,
699                                                   STAT_TRACKER_MESSAGE_COUNT,
700                                                   collectionInterval);
701     successCounter = new IncrementalTracker(clientID, threadID,
702                                             STAT_TRACKER_SUCCESS_COUNT,
703                                             collectionInterval);
704     failureCounter = new IncrementalTracker(clientID, threadID,
705                                             STAT_TRACKER_FAILURE_COUNT,
706                                             collectionInterval);
707
708
709     // Enable real-time reporting of the data for these stat trackers.
710
RealTimeStatReporter statReporter = getStatReporter();
711     if (statReporter != null)
712     {
713       String JavaDoc jobID = getJobID();
714       sessionCounter.enableRealTimeStats(statReporter, jobID);
715       sessionTimer.enableRealTimeStats(statReporter, jobID);
716       messageCountTracker.enableRealTimeStats(statReporter, jobID);
717       successCounter.enableRealTimeStats(statReporter, jobID);
718       failureCounter.enableRealTimeStats(statReporter, jobID);
719     }
720
721
722     // Seed the random number generator for this thread.
723
random = new Random(parentRandom.nextLong());
724   }
725
726
727
728   /**
729    * Perform the work of this job thread by executing the specified command.
730    */

731   public void runJob()
732   {
733     // Define variables that will be used throughout this method.
734
boolean keepReading;
735     BufferedReader reader;
736     BufferedWriter writer;
737     int highestUID;
738     int idCounter;
739     long lastStartTime = 0;
740     Socket socket;
741     String JavaDoc line;
742     String JavaDoc lowerLine;
743     String JavaDoc request;
744     String JavaDoc userID;
745
746
747     // Start the stat trackers.
748
sessionCounter.startTracker();
749     sessionTimer.startTracker();
750     messageCountTracker.startTracker();
751     successCounter.startTracker();
752     failureCounter.startTracker();
753
754
755     // Loop until it is determined that the job should stop.
756
mainLoop:
757     while (! shouldStop())
758     {
759       // If we need to sleep, then do so.
760
if (delay > 0)
761       {
762         long now = System.currentTimeMillis();
763         long prevTestTime = now - lastStartTime;
764         if (prevTestTime < delay)
765         {
766           try
767           {
768             Thread.sleep(delay - prevTestTime);
769           } catch (Exception JavaDoc e) {}
770         }
771       }
772
773       lastStartTime = System.currentTimeMillis();
774
775       // Start the attempt timer and indicate the beginning of a new attempt.
776
sessionCounter.increment();
777       sessionTimer.startTimer();
778
779
780       // Get the user ID to use in the next request.
781
userID = getUserID();
782       idCounter = 1;
783
784
785       // Open a connection to the IMAP server.
786
try
787       {
788         socket = new Socket(imapAddress, imapPort);
789         reader = new BufferedReader(new InputStreamReader(
790                                              socket.getInputStream()));
791         writer = new BufferedWriter(new OutputStreamWriter(
792                                              socket.getOutputStream()));
793       }
794       catch (IOException ioe)
795       {
796         sessionTimer.stopTimer();
797         failureCounter.increment();
798         continue;
799       }
800
801
802       // Read the initial hello line from the server.
803
try
804       {
805         line = reader.readLine();
806       }
807       catch (IOException ioe)
808       {
809         sessionTimer.stopTimer();
810         failureCounter.increment();
811
812         try
813         {
814           reader.close();
815           writer.close();
816           socket.close();
817         } catch (Exception JavaDoc e) {}
818
819         continue;
820       }
821
822
823       // Send the LOGIN request.
824
request = REQUEST_ID_PREFIX + idCounter + " LOGIN " + userID + " " +
825                 password;
826       try
827       {
828         writer.write(request);
829         writer.newLine();
830         writer.flush();
831       }
832       catch (IOException ioe)
833       {
834         sessionTimer.stopTimer();
835         failureCounter.increment();
836
837         try
838         {
839           reader.close();
840           writer.close();
841           socket.close();
842         } catch (Exception JavaDoc e) {}
843
844         continue;
845       }
846
847
848       // Read the LOGIN response. It should be a single line, but we'll make it
849
// a loop just in case.
850
keepReading = true;
851       while (keepReading)
852       {
853         try
854         {
855           line = reader.readLine();
856
857           if (line == null)
858           {
859             // The server must have closed the connection.
860
keepReading = false;
861             sessionTimer.stopTimer();
862             failureCounter.increment();
863
864             try
865             {
866               reader.close();
867               writer.close();
868               socket.close();
869             } catch (Exception JavaDoc e) {}
870
871             continue mainLoop;
872           }
873           else if (line.startsWith(REQUEST_ID_PREFIX + idCounter))
874           {
875             keepReading = false;
876             lowerLine = line.toLowerCase();
877             if (lowerLine.indexOf(REQUEST_ID_PREFIX + idCounter + " ok") < 0)
878             {
879               sessionTimer.stopTimer();
880               failureCounter.increment();
881
882               try
883               {
884                 reader.close();
885                 writer.close();
886                 socket.close();
887               } catch (Exception JavaDoc e) {}
888
889               continue mainLoop;
890             }
891           }
892         }
893         catch (IOException ioe)
894         {
895           sessionTimer.stopTimer();
896           failureCounter.increment();
897
898           try
899           {
900             reader.close();
901             writer.close();
902             socket.close();
903           } catch (Exception JavaDoc e) {}
904
905           continue mainLoop;
906         }
907       }
908
909
910       // Specify that we will be working with the INBOX folder.
911
idCounter++;
912       request = REQUEST_ID_PREFIX + idCounter + " SELECT INBOX";
913       try
914       {
915         writer.write(request);
916         writer.newLine();
917         writer.flush();
918       }
919       catch (IOException ioe)
920       {
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;
932       }
933
934
935       // Read the response from the SELECT operation. It will be multiple
936
// lines. In addition to the success line at the end, we will also want
937
// to get the UID of the last message in the inbox so that we can retrieve
938
// the entire list of flags.
939
highestUID = -1;
940       keepReading = true;
941       while (keepReading)
942       {
943         try
944         {
945           line = reader.readLine();
946           if (line == null)
947           {
948             // The server must have closed the connection.
949
keepReading = false;
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 mainLoop;
961           }
962
963           lowerLine = line.toLowerCase();
964           if (line.startsWith(REQUEST_ID_PREFIX + idCounter))
965           {
966             keepReading = false;
967             lowerLine = line.toLowerCase();
968             if (lowerLine.indexOf(REQUEST_ID_PREFIX + idCounter + " ok") < 0)
969             {
970               sessionTimer.stopTimer();
971               failureCounter.increment();
972
973               try
974               {
975                 reader.close();
976                 writer.close();
977                 socket.close();
978               } catch (Exception JavaDoc e) {}
979
980               continue mainLoop;
981             }
982           }
983           else if (lowerLine.startsWith("*") &&
984                    (lowerLine.indexOf("exists") > 0))
985           {
986             StringTokenizer tokenizer = new StringTokenizer(line, " ");
987             try
988             {
989               // The first will be the asterisk. The second should be the
990
// highest ID in the inbox.
991
tokenizer.nextToken();
992               highestUID = Integer.parseInt(tokenizer.nextToken());
993             }
994             catch (Exception JavaDoc e)
995             {
996               sessionTimer.stopTimer();
997               failureCounter.increment();
998
999               try
1000              {
1001                reader.close();
1002                writer.close();
1003                socket.close();
1004              } catch (Exception JavaDoc e2) {}
1005
1006              continue mainLoop;
1007            }
1008          }
1009        }
1010        catch (IOException ioe)
1011        {
1012          sessionTimer.stopTimer();
1013          failureCounter.increment();
1014
1015          try
1016          {
1017            reader.close();
1018            writer.close();
1019            socket.close();
1020          } catch (Exception JavaDoc e) {}
1021
1022          continue mainLoop;
1023        }
1024      }
1025
1026
1027      // If we didn't get a value for the highest message UID, then that's a
1028
// failure.
1029
if (highestUID < 0)
1030      {
1031        sessionTimer.stopTimer();
1032        failureCounter.increment();
1033
1034        try
1035        {
1036          reader.close();
1037          writer.close();
1038          socket.close();
1039        } catch (Exception JavaDoc e) {}
1040
1041        continue;
1042      }
1043      else
1044      {
1045        messageCountTracker.addValue(highestUID);
1046      }
1047
1048
1049      // If we got a value of 0 for the highest message UID, then that means
1050
// the mailbox is empty. That's not an error, but we shouldn't try to
1051
// get the list of messages.
1052
if (highestUID > 0)
1053      {
1054        // Create a request that will retrieve the flags for all messages in the
1055
// inbox.
1056
idCounter++;
1057        request = REQUEST_ID_PREFIX + idCounter + " FETCH 1:" + highestUID +
1058                  " (FLAGS)";
1059        try
1060        {
1061          writer.write(request);
1062          writer.newLine();
1063          writer.flush();
1064        }
1065        catch (IOException ioe)
1066        {
1067          sessionTimer.stopTimer();
1068          failureCounter.increment();
1069
1070          try
1071          {
1072            reader.close();
1073            writer.close();
1074            socket.close();
1075          } catch (Exception JavaDoc e) {}
1076
1077          continue;
1078        }
1079
1080
1081        // Read the list of flags for each message. We don't really care what
1082
// they are for this test, so just look for the end of the list.
1083
keepReading = true;
1084        while (keepReading)
1085        {
1086          try
1087          {
1088            line = reader.readLine();
1089            if (line == null)
1090            {
1091              // The server must have closed the connection.
1092
keepReading = false;
1093              sessionTimer.stopTimer();
1094              failureCounter.increment();
1095
1096              try
1097              {
1098                reader.close();
1099                writer.close();
1100                socket.close();
1101              } catch (Exception JavaDoc e) {}
1102
1103              continue mainLoop;
1104            }
1105            else if (line.startsWith(REQUEST_ID_PREFIX + idCounter))
1106            {
1107              keepReading = false;
1108              lowerLine = line.toLowerCase();
1109              if (lowerLine.indexOf(REQUEST_ID_PREFIX + idCounter + " ok") < 0)
1110              {
1111                sessionTimer.stopTimer();
1112                failureCounter.increment();
1113
1114                try
1115                {
1116                  reader.close();
1117                  writer.close();
1118                  socket.close();
1119                } catch (Exception JavaDoc e) {}
1120
1121                continue mainLoop;
1122              }
1123            }
1124          }
1125          catch (IOException ioe)
1126          {
1127            sessionTimer.stopTimer();
1128            failureCounter.increment();
1129
1130            try
1131            {
1132              reader.close();
1133              writer.close();
1134              socket.close();
1135            } catch (Exception JavaDoc e) {}
1136
1137            continue mainLoop;
1138          }
1139        }
1140      }
1141
1142
1143      // Send the request to log out from the server and close the connection.
1144
idCounter++;
1145      request = REQUEST_ID_PREFIX + idCounter + " LOGOUT";
1146      try
1147      {
1148        writer.write(request);
1149        writer.newLine();
1150        writer.flush();
1151
1152        reader.close();
1153        writer.close();
1154        socket.close();
1155
1156        sessionTimer.stopTimer();
1157        successCounter.increment();
1158      }
1159      catch (IOException ioe)
1160      {
1161        sessionTimer.stopTimer();
1162        failureCounter.increment();
1163
1164        try
1165        {
1166          reader.close();
1167          writer.close();
1168          socket.close();
1169        } catch (Exception JavaDoc e) {}
1170
1171        continue;
1172      }
1173    }
1174
1175
1176    // Stop the stat trackers.
1177
sessionCounter.stopTracker();
1178    sessionTimer.stopTracker();
1179    messageCountTracker.stopTracker();
1180    successCounter.stopTracker();
1181    failureCounter.stopTracker();
1182  }
1183
1184
1185
1186  /**
1187   * Chooses a user ID based on the criteria provided in the job parameters.
1188   *
1189   * @return The user ID that should be used for this attempt.
1190   */

1191  public String JavaDoc getUserID()
1192  {
1193    if (useIDRange)
1194    {
1195      int value;
1196      if (useSequentialID)
1197      {
1198        value = nextSequentialID++;
1199        if (nextSequentialID > idRangeMax)
1200        {
1201          nextSequentialID = idRangeMin;
1202        }
1203      }
1204      else
1205      {
1206        value = ((random.nextInt() & 0x7FFFFFFF) % idRangeSpan) + idRangeMin;
1207      }
1208
1209      return userIDInitial + value + userIDFinal;
1210    }
1211    else
1212    {
1213      return userIDInitial;
1214    }
1215  }
1216}
1217
1218
Popular Tags