KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > rubbos > client > UserSession


1 package edu.rice.rubbos.client;
2
3 import java.io.BufferedInputStream JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.io.RandomAccessFile JavaDoc;
6 import java.net.URL JavaDoc;
7 import java.util.GregorianCalendar JavaDoc;
8 import java.util.Random JavaDoc;
9 import java.util.Vector JavaDoc;
10
11 /**
12  * RUBBoS user session emulator.
13  * This class plays a random user session emulating a Web browser.
14  *
15  * @author <a HREF="mailto:cecchet@rice.edu">Emmanuel Cecchet</a> and <a HREF="mailto:julie.marguerite@inrialpes.fr">Julie Marguerite</a>
16  * @version 1.0
17  */

18 public class UserSession extends Thread JavaDoc
19 {
20   private RUBBoSProperties rubbos = null; // access to rubbos.properties file
21
private URLGenerator urlGen = null; // URL generator corresponding to the version to be used (PHP, EJB or Servlets)
22
private TransitionTable transition = null; // transition table user for this session
23
private String JavaDoc lastHTMLReply = null; // last HTML reply received from
24
private Random JavaDoc rand = new Random JavaDoc(); // random number generator
25
private int userId; // User id for the current session
26
private String JavaDoc username = null; // User name for the current session
27
private String JavaDoc password = null; // User password for the current session
28
private URL JavaDoc lastURL = null; // Last accessed URL
29
private int lastStoryId = -1; // This is to deal with back because the storyId cannot be retrieved from the current page
30
private int lastCategoryId = -1; // This is to deal with back when the categoryId cannot be retrieved from the current page
31
private String JavaDoc lastCategoryName = null; // This is to deal with back when the categoryName cannot be retrieved from the current page
32
private Stats stats; // Statistics to collect errors, time, ...
33
private int debugLevel = 0; // 0 = no debug message, 1 = just error messages, 2 = error messages+HTML pages, 3 = everything!
34
private int thisYear; // Current year (2001)
35
private RandomAccessFile JavaDoc dictionary = null; // Dictionary file to use to generate random words
36
private String JavaDoc lastRandomWord = null; // Last word used for free text search
37
private int lastSearch = 0; // Last search state (stories, comments or users)
38
private boolean isAuthorSession = false;
39
40   /**
41    * Creates a new <code>UserSession</code> instance.
42    * @param threadId a thread identifier
43    * @param URLGen the URLGenerator to use
44    * @param RUBBoS rubbos.properties
45    * @param statistics where to collect statistics
46    * @param isAuthor true if this user session is for an author, false for a regular user
47    */

48   public UserSession(String JavaDoc threadId, URLGenerator URLGen, RUBBoSProperties RUBBoS, Stats statistics, boolean isAuthor)
49   {
50     super(threadId);
51     urlGen = URLGen;
52     rubbos = RUBBoS;
53     stats = statistics;
54     debugLevel = rubbos.getMonitoringDebug();
55     isAuthorSession = isAuthor;
56
57     transition = new TransitionTable(rubbos.getNbOfColumns(), rubbos.getNbOfRows(), statistics, rubbos.useTPCWThinkTime());
58     if (isAuthorSession)
59     {
60       if (!transition.ReadExcelTextFile(rubbos.getAuthorTransitionTable()))
61         Runtime.getRuntime().exit(1);
62     }
63     else
64     {
65       if (!transition.ReadExcelTextFile(rubbos.getUserTransitionTable()))
66         Runtime.getRuntime().exit(1);
67     }
68   }
69
70
71   /**
72    * Call the HTTP Server according to the given URL and get the reply
73    *
74    * @param url URL to access
75    * @return <code>String</code> containing the web server reply (HTML file)
76    */

77   private String JavaDoc callHTTPServer(URL JavaDoc url)
78   {
79     String JavaDoc HTMLReply = "";
80     BufferedInputStream JavaDoc in = null;
81     int retry = 0;
82
83     if (debugLevel > 2)
84       System.out.println("Thread "+this.getName()+": "+url+"<br>");
85     
86     while (retry < 5)
87     {
88       // Open the connexion
89
try
90       {
91         in = new BufferedInputStream JavaDoc(url.openStream(), 4096);
92       }
93       catch (IOException JavaDoc ioe)
94       {
95         if (debugLevel>0)
96           System.err.println("Thread "+this.getName()+": Unable to open URL "+url+" ("+ioe.getMessage()+")<br>");
97         retry++;
98         try
99         {
100           Thread.currentThread().sleep(1000L);
101         }
102         catch (InterruptedException JavaDoc i)
103         {
104           if (debugLevel>0)
105             System.err.println("Thread "+this.getName()+": Interrupted in callHTTPServer()<br>");
106           return null;
107         }
108         continue;
109       }
110
111       // Get the data
112
try
113       {
114         byte[] buffer = new byte[4096];
115         int read;
116
117         while ((read = in.read(buffer, 0, buffer.length)) != -1)
118         {
119           if (read > 0)
120             HTMLReply = HTMLReply + new String JavaDoc(buffer, 0, read);
121         }
122       }
123       catch (IOException JavaDoc ioe)
124       {
125         if (debugLevel>0)
126           System.err.println("Thread "+this.getName()+": Unable to read from URL "+url+" ("+ioe.getMessage()+")<br>");
127         return null;
128       }
129
130       // No retry at this point
131
break;
132     }
133     try
134     {
135       if (in != null)
136         in.close();
137     }
138     catch (IOException JavaDoc ioe)
139     {
140       if (debugLevel>0)
141         System.err.println("Thread "+this.getName()+": Unable to close URL "+url+" ("+ioe.getMessage()+")<br>");
142     }
143     if (retry == 5)
144       return null;
145
146     // Look for any image to download
147
Vector JavaDoc images = new Vector JavaDoc();
148     int index = HTMLReply.indexOf("<IMG SRC=\"");
149     while (index != -1)
150     {
151       int startQuote = index + 10; // 10 equals to length of <IMG SRC"
152
int endQuote = HTMLReply.indexOf("\"", startQuote+1);
153       images.add(HTMLReply.substring(startQuote, endQuote));
154       index = HTMLReply.indexOf("<IMG SRC=\"", endQuote);
155     }
156     
157     // Download all images
158
byte[] buffer = new byte[4096];
159     while (images.size() > 0)
160     {
161       URL JavaDoc imageURL = urlGen.genericHTMLFile((String JavaDoc)images.elementAt(0));
162       try
163       {
164         BufferedInputStream JavaDoc inImage = new BufferedInputStream JavaDoc(imageURL.openStream(), 4096);
165         while (inImage.read(buffer, 0, buffer.length) != -1); // Just download, skip data
166
inImage.close();
167       }
168       catch (IOException JavaDoc ioe)
169       {
170         if (debugLevel>0)
171           System.err.println("Thread "+this.getName()+": Error while downloading image "+imageURL+" ("+ioe.getMessage()+")<br>");
172       }
173       images.removeElementAt(0);
174     }
175
176     return HTMLReply;
177   }
178
179
180   /**
181    * Internal method that returns the min between last_index
182    * and x if x is not equal to -1.
183    *
184    * @param last_index last_index value
185    * @param x value to compare with last_index
186    * @return x if (x<last_index and x!=-1) else last_index
187    */

188   private int isMin(int last_index, int x)
189   {
190     if (x == -1)
191       return last_index;
192     if (last_index <= x)
193       return last_index;
194     else
195       return x;
196   }
197
198
199   /**
200    * Internal method to compute the index of the end character
201    * of a key value. If the key is not found, the lastIndex
202    * value is returned unchanged.
203    *
204    * @param key the key to look for
205    * @param lastIndex index to start the lookup in lastHTMLReply
206    * @return new lastIndex value
207    */

208   private int computeLastIndex(String JavaDoc key, int lastIndex)
209   {
210     int keyIndex = lastHTMLReply.indexOf(key, lastIndex);
211     if (keyIndex == -1)
212     {
213       if (debugLevel>0)
214         System.err.println("Thread "+this.getName()+": Cannot find "+key+" in last HTML reply<br>");
215       if (debugLevel>1)
216         System.err.println("Thread "+this.getName()+": Last HTML reply is: "+lastHTMLReply+"<br>");
217     }
218     else
219     {
220       keyIndex += key.length();
221       lastIndex = lastHTMLReply.indexOf('\"', keyIndex);
222       lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('?', keyIndex));
223       lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('&', keyIndex));
224       lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('>', keyIndex));
225     }
226     return lastIndex;
227   }
228
229
230   /**
231    * Internal method to compute the index of the end character
232    * of a key value. If the key is not found, the lastIndex
233    * value is returned unchanged.
234    *
235    * @param key the key to look for
236    * @param skipFirst true if the first occurence of key must be ignored
237    * @return new lastIndex value
238    */

