1 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 44 public class IMAPCheckRateJobClass 45 extends JobClass 46 { 47 51 public static final String REQUEST_ID_PREFIX = "imaprate"; 52 53 54 55 59 public static final String STAT_TRACKER_IMAP_SESSIONS = "IMAP Sessions"; 60 61 62 63 67 public static final String STAT_TRACKER_FAILURE_COUNT = "Failed Logins"; 68 69 70 71 75 public static final String STAT_TRACKER_MESSAGE_COUNT = "Message Count"; 76 77 78 79 83 public static final String STAT_TRACKER_SESSION_DURATION = 84 "Session Duration (ms)"; 85 86 87 88 92 public static final String STAT_TRACKER_SUCCESS_COUNT = "Successful Logins"; 93 94 95 96 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 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 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 PlaceholderParameter placeholder = new PlaceholderParameter(); 118 119 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 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 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 imapAddress; 150 static String password; 151 static String userIDInitial; 152 static String userIDFinal; 153 154 155 static Random parentRandom; 157 Random random; 158 159 160 161 IncrementalTracker failureCounter; 163 IncrementalTracker sessionCounter; 164 IncrementalTracker successCounter; 165 IntegerValueTracker messageCountTracker; 166 TimeTracker sessionTimer; 167 168 169 170 171 177 public IMAPCheckRateJobClass() 178 { 179 super(); 180 } 181 182 183 184 189 public String getJobName() 190 { 191 return "IMAP CheckRate"; 192 } 193 194 195 196 201 public String 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 216 public String getJobCategoryName() 217 { 218 return "Mail"; 219 } 220 221 222 223 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 269 public StatTracker[] getStatTrackerStubs(String clientID, String 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 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 316 public boolean providesParameterTest() 317 { 318 return true; 319 } 320 321 322 323 350 public boolean testJobParameters(ParameterList parameters, 351 ArrayList outputMessages) 352 { 353 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 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 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 userPW = pwParam.getStringValue(); 392 393 394 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 e) 413 { 414 outputMessages.add("ERROR: Unable to connect: " + 415 stackTraceToString(e)); 416 return false; 417 } 418 419 420 try 422 { 423 outputMessages.add("Trying to read the hello string from the server...."); 424 425 String line = reader.readLine(); 426 427 outputMessages.add("Hello string was '" + line + "'."); 428 outputMessages.add(""); 429 } 430 catch (Exception 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 e2) {} 439 440 try 441 { 442 writer.close(); 443 } catch (Exception e2) {} 444 445 try 446 { 447 socket.close(); 448 } catch (Exception e2) {} 449 450 return false; 451 } 452 453 454 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 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 e2) {} 475 476 try 477 { 478 writer.close(); 479 } catch (Exception e2) {} 480 481 try 482 { 483 socket.close(); 484 } catch (Exception e2) {} 485 486 return false; 487 } 488 489 490 boolean loginSuccessful = false; 492 try 493 { 494 outputMessages.add("Trying to read the LOGIN response from the " + 495 "server...."); 496 497 String 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 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 e2) {} 515 516 try 517 { 518 writer.close(); 519 } catch (Exception e2) {} 520 521 try 522 { 523 socket.close(); 524 } catch (Exception e2) {} 525 526 return false; 527 } 528 529 530 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 e) {} 541 542 try 543 { 544 reader.close(); 545 } catch (Exception e) {} 546 547 try 548 { 549 writer.close(); 550 } catch (Exception e) {} 551 552 try 553 { 554 socket.close(); 555 } catch (Exception e) {} 556 557 558 outputMessages.add("All tests completed."); 559 return loginSuccessful; 560 } 561 562 563 564 576 public void initializeClient(String clientID, ParameterList parameters) 577 throws UnableToRunException 578 { 579 hostParameter = parameters.getStringParameter(hostParameter.getName()); 581 if (hostParameter != null) 582 { 583 imapAddress = hostParameter.getStringValue(); 584 } 585 586 portParameter = parameters.getIntegerParameter(portParameter.getName()); 588 if (portParameter != null) 589 { 590 imapPort = portParameter.getIntValue(); 591 } 592 593 useIDRange = false; 595 useSequentialID = false; 596 userIDParameter = parameters.getStringParameter(userIDParameter.getName()); 597 if (userIDParameter != null) 598 { 599 String 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 passwordParameter = 650 parameters.getPasswordParameter(passwordParameter.getName()); 651 if (passwordParameter != null) 652 { 653 password = passwordParameter.getStringValue(); 654 } 655 656 657 delayParameter = parameters.getIntegerParameter(delayParameter.getName()); 659 if (delayParameter != null) 660 { 661 delay = delayParameter.getIntValue(); 662 } 663 664 665 parentRandom = new Random(); 667 } 668 669 670 671 687 public void initializeThread(String clientID, String threadID, 688 int collectionInterval, ParameterList parameters) 689 throws UnableToRunException 690 { 691 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 RealTimeStatReporter statReporter = getStatReporter(); 711 if (statReporter != null) 712 { 713 String 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 random = new Random(parentRandom.nextLong()); 724 } 725 726 727 728 731 public void runJob() 732 { 733 boolean keepReading; 735 BufferedReader reader; 736 BufferedWriter writer; 737 int highestUID; 738 int idCounter; 739 long lastStartTime = 0; 740 Socket socket; 741 String line; 742 String lowerLine; 743 String request; 744 String userID; 745 746 747 sessionCounter.startTracker(); 749 sessionTimer.startTracker(); 750 messageCountTracker.startTracker(); 751 successCounter.startTracker(); 752 failureCounter.startTracker(); 753 754 755 mainLoop: 757 while (! shouldStop()) 758 { 759 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 e) {} 770 } 771 } 772 773 lastStartTime = System.currentTimeMillis(); 774 775 sessionCounter.increment(); 777 sessionTimer.startTimer(); 778 779 780 userID = getUserID(); 782 idCounter = 1; 783 784 785 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 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 e) {} 818 819 continue; 820 } 821 822 823 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 e) {} 843 844 continue; 845 } 846 847 848 keepReading = true; 851 while (keepReading) 852 { 853 try 854 { 855 line = reader.readLine(); 856 857 if (line == null) 858 { 859 keepReading = false; 861 sessionTimer.stopTimer(); 862 failureCounter.increment(); 863 864 try 865 { 866 reader.close(); 867 writer.close(); 868 socket.close(); 869 } catch (Exception 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 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 e) {} 904 905 continue mainLoop; 906 } 907 } 908 909 910 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 e) {} 930 931 continue; 932 } 933 934 935 highestUID = -1; 940 keepReading = true; 941 while (keepReading) 942 { 943 try 944 { 945 line = reader.readLine(); 946 if (line == null) 947 { 948 keepReading = false; 950 sessionTimer.stopTimer(); 951 failureCounter.increment(); 952 953 try 954 { 955 reader.close(); 956 writer.close(); 957 socket.close(); 958 } catch (Exception 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 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 tokenizer.nextToken(); 992 highestUID = Integer.parseInt(tokenizer.nextToken()); 993 } 994 catch (Exception e) 995 { 996 sessionTimer.stopTimer(); 997 failureCounter.increment(); 998 999 try 1000 { 1001 reader.close(); 1002 writer.close(); 1003 socket.close(); 1004 } catch (Exception 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 e) {} 1021 1022 continue mainLoop; 1023 } 1024 } 1025 1026 1027 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 e) {} 1040 1041 continue; 1042 } 1043 else 1044 { 1045 messageCountTracker.addValue(highestUID); 1046 } 1047 1048 1049 if (highestUID > 0) 1053 { 1054 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 e) {} 1076 1077 continue; 1078 } 1079 1080 1081 keepReading = true; 1084 while (keepReading) 1085 { 1086 try 1087 { 1088 line = reader.readLine(); 1089 if (line == null) 1090 { 1091 keepReading = false; 1093 sessionTimer.stopTimer(); 1094 failureCounter.increment(); 1095 1096 try 1097 { 1098 reader.close(); 1099 writer.close(); 1100 socket.close(); 1101 } catch (Exception 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 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 e) {} 1136 1137 continue mainLoop; 1138 } 1139 } 1140 } 1141 1142 1143 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 e) {} 1170 1171 continue; 1172 } 1173 } 1174 1175 1176 sessionCounter.stopTracker(); 1178 sessionTimer.stopTracker(); 1179 messageCountTracker.stopTracker(); 1180 successCounter.stopTracker(); 1181 failureCounter.stopTracker(); 1182 } 1183 1184 1185 1186 1191 public String 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 |