Issue 30: Binder.addError(Throwable); a little associated cleanup

git-svn-id: https://google-guice.googlecode.com/svn/trunk@245 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/AbstractModule.java b/src/com/google/inject/AbstractModule.java
index 408bbc8..1097b3f 100644
--- a/src/com/google/inject/AbstractModule.java
+++ b/src/com/google/inject/AbstractModule.java
@@ -156,6 +156,20 @@
   }
 
   /**
+   * @see Binder#addError(String, Object[])
+   */
+  protected void addError(String message, Object... arguments) {
+    builder.addError(message, arguments);
+  }
+
+  /**
+   * @see Binder#addError(Throwable) 
+   */
+  protected void addError(Throwable t) {
+    builder.addError(t);
+  }
+
+  /**
    * @see Binder#requestStaticInjection(Class[])
    */
   protected void requestStaticInjection(Class<?>... types) {
diff --git a/src/com/google/inject/Binder.java b/src/com/google/inject/Binder.java
index 323f3b0..eb767dc 100644
--- a/src/com/google/inject/Binder.java
+++ b/src/com/google/inject/Binder.java
@@ -102,4 +102,12 @@
    * message.
    */
   void addError(String message, Object... arguments);
+
+  /**
+   * Records an exception, the full details of which will be logged, and the
+   * message of which will be presented to the user at a later
+   * time. If your Module calls something that you worry may fail, you should
+   * catch the exception and pass it into this.
+   */
+  void addError(Throwable t);
 }
diff --git a/src/com/google/inject/BinderImpl.java b/src/com/google/inject/BinderImpl.java
index 705322d..cb5e331 100644
--- a/src/com/google/inject/BinderImpl.java
+++ b/src/com/google/inject/BinderImpl.java
@@ -34,6 +34,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.aopalliance.intercept.MethodInterceptor;
 
@@ -274,6 +275,17 @@
     configurationErrorHandler.handle(source(), message, arguments);
   }
 
+  public void addError(Throwable t) {
+    Object source = source();
+    String className = t.getClass().getSimpleName();
+    String message = t.getMessage();
+    String logMessage = String.format(
+        ErrorMessages.EXCEPTION_REPORTED_BY_MODULE, className, message);
+    logger.log(Level.INFO, logMessage, t);
+    addError(source, ErrorMessages.EXCEPTION_REPORTED_BY_MODULE_SEE_LOG,
+        className, message);
+  }
+
   void addError(Object source, String message, Object... arguments) {
     configurationErrorHandler.handle(source, message, arguments);
   }
diff --git a/src/com/google/inject/BindingBuilderImpl.java b/src/com/google/inject/BindingBuilderImpl.java
index a58b123..f633e28 100644
--- a/src/com/google/inject/BindingBuilderImpl.java
+++ b/src/com/google/inject/BindingBuilderImpl.java
@@ -270,10 +270,13 @@
           injector.injectMembers(o);
         }
         catch (Exception e) {
-          logger.log(Level.SEVERE, "An error occurred while injecting"
-              + " members of an object during Injector creation.", e);
-          binder.addError(
-              source, ErrorMessages.ERROR_INJECTING_MEMBERS, o, e.getMessage());
+          String className = e.getClass().getSimpleName();
+          String message = e.getMessage();
+          String logMessage = String.format(
+              ErrorMessages.ERROR_INJECTING_MEMBERS, className, o, message);
+          logger.log(Level.INFO, logMessage, e);
+          binder.addError(source, ErrorMessages.ERROR_INJECTING_MEMBERS_SEE_LOG,
+              className, o, message);
         }
       }
     });
diff --git a/src/com/google/inject/ErrorMessages.java b/src/com/google/inject/ErrorMessages.java
index 165efeb..f852cb3 100644
--- a/src/com/google/inject/ErrorMessages.java
+++ b/src/com/google/inject/ErrorMessages.java
@@ -52,8 +52,18 @@
     }
   }
 
-  static final String ERROR_INJECTING_MEMBERS = "An error occurred while"
-      + " injecting members of %s. See log for details. Error message: %s";
+  static final String ERROR_INJECTING_MEMBERS = "An error of type %s occurred"
+      + " while injecting members of %s. Error message: %s";
+
+  static final String ERROR_INJECTING_MEMBERS_SEE_LOG = "An error of type %s"
+      + " occurred while injecting members of %s. See log for details. Error"
+      + " message: %s";
+
+  static final String EXCEPTION_REPORTED_BY_MODULE = "An error of type %s was"
+      + " caught and reported. Error message: %s";
+
+  static final String EXCEPTION_REPORTED_BY_MODULE_SEE_LOG = "An error of type" 
+      + " %s was caught and reported. See log for details. Error message: %s";
 
   static final String MISSING_BINDING_ANNOTATION = "Please annotate with"
       + " @BindingAnnotation. Bound at %s.";
diff --git a/test/com/google/inject/ErrorHandlingTest.java b/test/com/google/inject/ErrorHandlingTest.java
index a174882..cbc3d40 100644
--- a/test/com/google/inject/ErrorHandlingTest.java
+++ b/test/com/google/inject/ErrorHandlingTest.java
@@ -86,7 +86,21 @@
       link(Key.get(Runnable.class)).to(Key.get(Runnable.class));
       bind(TooManyScopes.class);
       bindScope(BadScope.class, Scopes.SINGLETON);
+      bind(Object.class).toInstance(new Object() {
+        @Inject void foo() {
+          throw new RuntimeException();
+        }
+      });
       requestStaticInjection(ErrorHandlingTest.class);
+
+      addError("I don't like %s", "you");
+      
+      Object o = "2";
+      try {
+        Integer i = (Integer) o;
+      } catch (Exception e) {
+        addError(e);
+      }
     }
   }
 }