239   private int[] randomComputeLastIndex(String JavaDoc key, boolean skipFirst)
240   {
241     int count = 0;
242     int keyIndex = lastHTMLReply.indexOf(key);
243     // 1. Count the number of times we find key
244
while (keyIndex != -1)
245     {
246       count++;
247       keyIndex = lastHTMLReply.indexOf(key, keyIndex+key.length());
248     }
249     if ((count == 0) || (skipFirst && (count <= 1)))
250     {
251       if (debugLevel>0)
252         System.err.println("Thread "+this.getName()+": Cannot find "+key+" in last HTML reply<br>");
253       if (debugLevel>1)
254         System.err.println("Thread "+this.getName()+": Last HTML reply is: "+lastHTMLReply+"<br>");
255       return null;
256     }
257
258     // 2. Pickup randomly a key
259
keyIndex = -key.length();
260     count = rand.nextInt(count)+1;
261     if ((skipFirst) && (count == 1))
262       count++; // Force to skip the first element
263
while (count > 0)
264     {
265       keyIndex = lastHTMLReply.indexOf(key, keyIndex+key.length());
266       count--;
267     }
268     keyIndex += key.length();
269     int lastIndex = isMin(Integer.MAX_VALUE, lastHTMLReply.indexOf('\"', keyIndex));
270     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('?', keyIndex));
271     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('&', keyIndex));
272     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('>', keyIndex));
273     int[] result = new int[2];
274     result[0] = keyIndex;
275     result[1] = lastIndex;
276     return result;
277   }
278
279
280   /**
281    * Extract a storyId from the last HTML reply. If several storyId entries
282    * are found, one of them is picked up randomly.
283    *
284    * @return an item identifier or -1 on error
285    */

