Author: bago
Date: Tue Jun 24 03:19:18 2008
New Revision: 671115

URL: http://svn.apache.org/viewvc?rev=671115&view=rev
Log:
Reflection-based approach to implementation specific transports/exception. This 
allow use of sun's and geronimo implementations with the same code and no build 
time dependency (JAMES-843)

Modified:
    
james/server/trunk/mailets-function/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java

Modified: 
james/server/trunk/mailets-function/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/mailets-function/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java?rev=671115&r1=671114&r2=671115&view=diff
==============================================================================
--- 
james/server/trunk/mailets-function/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
 (original)
+++ 
james/server/trunk/mailets-function/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
 Tue Jun 24 03:19:18 2008
@@ -42,11 +42,6 @@
 import org.apache.oro.text.regex.Perl5Compiler;
 import org.apache.oro.text.regex.Perl5Matcher;
 
-import com.sun.mail.smtp.SMTPAddressFailedException;
-import com.sun.mail.smtp.SMTPAddressSucceededException;
-import com.sun.mail.smtp.SMTPSendFailedException;
-import com.sun.mail.smtp.SMTPTransport;
-
 import javax.mail.Address;
 import javax.mail.MessagingException;
 import javax.mail.SendFailedException;
@@ -61,6 +56,8 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.net.ConnectException;
 import java.net.InetAddress;
 import java.net.SocketException;
@@ -398,8 +395,8 @@
      * @param e The MessagingException to use
      * @return logString
      */
