1 17 18 package org.apache.james.fetchmail; 19 20 import java.util.ArrayList ; 21 import java.util.Collections ; 22 import java.util.Enumeration ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Properties ; 28 29 import javax.mail.MessagingException ; 30 import javax.mail.Session ; 31 32 import org.apache.avalon.cornerstone.services.scheduler.Target; 33 import org.apache.avalon.framework.configuration.Configurable; 34 import org.apache.avalon.framework.configuration.Configuration; 35 import org.apache.avalon.framework.configuration.ConfigurationException; 36 import org.apache.avalon.framework.logger.AbstractLogEnabled; 37 import org.apache.avalon.framework.service.ServiceException; 38 import org.apache.avalon.framework.service.ServiceManager; 39 import org.apache.james.services.MailServer; 40 import org.apache.james.services.UsersRepository; 41 import org.apache.james.services.UsersStore; 42 43 72 public class FetchMail extends AbstractLogEnabled implements Configurable, Target 73 { 74 77 private class DynamicAccountKey 78 { 79 82 private String fieldUserName; 83 84 87 private int fieldSequenceNumber; 88 89 92 private DynamicAccountKey() 93 { 94 super(); 95 } 96 97 100 public DynamicAccountKey(String userName, int sequenceNumber) 101 { 102 this(); 103 setUserName(userName); 104 setSequenceNumber(sequenceNumber); 105 } 106 107 110 public boolean equals(Object obj) 111 { 112 if (null == obj) 113 return false; 114 if (!(obj.getClass() == getClass())) 115 return false; 116 return ( 117 getUserName().equals(((DynamicAccountKey) obj).getUserName()) 118 && getSequenceNumber() 119 == ((DynamicAccountKey) obj).getSequenceNumber()); 120 } 121 122 125 public int hashCode() 126 { 127 return getUserName().hashCode() ^ getSequenceNumber(); 128 } 129 130 134 public int getSequenceNumber() 135 { 136 return fieldSequenceNumber; 137 } 138 139 143 public String getUserName() 144 { 145 return fieldUserName; 146 } 147 148 152 protected void setSequenceNumber(int sequenceNumber) 153 { 154 fieldSequenceNumber = sequenceNumber; 155 } 156 157 161 protected void setUserName(String userName) 162 { 163 fieldUserName = userName; 164 } 165 166 } 167 170 private class ParsedDynamicAccountParameters 171 { 172 private String fieldUserPrefix; 173 private String fieldUserSuffix; 174 175 private String fieldPassword; 176 177 private int fieldSequenceNumber; 178 179 private boolean fieldIgnoreRecipientHeader; 180 private String fieldRecipientPrefix; 181 private String fieldRecipientSuffix; 182 183 186 private ParsedDynamicAccountParameters() 187 { 188 super(); 189 } 190 191 194 public ParsedDynamicAccountParameters( 195 int sequenceNumber, 196 Configuration configuration) 197 throws ConfigurationException 198 { 199 this(); 200 setSequenceNumber(sequenceNumber); 201 setUserPrefix(configuration.getAttribute("userprefix", "")); 202 setUserSuffix(configuration.getAttribute("usersuffix", "")); 203 setRecipientPrefix(configuration.getAttribute("recipientprefix", "")); 204 setRecipientSuffix(configuration.getAttribute("recipientsuffix", "")); 205 setPassword(configuration.getAttribute("password")); 206 setIgnoreRecipientHeader( 207 configuration.getAttributeAsBoolean("ignorercpt-header")); 208 } 209 210 214 public String getRecipientPrefix() 215 { 216 return fieldRecipientPrefix; 217 } 218 219 223 public String getRecipientSuffix() 224 { 225 return fieldRecipientSuffix; 226 } 227 228 232 public String getUserPrefix() 233 { 234 return fieldUserPrefix; 235 } 236 237 241 public String getUserSuffix() 242 { 243 return fieldUserSuffix; 244 } 245 246 250 protected void setRecipientPrefix(String recipientprefix) 251 { 252 fieldRecipientPrefix = recipientprefix; 253 } 254 255 259 protected void setRecipientSuffix(String recipientsuffix) 260 { 261 fieldRecipientSuffix = recipientsuffix; 262 } 263 264 268 protected void setUserPrefix(String userprefix) 269 { 270 fieldUserPrefix = userprefix; 271 } 272 273 277 protected void setUserSuffix(String userSuffix) 278 { 279 fieldUserSuffix = userSuffix; 280 } 281 282 286 public String getPassword() 287 { 288 return fieldPassword; 289 } 290 291 295 protected void setIgnoreRecipientHeader(boolean ignoreRecipientHeader) 296 { 297 fieldIgnoreRecipientHeader = ignoreRecipientHeader; 298 } 299 300 304 protected void setPassword(String password) 305 { 306 fieldPassword = password; 307 } 308 309 313 public boolean isIgnoreRecipientHeader() 314 { 315 return fieldIgnoreRecipientHeader; 316 } 317 318 322 public int getSequenceNumber() 323 { 324 return fieldSequenceNumber; 325 } 326 327 331 protected void setSequenceNumber(int sequenceNumber) 332 { 333 fieldSequenceNumber = sequenceNumber; 334 } 335 336 } 337 340 private boolean fieldFetching = false; 341 342 345 private ParsedConfiguration fieldConfiguration; 346 347 351 private List fieldParsedDynamicAccountParameters; 352 353 357 private List fieldStaticAccounts; 358 359 362 363 private Session fieldSession; 364 365 369 private Map fieldDynamicAccounts; 370 371 374 private MailServer fieldServer; 375 376 379 private UsersRepository fieldLocalUsers; 380 381 384 public FetchMail() 385 { 386 super(); 387 } 388 389 397 public void configure(Configuration configuration) 398 throws ConfigurationException 399 { 400 setSessionParameters(configuration); 402 403 ParsedConfiguration parsedConfiguration = 405 new ParsedConfiguration( 406 configuration, 407 getLogger(), 408 getServer(), 409 getLocalUsers()); 410 setConfiguration(parsedConfiguration); 411 412 Configuration[] allAccounts = configuration.getChildren("accounts"); 414 if (allAccounts.length < 1) 415 throw new ConfigurationException("Missing <accounts> section."); 416 if (allAccounts.length > 1) 417 throw new ConfigurationException("Too many <accounts> sections, there must be exactly one"); 418 Configuration accounts = allAccounts[0]; 419 420 Configuration[] accountsChildren = accounts.getChildren(); 422 if (accountsChildren.length < 1) 423 throw new ConfigurationException("Missing <account> section."); 424 425 for (int i = 0; i < accountsChildren.length; i++) 426 { 427 Configuration accountsChild = accountsChildren[i]; 428 429 if (accountsChild.getName() == "alllocal") 430 { 431 getParsedDynamicAccountParameters().add( 434 new ParsedDynamicAccountParameters(i, accountsChild)); 435 continue; 436 } 437 438 if (accountsChild.getName() == "account") 439 { 440 getStaticAccounts().add( 443 new Account( 444 i, 445 parsedConfiguration, 446 accountsChild.getAttribute("user"), 447 accountsChild.getAttribute("password"), 448 accountsChild.getAttribute("recipient"), 449 accountsChild.getAttributeAsBoolean( 450 "ignorercpt-header"), 451 getSession())); 452 continue; 453 } 454 455 throw new ConfigurationException( 456 "Illegal token: <" 457 + accountsChild.getName() 458 + "> in <accounts>"); 459 } 460 } 461 462 467 public void targetTriggered(String arg0) 468 { 469 if (isFetching()) 471 { 472 getLogger().info( 473 "Triggered fetch cancelled. A fetch is already in progress."); 474 return; 475 } 476 477 try 479 { 480 setFetching(true); 481 getLogger().info("Fetcher starting fetches"); 482 483 if (getLogger().isDebugEnabled()) 486 { 487 getLogger().debug("Session properties:"); 488 Properties properties = getSession().getProperties(); 489 Enumeration e = properties.keys(); 490 while (e.hasMoreElements()) 491 { 492 String key = (String ) e.nextElement(); 493 String val = (String ) properties.get(key); 494 if (val.length() > 40) 495 { 496 val = val.substring(0, 37) + "..."; 497 } 498 getLogger().debug(key + "=" + val); 499 500 } 501 } 502 503 updateDynamicAccounts(); 508 ArrayList mergedAccounts = 509 new ArrayList ( 510 getDynamicAccounts().size() + getStaticAccounts().size()); 511 mergedAccounts.addAll(getDynamicAccounts().values()); 512 mergedAccounts.addAll(getStaticAccounts()); 513 Collections.sort(mergedAccounts); 514 515 StringBuffer logMessage = new StringBuffer (64); 516 logMessage.append("Processing "); 517 logMessage.append(getStaticAccounts().size()); 518 logMessage.append(" static accounts and "); 519 logMessage.append(getDynamicAccounts().size()); 520 logMessage.append(" dynamic accounts."); 521 getLogger().info(logMessage.toString()); 522 523 Iterator accounts = mergedAccounts.iterator(); 525 while (accounts.hasNext()) 526 { 527 try 528 { 529 new StoreProcessor((Account) accounts.next()).process(); 530 } 531 catch (MessagingException ex) 532 { 533 getLogger().error( 534 "A MessagingException has terminated processing of this Account", 535 ex); 536 } 537 } 538 } 539 catch (Exception ex) 540 { 541 getLogger().error("An Exception has terminated this fetch.", ex); 542 } 543 finally 544 { 545 getLogger().info("Fetcher completed fetches"); 546 547 setFetching(false); 549 } 550 } 551 552 556 protected boolean isFetching() 557 { 558 return fieldFetching; 559 } 560 561 564 public void service(final ServiceManager manager) throws ServiceException 565 { 566 try 567 { 568 setServer((MailServer) manager.lookup(MailServer.ROLE)); 569 } 570 catch (ClassCastException cce) 571 { 572 StringBuffer errorBuffer = 573 new StringBuffer (128).append("Component ").append( 574 MailServer.ROLE).append( 575 "does not implement the required interface."); 576 throw new ServiceException("", errorBuffer.toString()); 577 } 578 579 UsersStore usersStore = 580 (UsersStore) manager.lookup("org.apache.james.services.UsersStore"); 581 setLocalUsers(usersStore.getRepository("LocalUsers")); 582 if (getLocalUsers() == null) 583 throw new ServiceException( 584 "", 585 "The user repository could not be found."); 586 } 587 588 589 590 591 592 593 597 protected void setFetching(boolean fetching) 598 { 599 fieldFetching = fetching; 600 } 601 602 606 protected MailServer getServer() 607 { 608 return fieldServer; 609 } 610 611 615 protected ParsedConfiguration getConfiguration() 616 { 617 return fieldConfiguration; 618 } 619 620 624 protected void setConfiguration(ParsedConfiguration configuration) 625 { 626 fieldConfiguration = configuration; 627 } 628 629 633 protected void setServer(MailServer server) 634 { 635 fieldServer = server; 636 } 637 638 642 protected UsersRepository getLocalUsers() 643 { 644 return fieldLocalUsers; 645 } 646 647 651 protected void setLocalUsers(UsersRepository localUsers) 652 { 653 fieldLocalUsers = localUsers; 654 } 655 656 660 protected List getStaticAccounts() 661 { 662 List accounts = null; 663 if (null == (accounts = getStaticAccountsBasic())) 664 { 665 updateStaticAccounts(); 666 return getStaticAccounts(); 667 } 668 return fieldStaticAccounts; 669 } 670 671 675 private List getStaticAccountsBasic() 676 { 677 return fieldStaticAccounts; 678 } 679 680 684 protected void setStaticAccounts(List accounts) 685 { 686 fieldStaticAccounts = accounts; 687 } 688 689 692 protected void updateStaticAccounts() 693 { 694 setStaticAccounts(computeStaticAccounts()); 695 } 696 697 700 protected void updateParsedDynamicAccountParameters() 701 { 702 setParsedDynamicAccountParameters(computeParsedDynamicAccountParameters()); 703 } 704 705 708 protected void updateDynamicAccounts() throws ConfigurationException 709 { 710 setDynamicAccounts(computeDynamicAccounts()); 711 } 712 713 716 protected List computeStaticAccounts() 717 { 718 return new ArrayList (); 719 } 720 721 724 protected List computeParsedDynamicAccountParameters() 725 { 726 return new ArrayList (); 727 } 728 729 732 protected Map computeDynamicAccounts() throws ConfigurationException 733 { 734 Map newAccounts = 735 new HashMap ( 736 getLocalUsers().countUsers() 737 * getParsedDynamicAccountParameters().size()); 738 Map oldAccounts = getDynamicAccountsBasic(); 739 if (null == oldAccounts) 740 oldAccounts = new HashMap (0); 741 742 Iterator parameterIterator = 743 getParsedDynamicAccountParameters().iterator(); 744 745 while (parameterIterator.hasNext()) 747 { 748 Map accounts = 749 computeDynamicAccounts( 750 oldAccounts, 751 (ParsedDynamicAccountParameters) parameterIterator.next()); 752 Iterator oldAccountsIterator = oldAccounts.keySet().iterator(); 756 while (oldAccountsIterator.hasNext()) 757 { 758 if (accounts.containsKey(oldAccountsIterator.next())) 759 oldAccountsIterator.remove(); 760 } 761 newAccounts.putAll(accounts); 763 } 764 return newAccounts; 765 } 766 767 771 protected Map getDynamicAccounts() throws ConfigurationException 772 { 773 Map accounts = null; 774 if (null == (accounts = getDynamicAccountsBasic())) 775 { 776 updateDynamicAccounts(); 777 return getDynamicAccounts(); 778 } 779 return fieldDynamicAccounts; 780 } 781 782 786 private Map getDynamicAccountsBasic() 787 { 788 return fieldDynamicAccounts; 789 } 790 791 795 protected void setDynamicAccounts(Map dynamicAccounts) 796 { 797 fieldDynamicAccounts = dynamicAccounts; 798 } 799 800 809 protected Map computeDynamicAccounts( 810 Map oldAccounts, 811 ParsedDynamicAccountParameters parameters) 812 throws ConfigurationException 813 { 814 Map accounts = new HashMap (getLocalUsers().countUsers()); 815 Iterator usersIterator = getLocalUsers().list(); 816 while (usersIterator.hasNext()) 817 { 818 String userName = (String ) usersIterator.next(); 819 DynamicAccountKey key = 820 new DynamicAccountKey(userName, parameters.getSequenceNumber()); 821 Account account = (Account) oldAccounts.get(key); 822 if (null == account) 823 { 824 account = 826 new DynamicAccount( 827 parameters.getSequenceNumber(), 828 getConfiguration(), 829 userName, 830 parameters.getUserPrefix(), 831 parameters.getUserSuffix(), 832 parameters.getPassword(), 833 parameters.getRecipientPrefix(), 834 parameters.getRecipientSuffix(), 835 parameters.isIgnoreRecipientHeader(), 836 getSession()); 837 } 838 accounts.put(key, account); 839 } 840 return accounts; 841 } 842 845 protected void resetDynamicAccounts() 846 { 847 setDynamicAccounts(null); 848 } 849 850 854 protected List getParsedDynamicAccountParameters() 855 { 856 List accounts = null; 857 if (null == (accounts = getParsedDynamicAccountParametersBasic())) 858 { 859 updateParsedDynamicAccountParameters(); 860 return getParsedDynamicAccountParameters(); 861 } 862 return fieldParsedDynamicAccountParameters; 863 } 864 865 869 private List getParsedDynamicAccountParametersBasic() 870 { 871 return fieldParsedDynamicAccountParameters; 872 } 873 874 878 protected void setParsedDynamicAccountParameters(List parsedDynamicAccountParameters) 879 { 880 fieldParsedDynamicAccountParameters = parsedDynamicAccountParameters; 881 } 882 883 887 protected Session getSession() 888 { 889 Session session = null; 890 if (null == (session = getSessionBasic())) 891 { 892 updateSession(); 893 return getSession(); 894 } 895 return session; 896 } 897 898 902 private Session getSessionBasic() 903 { 904 return fieldSession; 905 } 906 907 911 protected Session computeSession() 912 { 913 return Session.getInstance(System.getProperties()); 914 } 915 916 919 protected void updateSession() 920 { 921 setSession(computeSession()); 922 } 923 924 928 protected void setSession(Session session) 929 { 930 fieldSession = session; 931 } 932 933 934 939 protected void setSessionParameters(Configuration configuration) 940 throws ConfigurationException 941 { 942 Configuration javaMailProperties = 943 configuration.getChild("javaMailProperties", false); 944 if (null != javaMailProperties) 945 { 946 Properties properties = getSession().getProperties(); 947 Configuration[] allProperties = 948 javaMailProperties.getChildren("property"); 949 for (int i = 0; i < allProperties.length; i++) 950 { 951 properties.setProperty( 952 allProperties[i].getAttribute("name"), 953 allProperties[i].getAttribute("value")); 954 if (getLogger().isDebugEnabled()) 955 { 956 StringBuffer messageBuffer = 957 new StringBuffer ("Set property name: "); 958 messageBuffer.append(allProperties[i].getAttribute("name")); 959 messageBuffer.append(" to: "); 960 messageBuffer.append( 961 allProperties[i].getAttribute("value")); 962 getLogger().debug(messageBuffer.toString()); 963 } 964 } 965 } 966 } 967 968 } 969 | Popular Tags |