286   private int extractStoryIdFromHTML()
287   {
288     if (lastHTMLReply == null)
289     {
290       if (debugLevel>0)
291         System.err.println("Thread "+this.getName()+": There is no previous HTML reply<br>");
292       return -1;
293     }
294
295     // Choose randomly a story
296
int[] pos = randomComputeLastIndex("storyId=", false);
297     if (pos == null)
298       return lastStoryId;
299     Integer JavaDoc foo = new Integer JavaDoc(lastHTMLReply.substring(pos[0], pos[1]));
300     lastStoryId = foo.intValue();
301     return lastStoryId;
302   }
303
304
305   /**
306    * Extract a category (id+name) from the last HTML reply. If several entries
307    * are found, one of them is picked up randomly.
308    *
309    * @return a vector containing first the category identifier (Integer) and then the category name (String)
310    */

311   private Vector JavaDoc extractCategoryFromHTML()
312   {
313     if (lastHTMLReply == null)
314     {
315       if (debugLevel>0)
316         System.err.println("Thread "+this.getName()+": There is no previous HTML reply<br>");
317       return null;
318     }
319
320     // Choose randomly a category
321
int[] pos = randomComputeLastIndex("category=", false);
322     if (pos == null)
323       return null;
324     Integer JavaDoc categoryId = new Integer JavaDoc(lastHTMLReply.substring(pos[0], pos[1]));
325     String JavaDoc categoryName = null;
326     int newLast = computeLastIndex("categoryName=", pos[1]);
327     if (newLast != pos[1])
328       categoryName = lastHTMLReply.substring(pos[1]+"categoryName=".length()+1, newLast);
329     Vector JavaDoc result = new Vector JavaDoc(2);
330     result.add(categoryId);
331     result.add(categoryName);
332     return result;
333   }
334
335   /**
336    * Extract post comment parameters (comment_table+storyId+parent) from the last HTML reply.
337    * If several entries are found, one of them is picked up randomly.
338    *
339    * @return a vector containing first the comment table (String), then the story identfier (Integer) and finally the parent identifier (Integer)
340    */

341   private Vector JavaDoc extractPostCommentFromHTML(String JavaDoc scriptName)
342   {
343     if (lastHTMLReply == null)
344     {
345       if (debugLevel>0)
346         System.err.println("Thread "+this.getName()+": There is no previous HTML reply<br>");
347       return null;
348     }
349
350     int[] pos = randomComputeLastIndex(scriptName, false);
351     if (pos == null)
352       return null;
353
354     // Now we have chosen a 'scriptName?...' we can extract the parameters
355
String JavaDoc comment_table = null;
356     Integer JavaDoc storyId = null;
357     Integer JavaDoc parent = null;
358
359     int newLast = computeLastIndex("comment_table=", pos[1]);
360     if (newLast != pos[1])
361       comment_table = lastHTMLReply.substring(pos[1]+"comment_table=".length()+1, newLast);
362     pos[1] = newLast;
363     newLast = computeLastIndex("storyId=", pos[1]);
364     if (newLast != pos[1])
365       storyId = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"storyId=".length()+1, newLast));
366     pos[1] = newLast;
367     newLast = computeLastIndex("parent=", pos[1]);
368     if (newLast != pos[1])
369       parent = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"parent=".length()+1, newLast));
370
371     Vector JavaDoc result = new Vector JavaDoc(3);
372     result.add(comment_table);
373     result.add(storyId);
374     result.add(parent);
375     return result;
376   }
377
378   /**
379    * Extract post comment parameters (comment_table+storyId+parent+commentId+filter+display) from the last HTML reply.
380    * If several entries are found, one of them is picked up randomly.
381    *
382    * @return a vector containing first the comment table (String), then the story identfier (Integer) and finally the parent identifier (Integer)
383    */