-    private String exceptionToLogString(MessagingException e) {
-        if (e instanceof SMTPSendFailedException) {
+    private String exceptionToLogString(Exception e) {
+        if (e.getClass().getName().endsWith(".SMTPSendFailedException")) {
               return "RemoteHost said: " + e.getMessage();
         } else if (e instanceof SendFailedException) {
             SendFailedException exception  = (SendFailedException) e;
@@ -413,12 +410,19 @@
              boolean smtpExFound = false;
              sb.append("RemoteHost said:");
 
-             while((ex = e.getNextException()) != null & ex instanceof 
MessagingException) {
-                 e = (MessagingException)ex;
-                 if (ex instanceof SMTPAddressFailedException) {
-                     SMTPAddressFailedException exc = 
(SMTPAddressFailedException) ex;
-                     sb.append(" ( " + exc.getAddress() + " - [" + 
exc.getMessage().replaceAll("\\n", "") + "] )");
-                     smtpExFound = true;
+             
+             if (e instanceof MessagingException) while((ex = 
((MessagingException) e).getNextException()) != null && ex instanceof 
MessagingException) {
+                 e = ex;
+                 if 
(ex.getClass().getName().endsWith(".SMTPAddressFailedException")) {
+                     try {
+                         InternetAddress ia = (InternetAddress) 
invokeGetter(ex, "getAddress");
+                         sb.append(" ( " + ia + " - [" + 
ex.getMessage().replaceAll("\\n", "") + "] )");
+                         smtpExFound = true;
+                     } catch (IllegalStateException ise) {
+                         // Error invoking the getAddress method
+                     } catch (ClassCastException cce) {
+                         // The getAddress method returned something different 
than InternetAddress
+                     }
                  } 
              }
              if (!smtpExFound) {
@@ -441,6 +445,28 @@
         }
         return null;
     }
+    
+    /**
+     * Utility method used to invoke getters for javamail implementation 
specific classes.
+     * 
+     * @param target the object whom method will be invoked
+     * @param getter the no argument method name
+     * @return the result object
+     * @throws IllegalStateException on invocation error
+     */
+    private Object invokeGetter(Object target, String getter) {
+        try {
+            Method getAddress = target.getClass().getMethod(getter, null);
+            return getAddress.invoke(target, null);
+        } catch (NoSuchMethodException nsme) {
+            // An SMTPAddressFailedException with no getAddress method.
+        } catch (IllegalAccessException iae) {
+        } catch (IllegalArgumentException iae) {
+        } catch (InvocationTargetException ite) {
+            // Other issues with getAddress invokation.
+        }
+        return new IllegalStateException("Exception invoking "+getter+" on a 
"+target.getClass()+" object");
+    }
 
     /*
      * private method to log the extended SendFailedException introduced in 
JavaMail 1.3.2.
@@ -448,35 +474,45 @@
     private void logSendFailedException(SendFailedException sfe) {
         if (isDebug) {
             MessagingException me = sfe;
-            if (me instanceof SMTPSendFailedException) {
-                SMTPSendFailedException ssfe = (SMTPSendFailedException)me;
-                log("SMTP SEND FAILED:");
-                log(ssfe.toString());
-                log("  Command: " + ssfe.getCommand());
-                log("  RetCode: " + ssfe.getReturnCode());
-                log("  Response: " + ssfe.getMessage());
+            if (me.getClass().getName().endsWith(".SMTPSendFailedException")) {
+                try {
+                    String command = (String) invokeGetter(sfe, "getCommand");
+                    Integer returnCode = (Integer) invokeGetter(sfe, 
"getReturnCode");
+                    log("SMTP SEND FAILED:");
+                    log(sfe.toString());
+                    log("  Command: " + command);
+                    log("  RetCode: " + returnCode);
+                    log("  Response: " + sfe.getMessage());
+                } catch (IllegalStateException ise) {
+                    // Error invoking the getAddress method
+                    log("Send failed: " + me.toString());
+                } catch (ClassCastException cce) {
+                    // The getAddress method returned something different than 
InternetAddress
+                    log("Send failed: " + me.toString());
+                }
             } else {
                 log("Send failed: " + me.toString());
             }
             Exception ne;
             while ((ne = me.getNextException()) != null && ne instanceof 
MessagingException) {
                 me = (MessagingException)ne;
-                if (me instanceof SMTPAddressFailedException) {
-                    SMTPAddressFailedException e = 
(SMTPAddressFailedException)me;
-                    log("ADDRESS FAILED:");
-                    log(e.toString());
-                    log("  Address: " + e.getAddress());
-                    log("  Command: " + e.getCommand());
-                    log("  RetCode: " + e.getReturnCode());
-                    log("  Response: " + e.getMessage());
-                } else if (me instanceof SMTPAddressSucceededException) {
-                    log("ADDRESS SUCCEEDED:");
-                    SMTPAddressSucceededException e = 
(SMTPAddressSucceededException)me;
-                    log(e.toString());
-                    log("  Address: " + e.getAddress());
-                    log("  Command: " + e.getCommand());
-                    log("  RetCode: " + e.getReturnCode());
-                    log("  Response: " + e.getMessage());
+                if 
(me.getClass().getName().endsWith(".SMTPAddressFailedException") || 
me.getClass().getName().endsWith(".SMTPAddressSucceededException")) {
+                    try {
+                        String action = 
me.getClass().getName().endsWith(".SMTPAddressFailedException") ? "FAILED" : 
"SUCCEEDED";
+                        InternetAddress address = (InternetAddress) 
invokeGetter(me, "getAddress");
+                        String command = (String) invokeGetter(me, 
"getCommand");
+                        Integer returnCode = (Integer) invokeGetter(me, 
"getReturnCode");
+                        log("ADDRESS "+action+":");
+                        log(me.toString());
+                        log("  Address: " + address);
+                        log("  Command: " + command);
+                        log("  RetCode: " + returnCode);
+                        log("  Response: " + me.getMessage());
+                    } catch (IllegalStateException ise) {
+                        // Error invoking the getAddress method
+                    } catch (ClassCastException cce) {
+                        // A method returned something different than expected
+                    }
                 }
             }
         }
@@ -610,8 +646,18 @@
                         }
                         // if the transport is a SMTPTransport (from sun) some
                         // performance enhancement can be done.
-                        if (transport instanceof SMTPTransport)  {
-                            SMTPTransport smtpTransport = (SMTPTransport) 
transport;
+                        if 
(transport.getClass().getName().endsWith(".SMTPTransport"))  {
+                            boolean supports8bitmime = false;
+                            try {
+                                Method supportsExtension = 
transport.getClass().getMethod("supportsExtension", new Class[] {String.class});
+                                supports8bitmime = ((Boolean) 
supportsExtension.invoke(transport, new Object[] {"8BITMIME"})).booleanValue();
+                            } catch (NoSuchMethodException nsme) {
+                                // An SMTPAddressFailedException with no 
getAddress method.
+                            } catch (IllegalAccessException iae) {
+                            } catch (IllegalArgumentException iae) {
+                            } catch (InvocationTargetException ite) {
+                                // Other issues with getAddress invokation.
+                            }
                            
                             // if the message is alredy 8bit or binary and the
                             // server doesn't support the 8bit extension it has
@@ -620,7 +666,7 @@
                             // rfc-compliant smtp server.
                             
                             // Temporarily disabled. See JAMES-638
-                            if (!smtpTransport.supportsExtension("8BITMIME")) 
{ 
+                            if (!supports8bitmime) {
                                 try {
                                     convertTo7Bit(message);
                                 } catch (IOException e) {
@@ -677,10 +723,14 @@
                     }
 
                     /* SMTPSendFailedException introduced in JavaMail 1.3.2, 
and provides detailed protocol reply code for the operation */
-                    if (sfe instanceof SMTPSendFailedException) {
-                        SMTPSendFailedException ssfe = 
(SMTPSendFailedException) sfe;
-                        // if 5xx, terminate this delivery attempt by 
re-throwing the exception.
-                        if (ssfe.getReturnCode() >= 500 && 
ssfe.getReturnCode() <= 599) throw sfe;
+                    if 
(sfe.getClass().getName().endsWith(".SMTPSendFailedException")) {
+                        try {
+                            int returnCode = ((Integer) invokeGetter(sfe, 
"getReturnCode")).intValue();
+                            // if 5xx, terminate this delivery attempt by 
re-throwing the exception.
+                            if (returnCode >= 500 && returnCode <= 599) throw 
sfe;
+                        } catch (ClassCastException cce) {
+                        } catch (IllegalArgumentException iae) {
+                        }
                     }
 
                     if (sfe.getValidUnsentAddresses() != null
@@ -756,21 +806,27 @@
              */
 
             /* SMTPSendFailedException introduced in JavaMail 1.3.2, and 
provides detailed protocol reply code for the operation */
-            if (sfe instanceof SMTPSendFailedException) {
-                // If we got an SMTPSendFailedException, use its RetCode to 
determine default permanent/temporary failure
-                SMTPSendFailedException ssfe = (SMTPSendFailedException) sfe;
-                deleteMessage = (ssfe.getReturnCode() >= 500 && 
ssfe.getReturnCode() <= 599);
-            } else {
-                // Sometimes we'll get a normal SendFailedException with 
nested SMTPAddressFailedException, so use the latter RetCode
-                MessagingException me = sfe;
-                Exception ne;
-                while ((ne = me.getNextException()) != null && ne instanceof 
MessagingException) {
-                    me = (MessagingException)ne;
-                    if (me instanceof SMTPAddressFailedException) {
-                        SMTPAddressFailedException ssfe = 
(SMTPAddressFailedException)me;
-                        deleteMessage = (ssfe.getReturnCode() >= 500 && 
ssfe.getReturnCode() <= 599);
+            try {
+                if 
(sfe.getClass().getName().endsWith(".SMTPSendFailedException")) {
+                    int returnCode = ((Integer) invokeGetter(sfe, 
"getReturnCode")).intValue();
+                    // If we got an SMTPSendFailedException, use its RetCode 
to determine default permanent/temporary failure
+                    deleteMessage = (returnCode >= 500 && returnCode <= 599);
+                } else {
+                    // Sometimes we'll get a normal SendFailedException with 
nested SMTPAddressFailedException, so use the latter RetCode
+                    MessagingException me = sfe;
+                    Exception ne;
+                    while ((ne = me.getNextException()) != null && ne 
instanceof MessagingException) {
+                        me = (MessagingException)ne;
+                        if 
(me.getClass().getName().endsWith(".SMTPAddressFailedException")) {
+                            int returnCode = ((Integer) invokeGetter(me, 
"getReturnCode")).intValue();
+                            deleteMessage = (returnCode >= 500 && returnCode 
<= 599);
+                        }
                     }
                 }
+            } catch (IllegalStateException ise) {
+                // unexpected exception (not a compatible javamail 
implementation)
+            } catch (ClassCastException cce) {
+                // unexpected exception (not a compatible javamail 
implementation)
             }
 
             // log the original set of intended recipients
@@ -810,9 +866,9 @@
                         }
                     }
                     if (isDebug) log("Unsent recipients: " + recipients);
-                    if (sfe instanceof SMTPSendFailedException) {
-                        SMTPSendFailedException ssfe = 
(SMTPSendFailedException) sfe;
-                        deleteMessage = failMessage(mail, sfe, 
ssfe.getReturnCode() >= 500 && ssfe.getReturnCode() <= 599);
+                    if 
(sfe.getClass().getName().endsWith(".SMTPSendFailedException")) {
+                        int returnCode = ((Integer) invokeGetter(sfe, 
"getReturnCode")).intValue();
+                        deleteMessage = failMessage(mail, sfe, returnCode >= 
500 && returnCode <= 599);
                     } else {
                         deleteMessage = failMessage(mail, sfe, false);
                     }
@@ -833,6 +889,9 @@
             // or mailbox is full or domain is setup wrong).
             // We fail permanently if this was a 5xx error
             return failMessage(mail, ex, ('5' == ex.getMessage().charAt(0)));
+        } catch (Exception ex) {
+            // Generic exception = permanent failure
+            return failMessage(mail, ex, true);
         }
 
         /* If we get here, we've exhausted the loop of servers without
@@ -876,7 +935,7 @@
      * @param permanent
      * @return boolean Whether the message failed fully and can be deleted
      */
-    private boolean failMessage(Mail mail, MessagingException ex, boolean 
permanent) {
+    private boolean failMessage(Mail mail, Exception ex, boolean permanent) {
         StringWriter sout = new StringWriter();
         PrintWriter out = new PrintWriter(sout, true);
         if (permanent) {
@@ -965,7 +1024,7 @@
         return true;
     }
 
-    private void bounce(Mail mail, MessagingException ex) {
+    private void bounce(Mail mail, Exception ex) {
         StringWriter sout = new StringWriter();
         PrintWriter out = new PrintWriter(sout, true);
         String machine = "[unknown]";
@@ -989,22 +1048,24 @@
         for (Iterator i = mail.getRecipients().iterator(); i.hasNext(); ) {
             out.println(i.next());
         }
-        if (ex.getNextException() == null) {
-            out.println(ex.getMessage().trim());
-        } else {
-            Exception ex1 = ex.getNextException();
-            if (ex1 instanceof SendFailedException) {
-                out.println("Remote mail server told me: " + 
ex1.getMessage().trim());
-            } else if (ex1 instanceof UnknownHostException) {
-                out.println("Unknown host: " + ex1.getMessage().trim());
-                out.println("This could be a DNS server error, a typo, or a 
problem with the recipient's mail server.");
-            } else if (ex1 instanceof ConnectException) {
-                //Already formatted as "Connection timed out: connect"
-                out.println(ex1.getMessage().trim());
-            } else if (ex1 instanceof SocketException) {
-                out.println("Socket exception: " + ex1.getMessage().trim());
+        if (ex instanceof MessagingException) {
+            if (((MessagingException) ex).getNextException() == null) {
+                out.println(ex.getMessage().trim());
             } else {
-                out.println(ex1.getMessage().trim());
+                Exception ex1 = ((MessagingException) ex).getNextException();
+                if (ex1 instanceof SendFailedException) {
+                    out.println("Remote mail server told me: " + 
ex1.getMessage().trim());
+                } else if (ex1 instanceof UnknownHostException) {
+                    out.println("Unknown host: " + ex1.getMessage().trim());
+                    out.println("This could be a DNS server error, a typo, or 
a problem with the recipient's mail server.");
+                } else if (ex1 instanceof ConnectException) {
+                    //Already formatted as "Connection timed out: connect"
+                    out.println(ex1.getMessage().trim());
+                } else if (ex1 instanceof SocketException) {
+                    out.println("Socket exception: " + 
ex1.getMessage().trim());
+                } else {
+                    out.println(ex1.getMessage().trim());
+                }
             }
         }
         out.println();
@@ -1176,7 +1237,7 @@
         
         props.putAll(defprops);
 
-        Session session = Session.getInstance(props, null);
+        Session session = obtainSession(props);
         try {
             while (!Thread.interrupted() && !destroyed) {
                 try {
@@ -1244,6 +1305,16 @@
     }
     
     /**
+     * Returns the javamail Session object.
+     * @param props
+     * @param authenticator 
+     * @return
+     */
+    protected Session obtainSession(Properties props) {
+        return Session.getInstance(props);
+    }
+    
+    /**
      * This method expands an ArrayList containing Delay objects into an array 
holding the
      * only delaytime in the order.<p>
      * So if the list has 2 Delay objects the first having attempts=2 and 
delaytime 4000
@@ -1453,4 +1524,12 @@
             }
         };
     }
+    
+    /**
+     * Setter for the dnsserver service
+     * @param dnsServer dns service
+     */
+    protected synchronized void setDNSServer(DNSServer dnsServer) {
+        this.dnsServer = dnsServer;
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to