384   private Vector JavaDoc extractViewCommentFromHTML(String JavaDoc scriptName)
385   {
386     if (lastHTMLReply == null)
387     {
388       if (debugLevel>0)
389         System.err.println("Thread "+this.getName()+": There is no previous HTML reply<br>");
390       return null;
391     }
392
393     int[] pos = randomComputeLastIndex(scriptName, true);
394     if (pos == null)
395       return null;
396
397     // Now we have chosen a 'scriptName?...' we can extract the parameters
398
String JavaDoc comment_table = null;
399     Integer JavaDoc storyId = null;
400     Integer JavaDoc commentId = null;
401     Integer JavaDoc filter = null;
402     Integer JavaDoc display = null;
403
404     int newLast = computeLastIndex("comment_table=", pos[1]);
405     if (newLast != pos[1])
406       comment_table = lastHTMLReply.substring(pos[1]+"comment_table=".length()+1, newLast);
407     pos[1] = newLast;
408     newLast = computeLastIndex("storyId=", pos[1]);
409     if (newLast != pos[1])
410       storyId = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"storyId=".length()+1, newLast));
411     pos[1] = newLast;
412     newLast = computeLastIndex("commentId=", pos[1]);
413     if (newLast != pos[1])
414       commentId = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"commentId=".length()+1, newLast));
415     pos[1] = newLast;
416     newLast = computeLastIndex("filter=", pos[1]);
417     if (newLast != pos[1])
418       filter = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"filter=".length()+1, newLast));
419     pos[1] = newLast;
420     newLast = computeLastIndex("display=", pos[1]);
421     if (newLast != pos[1])
422       display = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"display=".length()+1, newLast));
423     
424     Vector JavaDoc result = new Vector JavaDoc(5);
425     result.add(comment_table);
426     result.add(storyId);
427     result.add(commentId);
428     result.add(filter);
429     result.add(display);
430     return result;
431   }
432
433
434   /**
435    * Extract the comment table and identifier from the last page for a moderation.
436    * If several entries are found, one of them is picked up randomly.
437    *
438    * @return First the comment table value (String), then the comment identifier (Integer)
439    */

440   private Vector JavaDoc extractModerateCommentIdFromHTML(String JavaDoc scriptName)
441   {
442     if (lastHTMLReply == null)
443     {
444       if (debugLevel>0)
445         System.err.println("Thread "+this.getName()+": There is no previous HTML reply<br>");
446       return null;
447     }
448
449     int[] pos = randomComputeLastIndex(scriptName, false);
450     if (pos == null)
451       return null;
452
453     // Now we have chosen a 'scriptName?...' we can extract the parameters
454
String JavaDoc comment_table = null;
455     Integer JavaDoc commentId = null;
456
457     int newLast = computeLastIndex("comment_table=", pos[1]);
458     if (newLast != pos[1])
459       comment_table = lastHTMLReply.substring(pos[1]+"comment_table=".length()+1, newLast);
460     pos[1] = newLast;
461     newLast = computeLastIndex("commentId=", pos[1]);
462     if (newLast != pos[1])
463       commentId = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"commentId=".length()+1, newLast));
464     pos[1] = newLast;
465
466     Vector JavaDoc result = new Vector JavaDoc(2);
467     result.add(comment_table);
468     result.add(commentId);
469     return result;
470   }
471
472
473   /**
474    * Extract the story identifier from the review story page for an accept or reject.
475    * If several entries are found, one of them is picked up randomly.
476    *
477    * @return the selected story identifier
478    */

479   private Integer JavaDoc extractAcceptRejectStoryIdFromHTML(String JavaDoc scriptName)
480   {
481     Integer JavaDoc storyId = null;
482
483     if (lastHTMLReply == null)
484     {
485       if (debugLevel>0)
486         System.err.println("Thread "+this.getName()+": There is no previous HTML reply<br>");
487       return null;
488     }
489
490     int[] pos = randomComputeLastIndex(scriptName, false);
491     if (pos == null)
492       return null;
493
494     // Now we have chosen a 'scriptName?...' we can extract the parameters
495
int newLast = computeLastIndex("storyId=", pos[1]);
496     if (newLast != pos[1])
497       storyId = new Integer JavaDoc(lastHTMLReply.substring(pos[1]+"storyId=".length()+1, newLast));
498
499     return storyId;
500   }
501
502
503   /**
504    * Extract a page value from the last HTML reply (used from BrowseCategories like functions)
505    *
506    * @return a page value
507    */

508   private int extractPageFromHTML()
509   {
510     if (lastHTMLReply == null)
511       return 0;
512
513     int firstPageIndex = lastHTMLReply.indexOf("&page=");
514     if (firstPageIndex == -1)
515       return 0;
516     int secondPageIndex = lastHTMLReply.indexOf("&page=", firstPageIndex+6); // 6 equals to &page=
517
int chosenIndex = 0;
518     if (secondPageIndex == -1)
519       chosenIndex = firstPageIndex; // First or last page => go to next or previous page
520
else
521     { // Choose randomly a page (previous or next)
522
if (rand.nextInt(100000) < 50000)
523         chosenIndex = firstPageIndex;
524       else
525         chosenIndex = secondPageIndex;
526     }
527     int lastIndex = lastHTMLReply.indexOf('\"', chosenIndex+6);
528     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('?', chosenIndex+6));
529     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('&', chosenIndex+6));
530     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('>', chosenIndex+6));
531     Integer JavaDoc foo = new Integer JavaDoc(lastHTMLReply.substring(chosenIndex+6, lastIndex));
532     return foo.intValue();
533   }
534
535
536   /**
537    * Extract an int value corresponding to the given key
538    * from the last HTML reply. Example :
539    * <pre>int userId = extractIdFromHTML("&userId=")</pre>
540    *
541    * @param key the pattern to look for
542    * @return the <code>int</code> value or -1 on error.
543    */

544   private int extractIntFromHTML(String JavaDoc key)
545   {
546     if (lastHTMLReply == null)
547     {
548       if (debugLevel>0)
549         System.err.println("Thread "+this.getName()+": There is no previous HTML reply");
550       return -1;
551     }
552
553     // Look for the key
554
int keyIndex = lastHTMLReply.indexOf(key);
555     if (keyIndex == -1)
556     {
557       if (debugLevel > 0)
558         System.err.println("Thread "+this.getName()+": Cannot find "+key+" in last HTML reply<br>");
559       if (debugLevel > 1)
560         System.err.println("Thread "+this.getName()+": Last HTML reply is: "+lastHTMLReply+"<br>");
561       return -1;
562     }
563     int lastIndex = lastHTMLReply.indexOf('\"', keyIndex+key.length());
564     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('?', keyIndex+key.length()));
565     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('&', keyIndex+key.length()));
566     lastIndex = isMin(lastIndex, lastHTMLReply.indexOf('>', keyIndex+key.length()));
567     Integer JavaDoc foo = new Integer JavaDoc(lastHTMLReply.substring(keyIndex+key.length(), lastIndex));
568     return foo.intValue();
569   }
570
571
572   /**
573    * This method chooses randomly a word from the dictionary.
574    *
575    * @return random word
576    */

577   public String JavaDoc randomWordFromDictionary(boolean withPunctuation)
578   {
579     String JavaDoc word = null;
580     try
581     {
582       int pos = rand.nextInt((int)dictionary.length());
583       dictionary.seek(pos);
584       word = dictionary.readLine(); // we surely only get the end of a word
585
word = dictionary.readLine(); // this one should be ok
586
}
587     catch (Exception JavaDoc e)
588     {
589       System.err.println("Unable to read dictionary file '"+rubbos.getStoryDictionary()+"' to generate random word (got exception: "+e.getMessage()+")<br>");
590       return null;
591     }
592     if (word.indexOf(' ') != -1)
593       word = word.substring(0, word.indexOf(' ')); // Ignore everything after the first space
594
if (withPunctuation)
595     {
596       switch (rand.nextInt(10))
597       {
598       case 0:
599         word += ", ";
600         break;
601       case 1:
602         word += ". ";
603         break;
604       case 2:
605         word += " ? ";
606         break;
607       case 3:
608         word += " ! ";
609         break;
610       case 4:
611         word += ": ";
612         break;
613       case 5:
614         word += " ; ";
615         break;
616       default:
617         word += " ";
618         break;
619       }
620     }
621     return word;
622   }
623
624
625   /**
626    * Computes the URL to be accessed according to the given state.
627    * If any parameter are needed, they are computed from last HTML reply.
628    *
629    * @param state current state
630    * @return URL corresponding to the state
631    */

632   public URL JavaDoc computeURLFromState(int state)
633   {
634     if (lastHTMLReply != null)
635     {
636       if (lastHTMLReply.indexOf("Sorry") != -1) // Nothing matched the request, we have to go back
637
state = transition.backToPreviousState();
638     }
639     if ((state < 17) || (state > 19)) // Reset lastSearch if we don't stay in a search state
640
lastSearch = 0;
641
642     switch (state)
643     {
644     case -1: // An error occured, reset to home page
645
transition.resetToInitialState();
646     case 0: // Home Page == Stories of the Day
647
return urlGen.homePage();
648     case 1: // Register User Page
649
return urlGen.register();
650     case 2: // Register the user in the database
651
{ // Choose a random nb over already known attributed ids
652
int i = rubbos.getNbOfUsers()+rand.nextInt(1000000)+1;
653         String JavaDoc firstname = "Great"+i;
654         String JavaDoc lastname = "User"+i;
655         String JavaDoc nickname = "user"+i;
656         String JavaDoc email = firstname+"."+lastname+"@rubbos.com";
657         String JavaDoc password = "password"+i;
658         
659         return urlGen.registerUser(firstname, lastname, nickname, email, password);
660       }
661     case 3: // Browse Page
662
return urlGen.browse();
663     case 4: // Browse Categories
664
return urlGen.browseCategories();
665     case 5: // Browse stories in a category
666
{ // We randomly pickup a category from the generated HTML page
667
Vector JavaDoc c = extractCategoryFromHTML();
668         int categoryId;
669         String JavaDoc categoryName;
670         if (c == null)
671         {
672           categoryId = lastCategoryId;
673           categoryName = lastCategoryName;
674         }
675         else
676         {
677           categoryId = ((Integer JavaDoc)c.get(0)).intValue();
678           categoryName = (String JavaDoc)c.get(1);
679           lastCategoryId = categoryId;
680           lastCategoryName = categoryName;
681         }
682         return urlGen.browseStoriesByCategory(categoryId, categoryName, extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());
683       }
684     case 6: // Older stories
685
{
686         // We have to make hit on past days more successful than hits on 10 years old stories
687
int day;
688         int month;
689         int year;
690         int when = rand.nextInt(100);
691         if (when > 95)
692         { // Pickup any date
693
day = rand.nextInt(31) + 1;
694           month = rand.nextInt(12) + 1;
695           year = rubbos.getOldestStoryYear()+rand.nextInt(3);
696         }
697         else
698         { // Some date in the past week
699
GregorianCalendar JavaDoc y = new GregorianCalendar JavaDoc();
700           when = when / 10;
701           if (when == 0)
702             when = 1;
703           if (when > 7)
704             when = 7;
705           for (int i = 0 ; i < when ; i++)
706             y.roll(GregorianCalendar.DAY_OF_MONTH, false);
707           day = y.get(GregorianCalendar.DAY_OF_MONTH);
708           month = y.get(GregorianCalendar.MONTH)+1; // Month start at 0
709
year = y.get(GregorianCalendar.YEAR);
710         }
711         if (year > thisYear)
712           year = thisYear;
713         if (year == rubbos.getOldestStoryYear())
714         {
715           if (month <= rubbos.getOldestStoryMonth())
716             month = rubbos.getOldestStoryMonth();
717         }
718         return urlGen.OlderStories(day, month, year, extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());
719       }
720     case 7: // View a story
721
{ // We randomly pickup a story from the generated HTML page
722
int storyId = extractStoryIdFromHTML();
723         if (storyId == -1)
724           return computeURLFromState(transition.backToPreviousState()); // Nothing then go back
725
else
726           return urlGen.viewStory(storyId);
727       }
728     case 8: // Post Comment
729
{
730         Vector JavaDoc p = extractPostCommentFromHTML(urlGen.PostCommentScript());
731         if (p == null)
732         {
733           if (debugLevel > 0)
734             System.out.println("Thread "+this.getName()+": Unable to extract PostComment parameters from last HTML reply.<br>");
735           return null;
736         }
737         String JavaDoc comment_table = (String JavaDoc)p.get(0);
738         Integer JavaDoc storyId = (Integer JavaDoc)p.get(1);
739         Integer JavaDoc parent = (Integer JavaDoc)p.get(2);
740
741         if ((comment_table == null) || (storyId == null) || (parent == null))
742           return computeURLFromState(transition.backToPreviousState()); // Nothing then go back
743
else
744           return urlGen.postComment(storyId.intValue(), parent.intValue(), comment_table);
745       }
746     case 9: // Store comment
747
{
748         String JavaDoc subject = "";
749         String JavaDoc body = "";
750
751         int size = rand.nextInt(100); // Subject size must be smaller than 100 characters
752
do
753           subject += randomWordFromDictionary(true);
754         while ((subject != null) && (subject.length() < size));
755         
756         size = rand.nextInt(rubbos.getStoryMaximumLength());
757         do
758           body += randomWordFromDictionary(true);
759         while ((body != null) && (body.length() < size));
760
761         int[] pos = randomComputeLastIndex("name=comment_table value=", false);
762         if (pos == null)
763           return null;
764         String JavaDoc comment_table = lastHTMLReply.substring(pos[0], pos[1]);
765         return urlGen.storeComment(username, password, extractIntFromHTML("name=storyId value="), extractIntFromHTML("name=parent value="),
766                                    subject, body, comment_table);
767       }
768     case 10: // View comment
769
{
770         Vector JavaDoc p = extractViewCommentFromHTML(urlGen.ViewCommentScript());
771         if (p == null)
772         {
773           state = transition.backToPreviousState();
774           return computeURLFromState(state);
775         }
776         String JavaDoc comment_table = (String JavaDoc)p.get(0);
777         Integer JavaDoc storyId = (Integer JavaDoc)p.get(1);
778         Integer JavaDoc commentId = (Integer JavaDoc)p.get(2);
779         Integer JavaDoc filter = (Integer JavaDoc)p.get(3);
780         Integer JavaDoc display = (Integer JavaDoc)p.get(4);
781
782         if ((comment_table == null) || (storyId == null) || (commentId == null) || (filter == null) || (display == null))
783           return computeURLFromState(transition.backToPreviousState()); // Nothing then go back
784
else
785           return urlGen.viewComment(commentId.intValue(), filter.intValue(), display.intValue(), storyId.intValue(), comment_table);
786       }
787     case 11: // Moderate comment
788
{
789         Vector JavaDoc c = extractModerateCommentIdFromHTML(urlGen.ModerateCommentScript());
790         if (c == null)
791         {
792           state = transition.backToPreviousState();
793           return computeURLFromState(state);
794         }
795         String JavaDoc comment_table = (String JavaDoc)c.get(0);
796         Integer JavaDoc commentId = (Integer JavaDoc)c.get(1);
797         if ((comment_table == null) || (commentId == null))
798           return computeURLFromState(transition.backToPreviousState()); // Nothing then go back
799
else
800           return urlGen.moderateComment(commentId.intValue(), comment_table);
801       }
802     case 12: // Moderate log
803
{
804         int rating = rand.nextInt(2)-1; // random value between -1 and 1
805

806         int[] pos = randomComputeLastIndex("name=comment_table value=", false);
807         if (pos == null)
808           return null;
809         String JavaDoc comment_table = lastHTMLReply.substring(pos[0], pos[1]);
810
811         return urlGen.storeModerateLog(username, password, extractIntFromHTML("name=commentId value="), rating, comment_table);
812       }
813     case 13: // Submit story
814
return urlGen.submitStory();
815     case 14: // Store story
816
{
817         String JavaDoc title = "";
818         String JavaDoc body = "";
819
820         int size = rand.nextInt(100); // title size must be smaller than 100 characters
821
do
822           title += randomWordFromDictionary(true);
823         while ((title != null) && (title.length() < size));
824         
825         size = rand.nextInt(rubbos.getStoryMaximumLength());
826         do
827           body += randomWordFromDictionary(true);
828         while ((body != null) && (body.length() < size));
829
830         int[] pos = randomComputeLastIndex("OPTION value=\"", false);
831         if (pos == null)
832           return null;
833         Integer JavaDoc categoryId = new Integer JavaDoc(lastHTMLReply.substring(pos[0], pos[1]));
834         return urlGen.storeStory(username, password, title, body, categoryId.intValue());
835       }
836     case 15: // Search
837
return urlGen.search(null, null, 0, 0);
838     case 16: // Search stories
839
{
840         if (lastSearch != 17)
841           lastRandomWord = randomWordFromDictionary(false); // Generate randomly a word to look for
842
lastSearch = 17;
843         return urlGen.search(lastRandomWord, "0", extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());
844       }
845     case 17: // Search comments
846
{
847         if (lastSearch != 18)
848           lastRandomWord = randomWordFromDictionary(false);
849         lastSearch = 18;
850         return urlGen.search(lastRandomWord, "1", extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());
851       }
852     case 18: // Search users
853
{
854         if (lastSearch != 19) // Generate randomly a user to look for
855
lastRandomWord = "user"+(rand.nextInt(rubbos.getNbOfUsers())+1);
856         lastSearch = 19;
857         return urlGen.search(lastRandomWord, "2", extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());
858       }
859     case 19: // Author login
860
return urlGen.authorLogin();
861     case 20: // Author tasks
862
return urlGen.authorTasks(username, password);
863     case 21: // Review stories
864
return urlGen.reviewStories();
865     case 22: // Accept story
866
{
867         Integer JavaDoc storyId = extractAcceptRejectStoryIdFromHTML(urlGen.AcceptStoryScript());
868         if (storyId == null)
869         { // No more stories to process go back to home page
870
transition.resetToInitialState();
871           return urlGen.homePage();
872         }
873         else
874           return urlGen.acceptStory(storyId.intValue());
875       }
876     case 23: // Reject story
877
{
878         Integer JavaDoc storyId = extractAcceptRejectStoryIdFromHTML(urlGen.RejectStoryScript());
879         if (storyId == null)
880         { // No more stories to process go back to home page
881
transition.resetToInitialState();
882           return urlGen.homePage();
883         }
884         else
885           return urlGen.rejectStory(storyId.intValue());
886       }
887     default:
888       if (debugLevel > 0)
889         System.err.println("Thread "+this.getName()+": This state is not supported ("+state+")<br>");
890       return null;
891     }
892   }
893
894
895   /**
896    * Emulate a user session using the current transition table.
897    */

898   public void run()
899   {
900     int nbOfTransitions;
901     int next;
902     long time;
903     long startSession, endSession;
904
905     GregorianCalendar JavaDoc cal = new GregorianCalendar JavaDoc();
906     thisYear = cal.get(GregorianCalendar.YEAR);
907     try
908     {
909       dictionary = new RandomAccessFile JavaDoc(rubbos.getStoryDictionary(), "r");
910       String JavaDoc test = dictionary.readLine();
911     }
912     catch (Exception JavaDoc e)
913     {
914       System.err.println("Unable to open dictionary file '"+rubbos.getStoryDictionary()+"' (got exception: "+e.getMessage()+")<br>");
915       return ;
916     }
917
918     while (!ClientEmulator.isEndOfSimulation())
919     {
920       // Select a random user for this session
921
if (isAuthorSession)
922       {
923         userId = rand.nextInt(rubbos.getNbOfAuthors());
924         username = "author"+(userId+1);
925       }
926       else
927       {
928         userId = rand.nextInt(rubbos.getNbOfUsers());
929         username = "user"+(userId+1);
930       }
931       password = "password"+(userId+1);
932       nbOfTransitions = rubbos.getMaxNbOfTransitions();
933       if (debugLevel > 2)
934         System.out.println("Thread "+this.getName()+": Starting a new user session for "+username+" ...<br>");
935       startSession = System.currentTimeMillis();
936       // Start from Home Page
937
transition.resetToInitialState();
938       next = transition.getCurrentState();
939       while (!ClientEmulator.isEndOfSimulation() && !transition.isEndOfSession() && (nbOfTransitions > 0))
940       {
941         // Compute next step and call HTTP server (also measure time spend in server call)
942
lastURL = computeURLFromState(next);
943         if (lastURL == null)
944         {
945           System.out.println("Thread "+this.getName()+": Fatal error in computing next URL. Restarting from home page.<br>");
946           transition.resetToInitialState();
947           lastURL = urlGen.homePage();
948         }
949         time = System.currentTimeMillis();
950         lastHTMLReply = callHTTPServer(lastURL);
951         stats.updateTime(next, System.currentTimeMillis() - time);
952
953         // If an error occured, reset to Home page
954
if ((lastHTMLReply == null) || (lastHTMLReply.indexOf("ERROR") != -1))
955         {
956           if (debugLevel > 0)
957             System.out.println("Thread "+this.getName()+": Error returned from access to "+lastURL+"<br>");
958           stats.incrementError(next);
959           if (debugLevel > 1)
960             System.out.println("Thread "+this.getName()+": HTML reply was: "+lastHTMLReply+"<br>");
961           transition.resetToInitialState();
962           next = transition.getCurrentState();
963         }
964         else
965           next = transition.nextState();
966         nbOfTransitions--;
967       }
968       if ((transition.isEndOfSession()) || (nbOfTransitions == 0))
969       {
970         if (debugLevel > 2)
971           System.out.println("Thread "+this.getName()+": Session of "+username+" successfully ended<br>");
972         endSession= System.currentTimeMillis();
973         long sessionTime = endSession - startSession;
974         stats.addSessionTime(sessionTime);
975       }
976       else
977       {
978         if (debugLevel > 2)
979           System.out.println("Thread "+this.getName()+": Session of "+username+" aborted<br>");
980       }
981     }
982     try
983     {
984       dictionary.close();
985     }
986     catch (Exception JavaDoc e)
987     {
988       System.err.println("Unable to close dictionary file '"+rubbos.getStoryDictionary()+"' (got exception: "+e.getMessage()+")<br>");
989     }
990   }
991
992 }
993
Popular Tags