diff -Nru sisu-guice-3.2.6/bom/pom.xml sisu-guice-4.2.0/bom/pom.xml --- sisu-guice-3.2.6/bom/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/bom/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject guice-parent - 3.2.6 + 4.2.0 pom @@ -60,11 +60,6 @@ ${project.version} - org.sonatype.sisu.inject - guice-multibindings - ${project.version} - - org.sonatype.sisu.inject guice-persist ${project.version} diff -Nru sisu-guice-3.2.6/build.properties sisu-guice-4.2.0/build.properties --- sisu-guice-3.2.6/build.properties 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/build.properties 2018-04-03 18:18:08.000000000 +0000 @@ -7,7 +7,6 @@ jmx.src.dir=extensions/jmx/src jndi.src.dir=extensions/jndi/src throwingproviders.src.dir=extensions/throwingproviders/src -multibindings.src.dir=extensions/multibindings/src daggeradapter.src.dir=extensions/dagger-adapter/src privatemodules.src.dir=extensions/privatemodules/src lifecycle.src.dir=extensions/lifecycle/src diff -Nru sisu-guice-3.2.6/build.xml sisu-guice-4.2.0/build.xml --- sisu-guice-3.2.6/build.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/build.xml 2018-04-03 18:18:08.000000000 +0000 @@ -34,7 +34,6 @@ - @@ -62,9 +61,6 @@ - - - @@ -120,10 +116,11 @@ - - + + + @@ -139,7 +136,7 @@ - + @@ -162,7 +159,6 @@ - @@ -204,7 +200,7 @@ windowtitle="Guice ${new.api} API" author="false" protected="true"> - + @@ -216,9 +212,6 @@ - - - @@ -286,13 +279,13 @@ - ]]> + ]]> - ]]> + ]]> - ]]> + ]]> @@ -309,7 +302,6 @@ - diff -Nru sisu-guice-3.2.6/common.xml sisu-guice-4.2.0/common.xml --- sisu-guice-3.2.6/common.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/common.xml 2018-04-03 18:18:08.000000000 +0000 @@ -14,7 +14,7 @@ + source="1.7" target="1.7" includeantruntime="false"> @@ -35,11 +35,11 @@ - + - + @@ -80,7 +80,7 @@ + source="1.7" target="1.7" includeantruntime="false"> @@ -148,8 +148,8 @@ classpath="${common.basedir}/lib/build/jarjar-1.1.jar"/> - - + + diff -Nru sisu-guice-3.2.6/core/pom.xml sisu-guice-4.2.0/core/pom.xml --- sisu-guice-3.2.6/core/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject guice-parent - 3.2.6 + 4.2.0 org.sonatype.sisu @@ -79,6 +79,11 @@ 3.0.5 test + + com.google.truth + truth + test + @@ -90,7 +95,7 @@ maven-remote-resources-plugin org.codehaus.mojo @@ -128,6 +133,10 @@ ${project.artifactId}$(if;$(classes;NAMED;*.MethodAspect);; (no_aop)) !net.sf.cglib.*,!org.objectweb.asm.*,!com.google.inject.*,* true + + + !Bundle-Name,!Import-Package + org.slf4j @@ -142,6 +151,11 @@ LICENSE NOTICE + + + com.google.guice + + diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/AbstractModule.java sisu-guice-4.2.0/core/src/com/google/inject/AbstractModule.java --- sisu-guice-3.2.6/core/src/com/google/inject/AbstractModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/AbstractModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,15 +27,13 @@ import com.google.inject.spi.ProvisionListener; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeListener; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** - * A support class for {@link Module}s which reduces repetition and results in - * a more readable configuration. Simply extend this class, implement {@link - * #configure()}, and call the inherited methods which mirror those found in - * {@link Binder}. For example: + * A support class for {@link Module}s which reduces repetition and results in a more readable + * configuration. Simply extend this class, implement {@link #configure()}, and call the inherited + * methods which mirror those found in {@link Binder}. For example: * *
  * public class MyModule extends AbstractModule {
@@ -54,84 +52,63 @@
 
   Binder binder;
 
+  @Override
   public final synchronized void configure(Binder builder) {
     checkState(this.binder == null, "Re-entry is not allowed.");
 
     this.binder = checkNotNull(builder, "builder");
     try {
       configure();
-    }
-    finally {
+    } finally {
       this.binder = null;
     }
   }
 
-  /**
-   * Configures a {@link Binder} via the exposed methods.
-   */
-  protected abstract void configure();
+  /** Configures a {@link Binder} via the exposed methods. */
+  protected void configure() {}
 
-  /**
-   * Gets direct access to the underlying {@code Binder}.
-   */
+  /** Gets direct access to the underlying {@code Binder}. */
   protected Binder binder() {
     checkState(binder != null, "The binder can only be used inside configure()");
     return binder;
   }
 
-  /**
-   * @see Binder#bindScope(Class, Scope)
-   */
-  protected void bindScope(Class scopeAnnotation,
-      Scope scope) {
+  /** @see Binder#bindScope(Class, Scope) */
+  protected void bindScope(Class scopeAnnotation, Scope scope) {
     binder().bindScope(scopeAnnotation, scope);
   }
 
-  /**
-   * @see Binder#bind(Key)
-   */
+  /** @see Binder#bind(Key) */
   protected  LinkedBindingBuilder bind(Key key) {
     return binder().bind(key);
   }
 
-  /**
-   * @see Binder#bind(TypeLiteral)
-   */
+  /** @see Binder#bind(TypeLiteral) */
   protected  AnnotatedBindingBuilder bind(TypeLiteral typeLiteral) {
     return binder().bind(typeLiteral);
   }
 
-  /**
-   * @see Binder#bind(Class)
-   */
+  /** @see Binder#bind(Class) */
   protected  AnnotatedBindingBuilder bind(Class clazz) {
     return binder().bind(clazz);
   }
 
-  /**
-   * @see Binder#bindConstant()
-   */
+  /** @see Binder#bindConstant() */
   protected AnnotatedConstantBindingBuilder bindConstant() {
     return binder().bindConstant();
   }
 
-  /**
-   * @see Binder#install(Module)
-   */
+  /** @see Binder#install(Module) */
   protected void install(Module module) {
     binder().install(module);
   }
 
-  /**
-   * @see Binder#addError(String, Object[])
-   */
+  /** @see Binder#addError(String, Object[]) */
   protected void addError(String message, Object... arguments) {
     binder().addError(message, arguments);
   }
 
-  /**
-   * @see Binder#addError(Throwable) 
-   */
+  /** @see Binder#addError(Throwable) */
   protected void addError(Throwable t) {
     binder().addError(t);
   }
@@ -152,9 +129,7 @@
     binder().requestInjection(instance);
   }
 
-  /**
-   * @see Binder#requestStaticInjection(Class[])
-   */
+  /** @see Binder#requestStaticInjection(Class[]) */
   protected void requestStaticInjection(Class... types) {
     binder().requestStaticInjection(types);
   }
@@ -162,10 +137,10 @@
   /*if[AOP]*/
   /**
    * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher,
-   *  com.google.inject.matcher.Matcher,
-   *  org.aopalliance.intercept.MethodInterceptor[])
+   *     com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
    */
-  protected void bindInterceptor(Matcher> classMatcher,
+  protected void bindInterceptor(
+      Matcher> classMatcher,
       Matcher methodMatcher,
       org.aopalliance.intercept.MethodInterceptor... interceptors) {
     binder().bindInterceptor(classMatcher, methodMatcher, interceptors);
@@ -173,10 +148,9 @@
   /*end[AOP]*/
 
   /**
-   * Adds a dependency from this module to {@code key}. When the injector is
-   * created, Guice will report an error if {@code key} cannot be injected.
-   * Note that this requirement may be satisfied by implicit binding, such as
-   * a public no-arguments constructor.
+   * Adds a dependency from this module to {@code key}. When the injector is created, Guice will
+   * report an error if {@code key} cannot be injected. Note that this requirement may be satisfied
+   * by implicit binding, such as a public no-arguments constructor.
    *
    * @since 2.0
    */
@@ -185,10 +159,9 @@
   }
 
   /**
-   * Adds a dependency from this module to {@code type}. When the injector is
-   * created, Guice will report an error if {@code type} cannot be injected.
-   * Note that this requirement may be satisfied by implicit binding, such as
-   * a public no-arguments constructor.
+   * Adds a dependency from this module to {@code type}. When the injector is created, Guice will
+   * report an error if {@code type} cannot be injected. Note that this requirement may be satisfied
+   * by implicit binding, such as a public no-arguments constructor.
    *
    * @since 2.0
    */
@@ -216,13 +189,13 @@
    * @see Binder#convertToTypes
    * @since 2.0
    */
-  protected void convertToTypes(Matcher> typeMatcher,
-      TypeConverter converter) {
+  protected void convertToTypes(
+      Matcher> typeMatcher, TypeConverter converter) {
     binder().convertToTypes(typeMatcher, converter);
   }
 
   /**
-   * @see Binder#currentStage() 
+   * @see Binder#currentStage()
    * @since 2.0
    */
   protected Stage currentStage() {
@@ -246,21 +219,19 @@
   }
 
   /**
-   * @see Binder#bindListener(com.google.inject.matcher.Matcher,
-   *  com.google.inject.spi.TypeListener)
+   * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)
    * @since 2.0
    */
-  protected void bindListener(Matcher> typeMatcher,
-      TypeListener listener) {
+  protected void bindListener(Matcher> typeMatcher, TypeListener listener) {
     binder().bindListener(typeMatcher, listener);
   }
-  
+
   /**
    * @see Binder#bindListener(Matcher, ProvisionListener...)
    * @since 4.0
    */
-  protected void bindListener(Matcher> bindingMatcher,
-      ProvisionListener... listener) {
+  protected void bindListener(
+      Matcher> bindingMatcher, ProvisionListener... listener) {
     binder().bindListener(bindingMatcher, listener);
   }
 }
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java	2018-04-03 18:18:08.000000000 +0000
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,14 +25,9 @@
  */
 public interface AnnotatedBindingBuilder extends LinkedBindingBuilder {
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
-  LinkedBindingBuilder annotatedWith(
-      Class annotationType);
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
+  LinkedBindingBuilder annotatedWith(Class annotationType);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   LinkedBindingBuilder annotatedWith(Annotation annotation);
 }
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java	2018-04-03 18:18:08.000000000 +0000
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,14 +25,9 @@
  */
 public interface AnnotatedConstantBindingBuilder {
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
-  ConstantBindingBuilder annotatedWith(
-      Class annotationType);
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
+  ConstantBindingBuilder annotatedWith(Class annotationType);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   ConstantBindingBuilder annotatedWith(Annotation annotation);
 }
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/AnnotatedElementBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/binder/AnnotatedElementBuilder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/AnnotatedElementBuilder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/AnnotatedElementBuilder.java	2018-04-03 18:18:08.000000000 +0000
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2008 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,13 +26,9 @@
  */
 public interface AnnotatedElementBuilder {
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   void annotatedWith(Class annotationType);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   void annotatedWith(Annotation annotation);
 }
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/ConstantBindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/binder/ConstantBindingBuilder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/ConstantBindingBuilder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/ConstantBindingBuilder.java	2018-04-03 18:18:08.000000000 +0000
@@ -16,65 +16,43 @@
 
 package com.google.inject.binder;
 
-/**
- * Binds to a constant value.
- */
+/** Binds to a constant value. */
 public interface ConstantBindingBuilder {
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(String value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(int value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(long value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(boolean value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(double value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(float value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(short value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(char value);
 
   /**
    * Binds constant to the given value.
-   * 
+   *
    * @since 3.0
    */
   void to(byte value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   void to(Class value);
 
-  /**
-   * Binds constant to the given value.
-   */
+  /** Binds constant to the given value. */
   > void to(E value);
 }
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/LinkedBindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/binder/LinkedBindingBuilder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/LinkedBindingBuilder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/LinkedBindingBuilder.java	2018-04-03 18:18:08.000000000 +0000
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,6 @@
 import com.google.inject.Key;
 import com.google.inject.Provider;
 import com.google.inject.TypeLiteral;
-
 import java.lang.reflect.Constructor;
 
 /**
@@ -29,19 +28,13 @@
  */
 public interface LinkedBindingBuilder extends ScopedBindingBuilder {
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   ScopedBindingBuilder to(Class implementation);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   ScopedBindingBuilder to(TypeLiteral implementation);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   ScopedBindingBuilder to(Key targetKey);
 
   /**
@@ -57,7 +50,7 @@
    * @see com.google.inject.Injector#injectMembers
    */
   ScopedBindingBuilder toProvider(Provider provider);
-  
+
   /**
    * See the EDSL examples at {@link com.google.inject.Binder}.
    *
@@ -66,34 +59,26 @@
    */
   ScopedBindingBuilder toProvider(javax.inject.Provider provider);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
-  ScopedBindingBuilder toProvider(
-      Class> providerType);
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
+  ScopedBindingBuilder toProvider(Class> providerType);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   ScopedBindingBuilder toProvider(
       TypeLiteral> providerType);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
-  ScopedBindingBuilder toProvider(
-      Key> providerKey);
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
+  ScopedBindingBuilder toProvider(Key> providerKey);
 
   /**
    * See the EDSL examples at {@link com.google.inject.Binder}.
-   * 
+   *
    * @since 3.0
    */
    ScopedBindingBuilder toConstructor(Constructor constructor);
 
   /**
    * See the EDSL examples at {@link com.google.inject.Binder}.
-   * 
+   *
    * @since 3.0
    */
    ScopedBindingBuilder toConstructor(
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/binder/package-info.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/package-info.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/package-info.java	2018-04-03 18:18:08.000000000 +0000
@@ -14,8 +14,5 @@
  * limitations under the License.
  */
 
-/**
- * Interfaces which make up {@link com.google.inject.Binder}'s
- * expression language.
- */
-package com.google.inject.binder;
\ No newline at end of file
+/** Interfaces which make up {@link com.google.inject.Binder}'s expression language. */
+package com.google.inject.binder;
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/binder/ScopedBindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/binder/ScopedBindingBuilder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/binder/ScopedBindingBuilder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/binder/ScopedBindingBuilder.java	2018-04-03 18:18:08.000000000 +0000
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
 package com.google.inject.binder;
 
 import com.google.inject.Scope;
-
 import java.lang.annotation.Annotation;
 
 /**
@@ -27,20 +26,15 @@
  */
 public interface ScopedBindingBuilder {
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   void in(Class scopeAnnotation);
 
-  /**
-   * See the EDSL examples at {@link com.google.inject.Binder}.
-   */
+  /** See the EDSL examples at {@link com.google.inject.Binder}. */
   void in(Scope scope);
 
   /**
-   * Instructs the {@link com.google.inject.Injector} to eagerly initialize this
-   * singleton-scoped binding upon creation. Useful for application
-   * initialization logic.  See the EDSL examples at
+   * Instructs the {@link com.google.inject.Injector} to eagerly initialize this singleton-scoped
+   * binding upon creation. Useful for application initialization logic. See the EDSL examples at
    * {@link com.google.inject.Binder}.
    */
   void asEagerSingleton();
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Binder.java sisu-guice-4.2.0/core/src/com/google/inject/Binder.java
--- sisu-guice-3.2.6/core/src/com/google/inject/Binder.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/Binder.java	2018-04-03 18:18:08.000000000 +0000
@@ -26,129 +26,111 @@
 import com.google.inject.spi.ProvisionListener;
 import com.google.inject.spi.TypeConverter;
 import com.google.inject.spi.TypeListener;
-
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 
 /**
- * Collects configuration information (primarily bindings) which will be
- * used to create an {@link Injector}. Guice provides this object to your
- * application's {@link Module} implementors so they may each contribute
- * their own bindings and other registrations.
+ * Collects configuration information (primarily bindings) which will be used to create an
+ * {@link Injector}. Guice provides this object to your application's {@link Module} implementors so
+ * they may each contribute their own bindings and other registrations.
  *
  * 

The Guice Binding EDSL

* - * Guice uses an embedded domain-specific language, or EDSL, to help you - * create bindings simply and readably. This approach is great for overall - * usability, but it does come with a small cost: it is difficult to - * learn how to use the Binding EDSL by reading - * method-level javadocs. Instead, you should consult the series of - * examples below. To save space, these examples omit the opening - * {@code binder}, just as you will if your module extends - * {@link AbstractModule}. + * Guice uses an embedded domain-specific language, or EDSL, to help you create bindings + * simply and readably. This approach is great for overall usability, but it does come with a small + * cost: it is difficult to learn how to use the Binding EDSL by reading method-level + * javadocs. Instead, you should consult the series of examples below. To save space, these + * examples omit the opening {@code binder}, just as you will if your module extends {@link + * AbstractModule}. * *
  *     bind(ServiceImpl.class);
* - * This statement does essentially nothing; it "binds the {@code ServiceImpl} - * class to itself" and does not change Guice's default behavior. You may still - * want to use this if you prefer your {@link Module} class to serve as an - * explicit manifest for the services it provides. Also, in rare cases, - * Guice may be unable to validate a binding at injector creation time unless it - * is given explicitly. + * This statement does essentially nothing; it "binds the {@code ServiceImpl} class to itself" and + * does not change Guice's default behavior. You may still want to use this if you prefer your + * {@link Module} class to serve as an explicit manifest for the services it provides. Also, + * in rare cases, Guice may be unable to validate a binding at injector creation time unless it is + * given explicitly. * *
  *     bind(Service.class).to(ServiceImpl.class);
* - * Specifies that a request for a {@code Service} instance with no binding - * annotations should be treated as if it were a request for a - * {@code ServiceImpl} instance. This overrides the function of any - * {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy} - * annotations found on {@code Service}, since Guice will have already - * "moved on" to {@code ServiceImpl} before it reaches the point when it starts - * looking for these annotations. + * Specifies that a request for a {@code Service} instance with no binding annotations should be + * treated as if it were a request for a {@code ServiceImpl} instance. This overrides the + * function of any {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy} + * annotations found on {@code Service}, since Guice will have already "moved on" to {@code + * ServiceImpl} before it reaches the point when it starts looking for these annotations. * *
  *     bind(Service.class).toProvider(ServiceProvider.class);
* - * In this example, {@code ServiceProvider} must extend or implement - * {@code Provider}. This binding specifies that Guice should resolve - * an unannotated injection request for {@code Service} by first resolving an - * instance of {@code ServiceProvider} in the regular way, then calling - * {@link Provider#get get()} on the resulting Provider instance to obtain the - * {@code Service} instance. - * - *

The {@link Provider} you use here does not have to be a "factory"; that - * is, a provider which always creates each instance it provides. - * However, this is generally a good practice to follow. You can then use - * Guice's concept of {@link Scope scopes} to guide when creation should happen - * -- "letting Guice work for you". + * In this example, {@code ServiceProvider} must extend or implement {@code Provider}. This + * binding specifies that Guice should resolve an unannotated injection request for {@code Service} + * by first resolving an instance of {@code ServiceProvider} in the regular way, then calling {@link + * Provider#get get()} on the resulting Provider instance to obtain the {@code Service} instance. + * + *

The {@link Provider} you use here does not have to be a "factory"; that is, a provider which + * always creates each instance it provides. However, this is generally a good practice to + * follow. You can then use Guice's concept of {@link Scope scopes} to guide when creation should + * happen -- "letting Guice work for you". * *

  *     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
* - * Like the previous example, but only applies to injection requests that use - * the binding annotation {@code @Red}. If your module also includes bindings - * for particular values of the {@code @Red} annotation (see below), - * then this binding will serve as a "catch-all" for any values of {@code @Red} - * that have no exact match in the bindings. - * + * Like the previous example, but only applies to injection requests that use the binding annotation + * {@code @Red}. If your module also includes bindings for particular values of the + * {@code @Red} annotation (see below), then this binding will serve as a "catch-all" for any values + * of {@code @Red} that have no exact match in the bindings. + * *
  *     bind(ServiceImpl.class).in(Singleton.class);
  *     // or, alternatively
  *     bind(ServiceImpl.class).in(Scopes.SINGLETON);
* - * Either of these statements places the {@code ServiceImpl} class into - * singleton scope. Guice will create only one instance of {@code ServiceImpl} - * and will reuse it for all injection requests of this type. Note that it is - * still possible to bind another instance of {@code ServiceImpl} if the second - * binding is qualified by an annotation as in the previous example. Guice is - * not overly concerned with preventing you from creating multiple - * instances of your "singletons", only with enabling your application to - * share only one instance if that's all you tell Guice you need. - * - *

Note: a scope specified in this way overrides any scope that - * was specified with an annotation on the {@code ServiceImpl} class. - * - *

Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are - * servlet-specific scopes available in - * {@code com.google.inject.servlet.ServletScopes}, and your Modules can - * contribute their own custom scopes for use here as well. + * Either of these statements places the {@code ServiceImpl} class into singleton scope. Guice will + * create only one instance of {@code ServiceImpl} and will reuse it for all injection requests of + * this type. Note that it is still possible to bind another instance of {@code ServiceImpl} if the + * second binding is qualified by an annotation as in the previous example. Guice is not overly + * concerned with preventing you from creating multiple instances of your "singletons", only + * with enabling your application to share only one instance if that's all you tell Guice you + * need. + * + *

Note: a scope specified in this way overrides any scope that was specified with + * an annotation on the {@code ServiceImpl} class. + * + *

Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are servlet-specific scopes + * available in {@code com.google.inject.servlet.ServletScopes}, and your Modules can contribute + * their own custom scopes for use here as well. * *

  *     bind(new TypeLiteral<PaymentService<CreditCard>>() {})
  *         .to(CreditCardPaymentService.class);
* - * This admittedly odd construct is the way to bind a parameterized type. It - * tells Guice how to honor an injection request for an element of type - * {@code PaymentService}. The class - * {@code CreditCardPaymentService} must implement the - * {@code PaymentService} interface. Guice cannot currently bind or - * inject a generic type, such as {@code Set}; all type parameters must be - * fully specified. + * This admittedly odd construct is the way to bind a parameterized type. It tells Guice how to + * honor an injection request for an element of type {@code PaymentService}. The class + * {@code CreditCardPaymentService} must implement the {@code PaymentService} interface. + * Guice cannot currently bind or inject a generic type, such as {@code Set}; all type parameters + * must be fully specified. * *
  *     bind(Service.class).toInstance(new ServiceImpl());
  *     // or, alternatively
  *     bind(Service.class).toInstance(SomeLegacyRegistry.getService());
* - * In this example, your module itself, not Guice, takes responsibility - * for obtaining a {@code ServiceImpl} instance, then asks Guice to always use - * this single instance to fulfill all {@code Service} injection requests. When - * the {@link Injector} is created, it will automatically perform field - * and method injection for this instance, but any injectable constructor on - * {@code ServiceImpl} is simply ignored. Note that using this approach results - * in "eager loading" behavior that you can't control. + * In this example, your module itself, not Guice, takes responsibility for obtaining a + * {@code ServiceImpl} instance, then asks Guice to always use this single instance to fulfill all + * {@code Service} injection requests. When the {@link Injector} is created, it will automatically + * perform field and method injection for this instance, but any injectable constructor on {@code + * ServiceImpl} is simply ignored. Note that using this approach results in "eager loading" behavior + * that you can't control. * *
  *     bindConstant().annotatedWith(ServerHost.class).to(args[0]);
* - * Sets up a constant binding. Constant injections must always be annotated. - * When a constant binding's value is a string, it is eligile for conversion to - * all primitive types, to {@link Enum#valueOf(Class, String) all enums}, and to - * {@link Class#forName class literals}. Conversions for other types can be - * configured using {@link #convertToTypes(Matcher, TypeConverter) + * Sets up a constant binding. Constant injections must always be annotated. When a constant + * binding's value is a string, it is eligile for conversion to all primitive types, to {@link + * Enum#valueOf(Class, String) all enums}, and to {@link Class#forName class literals}. Conversions + * for other types can be configured using {@link #convertToTypes(Matcher, TypeConverter) * convertToTypes()}. * *
@@ -157,46 +139,42 @@
  *     red = MyModule.class.getDeclaredField("red").getAnnotation(Color.class);
  *     bind(Service.class).annotatedWith(red).to(RedService.class);
* - * If your binding annotation has parameters you can apply different bindings to - * different specific values of your annotation. Getting your hands on the - * right instance of the annotation is a bit of a pain -- one approach, shown - * above, is to apply a prototype annotation to a field in your module class, so - * that you can read this annotation instance and give it to Guice. + * If your binding annotation has parameters you can apply different bindings to different specific + * values of your annotation. Getting your hands on the right instance of the annotation is a bit of + * a pain -- one approach, shown above, is to apply a prototype annotation to a field in your module + * class, so that you can read this annotation instance and give it to Guice. * *
  *     bind(Service.class)
  *         .annotatedWith(Names.named("blue"))
  *         .to(BlueService.class);
* - * Differentiating by names is a common enough use case that we provided a - * standard annotation, {@link com.google.inject.name.Named @Named}. Because of - * Guice's library support, binding by name is quite easier than in the - * arbitrary binding annotation case we just saw. However, remember that these - * names will live in a single flat namespace with all the other names used in - * your application. + * Differentiating by names is a common enough use case that we provided a standard annotation, + * {@link com.google.inject.name.Named @Named}. Because of Guice's library support, binding by name + * is quite easier than in the arbitrary binding annotation case we just saw. However, remember that + * these names will live in a single flat namespace with all the other names used in your + * application. * *
  *     Constructor loneCtor = getLoneCtorFromServiceImplViaReflection();
  *     bind(ServiceImpl.class)
  *         .toConstructor(loneCtor);
* - * In this example, we directly tell Guice which constructor to use in a concrete - * class implementation. It means that we do not need to place {@literal @}Inject - * on any of the constructors and that Guice treats the provided constructor as though - * it were annotated so. It is useful for cases where you cannot modify existing - * classes and is a bit simpler than using a {@link Provider}. - * - *

The above list of examples is far from exhaustive. If you can think of - * how the concepts of one example might coexist with the concepts from another, - * you can most likely weave the two together. If the two concepts make no - * sense with each other, you most likely won't be able to do it. In a few - * cases Guice will let something bogus slip by, and will then inform you of - * the problems at runtime, as soon as you try to create your Injector. - * - *

The other methods of Binder such as {@link #bindScope}, - * {@link #bindInterceptor}, {@link #install}, {@link #requestStaticInjection}, - * {@link #addError} and {@link #currentStage} are not part of the Binding EDSL; - * you can learn how to use these in the usual way, from the method + * In this example, we directly tell Guice which constructor to use in a concrete class + * implementation. It means that we do not need to place {@literal @}Inject on any of the + * constructors and that Guice treats the provided constructor as though it were annotated so. It is + * useful for cases where you cannot modify existing classes and is a bit simpler than using a + * {@link Provider}. + * + *

The above list of examples is far from exhaustive. If you can think of how the concepts of one + * example might coexist with the concepts from another, you can most likely weave the two together. + * If the two concepts make no sense with each other, you most likely won't be able to do it. In a + * few cases Guice will let something bogus slip by, and will then inform you of the problems at + * runtime, as soon as you try to create your Injector. + * + *

The other methods of Binder such as {@link #bindScope}, {@link #bindInterceptor}, {@link + * #install}, {@link #requestStaticInjection}, {@link #addError} and {@link #currentStage} are not + * part of the Binding EDSL; you can learn how to use these in the usual way, from the method * documentation. * * @author crazybob@google.com (Bob Lee) @@ -211,51 +189,41 @@ * eligible for interception if: * *

    - *
  • Guice created the instance the method is on
  • - *
  • Neither the enclosing type nor the method is final
  • - *
  • And the method is package-private, protected, or public
  • + *
  • Guice created the instance the method is on + *
  • Neither the enclosing type nor the method is final + *
  • And the method is package-private, protected, or public *
* - * @param classMatcher matches classes the interceptor should apply to. For - * example: {@code only(Runnable.class)}. - * @param methodMatcher matches methods the interceptor should apply to. For - * example: {@code annotatedWith(Transactional.class)}. - * @param interceptors to bind. The interceptors are called in the order they - * are given. + * @param classMatcher matches classes the interceptor should apply to. For example: {@code + * only(Runnable.class)}. + * @param methodMatcher matches methods the interceptor should apply to. For example: {@code + * annotatedWith(Transactional.class)}. + * @param interceptors to bind. The interceptors are called in the order they are given. */ - void bindInterceptor(Matcher> classMatcher, + void bindInterceptor( + Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors); /*end[AOP]*/ - /** - * Binds a scope to an annotation. - */ + /** Binds a scope to an annotation. */ void bindScope(Class annotationType, Scope scope); - /** - * See the EDSL examples at {@link Binder}. - */ + /** See the EDSL examples at {@link Binder}. */ LinkedBindingBuilder bind(Key key); - /** - * See the EDSL examples at {@link Binder}. - */ + /** See the EDSL examples at {@link Binder}. */ AnnotatedBindingBuilder bind(TypeLiteral typeLiteral); - /** - * See the EDSL examples at {@link Binder}. - */ + /** See the EDSL examples at {@link Binder}. */ AnnotatedBindingBuilder bind(Class type); - /** - * See the EDSL examples at {@link Binder}. - */ + /** See the EDSL examples at {@link Binder}. */ AnnotatedConstantBindingBuilder bindConstant(); /** - * Upon successful creation, the {@link Injector} will inject instance fields - * and methods of the given object. + * Upon successful creation, the {@link Injector} will inject instance fields and methods of the + * given object. * * @param type of instance * @param instance for which members will be injected @@ -264,8 +232,8 @@ void requestInjection(TypeLiteral type, T instance); /** - * Upon successful creation, the {@link Injector} will inject instance fields - * and methods of the given object. + * Upon successful creation, the {@link Injector} will inject instance fields and methods of the + * given object. * * @param instance for which members will be injected * @since 2.0 @@ -273,37 +241,30 @@ void requestInjection(Object instance); /** - * Upon successful creation, the {@link Injector} will inject static fields - * and methods in the given classes. + * Upon successful creation, the {@link Injector} will inject static fields and methods in the + * given classes. * * @param types for which static members will be injected */ void requestStaticInjection(Class... types); - /** - * Uses the given module to configure more bindings. - */ + /** Uses the given module to configure more bindings. */ void install(Module module); - /** - * Gets the current stage. - */ + /** Gets the current stage. */ Stage currentStage(); /** - * Records an error message which will be presented to the user at a later - * time. Unlike throwing an exception, this enable us to continue - * configuring the Injector and discover more errors. Uses {@link - * String#format(String, Object[])} to insert the arguments into the - * message. + * Records an error message which will be presented to the user at a later time. Unlike throwing + * an exception, this enable us to continue configuring the Injector and discover more errors. + * Uses {@link String#format(String, Object[])} to insert the arguments into the 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. + * 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); @@ -315,32 +276,29 @@ void addError(Message message); /** - * Returns the provider used to obtain instances for the given injection key. - * The returned provider will not be valid until the {@link Injector} has been - * created. The provider will throw an {@code IllegalStateException} if you - * try to use it beforehand. + * Returns the provider used to obtain instances for the given injection key. The returned + * provider will not be valid until the {@link Injector} has been created. The provider will throw + * an {@code IllegalStateException} if you try to use it beforehand. * * @since 2.0 */ Provider getProvider(Key key); /** - * Returns the provider used to obtain instances for the given injection key. - * The returned provider will be attached to the injection point and will - * follow the nullability specified in the dependency. - * Additionally, the returned provider will not be valid until the {@link Injector} - * has been created. The provider will throw an {@code IllegalStateException} if you - * try to use it beforehand. + * Returns the provider used to obtain instances for the given injection key. The returned + * provider will be attached to the injection point and will follow the nullability specified in + * the dependency. Additionally, the returned provider will not be valid until the {@link + * Injector} has been created. The provider will throw an {@code IllegalStateException} if you try + * to use it beforehand. * * @since 4.0 */ Provider getProvider(Dependency dependency); /** - * Returns the provider used to obtain instances for the given injection type. - * The returned provider will not be valid until the {@link Injector} has been - * created. The provider will throw an {@code IllegalStateException} if you - * try to use it beforehand. + * Returns the provider used to obtain instances for the given injection type. The returned + * provider will not be valid until the {@link Injector} has been created. The provider will throw + * an {@code IllegalStateException} if you try to use it beforehand. * * @since 2.0 */ @@ -369,15 +327,14 @@ MembersInjector getMembersInjector(Class type); /** - * Binds a type converter. The injector will use the given converter to - * convert string constants to matching types as needed. + * Binds a type converter. The injector will use the given converter to convert string constants + * to matching types as needed. * * @param typeMatcher matches types the converter can handle * @param converter converts values * @since 2.0 */ - void convertToTypes(Matcher> typeMatcher, - TypeConverter converter); + void convertToTypes(Matcher> typeMatcher, TypeConverter converter); /** * Registers a listener for injectable types. Guice will notify the listener when it encounters @@ -387,43 +344,38 @@ * @param listener for injectable types matched by typeMatcher * @since 2.0 */ - void bindListener(Matcher> typeMatcher, - TypeListener listener); + void bindListener(Matcher> typeMatcher, TypeListener listener); /** - * Registers listeners for provisioned objects. Guice will notify the - * listeners just before and after the object is provisioned. Provisioned - * objects that are also injectable (everything except objects provided - * through Providers) can also be notified through TypeListeners registered in - * {@link #bindListener}. - * - * @param bindingMatcher that matches bindings of provisioned objects the listener - * should be notified of - * @param listeners for provisioned objects matched by bindingMatcher + * Registers listeners for provisioned objects. Guice will notify the listeners just before and + * after the object is provisioned. Provisioned objects that are also injectable (everything + * except objects provided through Providers) can also be notified through TypeListeners + * registered in {@link #bindListener}. + * + * @param bindingMatcher that matches bindings of provisioned objects the listener should be + * notified of + * @param listeners for provisioned objects matched by bindingMatcher * @since 4.0 */ void bindListener(Matcher> bindingMatcher, ProvisionListener... listeners); /** - * Returns a binder that uses {@code source} as the reference location for - * configuration errors. This is typically a {@link StackTraceElement} - * for {@code .java} source but it could any binding source, such as the - * path to a {@code .properties} file. + * Returns a binder that uses {@code source} as the reference location for configuration errors. + * This is typically a {@link StackTraceElement} for {@code .java} source but it could any binding + * source, such as the path to a {@code .properties} file. * - * @param source any object representing the source location and has a - * concise {@link Object#toString() toString()} value + * @param source any object representing the source location and has a concise {@link + * Object#toString() toString()} value * @return a binder that shares its configuration with this binder * @since 2.0 */ Binder withSource(Object source); /** - * Returns a binder that skips {@code classesToSkip} when identify the - * calling code. The caller's {@link StackTraceElement} is used to locate - * the source of configuration errors. + * Returns a binder that skips {@code classesToSkip} when identify the calling code. The caller's + * {@link StackTraceElement} is used to locate the source of configuration errors. * - * @param classesToSkip library classes that create bindings on behalf of - * their clients. + * @param classesToSkip library classes that create bindings on behalf of their clients. * @return a binder that shares its configuration with this binder. * @since 2.0 */ @@ -435,75 +387,69 @@ * PrivateModule} for details. * * @return a binder that inherits configuration from this binder. Only exposed configuration on - * the returned binder will be visible to this binder. + * the returned binder will be visible to this binder. * @since 2.0 */ PrivateBinder newPrivateBinder(); /** - * Instructs the Injector that bindings must be listed in a Module in order to - * be injected. Classes that are not explicitly bound in a module cannot be - * injected. Bindings created through a linked binding - * (bind(Foo.class).to(FooImpl.class)) are allowed, but the - * implicit binding (FooImpl) cannot be directly injected unless - * it is also explicitly bound (bind(FooImpl.class)). - *

- * Tools can still retrieve bindings for implicit bindings (bindings created - * through a linked binding) if explicit bindings are required, however - * {@link Binding#getProvider} will fail. - *

- * By default, explicit bindings are not required. - *

- * If a parent injector requires explicit bindings, then all child injectors - * (and private modules within that injector) also require explicit bindings. - * If a parent does not require explicit bindings, a child injector or private - * module may optionally declare itself as requiring explicit bindings. If it - * does, the behavior is limited only to that child or any grandchildren. No - * siblings of the child will require explicit bindings. - *

- * In the absence of an explicit binding for the target, linked bindings in - * child injectors create a binding for the target in the parent. Since this - * behavior can be surprising, it causes an error instead if explicit bindings - * are required. To avoid this error, add an explicit binding for the target, - * either in the child or the parent. - * + * Instructs the Injector that bindings must be listed in a Module in order to be injected. + * Classes that are not explicitly bound in a module cannot be injected. Bindings created through + * a linked binding (bind(Foo.class).to(FooImpl.class)) are allowed, but the implicit + * binding (FooImpl) cannot be directly injected unless it is also explicitly bound ( + * bind(FooImpl.class)). + * + *

Tools can still retrieve bindings for implicit bindings (bindings created through a linked + * binding) if explicit bindings are required, however {@link Binding#getProvider} will fail. + * + *

By default, explicit bindings are not required. + * + *

If a parent injector requires explicit bindings, then all child injectors (and private + * modules within that injector) also require explicit bindings. If a parent does not require + * explicit bindings, a child injector or private module may optionally declare itself as + * requiring explicit bindings. If it does, the behavior is limited only to that child or any + * grandchildren. No siblings of the child will require explicit bindings. + * + *

In the absence of an explicit binding for the target, linked bindings in child injectors + * create a binding for the target in the parent. Since this behavior can be surprising, it causes + * an error instead if explicit bindings are required. To avoid this error, add an explicit + * binding for the target, either in the child or the parent. + * * @since 3.0 */ void requireExplicitBindings(); - + /** - * Prevents Guice from constructing a {@link Proxy} when a circular dependency - * is found. By default, circular proxies are not disabled. - *

- * If a parent injector disables circular proxies, then all child injectors - * (and private modules within that injector) also disable circular proxies. - * If a parent does not disable circular proxies, a child injector or private - * module may optionally declare itself as disabling circular proxies. If it - * does, the behavior is limited only to that child or any grandchildren. No - * siblings of the child will disable circular proxies. - * + * Prevents Guice from injecting dependencies that form a cycle, unless broken by a {@link + * Provider}. By default, circular dependencies are not disabled. + * + *

If a parent injector disables circular dependencies, then all child injectors (and private + * modules within that injector) also disable circular dependencies. If a parent does not disable + * circular dependencies, a child injector or private module may optionally declare itself as + * disabling circular dependencies. If it does, the behavior is limited only to that child or any + * grandchildren. No siblings of the child will disable circular dependencies. + * * @since 3.0 */ void disableCircularProxies(); - + /** * Requires that a {@literal @}{@link Inject} annotation exists on a constructor in order for * Guice to consider it an eligible injectable class. By default, Guice will inject classes that * have a no-args constructor if no {@literal @}{@link Inject} annotation exists on any * constructor. - *

- * If the class is bound using {@link LinkedBindingBuilder#toConstructor}, Guice will still inject - * that constructor regardless of annotations. + * + *

If the class is bound using {@link LinkedBindingBuilder#toConstructor}, Guice will still + * inject that constructor regardless of annotations. * * @since 4.0 */ void requireAtInjectOnConstructors(); /** - * Requires that Guice finds an exactly matching binding annotation. This disables the - * error-prone feature in Guice where it can substitute a binding for - * {@literal @}Named Foo when attempting to inject - * {@literal @}Named("foo") Foo. + * Requires that Guice finds an exactly matching binding annotation. This disables the error-prone + * feature in Guice where it can substitute a binding for {@literal @}Named Foo when + * attempting to inject {@literal @}Named("foo") Foo. * * @since 4.0 */ diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/BindingAnnotation.java sisu-guice-4.2.0/core/src/com/google/inject/BindingAnnotation.java --- sisu-guice-3.2.6/core/src/com/google/inject/BindingAnnotation.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/BindingAnnotation.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,9 +23,9 @@ import java.lang.annotation.Target; /** - * Annotates annotations which are used for binding. Only one such annotation - * may apply to a single injection point. You must also annotate binder - * annotations with {@code @Retention(RUNTIME)}. For example: + * Annotates annotations which are used for binding. Only one such annotation may apply to a single + * injection point. You must also annotate binder annotations with {@code @Retention(RUNTIME)}. For + * example: * *

  *   {@code @}Retention(RUNTIME)
diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Binding.java sisu-guice-4.2.0/core/src/com/google/inject/Binding.java
--- sisu-guice-3.2.6/core/src/com/google/inject/Binding.java	2015-04-25 16:25:40.000000000 +0000
+++ sisu-guice-4.2.0/core/src/com/google/inject/Binding.java	2018-04-03 18:18:08.000000000 +0000
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2008 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,55 +22,50 @@
 
 /**
  * A mapping from a key (type and optional annotation) to the strategy for getting instances of the
- * type. This interface is part of the introspection API and is intended primarily for use by 
- * tools.
+ * type. This interface is part of the introspection API and is intended primarily for use by tools.
  *
  * 

Bindings are created in several ways: + * *

    - *
  • Explicitly in a module, via {@code bind()} and {@code bindConstant()} - * statements: - *
    + * 
  • Explicitly in a module, via {@code bind()} and {@code bindConstant()} statements: + *
      *     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
    - *     bindConstant().annotatedWith(ServerHost.class).to(args[0]);
  • - *
  • Implicitly by the Injector by following a type's {@link ImplementedBy - * pointer} {@link ProvidedBy annotations} or by using its {@link Inject annotated} or - * default constructor.
  • - *
  • By converting a bound instance to a different type.
  • - *
  • For {@link Provider providers}, by delegating to the binding for the provided type.
  • - *
+ * bindConstant().annotatedWith(ServerHost.class).to(args[0]);
* + *
  • Implicitly by the Injector by following a type's {@link ImplementedBy pointer} {@link + * ProvidedBy annotations} or by using its {@link Inject annotated} or default constructor. + *
  • By converting a bound instance to a different type. + *
  • For {@link Provider providers}, by delegating to the binding for the provided type. + * * *

    They exist on both modules and on injectors, and their behaviour is different for each: + * *

      - *
    • Module bindings are incomplete and cannot be used to provide instances. - * This is because the applicable scopes and interceptors may not be known until an injector - * is created. From a tool's perspective, module bindings are like the injector's source - * code. They can be inspected or rewritten, but this analysis must be done statically.
    • - *
    • Injector bindings are complete and valid and can be used to provide - * instances. From a tools' perspective, injector bindings are like reflection for an - * injector. They have full runtime information, including the complete graph of injections - * necessary to satisfy a binding.
    • + *
    • Module bindings are incomplete and cannot be used to provide instances. This + * is because the applicable scopes and interceptors may not be known until an injector is + * created. From a tool's perspective, module bindings are like the injector's source code. They + * can be inspected or rewritten, but this analysis must be done statically. + *
    • Injector bindings are complete and valid and can be used to provide + * instances. From a tools' perspective, injector bindings are like reflection for an injector. + * They have full runtime information, including the complete graph of injections necessary to + * satisfy a binding. *
    * * @param the bound type. The injected is always assignable to this type. - * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ public interface Binding extends Element { - /** - * Returns the key for this binding. - */ + /** Returns the key for this binding. */ Key getKey(); /** - * Returns the scoped provider guice uses to fulfill requests for this - * binding. + * Returns the scoped provider guice uses to fulfill requests for this binding. * - * @throws UnsupportedOperationException when invoked on a {@link Binding} - * created via {@link com.google.inject.spi.Elements#getElements}. This - * method is only supported on {@link Binding}s returned from an injector. + * @throws UnsupportedOperationException when invoked on a {@link Binding} created via {@link + * com.google.inject.spi.Elements#getElements}. This method is only supported on {@link + * Binding}s returned from an injector. */ Provider getProvider(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/ConfigurationException.java sisu-guice-4.2.0/core/src/com/google/inject/ConfigurationException.java --- sisu-guice-3.2.6/core/src/com/google/inject/ConfigurationException.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/ConfigurationException.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,8 @@ import static com.google.common.base.Preconditions.checkState; -import com.google.common.collect.ImmutableSet; -import com.google.inject.internal.Errors; +import com.google.inject.internal.Messages; import com.google.inject.spi.Message; - import java.util.Collection; /** @@ -33,13 +31,13 @@ */ public final class ConfigurationException extends RuntimeException { - private final ImmutableSet messages; + private final com.google.common.collect.ImmutableSet messages; private Object partialValue = null; /** Creates a ConfigurationException containing {@code messages}. */ public ConfigurationException(Iterable messages) { - this.messages = ImmutableSet.copyOf(messages); - initCause(Errors.getOnlyCause(this.messages)); + this.messages = com.google.common.collect.ImmutableSet.copyOf(messages); + initCause(Messages.getOnlyCause(this.messages)); } /** Returns a copy of this configuration exception with the specified partial value. */ @@ -57,20 +55,23 @@ } /** - * Returns a value that was only partially computed due to this exception. The caller can use - * this while collecting additional configuration problems. + * Returns a value that was only partially computed due to this exception. The caller can use this + * while collecting additional configuration problems. * * @return the partial value, or {@code null} if none was set. The type of the partial value is - * specified by the throwing method. + * specified by the throwing method. */ - @SuppressWarnings("unchecked") // this is *extremely* unsafe. We trust the caller here. + @SuppressWarnings({ + "unchecked", + "TypeParameterUnusedInFormals" + }) // this is *extremely* unsafe. We trust the caller here. public E getPartialValue() { return (E) partialValue; } @Override public String getMessage() { - return Errors.format("Guice configuration errors", messages); + return Messages.formatMessages("Guice configuration errors", messages); } private static final long serialVersionUID = 0; -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/CreationException.java sisu-guice-4.2.0/core/src/com/google/inject/CreationException.java --- sisu-guice-3.2.6/core/src/com/google/inject/CreationException.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/CreationException.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,9 +19,8 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.collect.ImmutableSet; -import com.google.inject.internal.Errors; +import com.google.inject.internal.Messages; import com.google.inject.spi.Message; - import java.util.Collection; /** @@ -38,7 +37,7 @@ public CreationException(Collection messages) { this.messages = ImmutableSet.copyOf(messages); checkArgument(!this.messages.isEmpty()); - initCause(Errors.getOnlyCause(this.messages)); + initCause(Messages.getOnlyCause(this.messages)); } /** Returns messages for the errors that caused this exception. */ @@ -46,8 +45,9 @@ return messages; } - @Override public String getMessage() { - return Errors.format("Unable to create injector, see the following errors", messages); + @Override + public String getMessage() { + return Messages.formatMessages("Unable to create injector, see the following errors", messages); } private static final long serialVersionUID = 0; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Exposed.java sisu-guice-4.2.0/core/src/com/google/inject/Exposed.java --- sisu-guice-3.2.6/core/src/com/google/inject/Exposed.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Exposed.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,5 +30,7 @@ * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ -@Target(ElementType.METHOD) @Retention(RUNTIME) @Documented +@Target(ElementType.METHOD) +@Retention(RUNTIME) +@Documented public @interface Exposed {} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Guice.java sisu-guice-4.2.0/core/src/com/google/inject/Guice.java --- sisu-guice-3.2.6/core/src/com/google/inject/Guice.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Guice.java 2018-04-03 18:18:08.000000000 +0000 @@ -17,19 +17,17 @@ package com.google.inject; import com.google.inject.internal.InternalInjectorCreator; - import java.util.Arrays; /** - * The entry point to the Guice framework. Creates {@link Injector}s from - * {@link Module}s. + * The entry point to the Guice framework. Creates {@link Injector}s from {@link Module}s. + * + *

    Guice supports a model of development that draws clear boundaries between APIs, + * Implementations of these APIs, Modules which configure these implementations, and finally + * Applications which consist of a collection of Modules. It is the Application, which typically + * defines your {@code main()} method, that bootstraps the Guice Injector using the {@code Guice} + * class, as in this example: * - *

    Guice supports a model of development that draws clear boundaries between - * APIs, Implementations of these APIs, Modules which configure these - * implementations, and finally Applications which consist of a collection of - * Modules. It is the Application, which typically defines your {@code main()} - * method, that bootstraps the Guice Injector using the {@code Guice} class, as - * in this example: *

      *     public class FooApplication {
      *       public static void main(String[] args) {
    @@ -52,50 +50,40 @@
       private Guice() {}
     
       /**
    -   * Creates an injector for the given set of modules. This is equivalent to
    -   * calling {@link #createInjector(Stage, Module...)} with Stage.DEVELOPMENT.
    +   * Creates an injector for the given set of modules. This is equivalent to calling {@link
    +   * #createInjector(Stage, Module...)} with Stage.DEVELOPMENT.
        *
    -   * @throws CreationException if one or more errors occur during injector
    -   *     construction
    +   * @throws CreationException if one or more errors occur during injector construction
        */
       public static Injector createInjector(Module... modules) {
         return createInjector(Arrays.asList(modules));
       }
     
       /**
    -   * Creates an injector for the given set of modules. This is equivalent to
    -   * calling {@link #createInjector(Stage, Iterable)} with Stage.DEVELOPMENT.
    +   * Creates an injector for the given set of modules. This is equivalent to calling {@link
    +   * #createInjector(Stage, Iterable)} with Stage.DEVELOPMENT.
        *
    -   * @throws CreationException if one or more errors occur during injector
    -   *     creation
    +   * @throws CreationException if one or more errors occur during injector creation
        */
       public static Injector createInjector(Iterable modules) {
         return createInjector(Stage.DEVELOPMENT, modules);
       }
     
       /**
    -   * Creates an injector for the given set of modules, in a given development
    -   * stage.
    +   * Creates an injector for the given set of modules, in a given development stage.
        *
    -   * @throws CreationException if one or more errors occur during injector
    -   *     creation.
    +   * @throws CreationException if one or more errors occur during injector creation.
        */
       public static Injector createInjector(Stage stage, Module... modules) {
         return createInjector(stage, Arrays.asList(modules));
       }
     
       /**
    -   * Creates an injector for the given set of modules, in a given development
    -   * stage.
    +   * Creates an injector for the given set of modules, in a given development stage.
        *
    -   * @throws CreationException if one or more errors occur during injector
    -   *     construction
    +   * @throws CreationException if one or more errors occur during injector construction
        */
    -  public static Injector createInjector(Stage stage,
    -      Iterable modules) {
    -    return new InternalInjectorCreator()
    -        .stage(stage)
    -        .addModules(modules)
    -        .build();
    +  public static Injector createInjector(Stage stage, Iterable modules) {
    +    return new InternalInjectorCreator().stage(stage).addModules(modules).build();
       }
     }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/ImplementedBy.java sisu-guice-4.2.0/core/src/com/google/inject/ImplementedBy.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/ImplementedBy.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/ImplementedBy.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -31,8 +31,6 @@
     @Target(TYPE)
     public @interface ImplementedBy {
     
    -  /**
    -   * The implementation type.
    -   */
    +  /** The implementation type. */
       Class value();
     }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Inject.java sisu-guice-4.2.0/core/src/com/google/inject/Inject.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/Inject.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/Inject.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -26,44 +26,37 @@
     import java.lang.annotation.Target;
     
     /**
    - * Annotates members of your implementation class (constructors, methods
    - * and fields) into which the {@link Injector} should inject values.
    - * The Injector fulfills injection requests for:
    + * Annotates members of your implementation class (constructors, methods and fields) into which the
    + * {@link Injector} should inject values. The Injector fulfills injection requests for:
      *
      * 
      - *
    • Every instance it constructs. The class being constructed must have - * exactly one of its constructors marked with {@code @Inject} or must have a - * constructor taking no parameters. The Injector then proceeds to perform - * field and method injections. - * - *
    • Pre-constructed instances passed to {@link Injector#injectMembers}, - * {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and - * {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(javax.inject.Provider)}. - * In this case all constructors are, of course, ignored. - * - *
    • Static fields and methods of classes which any {@link Module} has - * specifically requested static injection for, using - * {@link Binder#requestStaticInjection}. + *
    • Every instance it constructs. The class being constructed must have exactly one of its + * constructors marked with {@code @Inject} or must have a constructor taking no parameters. The + * Injector then proceeds to perform field and method injections. + *
    • Pre-constructed instances passed to {@link Injector#injectMembers}, {@link + * com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and {@link + * com.google.inject.binder.LinkedBindingBuilder#toProvider(javax.inject.Provider)}. In this + * case all constructors are, of course, ignored. + *
    • Static fields and methods of classes which any {@link Module} has specifically requested + * static injection for, using {@link Binder#requestStaticInjection}. *
    * - * In all cases, a member can be injected regardless of its Java access - * specifier (private, default, protected, public). + * In all cases, a member can be injected regardless of its Java access specifier (private, default, + * protected, public). * * @author crazybob@google.com (Bob Lee) */ -@Target({ METHOD, CONSTRUCTOR, FIELD }) +@Target({METHOD, CONSTRUCTOR, FIELD}) @Retention(RUNTIME) @Documented public @interface Inject { /** - * If true, and the appropriate binding is not found, - * the Injector will skip injection of this method or field rather than - * produce an error. When applied to a field, any default value already - * assigned to the field will remain (guice will not actively null out the - * field). When applied to a method, the method will only be invoked if - * bindings for all parameters are found. When applied to a - * constructor, an error will result upon Injector creation. + * If true, and the appropriate binding is not found, the Injector will skip injection of this + * method or field rather than produce an error. When applied to a field, any default value + * already assigned to the field will remain (guice will not actively null out the field). When + * applied to a method, the method will only be invoked if bindings for all parameters are + * found. When applied to a constructor, an error will result upon Injector creation. */ boolean optional() default false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Injector.java sisu-guice-4.2.0/core/src/com/google/inject/Injector.java --- sisu-guice-3.2.6/core/src/com/google/inject/Injector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Injector.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject; import com.google.inject.spi.TypeConverterBinding; - import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; @@ -64,9 +63,8 @@ * you, you'll never need to use this method. * * @param instance to inject members on - * * @see Binder#getMembersInjector(Class) for a preferred alternative that supports checks before - * run time + * run time */ void injectMembers(Object instance); @@ -76,7 +74,7 @@ * * @param typeLiteral type to get members injector for * @see Binder#getMembersInjector(TypeLiteral) for an alternative that offers up front error - * detection + * detection * @since 2.0 */ MembersInjector getMembersInjector(TypeLiteral typeLiteral); @@ -87,8 +85,7 @@ * instead to get increased up front error detection. * * @param type type to get members injector for - * @see Binder#getMembersInjector(Class) for an alternative that offers up front error - * detection + * @see Binder#getMembersInjector(Class) for an alternative that offers up front error detection * @since 2.0 */ MembersInjector getMembersInjector(Class type); @@ -97,9 +94,9 @@ * Returns this injector's explicit bindings. * *

    The returned map does not include bindings inherited from a {@link #getParent() parent - * injector}, should one exist. The returned map is guaranteed to iterate (for example, with - * its {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in - * which bindings appear in user Modules. + * injector}, should one exist. The returned map is guaranteed to iterate (for example, with its + * {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in which + * bindings appear in user Modules. * *

    This method is part of the Guice SPI and is intended for use by tools and extensions. */ @@ -108,14 +105,15 @@ /** * Returns a snapshot of this injector's bindings, both explicit and * just-in-time. The returned map is immutable; it contains only the bindings that were - * present when {@code getAllBindings()} was invoked. Subsequent calls may return a map with - * additional just-in-time bindings. + * present when {@code getAllBindings()} was invoked. Just-in-time bindings are only present if + * they have been requested at least once. Subsequent calls may return a map with additional + * just-in-time bindings. * *

    The returned map does not include bindings inherited from a {@link #getParent() parent * injector}, should one exist. * *

    This method is part of the Guice SPI and is intended for use by tools and extensions. - * + * * @since 3.0 */ Map, Binding> getAllBindings(); @@ -142,17 +140,17 @@ * @since 2.0 */ Binding getBinding(Class type); - + /** - * Returns the binding if it already exists, or null if does not exist. Unlike - * {@link #getBinding(Key)}, this does not attempt to create just-in-time bindings - * for keys that aren't bound. - * - *

    This method is part of the Guice SPI and is intended for use by tools and extensions. - * + * Returns the binding if it already exists, or null if does not exist. Unlike {@link + * #getBinding(Key)}, this does not attempt to create just-in-time bindings for keys that aren't + * bound. + * + *

    This method is part of the Guice SPI and is intended for use by tools and extensions. + * * @since 3.0 */ - Binding getExistingBinding(Key key); + Binding getExistingBinding(Key key); /** * Returns all explicit bindings for {@code type}. @@ -171,8 +169,8 @@ Provider getProvider(Key key); /** - * Returns the provider used to obtain instances for the given type. When feasible, avoid - * using this method, in favor of having Guice inject your dependencies ahead of time. + * Returns the provider used to obtain instances for the given type. When feasible, avoid using + * this method, in favor of having Guice inject your dependencies ahead of time. * * @throws ConfigurationException if this injector cannot find or create the provider. * @see Binder#getProvider(Class) for an alternative that offers up front error detection @@ -213,9 +211,9 @@ * *

    Just-in-time bindings created for child injectors will be created in an ancestor injector * whenever possible. This allows for scoped instances to be shared between injectors. Use - * explicit bindings to prevent bindings from being shared with the parent injector. Optional - * injections in just-in-time bindings (created in the parent injector) may be silently - * ignored if the optional dependencies are from the child injector. + * explicit bindings to prevent bindings from being shared with the parent injector. Optional + * injections in just-in-time bindings (created in the parent injector) may be silently ignored if + * the optional dependencies are from the child injector. * *

    No key may be bound by both an injector and one of its ancestors. This includes just-in-time * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each @@ -243,12 +241,12 @@ Injector createChildInjector(Module... modules); /** - * Returns a map containing all scopes in the injector. The maps keys are scoping annotations - * like {@code Singleton.class}, and the values are scope instances, such as {@code - * Scopes.SINGLETON}. The returned map is immutable. + * Returns a map containing all scopes in the injector. The maps keys are scoping annotations like + * {@code Singleton.class}, and the values are scope instances, such as {@code Scopes.SINGLETON}. + * The returned map is immutable. * *

    This method is part of the Guice SPI and is intended for use by tools and extensions. - * + * * @since 3.0 */ Map, Scope> getScopeBindings(); @@ -258,7 +256,7 @@ * immutable. * *

    This method is part of the Guice SPI and is intended for use by tools and extensions. - * + * * @since 3.0 */ Set getTypeConverterBindings(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/AbstractBindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/internal/AbstractBindingBuilder.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/AbstractBindingBuilder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/AbstractBindingBuilder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.inject.Scope; import com.google.inject.spi.Element; import com.google.inject.spi.InstanceBinding; - import java.lang.annotation.Annotation; import java.util.List; @@ -35,14 +34,15 @@ public abstract class AbstractBindingBuilder { public static final String IMPLEMENTATION_ALREADY_SET = "Implementation is set more than once."; - public static final String SINGLE_INSTANCE_AND_SCOPE - = "Setting the scope is not permitted when binding to a single instance."; + public static final String SINGLE_INSTANCE_AND_SCOPE = + "Setting the scope is not permitted when binding to a single instance."; public static final String SCOPE_ALREADY_SET = "Scope is set more than once."; - public static final String BINDING_TO_NULL = "Binding to null instances is not allowed. " - + "Use toProvider(Providers.of(null)) if this is your intended behaviour."; + public static final String BINDING_TO_NULL = + "Binding to null instances is not allowed. " + + "Use toProvider(Providers.of(null)) if this is your intended behaviour."; public static final String CONSTANT_VALUE_ALREADY_SET = "Constant value is set more than once."; - public static final String ANNOTATION_ALREADY_SPECIFIED - = "More than one annotation is specified for this binding."; + public static final String ANNOTATION_ALREADY_SPECIFIED = + "More than one annotation is specified for this binding."; protected static final Key NULL_KEY = Key.get(Void.class); @@ -55,7 +55,7 @@ this.binder = binder; this.elements = elements; this.position = elements.size(); - this.binding = new UntargettedBindingImpl(source, key, Scoping.UNSCOPED); + this.binding = new UntargettedBindingImpl<>(source, key, Scoping.UNSCOPED); elements.add(position, this.binding); } @@ -73,16 +73,15 @@ protected BindingImpl annotatedWithInternal(Class annotationType) { checkNotNull(annotationType, "annotationType"); checkNotAnnotated(); - return setBinding(binding.withKey( - Key.get(this.binding.getKey().getTypeLiteral(), annotationType))); + return setBinding( + binding.withKey(Key.get(this.binding.getKey().getTypeLiteral(), annotationType))); } /** Sets the binding to a copy with the specified annotation on the bound key */ protected BindingImpl annotatedWithInternal(Annotation annotation) { checkNotNull(annotation, "annotation"); checkNotAnnotated(); - return setBinding(binding.withKey( - Key.get(this.binding.getKey().getTypeLiteral(), annotation))); + return setBinding(binding.withKey(Key.get(this.binding.getKey().getTypeLiteral(), annotation))); } public void in(final Class scopeAnnotation) { @@ -129,4 +128,4 @@ binder.addError(SCOPE_ALREADY_SET); } } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/AbstractBindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/AbstractBindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/AbstractBindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/AbstractBindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,11 +30,9 @@ import com.google.inject.TypeLiteral; import com.google.inject.spi.DefaultBindingTargetVisitor; -import java.util.Set; - /** * Guarantees that processing of Binding elements happens in a sane way. - * + * * @author sameb@google.com (Sam Berlin) */ abstract class AbstractBindingProcessor extends AbstractProcessor { @@ -42,21 +40,22 @@ // It's unfortunate that we have to maintain a blacklist of specific // classes, but we can't easily block the whole package because of // all our unit tests. - private static final Set> FORBIDDEN_TYPES = ImmutableSet.>of( - AbstractModule.class, - Binder.class, - Binding.class, - Injector.class, - Key.class, - MembersInjector.class, - Module.class, - Provider.class, - Scope.class, - Stage.class, - TypeLiteral.class); - + private static final ImmutableSet> FORBIDDEN_TYPES = + ImmutableSet.>of( + AbstractModule.class, + Binder.class, + Binding.class, + Injector.class, + Key.class, + MembersInjector.class, + Module.class, + Provider.class, + Scope.class, + Stage.class, + TypeLiteral.class); + protected final ProcessedBindingData bindingData; - + AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) { super(errors); this.bindingData = bindingData; @@ -66,7 +65,7 @@ InjectorImpl injector, Key key, Object source) { return new UntargettedBindingImpl(injector, key, source); } - + protected void putBinding(BindingImpl binding) { Key key = binding.getKey(); @@ -81,11 +80,11 @@ // If it failed because of an explicit duplicate binding... if (injector.state.getExplicitBinding(key) != null) { try { - if(!isOkayDuplicate(original, binding, injector.state)) { + if (!isOkayDuplicate(original, binding, injector.state)) { errors.bindingAlreadySet(key, original.getSource()); return; } - } catch(Throwable t) { + } catch (Throwable t) { errors.errorCheckingDuplicateBinding(key, original.getSource(), t); return; } @@ -103,8 +102,8 @@ } /** - * We tolerate duplicate bindings if one exposes the other or if the two bindings - * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}. + * We tolerate duplicate bindings if one exposes the other or if the two bindings are considered + * duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}. * * @param original the binding in the parent injector (candidate for an exposing binding) * @param binding the binding to check (candidate for the exposed binding) @@ -115,46 +114,63 @@ InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector(); return (exposedFrom == binding.getInjector()); } else { - original = (BindingImpl)state.getExplicitBindingsThisLevel().get(binding.getKey()); + original = (BindingImpl) state.getExplicitBindingsThisLevel().get(binding.getKey()); // If no original at this level, the original was on a parent, and we don't // allow deduplication between parents & children. - if(original == null) { + if (original == null) { return false; } else { return original.equals(binding); } } } - + private void validateKey(Object source, Key key) { Annotations.checkForMisplacedScopeAnnotations( key.getTypeLiteral().getRawType(), source, errors); } - - /** - * Processor for visiting bindings. Each overriden method that wants to - * actually process the binding should call prepareBinding first. + + /** + * Processor for visiting bindings. Each overriden method that wants to actually process the + * binding should call prepareBinding first. */ abstract class Processor extends DefaultBindingTargetVisitor { final Object source; final Key key; final Class rawType; Scoping scoping; - + Processor(BindingImpl binding) { source = binding.getSource(); key = binding.getKey(); rawType = key.getTypeLiteral().getRawType(); scoping = binding.getScoping(); } - - protected void prepareBinding() { + + protected void prepareBinding() { validateKey(source, key); scoping = Scoping.makeInjectable(scoping, injector, errors); } - protected void scheduleInitialization(final BindingImpl binding) { - bindingData.addUninitializedBinding(new Runnable() { + /** + * Schedule initialization of this binding to occur immediately after all bindings have been + * initialially processed. + */ + protected void scheduleInitialization(BindingImpl binding) { + bindingData.addUninitializedBinding(asRunnable(binding)); + } + + /** + * Schedule initialization for this binding to occur after all other static initialization of + * bindings. + */ + protected void scheduleDelayedInitialization(BindingImpl binding) { + bindingData.addDelayedUninitializedBinding(asRunnable(binding)); + } + + private Runnable asRunnable(final BindingImpl binding) { + return new Runnable() { + @Override public void run() { try { binding.getInjector().initializeBinding(binding, errors.withSource(source)); @@ -162,7 +178,7 @@ errors.merge(e.getErrors()); } } - }); + }; } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/AbstractProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/AbstractProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/AbstractProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/AbstractProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,16 +18,14 @@ import com.google.inject.spi.DefaultElementVisitor; import com.google.inject.spi.Element; - import java.util.Iterator; import java.util.List; /** * Abstract base class for creating an injector from module elements. * - *

    Extending classes must return {@code true} from any overridden - * {@code visit*()} methods, in order for the element processor to remove the - * handled element. + *

    Extending classes must return {@code true} from any overridden {@code visit*()} methods, in + * order for the element processor to remove the handled element. * * @author jessewilson@google.com (Jesse Wilson) */ @@ -63,7 +61,7 @@ this.injector = null; } } - + @Override protected Boolean visitOther(Element element) { return false; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Annotations.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Annotations.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Annotations.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Annotations.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,8 @@ package com.google.inject.internal; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Joiner.MapJoiner; @@ -32,7 +34,6 @@ import com.google.inject.internal.util.Classes; import com.google.inject.name.Named; import com.google.inject.name.Names; - import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,7 +44,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Map; - import javax.inject.Qualifier; /** @@ -53,9 +53,7 @@ */ public class Annotations { - /** - * Returns {@code true} if the given annotation type has no attributes. - */ + /** Returns {@code true} if the given annotation type has no attributes. */ public static boolean isMarker(Class annotationType) { return annotationType.getDeclaredMethods().length == 0; } @@ -72,13 +70,15 @@ } private static final LoadingCache, Annotation> cache = - CacheBuilder.newBuilder().weakKeys().build( - new CacheLoader, Annotation>() { - @Override - public Annotation load(Class input) { - return generateAnnotationImpl(input); - } - }); + CacheBuilder.newBuilder() + .weakKeys() + .build( + new CacheLoader, Annotation>() { + @Override + public Annotation load(Class input) { + return generateAnnotationImpl(input); + } + }); /** * Generates an Annotation for the annotation class. Requires that the annotation is all @@ -87,31 +87,32 @@ public static T generateAnnotation(Class annotationType) { Preconditions.checkState( isAllDefaultMethods(annotationType), "%s is not all default methods", annotationType); - return (T)cache.getUnchecked(annotationType); + return (T) cache.getUnchecked(annotationType); } private static T generateAnnotationImpl(final Class annotationType) { final Map members = resolveMembers(annotationType); - return annotationType.cast(Proxy.newProxyInstance( - annotationType.getClassLoader(), - new Class[] { annotationType }, - new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Exception { - String name = method.getName(); - if (name.equals("annotationType")) { - return annotationType; - } else if (name.equals("toString")) { - return annotationToString(annotationType, members); - } else if (name.equals("hashCode")) { - return annotationHashCode(annotationType, members); - } else if (name.equals("equals")) { - return annotationEquals(annotationType, members, args[0]); - } else { - return members.get(name); - } - } - })); + return annotationType.cast( + Proxy.newProxyInstance( + annotationType.getClassLoader(), + new Class[] {annotationType}, + new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Exception { + String name = method.getName(); + if (name.equals("annotationType")) { + return annotationType; + } else if (name.equals("toString")) { + return annotationToString(annotationType, members); + } else if (name.equals("hashCode")) { + return annotationHashCode(annotationType, members); + } else if (name.equals("equals")) { + return annotationEquals(annotationType, members, args[0]); + } else { + return members.get(name); + } + } + })); } private static ImmutableMap resolveMembers( @@ -124,8 +125,9 @@ } /** Implements {@link Annotation#equals}. */ - private static boolean annotationEquals(Class type, - Map members, Object other) throws Exception { + private static boolean annotationEquals( + Class type, Map members, Object other) + throws Exception { if (!type.isInstance(other)) { return false; } @@ -140,8 +142,8 @@ } /** Implements {@link Annotation#hashCode}. */ - private static int annotationHashCode(Class type, - Map members) throws Exception { + private static int annotationHashCode( + Class type, Map members) throws Exception { int result = 0; for (Method method : type.getDeclaredMethods()) { String name = method.getName(); @@ -153,25 +155,24 @@ private static final MapJoiner JOINER = Joiner.on(", ").withKeyValueSeparator("="); - private static final Function DEEP_TO_STRING_FN = new Function() { - @Override - public String apply(Object arg) { - String s = Arrays.deepToString(new Object[] {arg}); - return s.substring(1, s.length() - 1); // cut off brackets - } - }; + private static final Function DEEP_TO_STRING_FN = + new Function() { + @Override + public String apply(Object arg) { + String s = Arrays.deepToString(new Object[] {arg}); + return s.substring(1, s.length() - 1); // cut off brackets + } + }; /** Implements {@link Annotation#toString}. */ - private static String annotationToString(Class type, - Map members) throws Exception { + private static String annotationToString( + Class type, Map members) throws Exception { StringBuilder sb = new StringBuilder().append("@").append(type.getName()).append("("); JOINER.appendTo(sb, Maps.transformValues(members, DEEP_TO_STRING_FN)); return sb.append(")").toString(); } - /** - * Returns true if the given annotation is retained at runtime. - */ + /** Returns true if the given annotation is retained at runtime. */ public static boolean isRetainedAtRuntime(Class annotationType) { Retention retention = annotationType.getAnnotation(Retention.class); return retention != null && retention.value() == RetentionPolicy.RUNTIME; @@ -184,7 +185,8 @@ } /** Returns the scoping annotation, or null if there isn't one. */ - public static Class findScopeAnnotation(Errors errors, Annotation[] annotations) { + public static Class findScopeAnnotation( + Errors errors, Annotation[] annotations) { Class found = null; for (Annotation annotation : annotations) { @@ -212,53 +214,77 @@ return false; } + private static final boolean QUOTE_MEMBER_VALUES = determineWhetherToQuote(); + /** - * Checks for the presence of annotations. Caches results because Android doesn't. + * Returns {@code value}, quoted if annotation implementations quote their member values. In Java + * 9, annotations quote their string members. */ + public static String memberValueString(String value) { + return QUOTE_MEMBER_VALUES ? "\"" + value + "\"" : value; + } + + @Retention(RUNTIME) + private @interface TestAnnotation { + String value(); + } + + @TestAnnotation("determineWhetherToQuote") + private static boolean determineWhetherToQuote() { + try { + String annotation = + Annotations.class + .getDeclaredMethod("determineWhetherToQuote") + .getAnnotation(TestAnnotation.class) + .toString(); + return annotation.contains("\"determineWhetherToQuote\""); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + } + + /** Checks for the presence of annotations. Caches results because Android doesn't. */ static class AnnotationChecker { private final Collection> annotationTypes; /** Returns true if the given class has one of the desired annotations. */ private CacheLoader, Boolean> hasAnnotations = new CacheLoader, Boolean>() { - public Boolean load(Class annotationType) { - for (Annotation annotation : annotationType.getAnnotations()) { - if (annotationTypes.contains(annotation.annotationType())) { - return true; + @Override + public Boolean load(Class annotationType) { + for (Annotation annotation : annotationType.getAnnotations()) { + if (annotationTypes.contains(annotation.annotationType())) { + return true; + } + } + return false; } - } - return false; - } - }; + }; - final LoadingCache, Boolean> cache = CacheBuilder.newBuilder().weakKeys() - .build(hasAnnotations); + final LoadingCache, Boolean> cache = + CacheBuilder.newBuilder().weakKeys().build(hasAnnotations); - /** - * Constructs a new checker that looks for annotations of the given types. - */ + /** Constructs a new checker that looks for annotations of the given types. */ AnnotationChecker(Collection> annotationTypes) { this.annotationTypes = annotationTypes; } - /** - * Returns true if the given type has one of the desired annotations. - */ + /** Returns true if the given type has one of the desired annotations. */ boolean hasAnnotations(Class annotated) { return cache.getUnchecked(annotated); } } - private static final AnnotationChecker scopeChecker = new AnnotationChecker( - Arrays.asList(ScopeAnnotation.class, javax.inject.Scope.class)); + private static final AnnotationChecker scopeChecker = + new AnnotationChecker(Arrays.asList(ScopeAnnotation.class, javax.inject.Scope.class)); public static boolean isScopeAnnotation(Class annotationType) { return scopeChecker.hasAnnotations(annotationType); } /** - * Adds an error if there is a misplaced annotations on {@code type}. Scoping - * annotations are not allowed on abstract classes or interfaces. + * Adds an error if there is a misplaced annotations on {@code type}. Scoping annotations are not + * allowed on abstract classes or interfaces. */ public static void checkForMisplacedScopeAnnotations( Class type, Object source, Errors errors) { @@ -274,18 +300,20 @@ } } + // NOTE: getKey/findBindingAnnotation are used by Gin which is abandoned. So changing this API + // will prevent Gin users from upgrading Guice version. + /** Gets a key for the given type, member and annotations. */ - public static Key getKey(TypeLiteral type, Member member, Annotation[] annotations, - Errors errors) throws ErrorsException { + public static Key getKey( + TypeLiteral type, Member member, Annotation[] annotations, Errors errors) + throws ErrorsException { int numErrorsBefore = errors.size(); Annotation found = findBindingAnnotation(errors, member, annotations); errors.throwIfNewErrors(numErrorsBefore); return found == null ? Key.get(type) : Key.get(type, found); } - /** - * Returns the binding annotation on {@code member}, or null if there isn't one. - */ + /** Returns the binding annotation on {@code member}, or null if there isn't one. */ public static Annotation findBindingAnnotation( Errors errors, Member member, Annotation[] annotations) { Annotation found = null; @@ -304,23 +332,21 @@ return found; } - private static final AnnotationChecker bindingAnnotationChecker = new AnnotationChecker( - Arrays.asList(BindingAnnotation.class, Qualifier.class)); + private static final AnnotationChecker bindingAnnotationChecker = + new AnnotationChecker(Arrays.asList(BindingAnnotation.class, Qualifier.class)); - /** - * Returns true if annotations of the specified type are binding annotations. - */ + /** Returns true if annotations of the specified type are binding annotations. */ public static boolean isBindingAnnotation(Class annotationType) { return bindingAnnotationChecker.hasAnnotations(annotationType); } /** * If the annotation is an instance of {@code javax.inject.Named}, canonicalizes to - * com.google.guice.name.Named. Returns the given annotation otherwise. + * com.google.guice.name.Named. Returns the given annotation otherwise. */ public static Annotation canonicalizeIfNamed(Annotation annotation) { - if(annotation instanceof javax.inject.Named) { - return Names.named(((javax.inject.Named)annotation).value()); + if (annotation instanceof javax.inject.Named) { + return Names.named(((javax.inject.Named) annotation).value()); } else { return annotation; } @@ -338,4 +364,22 @@ return annotationType; } } + + /** + * Returns the name the binding should use. This is based on the annotation. If the annotation has + * an instance and is not a marker annotation, we ask the annotation for its toString. If it was a + * marker annotation or just an annotation type, we use the annotation's name. Otherwise, the name + * is the empty string. + */ + public static String nameOf(Key key) { + Annotation annotation = key.getAnnotation(); + Class annotationType = key.getAnnotationType(); + if (annotation != null && !isMarker(annotationType)) { + return key.getAnnotation().toString(); + } else if (key.getAnnotationType() != null) { + return "@" + key.getAnnotationType().getName(); + } else { + return ""; + } + } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/BindingBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/internal/BindingBuilder.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/BindingBuilder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/BindingBuilder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,6 @@ import com.google.inject.spi.Element; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.Message; - import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.util.List; @@ -47,33 +46,39 @@ super(binder, elements, source, key); } + @Override public BindingBuilder annotatedWith(Class annotationType) { annotatedWithInternal(annotationType); return this; } + @Override public BindingBuilder annotatedWith(Annotation annotation) { annotatedWithInternal(annotation); return this; } + @Override public BindingBuilder to(Class implementation) { return to(Key.get(implementation)); } + @Override public BindingBuilder to(TypeLiteral implementation) { return to(Key.get(implementation)); } + @Override public BindingBuilder to(Key linkedKey) { checkNotNull(linkedKey, "linkedKey"); checkNotTargetted(); BindingImpl base = getBinding(); - setBinding(new LinkedBindingImpl( - base.getSource(), base.getKey(), base.getScoping(), linkedKey)); + setBinding( + new LinkedBindingImpl(base.getSource(), base.getKey(), base.getScoping(), linkedKey)); return this; } + @Override public void toInstance(T instance) { checkNotTargetted(); @@ -92,14 +97,17 @@ } BindingImpl base = getBinding(); - setBinding(new InstanceBindingImpl( - base.getSource(), base.getKey(), Scoping.EAGER_SINGLETON, injectionPoints, instance)); + setBinding( + new InstanceBindingImpl( + base.getSource(), base.getKey(), Scoping.EAGER_SINGLETON, injectionPoints, instance)); } + @Override public BindingBuilder toProvider(Provider provider) { return toProvider((javax.inject.Provider) provider); } + @Override public BindingBuilder toProvider(javax.inject.Provider provider) { checkNotNull(provider, "provider"); checkNotTargetted(); @@ -114,38 +122,45 @@ } BindingImpl base = getBinding(); - setBinding(new ProviderInstanceBindingImpl( - base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider)); + setBinding( + new ProviderInstanceBindingImpl( + base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider)); return this; } + @Override public BindingBuilder toProvider( Class> providerType) { return toProvider(Key.get(providerType)); } + @Override public BindingBuilder toProvider( TypeLiteral> providerType) { return toProvider(Key.get(providerType)); } + @Override public BindingBuilder toProvider( Key> providerKey) { checkNotNull(providerKey, "providerKey"); checkNotTargetted(); BindingImpl base = getBinding(); - setBinding(new LinkedProviderBindingImpl( - base.getSource(), base.getKey(), base.getScoping(), providerKey)); + setBinding( + new LinkedProviderBindingImpl( + base.getSource(), base.getKey(), base.getScoping(), providerKey)); return this; } + @Override public ScopedBindingBuilder toConstructor(Constructor constructor) { return toConstructor(constructor, TypeLiteral.get(constructor.getDeclaringClass())); } - public ScopedBindingBuilder toConstructor(Constructor constructor, - TypeLiteral type) { + @Override + public ScopedBindingBuilder toConstructor( + Constructor constructor, TypeLiteral type) { checkNotNull(constructor, "constructor"); checkNotNull(type, "type"); checkNotTargetted(); @@ -162,16 +177,22 @@ try { InjectionPoint constructorPoint = InjectionPoint.forConstructor(constructor, type); - setBinding(new ConstructorBindingImpl(base.getKey(), base.getSource(), base.getScoping(), - constructorPoint, injectionPoints)); + setBinding( + new ConstructorBindingImpl( + base.getKey(), + base.getSource(), + base.getScoping(), + constructorPoint, + injectionPoints)); } catch (ConfigurationException e) { copyErrorsToBinder(e); } return this; } - - @Override public String toString() { + + @Override + public String toString() { return "BindingBuilder<" + getBinding().getKey().getTypeLiteral() + ">"; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/BindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/BindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/BindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/BindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ package com.google.inject.internal; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Provider; @@ -24,9 +24,7 @@ import com.google.inject.spi.ElementVisitor; import com.google.inject.spi.InstanceBinding; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public abstract class BindingImpl implements Binding { private final InjectorImpl injector; @@ -35,8 +33,12 @@ private final Scoping scoping; private final InternalFactory internalFactory; - public BindingImpl(InjectorImpl injector, Key key, Object source, - InternalFactory internalFactory, Scoping scoping) { + public BindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping) { this.injector = injector; this.key = key; this.source = source; @@ -52,16 +54,19 @@ this.scoping = scoping; } + @Override public Key getKey() { return key; } + @Override public Object getSource() { return source; } private volatile Provider provider; + @Override public Provider getProvider() { if (provider == null) { if (injector == null) { @@ -82,17 +87,19 @@ } /** - * Is this a constant binding? This returns true for constant bindings as - * well as toInstance() bindings. + * Is this a constant binding? This returns true for constant bindings as well as toInstance() + * bindings. */ public boolean isConstant() { return this instanceof InstanceBinding; } + @Override public V acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } + @Override public V acceptScopingVisitor(BindingScopingVisitor visitor) { return scoping.acceptVisitor(visitor); } @@ -104,9 +111,10 @@ protected BindingImpl withKey(Key key) { throw new AssertionError(); } - - @Override public String toString() { - return Objects.toStringHelper(Binding.class) + + @Override + public String toString() { + return MoreObjects.toStringHelper(Binding.class) .add("key", key) .add("scope", scoping) .add("source", source) diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/BindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/BindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/BindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/BindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,6 @@ import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderKeyBinding; import com.google.inject.spi.UntargettedBinding; - import java.util.Set; /** @@ -49,7 +48,8 @@ this.initializer = initializer; } - @Override public Boolean visit(Binding command) { + @Override + public Boolean visit(Binding command) { Class rawType = command.getKey().getTypeLiteral().getRawType(); if (Void.class.equals(rawType)) { if (command instanceof ProviderInstanceBinding @@ -61,127 +61,183 @@ } return true; } - + if (rawType == Provider.class) { errors.bindingToProvider(); return true; } - - return command.acceptTargetVisitor(new Processor((BindingImpl)command) { - @Override - public Boolean visit(ConstructorBinding binding) { - prepareBinding(); - try { - ConstructorBindingImpl onInjector = ConstructorBindingImpl.create(injector, key, - binding.getConstructor(), source, scoping, errors, false, false); - scheduleInitialization(onInjector); - putBinding(onInjector); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); - putBinding(invalidBinding(injector, key, source)); - } - return true; - } - - @Override - public Boolean visit(InstanceBinding binding) { - prepareBinding(); - Set injectionPoints = binding.getInjectionPoints(); - T instance = binding.getInstance(); - @SuppressWarnings("unchecked") // safe to cast to binding because - // the processor was constructed w/ it - Initializable ref = initializer.requestInjection( - injector, instance, (Binding) binding, source, injectionPoints); - ConstantFactory factory = new ConstantFactory(ref); - InternalFactory scopedFactory - = Scoping.scope(key, injector, factory, source, scoping); - putBinding(new InstanceBindingImpl(injector, key, source, scopedFactory, injectionPoints, - instance)); - return true; - } - - @Override - public Boolean visit(ProviderInstanceBinding binding) { - prepareBinding(); - javax.inject.Provider provider = binding.getUserSuppliedProvider(); - Set injectionPoints = binding.getInjectionPoints(); - Initializable> initializable = - initializer.>requestInjection( - injector, provider, null, source, injectionPoints); - // always visited with Binding - @SuppressWarnings("unchecked") - InternalFactory factory = new InternalFactoryToInitializableAdapter( - initializable, source, - injector.provisionListenerStore.get((ProviderInstanceBinding)binding)); - InternalFactory scopedFactory - = Scoping.scope(key, injector, factory, source, scoping); - putBinding(new ProviderInstanceBindingImpl(injector, key, source, scopedFactory, scoping, - provider, injectionPoints)); - return true; - } - - @Override - public Boolean visit(ProviderKeyBinding binding) { - prepareBinding(); - Key> providerKey = binding.getProviderKey(); - // always visited with Binding - @SuppressWarnings("unchecked") - BoundProviderFactory boundProviderFactory = new BoundProviderFactory( - injector, providerKey, source, - injector.provisionListenerStore.get((ProviderKeyBinding) binding)); - bindingData.addCreationListener(boundProviderFactory); - InternalFactory scopedFactory = Scoping.scope( - key, injector, (InternalFactory) boundProviderFactory, source, scoping); - putBinding(new LinkedProviderBindingImpl( - injector, key, source, scopedFactory, scoping, providerKey)); - return true; - } - - @Override - public Boolean visit(LinkedKeyBinding binding) { - prepareBinding(); - Key linkedKey = binding.getLinkedKey(); - if (key.equals(linkedKey)) { - errors.recursiveBinding(); - } - - FactoryProxy factory = new FactoryProxy(injector, key, linkedKey, source); - bindingData.addCreationListener(factory); - InternalFactory scopedFactory - = Scoping.scope(key, injector, factory, source, scoping); - putBinding( - new LinkedBindingImpl(injector, key, source, scopedFactory, scoping, linkedKey)); - return true; - } - - @Override - public Boolean visit(UntargettedBinding untargetted) { - return false; - } - @Override - public Boolean visit(ExposedBinding binding) { - throw new IllegalArgumentException("Cannot apply a non-module element"); - } - - @Override - public Boolean visit(ConvertedConstantBinding binding) { - throw new IllegalArgumentException("Cannot apply a non-module element"); - } - - @Override - public Boolean visit(ProviderBinding binding) { - throw new IllegalArgumentException("Cannot apply a non-module element"); - } - - @Override - protected Boolean visitOther(Binding binding) { - throw new IllegalStateException("BindingProcessor should override all visitations"); - } - }); + return command.acceptTargetVisitor( + new Processor((BindingImpl) command) { + @Override + public Boolean visit(ConstructorBinding binding) { + prepareBinding(); + try { + ConstructorBindingImpl onInjector = + ConstructorBindingImpl.create( + injector, + key, + binding.getConstructor(), + source, + scoping, + errors, + false, + false); + scheduleInitialization(onInjector); + putBinding(onInjector); + } catch (ErrorsException e) { + errors.merge(e.getErrors()); + putBinding(invalidBinding(injector, key, source)); + } + return true; + } + + @Override + public Boolean visit(InstanceBinding binding) { + prepareBinding(); + Set injectionPoints = binding.getInjectionPoints(); + T instance = binding.getInstance(); + @SuppressWarnings("unchecked") // safe to cast to binding because + // the processor was constructed w/ it + Initializable ref = + initializer.requestInjection( + injector, instance, (Binding) binding, source, injectionPoints); + ConstantFactory factory = new ConstantFactory<>(ref); + InternalFactory scopedFactory = + Scoping.scope(key, injector, factory, source, scoping); + putBinding( + new InstanceBindingImpl( + injector, key, source, scopedFactory, injectionPoints, instance)); + return true; + } + + @Override + public Boolean visit(ProviderInstanceBinding binding) { + prepareBinding(); + javax.inject.Provider provider = binding.getUserSuppliedProvider(); + if (provider instanceof InternalProviderInstanceBindingImpl.Factory) { + @SuppressWarnings("unchecked") + InternalProviderInstanceBindingImpl.Factory asProviderMethod = + (InternalProviderInstanceBindingImpl.Factory) provider; + return visitInternalProviderInstanceBindingFactory(asProviderMethod); + } + Set injectionPoints = binding.getInjectionPoints(); + Initializable> initializable = + initializer.>requestInjection( + injector, provider, null, source, injectionPoints); + // always visited with Binding + @SuppressWarnings("unchecked") + InternalFactory factory = + new InternalFactoryToInitializableAdapter( + initializable, + source, + injector.provisionListenerStore.get((ProviderInstanceBinding) binding)); + InternalFactory scopedFactory = + Scoping.scope(key, injector, factory, source, scoping); + putBinding( + new ProviderInstanceBindingImpl( + injector, key, source, scopedFactory, scoping, provider, injectionPoints)); + return true; + } + + @Override + public Boolean visit(ProviderKeyBinding binding) { + prepareBinding(); + Key> providerKey = + binding.getProviderKey(); + // always visited with Binding + @SuppressWarnings("unchecked") + BoundProviderFactory boundProviderFactory = + new BoundProviderFactory( + injector, + providerKey, + source, + injector.provisionListenerStore.get((ProviderKeyBinding) binding)); + bindingData.addCreationListener(boundProviderFactory); + InternalFactory scopedFactory = + Scoping.scope( + key, + injector, + (InternalFactory) boundProviderFactory, + source, + scoping); + putBinding( + new LinkedProviderBindingImpl( + injector, key, source, scopedFactory, scoping, providerKey)); + return true; + } + + @Override + public Boolean visit(LinkedKeyBinding binding) { + prepareBinding(); + Key linkedKey = binding.getLinkedKey(); + if (key.equals(linkedKey)) { + errors.recursiveBinding(); + } + + FactoryProxy factory = new FactoryProxy<>(injector, key, linkedKey, source); + bindingData.addCreationListener(factory); + InternalFactory scopedFactory = + Scoping.scope(key, injector, factory, source, scoping); + putBinding( + new LinkedBindingImpl(injector, key, source, scopedFactory, scoping, linkedKey)); + return true; + } + + /** Handle ProviderMethods specially. */ + private Boolean visitInternalProviderInstanceBindingFactory( + InternalProviderInstanceBindingImpl.Factory provider) { + InternalProviderInstanceBindingImpl binding = + new InternalProviderInstanceBindingImpl( + injector, + key, + source, + provider, + Scoping.scope(key, injector, provider, source, scoping), + scoping); + switch (binding.getInitializationTiming()) { + case DELAYED: + scheduleDelayedInitialization(binding); + break; + case EAGER: + scheduleInitialization(binding); + break; + default: + throw new AssertionError(); + } + putBinding(binding); + return true; + } + + @Override + public Boolean visit(UntargettedBinding untargetted) { + return false; + } + + @Override + public Boolean visit(ExposedBinding binding) { + throw new IllegalArgumentException("Cannot apply a non-module element"); + } + + @Override + public Boolean visit(ConvertedConstantBinding binding) { + throw new IllegalArgumentException("Cannot apply a non-module element"); + } + + @Override + public Boolean visit(ProviderBinding binding) { + throw new IllegalArgumentException("Cannot apply a non-module element"); + } + + @Override + protected Boolean visitOther(Binding binding) { + throw new IllegalStateException("BindingProcessor should override all visitations"); + } + }); } - @Override public Boolean visit(PrivateElements privateElements) { + @Override + public Boolean visit(PrivateElements privateElements) { for (Key key : privateElements.getExposedKeys()) { bindExposed(privateElements, key); } @@ -189,9 +245,14 @@ } private void bindExposed(PrivateElements privateElements, Key key) { - ExposedKeyFactory exposedKeyFactory = new ExposedKeyFactory(key, privateElements); + ExposedKeyFactory exposedKeyFactory = new ExposedKeyFactory<>(key, privateElements); bindingData.addCreationListener(exposedKeyFactory); - putBinding(new ExposedBindingImpl( - injector, privateElements.getExposedSource(key), key, exposedKeyFactory, privateElements)); + putBinding( + new ExposedBindingImpl( + injector, + privateElements.getExposedSource(key), + key, + exposedKeyFactory, + privateElements)); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/BoundProviderFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/BoundProviderFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/BoundProviderFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/BoundProviderFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,17 +16,12 @@ package com.google.inject.internal; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.inject.Key; import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.spi.Dependency; - import javax.inject.Provider; -/** - * Delegates to a custom factory which is also bound in the injector. - */ +/** Delegates to a custom factory which is also bound in the injector. */ final class BoundProviderFactory extends ProviderInternalFactory implements CreationListener { private final ProvisionListenerStackCallback provisionCallback; @@ -40,42 +35,53 @@ Object source, ProvisionListenerStackCallback provisionCallback) { super(source); - this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback"); + this.provisionCallback = provisionCallback; this.injector = injector; this.providerKey = providerKey; } + @Override public void notify(Errors errors) { try { - providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); + providerFactory = + injector.getInternalFactory( + providerKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { context.pushState(providerKey, source); + try { - errors = errors.withSource(providerKey); - javax.inject.Provider provider = providerFactory.get(errors, context, dependency, true); - return circularGet(provider, errors, context, dependency, provisionCallback); - } finally { - context.popState(); + javax.inject.Provider provider = providerFactory.get(context, dependency, true); + return circularGet(provider, context, dependency, provisionCallback); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(providerKey); + } finally { + context.popState(); + } } - + @Override - protected T provision(Provider provider, Errors errors, Dependency dependency, - ConstructionContext constructionContext) throws ErrorsException { + protected T provision( + Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { try { - return super.provision(provider, errors, dependency, constructionContext); - } catch(RuntimeException userException) { - throw errors.errorInProvider(userException).toException(); - } + return super.provision(provider, dependency, constructionContext); + } catch (RuntimeException userException) { + throw InternalProvisionException.errorInProvider(userException); + } } - @Override public String toString() { + @Override + public String toString() { return providerKey.toString(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/BytecodeGen.java sisu-guice-4.2.0/core/src/com/google/inject/internal/BytecodeGen.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/BytecodeGen.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/BytecodeGen.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,13 +22,13 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.inject.internal.InternalFlags.CustomClassLoadingOption; - import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -37,24 +37,26 @@ * interceptors} and to proxy circular dependencies. * *

    When loading classes, we need to be careful of: + * *

      - *
    • Memory leaks. Generated classes need to be garbage collected in long-lived - * applications. Once an injector and any instances it created can be garbage collected, the - * corresponding generated classes should be collectable. - *
    • Visibility. Containers like OSGi use class loader boundaries - * to enforce modularity at runtime. + *
    • Memory leaks. Generated classes need to be garbage collected in long-lived + * applications. Once an injector and any instances it created can be garbage collected, the + * corresponding generated classes should be collectable. + *
    • Visibility. Containers like OSGi use class loader boundaries to + * enforce modularity at runtime. *
    * *

    For each generated class, there's multiple class loaders involved: + * *

      - *
    • The related class's class loader. Every generated class services exactly - * one user-supplied class. This class loader must be used to access members with private and - * package visibility. - *
    • Guice's class loader. - *
    • Our bridge class loader. This is a child of the user's class loader. It - * selectively delegates to either the user's class loader (for user classes) or the Guice - * class loader (for internal classes that are used by the generated classes). This class - * loader that owns the classes generated by Guice. + *
    • The related class's class loader. Every generated class services exactly one + * user-supplied class. This class loader must be used to access members with protected and + * package visibility. + *
    • Guice's class loader. + *
    • Our bridge class loader. This is a child of the user's class loader. It + * selectively delegates to either the user's class loader (for user classes) or the Guice class + * loader (for internal classes that are used by the generated classes). This class loader that + * owns the classes generated by Guice. *
    * * @author mcculls@gmail.com (Stuart McCulloch) @@ -72,56 +74,57 @@ } /** ie. "com.google.inject.internal" */ - static final String GUICE_INTERNAL_PACKAGE - = BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal"); + static final String GUICE_INTERNAL_PACKAGE = + BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal"); /*if[AOP]*/ /** either "net.sf.cglib", or "com.google.inject.internal.cglib" */ - static final String CGLIB_PACKAGE - = net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib"); + static final String CGLIB_PACKAGE = + net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib"); - static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY - = new net.sf.cglib.core.DefaultNamingPolicy() { - @Override protected String getTag() { - return "ByGuice"; - } + static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY = + new net.sf.cglib.core.DefaultNamingPolicy() { + @Override + protected String getTag() { + return "ByGuice"; + } - @Override - public String getClassName(String prefix, String source, Object key, - net.sf.cglib.core.Predicate names) { - // we explicitly set the source here to "FastClass" so that our jarjar renaming - // to $FastClass doesn't leak into the class names. if we did not do this, - // classes would end up looking like $$$FastClassByGuice$$, with the extra $ - // at the front. - return super.getClassName(prefix, "FastClass", key, names); - } - }; + @Override + public String getClassName( + String prefix, String source, Object key, net.sf.cglib.core.Predicate names) { + // we explicitly set the source here to "FastClass" so that our jarjar renaming + // to $FastClass doesn't leak into the class names. if we did not do this, + // classes would end up looking like $$$FastClassByGuice$$, with the extra $ + // at the front. + return super.getClassName(prefix, "FastClass", key, names); + } + }; - static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY - = new net.sf.cglib.core.DefaultNamingPolicy() { - @Override - protected String getTag() { - return "ByGuice"; - } + static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY = + new net.sf.cglib.core.DefaultNamingPolicy() { + @Override + protected String getTag() { + return "ByGuice"; + } - @Override - public String getClassName(String prefix, String source, Object key, - net.sf.cglib.core.Predicate names) { - // we explicitly set the source here to "Enhancer" so that our jarjar renaming - // to $Enhancer doesn't leak into the class names. if we did not do this, - // classes would end up looking like $$$EnhancerByGuice$$, with the extra $ - // at the front. - return super.getClassName(prefix, "Enhancer", key, names); - } - }; + @Override + public String getClassName( + String prefix, String source, Object key, net.sf.cglib.core.Predicate names) { + // we explicitly set the source here to "Enhancer" so that our jarjar renaming + // to $Enhancer doesn't leak into the class names. if we did not do this, + // classes would end up looking like $$$EnhancerByGuice$$, with the extra $ + // at the front. + return super.getClassName(prefix, "Enhancer", key, names); + } + }; /*end[AOP]*/ /*if[NO_AOP] private static final String CGLIB_PACKAGE = " "; // any string that's illegal in a package name end[NO_AOP]*/ /** - * Weak cache of bridge class loaders that make the Guice implementation - * classes visible to various code-generated proxies of client classes. + * Weak cache of bridge class loaders that make the Guice implementation classes visible to + * various code-generated proxies of client classes. */ private static final LoadingCache CLASS_LOADER_CACHE; @@ -130,30 +133,32 @@ if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) { builder.maximumSize(0); } - CLASS_LOADER_CACHE = builder.build( - new CacheLoader() { - @Override public ClassLoader load(final ClassLoader typeClassLoader) { - logger.fine("Creating a bridge ClassLoader for " + typeClassLoader); - return AccessController.doPrivileged(new PrivilegedAction() { - public ClassLoader run() { - return new BridgeClassLoader(typeClassLoader); + CLASS_LOADER_CACHE = + builder.build( + new CacheLoader() { + @Override + public ClassLoader load(final ClassLoader typeClassLoader) { + logger.fine("Creating a bridge ClassLoader for " + typeClassLoader); + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public ClassLoader run() { + return new BridgeClassLoader(typeClassLoader); + } + }); } }); - } - }); } /** - * Attempts to canonicalize null references to the system class loader. - * May return null if for some reason the system loader is unavailable. + * Attempts to canonicalize null references to the system class loader. May return null if for + * some reason the system loader is unavailable. */ private static ClassLoader canonicalize(ClassLoader classLoader) { return classLoader != null ? classLoader : SystemBridgeHolder.SYSTEM_BRIDGE.getParent(); } - /** - * Returns the class loader to host generated classes for {@code type}. - */ + /** Returns the class loader to host generated classes for {@code type}. */ public static ClassLoader getClassLoader(Class type) { return getClassLoader(type, type.getClassLoader()); } @@ -191,19 +196,108 @@ } /*if[AOP]*/ - // use fully-qualified names so imports don't need preprocessor statements - public static net.sf.cglib.reflect.FastClass newFastClass(Class type, Visibility visibility) { - net.sf.cglib.reflect.FastClass.Generator generator - = new net.sf.cglib.reflect.FastClass.Generator(); - generator.setType(type); - if (visibility == Visibility.PUBLIC) { + // use fully-qualified names so imports don't need preprocessor statements + /** + * Returns a FastClass proxy for invoking the given member or {@code null} if access rules + * disallow it. + * + * @see #newFastClassForMember(Class, Member) for a full description + */ + public static net.sf.cglib.reflect.FastClass newFastClassForMember(Member member) { + return newFastClassForMember(member.getDeclaringClass(), member); + } + + /** + * Returns a FastClass proxy for invoking the given member or {@code null} if access rules + * disallow it. + * + *

    FastClass works by generating a type in the same package as the target {@code type}. This + * may or may not work depending on the access level of the class/member. It breaks down into the + * following cases depending on accessibility: + * + *

      + *
    • Public: This always works since we can generate the type into the {@link BridgeClassLoader} + * which ensures there are no versioning issues. + *
    • Package private and Protected: This works as long as: + *
        + *
      • We can generate into the same classloader as the type. This is not possible for JDK + * types which use the 'bootstrap' loader. + *
      • The classloader of the type has the same version of {@code FastClass} as we do. This + * may be violated when running in OSGI bundles. + *
      + * + *
    • Private: This never works. + *
    + * + * If we are unable to generate the type, then we return null and callers should work around by + * using normal java reflection. + */ + public static net.sf.cglib.reflect.FastClass newFastClassForMember(Class type, Member member) { + if (!new net.sf.cglib.core.VisibilityPredicate(type, false).evaluate(member)) { + // the member cannot be indexed by fast class. Bail out. + return null; + } + + boolean publiclyCallable = isPubliclyCallable(member); + if (!publiclyCallable && !hasSameVersionOfCglib(type.getClassLoader())) { + // The type is in a classloader with a different version of cglib and is not publicly visible + // (so we can't use the bridge classloader to work around). Bail out. + return null; + } + net.sf.cglib.reflect.FastClass.Generator generator = + new net.sf.cglib.reflect.FastClass.Generator(); + if (publiclyCallable) { + // Use the bridge classloader if we can generator.setClassLoader(getClassLoader(type)); } + generator.setType(type); generator.setNamingPolicy(FASTCLASS_NAMING_POLICY); - logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader()); + if (logger.isLoggable(Level.FINE)) { + logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader()); + } return generator.create(); } + /** + * Returns true if the types classloader has the same version of cglib that BytecodeGen has. This + * only returns false in strange OSGI situations, but it prevents us from using FastClass for non + * public members. + */ + private static boolean hasSameVersionOfCglib(ClassLoader classLoader) { + Class fc = net.sf.cglib.reflect.FastClass.class; + try { + return classLoader.loadClass(fc.getName()) == fc; + } catch (ClassNotFoundException e) { + return false; + } + } + + /** + * Returns true if the member can be called by a fast class generated in a different classloader. + */ + private static boolean isPubliclyCallable(Member member) { + if (!Modifier.isPublic(member.getModifiers())) { + return false; + } + Class[] parameterTypes; + if (member instanceof Constructor) { + parameterTypes = ((Constructor) member).getParameterTypes(); + } else { + Method method = (Method) member; + if (!Modifier.isPublic(method.getReturnType().getModifiers())) { + return false; + } + parameterTypes = method.getParameterTypes(); + } + + for (Class type : parameterTypes) { + if (!Modifier.isPublic(type.getModifiers())) { + return false; + } + } + return true; + } + public static net.sf.cglib.proxy.Enhancer newEnhancer(Class type, Visibility visibility) { net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer(); enhancer.setSuperclass(type); @@ -298,10 +392,10 @@ super(usersClassLoader); } - @Override protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (name.startsWith("sun.reflect")) { + if (name.startsWith("sun.reflect") || name.startsWith("jdk.internal.reflect")) { // these reflection classes must be loaded from bootstrap class loader return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve); } @@ -326,8 +420,7 @@ } // make the classic delegating loadClass method visible - Class classicLoadClass(String name, boolean resolve) - throws ClassNotFoundException { + Class classicLoadClass(String name, boolean resolve) throws ClassNotFoundException { return super.loadClass(name, resolve); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/CircularDependencyProxy.java sisu-guice-4.2.0/core/src/com/google/inject/internal/CircularDependencyProxy.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/CircularDependencyProxy.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/CircularDependencyProxy.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +16,7 @@ package com.google.inject.internal; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public interface CircularDependencyProxy { // marker interface } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.inject.binder.ConstantBindingBuilder; import com.google.inject.spi.Element; import com.google.inject.spi.InjectionPoint; - import java.lang.annotation.Annotation; import java.util.List; @@ -32,8 +31,7 @@ * * @author jessewilson@google.com (Jesse Wilson) */ -public final class ConstantBindingBuilderImpl - extends AbstractBindingBuilder +public final class ConstantBindingBuilderImpl extends AbstractBindingBuilder implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder { @SuppressWarnings("unchecked") // constant bindings start out with T unknown @@ -41,56 +39,69 @@ super(binder, elements, source, (Key) NULL_KEY); } + @Override public ConstantBindingBuilder annotatedWith(Class annotationType) { annotatedWithInternal(annotationType); return this; } + @Override public ConstantBindingBuilder annotatedWith(Annotation annotation) { annotatedWithInternal(annotation); return this; } + @Override public void to(final String value) { toConstant(String.class, value); } + @Override public void to(final int value) { toConstant(Integer.class, value); } + @Override public void to(final long value) { toConstant(Long.class, value); } + @Override public void to(final boolean value) { toConstant(Boolean.class, value); } + @Override public void to(final double value) { toConstant(Double.class, value); } + @Override public void to(final float value) { toConstant(Float.class, value); } + @Override public void to(final short value) { toConstant(Short.class, value); } + @Override public void to(final char value) { toConstant(Character.class, value); } + @Override public void to(final byte value) { toConstant(Byte.class, value); - } + } + @Override public void to(final Class value) { toConstant(Class.class, value); } + @Override public > void to(final E value) { toConstant(value.getDeclaringClass(), value); } @@ -121,11 +132,17 @@ binder.addError(BINDING_TO_NULL); } - setBinding(new InstanceBindingImpl( - base.getSource(), key, base.getScoping(), ImmutableSet.of(), instanceAsT)); + setBinding( + new InstanceBindingImpl( + base.getSource(), + key, + base.getScoping(), + ImmutableSet.of(), + instanceAsT)); } - @Override public String toString() { + @Override + public String toString() { return "ConstantBindingBuilder"; } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstantFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstantFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstantFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstantFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +16,10 @@ package com.google.inject.internal; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.inject.spi.Dependency; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ final class ConstantFactory implements InternalFactory { private final Initializable initializable; @@ -30,14 +28,14 @@ this.initializable = initializable; } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - return initializable.get(errors); + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + return initializable.get(); } + @Override public String toString() { - return Objects.toStringHelper(ConstantFactory.class) - .add("value", initializable) - .toString(); + return MoreObjects.toStringHelper(ConstantFactory.class).add("value", initializable).toString(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructionContext.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructionContext.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructionContext.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructionContext.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.internal; import com.google.inject.internal.InjectorImpl.InjectorOptions; - import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; @@ -59,28 +58,31 @@ invocationHandlers = null; } - public Object createProxy(Errors errors, InjectorOptions injectorOptions, - Class expectedType) throws ErrorsException { + public Object createProxy(InjectorOptions injectorOptions, Class expectedType) + throws InternalProvisionException { if (injectorOptions.disableCircularProxies) { - throw errors.circularProxiesDisabled(expectedType).toException(); + throw InternalProvisionException.circularDependenciesDisabled(expectedType); } if (!expectedType.isInterface()) { - throw errors.cannotSatisfyCircularDependency(expectedType).toException(); + throw InternalProvisionException.cannotProxyClass(expectedType); } if (invocationHandlers == null) { - invocationHandlers = new ArrayList>(); + invocationHandlers = new ArrayList<>(); } - DelegatingInvocationHandler invocationHandler = new DelegatingInvocationHandler(); + DelegatingInvocationHandler invocationHandler = new DelegatingInvocationHandler<>(); invocationHandlers.add(invocationHandler); // TODO: if I create a proxy which implements all the interfaces of // the implementation type, I'll be able to get away with one proxy // instance (as opposed to one per caller). ClassLoader classLoader = BytecodeGen.getClassLoader(expectedType); - return expectedType.cast(Proxy.newProxyInstance(classLoader, - new Class[] { expectedType, CircularDependencyProxy.class }, invocationHandler)); + return expectedType.cast( + Proxy.newProxyInstance( + classLoader, + new Class[] {expectedType, CircularDependencyProxy.class}, + invocationHandler)); } public void setProxyDelegates(T delegate) { diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructionProxyFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructionProxyFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructionProxyFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructionProxyFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,8 +23,6 @@ */ interface ConstructionProxyFactory { - /** - * Gets a construction proxy for the given constructor. - */ + /** Gets a construction proxy for the given constructor. */ ConstructionProxy create() throws ErrorsException; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructionProxy.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructionProxy.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructionProxy.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructionProxy.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,28 +18,22 @@ import com.google.common.collect.ImmutableMap; import com.google.inject.spi.InjectionPoint; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; /** - * Proxies calls to a {@link java.lang.reflect.Constructor} for a class - * {@code T}. + * Proxies calls to a {@link java.lang.reflect.Constructor} for a class {@code T}. * * @author crazybob@google.com (Bob Lee) */ interface ConstructionProxy { - /** - * Constructs an instance of {@code T} for the given arguments. - */ + /** Constructs an instance of {@code T} for the given arguments. */ T newInstance(Object... arguments) throws InvocationTargetException; - /** - * Returns the injection point for this constructor. - */ + /** Returns the injection point for this constructor. */ InjectionPoint getInjectionPoint(); /** @@ -49,9 +43,7 @@ Constructor getConstructor(); /*if[AOP]*/ - /** - * Returns the interceptors applied to each method, in order of invocation. - */ + /** Returns the interceptors applied to each method, in order of invocation. */ ImmutableMap> getMethodInterceptors(); /*end[AOP]*/ } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructorBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructorBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructorBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructorBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.inject.internal.Annotations.findScopeAnnotation; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; @@ -31,7 +32,6 @@ import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; - import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -46,44 +46,60 @@ private final Factory factory; private final InjectionPoint constructorInjectionPoint; - private ConstructorBindingImpl(InjectorImpl injector, Key key, Object source, - InternalFactory scopedFactory, Scoping scoping, Factory factory, + private ConstructorBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory scopedFactory, + Scoping scoping, + Factory factory, InjectionPoint constructorInjectionPoint) { super(injector, key, source, scopedFactory, scoping); this.factory = factory; this.constructorInjectionPoint = constructorInjectionPoint; } - public ConstructorBindingImpl(Key key, Object source, Scoping scoping, - InjectionPoint constructorInjectionPoint, Set injectionPoints) { + public ConstructorBindingImpl( + Key key, + Object source, + Scoping scoping, + InjectionPoint constructorInjectionPoint, + Set injectionPoints) { super(source, key, scoping); - this.factory = new Factory(false, key); - ConstructionProxy constructionProxy - = new DefaultConstructionProxyFactory(constructorInjectionPoint).create(); + this.factory = new Factory<>(false, key); + ConstructionProxy constructionProxy = + new DefaultConstructionProxyFactory(constructorInjectionPoint).create(); this.constructorInjectionPoint = constructorInjectionPoint; - factory.constructorInjector = new ConstructorInjector( - injectionPoints, constructionProxy, null, null); + factory.constructorInjector = + new ConstructorInjector(injectionPoints, constructionProxy, null, null); } /** * @param constructorInjector the constructor to use, or {@code null} to use the default. - * @param failIfNotLinked true if this ConstructorBindingImpl's InternalFactory should - * only succeed if retrieved from a linked binding + * @param failIfNotLinked true if this ConstructorBindingImpl's InternalFactory should only + * succeed if retrieved from a linked binding */ - static ConstructorBindingImpl create(InjectorImpl injector, Key key, - InjectionPoint constructorInjector, Object source, Scoping scoping, Errors errors, - boolean failIfNotLinked, boolean failIfNotExplicit) + static ConstructorBindingImpl create( + InjectorImpl injector, + Key key, + InjectionPoint constructorInjector, + Object source, + Scoping scoping, + Errors errors, + boolean failIfNotLinked, + boolean failIfNotExplicit) throws ErrorsException { int numErrors = errors.size(); @SuppressWarnings("unchecked") // constructorBinding guarantees type is consistent - Class rawType = constructorInjector == null - ? key.getTypeLiteral().getRawType() - : (Class) constructorInjector.getDeclaringType().getRawType(); + Class rawType = + constructorInjector == null + ? key.getTypeLiteral().getRawType() + : (Class) constructorInjector.getDeclaringType().getRawType(); // We can't inject abstract classes. if (Modifier.isAbstract(rawType.getModifiers())) { - errors.missingImplementation(key); + errors.missingImplementationWithHint(key, injector); } // Error: Inner class. @@ -110,16 +126,17 @@ Class annotatedType = constructorInjector.getMember().getDeclaringClass(); Class scopeAnnotation = findScopeAnnotation(errors, annotatedType); if (scopeAnnotation != null) { - scoping = Scoping.makeInjectable(Scoping.forAnnotation(scopeAnnotation), - injector, errors.withSource(rawType)); + scoping = + Scoping.makeInjectable( + Scoping.forAnnotation(scopeAnnotation), injector, errors.withSource(rawType)); } } errors.throwIfNewErrors(numErrors); - Factory factoryFactory = new Factory(failIfNotLinked, key); - InternalFactory scopedFactory - = Scoping.scope(key, injector, factoryFactory, source, scoping); + Factory factoryFactory = new Factory<>(failIfNotLinked, key); + InternalFactory scopedFactory = + Scoping.scope(key, injector, factoryFactory, source, scoping); return new ConstructorBindingImpl( injector, key, source, scopedFactory, scoping, factoryFactory, constructorInjector); @@ -131,12 +148,12 @@ || cxtor.isAnnotationPresent(javax.inject.Inject.class); } + @Override @SuppressWarnings("unchecked") // the result type always agrees with the ConstructorInjector type public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { factory.constructorInjector = (ConstructorInjector) injector.constructors.get(constructorInjectionPoint, errors); - factory.provisionCallback = - injector.provisionListenerStore.get(this); + factory.provisionCallback = injector.provisionListenerStore.get(this); } /** True if this binding has been initialized and is ready for use. */ @@ -146,7 +163,7 @@ /** Returns an injection point that can be used to clean up the constructor store. */ InjectionPoint getInternalConstructor() { - if(factory.constructorInjector != null) { + if (factory.constructorInjector != null) { return factory.constructorInjector.getConstructionProxy().getInjectionPoint(); } else { return constructorInjectionPoint; @@ -156,69 +173,87 @@ /** Returns a set of dependencies that can be iterated over to clean up stray JIT bindings. */ Set> getInternalDependencies() { ImmutableSet.Builder builder = ImmutableSet.builder(); - if(factory.constructorInjector == null) { + if (factory.constructorInjector == null) { builder.add(constructorInjectionPoint); // If the below throws, it's OK -- we just ignore those dependencies, because no one // could have used them anyway. try { - builder.addAll(InjectionPoint.forInstanceMethodsAndFields(constructorInjectionPoint.getDeclaringType())); - } catch(ConfigurationException ignored) {} + builder.addAll( + InjectionPoint.forInstanceMethodsAndFields( + constructorInjectionPoint.getDeclaringType())); + } catch (ConfigurationException ignored) { + } } else { - builder.add(getConstructor()) - .addAll(getInjectableMembers()); + builder.add(getConstructor()).addAll(getInjectableMembers()); } return Dependency.forInjectionPoints(builder.build()); } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { checkState(factory.constructorInjector != null, "not initialized"); return visitor.visit(this); } + @Override public InjectionPoint getConstructor() { checkState(factory.constructorInjector != null, "Binding is not ready"); return factory.constructorInjector.getConstructionProxy().getInjectionPoint(); } + @Override public Set getInjectableMembers() { checkState(factory.constructorInjector != null, "Binding is not ready"); return factory.constructorInjector.getInjectableMembers(); } /*if[AOP]*/ + @Override public Map> getMethodInterceptors() { checkState(factory.constructorInjector != null, "Binding is not ready"); return factory.constructorInjector.getConstructionProxy().getMethodInterceptors(); } /*end[AOP]*/ + @Override public Set> getDependencies() { - return Dependency.forInjectionPoints(new ImmutableSet.Builder() - .add(getConstructor()) - .addAll(getInjectableMembers()) - .build()); + return Dependency.forInjectionPoints( + new ImmutableSet.Builder() + .add(getConstructor()) + .addAll(getInjectableMembers()) + .build()); } - @Override protected BindingImpl withScoping(Scoping scoping) { + @Override + protected BindingImpl withScoping(Scoping scoping) { return new ConstructorBindingImpl( null, getKey(), getSource(), factory, scoping, factory, constructorInjectionPoint); } - @Override protected BindingImpl withKey(Key key) { + @Override + protected BindingImpl withKey(Key key) { return new ConstructorBindingImpl( null, key, getSource(), factory, getScoping(), factory, constructorInjectionPoint); } + @Override @SuppressWarnings("unchecked") // the raw constructor member and declaring type always agree public void applyTo(Binder binder) { InjectionPoint constructor = getConstructor(); - getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).toConstructor( - (Constructor) getConstructor().getMember(), (TypeLiteral) constructor.getDeclaringType())); + getScoping() + .applyTo( + binder + .withSource(getSource()) + .bind(getKey()) + .toConstructor( + (Constructor) getConstructor().getMember(), + (TypeLiteral) constructor.getDeclaringType())); } - @Override public String toString() { - return Objects.toStringHelper(ConstructorBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(ConstructorBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) @@ -227,11 +262,11 @@ @Override public boolean equals(Object obj) { - if(obj instanceof ConstructorBindingImpl) { - ConstructorBindingImpl o = (ConstructorBindingImpl)obj; + if (obj instanceof ConstructorBindingImpl) { + ConstructorBindingImpl o = (ConstructorBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(constructorInjectionPoint, o.constructorInjectionPoint); + && getScoping().equals(o.getScoping()) + && Objects.equal(constructorInjectionPoint, o.constructorInjectionPoint); } else { return false; } @@ -253,19 +288,22 @@ this.key = key; } + @Override @SuppressWarnings("unchecked") - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - checkState(constructorInjector != null, "Constructor not ready"); + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + ConstructorInjector localInjector = constructorInjector; + if (localInjector == null) { + throw new IllegalStateException("Constructor not ready"); + } - if(failIfNotLinked && !linked) { - throw errors.jitDisabled(key).toException(); + if (!linked && failIfNotLinked) { + throw InternalProvisionException.jitDisabled(key); } // This may not actually be safe because it could return a super type of T (if that's all the // client needs), but it should be OK in practice thanks to the wonders of erasure. - return (T) constructorInjector.construct(errors, context, - dependency.getKey().getTypeLiteral().getRawType(), provisionCallback); + return (T) localInjector.construct(context, dependency, provisionCallback); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructorInjector.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructorInjector.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructorInjector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructorInjector.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,8 +18,8 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback; +import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; - import java.lang.reflect.InvocationTargetException; import java.util.Set; @@ -36,7 +36,8 @@ private final ConstructionProxy constructionProxy; private final MembersInjectorImpl membersInjector; - ConstructorInjector(Set injectableMembers, + ConstructorInjector( + Set injectableMembers, ConstructionProxy constructionProxy, SingleParameterInjector[] parameterInjectors, MembersInjectorImpl membersInjector) { @@ -55,40 +56,48 @@ } /** - * Construct an instance. Returns {@code Object} instead of {@code T} because - * it may return a proxy. + * Construct an instance. Returns {@code Object} instead of {@code T} because it may return a + * proxy. */ - Object construct(final Errors errors, final InternalContext context, - Class expectedType, - ProvisionListenerStackCallback provisionCallback) - throws ErrorsException { + Object construct( + final InternalContext context, + Dependency dependency, + /* @Nullable */ ProvisionListenerStackCallback provisionCallback) + throws InternalProvisionException { final ConstructionContext constructionContext = context.getConstructionContext(this); - // We have a circular reference between constructors. Return a proxy. if (constructionContext.isConstructing()) { // TODO (crazybob): if we can't proxy this object, can we proxy the other object? return constructionContext.createProxy( - errors, context.getInjectorOptions(), expectedType); + context.getInjectorOptions(), dependency.getKey().getTypeLiteral().getRawType()); } // If we're re-entering this factory while injecting fields or methods, // return the same instance. This prevents infinite loops. T t = constructionContext.getCurrentReference(); if (t != null) { - return t; + if (context.getInjectorOptions().disableCircularProxies) { + throw InternalProvisionException.circularDependenciesDisabled( + dependency.getKey().getTypeLiteral().getRawType()); + } else { + return t; + } } constructionContext.startConstruction(); try { // Optimization: Don't go through the callback stack if we have no listeners. - if (!provisionCallback.hasListeners()) { - return provision(errors, context, constructionContext); + if (provisionCallback == null) { + return provision(context, constructionContext); } else { - return provisionCallback.provision(errors, context, new ProvisionCallback() { - public T call() throws ErrorsException { - return provision(errors, context, constructionContext); - } - }); + return provisionCallback.provision( + context, + new ProvisionCallback() { + @Override + public T call() throws InternalProvisionException { + return provision(context, constructionContext); + } + }); } } finally { constructionContext.finishConstruction(); @@ -96,12 +105,12 @@ } /** Provisions a new T. */ - private T provision(Errors errors, InternalContext context, - ConstructionContext constructionContext) throws ErrorsException { + private T provision(InternalContext context, ConstructionContext constructionContext) + throws InternalProvisionException { try { T t; try { - Object[] parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors); + Object[] parameters = SingleParameterInjector.getAll(context, parameterInjectors); t = constructionProxy.newInstance(parameters); constructionContext.setProxyDelegates(t); } finally { @@ -111,16 +120,15 @@ // Store reference. If an injector re-enters this factory, they'll get the same reference. constructionContext.setCurrentReference(t); - membersInjector.injectMembers(t, errors, context, false); - membersInjector.notifyListeners(t, errors); + MembersInjectorImpl localMembersInjector = membersInjector; + localMembersInjector.injectMembers(t, context, false); + localMembersInjector.notifyListeners(t); return t; } catch (InvocationTargetException userException) { - Throwable cause = userException.getCause() != null - ? userException.getCause() - : userException; - throw errors.withSource(constructionProxy.getInjectionPoint()) - .errorInjectingConstructor(cause).toException(); + Throwable cause = userException.getCause() != null ? userException.getCause() : userException; + throw InternalProvisionException.errorInjectingConstructor(cause) + .addSource(constructionProxy.getInjectionPoint()); } finally { constructionContext.removeCurrentReference(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructorInjectorStore.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructorInjectorStore.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ConstructorInjectorStore.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ConstructorInjectorStore.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,35 +29,33 @@ final class ConstructorInjectorStore { private final InjectorImpl injector; - private final FailableCache> cache - = new FailableCache> () { - @Override - protected ConstructorInjector create(InjectionPoint constructorInjector, Errors errors) - throws ErrorsException { - return createConstructor(constructorInjector, errors); - } - }; + private final FailableCache> cache = + new FailableCache>() { + @Override + protected ConstructorInjector create(InjectionPoint constructorInjector, Errors errors) + throws ErrorsException { + return createConstructor(constructorInjector, errors); + } + }; ConstructorInjectorStore(InjectorImpl injector) { this.injector = injector; } - /** - * Returns a new complete constructor injector with injection listeners registered. - */ + /** Returns a new complete constructor injector with injection listeners registered. */ public ConstructorInjector get(InjectionPoint constructorInjector, Errors errors) throws ErrorsException { return cache.get(constructorInjector, errors); } - + /** * Purges an injection point from the cache. Use this only if the cache is not actually valid and * needs to be purged. (See issue 319 and * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is * necessary.) - * - * Returns true if the injector for that point was stored in the cache, false otherwise. + * + *

    Returns true if the injector for that point was stored in the cache, false otherwise. */ boolean remove(InjectionPoint ip) { return cache.remove(ip); @@ -67,27 +65,32 @@ throws ErrorsException { int numErrorsBefore = errors.size(); - SingleParameterInjector[] constructorParameterInjectors - = injector.getParametersInjectors(injectionPoint.getDependencies(), errors); + SingleParameterInjector[] constructorParameterInjectors = + injector.getParametersInjectors(injectionPoint.getDependencies(), errors); @SuppressWarnings("unchecked") // the injector type agrees with the injection point type - MembersInjectorImpl membersInjector = (MembersInjectorImpl) injector.membersInjectorStore - .get(injectionPoint.getDeclaringType(), errors); + MembersInjectorImpl membersInjector = + (MembersInjectorImpl) + injector.membersInjectorStore.get(injectionPoint.getDeclaringType(), errors); /*if[AOP]*/ ImmutableList injectorAspects = injector.state.getMethodAspects(); - ImmutableList methodAspects = membersInjector.getAddedAspects().isEmpty() - ? injectorAspects - : ImmutableList.copyOf(concat(injectorAspects, membersInjector.getAddedAspects())); - ConstructionProxyFactory factory = new ProxyFactory(injectionPoint, methodAspects); + ImmutableList methodAspects = + membersInjector.getAddedAspects().isEmpty() + ? injectorAspects + : ImmutableList.copyOf(concat(injectorAspects, membersInjector.getAddedAspects())); + ConstructionProxyFactory factory = new ProxyFactory<>(injectionPoint, methodAspects); /*end[AOP]*/ /*if[NO_AOP] - ConstructionProxyFactory factory = new DefaultConstructionProxyFactory(injectionPoint); + ConstructionProxyFactory factory = new DefaultConstructionProxyFactory<>(injectionPoint); end[NO_AOP]*/ errors.throwIfNewErrors(numErrorsBefore); - return new ConstructorInjector(membersInjector.getInjectionPoints(), factory.create(), - constructorParameterInjectors, membersInjector); + return new ConstructorInjector( + membersInjector.getInjectionPoints(), + factory.create(), + constructorParameterInjectors, + membersInjector); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ContextualCallable.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ContextualCallable.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ContextualCallable.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ContextualCallable.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.internal; - -/** - * @author crazybob@google.com (Bob Lee) - */ -interface ContextualCallable { - T call(InternalContext context) throws ErrorsException; -} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/CreationListener.java sisu-guice-4.2.0/core/src/com/google/inject/internal/CreationListener.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/CreationListener.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/CreationListener.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,4 +21,4 @@ /** Notifies that creation should happen. */ void notify(Errors errors); -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/CycleDetectingLock.java sisu-guice-4.2.0/core/src/com/google/inject/internal/CycleDetectingLock.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/CycleDetectingLock.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/CycleDetectingLock.java 2018-04-03 18:18:08.000000000 +0000 @@ -2,7 +2,6 @@ import com.google.common.base.Preconditions; import com.google.common.base.Supplier; -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.ListMultimap; @@ -10,7 +9,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; - import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; @@ -21,166 +19,174 @@ /** * Simplified version of {@link Lock} that is special due to how it handles deadlocks detection. * - *

    Is an inherent part of {@link SingletonScope}, moved into a upper level class due - * to its size and complexity. - * - * @param Lock identification provided by the client, is returned unmodified to the client - * when lock cycle is detected to identify it. Only toString() needs to be implemented. - * Lock references this object internally, - * for the purposes of Garbage Collection you should not use heavy IDs. - * Lock is referenced by a lock factory as long as it's owned by a thread. + *

    Is an inherent part of {@link SingletonScope}, moved into a upper level class due to its size + * and complexity. * + * @param Lock identification provided by the client, is returned unmodified to the client when + * lock cycle is detected to identify it. Only toString() needs to be implemented. Lock + * references this object internally, for the purposes of Garbage Collection you should not use + * heavy IDs. Lock is referenced by a lock factory as long as it's owned by a thread. * @see SingletonScope * @see com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory - * * @author timofeyb (Timothy Basanov) */ interface CycleDetectingLock { /** - * Takes a lock in a blocking fashion in case no potential deadlocks are detected. - * If the lock was successfully owned, returns an empty map indicating no detected potential - * deadlocks. + * Takes a lock in a blocking fashion in case no potential deadlocks are detected. If the lock was + * successfully owned, returns an empty map indicating no detected potential deadlocks. * - * Otherwise, a map indicating threads involved in a potential deadlock are returned. - * Map is ordered by dependency cycle and lists locks for each thread that are part of - * the loop in order. Returned map is created atomically. + *

    Otherwise, a map indicating threads involved in a potential deadlock are returned. Map is + * ordered by dependency cycle and lists locks for each thread that are part of the loop in order, + * the last lock in the list is the one that the thread is currently waiting for. Returned map is + * created atomically. * - * In case no cycle is detected performance is O(threads creating singletons), - * in case cycle is detected performance is O(singleton locks). + *

    In case no cycle is detected performance is O(threads creating singletons), in case cycle is + * detected performance is O(singleton locks). */ - ListMultimap lockOrDetectPotentialLocksCycle(); + ListMultimap lockOrDetectPotentialLocksCycle(); - /** - * Unlocks previously locked lock. - */ + /** Unlocks previously locked lock. */ void unlock(); /** - * Wraps locks so they would never cause a deadlock. On each - * {@link CycleDetectingLock#lockOrDetectPotentialLocksCycle} we check for dependency cycles - * within locks created by the same factory. Either we detect a cycle and return it - * or take it atomically. + * Wraps locks so they would never cause a deadlock. On each {@link + * CycleDetectingLock#lockOrDetectPotentialLocksCycle} we check for dependency cycles within locks + * created by the same factory. Either we detect a cycle and return it or take it atomically. * - *

    Important to note that we do not prevent deadlocks in the client code. As an example: - * Thread A takes lock L and creates singleton class CA depending on the singleton class CB. - * Meanwhile thread B is creating class CB and is waiting on the lock L. Issue happens - * due to client code creating interdependent classes and using locks, where - * no guarantees on the creation order from Guice are provided. + *

    Important to note that we do not prevent deadlocks in the client code. As an example: Thread + * A takes lock L and creates singleton class CA depending on the singleton class CB. Meanwhile + * thread B is creating class CB and is waiting on the lock L. Issue happens due to client code + * creating interdependent classes and using locks, where no guarantees on the creation order from + * Guice are provided. * *

    Instances of these locks are not intended to be exposed outside of {@link SingletonScope}. */ class CycleDetectingLockFactory { /** - * Specifies lock that thread is currently waiting on to own it. - * Used only for purposes of locks cycle detection. + * Specifies lock that thread is currently waiting on to own it. Used only for purposes of locks + * cycle detection. * - * Key: thread id - * Value: lock that is being waited on + *

      + *
    • Key: thread + *
    • Value: lock that is being waited on + *
    * - * Element is added inside {@link #lockOrDetectPotentialLocksCycle()} before {@link Lock#lock} - * is called. Element is removed inside {@link #lockOrDetectPotentialLocksCycle()} after - * {@link Lock#lock} and synchronously with adding it to {@link #locksOwnedByThread}. + *

    Element is added inside {@link #lockOrDetectPotentialLocksCycle()} before {@link + * Lock#lock} is called. Element is removed inside {@link #lockOrDetectPotentialLocksCycle()} + * after {@link Lock#lock} and synchronously with adding it to {@link #locksOwnedByThread}. * - * Same lock can be added for several threads in case all of them are trying to - * take it. + *

    Same lock can be added for several threads in case all of them are trying to take it. * - * Guarded by {@code this}. + *

    Guarded by {@code CycleDetectingLockFactory.class}. */ - private Map lockThreadIsWaitingOn = Maps.newHashMap(); + private static Map> lockThreadIsWaitingOn = + Maps.newHashMap(); /** - * Lists locks that thread owns. - * Used only to populate locks in a potential cycle when it is detected. + * Lists locks that thread owns. Used only to populate locks in a potential cycle when it is + * detected. * - * Key: thread id - * Value: stack of locks that were owned. + *

      + *
    • Key: thread + *
    • Value: stack of locks that were owned. + *
    * - * Element is added inside {@link #lockOrDetectPotentialLocksCycle()} after {@link Lock#lock} - * is called. Element is removed inside {@link #unlock()} synchronously with - * {@link Lock#unlock()} call. + *

    Element is added inside {@link #lockOrDetectPotentialLocksCycle()} after {@link Lock#lock} + * is called. Element is removed inside {@link #unlock()} synchronously with {@link + * Lock#unlock()} call. * - * Same lock can only be present several times for the same thread as locks are - * reentrant. Lock can not be owned by several different threads as the same time. + *

    Same lock can only be present several times for the same thread as locks are reentrant. + * Lock can not be owned by several different threads as the same time. * - * Guarded by {@code this}. + *

    Guarded by {@code CycleDetectingLockFactory.class}. */ - private final Multimap locksOwnedByThread = + private static final Multimap> locksOwnedByThread = LinkedHashMultimap.create(); /** - * Creates new lock within this factory context. We can guarantee that locks created by - * the same factory would not deadlock. + * Creates new lock within this factory context. We can guarantee that locks created by the same + * factory would not deadlock. * - * @param newLockId lock id that would be used to report lock cycles if detected + * @param userLockId lock id that would be used to report lock cycles if detected */ - CycleDetectingLock create(ID newLockId) { - return new ReentrantCycleDetectingLock(newLockId, new ReentrantLock()); + CycleDetectingLock create(ID userLockId) { + return new ReentrantCycleDetectingLock(this, userLockId, new ReentrantLock()); } /** The implementation for {@link CycleDetectingLock}. */ - class ReentrantCycleDetectingLock implements CycleDetectingLock { + static class ReentrantCycleDetectingLock implements CycleDetectingLock { /** Underlying lock used for actual waiting when no potential deadlocks are detected. */ private final Lock lockImplementation; /** User id for this lock. */ private final ID userLockId; + /** Factory that was used to create this lock. */ + private final CycleDetectingLockFactory lockFactory; /** - * Thread id for the thread that owned this lock. Nullable. - * Guarded by {@code CycleDetectingLockFactory.this}. + * Thread that owns this lock. Nullable. Guarded by {@code CycleDetectingLockFactory.this}. */ - private Long lockOwnerThreadId = null; + private Thread lockOwnerThread = null; + /** - * Number of times that thread owned this lock. - * Guarded by {@code CycleDetectingLockFactory.this}. + * Number of times that thread owned this lock. Guarded by {@code + * CycleDetectingLockFactory.this}. */ private int lockReentranceCount = 0; - ReentrantCycleDetectingLock(ID userLockId, Lock lockImplementation) { + ReentrantCycleDetectingLock( + CycleDetectingLockFactory lockFactory, ID userLockId, Lock lockImplementation) { + this.lockFactory = lockFactory; this.userLockId = Preconditions.checkNotNull(userLockId, "userLockId"); - this.lockImplementation = Preconditions.checkNotNull( - lockImplementation, "lockImplementation"); + this.lockImplementation = + Preconditions.checkNotNull(lockImplementation, "lockImplementation"); } - @Override public ListMultimap lockOrDetectPotentialLocksCycle() { - final long currentThreadId = Thread.currentThread().getId(); - synchronized (CycleDetectingLockFactory.this) { + @Override + public ListMultimap lockOrDetectPotentialLocksCycle() { + final Thread currentThread = Thread.currentThread(); + synchronized (CycleDetectingLockFactory.class) { checkState(); - ListMultimap locksInCycle = detectPotentialLocksCycle(); + // Add this lock to the waiting map to ensure it is included in any reported lock cycle. + lockThreadIsWaitingOn.put(currentThread, this); + ListMultimap locksInCycle = detectPotentialLocksCycle(); if (!locksInCycle.isEmpty()) { + // We aren't actually going to wait for this lock, so remove it from the map. + lockThreadIsWaitingOn.remove(currentThread); // potential deadlock is found, we don't try to take this lock return locksInCycle; } - lockThreadIsWaitingOn.put(currentThreadId, this); } // this may be blocking, but we don't expect it to cause a deadlock lockImplementation.lock(); - synchronized (CycleDetectingLockFactory.this) { + synchronized (CycleDetectingLockFactory.class) { // current thread is no longer waiting on this lock - lockThreadIsWaitingOn.remove(currentThreadId); + lockThreadIsWaitingOn.remove(currentThread); checkState(); // mark it as owned by us - lockOwnerThreadId = currentThreadId; + lockOwnerThread = currentThread; lockReentranceCount++; // add this lock to the list of locks owned by a current thread - locksOwnedByThread.put(currentThreadId, this); + locksOwnedByThread.put(currentThread, this); } // no deadlock is found, locking successful return ImmutableListMultimap.of(); } - @Override public void unlock() { - final long currentThreadId = Thread.currentThread().getId(); - synchronized (CycleDetectingLockFactory.this) { + @Override + public void unlock() { + final Thread currentThread = Thread.currentThread(); + synchronized (CycleDetectingLockFactory.class) { checkState(); - Preconditions.checkState(lockOwnerThreadId != null, - "Thread is trying to unlock a lock that is not locked"); - Preconditions.checkState(lockOwnerThreadId == currentThreadId, + Preconditions.checkState( + lockOwnerThread != null, "Thread is trying to unlock a lock that is not locked"); + Preconditions.checkState( + lockOwnerThread == currentThread, "Thread is trying to unlock a lock owned by another thread"); // releasing underlying lock @@ -190,12 +196,13 @@ lockReentranceCount--; if (lockReentranceCount == 0) { // we no longer own this lock - lockOwnerThreadId = null; - Preconditions.checkState(locksOwnedByThread.remove(currentThreadId, this), + lockOwnerThread = null; + Preconditions.checkState( + locksOwnedByThread.remove(currentThread, this), "Internal error: Can not find this lock in locks owned by a current thread"); - if (locksOwnedByThread.get(currentThreadId).isEmpty()) { + if (locksOwnedByThread.get(currentThread).isEmpty()) { // clearing memory - locksOwnedByThread.removeAll(currentThreadId); + locksOwnedByThread.removeAll(currentThread); } } } @@ -203,21 +210,26 @@ /** Check consistency of an internal state. */ void checkState() throws IllegalStateException { - final long currentThreadId = Thread.currentThread().getId(); - Preconditions.checkState(!lockThreadIsWaitingOn.containsKey(currentThreadId), + final Thread currentThread = Thread.currentThread(); + Preconditions.checkState( + !lockThreadIsWaitingOn.containsKey(currentThread), "Internal error: Thread should not be in a waiting thread on a lock now"); - if (lockOwnerThreadId != null) { + if (lockOwnerThread != null) { // check state of a locked lock - Preconditions.checkState(lockReentranceCount >= 0, + Preconditions.checkState( + lockReentranceCount >= 0, "Internal error: Lock ownership and reentrance count internal states do not match"); - Preconditions.checkState(locksOwnedByThread.get(lockOwnerThreadId).contains(this), + Preconditions.checkState( + locksOwnedByThread.get(lockOwnerThread).contains(this), "Internal error: Set of locks owned by a current thread and lock " + "ownership status do not match"); } else { // check state of a non locked lock - Preconditions.checkState(lockReentranceCount == 0, + Preconditions.checkState( + lockReentranceCount == 0, "Internal error: Reentrance count of a non locked lock is expect to be zero"); - Preconditions.checkState(!locksOwnedByThread.values().contains(this), + Preconditions.checkState( + !locksOwnedByThread.values().contains(this), "Internal error: Non locked lock should not be owned by any thread"); } } @@ -225,76 +237,93 @@ /** * Algorithm to detect a potential lock cycle. * - * For lock's thread owner check which lock is it trying to take. - * Repeat recursively. When current thread is found a potential cycle is detected. + *

    For lock's thread owner check which lock is it trying to take. Repeat recursively. When + * current thread is found a potential cycle is detected. * * @see CycleDetectingLock#lockOrDetectPotentialLocksCycle() */ - private ListMultimap detectPotentialLocksCycle() { - final long currentThreadId = Thread.currentThread().getId(); - if (lockOwnerThreadId == null || lockOwnerThreadId == currentThreadId) { + private ListMultimap detectPotentialLocksCycle() { + final Thread currentThread = Thread.currentThread(); + if (lockOwnerThread == null || lockOwnerThread == currentThread) { // if nobody owns this lock, lock cycle is impossible // if a current thread owns this lock, we let Guice to handle it return ImmutableListMultimap.of(); } - ListMultimap potentialLocksCycle = Multimaps.newListMultimap( - new LinkedHashMap>(), - new Supplier>() { - @Override - public List get() { - return Lists.newArrayList(); - } - }); + ListMultimap potentialLocksCycle = + Multimaps.newListMultimap( + new LinkedHashMap>(), + new Supplier>() { + @Override + public List get() { + return Lists.newArrayList(); + } + }); // lock that is a part of a potential locks cycle, starts with current lock - ReentrantCycleDetectingLock lockOwnerWaitingOn = this; + ReentrantCycleDetectingLock lockOwnerWaitingOn = this; // try to find a dependency path between lock's owner thread and a current thread - while (lockOwnerWaitingOn != null && lockOwnerWaitingOn.lockOwnerThreadId != null) { - Long threadOwnerThreadWaits = lockOwnerWaitingOn.lockOwnerThreadId; + while (lockOwnerWaitingOn != null && lockOwnerWaitingOn.lockOwnerThread != null) { + Thread threadOwnerThreadWaits = lockOwnerWaitingOn.lockOwnerThread; // in case locks cycle exists lock we're waiting for is part of it - potentialLocksCycle.putAll(threadOwnerThreadWaits, - getAllLockIdsAfter(threadOwnerThreadWaits, lockOwnerWaitingOn)); - - if (threadOwnerThreadWaits == currentThreadId) { + lockOwnerWaitingOn = + addAllLockIdsAfter(threadOwnerThreadWaits, lockOwnerWaitingOn, potentialLocksCycle); + if (threadOwnerThreadWaits == currentThread) { // owner thread depends on current thread, cycle detected return potentialLocksCycle; } - // going for the next thread we wait on indirectly - lockOwnerWaitingOn = lockThreadIsWaitingOn.get(threadOwnerThreadWaits); } // no dependency path from an owner thread to a current thread return ImmutableListMultimap.of(); } - /** Return locks owned by a thread after a lock specified, inclusive. */ - private List getAllLockIdsAfter(long threadId, ReentrantCycleDetectingLock lock) { - List ids = Lists.newArrayList(); + /** + * Adds all locks held by the given thread that are after the given lock and then returns the + * lock the thread is currently waiting on, if any + */ + private ReentrantCycleDetectingLock addAllLockIdsAfter( + Thread thread, + ReentrantCycleDetectingLock lock, + ListMultimap potentialLocksCycle) { boolean found = false; - Collection ownedLocks = locksOwnedByThread.get(threadId); - Preconditions.checkNotNull(ownedLocks, - "Internal error: No locks were found taken by a thread"); - for (ReentrantCycleDetectingLock ownedLock : ownedLocks) { + Collection> ownedLocks = locksOwnedByThread.get(thread); + Preconditions.checkNotNull( + ownedLocks, "Internal error: No locks were found taken by a thread"); + for (ReentrantCycleDetectingLock ownedLock : ownedLocks) { if (ownedLock == lock) { found = true; } - if (found) { - ids.add(ownedLock.userLockId); + if (found && ownedLock.lockFactory == this.lockFactory) { + // All locks are stored in a shared map therefore there is no way to + // enforce type safety. We know that our cast is valid as we check for a lock's + // factory. If the lock was generated by the + // same factory it has to have same type as the current lock. + @SuppressWarnings("unchecked") + ID userLockId = (ID) ownedLock.userLockId; + potentialLocksCycle.put(thread, userLockId); } } - Preconditions.checkState(found, "Internal error: We can not find locks that " - + "created a cycle that we detected"); - return ids; + Preconditions.checkState( + found, + "Internal error: We can not find locks that created a cycle that we detected"); + ReentrantCycleDetectingLock unownedLock = lockThreadIsWaitingOn.get(thread); + // If this thread is waiting for a lock add it to the cycle and return it + if (unownedLock != null && unownedLock.lockFactory == this.lockFactory) { + @SuppressWarnings("unchecked") + ID typed = (ID) unownedLock.userLockId; + potentialLocksCycle.put(thread, typed); + } + return unownedLock; } - @Override public String toString() { + @Override + public String toString() { // copy is made to prevent a data race // no synchronization is used, potentially stale data, should be good enough - Long localLockOwnerThreadId = this.lockOwnerThreadId; - if (localLockOwnerThreadId != null) { - return String.format("CycleDetectingLock[%s][locked by %s]", - userLockId, localLockOwnerThreadId); + Thread thread = this.lockOwnerThread; + if (thread != null) { + return String.format("%s[%s][locked by %s]", super.toString(), userLockId, thread); } else { - return String.format("CycleDetectingLock[%s][unlocked]", userLockId); + return String.format("%s[%s][unlocked]", super.toString(), userLockId); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,10 +16,9 @@ package com.google.inject.internal; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; -import com.google.inject.internal.BytecodeGen.Visibility; import com.google.inject.spi.InjectionPoint; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -35,73 +34,119 @@ private final InjectionPoint injectionPoint; - /** - * @param injectionPoint an injection point whose member is a constructor of {@code T}. - */ + /** @param injectionPoint an injection point whose member is a constructor of {@code T}. */ DefaultConstructionProxyFactory(InjectionPoint injectionPoint) { this.injectionPoint = injectionPoint; } + @Override public ConstructionProxy create() { @SuppressWarnings("unchecked") // the injection point is for a constructor of T final Constructor constructor = (Constructor) injectionPoint.getMember(); - // Use FastConstructor if the constructor is public. - if (Modifier.isPublic(constructor.getModifiers())) { - Class classToConstruct = constructor.getDeclaringClass(); - /*if[AOP]*/ - try { - final net.sf.cglib.reflect.FastConstructor fastConstructor - = BytecodeGen.newFastClass(classToConstruct, Visibility.forMember(constructor)) - .getConstructor(constructor); - - return new ConstructionProxy() { - @SuppressWarnings("unchecked") - public T newInstance(Object... arguments) throws InvocationTargetException { - return (T) fastConstructor.newInstance(arguments); - } - public InjectionPoint getInjectionPoint() { - return injectionPoint; - } - public Constructor getConstructor() { - return constructor; - } - public ImmutableMap> - getMethodInterceptors() { - return ImmutableMap.of(); - } - }; - } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */} - /*end[AOP]*/ - if (!Modifier.isPublic(classToConstruct.getModifiers())) { - constructor.setAccessible(true); + /*if[AOP]*/ + try { + net.sf.cglib.reflect.FastClass fc = BytecodeGen.newFastClassForMember(constructor); + if (fc != null) { + int index = fc.getIndex(constructor.getParameterTypes()); + // We could just fall back to reflection in this case but I believe this should actually + // be impossible. + Preconditions.checkArgument( + index >= 0, "Could not find constructor %s in fast class", constructor); + return new FastClassProxy(injectionPoint, constructor, fc, index); } - } else { - constructor.setAccessible(true); + } catch (net.sf.cglib.core.CodeGenerationException e) { + /* fall-through */ } + /*end[AOP]*/ - return new ConstructionProxy() { - public T newInstance(Object... arguments) throws InvocationTargetException { - try { - return constructor.newInstance(arguments); - } catch (InstantiationException e) { - throw new AssertionError(e); // shouldn't happen, we know this is a concrete type - } catch (IllegalAccessException e) { - throw new AssertionError(e); // a security manager is blocking us, we're hosed - } - } - public InjectionPoint getInjectionPoint() { - return injectionPoint; - } - public Constructor getConstructor() { - return constructor; + return new ReflectiveProxy(injectionPoint, constructor); + } + + /*if[AOP]*/ + /** A {@link ConstructionProxy} that uses FastClass to invoke the constructor. */ + private static final class FastClassProxy implements ConstructionProxy { + final InjectionPoint injectionPoint; + final Constructor constructor; + final net.sf.cglib.reflect.FastClass fc; + final int index; + + private FastClassProxy( + InjectionPoint injectionPoint, + Constructor constructor, + net.sf.cglib.reflect.FastClass fc, + int index) { + this.injectionPoint = injectionPoint; + this.constructor = constructor; + this.fc = fc; + this.index = index; + } + + @Override + @SuppressWarnings("unchecked") + public T newInstance(Object... arguments) throws InvocationTargetException { + // Use this method instead of FastConstructor to save a stack frame + return (T) fc.newInstance(index, arguments); + } + + @Override + public InjectionPoint getInjectionPoint() { + return injectionPoint; + } + + @Override + public Constructor getConstructor() { + return constructor; + } + + @Override + public ImmutableMap> + getMethodInterceptors() { + return ImmutableMap.of(); + } + } + /*end[AOP]*/ + + private static final class ReflectiveProxy implements ConstructionProxy { + final Constructor constructor; + final InjectionPoint injectionPoint; + + ReflectiveProxy(InjectionPoint injectionPoint, Constructor constructor) { + if (!Modifier.isPublic(constructor.getDeclaringClass().getModifiers()) + || !Modifier.isPublic(constructor.getModifiers())) { + constructor.setAccessible(true); } - /*if[AOP]*/ - public ImmutableMap> - getMethodInterceptors() { - return ImmutableMap.of(); + this.injectionPoint = injectionPoint; + this.constructor = constructor; + } + + @Override + public T newInstance(Object... arguments) throws InvocationTargetException { + try { + return constructor.newInstance(arguments); + } catch (InstantiationException e) { + throw new AssertionError(e); // shouldn't happen, we know this is a concrete type + } catch (IllegalAccessException e) { + throw new AssertionError(e); // a security manager is blocking us, we're hosed } - /*end[AOP]*/ - }; + } + + @Override + public InjectionPoint getInjectionPoint() { + return injectionPoint; + } + + @Override + public Constructor getConstructor() { + return constructor; + } + + /*if[AOP]*/ + @Override + public ImmutableMap> + getMethodInterceptors() { + return ImmutableMap.of(); + } + /*end[AOP]*/ } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/DeferredLookups.java sisu-guice-4.2.0/core/src/com/google/inject/internal/DeferredLookups.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/DeferredLookups.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/DeferredLookups.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ import com.google.inject.spi.Element; import com.google.inject.spi.MembersInjectorLookup; import com.google.inject.spi.ProviderLookup; - import java.util.List; /** @@ -41,22 +40,22 @@ this.injector = injector; } - /** - * Initialize the specified lookups, either immediately or when the injector is created. - */ + /** Initialize the specified lookups, either immediately or when the injector is created. */ void initialize(Errors errors) { injector.lookups = injector; new LookupProcessor(errors).process(injector, lookups); } + @Override public Provider getProvider(Key key) { - ProviderLookup lookup = new ProviderLookup(key, key); + ProviderLookup lookup = new ProviderLookup<>(key, key); lookups.add(lookup); return lookup.getProvider(); } + @Override public MembersInjector getMembersInjector(TypeLiteral type) { - MembersInjectorLookup lookup = new MembersInjectorLookup(type, type); + MembersInjectorLookup lookup = new MembersInjectorLookup<>(type, type); lookups.add(lookup); return lookup.getMembersInjector(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/DelayedInitialize.java sisu-guice-4.2.0/core/src/com/google/inject/internal/DelayedInitialize.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/DelayedInitialize.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/DelayedInitialize.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,15 +17,13 @@ package com.google.inject.internal; /** - * Something that needs some delayed initialization, typically - * a binding or internal factory that needs to be created & put - * into the bindings map & then initialized later. - * + * Something that needs some delayed initialization, typically a binding or internal factory that + * needs to be created & put into the bindings map & then initialized later. + * * @author sameb@google.com (Sam Berlin) */ interface DelayedInitialize { - + /** Initializes this binding, throwing any errors if necessary. */ void initialize(InjectorImpl injector, Errors errors) throws ErrorsException; - } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/DelegatingInvocationHandler.java sisu-guice-4.2.0/core/src/com/google/inject/internal/DelegatingInvocationHandler.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/DelegatingInvocationHandler.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/DelegatingInvocationHandler.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +16,7 @@ package com.google.inject.internal; - import com.google.common.base.Preconditions; - import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -29,16 +27,18 @@ private T delegate; - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // checking volatile field for synchronization - Preconditions.checkState(initialized, + Preconditions.checkState( + initialized, "This is a proxy used to support" + " circular references. The object we're" + " proxying is not constructed yet. Please wait until after" + " injection has completed to use this object."); - Preconditions.checkNotNull(delegate, + Preconditions.checkNotNull( + delegate, "This is a proxy used to support" + " circular references. The object we're " + " proxying is initialized to null." diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Element.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Element.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Element.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Element.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.BindingAnnotation; +import java.lang.annotation.Retention; + +/** + * An internal binding annotation applied to each element in a multibinding. All elements are + * assigned a globally-unique id to allow different modules to contribute multibindings + * independently. + * + * @author jessewilson@google.com (Jesse Wilson) + */ +@Retention(RUNTIME) +@BindingAnnotation +@interface Element { + + enum Type { + MAPBINDER, + MULTIBINDER; + } + + String setName(); + + int uniqueId(); + + Type type(); + + String keyType(); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/EncounterImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/EncounterImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/EncounterImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/EncounterImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,13 +30,10 @@ import com.google.inject.spi.InjectionListener; import com.google.inject.spi.Message; import com.google.inject.spi.TypeEncounter; - import java.lang.reflect.Method; import java.util.List; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ final class EncounterImpl implements TypeEncounter { private final Errors errors; @@ -59,12 +56,12 @@ /*if[AOP]*/ ImmutableList getAspects() { - return aspects == null - ? ImmutableList.of() - : ImmutableList.copyOf(aspects); + return aspects == null ? ImmutableList.of() : ImmutableList.copyOf(aspects); } - public void bindInterceptor(Matcher methodMatcher, + @Override + public void bindInterceptor( + Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { checkState(valid, "Encounters may not be used after hear() returns."); @@ -89,6 +86,7 @@ : ImmutableSet.copyOf(injectionListeners); } + @Override public void register(MembersInjector membersInjector) { checkState(valid, "Encounters may not be used after hear() returns."); @@ -99,6 +97,7 @@ membersInjectors.add(membersInjector); } + @Override public void register(InjectionListener injectionListener) { checkState(valid, "Encounters may not be used after hear() returns."); @@ -109,36 +108,43 @@ injectionListeners.add(injectionListener); } + @Override public void addError(String message, Object... arguments) { checkState(valid, "Encounters may not be used after hear() returns."); errors.addMessage(message, arguments); } + @Override public void addError(Throwable t) { checkState(valid, "Encounters may not be used after hear() returns."); errors.errorInUserCode(t, "An exception was caught and reported. Message: %s", t.getMessage()); } + @Override public void addError(Message message) { checkState(valid, "Encounters may not be used after hear() returns."); errors.addMessage(message); } + @Override public Provider getProvider(Key key) { checkState(valid, "Encounters may not be used after hear() returns."); return lookups.getProvider(key); } + @Override public Provider getProvider(Class type) { return getProvider(Key.get(type)); } + @Override public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { checkState(valid, "Encounters may not be used after hear() returns."); return lookups.getMembersInjector(typeLiteral); } + @Override public MembersInjector getMembersInjector(Class type) { return getMembersInjector(TypeLiteral.get(type)); } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ErrorHandler.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ErrorHandler.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ErrorHandler.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ErrorHandler.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,13 +25,9 @@ */ interface ErrorHandler { - /** - * Handles an error. - */ + /** Handles an error. */ void handle(Object source, Errors errors); - /** - * Handles a user-reported error. - */ + /** Handles a user-reported error. */ void handle(Message message); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ErrorsException.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ErrorsException.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ErrorsException.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ErrorsException.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.google.inject.internal; /** @@ -25,6 +24,8 @@ * @author jessewilson@google.com (Jesse Wilson) */ public class ErrorsException extends Exception { + // NOTE: this is used by Gin which is abandoned. So changing this API will prevent Gin users from + // upgrading Guice version. private final Errors errors; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Errors.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Errors.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Errors.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Errors.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,45 +20,34 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; -import com.google.common.collect.Sets; +import com.google.common.primitives.Primitives; +import com.google.inject.Binding; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; -import com.google.inject.Guice; +import com.google.inject.Injector; import com.google.inject.Key; -import com.google.inject.MembersInjector; -import com.google.inject.Provider; -import com.google.inject.Provides; import com.google.inject.ProvisionException; import com.google.inject.Scope; import com.google.inject.TypeLiteral; -import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.SourceProvider; -import com.google.inject.internal.util.StackTraceElements; -import com.google.inject.spi.Dependency; import com.google.inject.spi.ElementSource; -import com.google.inject.spi.InjectionListener; -import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.Message; import com.google.inject.spi.ScopeBinding; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; - -import java.io.PrintWriter; import java.io.Serializable; -import java.io.StringWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Collection; import java.util.Formatter; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; /** * A collection of error messages. If this type is passed as a method parameter, the method is @@ -77,30 +66,58 @@ */ public final class Errors implements Serializable { - private static final Logger logger = Logger.getLogger(Guice.class.getName()); - - private static final Set> warnedDependencies = - Sets.newSetFromMap(new ConcurrentHashMap, Boolean>()); + /** When a binding is not found, show at most this many bindings with the same type */ + private static final int MAX_MATCHING_TYPES_REPORTED = 3; + /** When a binding is not found, show at most this many bindings that have some similarities */ + private static final int MAX_RELATED_TYPES_REPORTED = 3; /** - * The root errors object. Used to access the list of error messages. + * Throws a ConfigurationException with an NullPointerExceptions as the cause if the given + * reference is {@code null}. */ - private final Errors root; + static T checkNotNull(T reference, String name) { + if (reference != null) { + return reference; + } + + NullPointerException npe = new NullPointerException(name); + throw new ConfigurationException(ImmutableSet.of(new Message(npe.toString(), npe))); + } /** - * The parent errors object. Used to obtain the chain of source objects. + * Throws a ConfigurationException with a formatted {@link Message} if this condition is {@code + * false}. */ - private final Errors parent; + static void checkConfiguration(boolean condition, String format, Object... args) { + if (condition) { + return; + } + + throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args)))); + } /** - * The leaf source for errors added here. + * If the key is unknown and it is one of these types, it generally means there is a missing + * annotation. */ + private static final ImmutableSet> COMMON_AMBIGUOUS_TYPES = + ImmutableSet.>builder() + .add(Object.class) + .add(String.class) + .addAll(Primitives.allWrapperTypes()) + .build(); + + /** The root errors object. Used to access the list of error messages. */ + private final Errors root; + + /** The parent errors object. Used to obtain the chain of source objects. */ + private final Errors parent; + + /** The leaf source for errors added here. */ private final Object source; - /** - * null unless (root == this) and error messages exist. Never an empty list. - */ + /** null unless (root == this) and error messages exist. Never an empty list. */ private List errors; // lazy, use getErrorsForAdd() public Errors() { @@ -121,9 +138,7 @@ this.source = source; } - /** - * Returns an instance that uses {@code source} as a reference point for newly added errors. - */ + /** Returns an instance that uses {@code source} as a reference point for newly added errors. */ public Errors withSource(Object source) { return source == this.source || source == SourceProvider.UNKNOWN_SOURCE ? this @@ -131,69 +146,166 @@ } /** - * We use a fairly generic error message here. The motivation is to share the - * same message for both bind time errors: + * We use a fairly generic error message here. The motivation is to share the same message for + * both bind time errors: + * *

    Guice.createInjector(new AbstractModule() {
        *   public void configure() {
        *     bind(Runnable.class);
        *   }
        * }
    + * * ...and at provide-time errors: + * *
    Guice.createInjector().getInstance(Runnable.class);
    - * Otherwise we need to know who's calling when resolving a just-in-time - * binding, which makes things unnecessarily complex. + * + * Otherwise we need to know who's calling when resolving a just-in-time binding, which makes + * things unnecessarily complex. */ public Errors missingImplementation(Key key) { return addMessage("No implementation for %s was bound.", key); } - public Errors jitDisabled(Key key) { + /** Within guice's core, allow for better missing binding messages */ + Errors missingImplementationWithHint(Key key, Injector injector) { + StringBuilder sb = new StringBuilder(); + + sb.append(format("No implementation for %s was bound.", key)); + + // Keys which have similar strings as the desired key + List possibleMatches = new ArrayList<>(); + + // Check for other keys that may have the same type, + // but not the same annotation + TypeLiteral type = key.getTypeLiteral(); + List> sameTypes = injector.findBindingsByType(type); + if (!sameTypes.isEmpty()) { + sb.append(format("%n Did you mean?")); + int howMany = Math.min(sameTypes.size(), MAX_MATCHING_TYPES_REPORTED); + for (int i = 0; i < howMany; ++i) { + // TODO: Look into a better way to prioritize suggestions. For example, possbily + // use levenshtein distance of the given annotation vs actual annotation. + sb.append(format("%n * %s", sameTypes.get(i).getKey())); + } + int remaining = sameTypes.size() - MAX_MATCHING_TYPES_REPORTED; + if (remaining > 0) { + String plural = (remaining == 1) ? "" : "s"; + sb.append(format("%n %d more binding%s with other annotations.", remaining, plural)); + } + } else { + // For now, do a simple substring search for possibilities. This can help spot + // issues when there are generics being used (such as a wrapper class) and the + // user has forgotten they need to bind based on the wrapper, not the underlying + // class. In the future, consider doing a strict in-depth type search. + // TODO: Look into a better way to prioritize suggestions. For example, possbily + // use levenshtein distance of the type literal strings. + String want = type.toString(); + Map, Binding> bindingMap = injector.getAllBindings(); + for (Key bindingKey : bindingMap.keySet()) { + String have = bindingKey.getTypeLiteral().toString(); + if (have.contains(want) || want.contains(have)) { + Formatter fmt = new Formatter(); + Messages.formatSource(fmt, bindingMap.get(bindingKey).getSource()); + String match = String.format("%s bound%s", convert(bindingKey), fmt.toString()); + possibleMatches.add(match); + // TODO: Consider a check that if there are more than some number of results, + // don't suggest any. + if (possibleMatches.size() > MAX_RELATED_TYPES_REPORTED) { + // Early exit if we have found more than we need. + break; + } + } + } + + if ((possibleMatches.size() > 0) && (possibleMatches.size() <= MAX_RELATED_TYPES_REPORTED)) { + sb.append(format("%n Did you mean?")); + for (String possibleMatch : possibleMatches) { + sb.append(format("%n %s", possibleMatch)); + } + } + } + + // If where are no possibilities to suggest, then handle the case of missing + // annotations on simple types. This is usually a bad idea. + if (sameTypes.isEmpty() + && possibleMatches.isEmpty() + && key.getAnnotation() == null + && COMMON_AMBIGUOUS_TYPES.contains(key.getTypeLiteral().getRawType())) { + // We don't recommend using such simple types without annotations. + sb.append(format("%nThe key seems very generic, did you forget an annotation?")); + } + + return addMessage(sb.toString()); + } + + public Errors jitDisabled(Key key) { return addMessage("Explicit bindings are required and %s is not explicitly bound.", key); } public Errors jitDisabledInParent(Key key) { return addMessage( "Explicit bindings are required and %s would be bound in a parent injector.%n" - + "Please add an explicit binding for it, either in the child or the parent.", + + "Please add an explicit binding for it, either in the child or the parent.", key); } public Errors atInjectRequired(Class clazz) { return addMessage( "Explicit @Inject annotations are required on constructors," - + " but %s has no constructors annotated with @Inject.", + + " but %s has no constructors annotated with @Inject.", clazz); } - public Errors converterReturnedNull(String stringValue, Object source, - TypeLiteral type, TypeConverterBinding typeConverterBinding) { - return addMessage("Received null converting '%s' (bound at %s) to %s%n" - + " using %s.", + public Errors converterReturnedNull( + String stringValue, + Object source, + TypeLiteral type, + TypeConverterBinding typeConverterBinding) { + return addMessage( + "Received null converting '%s' (bound at %s) to %s%n using %s.", stringValue, convert(source), type, typeConverterBinding); } - public Errors conversionTypeError(String stringValue, Object source, TypeLiteral type, - TypeConverterBinding typeConverterBinding, Object converted) { - return addMessage("Type mismatch converting '%s' (bound at %s) to %s%n" - + " using %s.%n" - + " Converter returned %s.", + public Errors conversionTypeError( + String stringValue, + Object source, + TypeLiteral type, + TypeConverterBinding typeConverterBinding, + Object converted) { + return addMessage( + "Type mismatch converting '%s' (bound at %s) to %s%n" + + " using %s.%n" + + " Converter returned %s.", stringValue, convert(source), type, typeConverterBinding, converted); } - public Errors conversionError(String stringValue, Object source, - TypeLiteral type, TypeConverterBinding typeConverterBinding, RuntimeException cause) { - return errorInUserCode(cause, "Error converting '%s' (bound at %s) to %s%n" - + " using %s.%n" - + " Reason: %s", - stringValue, convert(source), type, typeConverterBinding, cause); - } - - public Errors ambiguousTypeConversion(String stringValue, Object source, TypeLiteral type, - TypeConverterBinding a, TypeConverterBinding b) { - return addMessage("Multiple converters can convert '%s' (bound at %s) to %s:%n" - + " %s and%n" - + " %s.%n" - + " Please adjust your type converter configuration to avoid overlapping matches.", + public Errors conversionError( + String stringValue, + Object source, + TypeLiteral type, + TypeConverterBinding typeConverterBinding, + RuntimeException cause) { + return errorInUserCode( + cause, + "Error converting '%s' (bound at %s) to %s%n using %s.%n Reason: %s", + stringValue, + convert(source), + type, + typeConverterBinding, + cause); + } + + public Errors ambiguousTypeConversion( + String stringValue, + Object source, + TypeLiteral type, + TypeConverterBinding a, + TypeConverterBinding b) { + return addMessage( + "Multiple converters can convert '%s' (bound at %s) to %s:%n" + + " %s and%n" + + " %s.%n" + + " Please adjust your type converter configuration to avoid overlapping matches.", stringValue, convert(source), type, a, b); } @@ -201,11 +313,6 @@ return addMessage("Binding to Provider is not allowed."); } - public Errors subtypeNotProvided(Class> providerType, - Class type) { - return addMessage("%s doesn't provide instances of %s.", providerType, type); - } - public Errors notASubtype(Class implementationType, Class type) { return addMessage("%s doesn't extend %s.", implementationType, type); } @@ -227,8 +334,9 @@ } public Errors optionalConstructor(Constructor constructor) { - return addMessage("%s is annotated @Inject(optional=true), " - + "but constructors cannot be optional.", constructor); + return addMessage( + "%s is annotated @Inject(optional=true), but constructors cannot be optional.", + constructor); } public Errors cannotBindToGuiceType(String simpleName) { @@ -241,13 +349,17 @@ public Errors scopeAnnotationOnAbstractType( Class scopeAnnotation, Class type, Object source) { - return addMessage("%s is annotated with %s, but scope annotations are not supported " - + "for abstract types.%n Bound at %s.", type, scopeAnnotation, convert(source)); + return addMessage( + "%s is annotated with %s, but scope annotations are not supported " + + "for abstract types.%n Bound at %s.", + type, scopeAnnotation, convert(source)); } public Errors misplacedBindingAnnotation(Member member, Annotation bindingAnnotation) { - return addMessage("%s is annotated with %s, but binding annotations should be applied " - + "to its parameters instead.", member, bindingAnnotation); + return addMessage( + "%s is annotated with %s, but binding annotations should be applied " + + "to its parameters instead.", + member, bindingAnnotation); } private static final String CONSTRUCTOR_RULES = @@ -255,22 +367,24 @@ + "annotated with @Inject or a zero-argument constructor that is not private."; public Errors missingConstructor(Class implementation) { - return addMessage("Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES, - implementation); + return addMessage( + "Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES, implementation); } public Errors tooManyConstructors(Class implementation) { - return addMessage("%s has more than one constructor annotated with @Inject. " - + CONSTRUCTOR_RULES, implementation); + return addMessage( + "%s has more than one constructor annotated with @Inject. " + CONSTRUCTOR_RULES, + implementation); } public Errors constructorNotDefinedByType(Constructor constructor, TypeLiteral type) { return addMessage("%s does not define %s", type, constructor); } - public Errors duplicateScopes(ScopeBinding existing, - Class annotationType, Scope scope) { - return addMessage("Scope %s is already bound to %s at %s.%n Cannot bind %s.", + public Errors duplicateScopes( + ScopeBinding existing, Class annotationType, Scope scope) { + return addMessage( + "Scope %s is already bound to %s at %s.%n Cannot bind %s.", existing.getScope(), annotationType, existing.getSource(), scope); } @@ -283,14 +397,17 @@ } public Errors cannotInjectInnerClass(Class type) { - return addMessage("Injecting into inner classes is not supported. " - + "Please use a 'static' class (top-level or nested) instead of %s.", type); + return addMessage( + "Injecting into inner classes is not supported. " + + "Please use a 'static' class (top-level or nested) instead of %s.", + type); } - public Errors duplicateBindingAnnotations(Member member, - Class a, Class b) { - return addMessage("%s has more than one annotation annotated with @BindingAnnotation: " - + "%s and %s", member, a, b); + public Errors duplicateBindingAnnotations( + Member member, Class a, Class b) { + return addMessage( + "%s has more than one annotation annotated with @BindingAnnotation: %s and %s", + member, a, b); } public Errors staticInjectionOnInterface(Class clazz) { @@ -327,7 +444,8 @@ } public Errors jitBindingAlreadySet(Key key) { - return addMessage("A just-in-time binding to %s was already configured on a parent injector.", key); + return addMessage( + "A just-in-time binding to %s was already configured on a parent injector.", key); } public Errors childBindingAlreadySet(Key key, Set sources) { @@ -339,53 +457,32 @@ allSources.format("%n bound at %s", source); } } - Errors errors = addMessage( - "Unable to create binding for %s." - + " It was already configured on one or more child injectors or private modules" - + "%s%n" - + " If it was in a PrivateModule, did you forget to expose the binding?", - key, allSources.out()); + Errors errors = + addMessage( + "Unable to create binding for %s." + + " It was already configured on one or more child injectors or private modules" + + "%s%n" + + " If it was in a PrivateModule, did you forget to expose the binding?", + key, allSources.out()); return errors; } public Errors errorCheckingDuplicateBinding(Key key, Object source, Throwable t) { return addMessage( "A binding to %s was already configured at %s and an error was thrown " - + "while checking duplicate bindings. Error: %s", + + "while checking duplicate bindings. Error: %s", key, convert(source), t); } - public Errors errorInjectingMethod(Throwable cause) { - return errorInUserCode(cause, "Error injecting method, %s", cause); - } - - public Errors errorNotifyingTypeListener(TypeListenerBinding listener, - TypeLiteral type, Throwable cause) { - return errorInUserCode(cause, - "Error notifying TypeListener %s (bound at %s) of %s.%n" - + " Reason: %s", - listener.getListener(), convert(listener.getSource()), type, cause); - } - - public Errors errorInjectingConstructor(Throwable cause) { - return errorInUserCode(cause, "Error injecting constructor, %s", cause); - } - - public Errors errorInProvider(RuntimeException runtimeException) { - Throwable unwrapped = unwrap(runtimeException); - return errorInUserCode(unwrapped, "Error in custom provider, %s", unwrapped); - } - - public Errors errorInUserInjector( - MembersInjector listener, TypeLiteral type, RuntimeException cause) { - return errorInUserCode(cause, "Error injecting %s using %s.%n" - + " Reason: %s", type, listener, cause); - } - - public Errors errorNotifyingInjectionListener( - InjectionListener listener, TypeLiteral type, RuntimeException cause) { - return errorInUserCode(cause, "Error notifying InjectionListener %s of %s.%n" - + " Reason: %s", listener, type, cause); + public Errors errorNotifyingTypeListener( + TypeListenerBinding listener, TypeLiteral type, Throwable cause) { + return errorInUserCode( + cause, + "Error notifying TypeListener %s (bound at %s) of %s.%n Reason: %s", + listener.getListener(), + convert(listener.getSource()), + type, + cause); } public Errors exposedButNotBound(Key key) { @@ -422,14 +519,6 @@ } } - private Throwable unwrap(RuntimeException runtimeException) { - if(runtimeException instanceof Exceptions.UnhandledCheckedUserException) { - return runtimeException.getCause(); - } else { - return runtimeException; - } - } - public Errors cannotInjectRawProvider() { return addMessage("Cannot inject a Provider that has no type parameter"); } @@ -446,18 +535,6 @@ return addMessage("Cannot inject a TypeLiteral that has no type parameter"); } - public Errors cannotSatisfyCircularDependency(Class expectedType) { - return addMessage( - "Tried proxying %s to support a circular dependency, but it is not an interface.", - expectedType); - } - - public Errors circularProxiesDisabled(Class expectedType) { - return addMessage( - "Tried proxying %s to support a circular dependency, but circular proxies are disabled.", - expectedType); - } - public void throwCreationExceptionIfErrorsExist() { if (!hasErrors()) { return; @@ -474,6 +551,7 @@ throw new ConfigurationException(getMessages()); } + // Guice no longer calls this, but external callers do public void throwProvisionExceptionIfErrorsExist() { if (!hasErrors()) { return; @@ -482,16 +560,10 @@ throw new ProvisionException(getMessages()); } - private Message merge(Message message) { - List sources = Lists.newArrayList(); - sources.addAll(getSources()); - sources.addAll(message.getSources()); - return new Message(sources, message.getMessage(), message.getCause()); - } - public Errors merge(Collection messages) { + List sources = getSources(); for (Message message : messages) { - addMessage(merge(message)); + addMessage(Messages.mergeSources(sources, message)); } return this; } @@ -505,7 +577,12 @@ return this; } - public List getSources() { + public Errors merge(InternalProvisionException ipe) { + merge(ipe.getErrors()); + return this; + } + + private List getSources() { List sources = Lists.newArrayList(); for (Errors e = this; e != null; e = e.parent) { if (e.source != SourceProvider.UNKNOWN_SOURCE) { @@ -536,8 +613,7 @@ } private Errors addMessage(Throwable cause, String messageFormat, Object... arguments) { - String message = format(messageFormat, arguments); - addMessage(new Message(getSources(), message, cause)); + addMessage(Messages.create(cause, getSources(), messageFormat, arguments)); return this; } @@ -549,11 +625,9 @@ return this; } + // TODO(lukes): inline into callers public static String format(String messageFormat, Object... arguments) { - for (int i = 0; i < arguments.length; i++) { - arguments[i] = Errors.convert(arguments[i]); - } - return String.format(messageFormat, arguments); + return Messages.format(messageFormat, arguments); } public List getMessages() { @@ -569,274 +643,23 @@ }.sortedCopy(root.errors); } - /** Returns the formatted message for an exception with the specified messages. */ - public static String format(String heading, Collection errorMessages) { - Formatter fmt = new Formatter().format(heading).format(":%n%n"); - int index = 1; - boolean displayCauses = getOnlyCause(errorMessages) == null; - - for (Message errorMessage : errorMessages) { - fmt.format("%s) %s%n", index++, errorMessage.getMessage()); - - List dependencies = errorMessage.getSources(); - for (int i = dependencies.size() - 1; i >= 0; i--) { - Object source = dependencies.get(i); - formatSource(fmt, source); - } - - Throwable cause = errorMessage.getCause(); - if (displayCauses && cause != null) { - StringWriter writer = new StringWriter(); - cause.printStackTrace(new PrintWriter(writer)); - fmt.format("Caused by: %s", writer.getBuffer()); - } - - fmt.format("%n"); - } - - if (errorMessages.size() == 1) { - fmt.format("1 error"); - } else { - fmt.format("%s errors", errorMessages.size()); - } - - return fmt.toString(); - } - - /** - * Returns {@code value} if it is non-null allowed to be null. Otherwise a message is added and - * an {@code ErrorsException} is thrown. - */ - public T checkForNull(T value, Object source, Dependency dependency) - throws ErrorsException { - if (value != null || dependency.isNullable() ) { - return value; - } - - // Hack to allow null parameters to @Provides methods, for backwards compatibility. - if (dependency.getInjectionPoint().getMember() instanceof Method) { - Method annotated = (Method) dependency.getInjectionPoint().getMember(); - if (annotated.isAnnotationPresent(Provides.class)) { - switch (InternalFlags.getNullableProvidesOption()) { - case ERROR: - break; // break out & let the below exception happen - case IGNORE: - return value; // user doesn't care about injecting nulls to non-@Nullables. - case WARN: - // Warn only once, otherwise we spam logs too much. - if (!warnedDependencies.add(dependency)) { - return value; - } - logger.log(Level.WARNING, - "Guice injected null into parameter {0} of {1} (a {2}), please mark it @Nullable." - + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an" - + " error.", - new Object[] { - dependency.getParameterIndex(), - convert(dependency.getInjectionPoint().getMember()), - convert(dependency.getKey())}); - return null; // log & exit. - } - } - } - - int parameterIndex = dependency.getParameterIndex(); - String parameterName = (parameterIndex != -1) - ? "parameter " + parameterIndex + " of " - : ""; - addMessage("null returned by binding at %s%n but %s%s is not @Nullable", - source, parameterName, dependency.getInjectionPoint().getMember()); - - throw toException(); - } - - /** - * Returns the cause throwable if there is exactly one cause in {@code messages}. If there are - * zero or multiple messages with causes, null is returned. - */ - public static Throwable getOnlyCause(Collection messages) { - Throwable onlyCause = null; - for (Message message : messages) { - Throwable messageCause = message.getCause(); - if (messageCause == null) { - continue; - } - - if (onlyCause != null) { - return null; - } - - onlyCause = messageCause; - } - - return onlyCause; - } - public int size() { return root.errors == null ? 0 : root.errors.size(); } - private static abstract class Converter { - - final Class type; - - Converter(Class type) { - this.type = type; - } - - boolean appliesTo(Object o) { - return o != null && type.isAssignableFrom(o.getClass()); - } - - String convert(Object o) { - return toString(type.cast(o)); - } - - abstract String toString(T t); - } - - private static final Collection> converters = ImmutableList.of( - new Converter(Class.class) { - @Override public String toString(Class c) { - return c.getName(); - } - }, - new Converter(Member.class) { - @Override public String toString(Member member) { - return Classes.toString(member); - } - }, - new Converter(Key.class) { - @Override public String toString(Key key) { - if (key.getAnnotationType() != null) { - return key.getTypeLiteral() + " annotated with " - + (key.getAnnotation() != null ? key.getAnnotation() : key.getAnnotationType()); - } else { - return key.getTypeLiteral().toString(); - } - } - }); - + // TODO(lukes): inline in callers. There are some callers outside of guice, so this is difficult public static Object convert(Object o) { - ElementSource source = null; - if (o instanceof ElementSource) { - source = (ElementSource)o; - o = source.getDeclaringSource(); - } - return convert(o, source); + return Messages.convert(o); } + // TODO(lukes): inline in callers. There are some callers outside of guice, so this is difficult public static Object convert(Object o, ElementSource source) { - for (Converter converter : converters) { - if (converter.appliesTo(o)) { - return appendModules(converter.convert(o), source); - } - } - return appendModules(o, source); - } - - private static Object appendModules(Object source, ElementSource elementSource) { - String modules = moduleSourceString(elementSource); - if (modules.length() == 0) { - return source; - } else { - return source + modules; - } - } - - private static String moduleSourceString(ElementSource elementSource) { - // if we only have one module (or don't know what they are), then don't bother - // reporting it, because the source already is going to report exactly that module. - if (elementSource == null) { - return ""; - } - List modules = Lists.newArrayList(elementSource.getModuleClassNames()); - // Insert any original element sources w/ module info into the path. - while(elementSource.getOriginalElementSource() != null) { - elementSource = elementSource.getOriginalElementSource(); - modules.addAll(0, elementSource.getModuleClassNames()); - } - if (modules.size() <= 1) { - return ""; - } - - // Ideally we'd do: - // return Joiner.on(" -> ") - // .appendTo(new StringBuilder(" (via modules: "), Lists.reverse(modules)) - // .append(")").toString(); - // ... but for some reason we can't find Lists.reverse, so do it the boring way. - StringBuilder builder = new StringBuilder(" (via modules: "); - for (int i = modules.size() - 1; i >= 0; i--) { - builder.append(modules.get(i)); - if (i != 0) { - builder.append(" -> "); - } - } - builder.append(")"); - return builder.toString(); + return Messages.convert(o, source); } + // TODO(lukes): inline in callers. There are some callers outside of guice, so this is difficult public static void formatSource(Formatter formatter, Object source) { - ElementSource elementSource = null; - if (source instanceof ElementSource) { - elementSource = (ElementSource)source; - source = elementSource.getDeclaringSource(); - } - formatSource(formatter, source, elementSource); + Messages.formatSource(formatter, source); } - public static void formatSource(Formatter formatter, Object source, ElementSource elementSource) { - String modules = moduleSourceString(elementSource); - if (source instanceof Dependency) { - Dependency dependency = (Dependency) source; - InjectionPoint injectionPoint = dependency.getInjectionPoint(); - if (injectionPoint != null) { - formatInjectionPoint(formatter, dependency, injectionPoint, elementSource); - } else { - formatSource(formatter, dependency.getKey(), elementSource); - } - - } else if (source instanceof InjectionPoint) { - formatInjectionPoint(formatter, null, (InjectionPoint) source, elementSource); - - } else if (source instanceof Class) { - formatter.format(" at %s%s%n", StackTraceElements.forType((Class) source), modules); - - } else if (source instanceof Member) { - formatter.format(" at %s%s%n", StackTraceElements.forMember((Member) source), modules); - - } else if (source instanceof TypeLiteral) { - formatter.format(" while locating %s%s%n", source, modules); - - } else if (source instanceof Key) { - Key key = (Key) source; - formatter.format(" while locating %s%n", convert(key, elementSource)); - - } else if (source instanceof Thread) { - formatter.format(" in thread %s%n", source); - - } else { - formatter.format(" at %s%s%n", source, modules); - } - } - - public static void formatInjectionPoint(Formatter formatter, Dependency dependency, - InjectionPoint injectionPoint, ElementSource elementSource) { - Member member = injectionPoint.getMember(); - Class memberType = Classes.memberType(member); - - if (memberType == Field.class) { - dependency = injectionPoint.getDependencies().get(0); - formatter.format(" while locating %s%n", convert(dependency.getKey(), elementSource)); - formatter.format(" for field at %s%n", StackTraceElements.forMember(member)); - - } else if (dependency != null) { - formatter.format(" while locating %s%n", convert(dependency.getKey(), elementSource)); - formatter.format(" for parameter %s at %s%n", - dependency.getParameterIndex(), StackTraceElements.forMember(member)); - - } else { - formatSource(formatter, injectionPoint.getMember()); - } - } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Exceptions.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Exceptions.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Exceptions.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Exceptions.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -/** - * Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.internal; - - -/** - * Rethrows user-code exceptions in wrapped exceptions so that Errors can target the correct - * exception. - * - * @author sameb@google.com (Sam Berlin) - */ -class Exceptions { - - /** - * Rethrows the exception (or it's cause, if it has one) directly if possible. - * If it was a checked exception, this wraps the exception in a stack trace - * with no frames, so that the exception is shown immediately with no frames - * above it. - */ - public static RuntimeException rethrowCause(Throwable throwable) { - Throwable cause = throwable; - if(cause.getCause() != null) { - cause = cause.getCause(); - } - return rethrow(cause); - } - - /** Rethrows the exception. */ - public static RuntimeException rethrow(Throwable throwable) { - if(throwable instanceof RuntimeException) { - throw (RuntimeException)throwable; - } else if(throwable instanceof Error) { - throw (Error)throwable; - } else { - throw new UnhandledCheckedUserException(throwable); - } - } - - /** - * A marker exception class that we look for in order to unwrap the exception - * into the user exception, to provide a cleaner stack trace. - */ - static class UnhandledCheckedUserException extends RuntimeException { - public UnhandledCheckedUserException(Throwable cause) { - super(cause); - } - } -} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ExposedBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ExposedBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ExposedBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ExposedBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ package com.google.inject.internal; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; import com.google.inject.Injector; @@ -25,43 +25,51 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.PrivateElements; - import java.util.Set; public final class ExposedBindingImpl extends BindingImpl implements ExposedBinding { private final PrivateElements privateElements; - public ExposedBindingImpl(InjectorImpl injector, Object source, Key key, - InternalFactory factory, PrivateElements privateElements) { + public ExposedBindingImpl( + InjectorImpl injector, + Object source, + Key key, + InternalFactory factory, + PrivateElements privateElements) { super(injector, key, source, factory, Scoping.UNSCOPED); this.privateElements = privateElements; } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); } + @Override public PrivateElements getPrivateElements() { return privateElements; } - @Override public String toString() { - return Objects.toStringHelper(ExposedBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(ExposedBinding.class) .add("key", getKey()) .add("source", getSource()) .add("privateElements", privateElements) .toString(); } + @Override public void applyTo(Binder binder) { throw new UnsupportedOperationException("This element represents a synthetic binding."); } - + // Purposely does not override equals/hashcode, because exposed bindings are only equal to // themselves right now -- that is, there cannot be "duplicate" exposed bindings. } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ExposedKeyFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ExposedKeyFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ExposedKeyFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ExposedKeyFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +34,7 @@ this.privateElements = privateElements; } + @Override public void notify(Errors errors) { InjectorImpl privateInjector = (InjectorImpl) privateElements.getInjector(); BindingImpl explicitBinding = privateInjector.state.getExplicitBinding(key); @@ -49,8 +50,10 @@ this.delegate = explicitBinding; } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - return delegate.getInternalFactory().get(errors, context, dependency, linked); + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + // TODO(lukes): add a source to the thrown exception? + return delegate.getInternalFactory().get(context, dependency, linked); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ExposureBuilder.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ExposureBuilder.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ExposureBuilder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ExposureBuilder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,12 +20,9 @@ import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.binder.AnnotatedElementBuilder; - import java.lang.annotation.Annotation; -/** - * For private binder's expose() method. - */ +/** For private binder's expose() method. */ public class ExposureBuilder implements AnnotatedElementBuilder { private final Binder binder; private final Object source; @@ -43,12 +40,14 @@ } } + @Override public void annotatedWith(Class annotationType) { Preconditions.checkNotNull(annotationType, "annotationType"); checkNotAnnotated(); key = Key.get(key.getTypeLiteral(), annotationType); } + @Override public void annotatedWith(Annotation annotation) { Preconditions.checkNotNull(annotation, "annotation"); checkNotAnnotated(); @@ -63,7 +62,8 @@ return source; } - @Override public String toString() { + @Override + public String toString() { return "AnnotatedElementBuilder"; } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/FactoryProxy.java sisu-guice-4.2.0/core/src/com/google/inject/internal/FactoryProxy.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/FactoryProxy.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/FactoryProxy.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,14 +16,14 @@ package com.google.inject.internal; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.inject.Key; import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.spi.Dependency; /** - * A placeholder which enables us to swap in the real factory once the injector is created. - * Used for a linked binding, so that getting the linked binding returns the link's factory. + * A placeholder which enables us to swap in the real factory once the injector is created. Used for + * a linked binding, so that getting the linked binding returns the link's factory. */ final class FactoryProxy implements InternalFactory, CreationListener { @@ -41,26 +41,36 @@ this.source = source; } + @Override public void notify(final Errors errors) { try { - targetFactory = injector.getInternalFactory(targetKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); + targetFactory = + injector.getInternalFactory( + targetKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - context.pushState(targetKey, source); + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + Key localTargetKey = targetKey; + context.pushState(localTargetKey, source); + try { - return targetFactory.get(errors.withSource(targetKey), context, dependency, true); - } finally { - context.popState(); + return targetFactory.get(context, dependency, true); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(localTargetKey); + } finally { + context.popState(); + } } - @Override public String toString() { - return Objects.toStringHelper(FactoryProxy.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(FactoryProxy.class) .add("key", key) .add("provider", targetFactory) .toString(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/FailableCache.java sisu-guice-4.2.0/core/src/com/google/inject/internal/FailableCache.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/FailableCache.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/FailableCache.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,23 +27,26 @@ * @author jessewilson@google.com (Jesse Wilson) */ public abstract class FailableCache { - - private final LoadingCache delegate = CacheBuilder.newBuilder().build( - new CacheLoader() { - public Object load(K key) { - Errors errors = new Errors(); - V result = null; - try { - result = FailableCache.this.create(key, errors); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); - } - return errors.hasErrors() ? errors : result; - } - }); + + private final LoadingCache delegate = + CacheBuilder.newBuilder() + .build( + new CacheLoader() { + @Override + public Object load(K key) { + Errors errors = new Errors(); + V result = null; + try { + result = FailableCache.this.create(key, errors); + } catch (ErrorsException e) { + errors.merge(e.getErrors()); + } + return errors.hasErrors() ? errors : result; + } + }); protected abstract V create(K key, Errors errors) throws ErrorsException; - + public V get(K key, Errors errors) throws ErrorsException { Object resultOrError = delegate.getUnchecked(key); if (resultOrError instanceof Errors) { @@ -55,7 +58,7 @@ return result; } } - + boolean remove(K key) { return delegate.asMap().remove(key) != null; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Indexer.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Indexer.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Indexer.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Indexer.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import com.google.common.base.Objects; +import com.google.inject.Binding; +import com.google.inject.Injector; +import com.google.inject.Scope; +import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; +import com.google.inject.spi.BindingScopingVisitor; +import com.google.inject.spi.ConstructorBinding; +import com.google.inject.spi.ConvertedConstantBinding; +import com.google.inject.spi.DefaultBindingTargetVisitor; +import com.google.inject.spi.ExposedBinding; +import com.google.inject.spi.InstanceBinding; +import com.google.inject.spi.LinkedKeyBinding; +import com.google.inject.spi.ProviderBinding; +import com.google.inject.spi.ProviderInstanceBinding; +import com.google.inject.spi.ProviderKeyBinding; +import com.google.inject.spi.UntargettedBinding; +import java.lang.annotation.Annotation; + +/** + * Visits bindings to return a {@code IndexedBinding} that can be used to emulate the binding + * deduplication that Guice internally performs. + * + *

    Note: simply using equals/hashCode on the BindingImpls doesn't work because they all have + * unique annotations. This works around that by reimplementing equality semantics that ignores + * {@link Element#uniqueId()}. A better solution might be to introduce the idea of an 'anonymous' + * binding to guice, that might support this usecase directly. + */ +class Indexer extends DefaultBindingTargetVisitor + implements BindingScopingVisitor { + enum BindingType { + INSTANCE, + PROVIDER_INSTANCE, + PROVIDER_KEY, + LINKED_KEY, + UNTARGETTED, + CONSTRUCTOR, + CONSTANT, + EXPOSED, + PROVIDED_BY, + } + + static class IndexedBinding { + final String annotationName; + final Element.Type annotationType; + final TypeLiteral typeLiteral; + final Object scope; + final BindingType type; + final Object extraEquality; + + IndexedBinding(Binding binding, BindingType type, Object scope, Object extraEquality) { + this.scope = scope; + this.type = type; + this.extraEquality = extraEquality; + this.typeLiteral = binding.getKey().getTypeLiteral(); + Element annotation = (Element) binding.getKey().getAnnotation(); + this.annotationName = annotation.setName(); + this.annotationType = annotation.type(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IndexedBinding)) { + return false; + } + IndexedBinding o = (IndexedBinding) obj; + return type == o.type + && Objects.equal(scope, o.scope) + && typeLiteral.equals(o.typeLiteral) + && annotationType == o.annotationType + && annotationName.equals(o.annotationName) + && Objects.equal(extraEquality, o.extraEquality); + } + + @Override + public int hashCode() { + return Objects.hashCode( + type, scope, typeLiteral, annotationType, annotationName, extraEquality); + } + } + + final Injector injector; + + Indexer(Injector injector) { + this.injector = injector; + } + + boolean isIndexable(Binding binding) { + return binding.getKey().getAnnotation() instanceof Element; + } + + private Object scope(Binding binding) { + return binding.acceptScopingVisitor(this); + } + + @Override + public Indexer.IndexedBinding visit(ConstructorBinding binding) { + return new Indexer.IndexedBinding( + binding, BindingType.CONSTRUCTOR, scope(binding), binding.getConstructor()); + } + + @Override + public Indexer.IndexedBinding visit(ConvertedConstantBinding binding) { + return new Indexer.IndexedBinding( + binding, BindingType.CONSTANT, scope(binding), binding.getValue()); + } + + @Override + public Indexer.IndexedBinding visit(ExposedBinding binding) { + return new Indexer.IndexedBinding(binding, BindingType.EXPOSED, scope(binding), binding); + } + + @Override + public Indexer.IndexedBinding visit(InstanceBinding binding) { + return new Indexer.IndexedBinding( + binding, BindingType.INSTANCE, scope(binding), binding.getInstance()); + } + + @Override + public Indexer.IndexedBinding visit(LinkedKeyBinding binding) { + return new Indexer.IndexedBinding( + binding, BindingType.LINKED_KEY, scope(binding), binding.getLinkedKey()); + } + + @Override + public Indexer.IndexedBinding visit(ProviderBinding binding) { + return new Indexer.IndexedBinding( + binding, + BindingType.PROVIDED_BY, + scope(binding), + injector.getBinding(binding.getProvidedKey())); + } + + @Override + public Indexer.IndexedBinding visit(ProviderInstanceBinding binding) { + return new Indexer.IndexedBinding( + binding, BindingType.PROVIDER_INSTANCE, scope(binding), binding.getUserSuppliedProvider()); + } + + @Override + public Indexer.IndexedBinding visit(ProviderKeyBinding binding) { + return new Indexer.IndexedBinding( + binding, BindingType.PROVIDER_KEY, scope(binding), binding.getProviderKey()); + } + + @Override + public Indexer.IndexedBinding visit(UntargettedBinding binding) { + return new Indexer.IndexedBinding(binding, BindingType.UNTARGETTED, scope(binding), null); + } + + private static final Object EAGER_SINGLETON = new Object(); + + @Override + public Object visitEagerSingleton() { + return EAGER_SINGLETON; + } + + @Override + public Object visitNoScoping() { + return Scopes.NO_SCOPE; + } + + @Override + public Object visitScope(Scope scope) { + return scope; + } + + @Override + public Object visitScopeAnnotation(Class scopeAnnotation) { + return scopeAnnotation; + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InheritingState.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InheritingState.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InheritingState.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InheritingState.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,25 +31,21 @@ import com.google.inject.spi.ScopeBinding; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; - import java.lang.annotation.Annotation; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ final class InheritingState implements State { private final State parent; // Must be a linked hashmap in order to preserve order of bindings in Modules. private final Map, Binding> explicitBindingsMutable = Maps.newLinkedHashMap(); - private final Map, Binding> explicitBindings - = Collections.unmodifiableMap(explicitBindingsMutable); + private final Map, Binding> explicitBindings = + Collections.unmodifiableMap(explicitBindingsMutable); private final Map, ScopeBinding> scopes = Maps.newHashMap(); private final List converters = Lists.newArrayList(); /*if[AOP]*/ @@ -67,41 +63,50 @@ this.blacklistedKeys = new WeakKeySet(lock); } + @Override public State parent() { return parent; } + @Override @SuppressWarnings("unchecked") // we only put in BindingImpls that match their key types public BindingImpl getExplicitBinding(Key key) { Binding binding = explicitBindings.get(key); return binding != null ? (BindingImpl) binding : parent.getExplicitBinding(key); } + @Override public Map, Binding> getExplicitBindingsThisLevel() { return explicitBindings; } + @Override public void putBinding(Key key, BindingImpl binding) { explicitBindingsMutable.put(key, binding); } + @Override public ScopeBinding getScopeBinding(Class annotationType) { ScopeBinding scopeBinding = scopes.get(annotationType); return scopeBinding != null ? scopeBinding : parent.getScopeBinding(annotationType); } + @Override public void putScopeBinding(Class annotationType, ScopeBinding scope) { scopes.put(annotationType, scope); } + @Override public Iterable getConvertersThisLevel() { return converters; } + @Override public void addConverter(TypeConverterBinding typeConverterBinding) { converters.add(typeConverterBinding); } + @Override public TypeConverterBinding getConverter( String stringValue, TypeLiteral type, Errors errors, Object source) { TypeConverterBinding matchingConverter = null; @@ -119,10 +124,12 @@ } /*if[AOP]*/ + @Override public void addMethodAspect(MethodAspect methodAspect) { methodAspects.add(methodAspect); } + @Override public ImmutableList getMethodAspects() { return new ImmutableList.Builder() .addAll(parent.getMethodAspects()) @@ -131,10 +138,12 @@ } /*end[AOP]*/ + @Override public void addTypeListener(TypeListenerBinding listenerBinding) { typeListenerBindings.add(listenerBinding); } + @Override public List getTypeListenerBindings() { List parentBindings = parent.getTypeListenerBindings(); List result = @@ -143,11 +152,13 @@ result.addAll(typeListenerBindings); return result; } - + + @Override public void addProvisionListener(ProvisionListenerBinding listenerBinding) { provisionListenerBindings.add(listenerBinding); } + @Override public List getProvisionListenerBindings() { List parentBindings = parent.getProvisionListenerBindings(); List result = @@ -157,10 +168,12 @@ return result; } + @Override public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) { scannerBindings.add(scanner); } + @Override public List getScannerBindings() { List parentBindings = parent.getScannerBindings(); List result = @@ -170,23 +183,28 @@ return result; } + @Override public void blacklist(Key key, State state, Object source) { parent.blacklist(key, state, source); blacklistedKeys.add(key, state, source); } + @Override public boolean isBlacklisted(Key key) { return blacklistedKeys.contains(key); } - + + @Override public Set getSourcesForBlacklistedKey(Key key) { return blacklistedKeys.getSources(key); } + @Override public Object lock() { return lock; } + @Override public Map, Scope> getScopes() { ImmutableMap.Builder, Scope> builder = ImmutableMap.builder(); for (Map.Entry, ScopeBinding> entry : scopes.entrySet()) { diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Initializable.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Initializable.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Initializable.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Initializable.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,8 +23,6 @@ */ interface Initializable { - /** - * Ensures the reference is initialized, then returns it. - */ - T get(Errors errors) throws ErrorsException; + /** Ensures the reference is initialized, then returns it. */ + T get() throws InternalProvisionException; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Initializables.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Initializables.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Initializables.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Initializables.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,21 +16,19 @@ package com.google.inject.internal; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ final class Initializables { - /** - * Returns an initializable for an instance that requires no initialization. - */ + /** Returns an initializable for an instance that requires no initialization. */ static Initializable of(final T instance) { return new Initializable() { - public T get(Errors errors) throws ErrorsException { + @Override + public T get() { return instance; } - @Override public String toString() { + @Override + public String toString() { return String.valueOf(instance); } }; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Initializer.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Initializer.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Initializer.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Initializer.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,15 +21,16 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Stage; import com.google.inject.TypeLiteral; +import com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory; import com.google.inject.spi.InjectionPoint; - -import java.util.Map; +import java.util.IdentityHashMap; +import java.util.List; import java.util.Set; -import java.util.concurrent.CountDownLatch; /** * Manages and injects instances at injector-creation time. This is made more complicated by @@ -39,46 +40,76 @@ * @author jessewilson@google.com (Jesse Wilson) */ final class Initializer { - - /** the only thread that we'll use to inject members. */ - private final Thread creatingThread = Thread.currentThread(); - - /** zero means everything is injected. */ - private final CountDownLatch ready = new CountDownLatch(1); - - /** Maps from instances that need injection to the MembersInjector that will inject them. */ - private final Map> pendingMembersInjectors = - Maps.newIdentityHashMap(); - /** Maps instances that need injection to a source that registered them */ - private final Map> pendingInjection = Maps.newIdentityHashMap(); + /** Is set to true once {@link #validateOustandingInjections} is called. */ + private volatile boolean validationStarted = false; + + /** + * Allows us to detect circular dependencies. It's only used during injectable reference + * initialization. After initialization direct access through volatile field is used. + */ + private final CycleDetectingLockFactory> cycleDetectingLockFactory = + new CycleDetectingLockFactory>(); + + /** + * Instances that need injection during injector creation to a source that registered them. New + * references added before {@link #validateOustandingInjections}. Cleared up in {@link + * #injectAll}. + */ + private final List> pendingInjections = Lists.newArrayList(); + + /** + * Map that guarantees that no instance would get two references. New references added before + * {@link #validateOustandingInjections}. Cleared up in {@link #validateOustandingInjections}. + */ + private final IdentityHashMap> initializablesCache = + Maps.newIdentityHashMap(); /** * Registers an instance for member injection when that step is performed. * - * @param instance an instance that optionally has members to be injected (each annotated with - * @Inject). + * @param instance an instance that optionally has members to be injected (each annotated + * with @Inject). * @param binding the binding that caused this initializable to be created, if it exists. * @param source the source location that this injection was requested */ - Initializable requestInjection(InjectorImpl injector, T instance, Binding binding, - Object source, Set injectionPoints) { + Initializable requestInjection( + InjectorImpl injector, + T instance, + Binding binding, + Object source, + Set injectionPoints) { checkNotNull(source); - + Preconditions.checkState( + !validationStarted, "Member injection could not be requested after validation is started"); ProvisionListenerStackCallback provisionCallback = binding == null ? null : injector.provisionListenerStore.get(binding); // short circuit if the object has no injections or listeners. - if (instance == null || (injectionPoints.isEmpty() - && !injector.membersInjectorStore.hasTypeListeners() - && (provisionCallback == null || !provisionCallback.hasListeners()))) { + if (instance == null + || (injectionPoints.isEmpty() + && !injector.membersInjectorStore.hasTypeListeners() + && provisionCallback == null)) { return Initializables.of(instance); } - InjectableReference initializable = new InjectableReference( - injector, instance, binding == null ? null : binding.getKey(), provisionCallback, source); - pendingInjection.put(instance, initializable); - return initializable; + if (initializablesCache.containsKey(instance)) { + @SuppressWarnings("unchecked") // Map from T to InjectableReference + Initializable cached = (Initializable) initializablesCache.get(instance); + return cached; + } + + InjectableReference injectableReference = + new InjectableReference( + injector, + instance, + binding == null ? null : binding.getKey(), + provisionCallback, + source, + cycleDetectingLockFactory.create(instance.getClass())); + initializablesCache.put(instance, injectableReference); + pendingInjections.add(injectableReference); + return injectableReference; } /** @@ -86,9 +117,11 @@ * on the injected instances. */ void validateOustandingInjections(Errors errors) { - for (InjectableReference reference : pendingInjection.values()) { + validationStarted = true; + initializablesCache.clear(); + for (InjectableReference reference : pendingInjections) { try { - pendingMembersInjectors.put(reference.instance, reference.validate(errors)); + reference.validate(errors); } catch (ErrorsException e) { errors.merge(e.getErrors()); } @@ -101,88 +134,130 @@ * instances are codependent (directly or transitively), ordering of injection is arbitrary. */ void injectAll(final Errors errors) { - // loop over a defensive copy since ensureInjected() mutates the set. Unfortunately, that copy - // is made complicated by a bug in IBM's JDK, wherein entrySet().toArray(Object[]) doesn't work - for (InjectableReference reference : Lists.newArrayList(pendingInjection.values())) { + Preconditions.checkState(validationStarted, "Validation should be done before injection"); + for (InjectableReference reference : pendingInjections) { try { - reference.get(errors); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); + reference.get(); + } catch (InternalProvisionException ipe) { + errors.merge(ipe); } } + pendingInjections.clear(); + } - if (!pendingInjection.isEmpty()) { - throw new AssertionError("Failed to satisfy " + pendingInjection); - } - - ready.countDown(); + private enum InjectableReferenceState { + NEW, + VALIDATED, + INJECTING, + READY } - private class InjectableReference implements Initializable { + private static class InjectableReference implements Initializable { + private volatile InjectableReferenceState state = InjectableReferenceState.NEW; + private volatile MembersInjectorImpl membersInjector = null; + private final InjectorImpl injector; private final T instance; private final Object source; private final Key key; private final ProvisionListenerStackCallback provisionCallback; + private final CycleDetectingLock lock; - public InjectableReference(InjectorImpl injector, T instance, Key key, - ProvisionListenerStackCallback provisionCallback, Object source) { + public InjectableReference( + InjectorImpl injector, + T instance, + Key key, + ProvisionListenerStackCallback provisionCallback, + Object source, + CycleDetectingLock lock) { this.injector = injector; this.key = key; // possibly null! this.provisionCallback = provisionCallback; // possibly null! this.instance = checkNotNull(instance, "instance"); this.source = checkNotNull(source, "source"); + this.lock = checkNotNull(lock, "lock"); } - public MembersInjectorImpl validate(Errors errors) throws ErrorsException { + public void validate(Errors errors) throws ErrorsException { @SuppressWarnings("unchecked") // the type of 'T' is a TypeLiteral - TypeLiteral type = TypeLiteral.get((Class) instance.getClass()); - return injector.membersInjectorStore.get(type, errors.withSource(source)); + TypeLiteral type = TypeLiteral.get((Class) instance.getClass()); + membersInjector = injector.membersInjectorStore.get(type, errors.withSource(source)); + Preconditions.checkNotNull( + membersInjector, + "No membersInjector available for instance: %s, from key: %s", + instance, + key); + state = InjectableReferenceState.VALIDATED; } /** * Reentrant. If {@code instance} was registered for injection at injector-creation time, this * method will ensure that all its members have been injected before returning. */ - public T get(Errors errors) throws ErrorsException { - if (ready.getCount() == 0) { + @Override + public T get() throws InternalProvisionException { + // skipping acquiring lock if initialization is already finished + if (state == InjectableReferenceState.READY) { return instance; } - // just wait for everything to be injected by another thread - if (Thread.currentThread() != creatingThread) { - try { - ready.await(); - return instance; - } catch (InterruptedException e) { - // Give up, since we don't know if our injection is ready - throw new RuntimeException(e); - } + // acquire lock for current binding to initialize an instance + Multimap lockCycle = lock.lockOrDetectPotentialLocksCycle(); + if (!lockCycle.isEmpty()) { + // Potential deadlock detected and creation lock is not taken. + // According to injectAll()'s contract return non-initialized instance. + + // This condition should not be possible under the current Guice implementation. + // This clause exists for defensive programming purposes. + + // Reasoning: + // get() is called either directly from injectAll(), holds no locks and can not create + // a cycle, or it is called through a singleton scope, which resolves deadlocks by itself. + // Before calling get() object has to be requested for injection. + // Initializer.requestInjection() is called either for constant object bindings, which wrap + // creation into a Singleton scope, or from Binder.requestInjection(), which + // has to use Singleton scope to reuse the same InjectableReference to potentially + // create a lock cycle. + return instance; } + try { + // lock acquired, current thread owns this instance initialization + switch (state) { + case READY: + return instance; + // When instance depends on itself in the same thread potential dead lock + // is not detected. We have to prevent a stack overflow and we use + // an "injecting" stage to short-circuit a call. + case INJECTING: + return instance; + case VALIDATED: + state = InjectableReferenceState.INJECTING; + break; + case NEW: + throw new IllegalStateException("InjectableReference is not validated yet"); + default: + throw new IllegalStateException("Unknown state: " + state); + } - // toInject needs injection, do it right away. we only do this once, even if it fails - if (pendingInjection.remove(instance) != null) { - // safe because we only insert a members injector for the appropriate instance - @SuppressWarnings("unchecked") - MembersInjectorImpl membersInjector = - (MembersInjectorImpl)pendingMembersInjectors.remove(instance); - Preconditions.checkState(membersInjector != null, - "No membersInjector available for instance: %s, from key: %s", instance, key); - // if in Stage.TOOL, we only want to inject & notify toolable injection points. // (otherwise we'll inject all of them) - membersInjector.injectAndNotify(instance, - errors.withSource(source), - key, - provisionCallback, - source, - injector.options.stage == Stage.TOOL); + try { + membersInjector.injectAndNotify( + instance, key, provisionCallback, source, injector.options.stage == Stage.TOOL); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(source); + } + // mark instance as ready to skip a lock on subsequent calls + state = InjectableReferenceState.READY; + return instance; + } finally { + // always release our creation lock, even on failures + lock.unlock(); } - - return instance; } - @Override public String toString() { + @Override + public String toString() { return instance.toString(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectionRequestProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectionRequestProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectionRequestProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectionRequestProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InjectionRequest; import com.google.inject.spi.StaticInjectionRequest; - import java.util.List; import java.util.Set; @@ -44,12 +43,14 @@ this.initializer = initializer; } - @Override public Boolean visit(StaticInjectionRequest request) { + @Override + public Boolean visit(StaticInjectionRequest request) { staticInjections.add(new StaticInjection(injector, request)); return true; } - @Override public Boolean visit(InjectionRequest request) { + @Override + public Boolean visit(InjectionRequest request) { Set injectionPoints; try { injectionPoints = request.getInjectionPoints(); @@ -103,31 +104,32 @@ injectionPoints = e.getPartialValue(); } if (injectionPoints != null) { - memberInjectors = injector.membersInjectorStore.getInjectors( - injectionPoints, errorsForMember); + memberInjectors = + injector.membersInjectorStore.getInjectors(injectionPoints, errorsForMember); } else { memberInjectors = ImmutableList.of(); } - + errors.merge(errorsForMember); } void injectMembers() { + InternalContext context = injector.enterContext(); try { - injector.callInContext(new ContextualCallable() { - public Void call(InternalContext context) { - for (SingleMemberInjector memberInjector : memberInjectors) { - // Run injections if we're not in tool stage (ie, PRODUCTION or DEV), - // or if we are in tool stage and the injection point is toolable. - if(injector.options.stage != Stage.TOOL || memberInjector.getInjectionPoint().isToolable()) { - memberInjector.inject(errors, context, null); - } + boolean isStageTool = injector.options.stage == Stage.TOOL; + for (SingleMemberInjector memberInjector : memberInjectors) { + // Run injections if we're not in tool stage (ie, PRODUCTION or DEV), + // or if we are in tool stage and the injection point is toolable. + if (!isStageTool || memberInjector.getInjectionPoint().isToolable()) { + try { + memberInjector.inject(context, null); + } catch (InternalProvisionException e) { + errors.merge(e); } - return null; } - }); - } catch (ErrorsException e) { - throw new AssertionError(); + } + } finally { + context.close(); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectorImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectorImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectorImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectorImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,11 +16,13 @@ package com.google.inject.internal; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; +import com.google.common.collect.ListMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.inject.Binder; @@ -33,7 +35,6 @@ import com.google.inject.Module; import com.google.inject.ProvidedBy; import com.google.inject.Provider; -import com.google.inject.ProvisionException; import com.google.inject.Scope; import com.google.inject.Stage; import com.google.inject.TypeLiteral; @@ -43,10 +44,10 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.util.Providers; - import java.lang.annotation.Annotation; import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; @@ -57,7 +58,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentMap; /** * Default {@link Injector} implementation. @@ -75,8 +75,12 @@ final boolean atInjectRequired; final boolean exactBindingAnnotationsRequired; - InjectorOptions(Stage stage, boolean jitDisabled, boolean disableCircularProxies, - boolean atInjectRequired, boolean exactBindingAnnotationsRequired) { + InjectorOptions( + Stage stage, + boolean jitDisabled, + boolean disableCircularProxies, + boolean atInjectRequired, + boolean exactBindingAnnotationsRequired) { this.stage = stage; this.jitDisabled = jitDisabled; this.disableCircularProxies = disableCircularProxies; @@ -86,7 +90,7 @@ @Override public String toString() { - return Objects.toStringHelper(getClass()) + return MoreObjects.toStringHelper(getClass()) .add("stage", stage) .add("jitDisabled", jitDisabled) .add("disableCircularProxies", disableCircularProxies) @@ -108,14 +112,14 @@ final State state; final InjectorImpl parent; - final BindingsMultimap bindingsMultimap = new BindingsMultimap(); + final ListMultimap, Binding> bindingsMultimap = ArrayListMultimap.create(); final InjectorOptions options; /** Just-in-time binding cache. Guarded by state.lock() */ final Map, BindingImpl> jitBindings = Maps.newHashMap(); /** - * Cache of Keys that we were unable to create JIT bindings for, so we don't - * keep trying. Also guarded by state.lock(). + * Cache of Keys that we were unable to create JIT bindings for, so we don't keep trying. Also + * guarded by state.lock(). */ final Set> failedJitBindings = Sets.newHashSet(); @@ -129,26 +133,29 @@ if (parent != null) { localContext = parent.localContext; } else { - localContext = new ThreadLocal(); + // No ThreadLocal.initialValue(), as that would cause classloader leaks. See + // https://github.com/google/guice/issues/288#issuecomment-48216933, + // https://github.com/google/guice/issues/288#issuecomment-48216944 + localContext = new ThreadLocal<>(); } } /** Indexes bindings by type. */ void index() { for (Binding binding : state.getExplicitBindingsThisLevel().values()) { - index(binding); + bindingsMultimap.put(binding.getKey().getTypeLiteral(), binding); } } - void index(Binding binding) { - bindingsMultimap.put(binding.getKey().getTypeLiteral(), binding); - } - + @Override public List> findBindingsByType(TypeLiteral type) { - return bindingsMultimap.getAll(type); + @SuppressWarnings("unchecked") // safe because we only put matching entries into the map + List> list = (List>) (List) bindingsMultimap.get(type); + return Collections.unmodifiableList(list); } /** Returns the binding for {@code key} */ + @Override public BindingImpl getBinding(Key key) { Errors errors = new Errors(key); try { @@ -160,6 +167,7 @@ } } + @Override public BindingImpl getExistingBinding(Key key) { // Check explicit bindings, i.e. bindings created by modules. BindingImpl explicitBinding = state.getExplicitBinding(key); @@ -171,7 +179,7 @@ for (InjectorImpl injector = this; injector != null; injector = injector.parent) { @SuppressWarnings("unchecked") BindingImpl jitBinding = (BindingImpl) injector.jitBindings.get(key); - if(jitBinding != null) { + if (jitBinding != null) { return jitBinding; } } @@ -179,15 +187,15 @@ // If Key is a Provider, we have to see if the type it is providing exists, // and, if so, we have to create the binding for the provider. - if(isProvider(key)) { + if (isProvider(key)) { try { // This is safe because isProvider above ensures that T is a Provider @SuppressWarnings({"unchecked", "cast"}) - Key providedKey = (Key)getProvidedKey((Key)key, new Errors()); - if(getExistingBinding(providedKey) != null) { + Key providedKey = (Key) getProvidedKey((Key) key, new Errors()); + if (getExistingBinding(providedKey) != null) { return getBinding(key); } - } catch(ErrorsException e) { + } catch (ErrorsException e) { throw new ConfigurationException(e.getErrors().getMessages()); } } @@ -197,8 +205,8 @@ } /** - * Gets a binding implementation. First, it check to see if the parent has a binding. If the - * parent has a binding and the binding is scoped, it will use that binding. Otherwise, this + * Gets a binding implementation. First, it check to see if the parent has a binding. If the + * parent has a binding and the binding is scoped, it will use that binding. Otherwise, this * checks for an explicit binding. If no explicit binding is found, it looks for a just-in-time * binding. */ @@ -214,21 +222,22 @@ return getJustInTimeBinding(key, errors, jitType); } + @Override public Binding getBinding(Class type) { return getBinding(Key.get(type)); } + @Override public Injector getParent() { return parent; } + @Override public Injector createChildInjector(Iterable modules) { - return new InternalInjectorCreator() - .parentInjector(this) - .addModules(modules) - .build(); + return new InternalInjectorCreator().parentInjector(this).addModules(modules).build(); } + @Override public Injector createChildInjector(Module... modules) { return createChildInjector(ImmutableList.copyOf(modules)); } @@ -292,7 +301,8 @@ return key.getTypeLiteral().getRawType().equals(TypeLiteral.class); } - private static Key getProvidedKey(Key> key, Errors errors) throws ErrorsException { + private static Key getProvidedKey(Key> key, Errors errors) + throws ErrorsException { Type providerType = key.getTypeLiteral().getType(); // If the Provider has no type parameter (raw Provider)... @@ -321,21 +331,26 @@ } @SuppressWarnings("unchecked") // safe because T came from Key> - TypeLiteral instanceType = (TypeLiteral) TypeLiteral.get( - ((ParameterizedType) membersInjectorType).getActualTypeArguments()[0]); + TypeLiteral instanceType = + (TypeLiteral) + TypeLiteral.get(((ParameterizedType) membersInjectorType).getActualTypeArguments()[0]); MembersInjector membersInjector = membersInjectorStore.get(instanceType, errors); - InternalFactory> factory = new ConstantFactory>( - Initializables.of(membersInjector)); - + InternalFactory> factory = + new ConstantFactory>(Initializables.of(membersInjector)); - return new InstanceBindingImpl>(this, key, SourceProvider.UNKNOWN_SOURCE, - factory, ImmutableSet.of(), membersInjector); + return new InstanceBindingImpl>( + this, + key, + SourceProvider.UNKNOWN_SOURCE, + factory, + ImmutableSet.of(), + membersInjector); } /** - * Creates a synthetic binding to {@code Provider}, i.e. a binding to the provider from - * {@code Binding}. + * Creates a synthetic binding to {@code Provider}, i.e. a binding to the provider from {@code + * Binding}. */ private BindingImpl> createProviderBinding(Key> key, Errors errors) throws ErrorsException { @@ -349,7 +364,11 @@ final BindingImpl providedBinding; ProviderBindingImpl(InjectorImpl injector, Key> key, Binding providedBinding) { - super(injector, key, providedBinding.getSource(), createInternalFactory(providedBinding), + super( + injector, + key, + providedBinding.getSource(), + createInternalFactory(providedBinding), Scoping.UNSCOPED); this.providedBinding = (BindingImpl) providedBinding; } @@ -357,42 +376,48 @@ static InternalFactory> createInternalFactory(Binding providedBinding) { final Provider provider = providedBinding.getProvider(); return new InternalFactory>() { - public Provider get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { + @Override + public Provider get(InternalContext context, Dependency dependency, boolean linked) { return provider; } }; } + @Override public Key getProvidedKey() { return providedBinding.getKey(); } + @Override public V acceptTargetVisitor(BindingTargetVisitor, V> visitor) { return visitor.visit(this); } + @Override public void applyTo(Binder binder) { throw new UnsupportedOperationException("This element represents a synthetic binding."); } - @Override public String toString() { - return Objects.toStringHelper(ProviderBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(ProviderBinding.class) .add("key", getKey()) .add("providedKey", getProvidedKey()) .toString(); } + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(getProvidedKey())); } @Override public boolean equals(Object obj) { - if(obj instanceof ProviderBindingImpl) { - ProviderBindingImpl o = (ProviderBindingImpl)obj; + if (obj instanceof ProviderBindingImpl) { + ProviderBindingImpl o = (ProviderBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(providedBinding, o.providedBinding); + && getScoping().equals(o.getScoping()) + && Objects.equal(providedBinding, o.providedBinding); } else { return false; } @@ -419,12 +444,17 @@ return null; } - String stringValue = stringBinding.getProvider().get(); + // We can't call getProvider().get() because this InstanceBinding may not have been inintialized + // yet (because we may have been called during InternalInjectorCreator.initializeStatically and + // instance binding validation hasn't happened yet.) + @SuppressWarnings("unchecked") + String stringValue = ((InstanceBinding) stringBinding).getInstance(); Object source = stringBinding.getSource(); // Find a matching type converter. TypeLiteral type = key.getTypeLiteral(); - TypeConverterBinding typeConverterBinding = state.getConverter(stringValue, type, errors, source); + TypeConverterBinding typeConverterBinding = + state.getConverter(stringValue, type, errors, source); if (typeConverterBinding == null) { // No converter can handle the given type. @@ -437,73 +467,91 @@ T converted = (T) typeConverterBinding.getTypeConverter().convert(stringValue, type); if (converted == null) { - throw errors.converterReturnedNull(stringValue, source, type, typeConverterBinding) + throw errors + .converterReturnedNull(stringValue, source, type, typeConverterBinding) .toException(); } if (!type.getRawType().isInstance(converted)) { - throw errors.conversionTypeError(stringValue, source, type, typeConverterBinding, converted) + throw errors + .conversionTypeError(stringValue, source, type, typeConverterBinding, converted) .toException(); } - return new ConvertedConstantBindingImpl(this, key, converted, stringBinding, - typeConverterBinding); + return new ConvertedConstantBindingImpl( + this, key, converted, stringBinding, typeConverterBinding); } catch (ErrorsException e) { throw e; } catch (RuntimeException e) { - throw errors.conversionError(stringValue, source, type, typeConverterBinding, e) + throw errors + .conversionError(stringValue, source, type, typeConverterBinding, e) .toException(); } } - private static class ConvertedConstantBindingImpl - extends BindingImpl implements ConvertedConstantBinding { + private static class ConvertedConstantBindingImpl extends BindingImpl + implements ConvertedConstantBinding { final T value; final Provider provider; final Binding originalBinding; final TypeConverterBinding typeConverterBinding; ConvertedConstantBindingImpl( - InjectorImpl injector, Key key, T value, Binding originalBinding, + InjectorImpl injector, + Key key, + T value, + Binding originalBinding, TypeConverterBinding typeConverterBinding) { - super(injector, key, originalBinding.getSource(), - new ConstantFactory(Initializables.of(value)), Scoping.UNSCOPED); + super( + injector, + key, + originalBinding.getSource(), + new ConstantFactory(Initializables.of(value)), + Scoping.UNSCOPED); this.value = value; provider = Providers.of(value); this.originalBinding = originalBinding; this.typeConverterBinding = typeConverterBinding; } - @Override public Provider getProvider() { + @Override + public Provider getProvider() { return provider; } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } + @Override public T getValue() { return value; } + @Override public TypeConverterBinding getTypeConverterBinding() { return typeConverterBinding; } + @Override public Key getSourceKey() { return originalBinding.getKey(); } + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(getSourceKey())); } + @Override public void applyTo(Binder binder) { throw new UnsupportedOperationException("This element represents a synthetic binding."); } - @Override public String toString() { - return Objects.toStringHelper(ConvertedConstantBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(ConvertedConstantBinding.class) .add("key", getKey()) .add("sourceKey", getSourceKey()) .add("value", value) @@ -512,11 +560,11 @@ @Override public boolean equals(Object obj) { - if(obj instanceof ConvertedConstantBindingImpl) { - ConvertedConstantBindingImpl o = (ConvertedConstantBindingImpl)obj; + if (obj instanceof ConvertedConstantBindingImpl) { + ConvertedConstantBindingImpl o = (ConvertedConstantBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(value, o.value); + && getScoping().equals(o.getScoping()) + && Objects.equal(value, o.value); } else { return false; } @@ -542,7 +590,7 @@ Key key = binding.getKey(); jitBindings.put(key, binding); boolean successful = false; - DelayedInitialize delayed = (DelayedInitialize)binding; + DelayedInitialize delayed = (DelayedInitialize) binding; try { delayed.initialize(this, errors); successful = true; @@ -560,32 +608,32 @@ /** * Iterates through the binding's dependencies to clean up any stray bindings that were leftover - * from a failed JIT binding. This is required because the bindings are eagerly & - * optimistically added to allow circular dependency support, so dependencies may pass where they - * should have failed. + * from a failed JIT binding. This is required because the bindings are eagerly & optimistically + * added to allow circular dependency support, so dependencies may pass where they should have + * failed. */ private boolean cleanup(BindingImpl binding, Set encountered) { boolean bindingFailed = false; Set> deps = getInternalDependencies(binding); - for(Dependency dep : deps) { + for (Dependency dep : deps) { Key depKey = dep.getKey(); InjectionPoint ip = dep.getInjectionPoint(); - if(encountered.add(depKey)) { // only check if we haven't looked at this key yet + if (encountered.add(depKey)) { // only check if we haven't looked at this key yet BindingImpl depBinding = jitBindings.get(depKey); - if(depBinding != null) { // if the binding still exists, validate + if (depBinding != null) { // if the binding still exists, validate boolean failed = cleanup(depBinding, encountered); // if children fail, we fail - if(depBinding instanceof ConstructorBindingImpl) { - ConstructorBindingImpl ctorBinding = (ConstructorBindingImpl)depBinding; + if (depBinding instanceof ConstructorBindingImpl) { + ConstructorBindingImpl ctorBinding = (ConstructorBindingImpl) depBinding; ip = ctorBinding.getInternalConstructor(); - if(!ctorBinding.isInitialized()) { + if (!ctorBinding.isInitialized()) { failed = true; } } - if(failed) { + if (failed) { removeFailedJitBinding(depBinding, ip); bindingFailed = true; } - } else if(state.getExplicitBinding(depKey) == null) { + } else if (state.getExplicitBinding(depKey) == null) { // ignore keys if they were explicitly bound, but if neither JIT // nor explicit, it's also invalid & should let parent know. bindingFailed = true; @@ -601,7 +649,7 @@ jitBindings.remove(binding.getKey()); membersInjectorStore.remove(binding.getKey().getTypeLiteral()); provisionListenerStore.remove(binding); - if(ip != null) { + if (ip != null) { constructors.remove(ip); } } @@ -609,10 +657,10 @@ /** Safely gets the dependencies of possibly not initialized bindings. */ @SuppressWarnings("unchecked") private Set> getInternalDependencies(BindingImpl binding) { - if(binding instanceof ConstructorBindingImpl) { - return ((ConstructorBindingImpl)binding).getInternalDependencies(); - } else if(binding instanceof HasDependencies) { - return ((HasDependencies)binding).getDependencies(); + if (binding instanceof ConstructorBindingImpl) { + return ((ConstructorBindingImpl) binding).getInternalDependencies(); + } else if (binding instanceof HasDependencies) { + return ((HasDependencies) binding).getDependencies(); } else { return ImmutableSet.of(); } @@ -622,22 +670,23 @@ * Creates a binding for an injectable type with the given scope. Looks for a scope on the type if * none is specified. */ - BindingImpl createUninitializedBinding(Key key, Scoping scoping, Object source, - Errors errors, boolean jitBinding) throws ErrorsException { + BindingImpl createUninitializedBinding( + Key key, Scoping scoping, Object source, Errors errors, boolean jitBinding) + throws ErrorsException { Class rawType = key.getTypeLiteral().getRawType(); ImplementedBy implementedBy = rawType.getAnnotation(ImplementedBy.class); // Don't try to inject arrays or enums annotated with @ImplementedBy. if (rawType.isArray() || (rawType.isEnum() && implementedBy != null)) { - throw errors.missingImplementation(key).toException(); + throw errors.missingImplementationWithHint(key, this).toException(); } // Handle TypeLiteral by binding the inner type if (rawType == TypeLiteral.class) { @SuppressWarnings("unchecked") // we have to fudge the inner type as Object - BindingImpl binding = (BindingImpl) createTypeLiteralBinding( - (Key>) key, errors); + BindingImpl binding = + (BindingImpl) createTypeLiteralBinding((Key>) key, errors); return binding; } @@ -654,8 +703,8 @@ return createProvidedByBinding(key, scoping, providedBy, errors); } - - return ConstructorBindingImpl.create(this, + return ConstructorBindingImpl.create( + this, key, null, /* use default constructor */ source, @@ -689,17 +738,22 @@ @SuppressWarnings("unchecked") // by definition, innerType == T, so this is safe TypeLiteral value = (TypeLiteral) TypeLiteral.get(innerType); - InternalFactory> factory = new ConstantFactory>( - Initializables.of(value)); - return new InstanceBindingImpl>(this, key, SourceProvider.UNKNOWN_SOURCE, - factory, ImmutableSet.of(), value); + InternalFactory> factory = + new ConstantFactory>(Initializables.of(value)); + return new InstanceBindingImpl>( + this, + key, + SourceProvider.UNKNOWN_SOURCE, + factory, + ImmutableSet.of(), + value); } /** Creates a binding for a type annotated with @ProvidedBy. */ - BindingImpl createProvidedByBinding(Key key, Scoping scoping, - ProvidedBy providedBy, Errors errors) throws ErrorsException { + BindingImpl createProvidedByBinding( + Key key, Scoping scoping, ProvidedBy providedBy, Errors errors) throws ErrorsException { Class rawType = key.getTypeLiteral().getRawType(); - Class> providerType = providedBy.value(); + Class> providerType = providedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper loops? if (providerType == rawType) { @@ -712,21 +766,22 @@ ProvidedByInternalFactory internalFactory = new ProvidedByInternalFactory(rawType, providerType, providerKey); Object source = rawType; - BindingImpl binding = LinkedProviderBindingImpl.createWithInitializer( - this, - key, - source, - Scoping.scope(key, this, internalFactory, source, scoping), - scoping, - providerKey, - internalFactory); + BindingImpl binding = + LinkedProviderBindingImpl.createWithInitializer( + this, + key, + source, + Scoping.scope(key, this, internalFactory, source, scoping), + scoping, + providerKey, + internalFactory); internalFactory.setProvisionListenerCallback(provisionListenerStore.get(binding)); return binding; } /** Creates a binding for a type annotated with @ImplementedBy. */ - private BindingImpl createImplementedByBinding(Key key, Scoping scoping, - ImplementedBy implementedBy, Errors errors) + private BindingImpl createImplementedByBinding( + Key key, Scoping scoping, ImplementedBy implementedBy, Errors errors) throws ErrorsException { Class rawType = key.getTypeLiteral().getRawType(); Class implementationType = implementedBy.value(); @@ -746,27 +801,14 @@ // Look up the target binding. final Key targetKey = Key.get(subclass); - final BindingImpl targetBinding = getBindingOrThrow(targetKey, errors, JitLimitation.NEW_OR_EXISTING_JIT); - - InternalFactory internalFactory = new InternalFactory() { - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - context.pushState(targetKey, targetBinding.getSource()); - try { - return targetBinding.getInternalFactory().get( - errors.withSource(targetKey), context, dependency, true); - } finally { - context.popState(); - } - } - }; - Object source = rawType; + FactoryProxy factory = new FactoryProxy<>(this, key, targetKey, source); + factory.notify(errors); // causes the factory to initialize itself internally return new LinkedBindingImpl( this, key, source, - Scoping.scope(key, this, internalFactory, source, scoping), + Scoping.scope(key, this, factory, source, scoping), scoping, targetKey); } @@ -775,18 +817,23 @@ * Attempts to create a just-in-time binding for {@code key} in the root injector, falling back to * other ancestor injectors until this injector is tried. */ - private BindingImpl createJustInTimeBindingRecursive(Key key, Errors errors, - boolean jitDisabled, JitLimitation jitType) throws ErrorsException { + private BindingImpl createJustInTimeBindingRecursive( + Key key, Errors errors, boolean jitDisabled, JitLimitation jitType) + throws ErrorsException { // ask the parent to create the JIT binding if (parent != null) { if (jitType == JitLimitation.NEW_OR_EXISTING_JIT - && jitDisabled && !parent.options.jitDisabled) { + && jitDisabled + && !parent.options.jitDisabled) { // If the binding would be forbidden here but allowed in a parent, report an error instead throw errors.jitDisabledInParent(key).toException(); } try { - return parent.createJustInTimeBindingRecursive(key, new Errors(), jitDisabled, + return parent.createJustInTimeBindingRecursive( + key, + new Errors(), + jitDisabled, parent.options.jitDisabled ? JitLimitation.NO_JIT : jitType); } catch (ErrorsException ignored) { } @@ -811,18 +858,20 @@ /** * Returns a new just-in-time binding created by resolving {@code key}. The strategies used to * create just-in-time bindings are: + * *
      - *
    1. Internalizing Providers. If the requested binding is for {@code Provider}, we delegate + *
    2. Internalizing Providers. If the requested binding is for {@code Provider}, we delegate * to the binding for {@code T}. - *
    3. Converting constants. - *
    4. ImplementedBy and ProvidedBy annotations. Only for unannotated keys. - *
    5. The constructor of the raw type. Only for unannotated keys. + *
    6. Converting constants. + *
    7. ImplementedBy and ProvidedBy annotations. Only for unannotated keys. + *
    8. The constructor of the raw type. Only for unannotated keys. *
    * * @throws com.google.inject.internal.ErrorsException if the binding cannot be created. */ - private BindingImpl createJustInTimeBinding(Key key, Errors errors, - boolean jitDisabled, JitLimitation jitType) throws ErrorsException { + private BindingImpl createJustInTimeBinding( + Key key, Errors errors, boolean jitDisabled, JitLimitation jitType) + throws ErrorsException { int numErrorsBefore = errors.size(); // Retrieve the sources before checking for blacklisting to guard against sources becoming null @@ -858,9 +907,7 @@ return convertedBinding; } - if (!isTypeLiteral(key) - && jitDisabled - && jitType != JitLimitation.NEW_OR_EXISTING_JIT) { + if (!isTypeLiteral(key) && jitDisabled && jitType != JitLimitation.NEW_OR_EXISTING_JIT) { throw errors.jitDisabled(key).toException(); } @@ -875,25 +922,28 @@ // throw with a more appropriate message below } } - throw errors.missingImplementation(key).toException(); + throw errors.missingImplementationWithHint(key, this).toException(); } Object source = key.getTypeLiteral().getRawType(); - BindingImpl binding = createUninitializedBinding(key, Scoping.UNSCOPED, source, errors, true); + BindingImpl binding = + createUninitializedBinding(key, Scoping.UNSCOPED, source, errors, true); errors.throwIfNewErrors(numErrorsBefore); initializeJitBinding(binding, errors); return binding; } - InternalFactory getInternalFactory(Key key, Errors errors, JitLimitation jitType) - throws ErrorsException { + InternalFactory getInternalFactory( + Key key, Errors errors, JitLimitation jitType) throws ErrorsException { return getBindingOrThrow(key, errors, jitType).getInternalFactory(); } + @Override public Map, Binding> getBindings() { return state.getExplicitBindingsThisLevel(); } + @Override public Map, Binding> getAllBindings() { synchronized (state.lock()) { return new ImmutableMap.Builder, Binding>() @@ -903,41 +953,19 @@ } } + @Override public Map, Scope> getScopeBindings() { return ImmutableMap.copyOf(state.getScopes()); } + @Override public Set getTypeConverterBindings() { return ImmutableSet.copyOf(state.getConvertersThisLevel()); } - private static class BindingsMultimap { - final Map, List>> multimap = Maps.newHashMap(); - - void put(TypeLiteral type, Binding binding) { - List> bindingsForType = multimap.get(type); - if (bindingsForType == null) { - bindingsForType = Lists.newArrayList(); - multimap.put(type, bindingsForType); - } - bindingsForType.add(binding); - } - - - @SuppressWarnings("unchecked") // safe because we only put matching entries into the map - List> getAll(TypeLiteral type) { - List> bindings = multimap.get(type); - return bindings != null - ? Collections.>unmodifiableList((List) multimap.get(type)) - : ImmutableList.>of(); - } - } - - /** - * Returns parameter injectors, or {@code null} if there are no parameters. - */ - SingleParameterInjector[] getParametersInjectors( - List> parameters, Errors errors) throws ErrorsException { + /** Returns parameter injectors, or {@code null} if there are no parameters. */ + SingleParameterInjector[] getParametersInjectors(List> parameters, Errors errors) + throws ErrorsException { if (parameters.isEmpty()) { return null; } @@ -957,9 +985,10 @@ return result; } - SingleParameterInjector createParameterInjector(final Dependency dependency, - final Errors errors) throws ErrorsException { - BindingImpl binding = getBindingOrThrow(dependency.getKey(), errors, JitLimitation.NO_JIT); + SingleParameterInjector createParameterInjector( + final Dependency dependency, final Errors errors) throws ErrorsException { + BindingImpl binding = + getBindingOrThrow(dependency.getKey(), errors, JitLimitation.NO_JIT); return new SingleParameterInjector(dependency, binding); } @@ -978,12 +1007,14 @@ /** Cached provision listener callbacks for each key. */ ProvisionListenerCallbackStore provisionListenerStore; + @Override @SuppressWarnings("unchecked") // the members injector type is consistent with instance's type public void injectMembers(Object instance) { MembersInjector membersInjector = getMembersInjector(instance.getClass()); membersInjector.injectMembers(instance); } + @Override public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { Errors errors = new Errors(typeLiteral); try { @@ -993,45 +1024,47 @@ } } + @Override public MembersInjector getMembersInjector(Class type) { return getMembersInjector(TypeLiteral.get(type)); } + @Override public Provider getProvider(Class type) { return getProvider(Key.get(type)); } - Provider getProviderOrThrow(final Dependency dependency, Errors errors) throws ErrorsException { - final Key key = dependency.getKey(); - final BindingImpl binding = getBindingOrThrow(key, errors, JitLimitation.NO_JIT); + Provider getProviderOrThrow(final Dependency dependency, Errors errors) + throws ErrorsException { + Key key = dependency.getKey(); + BindingImpl binding = getBindingOrThrow(key, errors, JitLimitation.NO_JIT); + final InternalFactory internalFactory = binding.getInternalFactory(); + final Object source = binding.getSource(); return new Provider() { + @Override public T get() { - final Errors errors = new Errors(dependency); + InternalContext currentContext = enterContext(); + Dependency previous = currentContext.pushDependency(dependency, source); try { - T t = callInContext(new ContextualCallable() { - public T call(InternalContext context) throws ErrorsException { - Dependency previous = context.pushDependency(dependency, binding.getSource()); - try { - return binding.getInternalFactory().get(errors, context, dependency, false); - } finally { - context.popStateAndSetDependency(previous); - } - } - }); - errors.throwIfNewErrors(0); + T t = internalFactory.get(currentContext, dependency, false); return t; - } catch (ErrorsException e) { - throw new ProvisionException(errors.merge(e.getErrors()).getMessages()); + } catch (InternalProvisionException e) { + throw e.addSource(dependency).toProvisionException(); + } finally { + currentContext.popStateAndSetDependency(previous); + currentContext.close(); } } - @Override public String toString() { - return binding.getInternalFactory().toString(); + @Override + public String toString() { + return internalFactory.toString(); } }; } + @Override public Provider getProvider(final Key key) { Errors errors = new Errors(key); try { @@ -1043,77 +1076,68 @@ } } + @Override public T getInstance(Key key) { return getProvider(key).get(); } + @Override public T getInstance(Class type) { return getProvider(type).get(); } - /** @see #getGlobalInternalContext */ - private final ThreadLocal localContext; /** - * Synchronization: map value is modified only for the current thread, - * it's ok to read map values of other threads. It can change between your - * calls. + * Holds Object[] as a mutable wrapper, rather than InternalContext, since array operations are + * faster than ThreadLocal.set() / .get() operations. * - * @see #getGlobalInternalContext + *

    Holds Object[] rather than InternalContext[], since localContext never gets cleaned up at + * any point. This could lead to problems when, for example, an OSGI application is reloaded, the + * InjectorImpl is destroyed, but the thread that the injector runs on is kept alive. In such a + * case, ThreadLocal itself would hold on to a reference to localContext, which would hold on to + * the old InternalContext.class object, which would hold on to the old classloader that loaded + * that class, and so on. */ - private static final ConcurrentMap globalInternalContext = - Maps.newConcurrentMap(); + private final ThreadLocal localContext; + + /** Only to be called by the {@link SingletonScope} provider. */ + InternalContext getLocalContext() { + return (InternalContext) localContext.get()[0]; + } /** - * Provides access to the internal context for the current injector of all threads. - * One does not need to use this from Guice source code as context could be passed on the stack. - * It is required for custom scopes which are called from Guice and sometimes do require - * access to current internal context, but it is not passed in. Contrary to {@link #localContext} - * it is not used to store injector-specific state, but to provide easy access to the current - * state. + * Looks up thread local context and {@link InternalContext#enter() enters} it or creates a new + * context if necessary. + * + *

    All callers of this are responsible for calling {@link InternalContext#close()}. Typical + * usage should look like: * - * @return unmodifiable map + *

    {@code
    +   * InternalContext ctx = injector.enterContext();
    +   * try {
    +   *   ... use ctx ...
    +   * } finally {
    +   *   ctx.close();
    +   * }
    +   * }
    */ - static Map getGlobalInternalContext() { - return Collections.unmodifiableMap(globalInternalContext); - } - - /** Looks up thread local context. Creates (and removes) a new context if necessary. */ - T callInContext(ContextualCallable callable) throws ErrorsException { + InternalContext enterContext() { Object[] reference = localContext.get(); if (reference == null) { reference = new Object[1]; localContext.set(reference); } - Thread currentThread = Thread.currentThread(); - if (reference[0] == null) { - reference[0] = new InternalContext(options); - globalInternalContext.put(currentThread, (InternalContext) reference[0]); - try { - return callable.call((InternalContext) reference[0]); - } finally { - // Only clear contexts if this call created them. - reference[0] = null; - globalInternalContext.remove(currentThread); - } + InternalContext ctx = (InternalContext) reference[0]; + if (ctx == null) { + reference[0] = ctx = new InternalContext(options, reference); } else { - Object previousGlobalInternalContext = globalInternalContext.get(currentThread); - globalInternalContext.put(currentThread, (InternalContext) reference[0]); - try { - // Someone else will clean up this local context. - return callable.call((InternalContext) reference[0]); - } finally { - if (previousGlobalInternalContext != null) { - globalInternalContext.put(currentThread, (InternalContext) previousGlobalInternalContext); - } else { - globalInternalContext.remove(currentThread); - } - } + ctx.enter(); } + return ctx; } @Override public String toString() { - return Objects.toStringHelper(Injector.class) + return MoreObjects.toStringHelper(Injector.class) .add("bindings", state.getExplicitBindingsThisLevel().values()) .toString(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectorOptionsProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectorOptionsProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectorOptionsProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectorOptionsProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -53,11 +53,11 @@ jitDisabled = true; return true; } - + @Override public Boolean visit(RequireAtInjectOnConstructorsOption option) { atInjectRequired = true; - return true; + return true; } @Override @@ -68,7 +68,7 @@ InjectorOptions getOptions(Stage stage, InjectorOptions parentOptions) { checkNotNull(stage, "stage must be set"); - if(parentOptions == null) { + if (parentOptions == null) { return new InjectorOptions( stage, jitDisabled, @@ -85,5 +85,4 @@ exactBindingAnnotationsRequired || parentOptions.exactBindingAnnotationsRequired); } } - } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectorShell.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectorShell.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InjectorShell.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InjectorShell.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,14 +39,13 @@ import com.google.inject.spi.PrivateElements; import com.google.inject.spi.ProvisionListenerBinding; import com.google.inject.spi.TypeListenerBinding; - import java.util.List; import java.util.logging.Logger; /** - * A partially-initialized injector. See {@link InternalInjectorCreator}, which - * uses this to build a tree of injectors in batch. - * + * A partially-initialized injector. See {@link InternalInjectorCreator}, which uses this to build a + * tree of injectors in batch. + * * @author jessewilson@google.com (Jesse Wilson) */ final class InjectorShell { @@ -54,7 +53,7 @@ private final List elements; private final InjectorImpl injector; - private InjectorShell(Builder builder, List elements, InjectorImpl injector) { + private InjectorShell(List elements, InjectorImpl injector) { this.elements = elements; this.injector = injector; } @@ -80,7 +79,7 @@ /** null unless this exists in a {@link Binder#newPrivateBinder private environment} */ private PrivateElementsImpl privateElements; - + Builder stage(Stage stage) { this.stage = stage; return this; @@ -105,7 +104,7 @@ this.modules.add(module); } } - + Stage getStage() { return options.stage; } @@ -136,12 +135,12 @@ modules.add(0, new InheritedScannersModule(parent.state)); } elements.addAll(Elements.getElements(stage, modules)); - + // Look for injector-changing options InjectorOptionsProcessor optionsProcessor = new InjectorOptionsProcessor(errors); optionsProcessor.process(null, elements); options = optionsProcessor.getOptions(stage, options); - + InjectorImpl injector = new InjectorImpl(parent, state, options); if (privateElements != null) { privateElements.initInjector(injector); @@ -179,7 +178,7 @@ bindStage(injector, stage); bindInjector(injector); bindLogger(injector); - + // Process all normal bindings, then UntargettedBindings. // This is necessary because UntargettedBindings can create JIT bindings // and need all their other dependencies set up ahead of time. @@ -191,7 +190,7 @@ stopwatch.resetAndLog("Module annotated method scanners creation"); List injectorShells = Lists.newArrayList(); - injectorShells.add(new InjectorShell(this, elements, injector)); + injectorShells.add(new InjectorShell(elements, injector)); // recursively build child shells PrivateElementProcessor processor = new PrivateElementProcessor(errors); @@ -213,15 +212,21 @@ } /** - * The Injector is a special case because we allow both parent and child injectors to both have - * a binding for that key. + * The Injector is a special case because we allow both parent and child injectors to both have a + * binding for that key. */ private static void bindInjector(InjectorImpl injector) { Key key = Key.get(Injector.class); InjectorFactory injectorFactory = new InjectorFactory(injector); - injector.state.putBinding(key, - new ProviderInstanceBindingImpl(injector, key, SourceProvider.UNKNOWN_SOURCE, - injectorFactory, Scoping.UNSCOPED, injectorFactory, + injector.state.putBinding( + key, + new ProviderInstanceBindingImpl( + injector, + key, + SourceProvider.UNKNOWN_SOURCE, + injectorFactory, + Scoping.UNSCOPED, + injectorFactory, ImmutableSet.of())); } @@ -232,15 +237,17 @@ this.injector = injector; } - public Injector get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { + @Override + public Injector get(InternalContext context, Dependency dependency, boolean linked) { return injector; } + @Override public Injector get() { return injector; } + @Override public String toString() { return "Provider"; } @@ -253,10 +260,16 @@ private static void bindLogger(InjectorImpl injector) { Key key = Key.get(Logger.class); LoggerFactory loggerFactory = new LoggerFactory(); - injector.state.putBinding(key, - new ProviderInstanceBindingImpl(injector, key, - SourceProvider.UNKNOWN_SOURCE, loggerFactory, Scoping.UNSCOPED, - loggerFactory, ImmutableSet.of())); + injector.state.putBinding( + key, + new ProviderInstanceBindingImpl( + injector, + key, + SourceProvider.UNKNOWN_SOURCE, + loggerFactory, + Scoping.UNSCOPED, + loggerFactory, + ImmutableSet.of())); try { Key slf4jKey = Key.get(org.slf4j.Logger.class); @@ -269,22 +282,25 @@ } private static class LoggerFactory implements InternalFactory, Provider { - public Logger get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { + @Override + public Logger get(InternalContext context, Dependency dependency, boolean linked) { InjectionPoint injectionPoint = dependency.getInjectionPoint(); return injectionPoint == null ? Logger.getAnonymousLogger() : Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); } + @Override public Logger get() { return Logger.getAnonymousLogger(); } + @Override public String toString() { return "Provider"; } } - + private static class SLF4JLoggerFactory implements InternalFactory, Provider { private final Injector injector; @@ -306,7 +322,7 @@ return loggerFactory; } - public org.slf4j.Logger get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { + public org.slf4j.Logger get(InternalContext context, Dependency dependency, boolean linked) { InjectionPoint injectionPoint = dependency.getInjectionPoint(); if (injectionPoint != null) { return loggerFactory().getLogger(injectionPoint.getMember().getDeclaringClass().getName()); @@ -325,17 +341,19 @@ private static void bindStage(InjectorImpl injector, Stage stage) { Key key = Key.get(Stage.class); - InstanceBindingImpl stageBinding = new InstanceBindingImpl( - injector, - key, - SourceProvider.UNKNOWN_SOURCE, - new ConstantFactory(Initializables.of(stage)), - ImmutableSet.of(), - stage); + InstanceBindingImpl stageBinding = + new InstanceBindingImpl( + injector, + key, + SourceProvider.UNKNOWN_SOURCE, + new ConstantFactory(Initializables.of(stage)), + ImmutableSet.of(), + stage); injector.state.putBinding(key, stageBinding); } private static class RootModule implements Module { + @Override public void configure(Binder binder) { binder = binder.withSource(SourceProvider.UNKNOWN_SOURCE); binder.bindScope(Singleton.class, SINGLETON); @@ -350,6 +368,7 @@ this.state = state; } + @Override public void configure(Binder binder) { for (ModuleAnnotatedMethodScannerBinding binding : state.getScannerBindings()) { binding.applyTo(binder); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InstanceBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InstanceBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InstanceBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InstanceBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,80 +16,83 @@ package com.google.inject.internal; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; import com.google.inject.Key; -import com.google.inject.Provider; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InstanceBinding; -import com.google.inject.util.Providers; - import java.util.Set; final class InstanceBindingImpl extends BindingImpl implements InstanceBinding { final T instance; - final Provider provider; final ImmutableSet injectionPoints; - public InstanceBindingImpl(InjectorImpl injector, Key key, Object source, - InternalFactory internalFactory, Set injectionPoints, + public InstanceBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Set injectionPoints, T instance) { super(injector, key, source, internalFactory, Scoping.EAGER_SINGLETON); this.injectionPoints = ImmutableSet.copyOf(injectionPoints); this.instance = instance; - this.provider = Providers.of(instance); } - public InstanceBindingImpl(Object source, Key key, Scoping scoping, - Set injectionPoints, T instance) { + public InstanceBindingImpl( + Object source, Key key, Scoping scoping, Set injectionPoints, T instance) { super(source, key, scoping); this.injectionPoints = ImmutableSet.copyOf(injectionPoints); this.instance = instance; - this.provider = Providers.of(instance); - } - - @Override public Provider getProvider() { - return this.provider; } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } + @Override public T getInstance() { return instance; } + @Override public Set getInjectionPoints() { return injectionPoints; } + @Override public Set> getDependencies() { return instance instanceof HasDependencies ? ImmutableSet.copyOf(((HasDependencies) instance).getDependencies()) : Dependency.forInjectionPoints(injectionPoints); } + @Override public BindingImpl withScoping(Scoping scoping) { return new InstanceBindingImpl(getSource(), getKey(), scoping, injectionPoints, instance); } + @Override public BindingImpl withKey(Key key) { return new InstanceBindingImpl(getSource(), key, getScoping(), injectionPoints, instance); } + @Override public void applyTo(Binder binder) { // instance bindings aren't scoped binder.withSource(getSource()).bind(getKey()).toInstance(instance); } - @Override public String toString() { - return Objects.toStringHelper(InstanceBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(InstanceBinding.class) .add("key", getKey()) .add("source", getSource()) .add("instance", instance) @@ -98,11 +101,11 @@ @Override public boolean equals(Object obj) { - if(obj instanceof InstanceBindingImpl) { - InstanceBindingImpl o = (InstanceBindingImpl)obj; + if (obj instanceof InstanceBindingImpl) { + InstanceBindingImpl o = (InstanceBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(instance, o.instance); + && getScoping().equals(o.getScoping()) + && Objects.equal(instance, o.instance); } else { return false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InterceptorBindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InterceptorBindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InterceptorBindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InterceptorBindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,9 +30,11 @@ super(errors); } - @Override public Boolean visit(InterceptorBinding command) { - injector.state.addMethodAspect(new MethodAspect( - command.getClassMatcher(), command.getMethodMatcher(), command.getInterceptors())); + @Override + public Boolean visit(InterceptorBinding command) { + injector.state.addMethodAspect( + new MethodAspect( + command.getClassMatcher(), command.getMethodMatcher(), command.getInterceptors())); return true; } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InterceptorStackCallback.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InterceptorStackCallback.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InterceptorStackCallback.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InterceptorStackCallback.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,18 +17,15 @@ package com.google.inject.internal; import com.google.common.collect.Lists; - -import net.sf.cglib.proxy.MethodProxy; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import net.sf.cglib.proxy.MethodProxy; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; /** * Intercepts a method with a stack of interceptors. @@ -36,22 +33,24 @@ * @author crazybob@google.com (Bob Lee) */ final class InterceptorStackCallback implements net.sf.cglib.proxy.MethodInterceptor { - private static final Set AOP_INTERNAL_CLASSES = new HashSet(Arrays.asList( - InterceptorStackCallback.class.getName(), - InterceptedMethodInvocation.class.getName(), - MethodProxy.class.getName())); + private static final Set AOP_INTERNAL_CLASSES = + new HashSet( + Arrays.asList( + InterceptorStackCallback.class.getName(), + InterceptedMethodInvocation.class.getName(), + MethodProxy.class.getName())); final MethodInterceptor[] interceptors; final Method method; - public InterceptorStackCallback(Method method, - List interceptors) { + public InterceptorStackCallback(Method method, List interceptors) { this.method = method; this.interceptors = interceptors.toArray(new MethodInterceptor[interceptors.size()]); } - public Object intercept(Object proxy, Method method, Object[] arguments, - MethodProxy methodProxy) throws Throwable { + @Override + public Object intercept(Object proxy, Method method, Object[] arguments, MethodProxy methodProxy) + throws Throwable { return new InterceptedMethodInvocation(proxy, methodProxy, arguments, 0).proceed(); } @@ -62,49 +61,54 @@ final MethodProxy methodProxy; final int index; - public InterceptedMethodInvocation(Object proxy, MethodProxy methodProxy, - Object[] arguments, int index) { + public InterceptedMethodInvocation( + Object proxy, MethodProxy methodProxy, Object[] arguments, int index) { this.proxy = proxy; this.methodProxy = methodProxy; this.arguments = arguments; this.index = index; } + @Override public Object proceed() throws Throwable { try { return index == interceptors.length ? methodProxy.invokeSuper(proxy, arguments) - : interceptors[index].invoke( - new InterceptedMethodInvocation(proxy, methodProxy, arguments, index + 1)); + : interceptors[index] + .invoke(new InterceptedMethodInvocation(proxy, methodProxy, arguments, index + 1)); } catch (Throwable t) { pruneStacktrace(t); throw t; } } + @Override public Method getMethod() { return method; } + @Override public Object[] getArguments() { return arguments; } + @Override public Object getThis() { return proxy; } + @Override public AccessibleObject getStaticPart() { return getMethod(); } } /** - * Removes stacktrace elements related to AOP internal mechanics from the - * throwable's stack trace and any causes it may have. + * Removes stacktrace elements related to AOP internal mechanics from the throwable's stack trace + * and any causes it may have. */ private void pruneStacktrace(Throwable throwable) { - for(Throwable t = throwable; t != null; t = t.getCause()) { + for (Throwable t = throwable; t != null; t = t.getCause()) { StackTraceElement[] stackTrace = t.getStackTrace(); List pruned = Lists.newArrayList(); for (StackTraceElement element : stackTrace) { diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalContext.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalContext.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalContext.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalContext.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,129 +16,153 @@ package com.google.inject.internal; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.inject.Key; import com.google.inject.internal.InjectorImpl.InjectorOptions; import com.google.inject.spi.Dependency; -import com.google.inject.spi.DependencyAndSource; - -import java.util.Arrays; -import java.util.List; +import java.util.IdentityHashMap; import java.util.Map; /** - * Internal context. Used to coordinate injections and support circular - * dependencies. + * Internal context. Used to coordinate injections and support circular dependencies. * * @author crazybob@google.com (Bob Lee) */ -final class InternalContext { +final class InternalContext implements AutoCloseable { private final InjectorOptions options; - private Map> constructionContexts = Maps.newHashMap(); + private final Map> constructionContexts = + new IdentityHashMap>(); /** Keeps track of the type that is currently being requested for injection. */ private Dependency dependency; - /** Keeps track of the hierarchy of types needed during injection. */ - private final DependencyStack state = new DependencyStack(); + /** + * Keeps track of the hierarchy of types needed during injection. + * + *

    This is a pairwise combination of dependencies and sources, with dependencies or keys on + * even indices, and sources on odd indices. This structure is to avoid the memory overhead of + * DependencyAndSource objects, which can add to several tens of megabytes in large applications. + */ + private Object[] dependencyStack = new Object[16]; + + private int dependencyStackSize = 0; - InternalContext(InjectorOptions options) { + + /** + * The number of times {@link #enter()} has been called + 1 for initial construction. This value + * is decremented when {@link #exit()} is called. + */ + private int enterCount; + + /** + * A single element array to clear when the {@link #enterCount} hits {@code 0}. + * + *

    This is the value stored in the {@code InjectorImpl.localContext} thread local. + */ + private final Object[] toClear; + + InternalContext(InjectorOptions options, Object[] toClear) { this.options = options; + this.toClear = toClear; + this.enterCount = 1; + } + + /** Should only be called by InjectorImpl.enterContext(). */ + void enter() { + enterCount++; + } + + /** Should be called any any method that received an instance via InjectorImpl.enterContext(). */ + @Override + public void close() { + int newCount = --enterCount; + if (newCount < 0) { + throw new IllegalStateException("Called close() too many times"); + } + if (newCount == 0) { + toClear[0] = null; + } } - public InjectorOptions getInjectorOptions() { + InjectorOptions getInjectorOptions() { return options; } @SuppressWarnings("unchecked") - public ConstructionContext getConstructionContext(Object key) { - ConstructionContext constructionContext - = (ConstructionContext) constructionContexts.get(key); + ConstructionContext getConstructionContext(Object key) { + ConstructionContext constructionContext = + (ConstructionContext) constructionContexts.get(key); if (constructionContext == null) { - constructionContext = new ConstructionContext(); + constructionContext = new ConstructionContext<>(); constructionContexts.put(key, constructionContext); } return constructionContext; } - public Dependency getDependency() { + Dependency getDependency() { return dependency; } /** Sets the new current dependency & adds it to the state. */ - public Dependency pushDependency(Dependency dependency, Object source) { + Dependency pushDependency(Dependency dependency, Object source) { Dependency previous = this.dependency; this.dependency = dependency; - state.add(dependency, source); + doPushState(dependency, source); return previous; } + /** Pops the current state & sets the new dependency. */ - public void popStateAndSetDependency(Dependency newDependency) { - state.pop(); + void popStateAndSetDependency(Dependency newDependency) { + popState(); this.dependency = newDependency; } + /** Adds to the state without setting the dependency. */ - public void pushState(Key key, Object source) { - state.add(key, source); + void pushState(com.google.inject.Key key, Object source) { + doPushState(key, source); + } + + + private void doPushState(Object dependencyOrKey, Object source) { + int localSize = dependencyStackSize; + Object[] localStack = dependencyStack; + if (localStack.length < localSize + 2) { + localStack = dependencyStack = + java.util.Arrays.copyOf(localStack, (localStack.length * 3) / 2 + 2); + } + localStack[localSize++] = dependencyOrKey; + localStack[localSize++] = source; + dependencyStackSize = localSize; } - + + /** Pops from the state without setting a dependency. */ - public void popState() { - state.pop(); + void popState() { + // N.B. we don't null out the array entries. It isn't necessary since all the objects in the + // array (Key, Dependency, or Binding source objects) are all tied to the lifetime of the + // injector, which is greater than the lifetime of this object. So removing them from the array + // doesn't matter. + dependencyStackSize -= 2; } - /** Returns the current dependency chain (all the state). */ - public List getDependencyChain() { - ImmutableList.Builder builder = ImmutableList.builder(); - for (int i = 0; i < state.size(); i += 2) { - Object evenEntry = state.get(i); + + /** Returns the current dependency chain (all the state stored in the dependencyStack). */ + java.util.List getDependencyChain() { + com.google.common.collect.ImmutableList.Builder + builder = com.google.common.collect.ImmutableList.builder(); + for (int i = 0; i < dependencyStackSize; i += 2) { + Object evenEntry = dependencyStack[i]; Dependency dependency; - if (evenEntry instanceof Key) { - dependency = Dependency.get((Key) evenEntry); + if (evenEntry instanceof com.google.inject.Key) { + dependency = Dependency.get((com.google.inject.Key) evenEntry); } else { dependency = (Dependency) evenEntry; } - builder.add(new DependencyAndSource(dependency, state.get(i + 1))); + builder.add(new com.google.inject.spi.DependencyAndSource(dependency, dependencyStack[i + 1])); } return builder.build(); } - /** - * Keeps track of the hierarchy of types needed during injection. - * - *

    This is a pairwise combination of dependencies and sources, with dependencies or keys on - * even indices, and sources on odd indices. This structure is to avoid the memory overhead of - * DependencyAndSource objects, which can add to several tens of megabytes in large applications. - */ - private static final class DependencyStack { - private Object[] elements = new Object[16]; - private int size = 0; - - public void add(Object dependencyOrKey, Object source) { - if (elements.length < size + 2) { - elements = Arrays.copyOf(elements, (elements.length*3)/2 + 2); - } - elements[size++] = dependencyOrKey; - elements[size++] = source; - } - - public void pop() { - elements[--size] = null; - elements[--size] = null; - } - - public Object get(int i) { - return elements[i]; - } - - public int size() { - return size; - } - } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,12 +27,12 @@ /** * Creates an object to be injected. + * * @param context of this injection * @param linked true if getting as a result of a linked binding - * - * @throws com.google.inject.internal.ErrorsException if a value cannot be provided - * @return instance to be injected + * @throws com.google.inject.internal.InternalProvisionException if a value cannot be provided + * @return instance that was created */ - T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException; + T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +22,11 @@ import com.google.inject.spi.ProviderInstanceBinding; /** - * Adapts {@link ProviderInstanceBinding} providers, ensuring circular proxies - * fail (or proxy) properly. - * + * Adapts {@link ProviderInstanceBinding} providers, ensuring circular proxies fail (or proxy) + * properly. + * * @author sameb@google.com (Sam Berlin) -*/ + */ final class InternalFactoryToInitializableAdapter extends ProviderInternalFactory { private final ProvisionListenerStackCallback provisionCallback; @@ -34,29 +34,34 @@ public InternalFactoryToInitializableAdapter( Initializable> initializable, - Object source, ProvisionListenerStackCallback provisionCallback) { + Object source, + ProvisionListenerStackCallback provisionCallback) { super(source); - this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback"); + this.provisionCallback = provisionCallback; this.initializable = checkNotNull(initializable, "provider"); } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - return circularGet(initializable.get(errors), errors, context, dependency, - provisionCallback); + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + return circularGet(initializable.get(), context, dependency, provisionCallback); } - + @Override - protected T provision(javax.inject.Provider provider, Errors errors, - Dependency dependency, ConstructionContext constructionContext) throws ErrorsException { + protected T provision( + javax.inject.Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { try { - return super.provision(provider, errors, dependency, constructionContext); - } catch(RuntimeException userException) { - throw errors.withSource(source).errorInProvider(userException).toException(); + return super.provision(provider, dependency, constructionContext); + } catch (RuntimeException userException) { + throw InternalProvisionException.errorInProvider(userException).addSource(source); } } - @Override public String toString() { + @Override + public String toString() { return initializable.toString(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,9 +21,7 @@ import com.google.inject.Provider; import com.google.inject.spi.Dependency; -/** - * @author crazybob@google.com (Bob Lee) -*/ +/** @author crazybob@google.com (Bob Lee) */ final class InternalFactoryToProviderAdapter implements InternalFactory { private final Provider provider; @@ -34,17 +32,22 @@ this.source = checkNotNull(source, "source"); } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - // TODO(sameb): Does this need to push state into the context? + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { try { - return errors.checkForNull(provider.get(), source, dependency); + T t = provider.get(); + if (t == null && !dependency.isNullable()) { + InternalProvisionException.onNullInjectedIntoNonNullableDependency(source, dependency); + } + return t; } catch (RuntimeException userException) { - throw errors.withSource(source).errorInProvider(userException).toException(); + throw InternalProvisionException.errorInProvider(userException).addSource(source); } } - @Override public String toString() { + @Override + public String toString() { return provider.toString(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFlags.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFlags.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalFlags.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalFlags.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -121,11 +121,14 @@ Class enumType = defaultValue.getDeclaringClass(); String value = null; try { - value = AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty(name); - } - }); + value = + AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public String run() { + return System.getProperty(name); + } + }); return (value != null && value.length() > 0) ? Enum.valueOf(enumType, value) : defaultValue; } catch (SecurityException e) { return secureValue; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalInjectorCreator.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalInjectorCreator.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalInjectorCreator.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalInjectorCreator.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,8 +16,6 @@ package com.google.inject.internal; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; @@ -30,8 +28,8 @@ import com.google.inject.internal.util.Stopwatch; import com.google.inject.spi.Dependency; import com.google.inject.spi.TypeConverterBinding; - import java.lang.annotation.Annotation; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -43,14 +41,15 @@ * top-level injector. * *

    Injector construction happens in two phases. + * *

      - *
    1. Static building. In this phase, we interpret commands, create bindings, and inspect + *
    2. Static building. In this phase, we interpret commands, create bindings, and inspect * dependencies. During this phase, we hold a lock to ensure consistency with parent injectors. - * No user code is executed in this phase.
    3. - *
    4. Dynamic injection. In this phase, we call user code. We inject members that requested + * No user code is executed in this phase. + *
    5. Dynamic injection. In this phase, we call user code. We inject members that requested * injection. This may require user's objects be created and their providers be called. And we * create eager singletons. In this phase, user code may have started other threads. This phase - * is not executed for injectors created using {@link Stage#TOOL the tool stage}
    6. + * is not executed for injectors created using {@link Stage#TOOL the tool stage} *
    * * @author crazybob@google.com (Bob Lee) @@ -67,12 +66,12 @@ private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder(); private List shells; - + public InternalInjectorCreator() { injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer); bindingData = new ProcessedBindingData(); } - + public InternalInjectorCreator stage(Stage stage) { shellBuilder.stage(stage); return this; @@ -146,6 +145,11 @@ } stopwatch.resetAndLog("Provider verification"); + // This needs to come late since some user bindings rely on requireBinding calls to create + // jit bindings during the LookupProcessor. + bindingData.initializeDelayedBindings(); + stopwatch.resetAndLog("Delayed Binding initialization"); + for (InjectorShell shell : shells) { if (!shell.getElements().isEmpty()) { throw new AssertionError("Failed to execute " + shell.getElements()); @@ -155,9 +159,7 @@ errors.throwCreationExceptionIfErrorsExist(); } - /** - * Returns the injector being constructed. This is not necessarily the root injector. - */ + /** Returns the injector being constructed. This is not necessarily the root injector. */ private Injector primaryInjector() { return shells.get(0).getInjector(); } @@ -175,7 +177,7 @@ stopwatch.resetAndLog("Instance injection"); errors.throwCreationExceptionIfErrorsExist(); - if(shellBuilder.getStage() != Stage.TOOL) { + if (shellBuilder.getStage() != Stage.TOOL) { for (InjectorShell shell : shells) { loadEagerSingletons(shell.getInjector(), shellBuilder.getStage(), errors); } @@ -189,33 +191,33 @@ * while we're binding these singletons are not be eager. */ void loadEagerSingletons(InjectorImpl injector, Stage stage, final Errors errors) { + List> candidateBindings = new ArrayList<>(); @SuppressWarnings("unchecked") // casting Collection to Collection is safe - Iterable> candidateBindings = ImmutableList.copyOf(Iterables.concat( - (Collection) injector.state.getExplicitBindingsThisLevel().values(), - injector.jitBindings.values())); - for (final BindingImpl binding : candidateBindings) { - if (isEagerSingleton(injector, binding, stage)) { - try { - injector.callInContext(new ContextualCallable() { - Dependency dependency = Dependency.get(binding.getKey()); - public Void call(InternalContext context) { - Dependency previous = context.pushDependency(dependency, binding.getSource()); - Errors errorsForBinding = errors.withSource(dependency); - try { - binding.getInternalFactory().get(errorsForBinding, context, dependency, false); - } catch (ErrorsException e) { - errorsForBinding.merge(e.getErrors()); - } finally { - context.popStateAndSetDependency(previous); - } - - return null; + Collection> bindingsAtThisLevel = + (Collection) injector.state.getExplicitBindingsThisLevel().values(); + candidateBindings.addAll(bindingsAtThisLevel); + synchronized (injector.state.lock()) { + // jit bindings must be accessed while holding the lock. + candidateBindings.addAll(injector.jitBindings.values()); + } + InternalContext context = injector.enterContext(); + try { + for (BindingImpl binding : candidateBindings) { + if (isEagerSingleton(injector, binding, stage)) { + Dependency dependency = Dependency.get(binding.getKey()); + Dependency previous = context.pushDependency(dependency, binding.getSource()); + + try { + binding.getInternalFactory().get(context, dependency, false); + } catch (InternalProvisionException e) { + errors.withSource(dependency).merge(e); + } finally { + context.popStateAndSetDependency(previous); } - }); - } catch (ErrorsException e) { - throw new AssertionError(); } } + } finally { + context.close(); } } @@ -238,70 +240,106 @@ /** {@link Injector} exposed to users in {@link Stage#TOOL}. */ static class ToolStageInjector implements Injector { private final Injector delegateInjector; - + ToolStageInjector(Injector delegateInjector) { this.delegateInjector = delegateInjector; } + + @Override public void injectMembers(Object o) { throw new UnsupportedOperationException( - "Injector.injectMembers(Object) is not supported in Stage.TOOL"); + "Injector.injectMembers(Object) is not supported in Stage.TOOL"); } + + @Override public Map, Binding> getBindings() { return this.delegateInjector.getBindings(); } + + @Override public Map, Binding> getAllBindings() { return this.delegateInjector.getAllBindings(); } + + @Override public Binding getBinding(Key key) { return this.delegateInjector.getBinding(key); } + + @Override public Binding getBinding(Class type) { return this.delegateInjector.getBinding(type); } + + @Override public Binding getExistingBinding(Key key) { return this.delegateInjector.getExistingBinding(key); } + + @Override public List> findBindingsByType(TypeLiteral type) { return this.delegateInjector.findBindingsByType(type); } + + @Override public Injector getParent() { return delegateInjector.getParent(); } + + @Override public Injector createChildInjector(Iterable modules) { return delegateInjector.createChildInjector(modules); } + + @Override public Injector createChildInjector(Module... modules) { return delegateInjector.createChildInjector(modules); } + + @Override public Map, Scope> getScopeBindings() { return delegateInjector.getScopeBindings(); } + + @Override public Set getTypeConverterBindings() { return delegateInjector.getTypeConverterBindings(); } + + @Override public Provider getProvider(Key key) { throw new UnsupportedOperationException( - "Injector.getProvider(Key) is not supported in Stage.TOOL"); + "Injector.getProvider(Key) is not supported in Stage.TOOL"); } + + @Override public Provider getProvider(Class type) { throw new UnsupportedOperationException( - "Injector.getProvider(Class) is not supported in Stage.TOOL"); + "Injector.getProvider(Class) is not supported in Stage.TOOL"); } + + @Override public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { throw new UnsupportedOperationException( - "Injector.getMembersInjector(TypeLiteral) is not supported in Stage.TOOL"); + "Injector.getMembersInjector(TypeLiteral) is not supported in Stage.TOOL"); } + + @Override public MembersInjector getMembersInjector(Class type) { throw new UnsupportedOperationException( - "Injector.getMembersInjector(Class) is not supported in Stage.TOOL"); + "Injector.getMembersInjector(Class) is not supported in Stage.TOOL"); } + + @Override public T getInstance(Key key) { throw new UnsupportedOperationException( - "Injector.getInstance(Key) is not supported in Stage.TOOL"); + "Injector.getInstance(Key) is not supported in Stage.TOOL"); } + + @Override public T getInstance(Class type) { throw new UnsupportedOperationException( - "Injector.getInstance(Class) is not supported in Stage.TOOL"); + "Injector.getInstance(Class) is not supported in Stage.TOOL"); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalProviderInstanceBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalProviderInstanceBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalProviderInstanceBindingImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalProviderInstanceBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,195 @@ +package com.google.inject.internal; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Key; +import com.google.inject.Provider; +import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.ProviderWithExtensionVisitor; + +/** + * A {@link ProviderInstanceBindingImpl} for implementing 'native' guice extensions. + * + *

    Beyond the normal binding contract that is mostly handled by our baseclass, this also + * implements {@link DelayedInitialize} in order to initialize factory state. + */ +final class InternalProviderInstanceBindingImpl extends ProviderInstanceBindingImpl + implements DelayedInitialize { + enum InitializationTiming { + /** This factory can be initialized eagerly. This should be the case for most things. */ + EAGER, + + /** + * Initialization of this factory should be delayed until after all other static initialization + * completes. This will be useful for factories that need to call {@link + * InjectorImpl#getExistingBinding(Key)} to not create jit bindings, but also want to be able to + * conditionally consume jit bindings created by other other bindings. + */ + DELAYED; + } + + private final Factory originalFactory; + + InternalProviderInstanceBindingImpl( + InjectorImpl injector, + Key key, + Object source, + Factory originalFactory, + InternalFactory scopedFactory, + Scoping scoping) { + super( + injector, + key, + source, + scopedFactory, + scoping, + originalFactory, + ImmutableSet.of()); + this.originalFactory = originalFactory; + } + + InitializationTiming getInitializationTiming() { + return originalFactory.initializationTiming; + } + + @Override + public void initialize(final InjectorImpl injector, final Errors errors) throws ErrorsException { + originalFactory.source = getSource(); + originalFactory.provisionCallback = injector.provisionListenerStore.get(this); + // For these kinds of providers, the 'user supplied provider' is really 'guice supplied' + // So make our user supplied provider just delegate to the guice supplied one. + originalFactory.delegateProvider = getProvider(); + originalFactory.initialize(injector, errors); + } + + /** + * A base factory implementation. Any Factories that delegate to other bindings should use the + * {@code CyclicFactory} subclass, but trivial factories can use this one. + */ + abstract static class Factory implements InternalFactory, Provider, HasDependencies { + private final InitializationTiming initializationTiming; + private Object source; + private Provider delegateProvider; + ProvisionListenerStackCallback provisionCallback; + + Factory(InitializationTiming initializationTiming) { + this.initializationTiming = initializationTiming; + } + /** + * The binding source. + * + *

    May be useful for augmenting runtime error messages. + * + *

    Note: this will return {#code null} until {@link #initialize(InjectorImpl, Errors)} has + * already been called. + */ + final Object getSource() { + return source; + } + + /** + * A callback that allows for implementations to fetch dependencies on other bindings. + * + *

    Will be called exactly once, prior to any call to {@link #doProvision}. + */ + abstract void initialize(InjectorImpl injector, Errors errors) throws ErrorsException; + + @Override + public final T get() { + Provider local = delegateProvider; + if (local == null) { + throw new IllegalStateException( + "This Provider cannot be used until the Injector has been created."); + } + return local.get(); + } + + @Override + public T get(final InternalContext context, final Dependency dependency, boolean linked) + throws InternalProvisionException { + if (provisionCallback == null) { + return doProvision(context, dependency); + } else { + return provisionCallback.provision( + context, + new ProvisionCallback() { + @Override + public T call() throws InternalProvisionException { + return doProvision(context, dependency); + } + }); + } + } + /** + * Creates an object to be injected. + * + * @throws com.google.inject.internal.InternalProvisionException if a value cannot be provided + * @return instance to be injected + */ + protected abstract T doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException; + } + + /** + * An base factory implementation that can be extended to provide a specialized implementation of + * a {@link ProviderWithExtensionVisitor} and also implements {@link InternalFactory} + */ + abstract static class CyclicFactory extends Factory { + + CyclicFactory(InitializationTiming initializationTiming) { + super(initializationTiming); + } + + @Override + public final T get( + final InternalContext context, final Dependency dependency, boolean linked) + throws InternalProvisionException { + final ConstructionContext constructionContext = context.getConstructionContext(this); + // We have a circular reference between bindings. Return a proxy. + if (constructionContext.isConstructing()) { + Class expectedType = dependency.getKey().getTypeLiteral().getRawType(); + @SuppressWarnings("unchecked") + T proxyType = + (T) constructionContext.createProxy(context.getInjectorOptions(), expectedType); + return proxyType; + } + // Optimization: Don't go through the callback stack if no one's listening. + constructionContext.startConstruction(); + try { + if (provisionCallback == null) { + return provision(dependency, context, constructionContext); + } else { + return provisionCallback.provision( + context, + new ProvisionCallback() { + @Override + public T call() throws InternalProvisionException { + return provision(dependency, context, constructionContext); + } + }); + } + } finally { + constructionContext.removeCurrentReference(); + constructionContext.finishConstruction(); + } + } + + private T provision( + Dependency dependency, + InternalContext context, + ConstructionContext constructionContext) + throws InternalProvisionException { + try { + T t = doProvision(context, dependency); + constructionContext.setProxyDelegates(t); + return t; + } catch (InternalProvisionException ipe) { + throw ipe.addSource(getSource()); + } catch (Throwable t) { + throw InternalProvisionException.errorInProvider(t).addSource(getSource()); + } + } + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalProvisionException.java sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalProvisionException.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/InternalProvisionException.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/InternalProvisionException.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.inject.internal; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.inject.Guice; +import com.google.inject.Key; +import com.google.inject.MembersInjector; +import com.google.inject.Provides; +import com.google.inject.ProvisionException; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.util.SourceProvider; +import com.google.inject.internal.util.StackTraceElements; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.InjectionListener; +import com.google.inject.spi.Message; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A checked exception for provisioning errors. + * + *

    This is the internal dual of {@link ProvisionException}, similar to the relationship between + * {@link com.google.inject.ConfigurationException} and {@link ErrorsException}. This is useful for + * several reasons: + * + *

      + *
    • Since it is a checked exception, we get some assistance from the java compiler in ensuring + * that we correctly handle it everywhere. ProvisionException is unchecked. + *
    • Since this is an internal package, we can add useful construction and mutation APIs that + * would be undesirable in a public supported API. + *
    + * + *

    This exception will be thrown when errors are encountered during provisioning, ErrorsException + * will continue to be used for errors that are encountered during provisioning and both make use of + * the {@link Message} as the core model. + * + *

    NOTE: this object stores a list of messages but in the most common case the cardinality will + * be 1. The only time that multiple errors might be reported via this mechanism is when {@link + * #errorInUserCode} is called with an exception that holds multiple errors (like + * ProvisionException). + */ +public final class InternalProvisionException extends Exception { + private static final Logger logger = Logger.getLogger(Guice.class.getName()); + private static final Set> warnedDependencies = + Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); + + + public static InternalProvisionException circularDependenciesDisabled(Class expectedType) { + return create( + "Found a circular dependency involving %s, and circular dependencies are disabled.", + expectedType); + } + + public static InternalProvisionException cannotProxyClass(Class expectedType) { + return create( + "Tried proxying %s to support a circular dependency, but it is not an interface.", + expectedType); + } + + public static InternalProvisionException create(String format, Object... arguments) { + return new InternalProvisionException(Messages.create(format, arguments)); + } + + public static InternalProvisionException errorInUserCode( + Throwable cause, String messageFormat, Object... arguments) { + Collection messages = Errors.getMessagesFromThrowable(cause); + if (!messages.isEmpty()) { + // TODO(lukes): it seems like we are dropping some valuable context here.. + // consider eliminating this special case + return new InternalProvisionException(messages); + } else { + return new InternalProvisionException(Messages.create(cause, messageFormat, arguments)); + } + } + + public static InternalProvisionException subtypeNotProvided( + Class> providerType, Class type) { + return create("%s doesn't provide instances of %s.", providerType, type); + } + + public static InternalProvisionException errorInProvider(Throwable cause) { + return errorInUserCode(cause, "Error in custom provider, %s", cause); + } + + public static InternalProvisionException errorInjectingMethod(Throwable cause) { + return errorInUserCode(cause, "Error injecting method, %s", cause); + } + + public static InternalProvisionException errorInjectingConstructor(Throwable cause) { + return errorInUserCode(cause, "Error injecting constructor, %s", cause); + } + + public static InternalProvisionException errorInUserInjector( + MembersInjector listener, TypeLiteral type, RuntimeException cause) { + return errorInUserCode( + cause, "Error injecting %s using %s.%n Reason: %s", type, listener, cause); + } + + public static InternalProvisionException jitDisabled(Key key) { + return create("Explicit bindings are required and %s is not explicitly bound.", key); + } + + public static InternalProvisionException errorNotifyingInjectionListener( + InjectionListener listener, TypeLiteral type, RuntimeException cause) { + return errorInUserCode( + cause, "Error notifying InjectionListener %s of %s.%n Reason: %s", listener, type, cause); + } + + /** + * Returns {@code value} if it is non-null or allowed to be null. Otherwise a message is added and + * an {@code InternalProvisionException} is thrown. + */ + static void onNullInjectedIntoNonNullableDependency(Object source, Dependency dependency) + throws InternalProvisionException { + // Hack to allow null parameters to @Provides methods, for backwards compatibility. + if (dependency.getInjectionPoint().getMember() instanceof Method) { + Method annotated = (Method) dependency.getInjectionPoint().getMember(); + if (annotated.isAnnotationPresent(Provides.class)) { + switch (InternalFlags.getNullableProvidesOption()) { + case ERROR: + break; // break out & let the below exception happen + case IGNORE: + return; // user doesn't care about injecting nulls to non-@Nullables. + case WARN: + // Warn only once, otherwise we spam logs too much. + if (warnedDependencies.add(dependency)) { + logger.log( + Level.WARNING, + "Guice injected null into {0} (a {1}), please mark it @Nullable." + + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an" + + " error.", + new Object[] { + Messages.formatParameter(dependency), Messages.convert(dependency.getKey()) + }); + } + return; + } + } + } + + Object formattedDependency = + (dependency.getParameterIndex() != -1) + ? Messages.formatParameter(dependency) + : StackTraceElements.forMember(dependency.getInjectionPoint().getMember()); + + throw InternalProvisionException.create( + "null returned by binding at %s%n but %s is not @Nullable", source, formattedDependency) + .addSource(source); + } + + private final List sourcesToPrepend = new ArrayList<>(); + private final ImmutableList errors; + + private InternalProvisionException(Message error) { + this(ImmutableList.of(error)); + } + + private InternalProvisionException(Iterable errors) { + this.errors = ImmutableList.copyOf(errors); + checkArgument(!this.errors.isEmpty(), "Can't create a provision exception with no errors"); + } + + /** + * Prepends the given {@code source} to the stack of binding sources for the errors reported in + * this exception. + * + *

    See {@link Errors#withSource(Object)} + * + *

    It is expected that this method is called as the exception propagates up the stack. + * + * @param source + * @return {@code this} + */ + InternalProvisionException addSource(Object source) { + if (source == SourceProvider.UNKNOWN_SOURCE) { + return this; + } + int sz = sourcesToPrepend.size(); + if (sz > 0 && sourcesToPrepend.get(sz - 1) == source) { + // This is for when there are two identical sources added in a row. This behavior is copied + // from Errors.withSource where it can happen when an constructor/provider method throws an + // exception + return this; + } + sourcesToPrepend.add(source); + return this; + } + + ImmutableList getErrors() { + ImmutableList.Builder builder = ImmutableList.builder(); + // reverse them since sources are added as the exception propagates (so the first source is the + // last one added) + List newSources = Lists.reverse(sourcesToPrepend); + for (Message error : errors) { + builder.add(Messages.mergeSources(newSources, error)); + } + return builder.build(); + } + + /** Returns this exception convered to a ProvisionException. */ + public ProvisionException toProvisionException() { + return new ProvisionException(getErrors()); + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/LinkedBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/LinkedBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/LinkedBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/LinkedBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -16,6 +16,7 @@ package com.google.inject.internal; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; @@ -24,15 +25,19 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.LinkedKeyBinding; - import java.util.Set; -public final class LinkedBindingImpl extends BindingImpl implements LinkedKeyBinding, HasDependencies { +public final class LinkedBindingImpl extends BindingImpl + implements LinkedKeyBinding, HasDependencies { final Key targetKey; - public LinkedBindingImpl(InjectorImpl injector, Key key, Object source, - InternalFactory internalFactory, Scoping scoping, + public LinkedBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, Key targetKey) { super(injector, key, source, internalFactory, scoping); this.targetKey = targetKey; @@ -43,32 +48,39 @@ this.targetKey = targetKey; } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } + @Override public Key getLinkedKey() { return targetKey; } + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(targetKey)); } + @Override public BindingImpl withScoping(Scoping scoping) { return new LinkedBindingImpl(getSource(), getKey(), scoping, targetKey); } + @Override public BindingImpl withKey(Key key) { return new LinkedBindingImpl(getSource(), key, getScoping(), targetKey); } + @Override public void applyTo(Binder binder) { getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).to(getLinkedKey())); } - @Override public String toString() { - return Objects.toStringHelper(LinkedKeyBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(LinkedKeyBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) @@ -78,11 +90,11 @@ @Override public boolean equals(Object obj) { - if(obj instanceof LinkedBindingImpl) { - LinkedBindingImpl o = (LinkedBindingImpl)obj; + if (obj instanceof LinkedBindingImpl) { + LinkedBindingImpl o = (LinkedBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(targetKey, o.targetKey); + && getScoping().equals(o.getScoping()) + && Objects.equal(targetKey, o.targetKey); } else { return false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -16,6 +16,7 @@ package com.google.inject.internal; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; @@ -24,17 +25,20 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.ProviderKeyBinding; - import java.util.Set; -final class LinkedProviderBindingImpl - extends BindingImpl implements ProviderKeyBinding, HasDependencies, DelayedInitialize { +final class LinkedProviderBindingImpl extends BindingImpl + implements ProviderKeyBinding, HasDependencies, DelayedInitialize { final Key> providerKey; final DelayedInitialize delayedInitializer; - private LinkedProviderBindingImpl(InjectorImpl injector, Key key, Object source, - InternalFactory internalFactory, Scoping scoping, + private LinkedProviderBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, Key> providerKey, DelayedInitialize delayedInitializer) { super(injector, key, source, internalFactory, scoping); @@ -42,60 +46,79 @@ this.delayedInitializer = delayedInitializer; } - public LinkedProviderBindingImpl(InjectorImpl injector, Key key, Object source, - InternalFactory internalFactory, Scoping scoping, + public LinkedProviderBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, Key> providerKey) { this(injector, key, source, internalFactory, scoping, providerKey, null); } - LinkedProviderBindingImpl(Object source, Key key, Scoping scoping, + LinkedProviderBindingImpl( + Object source, + Key key, + Scoping scoping, Key> providerKey) { super(source, key, scoping); this.providerKey = providerKey; this.delayedInitializer = null; } - static LinkedProviderBindingImpl createWithInitializer(InjectorImpl injector, Key key, - Object source, InternalFactory internalFactory, Scoping scoping, + static LinkedProviderBindingImpl createWithInitializer( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, Key> providerKey, DelayedInitialize delayedInitializer) { - return new LinkedProviderBindingImpl(injector, key, source, internalFactory, scoping, - providerKey, delayedInitializer); + return new LinkedProviderBindingImpl( + injector, key, source, internalFactory, scoping, providerKey, delayedInitializer); } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } + @Override public Key> getProviderKey() { return providerKey; } + @Override public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { if (delayedInitializer != null) { delayedInitializer.initialize(injector, errors); } } + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(providerKey)); } + @Override public BindingImpl withScoping(Scoping scoping) { return new LinkedProviderBindingImpl(getSource(), getKey(), scoping, providerKey); } + @Override public BindingImpl withKey(Key key) { return new LinkedProviderBindingImpl(getSource(), key, getScoping(), providerKey); } + @Override public void applyTo(Binder binder) { - getScoping().applyTo(binder.withSource(getSource()) - .bind(getKey()).toProvider(getProviderKey())); + getScoping() + .applyTo(binder.withSource(getSource()).bind(getKey()).toProvider(getProviderKey())); } - @Override public String toString() { - return Objects.toStringHelper(ProviderKeyBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(ProviderKeyBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) @@ -105,11 +128,11 @@ @Override public boolean equals(Object obj) { - if(obj instanceof LinkedProviderBindingImpl) { - LinkedProviderBindingImpl o = (LinkedProviderBindingImpl)obj; + if (obj instanceof LinkedProviderBindingImpl) { + LinkedProviderBindingImpl o = (LinkedProviderBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(providerKey, o.providerKey); + && getScoping().equals(o.getScoping()) + && Objects.equal(providerKey, o.providerKey); } else { return false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ListenerBindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ListenerBindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ListenerBindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ListenerBindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,13 +30,15 @@ super(errors); } - @Override public Boolean visit(TypeListenerBinding binding) { + @Override + public Boolean visit(TypeListenerBinding binding) { injector.state.addTypeListener(binding); return true; } - - @Override public Boolean visit(ProvisionListenerBinding binding) { + + @Override + public Boolean visit(ProvisionListenerBinding binding) { injector.state.addProvisionListener(binding); return true; } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/LookupProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/LookupProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/LookupProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/LookupProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,10 +33,11 @@ super(errors); } - @Override public Boolean visit(MembersInjectorLookup lookup) { + @Override + public Boolean visit(MembersInjectorLookup lookup) { try { - MembersInjector membersInjector - = injector.membersInjectorStore.get(lookup.getType(), errors); + MembersInjector membersInjector = + injector.membersInjectorStore.get(lookup.getType(), errors); lookup.initializeDelegate(membersInjector); } catch (ErrorsException e) { errors.merge(e.getErrors()); // TODO: source @@ -45,7 +46,8 @@ return true; } - @Override public Boolean visit(ProviderLookup lookup) { + @Override + public Boolean visit(ProviderLookup lookup) { // ensure the provider can be created try { Provider provider = injector.getProviderOrThrow(lookup.getDependency(), errors); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Lookups.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Lookups.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Lookups.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Lookups.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/MembersInjectorImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/MembersInjectorImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/MembersInjectorImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/MembersInjectorImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,71 +33,77 @@ final class MembersInjectorImpl implements MembersInjector { private final TypeLiteral typeLiteral; private final InjectorImpl injector; - private final ImmutableList memberInjectors; - private final ImmutableSet> userMembersInjectors; - private final ImmutableSet> injectionListeners; - /*if[AOP]*/ - private final ImmutableList addedAspects; + // a null list means empty. Since it is common for many of these lists to be empty we can save + // some memory lookups by representing empty as null. + /* @Nullable */ private final ImmutableList memberInjectors; + /* @Nullable */ private final ImmutableList> userMembersInjectors; + /* @Nullable */ private final ImmutableList> injectionListeners; + /*if[AOP]*//* @Nullable */ private final ImmutableList addedAspects; /*end[AOP]*/ - MembersInjectorImpl(InjectorImpl injector, TypeLiteral typeLiteral, - EncounterImpl encounter, ImmutableList memberInjectors) { + MembersInjectorImpl( + InjectorImpl injector, + TypeLiteral typeLiteral, + EncounterImpl encounter, + ImmutableList memberInjectors) { this.injector = injector; this.typeLiteral = typeLiteral; - this.memberInjectors = memberInjectors; - this.userMembersInjectors = encounter.getMembersInjectors(); - this.injectionListeners = encounter.getInjectionListeners(); + this.memberInjectors = memberInjectors.isEmpty() ? null : memberInjectors; + this.userMembersInjectors = + encounter.getMembersInjectors().isEmpty() ? null : encounter.getMembersInjectors().asList(); + this.injectionListeners = + encounter.getInjectionListeners().isEmpty() + ? null + : encounter.getInjectionListeners().asList(); /*if[AOP]*/ - this.addedAspects = encounter.getAspects(); + this.addedAspects = encounter.getAspects().isEmpty() ? null : encounter.getAspects(); /*end[AOP]*/ } public ImmutableList getMemberInjectors() { - return memberInjectors; + return memberInjectors == null ? ImmutableList.of() : memberInjectors; } + @Override public void injectMembers(T instance) { - Errors errors = new Errors(typeLiteral); + TypeLiteral localTypeLiteral = typeLiteral; try { - injectAndNotify(instance, errors, null, null, typeLiteral, false); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); + injectAndNotify(instance, null, null, localTypeLiteral, false); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(localTypeLiteral).toProvisionException(); } - - errors.throwProvisionExceptionIfErrorsExist(); } - void injectAndNotify(final T instance, - final Errors errors, + void injectAndNotify( + final T instance, final Key key, // possibly null! final ProvisionListenerStackCallback provisionCallback, // possibly null! final Object source, - final boolean toolableOnly) throws ErrorsException { + final boolean toolableOnly) + throws InternalProvisionException { if (instance == null) { return; } - - injector.callInContext(new ContextualCallable() { - @Override - public Void call(final InternalContext context) throws ErrorsException { - context.pushState(key, source); - try { - if (provisionCallback != null && provisionCallback.hasListeners()) { - provisionCallback.provision(errors, context, new ProvisionCallback() { - @Override public T call() { - injectMembers(instance, errors, context, toolableOnly); + final InternalContext context = injector.enterContext(); + context.pushState(key, source); + try { + if (provisionCallback != null && provisionCallback.hasListeners()) { + provisionCallback.provision( + context, + new ProvisionCallback() { + @Override + public T call() throws InternalProvisionException { + injectMembers(instance, context, toolableOnly); return instance; } }); - } else { - injectMembers(instance, errors, context, toolableOnly); - } - } finally { - context.popState(); - } - return null; + } else { + injectMembers(instance, context, toolableOnly); } - }); + } finally { + context.popState(); + context.close(); + } // TODO: We *could* notify listeners too here, // but it's not clear if we want to. There's no way to know @@ -107,59 +113,80 @@ // if atleast one InjectionPoint was toolable, in which case // the above callInContext could return 'true' if it injected // anything.) - if(!toolableOnly) { - notifyListeners(instance, errors); + if (!toolableOnly) { + notifyListeners(instance); } } - void notifyListeners(T instance, Errors errors) throws ErrorsException { - int numErrorsBefore = errors.size(); - for (InjectionListener injectionListener : injectionListeners) { + void notifyListeners(T instance) throws InternalProvisionException { + ImmutableList> localInjectionListeners = injectionListeners; + if (localInjectionListeners == null) { + // no listeners + return; + } + // optimization: use manual for/each to save allocating an iterator here + for (int i = 0; i < localInjectionListeners.size(); i++) { + InjectionListener injectionListener = localInjectionListeners.get(i); try { injectionListener.afterInjection(instance); } catch (RuntimeException e) { - errors.errorNotifyingInjectionListener(injectionListener, typeLiteral, e); + throw InternalProvisionException.errorNotifyingInjectionListener( + injectionListener, typeLiteral, e); } } - errors.throwIfNewErrors(numErrorsBefore); } - void injectMembers(T t, Errors errors, InternalContext context, boolean toolableOnly) { - // optimization: use manual for/each to save allocating an iterator here - for (int i = 0, size = memberInjectors.size(); i < size; i++) { - SingleMemberInjector injector = memberInjectors.get(i); - if(!toolableOnly || injector.getInjectionPoint().isToolable()) { - injector.inject(errors, context, t); + void injectMembers(T t, InternalContext context, boolean toolableOnly) + throws InternalProvisionException { + ImmutableList localMembersInjectors = memberInjectors; + if (localMembersInjectors != null) { + // optimization: use manual for/each to save allocating an iterator here + for (int i = 0, size = localMembersInjectors.size(); i < size; i++) { + SingleMemberInjector injector = localMembersInjectors.get(i); + if (!toolableOnly || injector.getInjectionPoint().isToolable()) { + injector.inject(context, t); + } } } // TODO: There's no way to know if a user's MembersInjector wants toolable injections. - if(!toolableOnly) { - for (MembersInjector userMembersInjector : userMembersInjectors) { - try { - userMembersInjector.injectMembers(t); - } catch (RuntimeException e) { - errors.errorInUserInjector(userMembersInjector, typeLiteral, e); + if (!toolableOnly) { + ImmutableList> localUsersMembersInjectors = userMembersInjectors; + if (localUsersMembersInjectors != null) { + // optimization: use manual for/each to save allocating an iterator here + for (int i = 0; i < localUsersMembersInjectors.size(); i++) { + MembersInjector userMembersInjector = localUsersMembersInjectors.get(i); + try { + userMembersInjector.injectMembers(t); + } catch (RuntimeException e) { + throw InternalProvisionException.errorInUserInjector( + userMembersInjector, typeLiteral, e); + } } } } } - @Override public String toString() { + @Override + public String toString() { return "MembersInjector<" + typeLiteral + ">"; } public ImmutableSet getInjectionPoints() { - ImmutableSet.Builder builder = ImmutableSet.builder(); - for (SingleMemberInjector memberInjector : memberInjectors) { - builder.add(memberInjector.getInjectionPoint()); + ImmutableList localMemberInjectors = memberInjectors; + if (localMemberInjectors != null) { + ImmutableSet.Builder builder = ImmutableSet.builder(); + for (SingleMemberInjector memberInjector : localMemberInjectors) { + builder.add(memberInjector.getInjectionPoint()); + } + return builder.build(); } - return builder.build(); + return ImmutableSet.of(); } /*if[AOP]*/ public ImmutableList getAddedAspects() { - return addedAspects; + return addedAspects == null ? ImmutableList.of() : addedAspects; } /*end[AOP]*/ } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/MembersInjectorStore.java sisu-guice-4.2.0/core/src/com/google/inject/internal/MembersInjectorStore.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/MembersInjectorStore.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/MembersInjectorStore.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.TypeListener; import com.google.inject.spi.TypeListenerBinding; - import java.lang.reflect.Field; import java.util.List; import java.util.Set; @@ -38,16 +37,16 @@ private final InjectorImpl injector; private final ImmutableList typeListenerBindings; - private final FailableCache, MembersInjectorImpl> cache - = new FailableCache, MembersInjectorImpl>() { - @Override protected MembersInjectorImpl create(TypeLiteral type, Errors errors) - throws ErrorsException { - return createWithListeners(type, errors); - } - }; + private final FailableCache, MembersInjectorImpl> cache = + new FailableCache, MembersInjectorImpl>() { + @Override + protected MembersInjectorImpl create(TypeLiteral type, Errors errors) + throws ErrorsException { + return createWithListeners(type, errors); + } + }; - MembersInjectorStore(InjectorImpl injector, - List typeListenerBindings) { + MembersInjectorStore(InjectorImpl injector, List typeListenerBindings) { this.injector = injector; this.typeListenerBindings = ImmutableList.copyOf(typeListenerBindings); } @@ -60,9 +59,7 @@ return !typeListenerBindings.isEmpty(); } - /** - * Returns a new complete members injector with injection listeners registered. - */ + /** Returns a new complete members injector with injection listeners registered. */ @SuppressWarnings("unchecked") // the MembersInjector type always agrees with the passed type public MembersInjectorImpl get(TypeLiteral key, Errors errors) throws ErrorsException { return (MembersInjectorImpl) cache.get(key, errors); @@ -74,16 +71,14 @@ * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is * necessary.) - * - * Returns true if the type was stored in the cache, false otherwise. + * + *

    Returns true if the type was stored in the cache, false otherwise. */ boolean remove(TypeLiteral type) { return cache.remove(type); } - /** - * Creates a new members injector and attaches both injection listeners and method aspects. - */ + /** Creates a new members injector and attaches both injection listeners and method aspects. */ private MembersInjectorImpl createWithListeners(TypeLiteral type, Errors errors) throws ErrorsException { int numErrorsBefore = errors.size(); @@ -98,7 +93,7 @@ ImmutableList injectors = getInjectors(injectionPoints, errors); errors.throwIfNewErrors(numErrorsBefore); - EncounterImpl encounter = new EncounterImpl(errors, injector.lookups); + EncounterImpl encounter = new EncounterImpl<>(errors, injector.lookups); Set alreadySeenListeners = Sets.newHashSet(); for (TypeListenerBinding binding : typeListenerBindings) { TypeListener typeListener = binding.getListener(); @@ -117,20 +112,20 @@ return new MembersInjectorImpl(injector, type, encounter, injectors); } - /** - * Returns the injectors for the specified injection points. - */ + /** Returns the injectors for the specified injection points. */ ImmutableList getInjectors( Set injectionPoints, Errors errors) { List injectors = Lists.newArrayList(); for (InjectionPoint injectionPoint : injectionPoints) { try { - Errors errorsForMember = injectionPoint.isOptional() - ? new Errors(injectionPoint) - : errors.withSource(injectionPoint); - SingleMemberInjector injector = injectionPoint.getMember() instanceof Field - ? new SingleFieldInjector(this.injector, injectionPoint, errorsForMember) - : new SingleMethodInjector(this.injector, injectionPoint, errorsForMember); + Errors errorsForMember = + injectionPoint.isOptional() + ? new Errors(injectionPoint) + : errors.withSource(injectionPoint); + SingleMemberInjector injector = + injectionPoint.getMember() instanceof Field + ? new SingleFieldInjector(this.injector, injectionPoint, errorsForMember) + : new SingleMethodInjector(this.injector, injectionPoint, errorsForMember); injectors.add(injector); } catch (ErrorsException ignoredForNow) { // ignored for now diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/MessageProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/MessageProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/MessageProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/MessageProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.inject.Guice; import com.google.inject.spi.Message; - import java.util.logging.Level; import java.util.logging.Logger; @@ -36,10 +35,12 @@ super(errors); } - @Override public Boolean visit(Message message) { + @Override + public Boolean visit(Message message) { if (message.getCause() != null) { String rootMessage = getRootMessage(message.getCause()); - logger.log(Level.INFO, + logger.log( + Level.INFO, "An exception was caught and reported. Message: " + rootMessage, message.getCause()); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Messages.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Messages.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Messages.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Messages.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.inject.internal; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Equivalence; +import com.google.common.base.Objects; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.util.Classes; +import com.google.inject.internal.util.StackTraceElements; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.ElementSource; +import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.Message; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.util.Arrays; +import java.util.Collection; +import java.util.Formatter; +import java.util.List; +import java.util.Map; + +/** Utility methods for {@link Message} objects */ +public final class Messages { + private Messages() {} + + /** Prepends the list of sources to the given {@link Message} */ + static Message mergeSources(List sources, Message message) { + List messageSources = message.getSources(); + // It is possible that the end of getSources() and the beginning of message.getSources() are + // equivalent, in this case we should drop the repeated source when joining the lists. The + // most likely scenario where this would happen is when a scoped binding throws an exception, + // due to the fact that InternalFactoryToProviderAdapter applies the binding source when + // merging errors. + if (!sources.isEmpty() + && !messageSources.isEmpty() + && Objects.equal(messageSources.get(0), sources.get(sources.size() - 1))) { + messageSources = messageSources.subList(1, messageSources.size()); + } + return new Message( + ImmutableList.builder().addAll(sources).addAll(messageSources).build(), + message.getMessage(), + message.getCause()); + } + + /** + * Calls {@link String#format} after converting the arguments using some standard guice formatting + * for {@link Key}, {@link Class} and {@link Member} objects. + */ + public static String format(String messageFormat, Object... arguments) { + for (int i = 0; i < arguments.length; i++) { + arguments[i] = convert(arguments[i]); + } + return String.format(messageFormat, arguments); + } + + /** Returns the formatted message for an exception with the specified messages. */ + public static String formatMessages(String heading, Collection errorMessages) { + Formatter fmt = new Formatter().format(heading).format(":%n%n"); + int index = 1; + boolean displayCauses = getOnlyCause(errorMessages) == null; + + Map, Integer> causes = Maps.newHashMap(); + for (Message errorMessage : errorMessages) { + int thisIdx = index++; + fmt.format("%s) %s%n", thisIdx, errorMessage.getMessage()); + + List dependencies = errorMessage.getSources(); + for (int i = dependencies.size() - 1; i >= 0; i--) { + Object source = dependencies.get(i); + formatSource(fmt, source); + } + + Throwable cause = errorMessage.getCause(); + if (displayCauses && cause != null) { + Equivalence.Wrapper causeEquivalence = ThrowableEquivalence.INSTANCE.wrap(cause); + if (!causes.containsKey(causeEquivalence)) { + causes.put(causeEquivalence, thisIdx); + fmt.format("Caused by: %s", Throwables.getStackTraceAsString(cause)); + } else { + int causeIdx = causes.get(causeEquivalence); + fmt.format( + "Caused by: %s (same stack trace as error #%s)", + cause.getClass().getName(), causeIdx); + } + } + + fmt.format("%n"); + } + + if (errorMessages.size() == 1) { + fmt.format("1 error"); + } else { + fmt.format("%s errors", errorMessages.size()); + } + + return fmt.toString(); + } + + /** + * Creates a new Message without a cause. + * + * @param messageFormat Format string + * @param arguments format string arguments + */ + public static Message create(String messageFormat, Object... arguments) { + return create(null, messageFormat, arguments); + } + + /** + * Creates a new Message with the given cause. + * + * @param cause The exception that caused the error + * @param messageFormat Format string + * @param arguments format string arguments + */ + public static Message create(Throwable cause, String messageFormat, Object... arguments) { + return create(cause, ImmutableList.of(), messageFormat, arguments); + } + + /** + * Creates a new Message with the given cause and a binding source stack. + * + * @param cause The exception that caused the error + * @param sources The binding sources for the source stack + * @param messageFormat Format string + * @param arguments format string arguments + */ + public static Message create( + Throwable cause, List sources, String messageFormat, Object... arguments) { + String message = format(messageFormat, arguments); + return new Message(sources, message, cause); + } + + /** Formats an object in a user friendly way. */ + static Object convert(Object o) { + ElementSource source = null; + if (o instanceof ElementSource) { + source = (ElementSource) o; + o = source.getDeclaringSource(); + } + return convert(o, source); + } + + static Object convert(Object o, ElementSource source) { + for (Converter converter : converters) { + if (converter.appliesTo(o)) { + return appendModules(converter.convert(o), source); + } + } + return appendModules(o, source); + } + + private static Object appendModules(Object source, ElementSource elementSource) { + String modules = moduleSourceString(elementSource); + if (modules.length() == 0) { + return source; + } else { + return source + modules; + } + } + + private static String moduleSourceString(ElementSource elementSource) { + // if we only have one module (or don't know what they are), then don't bother + // reporting it, because the source already is going to report exactly that module. + if (elementSource == null) { + return ""; + } + List modules = Lists.newArrayList(elementSource.getModuleClassNames()); + // Insert any original element sources w/ module info into the path. + while (elementSource.getOriginalElementSource() != null) { + elementSource = elementSource.getOriginalElementSource(); + modules.addAll(0, elementSource.getModuleClassNames()); + } + if (modules.size() <= 1) { + return ""; + } + + // Ideally we'd do: + // return Joiner.on(" -> ") + // .appendTo(new StringBuilder(" (via modules: "), Lists.reverse(modules)) + // .append(")").toString(); + // ... but for some reason we can't find Lists.reverse, so do it the boring way. + StringBuilder builder = new StringBuilder(" (via modules: "); + for (int i = modules.size() - 1; i >= 0; i--) { + builder.append(modules.get(i)); + if (i != 0) { + builder.append(" -> "); + } + } + builder.append(")"); + return builder.toString(); + } + + static void formatSource(Formatter formatter, Object source) { + ElementSource elementSource = null; + if (source instanceof ElementSource) { + elementSource = (ElementSource) source; + source = elementSource.getDeclaringSource(); + } + formatSource(formatter, source, elementSource); + } + + static void formatSource(Formatter formatter, Object source, ElementSource elementSource) { + String modules = moduleSourceString(elementSource); + if (source instanceof Dependency) { + Dependency dependency = (Dependency) source; + InjectionPoint injectionPoint = dependency.getInjectionPoint(); + if (injectionPoint != null) { + formatInjectionPoint(formatter, dependency, injectionPoint, elementSource); + } else { + formatSource(formatter, dependency.getKey(), elementSource); + } + + } else if (source instanceof InjectionPoint) { + formatInjectionPoint(formatter, null, (InjectionPoint) source, elementSource); + + } else if (source instanceof Class) { + formatter.format(" at %s%s%n", StackTraceElements.forType((Class) source), modules); + + } else if (source instanceof Member) { + formatter.format(" at %s%s%n", StackTraceElements.forMember((Member) source), modules); + + } else if (source instanceof TypeLiteral) { + formatter.format(" while locating %s%s%n", source, modules); + + } else if (source instanceof Key) { + Key key = (Key) source; + formatter.format(" while locating %s%n", convert(key, elementSource)); + + } else if (source instanceof Thread) { + formatter.format(" in thread %s%n", source); + + } else { + formatter.format(" at %s%s%n", source, modules); + } + } + + private static void formatInjectionPoint( + Formatter formatter, + Dependency dependency, + InjectionPoint injectionPoint, + ElementSource elementSource) { + Member member = injectionPoint.getMember(); + Class memberType = Classes.memberType(member); + + if (memberType == Field.class) { + dependency = injectionPoint.getDependencies().get(0); + formatter.format(" while locating %s%n", convert(dependency.getKey(), elementSource)); + formatter.format(" for field at %s%n", StackTraceElements.forMember(member)); + + } else if (dependency != null) { + formatter.format(" while locating %s%n", convert(dependency.getKey(), elementSource)); + formatter.format(" for %s%n", formatParameter(dependency)); + + } else { + formatSource(formatter, injectionPoint.getMember()); + } + } + + static String formatParameter(Dependency dependency) { + int ordinal = dependency.getParameterIndex() + 1; + return String.format( + "the %s%s parameter of %s", + ordinal, + getOrdinalSuffix(ordinal), + StackTraceElements.forMember(dependency.getInjectionPoint().getMember())); + } + + /** + * Maps {@code 1} to the string {@code "1st"} ditto for all non-negative numbers + * + * @see + * https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers + */ + private static String getOrdinalSuffix(int ordinal) { + // negative ordinals don't make sense, we allow zero though because we are programmers + checkArgument(ordinal >= 0); + if ((ordinal / 10) % 10 == 1) { + // all the 'teens' are weird + return "th"; + } else { + // could use a lookup table? any better? + switch (ordinal % 10) { + case 1: + return "st"; + case 2: + return "nd"; + case 3: + return "rd"; + default: + return "th"; + } + } + } + + private abstract static class Converter { + + final Class type; + + Converter(Class type) { + this.type = type; + } + + boolean appliesTo(Object o) { + return o != null && type.isAssignableFrom(o.getClass()); + } + + String convert(Object o) { + return toString(type.cast(o)); + } + + abstract String toString(T t); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) // rawtypes aren't avoidable + private static final Collection> converters = + ImmutableList.of( + new Converter(Class.class) { + @Override + public String toString(Class c) { + return c.getName(); + } + }, + new Converter(Member.class) { + @Override + public String toString(Member member) { + return Classes.toString(member); + } + }, + new Converter(Key.class) { + @Override + public String toString(Key key) { + if (key.getAnnotationType() != null) { + return key.getTypeLiteral() + + " annotated with " + + (key.getAnnotation() != null ? key.getAnnotation() : key.getAnnotationType()); + } else { + return key.getTypeLiteral().toString(); + } + } + }); + + /** + * Returns the cause throwable if there is exactly one cause in {@code messages}. If there are + * zero or multiple messages with causes, null is returned. + */ + public static Throwable getOnlyCause(Collection messages) { + Throwable onlyCause = null; + for (Message message : messages) { + Throwable messageCause = message.getCause(); + if (messageCause == null) { + continue; + } + + if (onlyCause != null && !ThrowableEquivalence.INSTANCE.equivalent(onlyCause, messageCause)) { + return null; + } + + onlyCause = messageCause; + } + + return onlyCause; + } + + private static final class ThrowableEquivalence extends Equivalence { + static final ThrowableEquivalence INSTANCE = new ThrowableEquivalence(); + + @Override + protected boolean doEquivalent(Throwable a, Throwable b) { + return a.getClass().equals(b.getClass()) + && Objects.equal(a.getMessage(), b.getMessage()) + && Arrays.equals(a.getStackTrace(), b.getStackTrace()) + && equivalent(a.getCause(), b.getCause()); + } + + @Override + protected int doHash(Throwable t) { + return Objects.hashCode(t.getClass().hashCode(), t.getMessage(), hash(t.getCause())); + } + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/MethodAspect.java sisu-guice-4.2.0/core/src/com/google/inject/internal/MethodAspect.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/MethodAspect.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/MethodAspect.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,12 +19,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.inject.matcher.Matcher; - -import org.aopalliance.intercept.MethodInterceptor; - import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; +import org.aopalliance.intercept.MethodInterceptor; /** * Ties a matcher to a method interceptor. @@ -44,15 +42,19 @@ * annotatedWith(Transactional.class)}. * @param interceptors to apply */ - MethodAspect(Matcher> classMatcher, - Matcher methodMatcher, List interceptors) { + MethodAspect( + Matcher> classMatcher, + Matcher methodMatcher, + List interceptors) { this.classMatcher = checkNotNull(classMatcher, "class matcher"); this.methodMatcher = checkNotNull(methodMatcher, "method matcher"); this.interceptors = checkNotNull(interceptors, "interceptors"); } - MethodAspect(Matcher> classMatcher, - Matcher methodMatcher, MethodInterceptor... interceptors) { + MethodAspect( + Matcher> classMatcher, + Matcher methodMatcher, + MethodInterceptor... interceptors) { this(classMatcher, methodMatcher, Arrays.asList(interceptors)); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,8 @@ super(errors); } - @Override public Boolean visit(ModuleAnnotatedMethodScannerBinding command) { + @Override + public Boolean visit(ModuleAnnotatedMethodScannerBinding command) { injector.state.addScanner(command); return true; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/MoreTypes.java sisu-guice-4.2.0/core/src/com/google/inject/internal/MoreTypes.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/MoreTypes.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/MoreTypes.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.google.inject.internal; import static com.google.common.base.Preconditions.checkArgument; @@ -26,7 +25,6 @@ import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.util.Types; - import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; @@ -36,12 +34,10 @@ import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.Arrays; -import java.util.Map; import java.util.NoSuchElementException; /** - * Static methods for working with types that we aren't publishing in the - * public {@code Types} API. + * Static methods for working with types that we aren't publishing in the public {@code Types} API. * * @author jessewilson@google.com (Jesse Wilson) */ @@ -51,8 +47,8 @@ private MoreTypes() {} - private static final Map, TypeLiteral> PRIMITIVE_TO_WRAPPER - = new ImmutableMap.Builder, TypeLiteral>() + private static final ImmutableMap, TypeLiteral> PRIMITIVE_TO_WRAPPER = + new ImmutableMap.Builder, TypeLiteral>() .put(TypeLiteral.get(boolean.class), TypeLiteral.get(Boolean.class)) .put(TypeLiteral.get(byte.class), TypeLiteral.get(Byte.class)) .put(TypeLiteral.get(short.class), TypeLiteral.get(Short.class)) @@ -65,13 +61,12 @@ .build(); /** - * Returns a key that doesn't hold any references to parent classes. - * This is necessary for anonymous keys, so ensure we don't hold a ref - * to the containing module (or class) forever. + * Returns a key that doesn't hold any references to parent classes. This is necessary for + * anonymous keys, so ensure we don't hold a ref to the containing module (or class) forever. */ public static Key canonicalizeKey(Key key) { // If we know this isn't a subclass, return as-is. - // Otherwise, recreate the key to avoid the subclass + // Otherwise, recreate the key to avoid the subclass if (key.getClass() == Key.class) { return key; } else if (key.getAnnotation() != null) { @@ -106,8 +101,9 @@ // the following casts are generally unsafe, but com.google.inject.Provider extends // javax.inject.Provider and is covariant @SuppressWarnings("unchecked") - TypeLiteral guiceProviderType = (TypeLiteral) TypeLiteral.get( - Types.providerOf(parameterizedType.getActualTypeArguments()[0])); + TypeLiteral guiceProviderType = + (TypeLiteral) + TypeLiteral.get(Types.providerOf(parameterizedType.getActualTypeArguments()[0])); return guiceProviderType; } @@ -129,9 +125,7 @@ return recreated; } - /** - * Returns true if {@code type} is free from type variables. - */ + /** Returns true if {@code type} is free from type variables. */ private static boolean isFullySpecified(Type type) { if (type instanceof Class) { return true; @@ -139,7 +133,7 @@ } else if (type instanceof CompositeType) { return ((CompositeType) type).isFullySpecified(); - } else if (type instanceof TypeVariable){ + } else if (type instanceof TypeVariable) { return false; } else { @@ -148,9 +142,8 @@ } /** - * Returns a type that is functionally equal but not necessarily equal - * according to {@link Object#equals(Object) Object.equals()}. The returned - * type is {@link Serializable}. + * Returns a type that is functionally equal but not necessarily equal according to {@link + * Object#equals(Object) Object.equals()}. The returned type is {@link Serializable}. */ public static Type canonicalize(Type type) { if (type instanceof Class) { @@ -162,8 +155,8 @@ } else if (type instanceof ParameterizedType) { ParameterizedType p = (ParameterizedType) type; - return new ParameterizedTypeImpl(p.getOwnerType(), - p.getRawType(), p.getActualTypeArguments()); + return new ParameterizedTypeImpl( + p.getOwnerType(), p.getRawType(), p.getActualTypeArguments()); } else if (type instanceof GenericArrayType) { GenericArrayType g = (GenericArrayType) type; @@ -191,28 +184,33 @@ // Neal isn't either but suspects some pathological case related // to nested classes exists. Type rawType = parameterizedType.getRawType(); - checkArgument(rawType instanceof Class, - "Expected a Class, but <%s> is of type %s", type, type.getClass().getName()); + checkArgument( + rawType instanceof Class, + "Expected a Class, but <%s> is of type %s", + type, + type.getClass().getName()); return (Class) rawType; } else if (type instanceof GenericArrayType) { - Type componentType = ((GenericArrayType)type).getGenericComponentType(); + Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); - } else if (type instanceof TypeVariable) { + } else if (type instanceof TypeVariable || type instanceof WildcardType) { // we could use the variable's bounds, but that'll won't work if there are multiple. - // having a raw type that's more general than necessary is okay + // having a raw type that's more general than necessary is okay return Object.class; } else { - throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " - + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName()); + throw new IllegalArgumentException( + "Expected a Class, ParameterizedType, or " + + "GenericArrayType, but <" + + type + + "> is of type " + + type.getClass().getName()); } } - /** - * Returns true if {@code a} and {@code b} are equal. - */ + /** Returns true if {@code a} and {@code b} are equal. */ public static boolean equals(Type a, Type b) { if (a == b) { // also handles (a == null && b == null) @@ -278,8 +276,8 @@ /** * Returns the generic supertype for {@code type}. For example, given a class {@code IntegerSet}, - * the result for when supertype is {@code Set.class} is {@code Set} and the result - * when the supertype is {@code Collection.class} is {@code Collection}. + * the result for when supertype is {@code Set.class} is {@code Set} and the result when + * the supertype is {@code Collection.class} is {@code Collection}. */ public static Type getGenericSupertype(Type type, Class rawType, Class toResolve) { if (toResolve == rawType) { @@ -347,9 +345,7 @@ */ private static Class declaringClassOf(TypeVariable typeVariable) { GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration(); - return genericDeclaration instanceof Class - ? (Class) genericDeclaration - : null; + return genericDeclaration instanceof Class ? (Class) genericDeclaration : null; } public static class ParameterizedTypeImpl @@ -372,18 +368,22 @@ } } + @Override public Type[] getActualTypeArguments() { return typeArguments.clone(); } + @Override public Type getRawType() { return rawType; } + @Override public Type getOwnerType() { return ownerType; } + @Override public boolean isFullySpecified() { if (ownerType != null && !MoreTypes.isFullySpecified(ownerType)) { return false; @@ -402,18 +402,19 @@ return true; } - @Override public boolean equals(Object other) { + @Override + public boolean equals(Object other) { return other instanceof ParameterizedType && MoreTypes.equals(this, (ParameterizedType) other); } - @Override public int hashCode() { - return Arrays.hashCode(typeArguments) - ^ rawType.hashCode() - ^ hashCodeOrZero(ownerType); + @Override + public int hashCode() { + return Arrays.hashCode(typeArguments) ^ rawType.hashCode() ^ hashCodeOrZero(ownerType); } - @Override public String toString() { + @Override + public String toString() { StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1)); stringBuilder.append(typeToString(rawType)); @@ -431,10 +432,14 @@ private static void ensureOwnerType(Type ownerType, Type rawType) { if (rawType instanceof Class) { Class rawTypeAsClass = (Class) rawType; - checkArgument(ownerType != null || rawTypeAsClass.getEnclosingClass() == null, - "No owner type for enclosed %s", rawType); - checkArgument(ownerType == null || rawTypeAsClass.getEnclosingClass() != null, - "Owner type for unenclosed %s", rawType); + checkArgument( + ownerType != null || rawTypeAsClass.getEnclosingClass() == null, + "No owner type for enclosed %s", + rawType); + checkArgument( + ownerType == null || rawTypeAsClass.getEnclosingClass() != null, + "Owner type for unenclosed %s", + rawType); } } @@ -449,24 +454,28 @@ this.componentType = canonicalize(componentType); } + @Override public Type getGenericComponentType() { return componentType; } + @Override public boolean isFullySpecified() { return MoreTypes.isFullySpecified(componentType); } - @Override public boolean equals(Object o) { - return o instanceof GenericArrayType - && MoreTypes.equals(this, (GenericArrayType) o); + @Override + public boolean equals(Object o) { + return o instanceof GenericArrayType && MoreTypes.equals(this, (GenericArrayType) o); } - @Override public int hashCode() { + @Override + public int hashCode() { return componentType.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return typeToString(componentType) + "[]"; } @@ -474,9 +483,9 @@ } /** - * The WildcardType interface supports multiple upper bounds and multiple - * lower bounds. We only support what the Java 6 language needs - at most one - * bound. If a lower bound is set, the upper bound must be Object.class. + * The WildcardType interface supports multiple upper bounds and multiple lower bounds. We only + * support what the Java 6 language needs - at most one bound. If a lower bound is set, the upper + * bound must be Object.class. */ public static class WildcardTypeImpl implements WildcardType, Serializable, CompositeType { private final Type upperBound; @@ -501,31 +510,35 @@ } } + @Override public Type[] getUpperBounds() { - return new Type[] { upperBound }; + return new Type[] {upperBound}; } + @Override public Type[] getLowerBounds() { - return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY; + return lowerBound != null ? new Type[] {lowerBound} : EMPTY_TYPE_ARRAY; } + @Override public boolean isFullySpecified() { return MoreTypes.isFullySpecified(upperBound) && (lowerBound == null || MoreTypes.isFullySpecified(lowerBound)); } - @Override public boolean equals(Object other) { - return other instanceof WildcardType - && MoreTypes.equals(this, (WildcardType) other); + @Override + public boolean equals(Object other) { + return other instanceof WildcardType && MoreTypes.equals(this, (WildcardType) other); } - @Override public int hashCode() { - // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds()); - return (lowerBound != null ? 31 + lowerBound.hashCode() : 1) - ^ (31 + upperBound.hashCode()); + @Override + public int hashCode() { + // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds()); + return (lowerBound != null ? 31 + lowerBound.hashCode() : 1) ^ (31 + upperBound.hashCode()); } - @Override public String toString() { + @Override + public String toString() { if (lowerBound != null) { return "? super " + typeToString(lowerBound); } else if (upperBound == Object.class) { @@ -539,8 +552,11 @@ } private static void checkNotPrimitive(Type type, String use) { - checkArgument(!(type instanceof Class) || !((Class) type).isPrimitive(), - "Primitive types are not allowed in %s: %s", use, type); + checkArgument( + !(type instanceof Class) || !((Class) type).isPrimitive(), + "Primitive types are not allowed in %s: %s", + use, + type); } /** A type formed from other types, such as arrays, parameterized types or wildcard types */ diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Nullability.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Nullability.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Nullability.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Nullability.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,14 +21,13 @@ /** * Whether a member supports null values injected. * - *

    Support for {@code Nullable} annotations in Guice is loose. - * Any annotation type whose simplename is "Nullable" is sufficient to indicate - * support for null values injected. - * - *

    This allows support for JSR-305's - * - * javax.annotation.meta.Nullable annotation and IntelliJ IDEA's - * + *

    Support for {@code Nullable} annotations in Guice is loose. Any annotation type whose + * simplename is "Nullable" is sufficient to indicate support for null values injected. + * + *

    This allows support for JSR-305's + * javax.annotation.meta.Nullable annotation and IntelliJ IDEA's * org.jetbrains.annotations.Nullable. * * @author jessewilson@google.com (Jesse Wilson) @@ -37,7 +36,7 @@ private Nullability() {} public static boolean allowsNull(Annotation[] annotations) { - for(Annotation a : annotations) { + for (Annotation a : annotations) { Class type = a.annotationType(); if ("Nullable".equals(type.getSimpleName())) { return true; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/internal/package-info.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,8 +14,5 @@ * limitations under the License. */ -/** - * Guice (sounds like like "juice") - */ - -package com.google.inject.internal; \ No newline at end of file +/** Guice (sounds like "juice") */ +package com.google.inject.internal; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/PrivateElementProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/PrivateElementProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/PrivateElementProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/PrivateElementProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.common.collect.Lists; import com.google.inject.spi.PrivateElements; - import java.util.List; /** @@ -34,10 +33,10 @@ super(errors); } - @Override public Boolean visit(PrivateElements privateElements) { - InjectorShell.Builder builder = new InjectorShell.Builder() - .parent(injector) - .privateElements(privateElements); + @Override + public Boolean visit(PrivateElements privateElements) { + InjectorShell.Builder builder = + new InjectorShell.Builder().parent(injector).privateElements(privateElements); injectorShellBuilders.add(builder); return true; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/PrivateElementsImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/PrivateElementsImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/PrivateElementsImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/PrivateElementsImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; @@ -32,14 +32,11 @@ import com.google.inject.spi.Element; import com.google.inject.spi.ElementVisitor; import com.google.inject.spi.PrivateElements; - import java.util.List; import java.util.Map; import java.util.Set; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public final class PrivateElementsImpl implements PrivateElements { /* @@ -58,16 +55,19 @@ /** lazily instantiated */ private ImmutableMap, Object> exposedKeysToSources; + private Injector injector; public PrivateElementsImpl(Object source) { this.source = checkNotNull(source, "source"); } + @Override public Object getSource() { return source; } + @Override public List getElements() { if (elements == null) { elements = ImmutableList.copyOf(elementsMutable); @@ -77,6 +77,7 @@ return elements; } + @Override public Injector getInjector() { return injector; } @@ -86,6 +87,7 @@ this.injector = checkNotNull(injector, "injector"); } + @Override public Set> getExposedKeys() { if (exposedKeysToSources == null) { Map, Object> exposedKeysToSourcesMutable = Maps.newLinkedHashMap(); @@ -99,6 +101,7 @@ return exposedKeysToSources.keySet(); } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } @@ -111,6 +114,7 @@ exposureBuilders.add(exposureBuilder); } + @Override public void applyTo(Binder binder) { PrivateBinder privateBinder = binder.withSource(source).newPrivateBinder(); @@ -124,6 +128,7 @@ } } + @Override public Object getExposedSource(Key key) { getExposedKeys(); // ensure exposedKeysToSources is populated Object source = exposedKeysToSources.get(key); @@ -131,8 +136,9 @@ return source; } - @Override public String toString() { - return Objects.toStringHelper(PrivateElements.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(PrivateElements.class) .add("exposedKeys", getExposedKeys()) .add("source", getSource()) .toString(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProcessedBindingData.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProcessedBindingData.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProcessedBindingData.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProcessedBindingData.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,38 +17,58 @@ package com.google.inject.internal; import com.google.common.collect.Lists; - import java.util.List; /** - * Keeps track of creation listeners & uninitialized bindings, - * so they can be processed after bindings are recorded. - * + * Keeps track of creation listeners & uninitialized bindings, so they can be processed after + * bindings are recorded. + * * @author sameb@google.com (Sam Berlin) */ class ProcessedBindingData { - + private final List creationListeners = Lists.newArrayList(); private final List uninitializedBindings = Lists.newArrayList(); - + private final List delayedUninitializedBindings = Lists.newArrayList(); + void addCreationListener(CreationListener listener) { creationListeners.add(listener); } - + void addUninitializedBinding(Runnable runnable) { uninitializedBindings.add(runnable); } - + + void addDelayedUninitializedBinding(Runnable runnable) { + delayedUninitializedBindings.add(runnable); + } + + /** Initialize bindings. This may be done eagerly */ void initializeBindings() { for (Runnable initializer : uninitializedBindings) { initializer.run(); } } + /** + * Runs creation listeners. + * + *

    TODO(lukes): figure out exactly why this case exists. + */ void runCreationListeners(Errors errors) { for (CreationListener creationListener : creationListeners) { creationListener.notify(errors); } } + /** + * Initialized bindings that need to be delayed until after all injection points and other + * bindings are processed. The main current usecase for this is resolving Optional dependencies + * for OptionalBinder bindings. + */ + void initializeDelayedBindings() { + for (Runnable initializer : delayedUninitializedBindings) { + initializer.run(); + } + } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvidedByInternalFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvidedByInternalFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvidedByInternalFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvidedByInternalFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,79 +14,85 @@ * limitations under the License. */ - package com.google.inject.internal; -import static com.google.common.base.Preconditions.checkState; - import com.google.inject.Key; import com.google.inject.ProvidedBy; -import com.google.inject.Provider; import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.spi.Dependency; +import javax.inject.Provider; /** * An {@link InternalFactory} for {@literal @}{@link ProvidedBy} bindings. - * + * * @author sameb@google.com (Sam Berlin) */ -class ProvidedByInternalFactory extends ProviderInternalFactory - implements DelayedInitialize { - +class ProvidedByInternalFactory extends ProviderInternalFactory implements DelayedInitialize { + private final Class rawType; private final Class> providerType; private final Key> providerKey; private BindingImpl> providerBinding; private ProvisionListenerStackCallback provisionCallback; - + ProvidedByInternalFactory( Class rawType, Class> providerType, Key> providerKey) { super(providerKey); this.rawType = rawType; - this.providerType = providerType; + this.providerType = providerType; this.providerKey = providerKey; } - + void setProvisionListenerCallback(ProvisionListenerStackCallback listener) { provisionCallback = listener; } - + + @Override public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { providerBinding = injector.getBindingOrThrow(providerKey, errors, JitLimitation.NEW_OR_EXISTING_JIT); } - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) - throws ErrorsException { - checkState(providerBinding != null, "not initialized"); - - context.pushState(providerKey, providerBinding.getSource()); + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + BindingImpl> localProviderBinding = providerBinding; + if (localProviderBinding == null) { + throw new IllegalStateException("not initialized"); + } + Key> localProviderKey = providerKey; + context.pushState(localProviderKey, localProviderBinding.getSource()); + try { - errors = errors.withSource(providerKey); - Provider provider = providerBinding.getInternalFactory().get( - errors, context, dependency, true); - return circularGet(provider, errors, context, dependency, provisionCallback); - } finally { - context.popState(); + Provider provider = + localProviderBinding.getInternalFactory().get(context, dependency, true); + return circularGet(provider, context, dependency, provisionCallback); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(localProviderKey); + } finally { + context.popState(); + } } - + @Override - protected T provision(javax.inject.Provider provider, Errors errors, - Dependency dependency, ConstructionContext constructionContext) - throws ErrorsException { + protected T provision( + javax.inject.Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { try { - Object o = super.provision(provider, errors, dependency, constructionContext); + Object o = super.provision(provider, dependency, constructionContext); if (o != null && !rawType.isInstance(o)) { - throw errors.subtypeNotProvided(providerType, rawType).toException(); + throw InternalProvisionException.subtypeNotProvided(providerType, rawType); } @SuppressWarnings("unchecked") // protected by isInstance() check above T t = (T) o; return t; } catch (RuntimeException e) { - throw errors.errorInProvider(e).toException(); + throw InternalProvisionException.errorInProvider(e).addSource(source); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ package com.google.inject.internal; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; @@ -28,17 +29,19 @@ import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.util.Providers; - import java.util.Set; -final class ProviderInstanceBindingImpl extends BindingImpl - implements ProviderInstanceBinding { +class ProviderInstanceBindingImpl extends BindingImpl implements ProviderInstanceBinding { final javax.inject.Provider providerInstance; final ImmutableSet injectionPoints; - public ProviderInstanceBindingImpl(InjectorImpl injector, Key key, - Object source, InternalFactory internalFactory, Scoping scoping, + public ProviderInstanceBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, javax.inject.Provider providerInstance, Set injectionPoints) { super(injector, key, source, internalFactory, scoping); @@ -46,16 +49,21 @@ this.injectionPoints = ImmutableSet.copyOf(injectionPoints); } - public ProviderInstanceBindingImpl(Object source, Key key, Scoping scoping, - Set injectionPoints, javax.inject.Provider providerInstance) { + public ProviderInstanceBindingImpl( + Object source, + Key key, + Scoping scoping, + Set injectionPoints, + javax.inject.Provider providerInstance) { super(source, key, scoping); this.injectionPoints = ImmutableSet.copyOf(injectionPoints); this.providerInstance = providerInstance; } + @Override @SuppressWarnings("unchecked") // the extension type is always consistent with the provider type public V acceptTargetVisitor(BindingTargetVisitor visitor) { - if(providerInstance instanceof ProviderWithExtensionVisitor) { + if (providerInstance instanceof ProviderWithExtensionVisitor) { return ((ProviderWithExtensionVisitor) providerInstance) .acceptExtensionVisitor(visitor, this); } else { @@ -66,39 +74,46 @@ public Provider getProviderInstance() { return Providers.guicify(providerInstance); } - + + @Override public javax.inject.Provider getUserSuppliedProvider() { return providerInstance; } + @Override public Set getInjectionPoints() { return injectionPoints; } + @Override public Set> getDependencies() { return providerInstance instanceof HasDependencies ? ImmutableSet.copyOf(((HasDependencies) providerInstance).getDependencies()) : Dependency.forInjectionPoints(injectionPoints); } + @Override public BindingImpl withScoping(Scoping scoping) { return new ProviderInstanceBindingImpl( getSource(), getKey(), scoping, injectionPoints, providerInstance); } + @Override public BindingImpl withKey(Key key) { return new ProviderInstanceBindingImpl( getSource(), key, getScoping(), injectionPoints, providerInstance); } + @Override public void applyTo(Binder binder) { - getScoping().applyTo( - binder.withSource(getSource()).bind(getKey()).toProvider(getUserSuppliedProvider())); + getScoping() + .applyTo( + binder.withSource(getSource()).bind(getKey()).toProvider(getUserSuppliedProvider())); } @Override public String toString() { - return Objects.toStringHelper(ProviderInstanceBinding.class) + return MoreObjects.toStringHelper(ProviderInstanceBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) @@ -108,11 +123,11 @@ @Override public boolean equals(Object obj) { - if(obj instanceof ProviderInstanceBindingImpl) { - ProviderInstanceBindingImpl o = (ProviderInstanceBindingImpl)obj; + if (obj instanceof ProviderInstanceBindingImpl) { + ProviderInstanceBindingImpl o = (ProviderInstanceBindingImpl) obj; return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()) - && Objects.equal(providerInstance, o.providerInstance); + && getScoping().equals(o.getScoping()) + && Objects.equal(providerInstance, o.providerInstance); } else { return false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderInternalFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderInternalFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderInternalFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderInternalFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,57 +14,58 @@ * limitations under the License. */ - package com.google.inject.internal; import static com.google.common.base.Preconditions.checkNotNull; import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback; import com.google.inject.spi.Dependency; - import javax.inject.Provider; /** - * Base class for InternalFactories that are used by Providers, to handle - * circular dependencies. + * Base class for InternalFactories that are used by Providers, to handle circular dependencies. * * @author sameb@google.com (Sam Berlin) */ abstract class ProviderInternalFactory implements InternalFactory { - + protected final Object source; - + ProviderInternalFactory(Object source) { this.source = checkNotNull(source, "source"); } - - protected T circularGet(final Provider provider, final Errors errors, - InternalContext context, final Dependency dependency, - ProvisionListenerStackCallback provisionCallback) - throws ErrorsException { + + protected T circularGet( + final Provider provider, + InternalContext context, + final Dependency dependency, + /* @Nullable */ ProvisionListenerStackCallback provisionCallback) + throws InternalProvisionException { final ConstructionContext constructionContext = context.getConstructionContext(this); // We have a circular reference between constructors. Return a proxy. if (constructionContext.isConstructing()) { - Class expectedType = dependency.getKey().getTypeLiteral().getRawType(); - // TODO: if we can't proxy this object, can we proxy the other object? - @SuppressWarnings("unchecked") - T proxyType = (T) constructionContext.createProxy( - errors, context.getInjectorOptions(), expectedType); - return proxyType; + Class expectedType = dependency.getKey().getTypeLiteral().getRawType(); + // TODO: if we can't proxy this object, can we proxy the other object? + @SuppressWarnings("unchecked") + T proxyType = (T) constructionContext.createProxy(context.getInjectorOptions(), expectedType); + return proxyType; } // Optimization: Don't go through the callback stack if no one's listening. constructionContext.startConstruction(); try { - if (!provisionCallback.hasListeners()) { - return provision(provider, errors, dependency, constructionContext); + if (provisionCallback == null) { + return provision(provider, dependency, constructionContext); } else { - return provisionCallback.provision(errors, context, new ProvisionCallback() { - public T call() throws ErrorsException { - return provision(provider, errors, dependency, constructionContext); - } - }); + return provisionCallback.provision( + context, + new ProvisionCallback() { + @Override + public T call() throws InternalProvisionException { + return provision(provider, dependency, constructionContext); + } + }); } } finally { constructionContext.removeCurrentReference(); @@ -73,12 +74,18 @@ } /** - * Provisions a new instance. Subclasses should override this to catch - * exceptions & rethrow as ErrorsExceptions. + * Provisions a new instance. Subclasses should override this to catch exceptions & rethrow as + * ErrorsExceptions. */ - protected T provision(Provider provider, Errors errors, Dependency dependency, - ConstructionContext constructionContext) throws ErrorsException { - T t = errors.checkForNull(provider.get(), source, dependency); + protected T provision( + Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { + T t = provider.get(); + if (t == null && !dependency.isNullable()) { + InternalProvisionException.onNullInjectedIntoNonNullableDependency(source, dependency); + } constructionContext.setProxyDelegates(t); return t; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderMethod.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderMethod.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderMethod.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderMethod.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,15 +17,13 @@ package com.google.inject.internal; import com.google.common.base.Objects; -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; import com.google.inject.Exposed; import com.google.inject.Key; import com.google.inject.PrivateBinder; -import com.google.inject.Provider; import com.google.inject.Provides; -import com.google.inject.internal.BytecodeGen.Visibility; +import com.google.inject.internal.InternalProviderInstanceBindingImpl.InitializationTiming; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; @@ -34,12 +32,10 @@ import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.spi.ProvidesMethodBinding; import com.google.inject.spi.ProvidesMethodTargetVisitor; - import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.List; import java.util.Set; /** @@ -47,50 +43,47 @@ * * @author jessewilson@google.com (Jesse Wilson) */ -public abstract class ProviderMethod implements ProviderWithExtensionVisitor, HasDependencies, - ProvidesMethodBinding { +public abstract class ProviderMethod extends InternalProviderInstanceBindingImpl.CyclicFactory + implements HasDependencies, ProvidesMethodBinding, ProviderWithExtensionVisitor { /** * Creates a {@link ProviderMethod}. * - *

    Unless {@code skipFastClassGeneration} is set, this will use - * {@link net.sf.cglib.reflect.FastClass} to invoke the actual method, since it is significantly - * faster. However, this will fail if the method is {@code private} or {@code protected}, since - * fastclass is subject to java access policies. + *

    Unless {@code skipFastClassGeneration} is set, this will use {@link + * net.sf.cglib.reflect.FastClass} to invoke the actual method, since it is significantly faster. + * However, this will fail if the method is {@code private} or {@code protected}, since fastclass + * is subject to java access policies. */ - static ProviderMethod create(Key key, Method method, Object instance, - ImmutableSet> dependencies, List> parameterProviders, - Class scopeAnnotation, boolean skipFastClassGeneration, + static ProviderMethod create( + Key key, + Method method, + Object instance, + ImmutableSet> dependencies, + Class scopeAnnotation, + boolean skipFastClassGeneration, Annotation annotation) { int modifiers = method.getModifiers(); /*if[AOP]*/ - if (!skipFastClassGeneration && !Modifier.isPrivate(modifiers) - && !Modifier.isProtected(modifiers)) { + if (!skipFastClassGeneration) { try { - // We use an index instead of FastMethod to save a stack frame. - return new FastClassProviderMethod(key, - method, - instance, - dependencies, - parameterProviders, - scopeAnnotation, - annotation); - } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */} + net.sf.cglib.reflect.FastClass fc = BytecodeGen.newFastClassForMember(method); + if (fc != null) { + return new FastClassProviderMethod( + key, fc, method, instance, dependencies, scopeAnnotation, annotation); + } + } catch (net.sf.cglib.core.CodeGenerationException e) { + /* fall-through */ + } } /*end[AOP]*/ - if (!Modifier.isPublic(modifiers) || - !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { + if (!Modifier.isPublic(modifiers) + || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } - return new ReflectionProviderMethod(key, - method, - instance, - dependencies, - parameterProviders, - scopeAnnotation, - annotation); + return new ReflectionProviderMethod( + key, method, instance, dependencies, scopeAnnotation, annotation); } protected final Object instance; @@ -99,22 +92,30 @@ private final Key key; private final Class scopeAnnotation; private final ImmutableSet> dependencies; - private final List> parameterProviders; private final boolean exposed; private final Annotation annotation; /** - * @param method the method to invoke. It's return type must be the same type as {@code key}. + * Set by {@link #initialize(InjectorImpl, Errors)} so it is always available prior to injection. */ - private ProviderMethod(Key key, Method method, Object instance, - ImmutableSet> dependencies, List> parameterProviders, - Class scopeAnnotation, Annotation annotation) { + private SingleParameterInjector[] parameterInjectors; + + /** @param method the method to invoke. It's return type must be the same type as {@code key}. */ + private ProviderMethod( + Key key, + Method method, + Object instance, + ImmutableSet> dependencies, + Class scopeAnnotation, + Annotation annotation) { + // We can be safely initialized eagerly since our bindings must exist statically and it is an + // error for them not to. + super(InitializationTiming.EAGER); this.key = key; this.scopeAnnotation = scopeAnnotation; this.instance = instance; this.dependencies = dependencies; this.method = method; - this.parameterProviders = parameterProviders; this.exposed = method.isAnnotationPresent(Exposed.class); this.annotation = annotation; } @@ -133,12 +134,12 @@ public Object getInstance() { return instance; } - + @Override public Object getEnclosingInstance() { return instance; } - + @Override public Annotation getAnnotation() { return annotation; @@ -161,43 +162,48 @@ } @Override - public T get() { - Object[] parameters = new Object[parameterProviders.size()]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = parameterProviders.get(i).get(); - } + void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + parameterInjectors = injector.getParametersInjectors(dependencies.asList(), errors); + } + @Override + protected T doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException { try { - @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" }) - T result = (T) doProvision(parameters); - return result; + T t = doProvision(SingleParameterInjector.getAll(context, parameterInjectors)); + if (t == null && !dependency.isNullable()) { + InternalProvisionException.onNullInjectedIntoNonNullableDependency(getMethod(), dependency); + } + return t; } catch (IllegalAccessException e) { throw new AssertionError(e); - } catch (InvocationTargetException e) { - throw Exceptions.rethrowCause(e); + } catch (InvocationTargetException userException) { + Throwable cause = userException.getCause() != null ? userException.getCause() : userException; + throw InternalProvisionException.errorInProvider(cause).addSource(getSource()); } } /** Extension point for our subclasses to implement the provisioning strategy. */ - abstract Object doProvision(Object[] parameters) + abstract T doProvision(Object[] parameters) throws IllegalAccessException, InvocationTargetException; @Override public Set> getDependencies() { return dependencies; } - + @Override @SuppressWarnings("unchecked") - public V acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { if (visitor instanceof ProvidesMethodTargetVisitor) { - return ((ProvidesMethodTargetVisitor)visitor).visit(this); + return ((ProvidesMethodTargetVisitor) visitor).visit(this); } return visitor.visit(binding); } - @Override public String toString() { + @Override + public String toString() { String annotationString = annotation.toString(); // Show @Provides w/o the com.google.inject prefix. if (annotation.annotationType() == Provides.class) { @@ -208,19 +214,19 @@ } return annotationString + " " + StackTraceElements.forMember(method); } - + @Override public boolean equals(Object obj) { if (obj instanceof ProviderMethod) { ProviderMethod o = (ProviderMethod) obj; return method.equals(o.method) - && instance.equals(o.instance) - && annotation.equals(o.annotation); + && instance.equals(o.instance) + && annotation.equals(o.annotation); } else { return false; } } - + @Override public int hashCode() { // Avoid calling hashCode on 'instance', which is a user-object @@ -238,65 +244,46 @@ final net.sf.cglib.reflect.FastClass fastClass; final int methodIndex; - FastClassProviderMethod(Key key, + FastClassProviderMethod( + Key key, + net.sf.cglib.reflect.FastClass fc, Method method, Object instance, ImmutableSet> dependencies, - List> parameterProviders, Class scopeAnnotation, Annotation annotation) { - super(key, - method, - instance, - dependencies, - parameterProviders, - scopeAnnotation, - annotation); - // We need to generate a FastClass for the method's class, not the object's class. - this.fastClass = - BytecodeGen.newFastClass(method.getDeclaringClass(), Visibility.forMember(method)); - // Use the Signature overload of getIndex because it properly uses return types to identify - // particular methods. This is normally irrelevant, except in the case of covariant overrides - // which java implements with a compiler generated bridge method to implement the override. - this.methodIndex = fastClass.getIndex( - new net.sf.cglib.core.Signature( - method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); - Preconditions.checkArgument(this.methodIndex >= 0, - "Could not find method %s in fast class for class %s", - method, - method.getDeclaringClass()); + super(key, method, instance, dependencies, scopeAnnotation, annotation); + this.fastClass = fc; + this.methodIndex = fc.getMethod(method).getIndex(); } - @Override public Object doProvision(Object[] parameters) + @SuppressWarnings("unchecked") + @Override + public T doProvision(Object[] parameters) throws IllegalAccessException, InvocationTargetException { - return fastClass.invoke(methodIndex, instance, parameters); + return (T) fastClass.invoke(methodIndex, instance, parameters); } } /*end[AOP]*/ /** - * A {@link ProviderMethod} implementation that invokes the method using normal java reflection. + * A {@link ProviderMethod} implementation that invokes the method using normal java reflection. */ private static final class ReflectionProviderMethod extends ProviderMethod { - ReflectionProviderMethod(Key key, + ReflectionProviderMethod( + Key key, Method method, Object instance, ImmutableSet> dependencies, - List> parameterProviders, Class scopeAnnotation, Annotation annotation) { - super(key, - method, - instance, - dependencies, - parameterProviders, - scopeAnnotation, - annotation); + super(key, method, instance, dependencies, scopeAnnotation, annotation); } - @Override Object doProvision(Object[] parameters) throws IllegalAccessException, - InvocationTargetException { - return method.invoke(instance, parameters); + @SuppressWarnings("unchecked") + @Override + T doProvision(Object[] parameters) throws IllegalAccessException, InvocationTargetException { + return (T) method.invoke(instance, parameters); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderMethodsModule.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderMethodsModule.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderMethodsModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderMethodsModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,30 +18,26 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.google.common.base.Optional; import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Module; -import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.TypeLiteral; -import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.Message; import com.google.inject.spi.ModuleAnnotatedMethodScanner; import com.google.inject.util.Modules; - import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; -import java.util.Set; /** * Creates bindings to methods annotated with {@literal @}{@link Provides}. Use the scope and @@ -51,61 +47,42 @@ * @author jessewilson@google.com (Jesse Wilson) */ public final class ProviderMethodsModule implements Module { - - private static ModuleAnnotatedMethodScanner PROVIDES_BUILDER = - new ModuleAnnotatedMethodScanner() { - @Override - public Key prepareMethod( - Binder binder, Annotation annotation, Key key, InjectionPoint injectionPoint) { - return key; - } - - @Override - public Set> annotationClasses() { - return ImmutableSet.of(Provides.class); - } - }; - private final Object delegate; private final TypeLiteral typeLiteral; private final boolean skipFastClassGeneration; private final ModuleAnnotatedMethodScanner scanner; - private ProviderMethodsModule(Object delegate, boolean skipFastClassGeneration, - ModuleAnnotatedMethodScanner scanner) { + private ProviderMethodsModule( + Object delegate, boolean skipFastClassGeneration, ModuleAnnotatedMethodScanner scanner) { this.delegate = checkNotNull(delegate, "delegate"); this.typeLiteral = TypeLiteral.get(this.delegate.getClass()); this.skipFastClassGeneration = skipFastClassGeneration; this.scanner = scanner; } - /** - * Returns a module which creates bindings for provider methods from the given module. - */ + /** Returns a module which creates bindings for provider methods from the given module. */ public static Module forModule(Module module) { - return forObject(module, false, PROVIDES_BUILDER); + return forObject(module, false, ProvidesMethodScanner.INSTANCE); } - /** - * Returns a module which creates bindings methods in the module that match the scanner. - */ + /** Returns a module which creates bindings methods in the module that match the scanner. */ public static Module forModule(Object module, ModuleAnnotatedMethodScanner scanner) { return forObject(module, false, scanner); } /** - * Returns a module which creates bindings for provider methods from the given object. - * This is useful notably for GIN + * Returns a module which creates bindings for provider methods from the given object. This is + * useful notably for GIN * *

    This will skip bytecode generation for provider methods, since it is assumed that callers * are only interested in Module metadata. */ public static Module forObject(Object object) { - return forObject(object, true, PROVIDES_BUILDER); + return forObject(object, true, ProvidesMethodScanner.INSTANCE); } - private static Module forObject(Object object, boolean skipFastClassGeneration, - ModuleAnnotatedMethodScanner scanner) { + private static Module forObject( + Object object, boolean skipFastClassGeneration, ModuleAnnotatedMethodScanner scanner) { // avoid infinite recursion, since installing a module always installs itself if (object instanceof ProviderMethodsModule) { return Modules.EMPTY_MODULE; @@ -119,91 +96,115 @@ } @Override - public synchronized void configure(Binder binder) { + public void configure(Binder binder) { for (ProviderMethod providerMethod : getProviderMethods(binder)) { providerMethod.configure(binder); } } public List> getProviderMethods(Binder binder) { - List> result = Lists.newArrayList(); - Multimap methodsBySignature = HashMultimap.create(); + List> result = null; + // The highest class in the type hierarchy that contained a provider method definition. + Class superMostClass = delegate.getClass(); for (Class c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) { for (Method method : c.getDeclaredMethods()) { - // private/static methods cannot override or be overridden by other methods, so there is no - // point in indexing them. - // Skip synthetic methods and bridge methods since java will automatically generate - // synthetic overrides in some cases where we don't want to generate an error (e.g. - // increasing visibility of a subclass). - if (((method.getModifiers() & (Modifier.PRIVATE | Modifier.STATIC)) == 0) - && !method.isBridge() && !method.isSynthetic()) { - methodsBySignature.put(new Signature(method), method); - } - Optional annotation = isProvider(binder, method); - if (annotation.isPresent()) { - result.add(createProviderMethod(binder, method, annotation.get())); + Annotation annotation = getAnnotation(binder, method); + if (annotation != null) { + if (result == null) { + result = Lists.newArrayList(); + } + result.add(createProviderMethod(binder, method, annotation)); + superMostClass = c; } } } - // we have found all the providers and now need to identify if any were overridden - // In the worst case this will have O(n^2) in the number of @Provides methods, but that is only - // assuming that every method is an override, in general it should be very quick. - for (ProviderMethod provider : result) { - Method method = provider.getMethod(); - for (Method matchingSignature : methodsBySignature.get(new Signature(method))) { - // matching signature is in the same class or a super class, therefore method cannot be - // overridding it. - if (matchingSignature.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) { - continue; + if (result == null) { + // We didn't find anything + return ImmutableList.of(); + } + // We have found some provider methods, now we need to check if any were overridden. + // We do this as a separate pass to avoid calculating all the signatures when there are no + // provides methods, or when all provides methods are defined in a single class. + Multimap methodsBySignature = null; + // We can stop scanning when we see superMostClass, since no superclass method can override + // a method in a subclass. Corrollary, if superMostClass == delegate.getClass(), there can be + // no overrides of a provides method. + for (Class c = delegate.getClass(); c != superMostClass; c = c.getSuperclass()) { + for (Method method : c.getDeclaredMethods()) { + if (((method.getModifiers() & (Modifier.PRIVATE | Modifier.STATIC)) == 0) + && !method.isBridge() + && !method.isSynthetic()) { + if (methodsBySignature == null) { + methodsBySignature = HashMultimap.create(); + } + methodsBySignature.put(new Signature(typeLiteral, method), method); } - // now we know matching signature is in a subtype of method.getDeclaringClass() - if (overrides(matchingSignature, method)) { - String annotationString = provider.getAnnotation().annotationType() == Provides.class - ? "@Provides" : "@" + provider.getAnnotation().annotationType().getCanonicalName(); - binder.addError( - "Overriding " + annotationString + " methods is not allowed." - + "\n\t" + annotationString + " method: %s\n\toverridden by: %s", - method, - matchingSignature); - break; + } + } + if (methodsBySignature != null) { + // we have found all the signatures and now need to identify if any were overridden + // In the worst case this will have O(n^2) in the number of @Provides methods, but that is + // only assuming that every method is an override, in general it should be very quick. + for (ProviderMethod provider : result) { + Method method = provider.getMethod(); + for (Method matchingSignature : + methodsBySignature.get(new Signature(typeLiteral, method))) { + // matching signature is in the same class or a super class, therefore method cannot be + // overridding it. + if (matchingSignature.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) { + continue; + } + // now we know matching signature is in a subtype of method.getDeclaringClass() + if (overrides(matchingSignature, method)) { + String annotationString = + provider.getAnnotation().annotationType() == Provides.class + ? "@Provides" + : "@" + provider.getAnnotation().annotationType().getCanonicalName(); + binder.addError( + "Overriding " + + annotationString + + " methods is not allowed." + + "\n\t" + + annotationString + + " method: %s\n\toverridden by: %s", + method, + matchingSignature); + break; + } } } } return result; } - /** - * Returns true if the method is a provider. - * - * Synthetic bridge methods are excluded. Starting with JDK 8, javac copies annotations onto - * bridge methods (which always have erased signatures). - */ - private Optional isProvider(Binder binder, Method method) { + /** Returns the annotation that is claimed by the scanner, or null if there is none. */ + private Annotation getAnnotation(Binder binder, Method method) { if (method.isBridge() || method.isSynthetic()) { - return Optional.absent(); + return null; } Annotation annotation = null; for (Class annotationClass : scanner.annotationClasses()) { Annotation foundAnnotation = method.getAnnotation(annotationClass); if (foundAnnotation != null) { if (annotation != null) { - binder.addError("More than one annotation claimed by %s on method %s." - + " Methods can only have one annotation claimed per scanner.", + binder.addError( + "More than one annotation claimed by %s on method %s." + + " Methods can only have one annotation claimed per scanner.", scanner, method); - return Optional.absent(); + return null; } annotation = foundAnnotation; } } - return Optional.fromNullable(annotation); + return annotation; } - private final class Signature { + private static final class Signature { final Class[] parameters; final String name; final int hashCode; - Signature(Method method) { + Signature(TypeLiteral typeLiteral, Method method) { this.name = method.getName(); // We need to 'resolve' the parameters against the actual class type in case this method uses // type parameters. This is so we can detect overrides of generic superclass methods where @@ -219,7 +220,8 @@ this.hashCode = name.hashCode() + 31 * Arrays.hashCode(parameters); } - @Override public boolean equals(Object obj) { + @Override + public boolean equals(Object obj) { if (obj instanceof Signature) { Signature other = (Signature) obj; return other.name.equals(name) && Arrays.equals(parameters, other.parameters); @@ -227,7 +229,8 @@ return false; } - @Override public int hashCode() { + @Override + public int hashCode() { return hashCode; } } @@ -246,34 +249,34 @@ return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage()); } - private ProviderMethod createProviderMethod(Binder binder, Method method, - Annotation annotation) { + private ProviderMethod createProviderMethod( + Binder binder, Method method, Annotation annotation) { binder = binder.withSource(method); Errors errors = new Errors(method); // prepare the parameter providers InjectionPoint point = InjectionPoint.forMethod(method, typeLiteral); - List> dependencies = point.getDependencies(); - List> parameterProviders = Lists.newArrayList(); - for (Dependency dependency : point.getDependencies()) { - parameterProviders.add(binder.getProvider(dependency)); - } - @SuppressWarnings("unchecked") // Define T as the method's return type. TypeLiteral returnType = (TypeLiteral) typeLiteral.getReturnType(method); Key key = getKey(errors, returnType, method, method.getAnnotations()); try { key = scanner.prepareMethod(binder, annotation, key, point); - } catch(Throwable t) { + } catch (Throwable t) { binder.addError(t); } - Class scopeAnnotation - = Annotations.findScopeAnnotation(errors, method.getAnnotations()); + Class scopeAnnotation = + Annotations.findScopeAnnotation(errors, method.getAnnotations()); for (Message message : errors.getMessages()) { binder.addError(message); } - return ProviderMethod.create(key, method, delegate, ImmutableSet.copyOf(dependencies), - parameterProviders, scopeAnnotation, skipFastClassGeneration, annotation); + return ProviderMethod.create( + key, + method, + delegate, + ImmutableSet.copyOf(point.getDependencies()), + scopeAnnotation, + skipFastClassGeneration, + annotation); } Key getKey(Errors errors, TypeLiteral type, Member member, Annotation[] annotations) { @@ -281,13 +284,15 @@ return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation); } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { return o instanceof ProviderMethodsModule && ((ProviderMethodsModule) o).delegate == delegate && ((ProviderMethodsModule) o).scanner == scanner; } - @Override public int hashCode() { + @Override + public int hashCode() { return delegate.hashCode(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,43 +17,42 @@ package com.google.inject.internal; import com.google.inject.Provider; -import com.google.inject.ProvisionException; -import com.google.inject.spi.Dependency; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ final class ProviderToInternalFactoryAdapter implements Provider { private final InjectorImpl injector; private final InternalFactory internalFactory; - public ProviderToInternalFactoryAdapter(InjectorImpl injector, - InternalFactory internalFactory) { + public ProviderToInternalFactoryAdapter( + InjectorImpl injector, InternalFactory internalFactory) { this.injector = injector; this.internalFactory = internalFactory; } + @Override public T get() { - final Errors errors = new Errors(); + InternalContext context = injector.enterContext(); try { - T t = injector.callInContext(new ContextualCallable() { - public T call(InternalContext context) throws ErrorsException { - Dependency dependency = context.getDependency(); - // Always pretend that we are a linked binding, to support - // scoping implicit bindings. If we are not actually a linked - // binding, we'll fail properly elsewhere in the chain. - return internalFactory.get(errors, context, dependency, true); - } - }); - errors.throwIfNewErrors(0); + // Always pretend that we are a linked binding, to support + // scoping implicit bindings. If we are not actually a linked + // binding, we'll fail properly elsewhere in the chain. + T t = internalFactory.get(context, context.getDependency(), true); return t; - } catch (ErrorsException e) { - throw new ProvisionException(errors.merge(e.getErrors()).getMessages()); + } catch (InternalProvisionException e) { + throw e.toProvisionException(); + } finally { + context.close(); } } - @Override public String toString() { + /** Exposed for SingletonScope. */ + InjectorImpl getInjector() { + return injector; + } + + @Override + public String toString() { return internalFactory.toString(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvidesMethodScanner.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvidesMethodScanner.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvidesMethodScanner.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvidesMethodScanner.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Binder; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; +import com.google.inject.multibindings.MapKey; +import com.google.inject.multibindings.ProvidesIntoMap; +import com.google.inject.multibindings.ProvidesIntoOptional; +import com.google.inject.multibindings.ProvidesIntoSet; +import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.ModuleAnnotatedMethodScanner; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; + +/** + * A {@link ModuleAnnotatedMethodScanner} that handles the {@Provides}, {@link ProvidesIntoSet}, + * {@link ProvidesIntoMap} and {@link ProvidesIntoOptional} annotations. + * + *

    This is the default scanner used by ProviderMethodsModule and handles all the built in + * annotations. + */ +final class ProvidesMethodScanner extends ModuleAnnotatedMethodScanner { + static final ProvidesMethodScanner INSTANCE = new ProvidesMethodScanner(); + private static final ImmutableSet> ANNOTATIONS = + ImmutableSet.of( + Provides.class, ProvidesIntoSet.class, ProvidesIntoMap.class, ProvidesIntoOptional.class); + + private ProvidesMethodScanner() {} + + @Override + public Set> annotationClasses() { + return ANNOTATIONS; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) // mapKey doesn't know its key type + @Override + public Key prepareMethod( + Binder binder, Annotation annotation, Key key, InjectionPoint injectionPoint) { + Method method = (Method) injectionPoint.getMember(); + AnnotationOrError mapKey = findMapKeyAnnotation(binder, method); + if (annotation instanceof Provides) { + if (mapKey.annotation != null) { + binder.addError("Found a MapKey annotation on non map binding at %s.", method); + } + // no key rewriting for plain old @Provides + return key; + } + if (annotation instanceof ProvidesIntoSet) { + if (mapKey.annotation != null) { + binder.addError("Found a MapKey annotation on non map binding at %s.", method); + } + return RealMultibinder.newRealSetBinder(binder, key).getKeyForNewItem(); + } else if (annotation instanceof ProvidesIntoMap) { + if (mapKey.error) { + // Already failed on the MapKey, don't bother doing more work. + return key; + } + if (mapKey.annotation == null) { + // If no MapKey, make an error and abort. + binder.addError("No MapKey found for map binding at %s.", method); + return key; + } + TypeAndValue typeAndValue = typeAndValueOfMapKey(mapKey.annotation); + return RealMapBinder.newRealMapBinder(binder, typeAndValue.type, key) + .getKeyForNewValue(typeAndValue.value); + } else if (annotation instanceof ProvidesIntoOptional) { + if (mapKey.annotation != null) { + binder.addError("Found a MapKey annotation on non map binding at %s.", method); + } + switch (((ProvidesIntoOptional) annotation).value()) { + case DEFAULT: + return RealOptionalBinder.newRealOptionalBinder(binder, key).getKeyForDefaultBinding(); + case ACTUAL: + return RealOptionalBinder.newRealOptionalBinder(binder, key).getKeyForActualBinding(); + } + } + throw new IllegalStateException("Invalid annotation: " + annotation); + } + + private static class AnnotationOrError { + final Annotation annotation; + final boolean error; + + AnnotationOrError(Annotation annotation, boolean error) { + this.annotation = annotation; + this.error = error; + } + + static AnnotationOrError forPossiblyNullAnnotation(Annotation annotation) { + return new AnnotationOrError(annotation, false); + } + + static AnnotationOrError forError() { + return new AnnotationOrError(null, true); + } + } + + private static AnnotationOrError findMapKeyAnnotation(Binder binder, Method method) { + Annotation foundAnnotation = null; + for (Annotation annotation : method.getAnnotations()) { + MapKey mapKey = annotation.annotationType().getAnnotation(MapKey.class); + if (mapKey != null) { + if (foundAnnotation != null) { + binder.addError("Found more than one MapKey annotations on %s.", method); + return AnnotationOrError.forError(); + } + if (mapKey.unwrapValue()) { + try { + // validate there's a declared method called "value" + Method valueMethod = annotation.annotationType().getDeclaredMethod("value"); + if (valueMethod.getReturnType().isArray()) { + binder.addError( + "Array types are not allowed in a MapKey with unwrapValue=true: %s", + annotation.annotationType()); + return AnnotationOrError.forError(); + } + } catch (NoSuchMethodException invalid) { + binder.addError( + "No 'value' method in MapKey with unwrapValue=true: %s", + annotation.annotationType()); + return AnnotationOrError.forError(); + } + } + foundAnnotation = annotation; + } + } + return AnnotationOrError.forPossiblyNullAnnotation(foundAnnotation); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + static TypeAndValue typeAndValueOfMapKey(Annotation mapKeyAnnotation) { + if (!mapKeyAnnotation.annotationType().getAnnotation(MapKey.class).unwrapValue()) { + return new TypeAndValue(TypeLiteral.get(mapKeyAnnotation.annotationType()), mapKeyAnnotation); + } else { + try { + Method valueMethod = mapKeyAnnotation.annotationType().getDeclaredMethod("value"); + valueMethod.setAccessible(true); + TypeLiteral returnType = + TypeLiteral.get(mapKeyAnnotation.annotationType()).getReturnType(valueMethod); + return new TypeAndValue(returnType, valueMethod.invoke(mapKeyAnnotation)); + } catch (NoSuchMethodException e) { + throw new IllegalStateException(e); + } catch (SecurityException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + throw new IllegalStateException(e); + } + } + } + + private static class TypeAndValue { + final TypeLiteral type; + final T value; + + TypeAndValue(TypeLiteral type, T value) { + this.type = type; + this.value = value; + } + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,9 +28,7 @@ import com.google.inject.Stage; import com.google.inject.spi.ProvisionListener; import com.google.inject.spi.ProvisionListenerBinding; - import java.util.List; -import java.util.Set; import java.util.logging.Logger; /** @@ -42,51 +40,57 @@ // TODO(sameb): Consider exposing this in the API somehow? Maybe? // Lots of code often want to skip over the internal stuffs. - private static final Set> INTERNAL_BINDINGS = + private static final ImmutableSet> INTERNAL_BINDINGS = ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class)); - + private final ImmutableList listenerBindings; - private final LoadingCache> cache - = CacheBuilder.newBuilder().build( - new CacheLoader>() { - public ProvisionListenerStackCallback load(KeyBinding key) { - return create(key.binding); - } - }); + private final LoadingCache> cache = + CacheBuilder.newBuilder() + .build( + new CacheLoader>() { + @Override + public ProvisionListenerStackCallback load(KeyBinding key) { + return create(key.binding); + } + }); ProvisionListenerCallbackStore(List listenerBindings) { this.listenerBindings = ImmutableList.copyOf(listenerBindings); } - /** Returns a new {@link ProvisionListenerStackCallback} for the key. + /** + * Returns a new {@link ProvisionListenerStackCallback} for the key or {@code null} if there are + * no listeners */ - @SuppressWarnings("unchecked") // the ProvisionListenerStackCallback type always agrees with the passed type + @SuppressWarnings( + "unchecked") // the ProvisionListenerStackCallback type always agrees with the passed type public ProvisionListenerStackCallback get(Binding binding) { // Never notify any listeners for internal bindings. if (!INTERNAL_BINDINGS.contains(binding.getKey())) { - return (ProvisionListenerStackCallback) cache.getUnchecked( - new KeyBinding(binding.getKey(), binding)); + ProvisionListenerStackCallback callback = + (ProvisionListenerStackCallback) + cache.getUnchecked(new KeyBinding(binding.getKey(), binding)); + return callback.hasListeners() ? callback : null; } - return ProvisionListenerStackCallback.emptyListener(); + return null; } /** - * Purges a key from the cache. Use this only if the type is not actually valid for - * binding and needs to be purged. (See issue 319 and + * Purges a key from the cache. Use this only if the type is not actually valid for binding and + * needs to be purged. (See issue 319 and * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is * necessary.) - * - * Returns true if the type was stored in the cache, false otherwise. + * + *

    Returns true if the type was stored in the cache, false otherwise. */ boolean remove(Binding type) { return cache.asMap().remove(type) != null; } /** - * Creates a new {@link ProvisionListenerStackCallback} with the correct listeners - * for the key. + * Creates a new {@link ProvisionListenerStackCallback} with the correct listeners for the key. */ private ProvisionListenerStackCallback create(Binding binding) { List listeners = null; @@ -105,21 +109,22 @@ } return new ProvisionListenerStackCallback(binding, listeners); } - + /** A struct that holds key & binding but uses just key for equality/hashcode. */ private static class KeyBinding { final Key key; final Binding binding; - + KeyBinding(Key key, Binding binding) { this.key = key; this.binding = binding; } - + @Override public boolean equals(Object obj) { - return obj instanceof KeyBinding && key.equals(((KeyBinding)obj).key); + return obj instanceof KeyBinding && key.equals(((KeyBinding) obj).key); } + @Override public int hashCode() { return key.hashCode(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,10 +19,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import com.google.inject.Binding; -import com.google.inject.ProvisionException; -import com.google.inject.spi.DependencyAndSource; import com.google.inject.spi.ProvisionListener; - import java.util.List; import java.util.Set; @@ -32,15 +29,16 @@ * @author sameb@google.com (Sam Berlin) */ final class ProvisionListenerStackCallback { - - private static final ProvisionListener EMPTY_LISTENER[] = new ProvisionListener[0]; - @SuppressWarnings("rawtypes") + + private static final ProvisionListener[] EMPTY_LISTENER = new ProvisionListener[0]; + + @SuppressWarnings({"rawtypes", "unchecked"}) private static final ProvisionListenerStackCallback EMPTY_CALLBACK = new ProvisionListenerStackCallback(null /* unused, so ok */, ImmutableList.of()); private final ProvisionListener[] listeners; private final Binding binding; - + @SuppressWarnings("unchecked") public static ProvisionListenerStackCallback emptyListener() { return (ProvisionListenerStackCallback) EMPTY_CALLBACK; @@ -55,30 +53,32 @@ this.listeners = deDuplicated.toArray(new ProvisionListener[deDuplicated.size()]); } } - + public boolean hasListeners() { return listeners.length > 0; } - public T provision(Errors errors, InternalContext context, ProvisionCallback callable) - throws ErrorsException { - Provision provision = new Provision(errors, context, callable); + public T provision(InternalContext context, ProvisionCallback callable) + throws InternalProvisionException { + Provision provision = new Provision(context, callable); RuntimeException caught = null; try { provision.provision(); - } catch(RuntimeException t) { + } catch (RuntimeException t) { caught = t; } - + if (provision.exceptionDuringProvision != null) { throw provision.exceptionDuringProvision; } else if (caught != null) { - Object listener = provision.erredListener != null ? - provision.erredListener.getClass() : "(unknown)"; - throw errors - .errorInUserCode(caught, "Error notifying ProvisionListener %s of %s.%n" - + " Reason: %s", listener, binding.getKey(), caught) - .toException(); + Object listener = + provision.erredListener != null ? provision.erredListener.getClass() : "(unknown)"; + throw InternalProvisionException.errorInUserCode( + caught, + "Error notifying ProvisionListener %s of %s.%n Reason: %s", + listener, + binding.getKey(), + caught); } else { return provision.result; } @@ -86,25 +86,22 @@ // TODO(sameb): Can this be more InternalFactory-like? public interface ProvisionCallback { - public T call() throws ErrorsException; + public T call() throws InternalProvisionException; } private class Provision extends ProvisionListener.ProvisionInvocation { - final Errors errors; - final int numErrorsBefore; final InternalContext context; + final ProvisionCallback callable; int index = -1; T result; - ErrorsException exceptionDuringProvision; + InternalProvisionException exceptionDuringProvision; ProvisionListener erredListener; - public Provision(Errors errors, InternalContext context, ProvisionCallback callable) { + public Provision(InternalContext context, ProvisionCallback callable) { this.callable = callable; this.context = context; - this.errors = errors; - this.numErrorsBefore = errors.size(); } @Override @@ -113,18 +110,15 @@ if (index == listeners.length) { try { result = callable.call(); - // Make sure we don't return the provisioned object if there were any errors - // injecting its field/method dependencies. - errors.throwIfNewErrors(numErrorsBefore); - } catch(ErrorsException ee) { - exceptionDuringProvision = ee; - throw new ProvisionException(errors.merge(ee.getErrors()).getMessages()); + } catch (InternalProvisionException ipe) { + exceptionDuringProvision = ipe; + throw ipe.toProvisionException(); } } else if (index < listeners.length) { int currentIdx = index; try { listeners[index].onProvision(this); - } catch(RuntimeException re) { + } catch (RuntimeException re) { erredListener = listeners[currentIdx]; throw re; } @@ -137,7 +131,7 @@ } return result; } - + @Override public Binding getBinding() { // TODO(sameb): Because so many places cast directly to BindingImpl & subclasses, @@ -145,10 +139,12 @@ // if someone calls that they'll get strange errors. return binding; } - + + @Deprecated @Override - public List getDependencyChain() { + public List getDependencyChain() { return context.getDependencyChain(); } + } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ProxyFactory.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ProxyFactory.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ProxyFactory.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ProxyFactory.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ package com.google.inject.internal; -import static com.google.inject.internal.BytecodeGen.newFastClass; +import static com.google.inject.internal.BytecodeGen.newFastClassForMember; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -24,16 +24,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.spi.InjectionPoint; - -import net.sf.cglib.core.MethodWrapper; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.CallbackFilter; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.reflect.FastClass; -import net.sf.cglib.reflect.FastConstructor; - -import org.aopalliance.intercept.MethodInterceptor; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -41,6 +31,12 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import net.sf.cglib.core.MethodWrapper; +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.CallbackFilter; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.reflect.FastClass; +import org.aopalliance.intercept.MethodInterceptor; /** * Builds a construction proxy that can participate in AOP. This class manages applying type and @@ -49,7 +45,7 @@ * @author jessewilson@google.com (Jesse Wilson) */ final class ProxyFactory implements ConstructionProxyFactory { - + private static final Logger logger = Logger.getLogger(ProxyFactory.class.getName()); private final InjectionPoint injectionPoint; @@ -68,7 +64,7 @@ this.injectionPoint = injectionPoint; @SuppressWarnings("unchecked") // the member of injectionPoint is always a Constructor - Constructor constructor = (Constructor) injectionPoint.getMember(); + Constructor constructor = (Constructor) injectionPoint.getMember(); declaringClass = constructor.getDeclaringClass(); // Find applicable aspects. Bow out if none are applicable to this class. @@ -101,12 +97,13 @@ for (MethodAspect methodAspect : applicableAspects) { for (MethodInterceptorsPair pair : methodInterceptorsPairs) { if (methodAspect.matches(pair.method)) { - if(pair.method.isSynthetic()) { - logger.log(Level.WARNING, + if (pair.method.isSynthetic()) { + logger.log( + Level.WARNING, "Method [{0}] is synthetic and is being intercepted by {1}." - + " This could indicate a bug. The method may be intercepted twice," - + " or may not be intercepted at all.", - new Object[] { pair.method, methodAspect.interceptors() }); + + " This could indicate a bug. The method may be intercepted twice," + + " or may not be intercepted at all.", + new Object[] {pair.method, methodAspect.interceptors()}); } visibility = visibility.and(BytecodeGen.Visibility.forMember(pair.method)); pair.addAll(methodAspect.interceptors()); @@ -142,18 +139,18 @@ callbacks[i] = new InterceptorStackCallback(pair.method, deDuplicated); } - interceptors = interceptorsMapBuilder != null - ? interceptorsMapBuilder.build() - : ImmutableMap.>of(); + interceptors = + interceptorsMapBuilder != null + ? interceptorsMapBuilder.build() + : ImmutableMap.>of(); } - /** - * Returns the interceptors that apply to the constructed type. - */ + /** Returns the interceptors that apply to the constructed type. */ public ImmutableMap> getInterceptors() { return interceptors; } + @Override public ConstructionProxy create() throws ErrorsException { if (interceptors.isEmpty()) { return new DefaultConstructionProxyFactory(injectionPoint).create(); @@ -172,10 +169,10 @@ // Create the proxied class. We're careful to ensure that all enhancer state is not-specific // to this injector. Otherwise, the proxies for each injector will waste PermGen memory try { - Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility); - enhancer.setCallbackFilter(new IndicesCallbackFilter(methods)); - enhancer.setCallbackTypes(callbackTypes); - return new ProxyConstructor(enhancer, injectionPoint, callbacks, interceptors); + Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility); + enhancer.setCallbackFilter(new IndicesCallbackFilter(methods)); + enhancer.setCallbackTypes(callbackTypes); + return new ProxyConstructor(enhancer, injectionPoint, callbacks, interceptors); } catch (Throwable e) { throw new Errors().errorEnhancingClass(declaringClass, e).toException(); } @@ -202,10 +199,9 @@ } /** - * A callback filter that maps methods to unique IDs. We define equals and - * hashCode without using any state related to the injector so that enhanced - * classes intercepting the same methods can be shared between injectors (and - * child injectors, etc). + * A callback filter that maps methods to unique IDs. We define equals and hashCode without using + * any state related to the injector so that enhanced classes intercepting the same methods can be + * shared between injectors (and child injectors, etc). */ private static class IndicesCallbackFilter implements CallbackFilter { final Map indices; @@ -220,63 +216,71 @@ this.hashCode = indices.hashCode(); } + @Override public int accept(Method method) { return indices.get(MethodWrapper.create(method)); } - @Override public boolean equals(Object o) { - return o instanceof IndicesCallbackFilter && - ((IndicesCallbackFilter) o).indices.equals(indices); + @Override + public boolean equals(Object o) { + return o instanceof IndicesCallbackFilter + && ((IndicesCallbackFilter) o).indices.equals(indices); } - @Override public int hashCode() { + @Override + public int hashCode() { return hashCode; } } - /** - * Constructs instances that participate in AOP. - */ + /** Constructs instances that participate in AOP. */ private static class ProxyConstructor implements ConstructionProxy { final Class enhanced; final InjectionPoint injectionPoint; final Constructor constructor; final Callback[] callbacks; - final FastConstructor fastConstructor; + final int constructorIndex; final ImmutableMap> methodInterceptors; + final FastClass fastClass; @SuppressWarnings("unchecked") // the constructor promises to construct 'T's - ProxyConstructor(Enhancer enhancer, InjectionPoint injectionPoint, Callback[] callbacks, + ProxyConstructor( + Enhancer enhancer, + InjectionPoint injectionPoint, + Callback[] callbacks, ImmutableMap> methodInterceptors) { this.enhanced = enhancer.createClass(); // this returns a cached class if possible this.injectionPoint = injectionPoint; this.constructor = (Constructor) injectionPoint.getMember(); this.callbacks = callbacks; this.methodInterceptors = methodInterceptors; - - FastClass fastClass = newFastClass(enhanced, BytecodeGen.Visibility.forMember(constructor)); - this.fastConstructor = fastClass.getConstructor(constructor.getParameterTypes()); + this.fastClass = newFastClassForMember(enhanced, constructor); + this.constructorIndex = fastClass.getIndex(constructor.getParameterTypes()); } + @Override @SuppressWarnings("unchecked") // the constructor promises to produce 'T's public T newInstance(Object... arguments) throws InvocationTargetException { Enhancer.registerCallbacks(enhanced, callbacks); try { - return (T) fastConstructor.newInstance(arguments); + return (T) fastClass.newInstance(constructorIndex, arguments); } finally { Enhancer.registerCallbacks(enhanced, null); } } + @Override public InjectionPoint getInjectionPoint() { return injectionPoint; } + @Override public Constructor getConstructor() { return constructor; } + @Override public ImmutableMap> getMethodInterceptors() { return methodInterceptors; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/RealElement.java sisu-guice-4.2.0/core/src/com/google/inject/internal/RealElement.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/RealElement.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/RealElement.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import com.google.inject.internal.Element.Type; +import java.lang.annotation.Annotation; +import java.util.concurrent.atomic.AtomicInteger; + +/** An implementation of Element. */ +// TODO(cgruber): Use AutoAnnotation when available, here & wherever else is makes sense. +class RealElement implements Element { + private static final AtomicInteger nextUniqueId = new AtomicInteger(1); + + private final int uniqueId; + private final String setName; + private final Element.Type type; + private final String keyType; + + RealElement(String setName, Element.Type type, String keyType) { + this(setName, type, keyType, nextUniqueId.incrementAndGet()); + } + + RealElement(String setName, Element.Type type, String keyType, int uniqueId) { + this.uniqueId = uniqueId; + this.setName = setName; + this.type = type; + this.keyType = keyType; + } + + @Override + public String setName() { + return setName; + } + + @Override + public int uniqueId() { + return uniqueId; + } + + @Override + public Element.Type type() { + return type; + } + + @Override + public String keyType() { + return keyType; + } + + @Override + public Class annotationType() { + return Element.class; + } + + @Override + public String toString() { + return "@" + + Element.class.getName() + + "(setName=" + + setName + + ",uniqueId=" + + uniqueId + + ", type=" + + type + + ", keyType=" + + keyType + + ")"; + } + + @Override + public boolean equals(Object o) { + return o instanceof Element + && ((Element) o).setName().equals(setName()) + && ((Element) o).uniqueId() == uniqueId() + && ((Element) o).type() == type() + && ((Element) o).keyType().equals(keyType()); + } + + @Override + public int hashCode() { + return ((127 * "setName".hashCode()) ^ setName.hashCode()) + + ((127 * "uniqueId".hashCode()) ^ uniqueId) + + ((127 * "type".hashCode()) ^ type.hashCode()) + + ((127 * "keyType".hashCode()) ^ keyType.hashCode()); + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/RealMapBinder.java sisu-guice-4.2.0/core/src/com/google/inject/internal/RealMapBinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/RealMapBinder.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/RealMapBinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,1344 @@ + +package com.google.inject.internal; + +import static com.google.inject.internal.Element.Type.MAPBINDER; +import static com.google.inject.internal.Errors.checkConfiguration; +import static com.google.inject.internal.Errors.checkNotNull; +import static com.google.inject.internal.RealMultibinder.setOf; +import static com.google.inject.util.Types.newParameterizedType; +import static com.google.inject.util.Types.newParameterizedTypeWithOwner; + +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import com.google.inject.Binder; +import com.google.inject.Binding; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.TypeLiteral; +import com.google.inject.binder.LinkedBindingBuilder; +import com.google.inject.internal.InternalProviderInstanceBindingImpl.InitializationTiming; +import com.google.inject.multibindings.MapBinderBinding; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.multibindings.MultibindingsTargetVisitor; +import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.Element; +import com.google.inject.spi.ProviderInstanceBinding; +import com.google.inject.spi.ProviderWithExtensionVisitor; +import com.google.inject.util.Types; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The actual mapbinder plays several roles: + * + *

    As a MapBinder, it acts as a factory for LinkedBindingBuilders for each of the map's values. + * It delegates to a {@link Multibinder} of entries (keys to value providers). + * + *

    As a Module, it installs the binding to the map itself, as well as to a corresponding map + * whose values are providers. + * + *

    As a module, this implements equals() and hashcode() in order to trick Guice into executing + * its configure() method only once. That makes it so that multiple mapbinders can be created for + * the same target map, but only one is bound. Since the list of bindings is retrieved from the + * injector itself (and not the mapbinder), each mapbinder has access to all contributions from all + * equivalent mapbinders. + * + *

    Rather than binding a single Map.Entry<K, V>, the map binder binds keys and values + * independently. This allows the values to be properly scoped. + */ +public final class RealMapBinder implements Module { + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with no binding annotation. + */ + public static RealMapBinder newMapRealBinder( + Binder binder, TypeLiteral keyType, TypeLiteral valueType) { + binder = binder.skipSources(RealMapBinder.class); + return newRealMapBinder( + binder, + keyType, + valueType, + Key.get(mapOf(keyType, valueType)), + RealMultibinder.newRealSetBinder(binder, Key.get(entryOfProviderOf(keyType, valueType)))); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with {@code annotation}. + */ + public static RealMapBinder newRealMapBinder( + Binder binder, TypeLiteral keyType, TypeLiteral valueType, Annotation annotation) { + binder = binder.skipSources(RealMapBinder.class); + return newRealMapBinder( + binder, + keyType, + valueType, + Key.get(mapOf(keyType, valueType), annotation), + RealMultibinder.newRealSetBinder( + binder, Key.get(entryOfProviderOf(keyType, valueType), annotation))); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with {@code annotationType}. + */ + public static RealMapBinder newRealMapBinder( + Binder binder, + TypeLiteral keyType, + TypeLiteral valueType, + Class annotationType) { + binder = binder.skipSources(RealMapBinder.class); + return newRealMapBinder( + binder, + keyType, + valueType, + Key.get(mapOf(keyType, valueType), annotationType), + RealMultibinder.newRealSetBinder( + binder, Key.get(entryOfProviderOf(keyType, valueType), annotationType))); + } + + @SuppressWarnings("unchecked") // a map of is safely a Map + static TypeLiteral> mapOf(TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>) + TypeLiteral.get(Types.mapOf(keyType.getType(), valueType.getType())); + } + + @SuppressWarnings("unchecked") // a provider map is safely a Map> + static TypeLiteral>> mapOfProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>) + TypeLiteral.get(Types.mapOf(keyType.getType(), Types.providerOf(valueType.getType()))); + } + + // provider map is safely a Map>> + @SuppressWarnings("unchecked") + static TypeLiteral>> mapOfJavaxProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>) + TypeLiteral.get( + Types.mapOf( + keyType.getType(), + newParameterizedType(javax.inject.Provider.class, valueType.getType()))); + } + + @SuppressWarnings("unchecked") // a provider map > is safely a Map>> + static TypeLiteral>>> mapOfSetOfProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>>) + TypeLiteral.get( + Types.mapOf(keyType.getType(), Types.setOf(Types.providerOf(valueType.getType())))); + } + + @SuppressWarnings("unchecked") // a provider map > is safely a Map>> + static TypeLiteral>>> mapOfSetOfJavaxProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>>) + TypeLiteral.get( + Types.mapOf( + keyType.getType(), Types.setOf(Types.javaxProviderOf(valueType.getType())))); + } + + @SuppressWarnings("unchecked") // a provider map > is safely a Map>> + static TypeLiteral>>> mapOfCollectionOfProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>>) + TypeLiteral.get( + Types.mapOf( + keyType.getType(), Types.collectionOf(Types.providerOf(valueType.getType())))); + } + + @SuppressWarnings("unchecked") // a provider map > is safely a Map>> + static + TypeLiteral>>> mapOfCollectionOfJavaxProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>>) + TypeLiteral.get( + Types.mapOf( + keyType.getType(), Types.collectionOf(Types.javaxProviderOf(valueType.getType())))); + } + + @SuppressWarnings("unchecked") // a provider entry is safely a Map.Entry> + static TypeLiteral>> entryOfProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>) + TypeLiteral.get( + newParameterizedTypeWithOwner( + Map.class, + Map.Entry.class, + keyType.getType(), + Types.providerOf(valueType.getType()))); + } + + @SuppressWarnings("unchecked") // a provider entry is safely a Map.Entry> + static TypeLiteral>> entryOfJavaxProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>) + TypeLiteral.get( + newParameterizedTypeWithOwner( + Map.class, + Map.Entry.class, + keyType.getType(), + Types.javaxProviderOf(valueType.getType()))); + } + + @SuppressWarnings("unchecked") // a provider entry is safely a Map.Entry> + static + TypeLiteral>>> setOfEntryOfJavaxProviderOf( + TypeLiteral keyType, TypeLiteral valueType) { + return (TypeLiteral>>>) + TypeLiteral.get(Types.setOf(entryOfJavaxProviderOf(keyType, valueType).getType())); + } + + /** Given a Key will return a Key> */ + @SuppressWarnings("unchecked") + private static Key> getKeyOfProvider(Key valueKey) { + return (Key>) + valueKey.ofType(Types.providerOf(valueKey.getTypeLiteral().getType())); + } + + // Note: We use valueTypeAndAnnotation effectively as a Pair + // since it's an easy way to group a type and an optional annotation type or instance. + static RealMapBinder newRealMapBinder( + Binder binder, TypeLiteral keyType, Key valueTypeAndAnnotation) { + binder = binder.skipSources(RealMapBinder.class); + TypeLiteral valueType = valueTypeAndAnnotation.getTypeLiteral(); + return newRealMapBinder( + binder, + keyType, + valueType, + valueTypeAndAnnotation.ofType(mapOf(keyType, valueType)), + RealMultibinder.newRealSetBinder( + binder, valueTypeAndAnnotation.ofType(entryOfProviderOf(keyType, valueType)))); + } + + private static RealMapBinder newRealMapBinder( + Binder binder, + TypeLiteral keyType, + TypeLiteral valueType, + Key> mapKey, + RealMultibinder>> entrySetBinder) { + RealMapBinder mapBinder = + new RealMapBinder(binder, keyType, valueType, mapKey, entrySetBinder); + binder.install(mapBinder); + return mapBinder; + } + + // Until the injector initializes us, we don't know what our dependencies are, + // so initialize to the whole Injector. + private static final ImmutableSet> MODULE_DEPENDENCIES = + ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); + + private final BindingSelection bindingSelection; + private final Binder binder; + + private final RealMultibinder>> entrySetBinder; + + private RealMapBinder( + Binder binder, + TypeLiteral keyType, + TypeLiteral valueType, + Key> mapKey, + RealMultibinder>> entrySetBinder) { + this.bindingSelection = new BindingSelection<>(keyType, valueType, mapKey, entrySetBinder); + this.binder = binder; + this.entrySetBinder = entrySetBinder; + } + + public void permitDuplicates() { + checkConfiguration(!bindingSelection.isInitialized(), "MapBinder was already initialized"); + entrySetBinder.permitDuplicates(); + binder.install(new MultimapBinder(bindingSelection)); + } + + /** Adds a binding to the map for the given key. */ + Key getKeyForNewValue(K key) { + checkNotNull(key, "key"); + checkConfiguration(!bindingSelection.isInitialized(), "MapBinder was already initialized"); + RealMultibinder>> entrySetBinder = + bindingSelection.getEntrySetBinder(); + + Key valueKey = + Key.get( + bindingSelection.getValueType(), + new RealElement( + entrySetBinder.getSetName(), MAPBINDER, bindingSelection.getKeyType().toString())); + entrySetBinder.addBinding().toProvider(new ProviderMapEntry(key, valueKey)); + return valueKey; + } + + /** + * This creates two bindings. One for the {@code Map.Entry>} and another for {@code + * V}. + */ + public LinkedBindingBuilder addBinding(K key) { + return binder.bind(getKeyForNewValue(key)); + } + + @Override + public void configure(Binder binder) { + checkConfiguration(!bindingSelection.isInitialized(), "MapBinder was already initialized"); + + // Binds a Map> + RealProviderMapProvider providerMapProvider = + new RealProviderMapProvider(bindingSelection); + binder.bind(bindingSelection.getProviderMapKey()).toProvider(providerMapProvider); + + // The map this exposes is internally an ImmutableMap, so it's OK to massage + // the guice Provider to javax Provider in the value (since Guice provider + // implements javax Provider). + @SuppressWarnings({"unchecked", "rawtypes"}) + Provider>> javaxProviderMapProvider = + (Provider) providerMapProvider; + binder.bind(bindingSelection.getJavaxProviderMapKey()).toProvider(javaxProviderMapProvider); + + RealMapProvider mapProvider = new RealMapProvider<>(bindingSelection); + binder.bind(bindingSelection.getMapKey()).toProvider(mapProvider); + + // The Map.Entries are all ProviderMapEntry instances which do not allow setValue, so it is + // safe to massage the return type like this + @SuppressWarnings({"unchecked", "rawtypes"}) + Key>>> massagedEntrySetProviderKey = + (Key) bindingSelection.getEntrySetBinder().getSetKey(); + binder.bind(bindingSelection.getEntrySetJavaxProviderKey()).to(massagedEntrySetProviderKey); + } + + @Override + public boolean equals(Object o) { + return o instanceof RealMapBinder + && ((RealMapBinder) o).bindingSelection.equals(bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + + /** + * The BindingSelection contains some of the core state and logic for the MapBinder. + * + *

    It lazily computes the value for keys for various permutations of Maps that are provided by + * this module. It also builds up maps from {@code K} to {@code Binding}, which is used by all + * of the internal factories to actually provide the desired maps. + * + *

    During initialization time there is only one BindingSelection. It is possible that multiple + * different BindingSelections are constructed. Specifically, in the case of two different modules + * each adding bindings to the same MapBinder. If that happens, we define the BindingSelection + * held by the {@link RealMapProvider} to be the authoritative one. The logic for this exists in + * {@link RealMultimapBinderProviderWithDependencies}. This is done to avoid confusion because the + * BindingSelection contains mutable state. + */ + private static final class BindingSelection { + private enum InitializationState { + UNINITIALIZED, + INITIALIZED, + HAS_ERRORS; + } + + private final TypeLiteral keyType; + private final TypeLiteral valueType; + private final Key> mapKey; + + // Lazily computed + private Key>> javaxProviderMapKey; + private Key>> providerMapKey; + private Key>> multimapKey; + private Key>>> providerSetMultimapKey; + private Key>>> javaxProviderSetMultimapKey; + private Key>>> providerCollectionMultimapKey; + private Key>>> javaxProviderCollectionMultimapKey; + private Key>>> entrySetJavaxProviderKey; + + private final RealMultibinder>> entrySetBinder; + + private InitializationState initializationState; + + /** + * These are built during initialization and used by all factories to actually provide the + * relevant maps. These contain all of the necessary information about the map binder. + */ + private ImmutableMap> mapBindings; + + private ImmutableMap>> multimapBindings; + private ImmutableList>> entries; + + /** + * Indicates if this Map permits duplicates. It is initialized during initialization by querying + * the injector. This is done because multiple different modules can contribute to a MapBinder, + * and any one could set permitDuplicates. + */ + private boolean permitsDuplicates; + + private BindingSelection( + TypeLiteral keyType, + TypeLiteral valueType, + Key> mapKey, + RealMultibinder>> entrySetBinder) { + this.keyType = keyType; + this.valueType = valueType; + this.mapKey = mapKey; + this.entrySetBinder = entrySetBinder; + this.initializationState = InitializationState.UNINITIALIZED; + } + + /** + * Will initialize internal data structures. + * + * @return {@code true} if initialization was successful, {@code false} if there were errors + */ + private boolean tryInitialize(InjectorImpl injector, Errors errors) { + // Every one of our providers will call this method, so only execute the logic once. + if (initializationState != InitializationState.UNINITIALIZED) { + return initializationState != InitializationState.HAS_ERRORS; + } + + // Multiple different modules can all contribute to the same MapBinder, and if any + // one of them permits duplicates, then the map binder as a whole will permit duplicates. + // Since permitDuplicates() may not have been called on this instance, we need to go + // to the injector to see if permitDuplicates was set. + permitsDuplicates = entrySetBinder.permitsDuplicates(injector); + + // We now build the Map>> from the entrySetBinder. + // The entrySetBinder contains all of the ProviderMapEntrys, and once + // we have those, it's easy to iterate through them to organize them by K. + Map>> bindingMultimapMutable = + new LinkedHashMap>>(); + Map> bindingMapMutable = new LinkedHashMap<>(); + Multimap index = HashMultimap.create(); + Indexer indexer = new Indexer(injector); + Multimap> duplicates = null; + + ImmutableList.Builder>> entriesBuilder = ImmutableList.builder(); + + // We get all of the Bindings that were put into the entrySetBinder + for (Binding>> binding : + injector.findBindingsByType(entrySetBinder.getElementTypeLiteral())) { + if (entrySetBinder.containsElement(binding)) { + + // Protected by findBindingByType() and the fact that all providers are added by us + // in addBinding(). It would theoretically be possible for someone to directly + // add their own binding to the entrySetBinder, but they shouldn't do that. + @SuppressWarnings({"unchecked", "rawtypes"}) + ProviderInstanceBinding> entryBinding = + (ProviderInstanceBinding) binding; + + // We added all these bindings initially, so we know they are ProviderMapEntrys + @SuppressWarnings({"unchecked", "rawtypes"}) + ProviderMapEntry entry = (ProviderMapEntry) entryBinding.getUserSuppliedProvider(); + K key = entry.getKey(); + + Key valueKey = entry.getValueKey(); + Binding valueBinding = injector.getExistingBinding(valueKey); + + // Use the indexer to de-dupe user bindings. This is needed because of the + // uniqueId in RealElement. The uniqueId intentionally circumvents the regular + // Guice deduplication, so we need to re-implement our own here, ignoring + // uniqueId. + if (index.put(key, valueBinding.acceptTargetVisitor(indexer))) { + + entriesBuilder.add(Maps.immutableEntry(key, valueBinding)); + + Binding previous = bindingMapMutable.put(key, valueBinding); + // Check if this is a duplicate binding + if (previous != null && !permitsDuplicates) { + if (duplicates == null) { + // This is linked for both keys and values to maintain order + duplicates = LinkedHashMultimap.create(); + } + + // We add both the previous and the current value to the duplicates map. + // This is because if there are three duplicates, we will only execute this code + // for the second and third, but we want all three values to display a helpful + // error message. We rely on the multimap to dedupe repeated values. + duplicates.put(key, previous); + duplicates.put(key, valueBinding); + } + + // Don't do extra work unless we need to + if (permitsDuplicates) { + // Create a set builder for this key if it's the first time we've seen it + if (!bindingMultimapMutable.containsKey(key)) { + bindingMultimapMutable.put(key, ImmutableSet.>builder()); + } + + // Add the Binding + bindingMultimapMutable.get(key).add(valueBinding); + } + } + } + } + + // It is safe to check if duplicates is non-null because if duplicates are allowed, + // we don't build up this data structure + if (duplicates != null) { + initializationState = InitializationState.HAS_ERRORS; + reportDuplicateKeysError(duplicates, errors); + + return false; + } + + // Build all of the ImmutableSet.Builders, + // transforming from Map>> to + // ImmutableMap>> + ImmutableMap.Builder>> bindingsMultimapBuilder = ImmutableMap.builder(); + for (Map.Entry>> entry : + bindingMultimapMutable.entrySet()) { + bindingsMultimapBuilder.put(entry.getKey(), entry.getValue().build()); + } + mapBindings = ImmutableMap.copyOf(bindingMapMutable); + multimapBindings = bindingsMultimapBuilder.build(); + + entries = entriesBuilder.build(); + + initializationState = InitializationState.INITIALIZED; + + return true; + } + + private static void reportDuplicateKeysError( + Multimap> duplicates, Errors errors) { + StringBuilder sb = new StringBuilder("Map injection failed due to duplicated key "); + boolean first = true; + for (Map.Entry>> entry : duplicates.asMap().entrySet()) { + K dupKey = entry.getKey(); + + if (first) { + first = false; + sb.append("\"" + dupKey + "\", from bindings:\n"); + } else { + sb.append("\n and key: \"" + dupKey + "\", from bindings:\n"); + } + + for (Binding dup : entry.getValue()) { + sb.append("\t at " + Errors.convert(dup.getSource()) + "\n"); + } + } + + // TODO(user): Add a different error for every duplicated key + errors.addMessage(sb.toString()); + } + + private boolean containsElement(Element element) { + if (entrySetBinder.containsElement(element)) { + return true; + } + + Key key; + if (element instanceof Binding) { + key = ((Binding) element).getKey(); + } else { + return false; // cannot match; + } + + return key.equals(getMapKey()) + || key.equals(getProviderMapKey()) + || key.equals(getJavaxProviderMapKey()) + || key.equals(getMultimapKey()) + || key.equals(getProviderSetMultimapKey()) + || key.equals(getJavaxProviderSetMultimapKey()) + || key.equals(getProviderCollectionMultimapKey()) + || key.equals(getJavaxProviderCollectionMultimapKey()) + || key.equals(entrySetBinder.getSetKey()) + || key.equals(getEntrySetJavaxProviderKey()) + || matchesValueKey(key); + } + + /** Returns true if the key indicates this is a value in the map. */ + private boolean matchesValueKey(Key key) { + return key.getAnnotation() instanceof RealElement + && ((RealElement) key.getAnnotation()).setName().equals(entrySetBinder.getSetName()) + && ((RealElement) key.getAnnotation()).type() == MAPBINDER + && ((RealElement) key.getAnnotation()).keyType().equals(keyType.toString()) + && key.getTypeLiteral().equals(valueType); + } + + private Key>> getProviderMapKey() { + Key>> local = providerMapKey; + if (local == null) { + local = providerMapKey = mapKey.ofType(mapOfProviderOf(keyType, valueType)); + } + return local; + } + + private Key>> getJavaxProviderMapKey() { + Key>> local = javaxProviderMapKey; + if (local == null) { + local = javaxProviderMapKey = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); + } + return local; + } + + private Key>> getMultimapKey() { + Key>> local = multimapKey; + if (local == null) { + local = multimapKey = mapKey.ofType(mapOf(keyType, setOf(valueType))); + } + return local; + } + + private Key>>> getProviderSetMultimapKey() { + Key>>> local = providerSetMultimapKey; + if (local == null) { + local = providerSetMultimapKey = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); + } + return local; + } + + private Key>>> getJavaxProviderSetMultimapKey() { + Key>>> local = javaxProviderSetMultimapKey; + if (local == null) { + local = + javaxProviderSetMultimapKey = + mapKey.ofType(mapOfSetOfJavaxProviderOf(keyType, valueType)); + } + return local; + } + + private Key>>> getProviderCollectionMultimapKey() { + Key>>> local = providerCollectionMultimapKey; + if (local == null) { + local = + providerCollectionMultimapKey = + mapKey.ofType(mapOfCollectionOfProviderOf(keyType, valueType)); + } + return local; + } + + private Key>>> + getJavaxProviderCollectionMultimapKey() { + Key>>> local = javaxProviderCollectionMultimapKey; + if (local == null) { + local = + javaxProviderCollectionMultimapKey = + mapKey.ofType(mapOfCollectionOfJavaxProviderOf(keyType, valueType)); + } + return local; + } + + private Key>>> getEntrySetJavaxProviderKey() { + Key>>> local = entrySetJavaxProviderKey; + if (local == null) { + local = + entrySetJavaxProviderKey = + mapKey.ofType(setOfEntryOfJavaxProviderOf(keyType, valueType)); + } + return local; + } + + private ImmutableMap> getMapBindings() { + checkConfiguration(isInitialized(), "MapBinder has not yet been initialized"); + return mapBindings; + } + + private ImmutableMap>> getMultimapBindings() { + checkConfiguration(isInitialized(), "MapBinder has not yet been initialized"); + return multimapBindings; + } + + private ImmutableList>> getEntries() { + checkConfiguration(isInitialized(), "MapBinder has not yet been initialized"); + return entries; + } + + private boolean isInitialized() { + return initializationState == InitializationState.INITIALIZED; + } + + private TypeLiteral getKeyType() { + return keyType; + } + + private TypeLiteral getValueType() { + return valueType; + } + + private Key> getMapKey() { + return mapKey; + } + + private RealMultibinder>> getEntrySetBinder() { + return entrySetBinder; + } + + private boolean permitsDuplicates() { + if (isInitialized()) { + return permitsDuplicates; + } else { + throw new UnsupportedOperationException( + "permitsDuplicates() not supported for module bindings"); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof BindingSelection && ((BindingSelection) o).mapKey.equals(mapKey); + } + + @Override + public int hashCode() { + return mapKey.hashCode(); + } + } + + private static final class RealProviderMapProvider + extends RealMapBinderProviderWithDependencies>> { + private Map> mapOfProviders; + private Set> dependencies = RealMapBinder.MODULE_DEPENDENCIES; + + private RealProviderMapProvider(BindingSelection bindingSelection) { + super(bindingSelection); + } + + @Override + public Set> getDependencies() { + return dependencies; + } + + @Override + protected void doInitialize(InjectorImpl injector, Errors errors) { + ImmutableMap.Builder> mapOfProvidersBuilder = ImmutableMap.builder(); + ImmutableSet.Builder> dependenciesBuilder = ImmutableSet.builder(); + for (Map.Entry> entry : bindingSelection.getMapBindings().entrySet()) { + mapOfProvidersBuilder.put(entry.getKey(), entry.getValue().getProvider()); + dependenciesBuilder.add(Dependency.get(getKeyOfProvider(entry.getValue().getKey()))); + } + + mapOfProviders = mapOfProvidersBuilder.build(); + dependencies = dependenciesBuilder.build(); + } + + @Override + protected Map> doProvision(InternalContext context, Dependency dependency) { + return mapOfProviders; + } + } + + private static final class RealMapProvider + extends RealMapBinderProviderWithDependencies> + implements ProviderWithExtensionVisitor>, MapBinderBinding> { + private Set> dependencies = RealMapBinder.MODULE_DEPENDENCIES; + + /** + * An array of all the injectors. + * + *

    This is parallel to array of keys below + */ + private SingleParameterInjector[] injectors; + + private K[] keys; + + private RealMapProvider(BindingSelection bindingSelection) { + super(bindingSelection); + } + + private BindingSelection getBindingSelection() { + return bindingSelection; + } + + @Override + protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException { + @SuppressWarnings("unchecked") + K[] keysArray = (K[]) new Object[bindingSelection.getMapBindings().size()]; + keys = keysArray; + ImmutableSet.Builder> dependenciesBuilder = ImmutableSet.builder(); + int i = 0; + for (Map.Entry> entry : bindingSelection.getMapBindings().entrySet()) { + dependenciesBuilder.add(Dependency.get(entry.getValue().getKey())); + keys[i] = entry.getKey(); + i++; + } + + ImmutableSet> localDependencies = dependenciesBuilder.build(); + dependencies = localDependencies; + + List> dependenciesList = localDependencies.asList(); + + // We know the type because we built up our own sets of dependencies, it's just + // that the interface uses a "?" generic + @SuppressWarnings("unchecked") + SingleParameterInjector[] typedInjectors = + (SingleParameterInjector[]) injector.getParametersInjectors(dependenciesList, errors); + injectors = typedInjectors; + } + + @Override + protected Map doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException { + SingleParameterInjector[] localInjectors = injectors; + if (localInjectors == null) { + // if injectors == null, then we have no bindings so return the empty map. + return ImmutableMap.of(); + } + + ImmutableMap.Builder resultBuilder = ImmutableMap.builder(); + K[] localKeys = keys; + for (int i = 0; i < localInjectors.length; i++) { + SingleParameterInjector injector = localInjectors[i]; + K key = localKeys[i]; + + V value = injector.inject(context); + + if (value == null) { + throw createNullValueException(key, bindingSelection.getMapBindings().get(key)); + } + + resultBuilder.put(key, value); + } + + return resultBuilder.build(); + } + + @Override + public Set> getDependencies() { + return dependencies; + } + + @Override + @SuppressWarnings("unchecked") + public W acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, W>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + + @Override + public Key> getMapKey() { + return bindingSelection.getMapKey(); + } + + @Override + public TypeLiteral getKeyTypeLiteral() { + return bindingSelection.getKeyType(); + } + + @Override + public TypeLiteral getValueTypeLiteral() { + return bindingSelection.getValueType(); + } + + @Override + @SuppressWarnings("unchecked") + public List>> getEntries() { + if (bindingSelection.isInitialized()) { + return (List>>) (List) bindingSelection.getEntries(); + } else { + throw new UnsupportedOperationException("getEntries() not supported for module bindings"); + } + } + + @Override + public List>> getEntries(Iterable elements) { + // Iterate over the elements, building up the below maps + // This is a preprocessing step allowing us to only iterate over elements + // once and have O(n) runtime + ImmutableMultimap.Builder> keyToValueKeyBuilder = ImmutableMultimap.builder(); + ImmutableMap.Builder, Binding> valueKeyToBindingBuilder = ImmutableMap.builder(); + ImmutableMap.Builder, K> valueKeyToKeyBuilder = ImmutableMap.builder(); + ImmutableMap.Builder, Binding>>> + valueKeyToEntryBindingBuilder = ImmutableMap.builder(); + for (Element element : elements) { + if (element instanceof Binding) { + Binding binding = (Binding) element; + if (bindingSelection.matchesValueKey(binding.getKey()) + && binding.getKey().getTypeLiteral().equals(bindingSelection.valueType)) { + // Safe because of the check on the type literal above + @SuppressWarnings("unchecked") + Binding typedBinding = (Binding) binding; + Key typedKey = typedBinding.getKey(); + valueKeyToBindingBuilder.put(typedKey, typedBinding); + } + } + + if (element instanceof ProviderInstanceBinding + && bindingSelection.getEntrySetBinder().containsElement(element)) { + // Safe because of the instanceof check, and containsElement() check + @SuppressWarnings({"unchecked", "rawtypes"}) + ProviderInstanceBinding>> entryBinding = + (ProviderInstanceBinding) element; + + // Safe because of the check for containsElement() above + @SuppressWarnings("unchecked") + Provider>> typedProvider = + (Provider>>) entryBinding.getUserSuppliedProvider(); + Provider>> userSuppliedProvider = typedProvider; + + if (userSuppliedProvider instanceof ProviderMapEntry) { + // Safe because of the instanceof check + @SuppressWarnings("unchecked") + ProviderMapEntry typedUserSuppliedProvider = + (ProviderMapEntry) userSuppliedProvider; + ProviderMapEntry entry = typedUserSuppliedProvider; + + keyToValueKeyBuilder.put(entry.getKey(), entry.getValueKey()); + valueKeyToEntryBindingBuilder.put(entry.getValueKey(), entryBinding); + valueKeyToKeyBuilder.put(entry.getValueKey(), entry.getKey()); + } + } + } + + ImmutableMultimap> keyToValueKey = keyToValueKeyBuilder.build(); + ImmutableMap, K> valueKeyToKey = valueKeyToKeyBuilder.build(); + ImmutableMap, Binding> valueKeyToBinding = valueKeyToBindingBuilder.build(); + ImmutableMap, Binding>>> valueKeyToEntryBinding = + valueKeyToEntryBindingBuilder.build(); + + // Check that there is a 1:1 mapping from keys from the ProviderMapEntrys to the + // keys from the Bindings. + Set> keysFromProviderMapEntrys = Sets.newHashSet(keyToValueKey.values()); + Set> keysFromBindings = valueKeyToBinding.keySet(); + + if (!keysFromProviderMapEntrys.equals(keysFromBindings)) { + Set> keysOnlyFromProviderMapEntrys = + Sets.difference(keysFromProviderMapEntrys, keysFromBindings); + Set> keysOnlyFromBindings = + Sets.difference(keysFromBindings, keysFromProviderMapEntrys); + + StringBuilder sb = new StringBuilder("Expected a 1:1 mapping from map keys to values."); + + if (!keysOnlyFromBindings.isEmpty()) { + sb.append( + Errors.format("%nFound these Bindings that were missing an associated entry:%n")); + for (Key key : keysOnlyFromBindings) { + sb.append( + Errors.format(" %s bound at: %s%n", key, valueKeyToBinding.get(key).getSource())); + } + } + + if (!keysOnlyFromProviderMapEntrys.isEmpty()) { + sb.append(Errors.format("%nFound these map keys without a corresponding value:%n")); + for (Key key : keysOnlyFromProviderMapEntrys) { + sb.append( + Errors.format( + " '%s' bound at: %s%n", + valueKeyToKey.get(key), valueKeyToEntryBinding.get(key).getSource())); + } + } + + throw new IllegalArgumentException(sb.toString()); + } + + // Now that we have the two maps, generate the result map + ImmutableList.Builder>> resultBuilder = ImmutableList.builder(); + for (Map.Entry> entry : keyToValueKey.entries()) { + Binding binding = valueKeyToBinding.get(entry.getValue()); + // No null check for binding needed because of the above check to make sure all the + // values in keyToValueKey are present as keys in valueKeyToBinding + + @SuppressWarnings({"unchecked", "rawtypes"}) + Map.Entry> newEntry = + (Map.Entry) Maps.immutableEntry(entry.getKey(), binding); + resultBuilder.add(newEntry); + } + return resultBuilder.build(); + } + + @Override + public boolean permitsDuplicates() { + if (bindingSelection.isInitialized()) { + return bindingSelection.permitsDuplicates(); + } else { + throw new UnsupportedOperationException( + "permitsDuplicates() not supported for module bindings"); + } + } + + @Override + public boolean containsElement(Element element) { + return bindingSelection.containsElement(element); + } + } + + /** + * Binds {@code Map>} and {{@code Map>>}. + * + *

    This will only exist if permitDuplicates() is called. + */ + private static final class MultimapBinder implements Module { + private final BindingSelection bindingSelection; + + private MultimapBinder(BindingSelection bindingSelection) { + this.bindingSelection = bindingSelection; + } + + @Override + public void configure(Binder binder) { + // Binds a Map>> + Provider>>> multimapProvider = + new RealProviderMultimapProvider(bindingSelection.getMapKey()); + binder.bind(bindingSelection.getProviderSetMultimapKey()).toProvider(multimapProvider); + + // Provide links from a few different public keys to the providerMultimapKey. + // The collection this exposes is internally an ImmutableMap, so it's OK to massage + // the guice Provider to javax Provider in the value (since the guice Provider implements + // javax Provider). + @SuppressWarnings({"unchecked", "rawtypes"}) + Provider>>> javaxProvider = (Provider) multimapProvider; + binder.bind(bindingSelection.getJavaxProviderSetMultimapKey()).toProvider(javaxProvider); + + @SuppressWarnings({"unchecked", "rawtypes"}) + Provider>>> collectionProvider = (Provider) multimapProvider; + binder + .bind(bindingSelection.getProviderCollectionMultimapKey()) + .toProvider(collectionProvider); + + @SuppressWarnings({"unchecked", "rawtypes"}) + Provider>>> collectionJavaxProvider = + (Provider) multimapProvider; + binder + .bind(bindingSelection.getJavaxProviderCollectionMultimapKey()) + .toProvider(collectionJavaxProvider); + + // Binds a Map> + @SuppressWarnings({"unchecked", "rawtypes"}) + Provider>> realMultimapProvider = + new RealMultimapProvider(bindingSelection.getMapKey()); + binder.bind(bindingSelection.getMultimapKey()).toProvider(realMultimapProvider); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + + @Override + public boolean equals(Object o) { + return o instanceof MultimapBinder + && ((MultimapBinder) o).bindingSelection.equals(bindingSelection); + } + + private static final class RealProviderMultimapProvider + extends RealMultimapBinderProviderWithDependencies>>> { + private Map>> multimapOfProviders; + private Set> dependencies = RealMapBinder.MODULE_DEPENDENCIES; + + private RealProviderMultimapProvider(Key> mapKey) { + super(mapKey); + } + + @Override + public Set> getDependencies() { + return dependencies; + } + + @Override + protected void doInitialize(InjectorImpl injector, Errors errors) { + ImmutableMap.Builder>> multimapOfProvidersBuilder = + ImmutableMap.builder(); + ImmutableSet.Builder> dependenciesBuilder = ImmutableSet.builder(); + for (Map.Entry>> entry : + bindingSelection.getMultimapBindings().entrySet()) { + ImmutableSet.Builder> providersBuilder = ImmutableSet.builder(); + for (Binding binding : entry.getValue()) { + providersBuilder.add(binding.getProvider()); + dependenciesBuilder.add(Dependency.get(getKeyOfProvider(binding.getKey()))); + } + + multimapOfProvidersBuilder.put(entry.getKey(), providersBuilder.build()); + } + multimapOfProviders = multimapOfProvidersBuilder.build(); + dependencies = dependenciesBuilder.build(); + } + + @Override + protected Map>> doProvision( + InternalContext context, Dependency dependency) { + return multimapOfProviders; + } + } + + private static final class RealMultimapProvider + extends RealMultimapBinderProviderWithDependencies>> { + + /** + * A simple class to hold a key and the associated bindings as an array. + * + *

    Arrays are used for performance. + */ + private static final class PerKeyData { + private final K key; + private final Binding[] bindings; + private final SingleParameterInjector[] injectors; + + private PerKeyData(K key, Binding[] bindings, SingleParameterInjector[] injectors) { + Preconditions.checkArgument(bindings.length == injectors.length); + + this.key = key; + this.bindings = bindings; + this.injectors = injectors; + } + } + + private Set> dependencies = RealMapBinder.MODULE_DEPENDENCIES; + + private PerKeyData[] perKeyDatas; + + private RealMultimapProvider(Key> mapKey) { + super(mapKey); + } + + @Override + public Set> getDependencies() { + return dependencies; + } + + @Override + protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException { + @SuppressWarnings({"unchecked", "rawtypes"}) + PerKeyData[] typedPerKeyData = + new PerKeyData[bindingSelection.getMapBindings().size()]; + perKeyDatas = typedPerKeyData; + ImmutableSet.Builder> dependenciesBuilder = ImmutableSet.builder(); + List> dependenciesForKey = Lists.newArrayList(); + int i = 0; + for (Map.Entry>> entry : + bindingSelection.getMultimapBindings().entrySet()) { + // Clear the list of dependencies because we're reusing it for each different key + dependenciesForKey.clear(); + + Set> bindings = entry.getValue(); + @SuppressWarnings({"unchecked", "rawtypes"}) + Binding[] typedBindings = new Binding[bindings.size()]; + Binding[] bindingsArray = typedBindings; + int j = 0; + for (Binding binding : bindings) { + Dependency dependency = Dependency.get(binding.getKey()); + dependenciesBuilder.add(dependency); + dependenciesForKey.add(dependency); + bindingsArray[j] = binding; + j++; + } + + @SuppressWarnings("unchecked") + SingleParameterInjector[] injectors = + (SingleParameterInjector[]) + injector.getParametersInjectors(dependenciesForKey, errors); + + perKeyDatas[i] = new PerKeyData<>(entry.getKey(), bindingsArray, injectors); + i++; + } + + dependencies = dependenciesBuilder.build(); + } + + @Override + protected Map> doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException { + ImmutableMap.Builder> resultBuilder = ImmutableMap.builder(); + + for (PerKeyData perKeyData : perKeyDatas) { + ImmutableSet.Builder bindingsBuilder = ImmutableSet.builder(); + SingleParameterInjector[] injectors = perKeyData.injectors; + for (int i = 0; i < injectors.length; i++) { + SingleParameterInjector injector = injectors[i]; + V value = injector.inject(context); + + if (value == null) { + throw createNullValueException(perKeyData.key, perKeyData.bindings[i]); + } + + bindingsBuilder.add(value); + } + + resultBuilder.put(perKeyData.key, bindingsBuilder.build()); + } + + return resultBuilder.build(); + } + } + } + + /** A factory for a {@code Map.Entry>}. */ + //VisibleForTesting + static final class ProviderMapEntry + extends InternalProviderInstanceBindingImpl.Factory>> { + private final K key; + private final Key valueKey; + private Map.Entry> entry; + + ProviderMapEntry(K key, Key valueKey) { + super(InitializationTiming.EAGER); + this.key = key; + this.valueKey = valueKey; + } + + @Override + public Set> getDependencies() { + // The dependencies are Key> + return ImmutableSet.>of(Dependency.get(getKeyOfProvider(valueKey))); + } + + @Override + void initialize(InjectorImpl injector, Errors errors) { + Binding valueBinding = injector.getExistingBinding(valueKey); + entry = Maps.immutableEntry(key, valueBinding.getProvider()); + } + + @Override + protected Map.Entry> doProvision( + InternalContext context, Dependency dependency) { + return entry; + } + + K getKey() { + return key; + } + + Key getValueKey() { + return valueKey; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ProviderMapEntry) { + ProviderMapEntry o = (ProviderMapEntry) obj; + return key.equals(o.key) && valueKey.equals(o.valueKey); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(key, valueKey); + } + + @Override + public String toString() { + return "ProviderMapEntry(" + key + ", " + valueKey + ")"; + } + } + + /** A base class for ProviderWithDependencies that need equality based on a specific object. */ + private abstract static class RealMapBinderProviderWithDependencies + extends InternalProviderInstanceBindingImpl.Factory

    { + final BindingSelection bindingSelection; + + private RealMapBinderProviderWithDependencies(BindingSelection bindingSelection) { + // While MapBinders only depend on bindings created in modules so we could theoretically + // initialize eagerly, they also depend on + // 1. findBindingsByType returning results + // 2. being able to call BindingImpl.acceptTargetVisitor + // neither of those is available during eager initialization, so we use DELAYED + super(InitializationTiming.DELAYED); + + this.bindingSelection = bindingSelection; + } + + @Override + final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + if (bindingSelection.tryInitialize(injector, errors)) { + doInitialize(injector, errors); + } + } + + /** + * Initialize the factory. BindingSelection is guaranteed to be initialized at this point and + * this will be called prior to any provisioning. + */ + protected abstract void doInitialize(InjectorImpl injector, Errors errors) + throws ErrorsException; + + @Override + public boolean equals(Object obj) { + return obj != null + && this.getClass() == obj.getClass() + && bindingSelection.equals( + ((RealMapBinderProviderWithDependencies) obj).bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + } + + /** + * A base class for ProviderWithDependencies that need equality based on a specific object. + * + *

    This differs from {@link RealMapBinderProviderWithDependencies} in that it gets the {@code + * bindingSelection} from the injector at initialization time, rather than in the constructor. + * This is done to allow all the providers to operate on the same instance of the {@link + * BindingSelection}. + */ + private abstract static class RealMultimapBinderProviderWithDependencies + extends InternalProviderInstanceBindingImpl.Factory

    { + final Key> mapKey; + BindingSelection bindingSelection; + + private RealMultimapBinderProviderWithDependencies(Key> mapKey) { + // While MapBinders only depend on bindings created in modules so we could theoretically + // initialize eagerly, they also depend on + // 1. findBindingsByType returning results + // 2. being able to call BindingImpl.acceptTargetVisitor + // neither of those is available during eager initialization, so we use DELAYED + super(InitializationTiming.DELAYED); + + this.mapKey = mapKey; + } + + /** + * This will get the authoritative {@link BindingSelection} from the map provider. This + * guarantees that everyone has the same instance of the bindingSelection and sees consistent + * state. + */ + @Override + final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + Binding> mapBinding = injector.getExistingBinding(mapKey); + ProviderInstanceBinding> providerInstanceBinding = + (ProviderInstanceBinding>) mapBinding; + @SuppressWarnings("unchecked") + RealMapProvider mapProvider = + (RealMapProvider) providerInstanceBinding.getUserSuppliedProvider(); + + this.bindingSelection = mapProvider.getBindingSelection(); + + if (bindingSelection.tryInitialize(injector, errors)) { + doInitialize(injector, errors); + } + } + + /** + * Initialize the factory. BindingSelection is guaranteed to be initialized at this point and + * this will be called prior to any provisioning. + */ + abstract void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException; + + @Override + public boolean equals(Object obj) { + return obj != null + && this.getClass() == obj.getClass() + && mapKey.equals(((RealMultimapBinderProviderWithDependencies) obj).mapKey); + } + + @Override + public int hashCode() { + return mapKey.hashCode(); + } + } + + private static InternalProvisionException createNullValueException( + K key, Binding binding) { + return InternalProvisionException.create( + "Map injection failed due to null value for key \"%s\", bound at: %s", + key, binding.getSource()); + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/RealMultibinder.java sisu-guice-4.2.0/core/src/com/google/inject/internal/RealMultibinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/RealMultibinder.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/RealMultibinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,604 @@ +package com.google.inject.internal; + +import static com.google.inject.internal.Element.Type.MULTIBINDER; +import static com.google.inject.internal.Errors.checkConfiguration; +import static com.google.inject.internal.Errors.checkNotNull; +import static com.google.inject.name.Names.named; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.inject.AbstractModule; +import com.google.inject.Binder; +import com.google.inject.Binding; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.TypeLiteral; +import com.google.inject.binder.LinkedBindingBuilder; +import com.google.inject.internal.InternalProviderInstanceBindingImpl.InitializationTiming; +import com.google.inject.multibindings.MultibinderBinding; +import com.google.inject.multibindings.MultibindingsTargetVisitor; +import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.ProviderInstanceBinding; +import com.google.inject.spi.ProviderWithExtensionVisitor; +import com.google.inject.util.Types; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * The actual multibinder plays several roles: + * + *

    As a Multibinder, it acts as a factory for LinkedBindingBuilders for each of the set's + * elements. Each binding is given an annotation that identifies it as a part of this set. + * + *

    As a Module, it installs the binding to the set itself. As a module, this implements equals() + * and hashcode() in order to trick Guice into executing its configure() method only once. That + * makes it so that multiple multibinders can be created for the same target collection, but only + * one is bound. Since the list of bindings is retrieved from the injector itself (and not the + * multibinder), each multibinder has access to all contributions from all multibinders. + * + *

    As a Provider, this constructs the set instances. + * + *

    We use a subclass to hide 'implements Module, Provider' from the public API. + */ +public final class RealMultibinder implements Module { + + /** Implementation of newSetBinder. */ + public static RealMultibinder newRealSetBinder(Binder binder, Key key) { + binder = binder.skipSources(RealMultibinder.class); + RealMultibinder result = new RealMultibinder<>(binder, key); + binder.install(result); + return result; + } + + @SuppressWarnings("unchecked") // wrapping a T in a Set safely returns a Set + static TypeLiteral> setOf(TypeLiteral elementType) { + Type type = Types.setOf(elementType.getType()); + return (TypeLiteral>) TypeLiteral.get(type); + } + + @SuppressWarnings("unchecked") + static TypeLiteral>> collectionOfProvidersOf( + TypeLiteral elementType) { + Type providerType = Types.providerOf(elementType.getType()); + Type type = Types.collectionOf(providerType); + return (TypeLiteral>>) TypeLiteral.get(type); + } + + @SuppressWarnings("unchecked") + static TypeLiteral>> collectionOfJavaxProvidersOf( + TypeLiteral elementType) { + Type providerType = + Types.newParameterizedType(javax.inject.Provider.class, elementType.getType()); + Type type = Types.collectionOf(providerType); + return (TypeLiteral>>) TypeLiteral.get(type); + } + + private final BindingSelection bindingSelection; + private final Binder binder; + + RealMultibinder(Binder binder, Key key) { + this.binder = checkNotNull(binder, "binder"); + this.bindingSelection = new BindingSelection<>(key); + } + + @Override + public void configure(Binder binder) { + checkConfiguration(!bindingSelection.isInitialized(), "Multibinder was already initialized"); + binder + .bind(bindingSelection.getSetKey()) + .toProvider(new RealMultibinderProvider(bindingSelection)); + Provider>> collectionOfProvidersProvider = + new RealMultibinderCollectionOfProvidersProvider(bindingSelection); + binder + .bind(bindingSelection.getCollectionOfProvidersKey()) + .toProvider(collectionOfProvidersProvider); + + // The collection this exposes is internally an ImmutableList, so it's OK to massage + // the guice Provider to javax Provider in the value (since the guice Provider implements + // javax Provider). + @SuppressWarnings("unchecked") + Provider>> javaxProvider = + (Provider) collectionOfProvidersProvider; + binder.bind(bindingSelection.getCollectionOfJavaxProvidersKey()).toProvider(javaxProvider); + } + + public void permitDuplicates() { + binder.install(new PermitDuplicatesModule(bindingSelection.getPermitDuplicatesKey())); + } + + /** Adds a new entry to the set and returns the key for it. */ + Key getKeyForNewItem() { + checkConfiguration(!bindingSelection.isInitialized(), "Multibinder was already initialized"); + return Key.get( + bindingSelection.getElementTypeLiteral(), + new RealElement(bindingSelection.getSetName(), MULTIBINDER, "")); + } + + public LinkedBindingBuilder addBinding() { + return binder.bind(getKeyForNewItem()); + } + + // These methods are used by RealMapBinder + + Key> getSetKey() { + return bindingSelection.getSetKey(); + } + + TypeLiteral getElementTypeLiteral() { + return bindingSelection.getElementTypeLiteral(); + } + + String getSetName() { + return bindingSelection.getSetName(); + } + + boolean permitsDuplicates(Injector injector) { + return bindingSelection.permitsDuplicates(injector); + } + + boolean containsElement(com.google.inject.spi.Element element) { + return bindingSelection.containsElement(element); + } + + private static final class RealMultibinderProvider + extends InternalProviderInstanceBindingImpl.Factory> + implements ProviderWithExtensionVisitor>, MultibinderBinding> { + private final BindingSelection bindingSelection; + private List> bindings; + private SingleParameterInjector[] injectors; + private boolean permitDuplicates; + + RealMultibinderProvider(BindingSelection bindingSelection) { + // While Multibinders only depend on bindings created in modules so we could theoretically + // initialize eagerly, they also depend on + // 1. findBindingsByType returning results + // 2. being able to call BindingImpl.acceptTargetVisitor + // neither of those is available during eager initialization, so we use DELAYED + super(InitializationTiming.DELAYED); + this.bindingSelection = bindingSelection; + } + + @Override + public Set> getDependencies() { + return bindingSelection.getDependencies(); + } + + @Override + void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + bindingSelection.initialize(injector, errors); + this.bindings = bindingSelection.getBindings(); + this.injectors = bindingSelection.getParameterInjectors(); + this.permitDuplicates = bindingSelection.permitsDuplicates(); + } + + @Override + protected Set doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException { + SingleParameterInjector[] localInjectors = injectors; + if (localInjectors == null) { + // if localInjectors == null, then we have no bindings so return the empty set. + return ImmutableSet.of(); + } + // Ideally we would just add to an ImmutableSet.Builder, but if we did that and there were + // duplicates we wouldn't be able to tell which one was the duplicate. So to manage this we + // first put everything into an array and then construct the set. This way if something gets + // dropped we can figure out what it is. + @SuppressWarnings("unchecked") + T[] values = (T[]) new Object[localInjectors.length]; + for (int i = 0; i < localInjectors.length; i++) { + SingleParameterInjector parameterInjector = localInjectors[i]; + T newValue = parameterInjector.inject(context); + if (newValue == null) { + throw newNullEntryException(i); + } + values[i] = newValue; + } + ImmutableSet set = ImmutableSet.copyOf(values); + // There are fewer items in the set than the array. Figure out which one got dropped. + if (!permitDuplicates && set.size() < values.length) { + throw newDuplicateValuesException(set, values); + } + return set; + } + + private InternalProvisionException newNullEntryException(int i) { + return InternalProvisionException.create( + "Set injection failed due to null element bound at: %s", bindings.get(i).getSource()); + } + + @SuppressWarnings("unchecked") + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, V>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + + private InternalProvisionException newDuplicateValuesException( + ImmutableSet set, T[] values) { + // TODO(lukes): consider reporting all duplicate values, the easiest way would be to rebuild + // a new set and detect dupes as we go + // Find the duplicate binding + // To do this we take advantage of the fact that set, values and bindings all have the same + // ordering for a non-empty prefix of the set. + // First we scan for the first item dropped from the set. + int newBindingIndex = 0; + for (T item : set) { + if (item != values[newBindingIndex]) { + break; + } + newBindingIndex++; + } + // once we exit the loop newBindingIndex will point at the first item in values that was + // dropped. + + Binding newBinding = bindings.get(newBindingIndex); + T newValue = values[newBindingIndex]; + // Now we scan again to find the index of the value, we are guaranteed to find it. + int oldBindingIndex = set.asList().indexOf(newValue); + T oldValue = values[oldBindingIndex]; + Binding duplicateBinding = bindings.get(oldBindingIndex); + String oldString = oldValue.toString(); + String newString = newValue.toString(); + if (Objects.equal(oldString, newString)) { + // When the value strings match, just show the source of the bindings + return InternalProvisionException.create( + "Set injection failed due to duplicated element \"%s\"" + + "\n Bound at %s\n Bound at %s", + newValue, duplicateBinding.getSource(), newBinding.getSource()); + } else { + // When the value strings don't match, include them both as they may be useful for debugging + return InternalProvisionException.create( + "Set injection failed due to multiple elements comparing equal:" + + "\n \"%s\"\n bound at %s" + + "\n \"%s\"\n bound at %s", + oldValue, duplicateBinding.getSource(), newValue, newBinding.getSource()); + } + } + + @Override + public boolean equals(Object obj) { + return obj instanceof RealMultibinderProvider + && bindingSelection.equals(((RealMultibinderProvider) obj).bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + + @Override + public Key> getSetKey() { + return bindingSelection.getSetKey(); + } + + @Override + public TypeLiteral getElementTypeLiteral() { + return bindingSelection.getElementTypeLiteral(); + } + + @Override + public List> getElements() { + return bindingSelection.getElements(); + } + + @Override + public boolean permitsDuplicates() { + return bindingSelection.permitsDuplicates(); + } + + @Override + public boolean containsElement(com.google.inject.spi.Element element) { + return bindingSelection.containsElement(element); + } + } + + private static final class BindingSelection { + // prior to initialization we declare just a dependency on the injector, but as soon as we are + // initialized we swap to dependencies on the elements. + private static final ImmutableSet> MODULE_DEPENDENCIES = + ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); + private final TypeLiteral elementType; + private final Key> setKey; + + // these are all lazily allocated + private String setName; + private Key>> collectionOfProvidersKey; + private Key>> collectionOfJavaxProvidersKey; + private Key permitDuplicatesKey; + + private boolean isInitialized; + /* a binding for each element in the set. null until initialization, non-null afterwards */ + private ImmutableList> bindings; + + // Starts out as Injector and gets set up properly after initialization + private ImmutableSet> dependencies = MODULE_DEPENDENCIES; + private ImmutableSet> providerDependencies = MODULE_DEPENDENCIES; + + /** whether duplicates are allowed. Possibly configured by a different instance */ + private boolean permitDuplicates; + + private SingleParameterInjector[] parameterinjectors; + + BindingSelection(Key key) { + this.setKey = key.ofType(setOf(key.getTypeLiteral())); + this.elementType = key.getTypeLiteral(); + } + + void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + // This will be called multiple times, once by each Factory. We only want + // to do the work to initialize everything once, so guard this code with + // isInitialized. + if (isInitialized) { + return; + } + List> bindings = Lists.newArrayList(); + Set index = Sets.newHashSet(); + Indexer indexer = new Indexer(injector); + List> dependencies = Lists.newArrayList(); + List> providerDependencies = Lists.newArrayList(); + for (Binding entry : injector.findBindingsByType(elementType)) { + if (keyMatches(entry.getKey())) { + @SuppressWarnings("unchecked") // protected by findBindingsByType() + Binding binding = (Binding) entry; + if (index.add(binding.acceptTargetVisitor(indexer))) { + // TODO(lukes): most of these are linked bindings since user bindings are linked to + // a user binding through the @Element annotation. Since this is an implementation + // detail we could 'dereference' the @Element if it is a LinkedBinding and avoid + // provisioning through the FactoryProxy at runtime. + // Ditto for OptionalBinder/MapBinder + bindings.add(binding); + Key key = binding.getKey(); + // TODO(lukes): we should mark this as a non-nullable dependency since we don't accept + // null. + // Add a dependency on Key + dependencies.add(Dependency.get(key)); + // and add a dependency on Key> + providerDependencies.add( + Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType())))); + } + } + } + + this.bindings = ImmutableList.copyOf(bindings); + this.dependencies = ImmutableSet.copyOf(dependencies); + this.providerDependencies = ImmutableSet.copyOf(providerDependencies); + this.permitDuplicates = permitsDuplicates(injector); + // This is safe because all our dependencies are assignable to T and we never assign to + // elements of this array. + @SuppressWarnings("unchecked") + SingleParameterInjector[] typed = + (SingleParameterInjector[]) injector.getParametersInjectors(dependencies, errors); + this.parameterinjectors = typed; + isInitialized = true; + } + + boolean permitsDuplicates(Injector injector) { + return injector.getBindings().containsKey(getPermitDuplicatesKey()); + } + + ImmutableList> getBindings() { + checkConfiguration(isInitialized, "not initialized"); + return bindings; + } + + SingleParameterInjector[] getParameterInjectors() { + checkConfiguration(isInitialized, "not initialized"); + return parameterinjectors; + } + + ImmutableSet> getDependencies() { + return dependencies; + } + + ImmutableSet> getProviderDependencies() { + return providerDependencies; + } + + String getSetName() { + // lazily initialized since most selectors don't survive module installation. + if (setName == null) { + setName = Annotations.nameOf(setKey); + } + return setName; + } + + Key getPermitDuplicatesKey() { + Key local = permitDuplicatesKey; + if (local == null) { + local = + permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates")); + } + return local; + } + + Key>> getCollectionOfProvidersKey() { + Key>> local = collectionOfProvidersKey; + if (local == null) { + local = collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); + } + return local; + } + + Key>> getCollectionOfJavaxProvidersKey() { + Key>> local = collectionOfJavaxProvidersKey; + if (local == null) { + local = + collectionOfJavaxProvidersKey = + setKey.ofType(collectionOfJavaxProvidersOf(elementType)); + } + return local; + } + + boolean isInitialized() { + return isInitialized; + } + + // MultibinderBinding API methods + + TypeLiteral getElementTypeLiteral() { + return elementType; + } + + Key> getSetKey() { + return setKey; + } + + @SuppressWarnings("unchecked") + List> getElements() { + if (isInitialized()) { + return (List>) (List) bindings; // safe because bindings is immutable. + } else { + throw new UnsupportedOperationException("getElements() not supported for module bindings"); + } + } + + boolean permitsDuplicates() { + if (isInitialized()) { + return permitDuplicates; + } else { + throw new UnsupportedOperationException( + "permitsDuplicates() not supported for module bindings"); + } + } + + boolean containsElement(com.google.inject.spi.Element element) { + if (element instanceof Binding) { + Binding binding = (Binding) element; + return keyMatches(binding.getKey()) + || binding.getKey().equals(getPermitDuplicatesKey()) + || binding.getKey().equals(setKey) + || binding.getKey().equals(collectionOfProvidersKey) + || binding.getKey().equals(collectionOfJavaxProvidersKey); + } else { + return false; + } + } + + private boolean keyMatches(Key key) { + return key.getTypeLiteral().equals(elementType) + && key.getAnnotation() instanceof Element + && ((Element) key.getAnnotation()).setName().equals(getSetName()) + && ((Element) key.getAnnotation()).type() == MULTIBINDER; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BindingSelection) { + return setKey.equals(((BindingSelection) obj).setKey); + } + return false; + } + + @Override + public int hashCode() { + return setKey.hashCode(); + } + + @Override + public String toString() { + return (getSetName().isEmpty() ? "" : getSetName() + " ") + + "Multibinder<" + + elementType + + ">"; + } + } + + @Override + public boolean equals(Object o) { + return o instanceof RealMultibinder + && ((RealMultibinder) o).bindingSelection.equals(bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + + private static final class RealMultibinderCollectionOfProvidersProvider + extends InternalProviderInstanceBindingImpl.Factory>> { + + private final BindingSelection bindingSelection; + private ImmutableList> collectionOfProviders; + + RealMultibinderCollectionOfProvidersProvider(BindingSelection bindingSelection) { + super(InitializationTiming.DELAYED); // See comment in RealMultibinderProvider + this.bindingSelection = bindingSelection; + } + + @Override + void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + bindingSelection.initialize(injector, errors); + ImmutableList.Builder> providers = ImmutableList.builder(); + for (Binding binding : bindingSelection.getBindings()) { + providers.add(binding.getProvider()); + } + this.collectionOfProviders = providers.build(); + } + + @Override + protected Collection> doProvision( + InternalContext context, Dependency dependency) { + return collectionOfProviders; + } + + @Override + public Set> getDependencies() { + return bindingSelection.getProviderDependencies(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof RealMultibinderCollectionOfProvidersProvider + && bindingSelection.equals( + ((RealMultibinderCollectionOfProvidersProvider) obj).bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + } + + /** + * We install the permit duplicates configuration as its own binding, all by itself. This way, if + * only one of a multibinder's users remember to call permitDuplicates(), they're still permitted. + * + *

    This is like setting a global variable in the injector so that each instance of the + * multibinder will have the same value for permitDuplicates, even if it is only set on one of + * them. + */ + private static class PermitDuplicatesModule extends AbstractModule { + private final Key key; + + PermitDuplicatesModule(Key key) { + this.key = key; + } + + @Override + protected void configure() { + bind(key).toInstance(true); + } + + @Override + public boolean equals(Object o) { + return o instanceof PermitDuplicatesModule && ((PermitDuplicatesModule) o).key.equals(key); + } + + @Override + public int hashCode() { + return getClass().hashCode() ^ key.hashCode(); + } + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/RealOptionalBinder.java sisu-guice-4.2.0/core/src/com/google/inject/internal/RealOptionalBinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/RealOptionalBinder.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/RealOptionalBinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,844 @@ +/* + * Copyright (C) 2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.inject.internal.Errors.checkConfiguration; +import static com.google.inject.util.Types.newParameterizedType; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.common.base.Optional; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.inject.Binder; +import com.google.inject.Binding; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.TypeLiteral; +import com.google.inject.binder.LinkedBindingBuilder; +import com.google.inject.internal.InternalProviderInstanceBindingImpl.InitializationTiming; +import com.google.inject.multibindings.MultibindingsTargetVisitor; +import com.google.inject.multibindings.OptionalBinderBinding; +import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.Element; +import com.google.inject.spi.ProviderInstanceBinding; +import com.google.inject.spi.ProviderWithExtensionVisitor; +import com.google.inject.util.Types; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Set; +import javax.inject.Qualifier; + +/** + * The actual OptionalBinder plays several roles. It implements Module to hide that fact from the + * public API, and installs the various bindings that are exposed to the user. + */ +public final class RealOptionalBinder implements Module { + public static RealOptionalBinder newRealOptionalBinder(Binder binder, Key type) { + binder = binder.skipSources(RealOptionalBinder.class); + RealOptionalBinder optionalBinder = new RealOptionalBinder<>(binder, type); + binder.install(optionalBinder); + return optionalBinder; + } + + /* Reflectively capture java 8's Optional types so we can bind them if we're running in java8. */ + private static final Class JAVA_OPTIONAL_CLASS; + private static final Object JAVA_OPTIONAL_EMPTY; + private static final Method JAVA_OPTIONAL_OF_METHOD; + + static { + Class optional = null; + Object emptyObject = null; + Method of = null; + boolean useJavaOptional = false; + try { + optional = Class.forName("java.util.Optional"); + emptyObject = optional.getDeclaredMethod("empty").invoke(null); + of = optional.getDeclaredMethod("of", Object.class); + // only use optional support if all our reflection succeeded + useJavaOptional = true; + } catch (ClassNotFoundException ignored) { + } catch (NoSuchMethodException ignored) { + } catch (SecurityException ignored) { + } catch (IllegalAccessException ignored) { + } catch (InvocationTargetException ignored) { + } + JAVA_OPTIONAL_CLASS = useJavaOptional ? optional : null; + JAVA_OPTIONAL_EMPTY = useJavaOptional ? emptyObject : null; + JAVA_OPTIONAL_OF_METHOD = useJavaOptional ? of : null; + } + + /** + * Returns java.util.Optional.empty() if the parameter is null, calls {@link + * #invokeJavaOptionalOf} otherwise. + */ + private static Object invokeJavaOptionalOfNullable(Object o) { + if (o == null) { + return JAVA_OPTIONAL_EMPTY; + } + return invokeJavaOptionalOf(o); + } + + /** Invokes java.util.Optional.of. */ + private static Object invokeJavaOptionalOf(Object o) { + try { + return JAVA_OPTIONAL_OF_METHOD.invoke(null, o); + } catch (IllegalAccessException e) { + throw new SecurityException(e); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + throw Throwables.propagate(e.getCause()); + } + } + + @SuppressWarnings("unchecked") + static TypeLiteral> optionalOf(TypeLiteral type) { + return (TypeLiteral>) + TypeLiteral.get(Types.newParameterizedType(Optional.class, type.getType())); + } + + static TypeLiteral javaOptionalOf(TypeLiteral type) { + checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); + return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, type.getType())); + } + + @SuppressWarnings("unchecked") + static TypeLiteral>> optionalOfJavaxProvider( + TypeLiteral type) { + return (TypeLiteral>>) + TypeLiteral.get( + Types.newParameterizedType( + Optional.class, newParameterizedType(javax.inject.Provider.class, type.getType()))); + } + + static TypeLiteral javaOptionalOfJavaxProvider(TypeLiteral type) { + checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); + return TypeLiteral.get( + Types.newParameterizedType( + JAVA_OPTIONAL_CLASS, + newParameterizedType(javax.inject.Provider.class, type.getType()))); + } + + @SuppressWarnings("unchecked") + static TypeLiteral>> optionalOfProvider(TypeLiteral type) { + return (TypeLiteral>>) + TypeLiteral.get( + Types.newParameterizedType( + Optional.class, newParameterizedType(Provider.class, type.getType()))); + } + + static TypeLiteral javaOptionalOfProvider(TypeLiteral type) { + checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); + return TypeLiteral.get( + Types.newParameterizedType( + JAVA_OPTIONAL_CLASS, newParameterizedType(Provider.class, type.getType()))); + } + + @SuppressWarnings("unchecked") + static Key> providerOf(Key key) { + Type providerT = Types.providerOf(key.getTypeLiteral().getType()); + return (Key>) key.ofType(providerT); + } + + enum Source { + DEFAULT, + ACTUAL + } + + @Retention(RUNTIME) + @Qualifier + @interface Default { + String value(); + } + + @Retention(RUNTIME) + @Qualifier + @interface Actual { + String value(); + } + + private final BindingSelection bindingSelection; + private final Binder binder; + + private RealOptionalBinder(Binder binder, Key typeKey) { + this.bindingSelection = new BindingSelection<>(typeKey); + this.binder = binder; + } + + /** + * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate + * bindings. + */ + private void addDirectTypeBinding(Binder binder) { + binder + .bind(bindingSelection.getDirectKey()) + .toProvider(new RealDirectTypeProvider(bindingSelection)); + } + + /** + * Returns the key to use for the default binding. + * + *

    As a side effect this installs support for the 'direct type', so a binding for {@code T} + * will be made available. + */ + Key getKeyForDefaultBinding() { + bindingSelection.checkNotInitialized(); + addDirectTypeBinding(binder); + return bindingSelection.getKeyForDefaultBinding(); + } + + public LinkedBindingBuilder setDefault() { + return binder.bind(getKeyForDefaultBinding()); + } + + /** + * Returns the key to use for the actual binding, overrides the default if set. + * + *

    As a side effect this installs support for the 'direct type', so a binding for {@code T} + * will be made available. + */ + Key getKeyForActualBinding() { + bindingSelection.checkNotInitialized(); + addDirectTypeBinding(binder); + return bindingSelection.getKeyForActualBinding(); + } + + public LinkedBindingBuilder setBinding() { + return binder.bind(getKeyForActualBinding()); + } + + @Override + public void configure(Binder binder) { + bindingSelection.checkNotInitialized(); + Key key = bindingSelection.getDirectKey(); + // Every OptionalBinder get's the following types bound + // * Optional> + // * Optional> + // * Optional + // If setDefault() or setBinding() is called then also + // * T is bound + // If java.util.Optional is on the classpath (because this is a jdk8+ vm), then you also get + // * java.util.Optional> + // * java.util.Optional> + // * java.util.Optional + InternalProviderInstanceBindingImpl.Factory>> optionalProviderFactory = + new RealOptionalProviderProvider(bindingSelection); + binder + .bind(key.ofType(optionalOfProvider(key.getTypeLiteral()))) + .toProvider(optionalProviderFactory); + + // Provider is assignable to javax.inject.Provider and the provider that the factory contains + // cannot be modified so we can use some rawtypes hackery to share the same implementation. + @SuppressWarnings("unchecked") + InternalProviderInstanceBindingImpl.Factory>> + optionalJavaxProviderFactory = + (InternalProviderInstanceBindingImpl.Factory) optionalProviderFactory; + binder + .bind(key.ofType(optionalOfJavaxProvider(key.getTypeLiteral()))) + .toProvider(optionalJavaxProviderFactory); + + Key> optionalKey = key.ofType(optionalOf(key.getTypeLiteral())); + binder + .bind(optionalKey) + .toProvider(new RealOptionalKeyProvider(bindingSelection, optionalKey)); + + // Bind the java-8 types if we know them. + bindJava8Optional(binder); + } + + @SuppressWarnings("unchecked") + private void bindJava8Optional(Binder binder) { + if (JAVA_OPTIONAL_CLASS != null) { + Key key = bindingSelection.getDirectKey(); + TypeLiteral typeLiteral = key.getTypeLiteral(); + InternalProviderInstanceBindingImpl.Factory javaOptionalProviderFactory = + new JavaOptionalProviderProvider(bindingSelection); + binder + .bind(key.ofType(javaOptionalOfProvider(typeLiteral))) + .toProvider((Provider) javaOptionalProviderFactory); + // Provider is assignable to javax.inject.Provider and the provider that the factory contains + // cannot be modified so we can use some rawtypes hackery to share the same implementation. + binder + .bind(key.ofType(javaOptionalOfJavaxProvider(typeLiteral))) + .toProvider((Provider) javaOptionalProviderFactory); + Key javaOptionalKey = key.ofType(javaOptionalOf(typeLiteral)); + binder + .bind(javaOptionalKey) + .toProvider(new JavaOptionalProvider(bindingSelection, javaOptionalKey)); + } + } + + /** Provides the binding for java.util.Optional. */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private static final class JavaOptionalProvider extends RealOptionalBinderProviderWithDependencies + implements ProviderWithExtensionVisitor, OptionalBinderBinding { + + private final Key optionalKey; + + private Dependency targetDependency; + private InternalFactory target; + + JavaOptionalProvider(BindingSelection bindingSelection, Key optionalKey) { + super(bindingSelection); + this.optionalKey = optionalKey; + } + + @Override + void doInitialize() { + if (bindingSelection.getBinding() != null) { + target = bindingSelection.getBinding().getInternalFactory(); + targetDependency = bindingSelection.getDependency(); + } + } + + @Override + protected Object doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException { + InternalFactory local = target; + if (local == null) { + return JAVA_OPTIONAL_EMPTY; + } + Dependency localDependency = targetDependency; + Object result; + Dependency previous = context.pushDependency(localDependency, getSource()); + + try { + // See comments in RealOptionalKeyProvider, about how localDependency may be more specific + // than what we actually need. + result = local.get(context, localDependency, false); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(localDependency); + } finally { + context.popStateAndSetDependency(previous); + + } + return invokeJavaOptionalOfNullable(result); + } + + @Override + public Set> getDependencies() { + return bindingSelection.dependencies; + } + + @SuppressWarnings("unchecked") + @Override + public Object acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + + @Override + public boolean containsElement(Element element) { + return bindingSelection.containsElement(element); + } + + @Override + public Binding getActualBinding() { + return bindingSelection.getActualBinding(); + } + + @Override + public Binding getDefaultBinding() { + return bindingSelection.getDefaultBinding(); + } + + @Override + public Key getKey() { + return optionalKey; + } + } + + /** Provides the binding for java.util.Optional>. */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private static final class JavaOptionalProviderProvider + extends RealOptionalBinderProviderWithDependencies { + private Object value; + + JavaOptionalProviderProvider(BindingSelection bindingSelection) { + super(bindingSelection); + } + + @Override + void doInitialize() { + if (bindingSelection.getBinding() == null) { + value = JAVA_OPTIONAL_EMPTY; + } else { + value = invokeJavaOptionalOf(bindingSelection.getBinding().getProvider()); + } + } + + @Override + protected Object doProvision(InternalContext context, Dependency dependency) { + return value; + } + + @Override + public Set> getDependencies() { + return bindingSelection.providerDependencies(); + } + } + + /** Provides the binding for T, conditionally installed by calling setBinding/setDefault. */ + private static final class RealDirectTypeProvider + extends RealOptionalBinderProviderWithDependencies { + private Key targetKey; + + private Object targetSource; + + private InternalFactory targetFactory; + + RealDirectTypeProvider(BindingSelection bindingSelection) { + super(bindingSelection); + } + + @Override + void doInitialize() { + BindingImpl targetBinding = bindingSelection.getBinding(); + // we only install this factory if they call setBinding()/setDefault() so we know that + // targetBinding will be non-null. + this.targetKey = targetBinding.getKey(); + this.targetSource = targetBinding.getSource(); + this.targetFactory = targetBinding.getInternalFactory(); + } + + @Override + protected T doProvision(InternalContext context, Dependency dependency) + throws InternalProvisionException { + // This is what linked bindings do (see FactoryProxy), and we are pretty similar. + context.pushState(targetKey, targetSource); + + try { + return targetFactory.get(context, dependency, true); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(targetKey); + } finally { + context.popState(); + + } + } + + @Override + public Set> getDependencies() { + return bindingSelection.dependencies; + } + } + + /** Provides the binding for Optional>. */ + private static final class RealOptionalProviderProvider + extends RealOptionalBinderProviderWithDependencies>> { + private Optional> value; + + RealOptionalProviderProvider(BindingSelection bindingSelection) { + super(bindingSelection); + } + + @Override + void doInitialize() { + if (bindingSelection.getBinding() == null) { + value = Optional.absent(); + } else { + value = Optional.of(bindingSelection.getBinding().getProvider()); + } + } + + @Override + protected Optional> doProvision(InternalContext context, Dependency dependency) { + return value; + } + + @Override + public Set> getDependencies() { + return bindingSelection.providerDependencies(); + } + } + + /** Provides the binding for Optional. */ + private static final class RealOptionalKeyProvider + extends RealOptionalBinderProviderWithDependencies> + implements ProviderWithExtensionVisitor>, OptionalBinderBinding> { + + private final Key> optionalKey; + + // These are assigned to non-null values during initialization if and only if we have a binding + // to delegate to. + private Dependency targetDependency; + private InternalFactory delegate; + + RealOptionalKeyProvider(BindingSelection bindingSelection, Key> optionalKey) { + super(bindingSelection); + this.optionalKey = optionalKey; + } + + @Override + void doInitialize() { + if (bindingSelection.getBinding() != null) { + delegate = bindingSelection.getBinding().getInternalFactory(); + targetDependency = bindingSelection.getDependency(); + } + } + + @Override + protected Optional doProvision(InternalContext context, Dependency currentDependency) + throws InternalProvisionException { + InternalFactory local = delegate; + if (local == null) { + return Optional.absent(); + } + Dependency localDependency = targetDependency; + T result; + Dependency previous = context.pushDependency(localDependency, getSource()); + + try { + // currentDependency is Optional, so we really just need to set the target + // dependency to ? super T, but we are currently setting it to T. We could hypothetically + // make it easier for our delegate to generate proxies by modifying the dependency, but that + // would also require us to rewrite the key on each call. So for now we don't do it. + result = local.get(context, localDependency, false); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(localDependency); + } finally { + context.popStateAndSetDependency(previous); + + } + return Optional.fromNullable(result); + } + + @Override + public Set> getDependencies() { + return bindingSelection.dependencies(); + } + + @SuppressWarnings("unchecked") + @Override + public R acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, R>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + + @Override + public Key> getKey() { + return optionalKey; + } + + @Override + public Binding getActualBinding() { + return bindingSelection.getActualBinding(); + } + + @Override + public Binding getDefaultBinding() { + return bindingSelection.getDefaultBinding(); + } + + @Override + public boolean containsElement(Element element) { + return bindingSelection.containsElement(element); + } + } + + /** + * A helper object that implements the core logic for deciding what the implementation of the + * binding will be. + * + *

    This also implements the main OptionalBinderBinding logic. + */ + private static final class BindingSelection { + private static final ImmutableSet> MODULE_DEPENDENCIES = + ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); + + /*@Nullable */ BindingImpl actualBinding; + /*@Nullable */ BindingImpl defaultBinding; + /*@Nullable */ BindingImpl binding; + private boolean initialized; + private final Key key; + + // Until the injector initializes us, we don't know what our dependencies are, + // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly). + private ImmutableSet> dependencies = MODULE_DEPENDENCIES; + private ImmutableSet> providerDependencies = MODULE_DEPENDENCIES; + + /** lazily allocated, by {@link #getBindingName}. */ + private String bindingName; + + /** lazily allocated, by {@link #getKeyForDefaultBinding}. */ + private Key defaultBindingKey; + + /** lazily allocated, by {@link #getKeyForActualBinding}. */ + private Key actualBindingKey; + + BindingSelection(Key key) { + this.key = key; + } + + void checkNotInitialized() { + checkConfiguration(!initialized, "already initialized"); + } + + void initialize(InjectorImpl injector) { + // Every one of our providers will call this method, so only execute the logic once. + if (initialized) { + return; + } + + actualBinding = injector.getExistingBinding(getKeyForActualBinding()); + defaultBinding = injector.getExistingBinding(getKeyForDefaultBinding()); + // We should never create Jit bindings, but we can use them if some other binding created it. + BindingImpl userBinding = injector.getExistingBinding(key); + if (actualBinding != null) { + // TODO(sameb): Consider exposing an option that will allow + // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null. + // Right now, an ACTUAL binding can convert from present -> absent + // if it's bound to a provider that returns null. + binding = actualBinding; + } else if (defaultBinding != null) { + binding = defaultBinding; + } else if (userBinding != null) { + // If neither the actual or default is set, then we fallback + // to the value bound to the type itself and consider that the + // "actual binding" for the SPI. + binding = userBinding; + actualBinding = userBinding; + } + if (binding != null) { + dependencies = ImmutableSet.>of(Dependency.get(binding.getKey())); + providerDependencies = + ImmutableSet.>of(Dependency.get(providerOf(binding.getKey()))); + } else { + dependencies = ImmutableSet.of(); + providerDependencies = ImmutableSet.of(); + } + initialized = true; + } + + Key getKeyForDefaultBinding() { + if (defaultBindingKey == null) { + defaultBindingKey = Key.get(key.getTypeLiteral(), new DefaultImpl(getBindingName())); + } + return defaultBindingKey; + } + + Key getKeyForActualBinding() { + if (actualBindingKey == null) { + actualBindingKey = Key.get(key.getTypeLiteral(), new ActualImpl(getBindingName())); + } + return actualBindingKey; + } + + Key getDirectKey() { + return key; + } + + private String getBindingName() { + // Lazily allocated, most instantiations will never need this because they are deduped during + // module installation. + if (bindingName == null) { + bindingName = Annotations.nameOf(key); + } + return bindingName; + } + + BindingImpl getBinding() { + return binding; + } + + // Provide default implementations for most of the OptionalBinderBinding interface + BindingImpl getDefaultBinding() { + return defaultBinding; + } + + BindingImpl getActualBinding() { + return actualBinding; + } + + ImmutableSet> providerDependencies() { + return providerDependencies; + } + + ImmutableSet> dependencies() { + return dependencies; + } + + /** + * Returns the Dependency for the target binding, throws NoSuchElementException if no target + * exists. + * + *

    Calls to this method should typically be guarded by checking if {@link #getBinding()} + * returns {@code null}. + */ + Dependency getDependency() { + return Iterables.getOnlyElement(dependencies); + } + + /** Implementation of {@link OptionalBinderBinding#containsElement}. */ + boolean containsElement(Element element) { + // All of our bindings are ProviderInstanceBindings whose providers extend + // RealOptionalBinderProviderWithDependencies and have 'this' as its binding selection. + if (element instanceof ProviderInstanceBinding) { + javax.inject.Provider providerInstance = + ((ProviderInstanceBinding) element).getUserSuppliedProvider(); + if (providerInstance instanceof RealOptionalBinderProviderWithDependencies) { + return ((RealOptionalBinderProviderWithDependencies) providerInstance) + .bindingSelection.equals(this); + } + } + if (element instanceof Binding) { + Key elementKey = ((Binding) element).getKey(); + // if it isn't one of the things we bound directly it might be an actual or default key + return elementKey.equals(getKeyForActualBinding()) + || elementKey.equals(getKeyForDefaultBinding()); + } + return false; // cannot match; + } + + @Override + public boolean equals(Object o) { + return o instanceof BindingSelection && ((BindingSelection) o).key.equals(key); + } + + @Override + public int hashCode() { + return key.hashCode(); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof RealOptionalBinder + && ((RealOptionalBinder) o).bindingSelection.equals(bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + + /** A base class for ProviderWithDependencies that need equality based on a specific object. */ + private abstract static class RealOptionalBinderProviderWithDependencies + extends InternalProviderInstanceBindingImpl.Factory

    { + protected final BindingSelection bindingSelection; + + RealOptionalBinderProviderWithDependencies(BindingSelection bindingSelection) { + // We need delayed initialization so we can detect jit bindings created by other bindings + // while not also creating jit bindings ourselves. This ensures we only pick up user bindings + // if the binding would have existed in the injector statically. + super(InitializationTiming.DELAYED); + this.bindingSelection = bindingSelection; + } + + @Override + final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + bindingSelection.initialize(injector); + doInitialize(); + } + + /** + * Initialize the factory. BindingSelection is guaranteed to be initialized at this point and + * this will be called prior to any provisioning. + */ + abstract void doInitialize(); + + @Override + public boolean equals(Object obj) { + return obj != null + && this.getClass() == obj.getClass() + && bindingSelection.equals( + ((RealOptionalBinderProviderWithDependencies) obj).bindingSelection); + } + + @Override + public int hashCode() { + return bindingSelection.hashCode(); + } + } + + static class DefaultImpl extends BaseAnnotation implements Default { + public DefaultImpl(String value) { + super(Default.class, value); + } + } + + static class ActualImpl extends BaseAnnotation implements Actual { + public ActualImpl(String value) { + super(Actual.class, value); + } + } + + abstract static class BaseAnnotation implements Serializable, Annotation { + + private final String value; + private final Class clazz; + + BaseAnnotation(Class clazz, String value) { + this.clazz = checkNotNull(clazz, "clazz"); + this.value = checkNotNull(value, "value"); + } + + public String value() { + return this.value; + } + + @Override + public int hashCode() { + // This is specified in java.lang.Annotation. + return (127 * "value".hashCode()) ^ value.hashCode(); + } + + @Override + public boolean equals(Object o) { + // We check against each annotation type instead of BaseAnnotation + // so that we can compare against generated annotation implementations. + if (o instanceof Actual && clazz == Actual.class) { + Actual other = (Actual) o; + return value.equals(other.value()); + } else if (o instanceof Default && clazz == Default.class) { + Default other = (Default) o; + return value.equals(other.value()); + } + return false; + } + + @Override + public String toString() { + return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")"); + } + + @Override + public Class annotationType() { + return clazz; + } + + private static final long serialVersionUID = 0; + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/ScopeBindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/ScopeBindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/ScopeBindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/ScopeBindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,6 @@ import com.google.inject.Scope; import com.google.inject.spi.ScopeBinding; - import java.lang.annotation.Annotation; /** @@ -35,9 +34,11 @@ super(errors); } - @Override public Boolean visit(ScopeBinding command) { + @Override + public Boolean visit(ScopeBinding command) { Scope scope = checkNotNull(command.getScope(), "scope"); - Class annotationType = checkNotNull(command.getAnnotationType(), "annotation type"); + Class annotationType = + checkNotNull(command.getAnnotationType(), "annotation type"); if (!Annotations.isScopeAnnotation(annotationType)) { errors.missingScopeAnnotation(annotationType); @@ -60,4 +61,4 @@ return true; } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/Scoping.java sisu-guice-4.2.0/core/src/com/google/inject/internal/Scoping.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/Scoping.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/Scoping.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,6 @@ import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.spi.ScopeBinding; - import java.lang.annotation.Annotation; /** @@ -41,98 +40,148 @@ * No scoping annotation has been applied. Note that this is different from {@code * in(Scopes.NO_SCOPE)}, where the 'NO_SCOPE' has been explicitly applied. */ - public static final Scoping UNSCOPED = new Scoping() { - @Override public V acceptVisitor(BindingScopingVisitor visitor) { - return visitor.visitNoScoping(); - } - - @Override public Scope getScopeInstance() { - return Scopes.NO_SCOPE; - } - - @Override public String toString() { - return Scopes.NO_SCOPE.toString(); - } - - @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { - // do nothing - } - }; - - public static final Scoping SINGLETON_ANNOTATION = new Scoping() { - @Override public V acceptVisitor(BindingScopingVisitor visitor) { - return visitor.visitScopeAnnotation(Singleton.class); - } - - @Override public Class getScopeAnnotation() { - return Singleton.class; - } - - @Override public String toString() { - return Singleton.class.getName(); - } - - @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { - scopedBindingBuilder.in(Singleton.class); - } - }; - - public static final Scoping SINGLETON_INSTANCE = new Scoping() { - @Override public V acceptVisitor(BindingScopingVisitor visitor) { - return visitor.visitScope(Scopes.SINGLETON); - } - - @Override public Scope getScopeInstance() { - return Scopes.SINGLETON; - } + public static final Scoping UNSCOPED = + new Scoping() { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { + return visitor.visitNoScoping(); + } + + @Override + public Scope getScopeInstance() { + return Scopes.NO_SCOPE; + } + + @Override + public String toString() { + return Scopes.NO_SCOPE.toString(); + } + + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + // do nothing + } + }; - @Override public String toString() { - return Scopes.SINGLETON.toString(); - } - - @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { - scopedBindingBuilder.in(Scopes.SINGLETON); - } - }; - - public static final Scoping EAGER_SINGLETON = new Scoping() { - @Override public V acceptVisitor(BindingScopingVisitor visitor) { - return visitor.visitEagerSingleton(); - } - - @Override public Scope getScopeInstance() { - return Scopes.SINGLETON; - } - - @Override public String toString() { - return "eager singleton"; - } - - @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { - scopedBindingBuilder.asEagerSingleton(); - } - }; + /** + * No scoping annotation has been applied explicitly. Note that this is is the same as {@code + * in(Scopes.NO_SCOPE)}. + */ + private static final Scoping EXPLICITLY_UNSCOPED = + new Scoping() { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { + return visitor.visitNoScoping(); + } + + @Override + public Scope getScopeInstance() { + return Scopes.NO_SCOPE; + } + + @Override + public String toString() { + return Scopes.NO_SCOPE.toString(); + } + + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + scopedBindingBuilder.in(Scopes.NO_SCOPE); + } + }; + + public static final Scoping SINGLETON_ANNOTATION = + new Scoping() { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { + return visitor.visitScopeAnnotation(Singleton.class); + } + + @Override + public Class getScopeAnnotation() { + return Singleton.class; + } + + @Override + public String toString() { + return Singleton.class.getName(); + } + + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + scopedBindingBuilder.in(Singleton.class); + } + }; + + public static final Scoping SINGLETON_INSTANCE = + new Scoping() { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { + return visitor.visitScope(Scopes.SINGLETON); + } + + @Override + public Scope getScopeInstance() { + return Scopes.SINGLETON; + } + + @Override + public String toString() { + return Scopes.SINGLETON.toString(); + } + + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + scopedBindingBuilder.in(Scopes.SINGLETON); + } + }; + + public static final Scoping EAGER_SINGLETON = + new Scoping() { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { + return visitor.visitEagerSingleton(); + } + + @Override + public Scope getScopeInstance() { + return Scopes.SINGLETON; + } + + @Override + public String toString() { + return "eager singleton"; + } + + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + scopedBindingBuilder.asEagerSingleton(); + } + }; public static Scoping forAnnotation(final Class scopingAnnotation) { - if (scopingAnnotation == Singleton.class - || scopingAnnotation == javax.inject.Singleton.class) { + if (scopingAnnotation == Singleton.class || scopingAnnotation == javax.inject.Singleton.class) { return SINGLETON_ANNOTATION; } return new Scoping() { - @Override public V acceptVisitor(BindingScopingVisitor visitor) { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitScopeAnnotation(scopingAnnotation); } - @Override public Class getScopeAnnotation() { + @Override + public Class getScopeAnnotation() { return scopingAnnotation; } - @Override public String toString() { + @Override + public String toString() { return scopingAnnotation.getName(); } - @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.in(scopingAnnotation); } }; @@ -141,22 +190,28 @@ public static Scoping forInstance(final Scope scope) { if (scope == Scopes.SINGLETON) { return SINGLETON_INSTANCE; + } else if (scope == Scopes.NO_SCOPE) { + return EXPLICITLY_UNSCOPED; } return new Scoping() { - @Override public V acceptVisitor(BindingScopingVisitor visitor) { + @Override + public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitScope(scope); } - @Override public Scope getScopeInstance() { + @Override + public Scope getScopeInstance() { return scope; } - @Override public String toString() { + @Override + public String toString() { return scope.toString(); } - @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { + @Override + public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.in(scope); } }; @@ -178,9 +233,7 @@ return getScopeInstance() == Scopes.NO_SCOPE; } - /** - * Returns true if this scope is a singleton that should be loaded eagerly in {@code stage}. - */ + /** Returns true if this scope is a singleton that should be loaded eagerly in {@code stage}. */ public boolean isEagerSingleton(Stage stage) { if (this == EAGER_SINGLETON) { return true; @@ -193,31 +246,27 @@ return false; } - /** - * Returns the scope instance, or {@code null} if that isn't known for this instance. - */ + /** Returns the scope instance, or {@code null} if that isn't known for this instance. */ public Scope getScopeInstance() { return null; } - /** - * Returns the scope annotation, or {@code null} if that isn't known for this instance. - */ + /** Returns the scope annotation, or {@code null} if that isn't known for this instance. */ public Class getScopeAnnotation() { return null; } - + @Override public boolean equals(Object obj) { - if(obj instanceof Scoping) { - Scoping o = (Scoping)obj; + if (obj instanceof Scoping) { + Scoping o = (Scoping) obj; return Objects.equal(getScopeAnnotation(), o.getScopeAnnotation()) - && Objects.equal(getScopeInstance(), o.getScopeInstance()); + && Objects.equal(getScopeInstance(), o.getScopeInstance()); } else { return false; } } - + @Override public int hashCode() { return Objects.hashCode(getScopeAnnotation(), getScopeInstance()); @@ -230,8 +279,12 @@ private Scoping() {} /** Scopes an internal factory. */ - static InternalFactory scope(Key key, InjectorImpl injector, - InternalFactory creator, Object source, Scoping scoping) { + static InternalFactory scope( + Key key, + InjectorImpl injector, + InternalFactory creator, + Object source, + Scoping scoping) { if (scoping.isNoScope()) { return creator; @@ -239,8 +292,11 @@ Scope scope = scoping.getScopeInstance(); - Provider scoped - = scope.scope(key, new ProviderToInternalFactoryAdapter(injector, creator)); + // NOTE: SingletonScope relies on the fact that we are passing a + // ProviderToInternalFactoryAdapter here. If you change the type make sure to update + // SingletonScope as well. + Provider scoped = + scope.scope(key, new ProviderToInternalFactoryAdapter(injector, creator)); return new InternalFactoryToProviderAdapter(scoped, source); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleFieldInjector.java sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleFieldInjector.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleFieldInjector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleFieldInjector.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,12 +19,9 @@ import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; - import java.lang.reflect.Field; -/** - * Sets an injectable field. - */ +/** Sets an injectable field. */ final class SingleFieldInjector implements SingleMemberInjector { final Field field; final InjectionPoint injectionPoint; @@ -42,23 +39,24 @@ binding = injector.getBindingOrThrow(dependency.getKey(), errors, JitLimitation.NO_JIT); } + @Override public InjectionPoint getInjectionPoint() { return injectionPoint; } - public void inject(Errors errors, InternalContext context, Object o) { - errors = errors.withSource(dependency); - + @Override + public void inject(InternalContext context, Object o) throws InternalProvisionException { Dependency previous = context.pushDependency(dependency, binding.getSource()); + try { - Object value = binding.getInternalFactory().get(errors, context, dependency, false); + Object value = binding.getInternalFactory().get(context, dependency, false); field.set(o, value); - } catch (ErrorsException e) { - errors.withSource(injectionPoint).merge(e.getErrors()); + } catch (InternalProvisionException e) { + throw e.addSource(dependency); } catch (IllegalAccessException e) { throw new AssertionError(e); // a security manager is blocking us, we're hosed } finally { - context.popStateAndSetDependency(previous); - } + context.popStateAndSetDependency(previous); + } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleMemberInjector.java sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleMemberInjector.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleMemberInjector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleMemberInjector.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,9 @@ import com.google.inject.spi.InjectionPoint; -/** - * Injects a field or method of a given object. - */ +/** Injects a field or method of a given object. */ interface SingleMemberInjector { - void inject(Errors errors, InternalContext context, Object o); + void inject(InternalContext context, Object o) throws InternalProvisionException; + InjectionPoint getInjectionPoint(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleMethodInjector.java sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleMethodInjector.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleMethodInjector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleMethodInjector.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,17 +16,13 @@ package com.google.inject.internal; -import com.google.inject.internal.BytecodeGen.Visibility; import com.google.inject.internal.InjectorImpl.MethodInvoker; import com.google.inject.spi.InjectionPoint; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -/** - * Invokes an injectable method. - */ +/** Invokes an injectable method. */ final class SingleMethodInjector implements SingleMemberInjector { private final MethodInvoker methodInvoker; private final SingleParameterInjector[] parameterInjectors; @@ -42,31 +38,33 @@ private MethodInvoker createMethodInvoker(final Method method) { - // We can't use FastMethod if the method is private. - int modifiers = method.getModifiers(); - if (!Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)) { - /*if[AOP]*/ - try { - final net.sf.cglib.reflect.FastMethod fastMethod - = BytecodeGen.newFastClass(method.getDeclaringClass(), Visibility.forMember(method)) - .getMethod(method); - - return new MethodInvoker() { - public Object invoke(Object target, Object... parameters) - throws IllegalAccessException, InvocationTargetException { - return fastMethod.invoke(target, parameters); - } - }; - } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */} - /*end[AOP]*/ + /*if[AOP]*/ + try { + final net.sf.cglib.reflect.FastClass fastClass = BytecodeGen.newFastClassForMember(method); + if (fastClass != null) { + final int index = fastClass.getMethod(method).getIndex(); + + return new MethodInvoker() { + @Override + public Object invoke(Object target, Object... parameters) + throws IllegalAccessException, InvocationTargetException { + return fastClass.invoke(index, target, parameters); + } + }; + } + } catch (net.sf.cglib.core.CodeGenerationException e) { + /* fall-through */ } + /*end[AOP]*/ - if (!Modifier.isPublic(modifiers) || - !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { + int modifiers = method.getModifiers(); + if (!Modifier.isPublic(modifiers) + || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } return new MethodInvoker() { + @Override public Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException { return method.invoke(target, parameters); @@ -74,28 +72,22 @@ }; } + @Override public InjectionPoint getInjectionPoint() { return injectionPoint; } - public void inject(Errors errors, InternalContext context, Object o) { - Object[] parameters; - try { - parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); - return; - } + @Override + public void inject(InternalContext context, Object o) throws InternalProvisionException { + Object[] parameters = SingleParameterInjector.getAll(context, parameterInjectors); try { methodInvoker.invoke(o, parameters); } catch (IllegalAccessException e) { throw new AssertionError(e); // a security manager is blocking us, we're hosed } catch (InvocationTargetException userException) { - Throwable cause = userException.getCause() != null - ? userException.getCause() - : userException; - errors.withSource(injectionPoint).errorInjectingMethod(cause); + Throwable cause = userException.getCause() != null ? userException.getCause() : userException; + throw InternalProvisionException.errorInjectingMethod(cause).addSource(injectionPoint); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleParameterInjector.java sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleParameterInjector.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/SingleParameterInjector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/SingleParameterInjector.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,54 +18,52 @@ import com.google.inject.spi.Dependency; -/** - * Resolves a single parameter, to be used in a constructor or method invocation. - */ +/** Resolves a single parameter, to be used in a constructor or method invocation. */ final class SingleParameterInjector { - private static final Object[] NO_ARGUMENTS = {}; + private static final Object[] NO_ARGUMENTS = {}; private final Dependency dependency; - private final BindingImpl binding; + + private final Object source; + + private final InternalFactory factory; SingleParameterInjector(Dependency dependency, BindingImpl binding) { this.dependency = dependency; - this.binding = binding; + this.source = binding.getSource(); + this.factory = binding.getInternalFactory(); } - private T inject(Errors errors, InternalContext context) throws ErrorsException { - Dependency previous = context.pushDependency(dependency, binding.getSource()); + T inject(InternalContext context) throws InternalProvisionException { + Dependency localDependency = dependency; + Dependency previous = context.pushDependency(localDependency, source); + try { - return binding.getInternalFactory().get(errors.withSource(dependency), context, dependency, false); - } finally { - context.popStateAndSetDependency(previous); + return factory.get(context, localDependency, false); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(localDependency); + } finally { + context.popStateAndSetDependency(previous); + } } - /** - * Returns an array of parameter values. - */ - static Object[] getAll(Errors errors, InternalContext context, - SingleParameterInjector[] parameterInjectors) throws ErrorsException { + // TODO(lukes): inline into callers to decrease stack depth + + /** Returns an array of parameter values. */ + static Object[] getAll(InternalContext context, SingleParameterInjector[] parameterInjectors) + throws InternalProvisionException { if (parameterInjectors == null) { return NO_ARGUMENTS; } - int numErrorsBefore = errors.size(); - int size = parameterInjectors.length; Object[] parameters = new Object[size]; - // optimization: use manual for/each to save allocating an iterator here + // optimization: use manual for/each to save allocating an iterator here for (int i = 0; i < size; i++) { - SingleParameterInjector parameterInjector = parameterInjectors[i]; - try { - parameters[i] = parameterInjector.inject(errors, context); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); - } + parameters[i] = parameterInjectors[i].inject(context); } - - errors.throwIfNewErrors(numErrorsBefore); return parameters; } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/SingletonScope.java sisu-guice-4.2.0/core/src/com/google/inject/internal/SingletonScope.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/SingletonScope.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/SingletonScope.java 2018-04-03 18:18:08.000000000 +0000 @@ -2,10 +2,8 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; @@ -15,58 +13,43 @@ import com.google.inject.Singleton; import com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory; import com.google.inject.spi.Dependency; -import com.google.inject.spi.DependencyAndSource; import com.google.inject.spi.Message; - -import java.util.Collections; +import java.util.Formatter; import java.util.List; -import java.util.Map; /** * One instance per {@link Injector}. Also see {@code @}{@link Singleton}. * - * Introduction from the author: - * Implementation of this class seems unreasonably complicated at the first sight. - * I fully agree with you, that the beast below is very complex - * and it's hard to reason on how does it work or not. - * Still I want to assure you that hundreds(?) of hours were thrown - * into making this code simple, while still maintaining Singleton contract. + *

    Introduction from the author: Implementation of this class seems unreasonably complicated at + * the first sight. I fully agree with you, that the beast below is very complex and it's hard to + * reason on how does it work or not. Still I want to assure you that hundreds(?) of hours were + * thrown into making this code simple, while still maintaining Singleton contract. * - * Anyway, why is it so complex? Singleton scope does not seem to be that unique. - * 1) Guice has never truly expected to be used in multi threading environment - * with many Injectors working alongside each other. There is almost no - * code with Guice that propagates state between threads. And Singleton - * scope is The exception. - * 2) Guice supports circular dependencies and thus manages proxy objects. - * There is no interface that allows user defined Scopes to create proxies, - * it is expected to be done by Guice. Singleton scope needs to be - * able to detect circular dependencies spanning several threads, - * therefore Singleton scope needs to be able to create these proxies. - * 3) To make things worse, Guice has a very tricky definition for a binding - * resolution when Injectors are in in a parent/child relationship. - * And Scope does not have access to this information by design, - * the only real action that Scope can do is to call or not to call a creator. - * 4) There is no readily available code in Guice that can detect a potential - * deadlock, and no code for handling dependency cycles spanning several threads. - * This is significantly harder as all the dependencies in a thread at runtime - * can be represented with a list, where in a multi threaded environment - * we have more complex dependency trees. - * 5) Guice has a pretty strong contract regarding Garbage Collection, - * which often prevents us from linking objects directly. - * So simple domain specific code can not be written and intermediary - * id objects need to be managed. - * 6) Guice is relatively fast and we should not make things worse. - * We're trying our best to optimize synchronization for speed and memory. - * Happy path should be almost as fast as in a single threaded solution - * and should not take much more memory. - * 7) Error message generation in Guice was not meant to be used like this and to work around - * its APIs we need a lot of code. Additional complexity comes from inherent data races - * as message is only generated when failure occurs on proxy object generation. - * Things get ugly pretty fast. + *

    Anyway, why is it so complex? Singleton scope does not seem to be that unique. 1) Guice has + * never truly expected to be used in multi threading environment with many Injectors working + * alongside each other. There is almost no code with Guice that propagates state between threads. + * And Singleton scope is The exception. 2) Guice supports circular dependencies and thus manages + * proxy objects. There is no interface that allows user defined Scopes to create proxies, it is + * expected to be done by Guice. Singleton scope needs to be able to detect circular dependencies + * spanning several threads, therefore Singleton scope needs to be able to create these proxies. 3) + * To make things worse, Guice has a very tricky definition for a binding resolution when Injectors + * are in in a parent/child relationship. And Scope does not have access to this information by + * design, the only real action that Scope can do is to call or not to call a creator. 4) There is + * no readily available code in Guice that can detect a potential deadlock, and no code for handling + * dependency cycles spanning several threads. This is significantly harder as all the dependencies + * in a thread at runtime can be represented with a list, where in a multi threaded environment we + * have more complex dependency trees. 5) Guice has a pretty strong contract regarding Garbage + * Collection, which often prevents us from linking objects directly. So simple domain specific code + * can not be written and intermediary id objects need to be managed. 6) Guice is relatively fast + * and we should not make things worse. We're trying our best to optimize synchronization for speed + * and memory. Happy path should be almost as fast as in a single threaded solution and should not + * take much more memory. 7) Error message generation in Guice was not meant to be used like this + * and to work around its APIs we need a lot of code. Additional complexity comes from inherent data + * races as message is only generated when failure occurs on proxy object generation. Things get + * ugly pretty fast. * * @see #scope(Key, Provider) * @see CycleDetectingLock - * * @author timofeyb (Timothy Basanov) */ public class SingletonScope implements Scope { @@ -78,36 +61,34 @@ * Allows us to detect when circular proxies are necessary. It's only used during singleton * instance initialization, after initialization direct access through volatile field is used. * - * NB: Factory uses {@link Key}s as a user locks ids, different injectors can - * share them. Cycles are detected properly as cycle detection does not rely on user locks ids, - * but error message generated could be less than ideal. - * - * TODO(user): we may use one factory per injector tree for optimization reasons + *

    NB: Factory uses {@link Key}s as a user locks ids, different injectors can share them. + * Cycles are detected properly as cycle detection does not rely on user locks ids, but error + * message generated could be less than ideal. */ + // TODO(user): we may use one factory per injector tree for optimization reasons private static final CycleDetectingLockFactory> cycleDetectingLockFactory = new CycleDetectingLockFactory>(); /** - * Provides singleton scope with the following properties: - * - creates no more than one instance per Key as a creator is used no more than once, - * - result is cached and returned quickly on subsequent calls, - * - exception in a creator is not treated as instance creation and is not cached, - * - creates singletons in parallel whenever possible, - * - waits for dependent singletons to be created even across threads and when dependencies - * are shared as long as no circular dependencies are detected, - * - returns circular proxy only when circular dependencies are detected, - * - aside from that, blocking synchronization is only used for proxy creation and initialization, + * Provides singleton scope with the following properties: - creates no more than one instance per + * Key as a creator is used no more than once, - result is cached and returned quickly on + * subsequent calls, - exception in a creator is not treated as instance creation and is not + * cached, - creates singletons in parallel whenever possible, - waits for dependent singletons to + * be created even across threads and when dependencies are shared as long as no circular + * dependencies are detected, - returns circular proxy only when circular dependencies are + * detected, - aside from that, blocking synchronization is only used for proxy creation and + * initialization, + * * @see CycleDetectingLockFactory */ + @Override public Provider scope(final Key key, final Provider creator) { /** - * Locking strategy: - * - volatile instance: double-checked locking for quick exit when scope is initialized, - * - constructionContext: manipulations with proxies list or instance initialization - * - creationLock: singleton instance creation, - * -- allows to guarantee only one instance per singleton, - * -- special type of a lock, that prevents potential deadlocks, - * -- guards constructionContext for all operations except proxy creation + * Locking strategy: - volatile instance: double-checked locking for quick exit when scope is + * initialized, - constructionContext: manipulations with proxies list or instance + * initialization - creationLock: singleton instance creation, -- allows to guarantee only one + * instance per singleton, -- special type of a lock, that prevents potential deadlocks, -- + * guards constructionContext for all operations except proxy creation */ return new Provider() { /** @@ -120,21 +101,43 @@ * Circular proxies are used when potential deadlocks are detected. Guarded by itself. * ConstructionContext is not thread-safe, so each call should be synchronized. */ - final ConstructionContext constructionContext = new ConstructionContext(); + final ConstructionContext constructionContext = new ConstructionContext<>(); /** For each binding there is a separate lock that we hold during object creation. */ final CycleDetectingLock> creationLock = cycleDetectingLockFactory.create(key); + /** + * The singleton provider needs a reference back to the injector, in order to get ahold of + * InternalContext during instantiation. + */ + final /* @Nullable */ InjectorImpl injector; + + { + // If we are getting called by Scoping + if (creator instanceof ProviderToInternalFactoryAdapter) { + injector = ((ProviderToInternalFactoryAdapter) creator).getInjector(); + } else { + injector = null; + } + } + @SuppressWarnings("DoubleCheckedLocking") + @Override public T get() { // cache volatile variable for the usual case of already initialized object final Object initialInstance = instance; if (initialInstance == null) { // instance is not initialized yet + // first, store the current InternalContext in a map, so that if there is a circular + // dependency error, we can use the InternalContext objects to create a complete + // error message. + // Handle injector being null, which can happen when users call Scoping.scope themselves + final InternalContext context = injector == null ? null : injector.getLocalContext(); // acquire lock for current binding to initialize an instance - final ListMultimap> locksCycle = + final ListMultimap> locksCycle = creationLock.lockOrDetectPotentialLocksCycle(); + if (locksCycle.isEmpty()) { // this thread now owns creation of an instance try { @@ -147,7 +150,7 @@ // scope called recursively can initialize instance as a side effect if (instance == null) { - // instance is still not initialized, se we can proceed + // instance is still not initialized, so we can proceed // don't remember proxies created by Guice on circular dependency // detection within the same thread; they are not real instances to cache @@ -162,7 +165,8 @@ } } else { // safety assert in case instance was initialized - Preconditions.checkState(instance == providedNotNull, + Preconditions.checkState( + instance == providedNotNull, "Singleton is called recursively returning different results"); } } @@ -178,50 +182,45 @@ creationLock.unlock(); } } else { + if (context == null) { + throw new ProvisionException( + ImmutableList.of(createCycleDependenciesMessage(locksCycle, null))); + } // potential deadlock detected, creation lock is not taken by this thread synchronized (constructionContext) { // guarantee thread-safety for instance and proxies initialization if (instance == null) { - // InjectorImpl.callInContext() sets this context when scope is called from Guice - Map globalInternalContext = - InjectorImpl.getGlobalInternalContext(); - InternalContext internalContext = globalInternalContext.get(Thread.currentThread()); - // creating a proxy to satisfy circular dependency across several threads - Dependency dependency = Preconditions.checkNotNull( - internalContext.getDependency(), - "globalInternalContext.get(currentThread()).getDependency()"); + Dependency dependency = + Preconditions.checkNotNull( + context.getDependency(), "internalContext.getDependency()"); Class rawType = dependency.getKey().getTypeLiteral().getRawType(); try { @SuppressWarnings("unchecked") - T proxy = (T) constructionContext.createProxy( - new Errors(), internalContext.getInjectorOptions(), rawType); + T proxy = + (T) constructionContext.createProxy(context.getInjectorOptions(), rawType); return proxy; - } catch (ErrorsException e) { + } catch (InternalProvisionException e) { // best effort to create a rich error message - List exceptionErrorMessages = e.getErrors().getMessages(); - // we expect an error thrown - Preconditions.checkState(exceptionErrorMessages.size() == 1); - // explicitly copy the map to guarantee iteration correctness - // it's ok to have a data race with other threads that are locked - Message cycleDependenciesMessage = createCycleDependenciesMessage( - ImmutableMap.copyOf(globalInternalContext), - locksCycle, - exceptionErrorMessages.get(0)); + Message proxyCreationError = Iterables.getOnlyElement(e.getErrors()); + Message cycleDependenciesMessage = + createCycleDependenciesMessage(locksCycle, proxyCreationError); // adding stack trace generated by us in addition to a standard one - throw new ProvisionException(ImmutableList.of( - cycleDependenciesMessage, exceptionErrorMessages.get(0))); + throw new ProvisionException( + ImmutableList.of(cycleDependenciesMessage, proxyCreationError)); } } } } + // at this point we're sure that singleton was initialized, // reread volatile variable to catch all corner cases // caching volatile variable to minimize number of reads performed final Object initializedInstance = instance; - Preconditions.checkState(initializedInstance != null, + Preconditions.checkState( + initializedInstance != null, "Internal error: Singleton is not initialized contrary to our expectations"); @SuppressWarnings("unchecked") T initializedTypedInstance = (T) initializedInstance; @@ -235,99 +234,45 @@ } /** - * Helper method to create beautiful and rich error descriptions. Best effort and slow. - * Tries its best to provide dependency information from injectors currently available - * in a global internal context. + * Helper method to create beautiful and rich error descriptions. Best effort and slow. Tries + * its best to provide dependency information from injectors currently available in a global + * internal context. + * + *

    The main thing being done is creating a list of Dependencies involved into lock cycle + * across all the threads involved. This is a structure we're creating: * - *

    The main thing being done is creating a list of Dependencies involved into - * lock cycle across all the threads involved. This is a structure we're creating: *

            * { Current Thread, C.class, B.class, Other Thread, B.class, C.class, Current Thread }
            * To be inserted in the beginning by Guice: { A.class, B.class, C.class }
            * 
    - * When we're calling Guice to create A and it fails in the deadlock while trying to - * create C, which is being created by another thread, which waits for B. List would - * be reversed before printing it to the end user. + * + * When we're calling Guice to create A and it fails in the deadlock while trying to create C, + * which is being created by another thread, which waits for B. List would be reversed before + * printing it to the end user. */ private Message createCycleDependenciesMessage( - Map globalInternalContext, - ListMultimap> locksCycle, - Message proxyCreationError) { + ListMultimap> locksCycle, /* @Nullable */ Message proxyCreationError) { // this is the main thing that we'll show in an error message, // current thread is populate by Guice - List sourcesCycle = Lists.newArrayList(); - sourcesCycle.add(Thread.currentThread()); - // temp map to speed up look ups - Map threadById = Maps.newHashMap(); - for (Thread thread : globalInternalContext.keySet()) { - threadById.put(thread.getId(), thread); + StringBuilder sb = new StringBuilder(); + Formatter fmt = new Formatter(sb); + fmt.format("Encountered circular dependency spanning several threads."); + if (proxyCreationError != null) { + fmt.format(" %s", proxyCreationError.getMessage()); } - for (long lockedThreadId : locksCycle.keySet()) { - Thread lockedThread = threadById.get(lockedThreadId); - List> lockedKeys = Collections.unmodifiableList(locksCycle.get(lockedThreadId)); - if (lockedThread == null) { - // thread in a lock cycle is already terminated - continue; + fmt.format("%n"); + for (Thread lockedThread : locksCycle.keySet()) { + List> lockedKeys = locksCycle.get(lockedThread); + fmt.format("%s is holding locks the following singletons in the cycle:%n", lockedThread); + for (Key lockedKey : lockedKeys) { + fmt.format("%s%n", Errors.convert(lockedKey)); } - List dependencyChain = null; - boolean allLockedKeysAreFoundInDependencies = false; - // thread in a cycle is still present - InternalContext lockedThreadInternalContext = globalInternalContext.get(lockedThread); - if (lockedThreadInternalContext != null) { - dependencyChain = lockedThreadInternalContext.getDependencyChain(); - - // check that all of the keys are still present in dependency chain in order - List> lockedKeysToFind = Lists.newLinkedList(lockedKeys); - // check stack trace of the thread - for (DependencyAndSource d : dependencyChain) { - Dependency dependency = d.getDependency(); - if (dependency == null) { - continue; - } - if (dependency.getKey().equals(lockedKeysToFind.get(0))) { - lockedKeysToFind.remove(0); - if (lockedKeysToFind.isEmpty()) { - // everything is found! - allLockedKeysAreFoundInDependencies = true; - break; - } - } - } - } - if (allLockedKeysAreFoundInDependencies) { - // all keys are present in a dependency chain of a thread's last injector, - // highly likely that we just have discovered a dependency - // chain that is part of a lock cycle starting with the first lock owned - Key firstLockedKey = lockedKeys.get(0); - boolean firstLockedKeyFound = false; - for (DependencyAndSource d : dependencyChain) { - Dependency dependency = d.getDependency(); - if (dependency == null) { - continue; - } - if (firstLockedKeyFound) { - sourcesCycle.add(dependency); - sourcesCycle.add(d.getBindingSource()); - } else if (dependency.getKey().equals(firstLockedKey)) { - firstLockedKeyFound = true; - // for the very first one found we don't care why, so no dependency is added - sourcesCycle.add(d.getBindingSource()); - } - } - } else { - // something went wrong and not all keys are present in a state of an injector - // that was used last for a current thread. - // let's add all keys we're aware of, still better than nothing - sourcesCycle.addAll(lockedKeys); + for (StackTraceElement traceElement : lockedThread.getStackTrace()) { + fmt.format("\tat %s%n", traceElement); } - // mentions that a tread is a part of a cycle - sourcesCycle.add(lockedThread); } - return new Message( - sourcesCycle, - String.format("Encountered circular dependency spanning several threads. %s", - proxyCreationError.getMessage()), - null); + fmt.close(); + return new Message(Thread.currentThread(), sb.toString()); } @Override @@ -337,7 +282,8 @@ }; } - @Override public String toString() { + @Override + public String toString() { return "Scopes.SINGLETON"; } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/State.java sisu-guice-4.2.0/core/src/com/google/inject/internal/State.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/State.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/State.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,13 +23,11 @@ import com.google.inject.Key; import com.google.inject.Scope; import com.google.inject.TypeLiteral; -import com.google.inject.spi.ModuleAnnotatedMethodScanner; import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding; import com.google.inject.spi.ProvisionListenerBinding; import com.google.inject.spi.ScopeBinding; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; - import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; @@ -43,101 +41,124 @@ */ interface State { - static final State NONE = new State() { - public State parent() { - throw new UnsupportedOperationException(); - } - - public BindingImpl getExplicitBinding(Key key) { - return null; - } - - public Map, Binding> getExplicitBindingsThisLevel() { - throw new UnsupportedOperationException(); - } - - public void putBinding(Key key, BindingImpl binding) { - throw new UnsupportedOperationException(); - } - - public ScopeBinding getScopeBinding(Class scopingAnnotation) { - return null; - } - - public void putScopeBinding(Class annotationType, ScopeBinding scope) { - throw new UnsupportedOperationException(); - } - - public void addConverter(TypeConverterBinding typeConverterBinding) { - throw new UnsupportedOperationException(); - } - - public TypeConverterBinding getConverter(String stringValue, TypeLiteral type, Errors errors, - Object source) { - throw new UnsupportedOperationException(); - } - - public Iterable getConvertersThisLevel() { - return ImmutableSet.of(); - } - - /*if[AOP]*/ - public void addMethodAspect(MethodAspect methodAspect) { - throw new UnsupportedOperationException(); - } - - public ImmutableList getMethodAspects() { - return ImmutableList.of(); - } - /*end[AOP]*/ - - public void addTypeListener(TypeListenerBinding typeListenerBinding) { - throw new UnsupportedOperationException(); - } - - public List getTypeListenerBindings() { - return ImmutableList.of(); - } - - public void addProvisionListener(ProvisionListenerBinding provisionListenerBinding) { - throw new UnsupportedOperationException(); - } - - public List getProvisionListenerBindings() { - return ImmutableList.of(); - } - - public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) { - throw new UnsupportedOperationException(); - } - - public List getScannerBindings() { - return ImmutableList.of(); - } - - public void blacklist(Key key, State state, Object source) { - } - - public boolean isBlacklisted(Key key) { - return true; - } - - public Set getSourcesForBlacklistedKey(Key key) { - throw new UnsupportedOperationException(); - } - - public Object lock() { - throw new UnsupportedOperationException(); - } - - public Object singletonCreationLock() { - throw new UnsupportedOperationException(); - } - - public Map, Scope> getScopes() { - return ImmutableMap.of(); - } - }; + static final State NONE = + new State() { + @Override + public State parent() { + throw new UnsupportedOperationException(); + } + + @Override + public BindingImpl getExplicitBinding(Key key) { + return null; + } + + @Override + public Map, Binding> getExplicitBindingsThisLevel() { + throw new UnsupportedOperationException(); + } + + @Override + public void putBinding(Key key, BindingImpl binding) { + throw new UnsupportedOperationException(); + } + + @Override + public ScopeBinding getScopeBinding(Class scopingAnnotation) { + return null; + } + + @Override + public void putScopeBinding( + Class annotationType, ScopeBinding scope) { + throw new UnsupportedOperationException(); + } + + @Override + public void addConverter(TypeConverterBinding typeConverterBinding) { + throw new UnsupportedOperationException(); + } + + @Override + public TypeConverterBinding getConverter( + String stringValue, TypeLiteral type, Errors errors, Object source) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getConvertersThisLevel() { + return ImmutableSet.of(); + } + + /*if[AOP]*/ + @Override + public void addMethodAspect(MethodAspect methodAspect) { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableList getMethodAspects() { + return ImmutableList.of(); + } + /*end[AOP]*/ + + @Override + public void addTypeListener(TypeListenerBinding typeListenerBinding) { + throw new UnsupportedOperationException(); + } + + @Override + public List getTypeListenerBindings() { + return ImmutableList.of(); + } + + @Override + public void addProvisionListener(ProvisionListenerBinding provisionListenerBinding) { + throw new UnsupportedOperationException(); + } + + @Override + public List getProvisionListenerBindings() { + return ImmutableList.of(); + } + + @Override + public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) { + throw new UnsupportedOperationException(); + } + + @Override + public List getScannerBindings() { + return ImmutableList.of(); + } + + @Override + public void blacklist(Key key, State state, Object source) {} + + @Override + public boolean isBlacklisted(Key key) { + return true; + } + + @Override + public Set getSourcesForBlacklistedKey(Key key) { + throw new UnsupportedOperationException(); + } + + @Override + public Object lock() { + throw new UnsupportedOperationException(); + } + + public Object singletonCreationLock() { + throw new UnsupportedOperationException(); + } + + @Override + public Map, Scope> getScopes() { + return ImmutableMap.of(); + } + }; State parent(); @@ -148,7 +169,7 @@ Map, Binding> getExplicitBindingsThisLevel(); void putBinding(Key key, BindingImpl binding); - + ScopeBinding getScopeBinding(Class scopingAnnotation); void putScopeBinding(Class annotationType, ScopeBinding scope); @@ -169,11 +190,11 @@ /*end[AOP]*/ void addTypeListener(TypeListenerBinding typeListenerBinding); - + List getTypeListenerBindings(); - + void addProvisionListener(ProvisionListenerBinding provisionListenerBinding); - + List getProvisionListenerBindings(); void addScanner(ModuleAnnotatedMethodScannerBinding scanner); @@ -192,7 +213,7 @@ * one of this injector's descendent's has bound the key. */ boolean isBlacklisted(Key key); - + /** Returns the source of a blacklisted key. */ Set getSourcesForBlacklistedKey(Key key); @@ -202,8 +223,6 @@ */ Object lock(); - /** - * Returns all the scope bindings at this level and parent levels. - */ + /** Returns all the scope bindings at this level and parent levels. */ Map, Scope> getScopes(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.inject.matcher.Matchers; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeConverterBinding; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -51,79 +50,97 @@ convertToPrimitiveType(injector, float.class, Float.class); convertToPrimitiveType(injector, double.class, Double.class); - convertToClass(injector, Character.class, new TypeConverter() { - public Object convert(String value, TypeLiteral toType) { - value = value.trim(); - if (value.length() != 1) { - throw new RuntimeException("Length != 1."); - } - return value.charAt(0); - } - - @Override public String toString() { - return "TypeConverter"; - } - }); - - convertToClasses(injector, Matchers.subclassesOf(Enum.class), new TypeConverter() { - @SuppressWarnings("unchecked") - public Object convert(String value, TypeLiteral toType) { - return Enum.valueOf((Class) toType.getRawType(), value); - } - - @Override public String toString() { - return "TypeConverter>"; - } - }); - - internalConvertToTypes(injector, new AbstractMatcher>() { - public boolean matches(TypeLiteral typeLiteral) { - return typeLiteral.getRawType() == Class.class; - } - - @Override public String toString() { - return "Class"; - } - }, - new TypeConverter() { - @SuppressWarnings("unchecked") - public Object convert(String value, TypeLiteral toType) { - try { - return Class.forName(value); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e.getMessage()); - } - } - - @Override public String toString() { - return "TypeConverter>"; - } - } - ); + convertToClass( + injector, + Character.class, + new TypeConverter() { + @Override + public Object convert(String value, TypeLiteral toType) { + value = value.trim(); + if (value.length() != 1) { + throw new RuntimeException("Length != 1."); + } + return value.charAt(0); + } + + @Override + public String toString() { + return "TypeConverter"; + } + }); + + convertToClasses( + injector, + Matchers.subclassesOf(Enum.class), + new TypeConverter() { + @Override + @SuppressWarnings("unchecked") + public Object convert(String value, TypeLiteral toType) { + return Enum.valueOf((Class) toType.getRawType(), value); + } + + @Override + public String toString() { + return "TypeConverter>"; + } + }); + + internalConvertToTypes( + injector, + new AbstractMatcher>() { + @Override + public boolean matches(TypeLiteral typeLiteral) { + return typeLiteral.getRawType() == Class.class; + } + + @Override + public String toString() { + return "Class"; + } + }, + new TypeConverter() { + @Override + @SuppressWarnings("unchecked") + public Object convert(String value, TypeLiteral toType) { + try { + return Class.forName(value); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.getMessage()); + } + } + + @Override + public String toString() { + return "TypeConverter>"; + } + }); } - private static void convertToPrimitiveType(InjectorImpl injector, Class primitiveType, - final Class wrapperType) { + private static void convertToPrimitiveType( + InjectorImpl injector, Class primitiveType, final Class wrapperType) { try { - final Method parser = wrapperType.getMethod( - "parse" + capitalize(primitiveType.getName()), String.class); + final Method parser = + wrapperType.getMethod("parse" + capitalize(primitiveType.getName()), String.class); - TypeConverter typeConverter = new TypeConverter() { - @SuppressWarnings("unchecked") - public Object convert(String value, TypeLiteral toType) { - try { - return parser.invoke(null, value); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e.getTargetException().getMessage()); - } - } - - @Override public String toString() { - return "TypeConverter<" + wrapperType.getSimpleName() + ">"; - } - }; + TypeConverter typeConverter = + new TypeConverter() { + @Override + @SuppressWarnings("unchecked") + public Object convert(String value, TypeLiteral toType) { + try { + return parser.invoke(null, value); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getTargetException().getMessage()); + } + } + + @Override + public String toString() { + return "TypeConverter<" + wrapperType.getSimpleName() + ">"; + } + }; convertToClass(injector, wrapperType, typeConverter); } catch (NoSuchMethodException e) { @@ -131,51 +148,54 @@ } } - private static void convertToClass(InjectorImpl injector, Class type, - TypeConverter converter) { + private static void convertToClass( + InjectorImpl injector, Class type, TypeConverter converter) { convertToClasses(injector, Matchers.identicalTo(type), converter); } - private static void convertToClasses(InjectorImpl injector, - final Matcher> typeMatcher, TypeConverter converter) { - internalConvertToTypes(injector, new AbstractMatcher>() { - public boolean matches(TypeLiteral typeLiteral) { - Type type = typeLiteral.getType(); - if (!(type instanceof Class)) { - return false; - } - Class clazz = (Class) type; - return typeMatcher.matches(clazz); - } - - @Override public String toString() { - return typeMatcher.toString(); - } - }, converter); - } - - private static void internalConvertToTypes(InjectorImpl injector, - Matcher> typeMatcher, - TypeConverter converter) { + private static void convertToClasses( + InjectorImpl injector, final Matcher> typeMatcher, TypeConverter converter) { + internalConvertToTypes( + injector, + new AbstractMatcher>() { + @Override + public boolean matches(TypeLiteral typeLiteral) { + Type type = typeLiteral.getType(); + if (!(type instanceof Class)) { + return false; + } + Class clazz = (Class) type; + return typeMatcher.matches(clazz); + } + + @Override + public String toString() { + return typeMatcher.toString(); + } + }, + converter); + } + + private static void internalConvertToTypes( + InjectorImpl injector, Matcher> typeMatcher, TypeConverter converter) { injector.state.addConverter( new TypeConverterBinding(SourceProvider.UNKNOWN_SOURCE, typeMatcher, converter)); } - @Override public Boolean visit(TypeConverterBinding command) { - injector.state.addConverter(new TypeConverterBinding( - command.getSource(), command.getTypeMatcher(), command.getTypeConverter())); + @Override + public Boolean visit(TypeConverterBinding command) { + injector.state.addConverter( + new TypeConverterBinding( + command.getSource(), command.getTypeMatcher(), command.getTypeConverter())); return true; } - + private static String capitalize(String s) { if (s.length() == 0) { return s; } char first = s.charAt(0); char capitalized = Character.toUpperCase(first); - return (first == capitalized) - ? s - : capitalized + s.substring(1); + return (first == capitalized) ? s : capitalized + s.substring(1); } - } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/UniqueAnnotations.java sisu-guice-4.2.0/core/src/com/google/inject/internal/UniqueAnnotations.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/UniqueAnnotations.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/UniqueAnnotations.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,21 +19,19 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.BindingAnnotation; - import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.util.concurrent.atomic.AtomicInteger; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class UniqueAnnotations { private UniqueAnnotations() {} + private static final AtomicInteger nextUniqueValue = new AtomicInteger(1); /** - * Returns an annotation instance that is not equal to any other annotation - * instances, for use in creating distinct {@link com.google.inject.Key}s. + * Returns an annotation instance that is not equal to any other annotation instances, for use in + * creating distinct {@link com.google.inject.Key}s. */ public static Annotation create() { return create(nextUniqueValue.getAndIncrement()); @@ -41,30 +39,35 @@ static Annotation create(final int value) { return new Internal() { + @Override public int value() { return value; } + @Override public Class annotationType() { return Internal.class; } - @Override public String toString() { + @Override + public String toString() { return "@" + Internal.class.getName() + "(value=" + value + ")"; } - @Override public boolean equals(Object o) { - return o instanceof Internal - && ((Internal) o).value() == value(); + @Override + public boolean equals(Object o) { + return o instanceof Internal && ((Internal) o).value() == value(); } - @Override public int hashCode() { + @Override + public int hashCode() { return (127 * "value".hashCode()) ^ value; } }; } - @Retention(RUNTIME) @BindingAnnotation + @Retention(RUNTIME) + @BindingAnnotation @interface Internal { int value(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/UntargettedBindingImpl.java sisu-guice-4.2.0/core/src/com/google/inject/internal/UntargettedBindingImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/UntargettedBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/UntargettedBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -16,6 +16,7 @@ package com.google.inject.internal; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.inject.Binder; import com.google.inject.Key; @@ -26,35 +27,46 @@ final class UntargettedBindingImpl extends BindingImpl implements UntargettedBinding { UntargettedBindingImpl(InjectorImpl injector, Key key, Object source) { - super(injector, key, source, new InternalFactory() { - public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { - throw new AssertionError(); - } - }, Scoping.UNSCOPED); + super( + injector, + key, + source, + new InternalFactory() { + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) { + throw new AssertionError(); + } + }, + Scoping.UNSCOPED); } public UntargettedBindingImpl(Object source, Key key, Scoping scoping) { super(source, key, scoping); } + @Override public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } + @Override public BindingImpl withScoping(Scoping scoping) { return new UntargettedBindingImpl(getSource(), getKey(), scoping); } + @Override public BindingImpl withKey(Key key) { return new UntargettedBindingImpl(getSource(), key, getScoping()); } + @Override public void applyTo(Binder binder) { getScoping().applyTo(binder.withSource(getSource()).bind(getKey())); } - @Override public String toString() { - return Objects.toStringHelper(UntargettedBinding.class) + @Override + public String toString() { + return MoreObjects.toStringHelper(UntargettedBinding.class) .add("key", getKey()) .add("source", getSource()) .toString(); @@ -62,10 +74,9 @@ @Override public boolean equals(Object obj) { - if(obj instanceof UntargettedBindingImpl) { - UntargettedBindingImpl o = (UntargettedBindingImpl)obj; - return getKey().equals(o.getKey()) - && getScoping().equals(o.getScoping()); + if (obj instanceof UntargettedBindingImpl) { + UntargettedBindingImpl o = (UntargettedBindingImpl) obj; + return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()); } else { return false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/UntargettedBindingProcessor.java sisu-guice-4.2.0/core/src/com/google/inject/internal/UntargettedBindingProcessor.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/UntargettedBindingProcessor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/UntargettedBindingProcessor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,45 +25,47 @@ * @author sameb@google.com (Sam Berlin) */ class UntargettedBindingProcessor extends AbstractBindingProcessor { - + UntargettedBindingProcessor(Errors errors, ProcessedBindingData bindingData) { super(errors, bindingData); } - + @Override public Boolean visit(Binding binding) { - return binding.acceptTargetVisitor(new Processor((BindingImpl)binding) { - public Boolean visit(UntargettedBinding untargetted) { - prepareBinding(); - - // Error: Missing implementation. - // Example: bind(Date.class).annotatedWith(Red.class); - // We can't assume abstract types aren't injectable. They may have an - // @ImplementedBy annotation or something. - if (key.getAnnotationType() != null) { - errors.missingImplementation(key); - putBinding(invalidBinding(injector, key, source)); - return true; - } - - // This cast is safe after the preceeding check. - try { - BindingImpl binding = injector.createUninitializedBinding( - key, scoping, source, errors, false); - scheduleInitialization(binding); - putBinding(binding); - } catch (ErrorsException e) { - errors.merge(e.getErrors()); - putBinding(invalidBinding(injector, key, source)); - } - - return true; - } - - @Override - protected Boolean visitOther(Binding binding) { - return false; - } - }); + return binding.acceptTargetVisitor( + new Processor((BindingImpl) binding) { + @Override + public Boolean visit(UntargettedBinding untargetted) { + prepareBinding(); + + // Error: Missing implementation. + // Example: bind(Date.class).annotatedWith(Red.class); + // We can't assume abstract types aren't injectable. They may have an + // @ImplementedBy annotation or something. + if (key.getAnnotationType() != null) { + errors.missingImplementationWithHint(key, injector); + putBinding(invalidBinding(injector, key, source)); + return true; + } + + // This cast is safe after the preceeding check. + try { + BindingImpl binding = + injector.createUninitializedBinding(key, scoping, source, errors, false); + scheduleInitialization(binding); + putBinding(binding); + } catch (ErrorsException e) { + errors.merge(e.getErrors()); + putBinding(invalidBinding(injector, key, source)); + } + + return true; + } + + @Override + protected Boolean visitOther(Binding binding) { + return false; + } + }); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/util/Classes.java sisu-guice-4.2.0/core/src/com/google/inject/internal/util/Classes.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/util/Classes.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/util/Classes.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,14 +24,11 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -/** - * Class utilities. - */ +/** Class utilities. */ public final class Classes { public static boolean isInnerClass(Class clazz) { - return !Modifier.isStatic(clazz.getModifiers()) - && clazz.getEnclosingClass() != null; + return !Modifier.isStatic(clazz.getModifiers()) && clazz.getEnclosingClass() != null; } public static boolean isConcrete(Class clazz) { @@ -40,12 +37,12 @@ } /** - * Formats a member as concise string, such as {@code java.util.ArrayList.size}, - * {@code java.util.ArrayList()} or {@code java.util.List.remove()}. + * Formats a member as concise string, such as {@code java.util.ArrayList.size}, {@code + * java.util.ArrayList()} or {@code java.util.List.remove()}. */ public static String toString(Member member) { Class memberType = Classes.memberType(member); - + if (memberType == Method.class) { return member.getDeclaringClass().getName() + "." + member.getName() + "()"; } else if (memberType == Field.class) { @@ -57,21 +54,19 @@ } } - /** - * Returns {@code Field.class}, {@code Method.class} or {@code Constructor.class}. - */ + /** Returns {@code Field.class}, {@code Method.class} or {@code Constructor.class}. */ public static Class memberType(Member member) { checkNotNull(member, "member"); - + if (member instanceof Field) { return Field.class; - + } else if (member instanceof Method) { return Method.class; - + } else if (member instanceof Constructor) { return Constructor.class; - + } else { throw new IllegalArgumentException( "Unsupported implementation class for Member, " + member.getClass()); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/util/LineNumbers.java sisu-guice-4.2.0/core/src/com/google/inject/internal/util/LineNumbers.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/util/LineNumbers.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/util/LineNumbers.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,15 +20,6 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Maps; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; @@ -36,6 +27,13 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.Map; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; /** * Looks up line numbers for classes and their members. @@ -62,7 +60,14 @@ if (!type.isArray()) { InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class"); if (in != null) { - new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES); + try { + new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES); + } finally { + try { + in.close(); + } catch (IOException ignored) { + } + } } } } @@ -82,11 +87,15 @@ * @param member a field, constructor, or method belonging to the class used during construction * @return the wrapped line number, or null if not available * @throws IllegalArgumentException if the member does not belong to the class used during - * construction + * construction */ public Integer getLineNumber(Member member) { - Preconditions.checkArgument(type == member.getDeclaringClass(), - "Member %s belongs to %s, not %s", member, member.getDeclaringClass(), type); + Preconditions.checkArgument( + type == member.getDeclaringClass(), + "Member %s belongs to %s, not %s", + member, + member.getDeclaringClass(), + type); return lines.get(memberKey(member)); } @@ -108,7 +117,7 @@ } else if (member instanceof Constructor) { StringBuilder sb = new StringBuilder().append("("); for (Class param : ((Constructor) member).getParameterTypes()) { - sb.append(org.objectweb.asm.Type.getDescriptor(param)); + sb.append(org.objectweb.asm.Type.getDescriptor(param)); } return sb.append(")V").toString(); @@ -120,7 +129,7 @@ /*if[NO_AOP] return ""; end[NO_AOP]*/ - } + } private class LineNumberReader extends ClassVisitor { @@ -129,16 +138,23 @@ private String name; LineNumberReader() { - super(Opcodes.ASM5); + super(Opcodes.ASM6); } - public void visit(int version, int access, String name, String signature, - String superName, String[] interfaces) { + @Override + public void visit( + int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { this.name = name; } - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { + @Override + public MethodVisitor visitMethod( + int access, String name, String desc, String signature, String[] exceptions) { if ((access & Opcodes.ACC_PRIVATE) != 0) { return null; } @@ -147,6 +163,7 @@ return new LineNumberMethodVisitor(); } + @Override public void visitSource(String source, String debug) { LineNumbers.this.source = source; } @@ -163,41 +180,47 @@ } } - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { + @Override + public FieldVisitor visitField( + int access, String name, String desc, String signature, Object value) { return null; } + @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return new LineNumberAnnotationVisitor(); } - public AnnotationVisitor visitParameterAnnotation(int parameter, - String desc, boolean visible) { + public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { return new LineNumberAnnotationVisitor(); } class LineNumberMethodVisitor extends MethodVisitor { LineNumberMethodVisitor() { - super(Opcodes.ASM5); + super(Opcodes.ASM6); } + @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return new LineNumberAnnotationVisitor(); } + @Override public AnnotationVisitor visitAnnotationDefault() { return new LineNumberAnnotationVisitor(); } - public void visitFieldInsn(int opcode, String owner, String name, - String desc) { - if (opcode == Opcodes.PUTFIELD && LineNumberReader.this.name.equals(owner) - && !lines.containsKey(name) && line != -1) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) { + if (opcode == Opcodes.PUTFIELD + && LineNumberReader.this.name.equals(owner) + && !lines.containsKey(name) + && line != -1) { lines.put(name, line); } } + @Override public void visitLineNumber(int line, Label start) { LineNumberReader.this.visitLineNumber(line, start); } @@ -205,19 +228,21 @@ class LineNumberAnnotationVisitor extends AnnotationVisitor { LineNumberAnnotationVisitor() { - super(Opcodes.ASM5); + super(Opcodes.ASM6); } + + @Override public AnnotationVisitor visitAnnotation(String name, String desc) { return this; } + + @Override public AnnotationVisitor visitArray(String name) { return this; } - public void visitLocalVariable(String name, String desc, String signature, - Label start, Label end, int index) { - } + public void visitLocalVariable( + String name, String desc, String signature, Label start, Label end, int index) {} } - } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/util/SourceProvider.java sisu-guice-4.2.0/core/src/com/google/inject/internal/util/SourceProvider.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/util/SourceProvider.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/util/SourceProvider.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,12 +19,11 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; - import java.util.List; /** * Provides access to the calling line of code. - * + * * @author crazybob@google.com (Bob Lee) */ public final class SourceProvider { @@ -34,9 +33,9 @@ private final SourceProvider parent; private final ImmutableSet classNamesToSkip; - - public static final SourceProvider DEFAULT_INSTANCE - = new SourceProvider(ImmutableSet.of(SourceProvider.class.getName())); + + public static final SourceProvider DEFAULT_INSTANCE = + new SourceProvider(ImmutableSet.of(SourceProvider.class.getName())); private SourceProvider(Iterable classesToSkip) { this(null, classesToSkip); @@ -44,7 +43,7 @@ private SourceProvider(SourceProvider parent, Iterable classesToSkip) { this.parent = parent; - + ImmutableSet.Builder classNamesToSkipBuilder = ImmutableSet.builder(); for (String classToSkip : classesToSkip) { if (parent == null || !parent.shouldBeSkipped(classToSkip)) { @@ -64,7 +63,7 @@ return (parent != null && parent.shouldBeSkipped(className)) || classNamesToSkip.contains(className); } - + /** Returns the class names as Strings */ private static List asStrings(Class... classes) { List strings = Lists.newArrayList(); @@ -82,7 +81,7 @@ Preconditions.checkNotNull(stackTraceElements, "The stack trace elements cannot be null."); for (final StackTraceElement element : stackTraceElements) { String className = element.getClassName(); - + if (!shouldBeSkipped(className)) { return element; } @@ -90,9 +89,7 @@ throw new AssertionError(); } - /** - * Returns the non-skipped module class name. - */ + /** Returns the non-skipped module class name. */ public Object getFromClassNames(List moduleClassNames) { Preconditions.checkNotNull(moduleClassNames, "The list of module class names cannot be null."); for (final String moduleClassName : moduleClassNames) { diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/util/StackTraceElements.java sisu-guice-4.2.0/core/src/com/google/inject/internal/util/StackTraceElements.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/util/StackTraceElements.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/util/StackTraceElements.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,12 +19,11 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.common.collect.MapMaker; - import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Member; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * Creates stack trace elements for members. @@ -34,25 +33,31 @@ public class StackTraceElements { private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; - private static final InMemoryStackTraceElement[] EMPTY_INMEMORY_STACK_TRACE = + private static final InMemoryStackTraceElement[] EMPTY_INMEMORY_STACK_TRACE = new InMemoryStackTraceElement[0]; /*if[AOP]*/ static final LoadingCache, LineNumbers> lineNumbersCache = - CacheBuilder.newBuilder().weakKeys().softValues().build( - new CacheLoader, LineNumbers>() { - public LineNumbers load(Class key) { - try { - return new LineNumbers(key); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - }); + CacheBuilder.newBuilder() + .weakKeys() + .softValues() + .build( + new CacheLoader, LineNumbers>() { + @Override + public LineNumbers load(Class key) { + try { + return new LineNumbers(key); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); /*end[AOP]*/ - private static Map cache = new MapMaker().makeMap(); + private static final ConcurrentMap + elementCache = new ConcurrentHashMap<>(); + private static final ConcurrentMap stringCache = new ConcurrentHashMap<>(); + private static final String UNKNOWN_SOURCE = "Unknown Source"; public static Object forMember(Member member) { @@ -91,31 +96,28 @@ return new StackTraceElement(implementation.getName(), "class", fileName, lineNumber); } - - /** - * Clears the internal cache for {@link StackTraceElement StackTraceElements}. - */ + + /** Clears the internal cache for {@link StackTraceElement StackTraceElements}. */ public static void clearCache() { - cache.clear(); + elementCache.clear(); + stringCache.clear(); } - - /** - * Returns encoded in-memory version of {@link StackTraceElement StackTraceElements}. - */ + + /** Returns encoded in-memory version of {@link StackTraceElement StackTraceElements}. */ public static InMemoryStackTraceElement[] convertToInMemoryStackTraceElement( StackTraceElement[] stackTraceElements) { if (stackTraceElements.length == 0) { return EMPTY_INMEMORY_STACK_TRACE; } - InMemoryStackTraceElement[] inMemoryStackTraceElements = + InMemoryStackTraceElement[] inMemoryStackTraceElements = new InMemoryStackTraceElement[stackTraceElements.length]; for (int i = 0; i < stackTraceElements.length; i++) { - inMemoryStackTraceElements[i] = + inMemoryStackTraceElements[i] = weakIntern(new InMemoryStackTraceElement(stackTraceElements[i])); } return inMemoryStackTraceElements; } - + /** * Decodes in-memory stack trace elements to regular {@link StackTraceElement StackTraceElements}. */ @@ -124,45 +126,43 @@ if (inMemoryStackTraceElements.length == 0) { return EMPTY_STACK_TRACE; } - StackTraceElement[] stackTraceElements = + StackTraceElement[] stackTraceElements = new StackTraceElement[inMemoryStackTraceElements.length]; for (int i = 0; i < inMemoryStackTraceElements.length; i++) { String declaringClass = inMemoryStackTraceElements[i].getClassName(); String methodName = inMemoryStackTraceElements[i].getMethodName(); int lineNumber = inMemoryStackTraceElements[i].getLineNumber(); - stackTraceElements[i] = + stackTraceElements[i] = new StackTraceElement(declaringClass, methodName, UNKNOWN_SOURCE, lineNumber); } return stackTraceElements; } - + private static InMemoryStackTraceElement weakIntern( InMemoryStackTraceElement inMemoryStackTraceElement) { - InMemoryStackTraceElement cached = - (InMemoryStackTraceElement) cache.get(inMemoryStackTraceElement); + InMemoryStackTraceElement cached = elementCache.get(inMemoryStackTraceElement); if (cached != null) { return cached; } - inMemoryStackTraceElement = new InMemoryStackTraceElement( - weakIntern(inMemoryStackTraceElement.getClassName()), - weakIntern(inMemoryStackTraceElement.getMethodName()), - inMemoryStackTraceElement.getLineNumber()); - cache.put(inMemoryStackTraceElement, inMemoryStackTraceElement); + inMemoryStackTraceElement = + new InMemoryStackTraceElement( + weakIntern(inMemoryStackTraceElement.getClassName()), + weakIntern(inMemoryStackTraceElement.getMethodName()), + inMemoryStackTraceElement.getLineNumber()); + elementCache.put(inMemoryStackTraceElement, inMemoryStackTraceElement); return inMemoryStackTraceElement; } - + private static String weakIntern(String s) { - String cached = (String) cache.get(s); + String cached = stringCache.get(s); if (cached != null) { return cached; } - cache.put(s, s); - return s; + stringCache.put(s, s); + return s; } - - /** - * In-Memory version of {@link StackTraceElement} that does not store the file name. - */ + + /** In-Memory version of {@link StackTraceElement} that does not store the file name. */ public static class InMemoryStackTraceElement { private String declaringClass; private String methodName; @@ -181,11 +181,11 @@ String getClassName() { return declaringClass; } - + String getMethodName() { return methodName; } - + int getLineNumber() { return lineNumber; } @@ -199,8 +199,9 @@ return false; } InMemoryStackTraceElement e = (InMemoryStackTraceElement) obj; - return e.declaringClass.equals(declaringClass) && e.lineNumber == lineNumber && - methodName.equals(e.methodName); + return e.declaringClass.equals(declaringClass) + && e.lineNumber == lineNumber + && methodName.equals(e.methodName); } @Override @@ -209,7 +210,7 @@ result = 31 * result + lineNumber; return result; } - + @Override public String toString() { return declaringClass + "." + methodName + "(" + lineNumber + ")"; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/util/Stopwatch.java sisu-guice-4.2.0/core/src/com/google/inject/internal/util/Stopwatch.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/util/Stopwatch.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/util/Stopwatch.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,9 +28,7 @@ private long start = System.currentTimeMillis(); - /** - * Resets and returns elapsed time in milliseconds. - */ + /** Resets and returns elapsed time in milliseconds. */ public long reset() { long now = System.currentTimeMillis(); try { @@ -40,9 +38,7 @@ } } - /** - * Resets and logs elapsed time in milliseconds. - */ + /** Resets and logs elapsed time in milliseconds. */ public void resetAndLog(String label) { logger.fine(label + ": " + reset() + "ms"); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/internal/WeakKeySet.java sisu-guice-4.2.0/core/src/com/google/inject/internal/WeakKeySet.java --- sisu-guice-3.2.6/core/src/com/google/inject/internal/WeakKeySet.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/internal/WeakKeySet.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,6 @@ import com.google.common.collect.Sets; import com.google.inject.Key; import com.google.inject.internal.util.SourceProvider; - import java.util.Map; import java.util.Set; @@ -52,18 +51,19 @@ * Tracks child injector lifetimes and evicts blacklisted keys/sources after the child injector is * garbage collected. */ - private final Cache> evictionCache = CacheBuilder.newBuilder() - .weakKeys() - .removalListener( - new RemovalListener>() { - @Override - public void onRemoval(RemovalNotification> notification) { - Preconditions.checkState(RemovalCause.COLLECTED.equals(notification.getCause())); - - cleanUpForCollectedState(notification.getValue()); - } - }) - .build(); + private final Cache> evictionCache = + CacheBuilder.newBuilder() + .weakKeys() + .removalListener( + new RemovalListener>() { + @Override + public void onRemoval(RemovalNotification> notification) { + Preconditions.checkState(RemovalCause.COLLECTED.equals(notification.getCause())); + + cleanUpForCollectedState(notification.getValue()); + } + }) + .build(); /** * There may be multiple child injectors blacklisting a certain key so only remove the source @@ -150,8 +150,7 @@ } KeyAndSource other = (KeyAndSource) obj; - return Objects.equal(key, other.key) - && Objects.equal(source, other.source); + return Objects.equal(key, other.key) && Objects.equal(source, other.source); } } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Key.java sisu-guice-4.2.0/core/src/com/google/inject/Key.java --- sisu-guice-3.2.6/core/src/com/google/inject/Key.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Key.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,20 +21,16 @@ import static com.google.inject.internal.Annotations.generateAnnotation; import static com.google.inject.internal.Annotations.isAllDefaultMethods; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; import com.google.inject.internal.Annotations; import com.google.inject.internal.MoreTypes; - import java.lang.annotation.Annotation; import java.lang.reflect.Type; /** - * Binding key consisting of an injection type and an optional annotation. - * Matches the type and annotation at a point of injection. + * Binding key consisting of an injection type and an optional annotation. Matches the type and + * annotation at a point of injection. * - *

    For example, {@code Key.get(Service.class, Transactional.class)} will - * match: + *

    For example, {@code Key.get(Service.class, Transactional.class)} will match: * *

      *   {@literal @}Inject
    @@ -43,12 +39,11 @@
      *   }
      * 
    * - *

    {@code Key} supports generic types via subclassing just like {@link - * TypeLiteral}. + *

    {@code Key} supports generic types via subclassing just like {@link TypeLiteral}. * - *

    Keys do not differentiate between primitive types (int, char, etc.) and - * their corresponding wrapper types (Integer, Character, etc.). Primitive - * types will be replaced with their wrapper types when keys are created. + *

    Keys do not differentiate between primitive types (int, char, etc.) and their corresponding + * wrapper types (Integer, Character, etc.). Primitive types will be replaced with their wrapper + * types when keys are created. * * @author crazybob@google.com (Bob Lee) */ @@ -58,38 +53,37 @@ private final TypeLiteral typeLiteral; private final int hashCode; - private final Supplier toStringSupplier; + // This field is updated using the 'Data-Race-Ful' lazy intialization pattern + // See http://jeremymanson.blogspot.com/2008/12/benign-data-races-in-java.html for a detailed + // explanation. + private String toString; /** * Constructs a new key. Derives the type from this class's type parameter. * - *

    Clients create an empty anonymous subclass. Doing so embeds the type - * parameter in the anonymous class's type hierarchy so we can reconstitute it - * at runtime despite erasure. + *

    Clients create an empty anonymous subclass. Doing so embeds the type parameter in the + * anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure. * - *

    Example usage for a binding of type {@code Foo} annotated with - * {@code @Bar}: + *

    Example usage for a binding of type {@code Foo} annotated with {@code @Bar}: * *

    {@code new Key(Bar.class) {}}. */ @SuppressWarnings("unchecked") protected Key(Class annotationType) { this.annotationStrategy = strategyFor(annotationType); - this.typeLiteral = MoreTypes.canonicalizeForKey( - (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass())); + this.typeLiteral = + MoreTypes.canonicalizeForKey( + (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass())); this.hashCode = computeHashCode(); - this.toStringSupplier = createToStringSupplier(); } /** * Constructs a new key. Derives the type from this class's type parameter. * - *

    Clients create an empty anonymous subclass. Doing so embeds the type - * parameter in the anonymous class's type hierarchy so we can reconstitute it - * at runtime despite erasure. + *

    Clients create an empty anonymous subclass. Doing so embeds the type parameter in the + * anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure. * - *

    Example usage for a binding of type {@code Foo} annotated with - * {@code @Bar}: + *

    Example usage for a binding of type {@code Foo} annotated with {@code @Bar}: * *

    {@code new Key(new Bar()) {}}. */ @@ -97,18 +91,17 @@ protected Key(Annotation annotation) { // no usages, not test-covered this.annotationStrategy = strategyFor(annotation); - this.typeLiteral = MoreTypes.canonicalizeForKey( - (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass())); + this.typeLiteral = + MoreTypes.canonicalizeForKey( + (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass())); this.hashCode = computeHashCode(); - this.toStringSupplier = createToStringSupplier(); } /** * Constructs a new key. Derives the type from this class's type parameter. * - *

    Clients create an empty anonymous subclass. Doing so embeds the type - * parameter in the anonymous class's type hierarchy so we can reconstitute it - * at runtime despite erasure. + *

    Clients create an empty anonymous subclass. Doing so embeds the type parameter in the + * anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure. * *

    Example usage for a binding of type {@code Foo}: * @@ -117,21 +110,18 @@ @SuppressWarnings("unchecked") protected Key() { this.annotationStrategy = NullAnnotationStrategy.INSTANCE; - this.typeLiteral = MoreTypes.canonicalizeForKey( - (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass())); + this.typeLiteral = + MoreTypes.canonicalizeForKey( + (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass())); this.hashCode = computeHashCode(); - this.toStringSupplier = createToStringSupplier(); } - /** - * Unsafe. Constructs a key from a manually specified type. - */ + /** Unsafe. Constructs a key from a manually specified type. */ @SuppressWarnings("unchecked") private Key(Type type, AnnotationStrategy annotationStrategy) { this.annotationStrategy = annotationStrategy; this.typeLiteral = MoreTypes.canonicalizeForKey((TypeLiteral) TypeLiteral.get(type)); this.hashCode = computeHashCode(); - this.toStringSupplier = createToStringSupplier(); } /** Constructs a key from a manually specified type. */ @@ -139,46 +129,24 @@ this.annotationStrategy = annotationStrategy; this.typeLiteral = MoreTypes.canonicalizeForKey(typeLiteral); this.hashCode = computeHashCode(); - this.toStringSupplier = createToStringSupplier(); } - /** - * Computes the hash code for this key. - */ + /** Computes the hash code for this key. */ private int computeHashCode() { return typeLiteral.hashCode() * 31 + annotationStrategy.hashCode(); } - /** - * @return a {@link Supplier} which memoizes the value for lazy initialization. - */ - private Supplier createToStringSupplier() { - // The performance hit on access is acceptable since the intended use is for non-performance- - // critical applications such as debugging and logging. - return Suppliers.memoize(new Supplier() { - @Override public String get() { - return "Key[type=" + typeLiteral + ", annotation=" + annotationStrategy + "]"; - } - }); - } - - /** - * Gets the key type. - */ + /** Gets the key type. */ public final TypeLiteral getTypeLiteral() { return typeLiteral; } - /** - * Gets the annotation type. - */ + /** Gets the annotation type. */ public final Class getAnnotationType() { return annotationStrategy.getAnnotationType(); } - /** - * Gets the annotation. - */ + /** Gets the annotation. */ public final Annotation getAnnotation() { return annotationStrategy.getAnnotation(); } @@ -201,14 +169,13 @@ return typeLiteral.getRawType(); } - /** - * Gets the key of this key's provider. - */ + /** Gets the key of this key's provider. */ Key> providerKey() { return ofType(typeLiteral.providerType()); } - @Override public final boolean equals(Object o) { + @Override + public final boolean equals(Object o) { if (o == this) { return true; } @@ -220,92 +187,76 @@ && typeLiteral.equals(other.typeLiteral); } - @Override public final int hashCode() { + @Override + public final int hashCode() { return this.hashCode; } - @Override public final String toString() { - return toStringSupplier.get(); + @Override + public final String toString() { + // Note: to not introduce dangerous data races the field should only be read once in this + // method. + String local = toString; + if (local == null) { + local = "Key[type=" + typeLiteral + ", annotation=" + annotationStrategy + "]"; + toString = local; + } + return local; } - /** - * Gets a key for an injection type and an annotation strategy. - */ - static Key get(Class type, - AnnotationStrategy annotationStrategy) { + /** Gets a key for an injection type and an annotation strategy. */ + static Key get(Class type, AnnotationStrategy annotationStrategy) { return new Key(type, annotationStrategy); } - /** - * Gets a key for an injection type. - */ + /** Gets a key for an injection type. */ public static Key get(Class type) { return new Key(type, NullAnnotationStrategy.INSTANCE); } - /** - * Gets a key for an injection type and an annotation type. - */ - public static Key get(Class type, - Class annotationType) { + /** Gets a key for an injection type and an annotation type. */ + public static Key get(Class type, Class annotationType) { return new Key(type, strategyFor(annotationType)); } - /** - * Gets a key for an injection type and an annotation. - */ + /** Gets a key for an injection type and an annotation. */ public static Key get(Class type, Annotation annotation) { return new Key(type, strategyFor(annotation)); } - /** - * Gets a key for an injection type. - */ + /** Gets a key for an injection type. */ public static Key get(Type type) { return new Key(type, NullAnnotationStrategy.INSTANCE); } - /** - * Gets a key for an injection type and an annotation type. - */ - public static Key get(Type type, - Class annotationType) { + /** Gets a key for an injection type and an annotation type. */ + public static Key get(Type type, Class annotationType) { return new Key(type, strategyFor(annotationType)); } - /** - * Gets a key for an injection type and an annotation. - */ + /** Gets a key for an injection type and an annotation. */ public static Key get(Type type, Annotation annotation) { return new Key(type, strategyFor(annotation)); } - /** - * Gets a key for an injection type. - */ + /** Gets a key for an injection type. */ public static Key get(TypeLiteral typeLiteral) { return new Key(typeLiteral, NullAnnotationStrategy.INSTANCE); } - /** - * Gets a key for an injection type and an annotation type. - */ - public static Key get(TypeLiteral typeLiteral, - Class annotationType) { + /** Gets a key for an injection type and an annotation type. */ + public static Key get( + TypeLiteral typeLiteral, Class annotationType) { return new Key(typeLiteral, strategyFor(annotationType)); } - /** - * Gets a key for an injection type and an annotation. - */ - public static Key get(TypeLiteral typeLiteral, - Annotation annotation) { + /** Gets a key for an injection type and an annotation. */ + public static Key get(TypeLiteral typeLiteral, Annotation annotation) { return new Key(typeLiteral, strategyFor(annotation)); } /** - * Returns a new key of the specified type with the same annotation as this - * key. + * Returns a new key of the specified type with the same annotation as this key. * * @since 3.0 */ @@ -314,8 +265,7 @@ } /** - * Returns a new key of the specified type with the same annotation as this - * key. + * Returns a new key of the specified type with the same annotation as this key. * * @since 3.0 */ @@ -324,8 +274,7 @@ } /** - * Returns a new key of the specified type with the same annotation as this - * key. + * Returns a new key of the specified type with the same annotation as this key. * * @since 3.0 */ @@ -343,8 +292,7 @@ } /** - * Returns this key without annotation attributes, i.e. with only the - * annotation type. + * Returns this key without annotation attributes, i.e. with only the annotation type. * * @since 3.0 */ @@ -354,14 +302,15 @@ interface AnnotationStrategy { Annotation getAnnotation(); + Class getAnnotationType(); + boolean hasAttributes(); + AnnotationStrategy withoutAttributes(); } - /** - * Gets the strategy for an annotation. - */ + /** Gets the strategy for an annotation. */ static AnnotationStrategy strategyFor(Annotation annotation) { checkNotNull(annotation, "annotation"); Class annotationType = annotation.annotationType(); @@ -375,9 +324,7 @@ return new AnnotationInstanceStrategy(Annotations.canonicalizeIfNamed(annotation)); } - /** - * Gets the strategy for an annotation type. - */ + /** Gets the strategy for an annotation type. */ static AnnotationStrategy strategyFor(Class annotationType) { annotationType = Annotations.canonicalizeIfNamed(annotationType); if (isAllDefaultMethods(annotationType)) { @@ -388,18 +335,18 @@ ensureRetainedAtRuntime(annotationType); ensureIsBindingAnnotation(annotationType); return new AnnotationTypeStrategy(annotationType, null); - } - private static void ensureRetainedAtRuntime( - Class annotationType) { - checkArgument(Annotations.isRetainedAtRuntime(annotationType), + private static void ensureRetainedAtRuntime(Class annotationType) { + checkArgument( + Annotations.isRetainedAtRuntime(annotationType), "%s is not retained at runtime. Please annotate it with @Retention(RUNTIME).", annotationType.getName()); } private static void ensureIsBindingAnnotation(Class annotationType) { - checkArgument(Annotations.isBindingAnnotation(annotationType), + checkArgument( + Annotations.isBindingAnnotation(annotationType), "%s is not a binding annotation. Please annotate it with @BindingAnnotation.", annotationType.getName()); } @@ -407,23 +354,28 @@ static enum NullAnnotationStrategy implements AnnotationStrategy { INSTANCE; + @Override public boolean hasAttributes() { return false; } + @Override public AnnotationStrategy withoutAttributes() { throw new UnsupportedOperationException("Key already has no attributes."); } + @Override public Annotation getAnnotation() { return null; } + @Override public Class getAnnotationType() { return null; } - @Override public String toString() { + @Override + public String toString() { return "[none]"; } } @@ -437,23 +389,28 @@ this.annotation = checkNotNull(annotation, "annotation"); } + @Override public boolean hasAttributes() { return true; } + @Override public AnnotationStrategy withoutAttributes() { return new AnnotationTypeStrategy(getAnnotationType(), annotation); } + @Override public Annotation getAnnotation() { return annotation; } + @Override public Class getAnnotationType() { return annotation.annotationType(); } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (!(o instanceof AnnotationInstanceStrategy)) { return false; } @@ -462,11 +419,13 @@ return annotation.equals(other.annotation); } - @Override public int hashCode() { + @Override + public int hashCode() { return annotation.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return annotation.toString(); } } @@ -478,29 +437,33 @@ // Keep the instance around if we have it so the client can request it. final Annotation annotation; - AnnotationTypeStrategy(Class annotationType, - Annotation annotation) { + AnnotationTypeStrategy(Class annotationType, Annotation annotation) { this.annotationType = checkNotNull(annotationType, "annotation type"); this.annotation = annotation; } + @Override public boolean hasAttributes() { return false; } + @Override public AnnotationStrategy withoutAttributes() { throw new UnsupportedOperationException("Key already has no attributes."); } + @Override public Annotation getAnnotation() { return annotation; } + @Override public Class getAnnotationType() { return annotationType; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (!(o instanceof AnnotationTypeStrategy)) { return false; } @@ -509,11 +472,13 @@ return annotationType.equals(other.annotationType); } - @Override public int hashCode() { + @Override + public int hashCode() { return annotationType.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "@" + annotationType.getName(); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/matcher/AbstractMatcher.java sisu-guice-4.2.0/core/src/com/google/inject/matcher/AbstractMatcher.java --- sisu-guice-3.2.6/core/src/com/google/inject/matcher/AbstractMatcher.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/matcher/AbstractMatcher.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,10 +25,12 @@ */ public abstract class AbstractMatcher implements Matcher { + @Override public Matcher and(final Matcher other) { return new AndMatcher(this, other); } + @Override public Matcher or(Matcher other) { return new OrMatcher(this, other); } @@ -41,21 +43,25 @@ this.b = b; } + @Override public boolean matches(T t) { return a.matches(t) && b.matches(t); } - @Override public boolean equals(Object other) { + @Override + public boolean equals(Object other) { return other instanceof AndMatcher && ((AndMatcher) other).a.equals(a) && ((AndMatcher) other).b.equals(b); } - @Override public int hashCode() { + @Override + public int hashCode() { return 41 * (a.hashCode() ^ b.hashCode()); } - @Override public String toString() { + @Override + public String toString() { return "and(" + a + ", " + b + ")"; } @@ -70,21 +76,25 @@ this.b = b; } + @Override public boolean matches(T t) { return a.matches(t) || b.matches(t); } - @Override public boolean equals(Object other) { + @Override + public boolean equals(Object other) { return other instanceof OrMatcher && ((OrMatcher) other).a.equals(a) && ((OrMatcher) other).b.equals(b); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * (a.hashCode() ^ b.hashCode()); } - @Override public String toString() { + @Override + public String toString() { return "or(" + a + ", " + b + ")"; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/matcher/Matcher.java sisu-guice-4.2.0/core/src/com/google/inject/matcher/Matcher.java --- sisu-guice-3.2.6/core/src/com/google/inject/matcher/Matcher.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/matcher/Matcher.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,20 +23,18 @@ */ public interface Matcher { - /** - * Returns {@code true} if this matches {@code t}, {@code false} otherwise. - */ + /** Returns {@code true} if this matches {@code t}, {@code false} otherwise. */ boolean matches(T t); /** - * Returns a new matcher which returns {@code true} if both this and the - * given matcher return {@code true}. + * Returns a new matcher which returns {@code true} if both this and the given matcher return + * {@code true}. */ Matcher and(Matcher other); /** - * Returns a new matcher which returns {@code true} if either this or the - * given matcher return {@code true}. + * Returns a new matcher which returns {@code true} if either this or the given matcher return + * {@code true}. */ Matcher or(Matcher other); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/matcher/Matchers.java sisu-guice-4.2.0/core/src/com/google/inject/matcher/Matchers.java --- sisu-guice-3.2.6/core/src/com/google/inject/matcher/Matchers.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/matcher/Matchers.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,9 +34,7 @@ public class Matchers { private Matchers() {} - /** - * Returns a matcher which matches any input. - */ + /** Returns a matcher which matches any input. */ public static Matcher any() { return ANY; } @@ -44,11 +42,13 @@ private static final Matcher ANY = new Any(); private static class Any extends AbstractMatcher implements Serializable { + @Override public boolean matches(Object o) { return true; } - @Override public String toString() { + @Override + public String toString() { return "any()"; } @@ -59,9 +59,7 @@ private static final long serialVersionUID = 0; } - /** - * Inverts the given matcher. - */ + /** Inverts the given matcher. */ public static Matcher not(final Matcher p) { return new Not(p); } @@ -73,37 +71,38 @@ this.delegate = checkNotNull(delegate, "delegate"); } + @Override public boolean matches(T t) { return !delegate.matches(t); } - @Override public boolean equals(Object other) { - return other instanceof Not - && ((Not) other).delegate.equals(delegate); + @Override + public boolean equals(Object other) { + return other instanceof Not && ((Not) other).delegate.equals(delegate); } - @Override public int hashCode() { + @Override + public int hashCode() { return -delegate.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "not(" + delegate + ")"; } private static final long serialVersionUID = 0; } - private static void checkForRuntimeRetention( - Class annotationType) { + private static void checkForRuntimeRetention(Class annotationType) { Retention retention = annotationType.getAnnotation(Retention.class); - checkArgument(retention != null && retention.value() == RetentionPolicy.RUNTIME, - "Annotation %s is missing RUNTIME retention", annotationType.getSimpleName()); + checkArgument( + retention != null && retention.value() == RetentionPolicy.RUNTIME, + "Annotation %s is missing RUNTIME retention", + annotationType.getSimpleName()); } - /** - * Returns a matcher which matches elements (methods, classes, etc.) - * with a given annotation. - */ + /** Returns a matcher which matches elements (methods, classes, etc.) with a given annotation. */ public static Matcher annotatedWith( final Class annotationType) { return new AnnotatedWithType(annotationType); @@ -118,32 +117,32 @@ checkForRuntimeRetention(annotationType); } + @Override public boolean matches(AnnotatedElement element) { return element.isAnnotationPresent(annotationType); } - @Override public boolean equals(Object other) { + @Override + public boolean equals(Object other) { return other instanceof AnnotatedWithType && ((AnnotatedWithType) other).annotationType.equals(annotationType); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * annotationType.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "annotatedWith(" + annotationType.getSimpleName() + ".class)"; } private static final long serialVersionUID = 0; } - /** - * Returns a matcher which matches elements (methods, classes, etc.) - * with a given annotation. - */ - public static Matcher annotatedWith( - final Annotation annotation) { + /** Returns a matcher which matches elements (methods, classes, etc.) with a given annotation. */ + public static Matcher annotatedWith(final Annotation annotation) { return new AnnotatedWith(annotation); } @@ -156,127 +155,130 @@ checkForRuntimeRetention(annotation.annotationType()); } + @Override public boolean matches(AnnotatedElement element) { Annotation fromElement = element.getAnnotation(annotation.annotationType()); return fromElement != null && annotation.equals(fromElement); } - @Override public boolean equals(Object other) { + @Override + public boolean equals(Object other) { return other instanceof AnnotatedWith && ((AnnotatedWith) other).annotation.equals(annotation); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * annotation.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "annotatedWith(" + annotation + ")"; } private static final long serialVersionUID = 0; } - /** - * Returns a matcher which matches subclasses of the given type (as well as - * the given type). - */ + /** Returns a matcher which matches subclasses of the given type (as well as the given type). */ public static Matcher subclassesOf(final Class superclass) { return new SubclassesOf(superclass); } - private static class SubclassesOf extends AbstractMatcher - implements Serializable { + private static class SubclassesOf extends AbstractMatcher implements Serializable { private final Class superclass; public SubclassesOf(Class superclass) { this.superclass = checkNotNull(superclass, "superclass"); } + @Override public boolean matches(Class subclass) { return superclass.isAssignableFrom(subclass); } - @Override public boolean equals(Object other) { - return other instanceof SubclassesOf - && ((SubclassesOf) other).superclass.equals(superclass); + @Override + public boolean equals(Object other) { + return other instanceof SubclassesOf && ((SubclassesOf) other).superclass.equals(superclass); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * superclass.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "subclassesOf(" + superclass.getSimpleName() + ".class)"; } private static final long serialVersionUID = 0; } - /** - * Returns a matcher which matches objects equal to the given object. - */ + /** Returns a matcher which matches objects equal to the given object. */ public static Matcher only(Object value) { return new Only(value); } - private static class Only extends AbstractMatcher - implements Serializable { + private static class Only extends AbstractMatcher implements Serializable { private final Object value; public Only(Object value) { this.value = checkNotNull(value, "value"); } + @Override public boolean matches(Object other) { return value.equals(other); } - @Override public boolean equals(Object other) { - return other instanceof Only - && ((Only) other).value.equals(value); + @Override + public boolean equals(Object other) { + return other instanceof Only && ((Only) other).value.equals(value); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * value.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "only(" + value + ")"; } private static final long serialVersionUID = 0; } - /** - * Returns a matcher which matches only the given object. - */ + /** Returns a matcher which matches only the given object. */ public static Matcher identicalTo(final Object value) { return new IdenticalTo(value); } - private static class IdenticalTo extends AbstractMatcher - implements Serializable { + private static class IdenticalTo extends AbstractMatcher implements Serializable { private final Object value; public IdenticalTo(Object value) { this.value = checkNotNull(value, "value"); } + @Override public boolean matches(Object other) { return value == other; } - @Override public boolean equals(Object other) { - return other instanceof IdenticalTo - && ((IdenticalTo) other).value == value; + @Override + public boolean equals(Object other) { + return other instanceof IdenticalTo && ((IdenticalTo) other).value == value; } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * System.identityHashCode(value); } - @Override public String toString() { + @Override + public String toString() { return "identicalTo(" + value + ")"; } @@ -300,20 +302,23 @@ this.packageName = targetPackage.getName(); } + @Override public boolean matches(Class c) { return c.getPackage().equals(targetPackage); } - @Override public boolean equals(Object other) { - return other instanceof InPackage - && ((InPackage) other).targetPackage.equals(targetPackage); + @Override + public boolean equals(Object other) { + return other instanceof InPackage && ((InPackage) other).targetPackage.equals(targetPackage); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * targetPackage.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "inPackage(" + targetPackage.getName() + ")"; } @@ -325,9 +330,9 @@ } /** - * Returns a matcher which matches classes in the given package and its subpackages. Unlike - * {@link #inPackage(Package) inPackage()}, this matches classes from any classloader. - * + * Returns a matcher which matches classes in the given package and its subpackages. Unlike {@link + * #inPackage(Package) inPackage()}, this matches classes from any classloader. + * * @since 2.0 */ public static Matcher inSubpackage(final String targetPackageName) { @@ -341,33 +346,34 @@ this.targetPackageName = targetPackageName; } + @Override public boolean matches(Class c) { String classPackageName = c.getPackage().getName(); return classPackageName.equals(targetPackageName) || classPackageName.startsWith(targetPackageName + "."); } - @Override public boolean equals(Object other) { + @Override + public boolean equals(Object other) { return other instanceof InSubpackage && ((InSubpackage) other).targetPackageName.equals(targetPackageName); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * targetPackageName.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "inSubpackage(" + targetPackageName + ")"; } private static final long serialVersionUID = 0; } - /** - * Returns a matcher which matches methods with matching return types. - */ - public static Matcher returns( - final Matcher> returnType) { + /** Returns a matcher which matches methods with matching return types. */ + public static Matcher returns(final Matcher> returnType) { return new Returns(returnType); } @@ -378,20 +384,23 @@ this.returnType = checkNotNull(returnType, "return type matcher"); } + @Override public boolean matches(Method m) { return returnType.matches(m.getReturnType()); } - @Override public boolean equals(Object other) { - return other instanceof Returns - && ((Returns) other).returnType.equals(returnType); + @Override + public boolean equals(Object other) { + return other instanceof Returns && ((Returns) other).returnType.equals(returnType); } - @Override public int hashCode() { + @Override + public int hashCode() { return 37 * returnType.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return "returns(" + returnType + ")"; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/matcher/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/matcher/package-info.java --- sisu-guice-3.2.6/core/src/com/google/inject/matcher/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/matcher/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,8 +14,5 @@ * limitations under the License. */ -/** - * Used for matching things. Primarily used to pick out methods to which to - * apply interceptors. - */ -package com.google.inject.matcher; \ No newline at end of file +/** Used for matching things. Primarily used to pick out methods to which to apply interceptors. */ +package com.google.inject.matcher; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/MembersInjector.java sisu-guice-4.2.0/core/src/com/google/inject/MembersInjector.java --- sisu-guice-3.2.6/core/src/com/google/inject/MembersInjector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/MembersInjector.java 2018-04-03 18:18:08.000000000 +0000 @@ -21,7 +21,6 @@ * presence or absence of an injectable constructor. * * @param type to inject members of - * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Module.java sisu-guice-4.2.0/core/src/com/google/inject/Module.java --- sisu-guice-3.2.6/core/src/com/google/inject/Module.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Module.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,18 +17,16 @@ package com.google.inject; /** - * A module contributes configuration information, typically interface - * bindings, which will be used to create an {@link Injector}. A Guice-based - * application is ultimately composed of little more than a set of - * {@code Module}s and some bootstrapping code. + * A module contributes configuration information, typically interface bindings, which will be used + * to create an {@link Injector}. A Guice-based application is ultimately composed of little more + * than a set of {@code Module}s and some bootstrapping code. * - *

    Your Module classes can use a more streamlined syntax by extending - * {@link AbstractModule} rather than implementing this interface directly. + *

    Your Module classes can use a more streamlined syntax by extending {@link AbstractModule} + * rather than implementing this interface directly. * - *

    In addition to the bindings configured via {@link #configure}, bindings - * will be created for all methods annotated with {@literal @}{@link Provides}. - * Use scope and binding annotations on these methods to configure the - * bindings. + *

    In addition to the bindings configured via {@link #configure}, bindings will be created for + * all methods annotated with {@literal @}{@link Provides}. Use scope and binding annotations on + * these methods to configure the bindings. */ public interface Module { diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ClassMapKey.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ClassMapKey.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ClassMapKey.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ClassMapKey.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Allows {@literal @}{@link ProvidesIntoMap} to specify a class map key. + * + * @since 4.0 + */ +@MapKey(unwrapValue = true) +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface ClassMapKey { + Class value(); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MapBinderBinding.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MapBinderBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MapBinderBinding.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MapBinderBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import com.google.inject.Binding; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import com.google.inject.spi.Element; +import com.google.inject.spi.Elements; +import java.util.List; +import java.util.Map; + +/** + * A binding for a MapBinder. + * + *

    Although MapBinders may be injected through a variety of generic types (Map<K, V>, Map + * <K, Provider<V>>, Map<K, Set<V>>, Map>, and even + * Set<Map.Entry<K, Provider<V>>), a MapBinderBinding exists only on the Binding associated + * with the Map<K, V> key. Other bindings can be validated to be derived from this + * MapBinderBinding using {@link #containsElement(Element)}. + * + * @param The fully qualified type of the map, including Map. For example: + * MapBinderBinding<Map<String, Snack>> + * @since 3.0 + * @author sameb@google.com (Sam Berlin) + */ +public interface MapBinderBinding { + + /** Returns the {@link Key} for the map. */ + Key getMapKey(); + + /** + * Returns the TypeLiteral describing the keys of the map. + * + *

    The TypeLiteral will always match the type Map's generic type. For example, if getMapKey + * returns a key of Map<String, Snack>, then this will always return a + * TypeLiteral<String>. + */ + TypeLiteral getKeyTypeLiteral(); + + /** + * Returns the TypeLiteral describing the values of the map. + * + *

    The TypeLiteral will always match the type Map's generic type. For example, if getMapKey + * returns a key of Map<String, Snack>, then this will always return a + * TypeLiteral<Snack>. + */ + TypeLiteral getValueTypeLiteral(); + + /** + * Returns all entries in the Map. The returned list of Map.Entries contains the key and a binding + * to the value. Duplicate keys or values will exist as separate Map.Entries in the returned list. + * This is only supported on bindings returned from an injector. This will throw {@link + * UnsupportedOperationException} if it is called on an element retrieved from {@link + * Elements#getElements}. + * + *

    The elements will always match the type Map's generic type. For example, if getMapKey + * returns a key of Map<String, Snack>, then this will always return a list of + * type List<Map.Entry<String, Binding<Snack>>>. + */ + List>> getEntries(); + + /** + * Similar to {@link #getEntries()}, but can be used on a MapBinderBinding retrieved from {@link + * Elements#getElements}. + * + *

    One way to use this is to pass in the results of {@link Elements#getElements} as the {@code + * elements} parameter. + * + *

    This differs from {@link #getEntries()} in that it will return duplicates if they are + * present in the {@code elements} passed in. This does not run the normal Guice de-duplication + * that {@link #getEntries()} does. + * + * @throws IllegalArgumentException if the provided elements contain partial map entries. If the + * elements come from {@link Elements#getElements} on a module with a MapBinder, there will be + * a 1:1 relationship and no exception will be thrown. + * @since 4.2 + */ + List>> getEntries(Iterable elements); + + /** + * Returns true if the MapBinder permits duplicates. This is only supported on bindings returned + * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a + * MapBinderBinding retrieved from {@link Elements#getElements}. + */ + boolean permitsDuplicates(); + + /** + * Returns true if this MapBinder contains the given Element in order to build the map or uses the + * given Element in order to support building and injecting the map. This will work for + * MapBinderBindings retrieved from an injector and {@link Elements#getElements}. Usually this is + * only necessary if you are working with elements retrieved from modules (without an Injector), + * otherwise {@link #getEntries} and {@link #permitsDuplicates} are better options. + * + *

    If you need to introspect the details of the map, such as the keys, values or if it permits + * duplicates, it is necessary to pass the elements through an Injector and use {@link + * #getEntries()} and {@link #permitsDuplicates()}. + */ + boolean containsElement(Element element); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MapBinder.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MapBinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MapBinder.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MapBinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static com.google.inject.internal.RealMapBinder.newMapRealBinder; +import static com.google.inject.internal.RealMapBinder.newRealMapBinder; + +import com.google.inject.Binder; +import com.google.inject.TypeLiteral; +import com.google.inject.binder.LinkedBindingBuilder; +import com.google.inject.internal.RealMapBinder; +import java.lang.annotation.Annotation; +import java.util.Map; + +/** + * An API to bind multiple map entries separately, only to later inject them as a complete map. + * MapBinder is intended for use in your application's module: + * + *

    
    + * public class SnacksModule extends AbstractModule {
    + *   protected void configure() {
    + *     MapBinder<String, Snack> mapbinder
    + *         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
    + *     mapbinder.addBinding("twix").toInstance(new Twix());
    + *     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
    + *     mapbinder.addBinding("skittles").to(Skittles.class);
    + *   }
    + * }
    + * + *

    With this binding, a {@link Map}{@code } can now be injected: + * + *

    
    + * class SnackMachine {
    + *   {@literal @}Inject
    + *   public SnackMachine(Map<String, Snack> snacks) { ... }
    + * }
    + * + *

    In addition to binding {@code Map}, a mapbinder will also bind {@code Map>} for lazy value provision: + * + *

    
    + * class SnackMachine {
    + *   {@literal @}Inject
    + *   public SnackMachine(Map<String, Provider<Snack>> snackProviders) { ... }
    + * }
    + * + *

    Contributing mapbindings from different modules is supported. For example, it is okay to have + * both {@code CandyModule} and {@code ChipsModule} both create their own {@code MapBinder}, and to each contribute bindings to the snacks map. When that map is injected, it will + * contain entries from both modules. + * + *

    The map's iteration order is consistent with the binding order. This is convenient when + * multiple elements are contributed by the same module because that module can order its bindings + * appropriately. Avoid relying on the iteration order of elements contributed by different modules, + * since there is no equivalent mechanism to order modules. + * + *

    The map is unmodifiable. Elements can only be added to the map by configuring the MapBinder. + * Elements can never be removed from the map. + * + *

    Values are resolved at map injection time. If a value is bound to a provider, that provider's + * get method will be called each time the map is injected (unless the binding is also scoped, or a + * map of providers is injected). + * + *

    Annotations are used to create different maps of the same key/value type. Each distinct + * annotation gets its own independent map. + * + *

    Keys must be distinct. If the same key is bound more than once, map injection + * will fail. However, use {@link #permitDuplicates()} in order to allow duplicate keys; extra + * bindings to {@code Map>} and {@code Map>} will be added. + * + *

    Keys must be non-null. {@code addBinding(null)} will throw an unchecked + * exception. + * + *

    Values must be non-null to use map injection. If any value is null, map + * injection will fail (although injecting a map of providers will not). + * + * @author dpb@google.com (David P. Baker) + */ +public class MapBinder { + // This class is non-final due to users mocking this in tests :( + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with no binding annotation. + */ + public static MapBinder newMapBinder( + Binder binder, TypeLiteral keyType, TypeLiteral valueType) { + return new MapBinder( + newMapRealBinder(binder.skipSources(MapBinder.class), keyType, valueType)); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with no binding annotation. + */ + public static MapBinder newMapBinder( + Binder binder, Class keyType, Class valueType) { + return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType)); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with {@code annotation}. + */ + public static MapBinder newMapBinder( + Binder binder, TypeLiteral keyType, TypeLiteral valueType, Annotation annotation) { + return new MapBinder( + newRealMapBinder(binder.skipSources(MapBinder.class), keyType, valueType, annotation)); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with {@code annotation}. + */ + public static MapBinder newMapBinder( + Binder binder, Class keyType, Class valueType, Annotation annotation) { + return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotation); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with {@code annotationType}. + */ + public static MapBinder newMapBinder( + Binder binder, + TypeLiteral keyType, + TypeLiteral valueType, + Class annotationType) { + return new MapBinder( + newRealMapBinder(binder.skipSources(MapBinder.class), keyType, valueType, annotationType)); + } + + /** + * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link + * Map} that is itself bound with {@code annotationType}. + */ + public static MapBinder newMapBinder( + Binder binder, + Class keyType, + Class valueType, + Class annotationType) { + return newMapBinder( + binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotationType); + } + + private final RealMapBinder delegate; + + private MapBinder(RealMapBinder delegate) { + this.delegate = delegate; + } + + /** + * Configures the {@code MapBinder} to handle duplicate entries. + * + *

    When multiple equal keys are bound, the value that gets included in the map is arbitrary. + * + *

    In addition to the {@code Map} and {@code Map>} maps that are normally + * bound, a {@code Map>} and {@code Map>>} are also bound, + * which contain all values bound to each key. + * + *

    When multiple modules contribute elements to the map, this configuration option impacts all + * of them. + * + * @return this map binder + * @since 3.0 + */ + public MapBinder permitDuplicates() { + delegate.permitDuplicates(); + return this; + } + + /** + * Returns a binding builder used to add a new entry in the map. Each key must be distinct (and + * non-null). Bound providers will be evaluated each time the map is injected. + * + *

    It is an error to call this method without also calling one of the {@code to} methods on the + * returned binding builder. + * + *

    Scoping elements independently is supported. Use the {@code in} method to specify a binding + * scope. + */ + public LinkedBindingBuilder addBinding(K key) { + return delegate.addBinding(key); + } + + // Some tests rely on MapBinder implementing equals/hashCode + + @Override + public boolean equals(Object obj) { + if (obj instanceof MapBinder) { + return delegate.equals(((MapBinder) obj).delegate); + } + return false; + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MapKey.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MapKey.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MapKey.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MapKey.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Allows users define customized key type annotations for map bindings by annotating an annotation + * of a {@code Map}'s key type. The custom key annotation can be applied to methods also annotated + * with {@literal @}{@link ProvidesIntoMap}. + * + *

    A {@link StringMapKey} and {@link ClassMapKey} are provided for convenience with maps whose + * keys are strings or classes. For maps with enums or primitive types as keys, you must provide + * your own MapKey annotation, such as this one for an enum: + * + *

    + * {@literal @}MapKey(unwrapValue = true)
    + * {@literal @}Retention(RUNTIME)
    + * public {@literal @}interface MyCustomEnumKey {
    + *   MyCustomEnum value();
    + * }
    + * 
    + * + * You can also use the whole annotation as the key, if {@code unwrapValue=false}. When unwrapValue + * is false, the annotation type will be the key type for the injected map and the annotation + * instances will be the key values. If {@code unwrapValue=true}, the value() type will be the key + * type for injected map and the value() instances will be the keys values. + * + * @since 4.0 + */ +@Documented +@Target(ANNOTATION_TYPE) +@Retention(RUNTIME) +public @interface MapKey { + /** + * if {@code unwrapValue} is false, then the whole annotation will be the type and annotation + * instances will be the keys. If {@code unwrapValue} is true, the value() type of key type + * annotation will be the key type for injected map and the value instances will be the keys. + */ + boolean unwrapValue() default true; +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MultibinderBinding.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MultibinderBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MultibinderBinding.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MultibinderBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import com.google.inject.Binding; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import com.google.inject.spi.Element; +import com.google.inject.spi.Elements; +import java.util.List; + +/** + * A binding for a Multibinder. + * + * @param The fully qualified type of the set, including Set. For example: + * MultibinderBinding<Set<Boolean>> + * @since 3.0 + * @author sameb@google.com (Sam Berlin) + */ +public interface MultibinderBinding { + + /** Returns the key for the set. */ + Key getSetKey(); + + /** + * Returns the TypeLiteral that describes the type of elements in the set. + * + *

    The elements will always match the type Set's generic type. For example, if getSetKey + * returns a key of Set<String>, then this will always return a + * TypeLiteral<String>. + */ + TypeLiteral getElementTypeLiteral(); + + /** + * Returns all bindings that make up the set. This is only supported on bindings returned from an + * injector. This will throw {@link UnsupportedOperationException} if it is called on an element + * retrieved from {@link Elements#getElements}. + * + *

    The elements will always match the type Set's generic type. For example, if getSetKey + * returns a key of Set<String>, then this will always return a list of type + * List<Binding<String>>. + */ + List> getElements(); + + /** + * Returns true if the multibinder permits duplicates. This is only supported on bindings returned + * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a + * MultibinderBinding retrieved from {@link Elements#getElements}. + */ + boolean permitsDuplicates(); + + /** + * Returns true if this Multibinder uses the given Element. This will be true for bindings that + * derive the elements of the set and other bindings that Multibinder uses internally. This will + * work for MultibinderBindings retrieved from an injector and {@link Elements#getElements}. + * Usually this is only necessary if you are working with elements retrieved from modules (without + * an Injector), otherwise {@link #getElements} and {@link #permitsDuplicates} are better options. + * + *

    If you need to introspect the details of the set, such as the values or if it permits + * duplicates, it is necessary to pass the elements through an Injector and use {@link + * #getElements()} and {@link #permitsDuplicates()}. + */ + boolean containsElement(Element element); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/Multibinder.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/Multibinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/Multibinder.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/Multibinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static com.google.inject.internal.RealMultibinder.newRealSetBinder; + +import com.google.inject.Binder; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import com.google.inject.binder.LinkedBindingBuilder; +import com.google.inject.internal.RealMultibinder; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.Set; + +/** + * An API to bind multiple values separately, only to later inject them as a complete collection. + * Multibinder is intended for use in your application's module: + * + *

    
    + * public class SnacksModule extends AbstractModule {
    + *   protected void configure() {
    + *     Multibinder<Snack> multibinder
    + *         = Multibinder.newSetBinder(binder(), Snack.class);
    + *     multibinder.addBinding().toInstance(new Twix());
    + *     multibinder.addBinding().toProvider(SnickersProvider.class);
    + *     multibinder.addBinding().to(Skittles.class);
    + *   }
    + * }
    + * + *

    With this binding, a {@link Set}{@code } can now be injected: + * + *

    
    + * class SnackMachine {
    + *   {@literal @}Inject
    + *   public SnackMachine(Set<Snack> snacks) { ... }
    + * }
    + * + * If desired, {@link Collection}{@code >} can also be injected. + * + *

    Contributing multibindings from different modules is supported. For example, it is okay for + * both {@code CandyModule} and {@code ChipsModule} to create their own {@code Multibinder}, + * and to each contribute bindings to the set of snacks. When that set is injected, it will contain + * elements from both modules. + * + *

    The set's iteration order is consistent with the binding order. This is convenient when + * multiple elements are contributed by the same module because that module can order its bindings + * appropriately. Avoid relying on the iteration order of elements contributed by different modules, + * since there is no equivalent mechanism to order modules. + * + *

    The set is unmodifiable. Elements can only be added to the set by configuring the multibinder. + * Elements can never be removed from the set. + * + *

    Elements are resolved at set injection time. If an element is bound to a provider, that + * provider's get method will be called each time the set is injected (unless the binding is also + * scoped). + * + *

    Annotations are be used to create different sets of the same element type. Each distinct + * annotation gets its own independent collection of elements. + * + *

    Elements must be distinct. If multiple bound elements have the same value, + * set injection will fail. + * + *

    Elements must be non-null. If any set element is null, set injection will + * fail. + * + * @author jessewilson@google.com (Jesse Wilson) + */ +public class Multibinder { + // This class is non-final due to users mocking this in tests :( + + /** + * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is + * itself bound with no binding annotation. + */ + public static Multibinder newSetBinder(Binder binder, TypeLiteral type) { + return newSetBinder(binder, Key.get(type)); + } + + /** + * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is + * itself bound with no binding annotation. + */ + public static Multibinder newSetBinder(Binder binder, Class type) { + return newSetBinder(binder, Key.get(type)); + } + + /** + * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is + * itself bound with {@code annotation}. + */ + public static Multibinder newSetBinder( + Binder binder, TypeLiteral type, Annotation annotation) { + return newSetBinder(binder, Key.get(type, annotation)); + } + + /** + * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is + * itself bound with {@code annotation}. + */ + public static Multibinder newSetBinder( + Binder binder, Class type, Annotation annotation) { + return newSetBinder(binder, Key.get(type, annotation)); + } + + /** + * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is + * itself bound with {@code annotationType}. + */ + public static Multibinder newSetBinder( + Binder binder, TypeLiteral type, Class annotationType) { + return newSetBinder(binder, Key.get(type, annotationType)); + } + + /** + * Returns a new multibinder that collects instances of the key's type in a {@link Set} that is + * itself bound with the annotation (if any) of the key. + * + * @since 4.0 + */ + public static Multibinder newSetBinder(Binder binder, Key key) { + return new Multibinder(newRealSetBinder(binder.skipSources(Multibinder.class), key)); + } + + /** + * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is + * itself bound with {@code annotationType}. + */ + public static Multibinder newSetBinder( + Binder binder, Class type, Class annotationType) { + return newSetBinder(binder, Key.get(type, annotationType)); + } + + private final RealMultibinder delegate; + + private Multibinder(RealMultibinder delegate) { + this.delegate = delegate; + } + + /** + * Configures the bound set to silently discard duplicate elements. When multiple equal values are + * bound, the one that gets included is arbitrary. When multiple modules contribute elements to + * the set, this configuration option impacts all of them. + * + * @return this multibinder + * @since 3.0 + */ + public Multibinder permitDuplicates() { + delegate.permitDuplicates(); + return this; + } + + /** + * Returns a binding builder used to add a new element in the set. Each bound element must have a + * distinct value. Bound providers will be evaluated each time the set is injected. + * + *

    It is an error to call this method without also calling one of the {@code to} methods on the + * returned binding builder. + * + *

    Scoping elements independently is supported. Use the {@code in} method to specify a binding + * scope. + */ + public LinkedBindingBuilder addBinding() { + return delegate.addBinding(); + } + + // Some tests rely on Multibinder implementing equals/hashCode + + @Override + public boolean equals(Object obj) { + if (obj instanceof Multibinder) { + return delegate.equals(((Multibinder) obj).delegate); + } + return false; + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MultibindingsScanner.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MultibindingsScanner.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MultibindingsScanner.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MultibindingsScanner.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Binder; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.ModuleAnnotatedMethodScanner; +import com.google.inject.util.Modules; +import java.lang.annotation.Annotation; +import java.util.Set; + +/** + * Scans a module for annotations that signal multibindings, mapbindings, and optional bindings. + * + * @since 4.0 + * @deprecated This functionality is installed by default. All references to this can be safely + * removed. This class will be removed in Guice 4.4 + */ +@Deprecated +public class MultibindingsScanner { + private MultibindingsScanner() {} + + /** + * Returns a module that, when installed, will scan all modules for methods with the annotations + * {@literal @}{@link ProvidesIntoMap}, {@literal @}{@link ProvidesIntoSet}, and + * {@literal @}{@link ProvidesIntoOptional}. + * + *

    This is a convenience method, equivalent to doing {@code + * binder().scanModulesForAnnotatedMethods(MultibindingsScanner.scanner())}. + * + * @deprecated This functionality is now installed by default. All references/installations can be + * eliminated. + */ + @Deprecated + public static Module asModule() { + return Modules.EMPTY_MODULE; + } + + /** + * @deprecated This method returns an empty scanner since the preexisting functionality is + * installed by default. + */ + @Deprecated + public static ModuleAnnotatedMethodScanner scanner() { + return new ModuleAnnotatedMethodScanner() { + @Override + public Set> annotationClasses() { + return ImmutableSet.of(); + } + + @Override + public Key prepareMethod( + Binder binder, Annotation annotation, Key key, InjectionPoint injectionPoint) { + throw new IllegalStateException("Unexpected annotation: " + annotation); + } + }; + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import com.google.inject.spi.BindingTargetVisitor; + +/** + * A visitor for the multibinder extension. + * + *

    If your {@link BindingTargetVisitor} implements this interface, bindings created by using + * {@link Multibinder}, {@link MapBinder} or {@link OptionalBinderBinding} will be visited through + * this interface. + * + * @since 3.0 + * @author sameb@google.com (Sam Berlin) + */ +public interface MultibindingsTargetVisitor extends BindingTargetVisitor { + + /** Visits a binding created through {@link Multibinder}. */ + V visit(MultibinderBinding multibinding); + + /** Visits a binding created through {@link MapBinder}. */ + V visit(MapBinderBinding mapbinding); + + /** + * Visits a binding created through {@link OptionalBinder}. + * + * @since 4.0 + */ + V visit(OptionalBinderBinding optionalbinding); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/OptionalBinderBinding.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/OptionalBinderBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/OptionalBinderBinding.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/OptionalBinderBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import com.google.inject.Binding; +import com.google.inject.Key; +import com.google.inject.spi.Element; +import com.google.inject.spi.Elements; + +/** + * A binding for a OptionalBinder. + * + *

    Although OptionalBinders may be injected through a variety of types {@code T}, {@code + * Optional}, {@code Optional>}, etc..), an OptionalBinderBinding exists only on the + * Binding associated with the {@code Optional} key. Other bindings can be validated to be + * derived from this OptionalBinderBinding using {@link #containsElement}. + * + * @param The fully qualified type of the optional binding, including Optional. For example: + * {@code Optional}. + * @since 4.0 + * @author sameb@google.com (Sam Berlin) + */ +public interface OptionalBinderBinding { + + /** Returns the {@link Key} for this binding. */ + Key getKey(); + + /** + * Returns the default binding (set by {@link OptionalBinder#setDefault}) if one exists or null if + * no default binding is set. This will throw {@link UnsupportedOperationException} if it is + * called on an element retrieved from {@link Elements#getElements}. + * + *

    The Binding's type will always match the type Optional's generic type. For example, if + * getKey returns a key of Optional<String>, then this will always return a + * Binding<String>. + */ + Binding getDefaultBinding(); + + /** + * Returns the actual binding (set by {@link OptionalBinder#setBinding}) or null if not set. This + * will throw {@link UnsupportedOperationException} if it is called on an element retrieved from + * {@link Elements#getElements}. + * + *

    The Binding's type will always match the type Optional's generic type. For example, if + * getKey returns a key of Optional<String>, then this will always return a + * Binding<String>. + */ + Binding getActualBinding(); + + /** + * Returns true if this OptionalBinder contains the given Element in order to build the optional + * binding or uses the given Element in order to support building and injecting its data. This + * will work for OptionalBinderBinding retrieved from an injector and {@link + * Elements#getElements}. Usually this is only necessary if you are working with elements + * retrieved from modules (without an Injector), otherwise {@link #getDefaultBinding} and {@link + * #getActualBinding} are better options. + */ + boolean containsElement(Element element); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/OptionalBinder.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/OptionalBinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/OptionalBinder.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/OptionalBinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static com.google.inject.internal.RealOptionalBinder.newRealOptionalBinder; + +import com.google.common.base.Optional; +import com.google.inject.Binder; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import com.google.inject.binder.LinkedBindingBuilder; +import com.google.inject.internal.RealOptionalBinder; + +/** + * An API to bind optional values, optionally with a default value. OptionalBinder fulfills two + * roles: + * + *

      + *
    1. It allows a framework to define an injection point that may or may not be bound by users. + *
    2. It allows a framework to supply a default value that can be changed by users. + *
    + * + *

    When an OptionalBinder is added, it will always supply the bindings: {@code Optional} and + * {@code Optional>}. If {@link #setBinding} or {@link #setDefault} are called, it will + * also bind {@code T}. + * + *

    {@code setDefault} is intended for use by frameworks that need a default value. User code can + * call {@code setBinding} to override the default. Warning: Even if setBinding is called, the + * default binding will still exist in the object graph. If it is a singleton, it will be + * instantiated in {@code Stage.PRODUCTION}. + * + *

    If setDefault or setBinding are linked to Providers, the Provider may return {@code null}. If + * it does, the Optional bindings will be absent. Binding setBinding to a Provider that returns null + * will not cause OptionalBinder to fall back to the setDefault binding. + * + *

    If neither setDefault nor setBinding are called, it will try to link to a user-supplied + * binding of the same type. If no binding exists, the optionals will be absent. Otherwise, if a + * user-supplied binding of that type exists, or if setBinding or setDefault are called, the + * optionals will return present if they are bound to a non-null value. + * + *

    Values are resolved at injection time. If a value is bound to a provider, that provider's get + * method will be called each time the optional is injected (unless the binding is also scoped, or + * an optional of provider is injected). + * + *

    Annotations are used to create different optionals of the same key/value type. Each distinct + * annotation gets its own independent binding. + * + *

    
    + * public class FrameworkModule extends AbstractModule {
    + *   protected void configure() {
    + *     OptionalBinder.newOptionalBinder(binder(), Renamer.class);
    + *   }
    + * }
    + * + *

    With this module, an {@link Optional}{@code } can now be injected. With no other + * bindings, the optional will be absent. Users can specify bindings in one of two ways: + * + *

    Option 1: + * + *

    
    + * public class UserRenamerModule extends AbstractModule {
    + *   protected void configure() {
    + *     bind(Renamer.class).to(ReplacingRenamer.class);
    + *   }
    + * }
    + * + *

    or Option 2: + * + *

    
    + * public class UserRenamerModule extends AbstractModule {
    + *   protected void configure() {
    + *     OptionalBinder.newOptionalBinder(binder(), Renamer.class)
    + *         .setBinding().to(ReplacingRenamer.class);
    + *   }
    + * }
    + * + * With both options, the {@code Optional} will be present and supply the ReplacingRenamer. + * + *

    Default values can be supplied using: + * + *

    
    + * public class FrameworkModule extends AbstractModule {
    + *   protected void configure() {
    + *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
    + *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
    + *   }
    + * }
    + * + * With the above module, code can inject an {@code @LookupUrl String} and it will supply the + * DEFAULT_LOOKUP_URL. A user can change this value by binding + * + *
    
    + * public class UserLookupModule extends AbstractModule {
    + *   protected void configure() {
    + *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
    + *         .setBinding().toInstance(CUSTOM_LOOKUP_URL);
    + *   }
    + * }
    + * + * ... which will override the default value. + * + *

    If one module uses setDefault the only way to override the default is to use setBinding. It is + * an error for a user to specify the binding without using OptionalBinder if setDefault or + * setBinding are called. For example, + * + *

    
    + * public class FrameworkModule extends AbstractModule {
    + *   protected void configure() {
    + *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
    + *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
    + *   }
    + * }
    + * public class UserLookupModule extends AbstractModule {
    + *   protected void configure() {
    + *     bind(Key.get(String.class, LookupUrl.class)).toInstance(CUSTOM_LOOKUP_URL);
    + *   }
    + * }
    + * + * ... would generate an error, because both the framework and the user are trying to bind + * {@code @LookupUrl String}. + * + * @author sameb@google.com (Sam Berlin) + * @since 4.0 + */ +public class OptionalBinder { + // This class is non-final due to users mocking this in tests :( + + public static OptionalBinder newOptionalBinder(Binder binder, Class type) { + return new OptionalBinder( + newRealOptionalBinder(binder.skipSources(OptionalBinder.class), Key.get(type))); + } + + public static OptionalBinder newOptionalBinder(Binder binder, TypeLiteral type) { + return new OptionalBinder( + newRealOptionalBinder(binder.skipSources(OptionalBinder.class), Key.get(type))); + } + + public static OptionalBinder newOptionalBinder(Binder binder, Key type) { + return new OptionalBinder( + newRealOptionalBinder(binder.skipSources(OptionalBinder.class), type)); + } + + private final RealOptionalBinder delegate; + + private OptionalBinder(RealOptionalBinder delegate) { + this.delegate = delegate; + } + + /** + * Returns a binding builder used to set the default value that will be injected. The binding set + * by this method will be ignored if {@link #setBinding} is called. + * + *

    It is an error to call this method without also calling one of the {@code to} methods on the + * returned binding builder. + */ + public LinkedBindingBuilder setDefault() { + return delegate.setDefault(); + } + + /** + * Returns a binding builder used to set the actual value that will be injected. This overrides + * any binding set by {@link #setDefault}. + * + *

    It is an error to call this method without also calling one of the {@code to} methods on the + * returned binding builder. + */ + public LinkedBindingBuilder setBinding() { + return delegate.setBinding(); + } + + // Some tests depend on equals/hashCode behavior of OptionalBinder + + @Override + public boolean equals(Object obj) { + if (obj instanceof OptionalBinder) { + return delegate.equals(((OptionalBinder) obj).delegate); + } + return false; + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/package-info.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/package-info.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Extension for binding multiple instances in a collection; this extension requires {@code + * guice-multibindings.jar}. + */ +package com.google.inject.multibindings; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ProvidesIntoMap.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ProvidesIntoMap.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ProvidesIntoMap.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ProvidesIntoMap.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.Module; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Annotates methods of a {@link Module} to add items to a {@link MapBinder}. The method's return + * type, binding annotation and additional key annotation determines what Map this will contribute + * to. For example, + * + *

    + * {@literal @}ProvidesIntoMap
    + * {@literal @}StringMapKey("Foo")
    + * {@literal @}Named("urls")
    + * Plugin provideFooUrl(FooManager fm) { return fm.getPlugin(); }
    + *
    + * {@literal @}ProvidesIntoMap
    + * {@literal @}StringMapKey("Bar")
    + * {@literal @}Named("urls")
    + * Plugin provideBarUrl(BarManager bm) { return bm.getPlugin(); }
    + * 
    + * + * will add two items to the {@code @Named("urls") Map} map. The key 'Foo' will map + * to the provideFooUrl method, and the key 'Bar' will map to the provideBarUrl method. The values + * are bound as providers and will be evaluated at injection time. + * + *

    Because the key is specified as an annotation, only Strings, Classes, enums, primitive types + * and annotation instances are supported as keys. + * + * @author sameb@google.com (Sam Berlin) + * @since 4.0 + */ +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface ProvidesIntoMap {} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ProvidesIntoOptional.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ProvidesIntoOptional.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ProvidesIntoOptional.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ProvidesIntoOptional.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.Module; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Annotates methods of a {@link Module} to add items to a {@link Multibinder}. The method's return + * type and binding annotation determines what Optional this will contribute to. For example, + * + *

    + * {@literal @}ProvidesIntoOptional(DEFAULT)
    + * {@literal @}Named("url")
    + * String provideFooUrl(FooManager fm) { returm fm.getUrl(); }
    + *
    + * {@literal @}ProvidesIntoOptional(ACTUAL)
    + * {@literal @}Named("url")
    + * String provideBarUrl(BarManager bm) { return bm.getUrl(); }
    + * 
    + * + * will set the default value of {@code @Named("url") Optional} to foo's URL, and then + * override it to bar's URL. + * + * @author sameb@google.com (Sam Berlin) + * @since 4.0 + */ +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface ProvidesIntoOptional { + /** @since 4.0 */ + enum Type { + /** Corresponds to {@link OptionalBinder#setBinding}. */ + ACTUAL, + + /** Corresponds to {@link OptionalBinder#setDefault}. */ + DEFAULT + } + + /** Specifies if the binding is for the actual or default value. */ + Type value(); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ProvidesIntoSet.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ProvidesIntoSet.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/ProvidesIntoSet.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/ProvidesIntoSet.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.Module; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Annotates methods of a {@link Module} to add items to a {@link Multibinder}. The method's return + * type and binding annotation determines what Set this will contribute to. For example, + * + *
    + * {@literal @}ProvidesIntoSet
    + * {@literal @}Named("urls")
    + * String provideFooUrl(FooManager fm) { returm fm.getUrl(); }
    + *
    + * {@literal @}ProvidesIntoSet
    + * {@literal @}Named("urls")
    + * String provideBarUrl(BarManager bm) { return bm.getUrl(); }
    + * 
    + * + * will add two items to the {@code @Named("urls") Set} set. The items are bound as + * providers and will be evaluated at injection time. + * + * @author sameb@google.com (Sam Berlin) + * @since 4.0 + */ +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface ProvidesIntoSet {} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/multibindings/StringMapKey.java sisu-guice-4.2.0/core/src/com/google/inject/multibindings/StringMapKey.java --- sisu-guice-3.2.6/core/src/com/google/inject/multibindings/StringMapKey.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/multibindings/StringMapKey.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Allows {@literal @}{@link ProvidesIntoMap} to specify a string map key. + * + * @since 4.0 + */ +@MapKey(unwrapValue = true) +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface StringMapKey { + String value(); +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/name/NamedImpl.java sisu-guice-4.2.0/core/src/com/google/inject/name/NamedImpl.java --- sisu-guice-3.2.6/core/src/com/google/inject/name/NamedImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/name/NamedImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.inject.internal.Annotations; import java.io.Serializable; import java.lang.annotation.Annotation; @@ -29,15 +30,18 @@ this.value = checkNotNull(value, "name"); } + @Override public String value() { return this.value; } + @Override public int hashCode() { // This is specified in java.lang.Annotation. return (127 * "value".hashCode()) ^ value.hashCode(); } + @Override public boolean equals(Object o) { if (!(o instanceof Named)) { return false; @@ -47,10 +51,12 @@ return value.equals(other.value()); } + @Override public String toString() { - return "@" + Named.class.getName() + "(value=" + value + ")"; + return "@" + Named.class.getName() + "(value=" + Annotations.memberValueString(value) + ")"; } + @Override public Class annotationType() { return Named.class; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/name/Named.java sisu-guice-4.2.0/core/src/com/google/inject/name/Named.java --- sisu-guice-3.2.6/core/src/com/google/inject/name/Named.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/name/Named.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.BindingAnnotation; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -30,7 +29,7 @@ * @author crazybob@google.com (Bob Lee) */ @Retention(RUNTIME) -@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @BindingAnnotation public @interface Named { String value(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/name/Names.java sisu-guice-4.2.0/core/src/com/google/inject/name/Names.java --- sisu-guice-3.2.6/core/src/com/google/inject/name/Names.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/name/Names.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.inject.Binder; import com.google.inject.Key; - import java.util.Enumeration; import java.util.Map; import java.util.Properties; @@ -32,17 +31,12 @@ private Names() {} - /** - * Creates a {@link Named} annotation with {@code name} as the value. - */ + /** Creates a {@link Named} annotation with {@code name} as the value. */ public static Named named(String name) { return new NamedImpl(name); } - /** - * Creates a constant binding to {@code @Named(key)} for each entry in - * {@code properties}. - */ + /** Creates a constant binding to {@code @Named(key)} for each entry in {@code properties}. */ public static void bindProperties(Binder binder, Map properties) { binder = binder.skipSources(Names.class); for (Map.Entry entry : properties.entrySet()) { @@ -53,9 +47,8 @@ } /** - * Creates a constant binding to {@code @Named(key)} for each property. This - * method binds all properties including those inherited from - * {@link Properties#defaults defaults}. + * Creates a constant binding to {@code @Named(key)} for each property. This method binds all + * properties including those inherited from {@link Properties#defaults defaults}. */ public static void bindProperties(Binder binder, Properties properties) { binder = binder.skipSources(Names.class); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/name/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/name/package-info.java --- sisu-guice-3.2.6/core/src/com/google/inject/name/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/name/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,7 +14,5 @@ * limitations under the License. */ -/** - * Support for binding to string-based names. - */ -package com.google.inject.name; \ No newline at end of file +/** Support for binding to string-based names. */ +package com.google.inject.name; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/OutOfScopeException.java sisu-guice-4.2.0/core/src/com/google/inject/OutOfScopeException.java --- sisu-guice-3.2.6/core/src/com/google/inject/OutOfScopeException.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/OutOfScopeException.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,8 +17,8 @@ package com.google.inject; /** - * Thrown from {@link Provider#get} when an attempt is made to access a scoped - * object while the scope in question is not currently active. + * Thrown from {@link Provider#get} when an attempt is made to access a scoped object while the + * scope in question is not currently active. * * @author kevinb@google.com (Kevin Bourrillion) * @since 2.0 diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/package-info.java --- sisu-guice-3.2.6/core/src/com/google/inject/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,33 +15,25 @@ */ /** - * Google Guice (pronounced "juice") is an ultra-lightweight dependency - * injection framework. Please refer to the Guice - * User's Guide - * for a gentle introduction. + * Google Guice (pronounced "juice") is an ultra-lightweight dependency injection framework. + * Please refer to the Guice User's + * Guide for a gentle introduction. * *

    The principal public APIs in this package are: * *

    *
    {@link com.google.inject.Inject} - *
    The annotation you will use in your implementation classes to tell Guice - * where and how it should send in ("inject") the objects you depend on - * (your "dependencies"). - * + *
    The annotation you will use in your implementation classes to tell Guice where and how it + * should send in ("inject") the objects you depend on (your "dependencies"). *
    {@link com.google.inject.Module} - *
    The interface you will implement in order to specify "bindings" -- - * instructions for how Guice should handle injection -- for a particular - * set of interfaces. - * + *
    The interface you will implement in order to specify "bindings" -- instructions for how Guice + * should handle injection -- for a particular set of interfaces. *
    {@link com.google.inject.Binder} - *
    The object that Guice passes into your {@link com.google.inject.Module} - * to collect these bindings. - * + *
    The object that Guice passes into your {@link com.google.inject.Module} to collect these + * bindings. *
    {@link com.google.inject.Provider} - *
    The interface you will implement when you need to customize exactly how - * Guice creates instances for a particular binding. - * + *
    The interface you will implement when you need to customize exactly how Guice creates + * instances for a particular binding. *
    - * */ -package com.google.inject; \ No newline at end of file +package com.google.inject; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/PrivateBinder.java sisu-guice-4.2.0/core/src/com/google/inject/PrivateBinder.java --- sisu-guice-3.2.6/core/src/com/google/inject/PrivateBinder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/PrivateBinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ /** * Returns a binder whose configuration information is hidden from its environment by default. See * {@link com.google.inject.PrivateModule PrivateModule} for details. - * + * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ @@ -32,8 +32,8 @@ /** * Makes a binding for {@code type} available to the enclosing environment. Use {@link - * com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a - * binding annotation. + * com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to + * expose {@code type} with a binding annotation. */ AnnotatedElementBuilder expose(Class type); @@ -44,7 +44,9 @@ */ AnnotatedElementBuilder expose(TypeLiteral type); + @Override PrivateBinder withSource(Object source); + @Override PrivateBinder skipSources(Class... classesToSkip); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/PrivateModule.java sisu-guice-4.2.0/core/src/com/google/inject/PrivateModule.java --- sisu-guice-3.2.6/core/src/com/google/inject/PrivateModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/PrivateModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,6 @@ import com.google.inject.spi.ProvisionListener; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeListener; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -37,14 +36,14 @@ * This module may expose the bindings it creates and the bindings of the modules it installs. * *

    A private module can be nested within a regular module or within another private module using - * {@link Binder#install install()}. Its bindings live in a new environment that inherits bindings, - * type converters, scopes, and interceptors from the surrounding ("parent") environment. When you + * {@link Binder#install install()}. Its bindings live in a new environment that inherits bindings, + * type converters, scopes, and interceptors from the surrounding ("parent") environment. When you * nest multiple private modules, the result is a tree of environments where the injector's * environment is the root. * *

    Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link - * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link - * Exposed} annotation: + * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link Exposed} + * annotation: * *

      * public class FooBarBazModule extends PrivateModule {
    @@ -69,7 +68,7 @@
      * 

    Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the * root environment. Such bindings are shared among all environments in the tree. - * + * *

    The scope of a binding is constrained to its environment. A singleton bound in a private * module will be unique to its environment. But a binding for the same type in a different private * module will yield a different instance. @@ -79,6 +78,7 @@ * gets access to all bindings in the child environment. * *

    To promote a just-in-time binding to an explicit binding, bind it: + * *

      *   bind(FooImpl.class);
      * 
    @@ -91,6 +91,7 @@ /** Like abstract module, the binder of the current private module */ private PrivateBinder binder; + @Override public final synchronized void configure(Binder binder) { checkState(this.binder == null, "Re-entry is not allowed."); @@ -134,155 +135,120 @@ // everything below is copied from AbstractModule - /** - * Returns the current binder. - */ + /** Returns the current binder. */ protected final PrivateBinder binder() { checkState(binder != null, "The binder can only be used inside configure()"); return binder; } - /** - * @see Binder#bindScope(Class, Scope) - */ + /** @see Binder#bindScope(Class, Scope) */ protected final void bindScope(Class scopeAnnotation, Scope scope) { binder().bindScope(scopeAnnotation, scope); } - /** - * @see Binder#bind(Key) - */ + /** @see Binder#bind(Key) */ protected final LinkedBindingBuilder bind(Key key) { return binder().bind(key); } - /** - * @see Binder#bind(TypeLiteral) - */ + /** @see Binder#bind(TypeLiteral) */ protected final AnnotatedBindingBuilder bind(TypeLiteral typeLiteral) { return binder().bind(typeLiteral); } - /** - * @see Binder#bind(Class) - */ + /** @see Binder#bind(Class) */ protected final AnnotatedBindingBuilder bind(Class clazz) { return binder().bind(clazz); } - /** - * @see Binder#bindConstant() - */ + /** @see Binder#bindConstant() */ protected final AnnotatedConstantBindingBuilder bindConstant() { return binder().bindConstant(); } - /** - * @see Binder#install(Module) - */ + /** @see Binder#install(Module) */ protected final void install(Module module) { binder().install(module); } - /** - * @see Binder#addError(String, Object[]) - */ + /** @see Binder#addError(String, Object[]) */ protected final void addError(String message, Object... arguments) { binder().addError(message, arguments); } - /** - * @see Binder#addError(Throwable) - */ + /** @see Binder#addError(Throwable) */ protected final void addError(Throwable t) { binder().addError(t); } - /** - * @see Binder#addError(Message) - */ + /** @see Binder#addError(Message) */ protected final void addError(Message message) { binder().addError(message); } - /** - * @see Binder#requestInjection(Object) - */ + /** @see Binder#requestInjection(Object) */ protected final void requestInjection(Object instance) { binder().requestInjection(instance); } - /** - * @see Binder#requestStaticInjection(Class[]) - */ + /** @see Binder#requestStaticInjection(Class[]) */ protected final void requestStaticInjection(Class... types) { binder().requestStaticInjection(types); } /*if[AOP]*/ /** - * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) + * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, + * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) */ - protected final void bindInterceptor(Matcher> classMatcher, + protected final void bindInterceptor( + Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { binder().bindInterceptor(classMatcher, methodMatcher, interceptors); } /*end[AOP]*/ - /** - * Instructs Guice to require a binding to the given key. - */ + /** Instructs Guice to require a binding to the given key. */ protected final void requireBinding(Key key) { binder().getProvider(key); } - /** - * Instructs Guice to require a binding to the given type. - */ + /** Instructs Guice to require a binding to the given type. */ protected final void requireBinding(Class type) { binder().getProvider(type); } - /** - * @see Binder#getProvider(Key) - */ + /** @see Binder#getProvider(Key) */ protected final Provider getProvider(Key key) { return binder().getProvider(key); } - - /** - * @see Binder#getProvider(Class) - */ + + /** @see Binder#getProvider(Class) */ protected final Provider getProvider(Class type) { return binder().getProvider(type); } /** - * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter) + * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, + * com.google.inject.spi.TypeConverter) */ - protected final void convertToTypes(Matcher> typeMatcher, - TypeConverter converter) { + protected final void convertToTypes( + Matcher> typeMatcher, TypeConverter converter) { binder().convertToTypes(typeMatcher, converter); } - /** - * @see Binder#currentStage() - */ + /** @see Binder#currentStage() */ protected final Stage currentStage() { return binder().currentStage(); } - /** - * @see Binder#getMembersInjector(Class) - */ + /** @see Binder#getMembersInjector(Class) */ protected MembersInjector getMembersInjector(Class type) { return binder().getMembersInjector(type); } - /** - * @see Binder#getMembersInjector(TypeLiteral) - */ + /** @see Binder#getMembersInjector(TypeLiteral) */ protected MembersInjector getMembersInjector(TypeLiteral type) { return binder().getMembersInjector(type); } @@ -290,17 +256,16 @@ /** * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener) */ - protected void bindListener(Matcher> typeMatcher, - TypeListener listener) { + protected void bindListener(Matcher> typeMatcher, TypeListener listener) { binder().bindListener(typeMatcher, listener); } - + /** * @see Binder#bindListener(Matcher, ProvisionListener...) * @since 4.0 */ - protected void bindListener(Matcher> bindingMatcher, - ProvisionListener... listeners) { + protected void bindListener( + Matcher> bindingMatcher, ProvisionListener... listeners) { binder().bindListener(bindingMatcher, listeners); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/ProvidedBy.java sisu-guice-4.2.0/core/src/com/google/inject/ProvidedBy.java --- sisu-guice-3.2.6/core/src/com/google/inject/ProvidedBy.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/ProvidedBy.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,8 +31,6 @@ @Target(TYPE) public @interface ProvidedBy { - /** - * The implementation type. - */ - Class> value(); + /** The implementation type. */ + Class> value(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Provider.java sisu-guice-4.2.0/core/src/com/google/inject/Provider.java --- sisu-guice-3.2.6/core/src/com/google/inject/Provider.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Provider.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,35 +22,32 @@ * *
      *
    • When the default means for obtaining instances (an injectable or parameterless constructor) - * is insufficient for a particular binding, the module can specify a custom {@code Provider} - * instead, to control exactly how Guice creates or obtains instances for the binding. - * + * is insufficient for a particular binding, the module can specify a custom {@code Provider} + * instead, to control exactly how Guice creates or obtains instances for the binding. *
    • An implementation class may always choose to have a {@code Provider} instance injected, - * rather than having a {@code T} injected directly. This may give you access to multiple - * instances, instances you wish to safely mutate and discard, instances which are out of scope - * (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or - * instances that will be initialized lazily. - * + * rather than having a {@code T} injected directly. This may give you access to multiple + * instances, instances you wish to safely mutate and discard, instances which are out of scope + * (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or + * instances that will be initialized lazily. *
    • A custom {@link Scope} is implemented as a decorator of {@code Provider}, which decides - * when to delegate to the backing provider and when to provide the instance some other way. - * - *
    • The {@link Injector} offers access to the {@code Provider} it uses to fulfill requests - * for a given key, via the {@link Injector#getProvider} methods. + * when to delegate to the backing provider and when to provide the instance some other way. + *
    • The {@link Injector} offers access to the {@code Provider} it uses to fulfill requests for + * a given key, via the {@link Injector#getProvider} methods. *
    * * @param the type of object this provides - * * @author crazybob@google.com (Bob Lee) */ public interface Provider extends javax.inject.Provider { /** - * Provides an instance of {@code T}. Must never return {@code null}. + * Provides an instance of {@code T}. * * @throws OutOfScopeException when an attempt is made to access a scoped object while the scope * in question is not currently active * @throws ProvisionException if an instance cannot be provided. Such exceptions include messages * and throwables to describe why provision failed. */ + @Override T get(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Provides.java sisu-guice-4.2.0/core/src/com/google/inject/Provides.java --- sisu-guice-3.2.6/core/src/com/google/inject/Provides.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Provides.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,5 +30,7 @@ * @author crazybob@google.com (Bob Lee) * @since 2.0 */ -@Documented @Target(METHOD) @Retention(RUNTIME) +@Documented +@Target(METHOD) +@Retention(RUNTIME) public @interface Provides {} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/ProvisionException.java sisu-guice-4.2.0/core/src/com/google/inject/ProvisionException.java --- sisu-guice-3.2.6/core/src/com/google/inject/ProvisionException.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/ProvisionException.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,14 +19,14 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.collect.ImmutableSet; -import com.google.inject.internal.Errors; +import com.google.inject.internal.Messages; import com.google.inject.spi.Message; - import java.util.Collection; /** * Indicates that there was a runtime failure while providing an instance. * + * * @author kevinb@google.com (Kevin Bourrillion) * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 @@ -39,7 +39,7 @@ public ProvisionException(Iterable messages) { this.messages = ImmutableSet.copyOf(messages); checkArgument(!this.messages.isEmpty()); - initCause(Errors.getOnlyCause(this.messages)); + initCause(Messages.getOnlyCause(this.messages)); } public ProvisionException(String message, Throwable cause) { @@ -56,8 +56,9 @@ return messages; } - @Override public String getMessage() { - return Errors.format("Unable to provision, see the following errors", messages); + @Override + public String getMessage() { + return Messages.formatMessages("Unable to provision, see the following errors", messages); } private static final long serialVersionUID = 0; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/ScopeAnnotation.java sisu-guice-4.2.0/core/src/com/google/inject/ScopeAnnotation.java --- sisu-guice-3.2.6/core/src/com/google/inject/ScopeAnnotation.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/ScopeAnnotation.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,9 +23,9 @@ import java.lang.annotation.Target; /** - * Annotates annotations which are used for scoping. Only one such annotation - * may apply to a single implementation class. You must also annotate scope - * annotations with {@code @Retention(RUNTIME)}. For example: + * Annotates annotations which are used for scoping. Only one such annotation may apply to a single + * implementation class. You must also annotate scope annotations with {@code @Retention(RUNTIME)}. + * For example: * *
      *   {@code @}Retention(RUNTIME)
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Scope.java sisu-guice-4.2.0/core/src/com/google/inject/Scope.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/Scope.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/Scope.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -17,13 +17,11 @@
     package com.google.inject;
     
     /**
    - * A scope is a level of visibility that instances provided by Guice may have.
    - * By default, an instance created by the {@link Injector} has no scope,
    - * meaning it has no state from the framework's perspective -- the
    - * {@code Injector} creates it, injects it once into the class that required it,
    - * and then immediately forgets it. Associating a scope with a particular
    - * binding allows the created instance to be "remembered" and possibly used
    - * again for other injections.
    + * A scope is a level of visibility that instances provided by Guice may have. By default, an
    + * instance created by the {@link Injector} has no scope, meaning it has no state from the
    + * framework's perspective -- the {@code Injector} creates it, injects it once into the class that
    + * required it, and then immediately forgets it. Associating a scope with a particular binding
    + * allows the created instance to be "remembered" and possibly used again for other injections.
      *
      * 

    An example of a scope is {@link Scopes#SINGLETON}. * @@ -32,28 +30,24 @@ public interface Scope { /** - * Scopes a provider. The returned provider returns objects from this scope. - * If an object does not exist in this scope, the provider can use the given - * unscoped provider to retrieve one. + * Scopes a provider. The returned provider returns objects from this scope. If an object does not + * exist in this scope, the provider can use the given unscoped provider to retrieve one. * - *

    Scope implementations are strongly encouraged to override - * {@link Object#toString} in the returned provider and include the backing - * provider's {@code toString()} output. + *

    Scope implementations are strongly encouraged to override {@link Object#toString} in the + * returned provider and include the backing provider's {@code toString()} output. * * @param key binding key - * @param unscoped locates an instance when one doesn't already exist in this - * scope. - * @return a new provider which only delegates to the given unscoped provider - * when an instance of the requested object doesn't already exist in this - * scope + * @param unscoped locates an instance when one doesn't already exist in this scope. + * @return a new provider which only delegates to the given unscoped provider when an instance of + * the requested object doesn't already exist in this scope */ public Provider scope(Key key, Provider unscoped); /** - * A short but useful description of this scope. For comparison, the standard - * scopes that ship with guice use the descriptions - * {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and + * A short but useful description of this scope. For comparison, the standard scopes that ship + * with guice use the descriptions {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and * {@code "ServletScopes.REQUEST"}. */ + @Override String toString(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Scopes.java sisu-guice-4.2.0/core/src/com/google/inject/Scopes.java --- sisu-guice-3.2.6/core/src/com/google/inject/Scopes.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Scopes.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ import com.google.inject.internal.SingletonScope; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.spi.ExposedBinding; - import java.lang.annotation.Annotation; /** @@ -33,47 +32,51 @@ private Scopes() {} - /** - * One instance per {@link Injector}. Also see {@code @}{@link Singleton}. - */ + /** One instance per {@link Injector}. Also see {@code @}{@link Singleton}. */ public static final Scope SINGLETON = new SingletonScope(); /** - * No scope; the same as not applying any scope at all. Each time the - * Injector obtains an instance of an object with "no scope", it injects this - * instance then immediately forgets it. When the next request for the same - * binding arrives it will need to obtain the instance over again. + * No scope; the same as not applying any scope at all. Each time the Injector obtains an instance + * of an object with "no scope", it injects this instance then immediately forgets it. When the + * next request for the same binding arrives it will need to obtain the instance over again. * - *

    This exists only in case a class has been annotated with a scope - * annotation such as {@link Singleton @Singleton}, and you need to override - * this to "no scope" in your binding. + *

    This exists only in case a class has been annotated with a scope annotation such as {@link + * Singleton @Singleton}, and you need to override this to "no scope" in your binding. * * @since 2.0 */ - public static final Scope NO_SCOPE = new Scope() { - public Provider scope(Key key, Provider unscoped) { - return unscoped; - } - @Override public String toString() { - return "Scopes.NO_SCOPE"; - } - }; + public static final Scope NO_SCOPE = + new Scope() { + @Override + public Provider scope(Key key, Provider unscoped) { + return unscoped; + } - private static final BindingScopingVisitor IS_SINGLETON_VISITOR - = new BindingScopingVisitor() { + @Override + public String toString() { + return "Scopes.NO_SCOPE"; + } + }; + + private static final BindingScopingVisitor IS_SINGLETON_VISITOR = + new BindingScopingVisitor() { + @Override public Boolean visitNoScoping() { return false; } + @Override public Boolean visitScopeAnnotation(Class scopeAnnotation) { return scopeAnnotation == Singleton.class || scopeAnnotation == javax.inject.Singleton.class; } + @Override public Boolean visitScope(Scope scope) { return scope == Scopes.SINGLETON; } + @Override public Boolean visitEagerSingleton() { return true; } @@ -101,8 +104,8 @@ binding = injector.getBinding(linkedBinding.getLinkedKey()); continue; } - } else if(binding instanceof ExposedBinding) { - ExposedBinding exposedBinding = (ExposedBinding)binding; + } else if (binding instanceof ExposedBinding) { + ExposedBinding exposedBinding = (ExposedBinding) binding; Injector injector = exposedBinding.getPrivateElements().getInjector(); if (injector != null) { binding = injector.getBinding(exposedBinding.getKey()); @@ -115,7 +118,6 @@ } /** - * Returns true if {@code binding} has the given scope. If the binding is a {@link * com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it * was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will @@ -126,26 +128,32 @@ * @param scopeAnnotation scope annotation class * @since 4.0 */ - public static boolean isScoped(Binding binding, final Scope scope, - final Class scopeAnnotation) { + public static boolean isScoped( + Binding binding, final Scope scope, final Class scopeAnnotation) { do { - boolean matches = binding.acceptScopingVisitor(new BindingScopingVisitor() { - public Boolean visitNoScoping() { - return false; - } - - public Boolean visitScopeAnnotation(Class visitedAnnotation) { - return visitedAnnotation == scopeAnnotation; - } - - public Boolean visitScope(Scope visitedScope) { - return visitedScope == scope; - } - - public Boolean visitEagerSingleton() { - return false; - } - }); + boolean matches = + binding.acceptScopingVisitor( + new BindingScopingVisitor() { + @Override + public Boolean visitNoScoping() { + return false; + } + + @Override + public Boolean visitScopeAnnotation(Class visitedAnnotation) { + return visitedAnnotation == scopeAnnotation; + } + + @Override + public Boolean visitScope(Scope visitedScope) { + return visitedScope == scope; + } + + @Override + public Boolean visitEagerSingleton() { + return false; + } + }); if (matches) { return true; @@ -158,8 +166,8 @@ binding = injector.getBinding(linkedBinding.getLinkedKey()); continue; } - } else if(binding instanceof ExposedBinding) { - ExposedBinding exposedBinding = (ExposedBinding)binding; + } else if (binding instanceof ExposedBinding) { + ExposedBinding exposedBinding = (ExposedBinding) binding; Injector injector = exposedBinding.getPrivateElements().getInjector(); if (injector != null) { binding = injector.getBinding(exposedBinding.getKey()); @@ -172,12 +180,11 @@ } /** - * Returns true if the object is a proxy for a circular dependency, - * constructed by Guice because it encountered a circular dependency. Scope - * implementations should be careful to not cache circular proxies, - * because the proxies are not intended for general purpose use. (They are - * designed just to fulfill the immediate injection, not all injections. - * Caching them can lead to IllegalArgumentExceptions or ClassCastExceptions.) + * Returns true if the object is a proxy for a circular dependency, constructed by Guice because + * it encountered a circular dependency. Scope implementations should be careful to not cache + * circular proxies, because the proxies are not intended for general purpose use. (They are + * designed just to fulfill the immediate injection, not all injections. Caching them can lead to + * IllegalArgumentExceptions or ClassCastExceptions.) * * @since 4.0 */ diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Singleton.java sisu-guice-4.2.0/core/src/com/google/inject/Singleton.java --- sisu-guice-3.2.6/core/src/com/google/inject/Singleton.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Singleton.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,12 +23,12 @@ import java.lang.annotation.Target; /** - * Apply this to implementation classes when you want only one instance - * (per {@link Injector}) to be reused for all injections for that binding. + * Apply this to implementation classes when you want only one instance (per {@link Injector}) to be + * reused for all injections for that binding. * * @author crazybob@google.com (Bob Lee) */ -@Target({ ElementType.TYPE, ElementType.METHOD }) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RUNTIME) @ScopeAnnotation public @interface Singleton {} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/BindingScopingVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/BindingScopingVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/BindingScopingVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/BindingScopingVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,14 +17,13 @@ package com.google.inject.spi; import com.google.inject.Scope; - import java.lang.annotation.Annotation; /** * Visits each of the strategies used to scope an injection. * - * @param any type to be returned by the visit method. Use {@link Void} with - * {@code return null} if no return type is needed. + * @param any type to be returned by the visit method. Use {@link Void} with {@code return null} + * if no return type is needed. * @since 2.0 */ public interface BindingScopingVisitor { @@ -35,9 +34,7 @@ */ V visitEagerSingleton(); - /** - * Visit a scope instance. This scope strategy is found on both module and injector bindings. - */ + /** Visit a scope instance. This scope strategy is found on both module and injector bindings. */ V visitScope(Scope scope); /** @@ -49,9 +46,9 @@ /** * Visit an unspecified or unscoped strategy. On a module, this strategy indicates that the - * injector should use scoping annotations to find a scope. On an injector, it indicates that - * no scope is applied to the binding. An unscoped binding will behave like a scoped one when it - * is linked to a scoped binding. + * injector should use scoping annotations to find a scope. On an injector, it indicates that no + * scope is applied to the binding. An unscoped binding will behave like a scoped one when it is + * linked to a scoped binding. */ V visitNoScoping(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/BindingTargetVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/BindingTargetVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/BindingTargetVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/BindingTargetVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,8 +19,8 @@ /** * Visits each of the strategies used to find an instance to satisfy an injection. * - * @param any type to be returned by the visit method. Use {@link Void} with - * {@code return null} if no return type is needed. + * @param any type to be returned by the visit method. Use {@link Void} with {@code return null} + * if no return type is needed. * @since 2.0 */ public interface BindingTargetVisitor { @@ -45,8 +45,8 @@ V visit(ProviderKeyBinding binding); /** - * Visit a linked key binding. The other key's binding is used to resolve injections. This - * target is found in both module and injector bindings. + * Visit a linked key binding. The other key's binding is used to resolve injections. This target + * is found in both module and injector bindings. */ V visit(LinkedKeyBinding binding); @@ -57,8 +57,8 @@ V visit(ExposedBinding binding); /** - * Visit an untargetted binding. This target is found only on module bindings. It indicates - * that the injector should use its implicit binding strategies to resolve injections. + * Visit an untargetted binding. This target is found only on module bindings. It indicates that + * the injector should use its implicit binding strategies to resolve injections. */ V visit(UntargettedBinding binding); @@ -69,8 +69,8 @@ V visit(ConstructorBinding binding); /** - * Visit a binding created from converting a bound instance to a new type. The source binding - * has the same binding annotation but a different type. This target is found only on injector + * Visit a binding created from converting a bound instance to a new type. The source binding has + * the same binding annotation but a different type. This target is found only on injector * bindings. */ V visit(ConvertedConstantBinding binding); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ConstructorBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ConstructorBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ConstructorBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ConstructorBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.spi; import com.google.inject.Binding; - import java.lang.reflect.Method; import java.util.List; import java.util.Map; @@ -32,17 +31,15 @@ */ public interface ConstructorBinding extends Binding, HasDependencies { - /** - * Gets the constructor this binding injects. - */ + /** Gets the constructor this binding injects. */ InjectionPoint getConstructor(); /** * Returns all instance method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. */ Set getInjectableMembers(); @@ -54,4 +51,4 @@ */ Map> getMethodInterceptors(); /*end[AOP]*/ -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ConvertedConstantBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ConvertedConstantBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ConvertedConstantBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ConvertedConstantBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.inject.Binding; import com.google.inject.Key; - import java.util.Set; /** @@ -30,14 +29,12 @@ */ public interface ConvertedConstantBinding extends Binding, HasDependencies { - /** - * Returns the converted value. - */ + /** Returns the converted value. */ T getValue(); /** * Returns the type converter binding used to convert the constant. - * + * * @since 3.0 */ TypeConverterBinding getTypeConverterBinding(); @@ -48,8 +45,7 @@ */ Key getSourceKey(); - /** - * Returns a singleton set containing only the converted key. - */ + /** Returns a singleton set containing only the converted key. */ + @Override Set> getDependencies(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,40 +17,40 @@ package com.google.inject.spi; import com.google.inject.Scope; - import java.lang.annotation.Annotation; /** - * No-op visitor for subclassing. All interface methods simply delegate to - * {@link #visitOther()}, returning its result. + * No-op visitor for subclassing. All interface methods simply delegate to {@link #visitOther()}, + * returning its result. * - * @param any type to be returned by the visit method. Use {@link Void} with - * {@code return null} if no return type is needed. - * + * @param any type to be returned by the visit method. Use {@link Void} with {@code return null} + * if no return type is needed. * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public class DefaultBindingScopingVisitor implements BindingScopingVisitor { - /** - * Default visit implementation. Returns {@code null}. - */ + /** Default visit implementation. Returns {@code null}. */ protected V visitOther() { return null; } + @Override public V visitEagerSingleton() { return visitOther(); } + @Override public V visitScope(Scope scope) { return visitOther(); } + @Override public V visitScopeAnnotation(Class scopeAnnotation) { return visitOther(); } + @Override public V visitNoScoping() { return visitOther(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,53 +22,59 @@ * No-op visitor for subclassing. All interface methods simply delegate to {@link * #visitOther(Binding)}, returning its result. * - * @param any type to be returned by the visit method. Use {@link Void} with - * {@code return null} if no return type is needed. - * + * @param any type to be returned by the visit method. Use {@link Void} with {@code return null} + * if no return type is needed. * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public abstract class DefaultBindingTargetVisitor implements BindingTargetVisitor { - /** - * Default visit implementation. Returns {@code null}. - */ + /** Default visit implementation. Returns {@code null}. */ protected V visitOther(Binding binding) { return null; } + @Override public V visit(InstanceBinding instanceBinding) { return visitOther(instanceBinding); } + @Override public V visit(ProviderInstanceBinding providerInstanceBinding) { return visitOther(providerInstanceBinding); } + @Override public V visit(ProviderKeyBinding providerKeyBinding) { return visitOther(providerKeyBinding); } + @Override public V visit(LinkedKeyBinding linkedKeyBinding) { return visitOther(linkedKeyBinding); } + @Override public V visit(ExposedBinding exposedBinding) { return visitOther(exposedBinding); } + @Override public V visit(UntargettedBinding untargettedBinding) { return visitOther(untargettedBinding); } + @Override public V visit(ConstructorBinding constructorBinding) { return visitOther(constructorBinding); } + @Override public V visit(ConvertedConstantBinding convertedConstantBinding) { return visitOther(convertedConstantBinding); } + @Override @SuppressWarnings("unchecked") public V visit(ProviderBinding providerBinding) { // TODO(cushon): remove raw (Binding) cast when we don't care about javac 6 anymore diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/DefaultElementVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/DefaultElementVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/DefaultElementVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/DefaultElementVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,90 +19,104 @@ import com.google.inject.Binding; /** - * No-op visitor for subclassing. All interface methods simply delegate to - * {@link #visitOther(Element)}, returning its result. - * - * @param any type to be returned by the visit method. Use {@link Void} with - * {@code return null} if no return type is needed. + * No-op visitor for subclassing. All interface methods simply delegate to {@link + * #visitOther(Element)}, returning its result. * + * @param any type to be returned by the visit method. Use {@link Void} with {@code return null} + * if no return type is needed. * @author sberlin@gmail.com (Sam Berlin) * @since 2.0 */ public abstract class DefaultElementVisitor implements ElementVisitor { - /** - * Default visit implementation. Returns {@code null}. - */ + /** Default visit implementation. Returns {@code null}. */ protected V visitOther(Element element) { return null; } + @Override public V visit(Message message) { return visitOther(message); } + @Override public V visit(Binding binding) { return visitOther(binding); } /*if[AOP]*/ + @Override public V visit(InterceptorBinding interceptorBinding) { return visitOther(interceptorBinding); } /*end[AOP]*/ + @Override public V visit(ScopeBinding scopeBinding) { return visitOther(scopeBinding); } + @Override public V visit(TypeConverterBinding typeConverterBinding) { return visitOther(typeConverterBinding); } + @Override public V visit(ProviderLookup providerLookup) { return visitOther(providerLookup); } + @Override public V visit(InjectionRequest injectionRequest) { return visitOther(injectionRequest); } + @Override public V visit(StaticInjectionRequest staticInjectionRequest) { return visitOther(staticInjectionRequest); } + @Override public V visit(PrivateElements privateElements) { return visitOther(privateElements); } + @Override public V visit(MembersInjectorLookup lookup) { return visitOther(lookup); } + @Override public V visit(TypeListenerBinding binding) { return visitOther(binding); } - + + @Override public V visit(ProvisionListenerBinding binding) { return visitOther(binding); } - + + @Override public V visit(DisableCircularProxiesOption option) { return visitOther(option); } - + + @Override public V visit(RequireExplicitBindingsOption option) { return visitOther(option); } - + + @Override public V visit(RequireAtInjectOnConstructorsOption option) { return visitOther(option); } + @Override public V visit(RequireExactBindingAnnotationsOption option) { return visitOther(option); } + @Override public V visit(ModuleAnnotatedMethodScannerBinding binding) { return visitOther(binding); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/DependencyAndSource.java sisu-guice-4.2.0/core/src/com/google/inject/spi/DependencyAndSource.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/DependencyAndSource.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/DependencyAndSource.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,12 +1,12 @@ /* * Copyright (C) 2011 Google Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -20,16 +20,19 @@ import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.internal.util.StackTraceElements; - import java.lang.reflect.Member; /** - * A combination of a {@link Dependency} and the {@link Binding#getSource() - * source} where the dependency was bound. - * + * A combination of a {@link Dependency} and the {@link Binding#getSource() source} where the + * dependency was bound. + * * @author sameb@google.com (Sam Berlin) * @since 4.0 + * @deprecated The only use of this object is for {@link + * ProvisionListener.ProvisionInvocation#getDependencyChain()} which is also deprecated. This + * object will also be removed in Guice 4.4. */ +@Deprecated public final class DependencyAndSource { private final Dependency dependency; private final Object source; @@ -40,21 +43,19 @@ } /** - * Returns the Dependency, if one exists. For anything that can be referenced - * by {@link Injector#getBinding}, a dependency exists. A dependency will not - * exist (and this will return null) for types initialized with - * {@link Binder#requestInjection} or {@link Injector#injectMembers(Object)}, - * nor will it exist for objects injected into Providers bound with - * LinkedBindingBuilder#toProvider(Provider). + * Returns the Dependency, if one exists. For anything that can be referenced by {@link + * Injector#getBinding}, a dependency exists. A dependency will not exist (and this will return + * null) for types initialized with {@link Binder#requestInjection} or {@link + * Injector#injectMembers(Object)}, nor will it exist for objects injected into Providers bound + * with LinkedBindingBuilder#toProvider(Provider). */ public Dependency getDependency() { return dependency; } /** - * Returns a string describing where this dependency was bound. If the binding - * was just-in-time, there is no valid binding source, so this describes the - * class in question. + * Returns a string describing where this dependency was bound. If the binding was just-in-time, + * there is no valid binding source, so this describes the class in question. */ public String getBindingSource() { if (source instanceof Class) { @@ -76,4 +77,4 @@ return "Source: " + source; } } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/Dependency.java sisu-guice-4.2.0/core/src/com/google/inject/spi/Dependency.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/Dependency.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/Dependency.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.common.collect.Lists; import com.google.inject.Key; import com.google.inject.internal.MoreTypes; - import java.util.List; import java.util.Set; @@ -58,9 +57,7 @@ return new Dependency(null, MoreTypes.canonicalizeKey(key), true, -1); } - /** - * Returns the dependencies from the given injection points. - */ + /** Returns the dependencies from the given injection points. */ public static Set> forInjectionPoints(Set injectionPoints) { List> dependencies = Lists.newArrayList(); for (InjectionPoint injectionPoint : injectionPoints) { @@ -69,16 +66,12 @@ return ImmutableSet.copyOf(dependencies); } - /** - * Returns the key to the binding that satisfies this dependency. - */ + /** Returns the key to the binding that satisfies this dependency. */ public Key getKey() { return this.key; } - /** - * Returns true if null is a legal value for this dependency. - */ + /** Returns true if null is a legal value for this dependency. */ public boolean isNullable() { return nullable; } @@ -100,11 +93,13 @@ return parameterIndex; } - @Override public int hashCode() { + @Override + public int hashCode() { return Objects.hashCode(injectionPoint, parameterIndex, key); } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (o instanceof Dependency) { Dependency dependency = (Dependency) o; return Objects.equal(injectionPoint, dependency.injectionPoint) @@ -115,7 +110,8 @@ } } - @Override public String toString() { + @Override + public String toString() { StringBuilder builder = new StringBuilder(); builder.append(key); if (injectionPoint != null) { diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/DisableCircularProxiesOption.java sisu-guice-4.2.0/core/src/com/google/inject/spi/DisableCircularProxiesOption.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/DisableCircularProxiesOption.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/DisableCircularProxiesOption.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,14 +33,17 @@ this.source = checkNotNull(source, "source"); } + @Override public Object getSource() { return source; } + @Override public void applyTo(Binder binder) { binder.withSource(getSource()).disableCircularProxies(); } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/Element.java sisu-guice-4.2.0/core/src/com/google/inject/spi/Element.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/Element.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/Element.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -60,5 +60,4 @@ * element. */ void applyTo(Binder binder); - } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/Elements.java sisu-guice-4.2.0/core/src/com/google/inject/spi/Elements.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/Elements.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/Elements.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,7 +50,6 @@ import com.google.inject.internal.util.SourceProvider; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.matcher.Matcher; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; @@ -69,41 +68,35 @@ */ public final class Elements { - private static final BindingTargetVisitor GET_INSTANCE_VISITOR - = new DefaultBindingTargetVisitor() { - @Override public Object visit(InstanceBinding binding) { - return binding.getInstance(); - } + private static final BindingTargetVisitor GET_INSTANCE_VISITOR = + new DefaultBindingTargetVisitor() { + @Override + public Object visit(InstanceBinding binding) { + return binding.getInstance(); + } - @Override protected Object visitOther(Binding binding) { - throw new IllegalArgumentException(); - } - }; + @Override + protected Object visitOther(Binding binding) { + throw new IllegalArgumentException(); + } + }; - /** - * Records the elements executed by {@code modules}. - */ + /** Records the elements executed by {@code modules}. */ public static List getElements(Module... modules) { return getElements(Stage.DEVELOPMENT, Arrays.asList(modules)); } - /** - * Records the elements executed by {@code modules}. - */ + /** Records the elements executed by {@code modules}. */ public static List getElements(Stage stage, Module... modules) { return getElements(stage, Arrays.asList(modules)); } - /** - * Records the elements executed by {@code modules}. - */ + /** Records the elements executed by {@code modules}. */ public static List getElements(Iterable modules) { return getElements(Stage.DEVELOPMENT, modules); } - /** - * Records the elements executed by {@code modules}. - */ + /** Records the elements executed by {@code modules}. */ public static List getElements(Stage stage, Iterable modules) { RecordingBinder binder = new RecordingBinder(stage); for (Module module : modules) { @@ -133,9 +126,7 @@ } } - /** - * Returns the module composed of {@code elements}. - */ + /** Returns the module composed of {@code elements}. */ public static Module getModule(final Iterable elements) { return new ElementsAsModule(elements); } @@ -164,11 +155,13 @@ private final Object source; /** The current modules stack */ private ModuleSource moduleSource = null; + private final SourceProvider sourceProvider; private final Set scanners; /** The binder where exposed bindings will be created */ private final RecordingBinder parent; + private final PrivateElementsImpl privateElements; /** All children private binders, so we can scan through them. */ @@ -180,9 +173,14 @@ this.scanners = Sets.newLinkedHashSet(); this.elements = Lists.newArrayList(); this.source = null; - this.sourceProvider = SourceProvider.DEFAULT_INSTANCE.plusSkippedClasses( - Elements.class, RecordingBinder.class, AbstractModule.class, - ConstantBindingBuilderImpl.class, AbstractBindingBuilder.class, BindingBuilder.class); + this.sourceProvider = + SourceProvider.DEFAULT_INSTANCE.plusSkippedClasses( + Elements.class, + RecordingBinder.class, + AbstractModule.class, + ConstantBindingBuilderImpl.class, + AbstractBindingBuilder.class, + BindingBuilder.class); this.parent = null; this.privateElements = null; this.privateBinders = Lists.newArrayList(); @@ -225,8 +223,8 @@ Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { - elements.add(new InterceptorBinding( - getElementSource(), classMatcher, methodMatcher, interceptors)); + elements.add( + new InterceptorBinding(getElementSource(), classMatcher, methodMatcher, interceptors)); } /*end[AOP]*/ @@ -243,31 +241,37 @@ @Override public void requestInjection(TypeLiteral type, T instance) { - elements.add(new InjectionRequest(getElementSource(), MoreTypes.canonicalizeForKey(type), - instance)); + elements.add( + new InjectionRequest( + getElementSource(), MoreTypes.canonicalizeForKey(type), instance)); } @Override public MembersInjector getMembersInjector(final TypeLiteral typeLiteral) { - final MembersInjectorLookup element = new MembersInjectorLookup(getElementSource(), - MoreTypes.canonicalizeForKey(typeLiteral)); + final MembersInjectorLookup element = + new MembersInjectorLookup( + getElementSource(), MoreTypes.canonicalizeForKey(typeLiteral)); elements.add(element); return element.getMembersInjector(); } + @Override public MembersInjector getMembersInjector(Class type) { return getMembersInjector(TypeLiteral.get(type)); } + @Override public void bindListener(Matcher> typeMatcher, TypeListener listener) { elements.add(new TypeListenerBinding(getElementSource(), listener, typeMatcher)); } - - public void bindListener(Matcher> bindingMatcher, - ProvisionListener... listeners) { + + @Override + public void bindListener( + Matcher> bindingMatcher, ProvisionListener... listeners) { elements.add(new ProvisionListenerBinding(getElementSource(), bindingMatcher, listeners)); } + @Override public void requestStaticInjection(Class... types) { for (Class type : types) { elements.add(new StaticInjectionRequest(getElementSource(), type)); @@ -275,10 +279,9 @@ } /** - * Applies all scanners to the modules we've installed. We skip certain - * PrivateModules because store them in more than one Modules map and only - * want to process them through one of the maps. (They're stored in both - * maps to prevent a module from being installed more than once.) + * Applies all scanners to the modules we've installed. We skip certain PrivateModules because + * store them in more than one Modules map and only want to process them through one of the + * maps. (They're stored in both maps to prevent a module from being installed more than once.) */ void scanForAnnotatedMethods() { for (ModuleAnnotatedMethodScanner scanner : scanners) { @@ -293,7 +296,7 @@ moduleSource = entry.getValue().moduleSource; try { info.binder.install(ProviderMethodsModule.forModule(module, scanner)); - } catch(RuntimeException e) { + } catch (RuntimeException e) { Collection messages = Errors.getMessagesFromThrowable(e); if (!messages.isEmpty()) { elements.addAll(messages); @@ -306,6 +309,7 @@ moduleSource = null; } + @Override public void install(Module module) { if (!modules.containsKey(module)) { RecordingBinder binder = this; @@ -354,64 +358,78 @@ } } + @Override public Stage currentStage() { return stage; } + @Override public void addError(String message, Object... arguments) { elements.add(new Message(getElementSource(), Errors.format(message, arguments))); } + @Override public void addError(Throwable t) { String message = "An exception was caught and reported. Message: " + t.getMessage(); elements.add(new Message(ImmutableList.of((Object) getElementSource()), message, t)); } + @Override public void addError(Message message) { elements.add(message); } + @Override public AnnotatedBindingBuilder bind(Key key) { BindingBuilder builder = new BindingBuilder(this, elements, getElementSource(), MoreTypes.canonicalizeKey(key)); return builder; } + @Override public AnnotatedBindingBuilder bind(TypeLiteral typeLiteral) { return bind(Key.get(typeLiteral)); } + @Override public AnnotatedBindingBuilder bind(Class type) { return bind(Key.get(type)); } + @Override public AnnotatedConstantBindingBuilder bindConstant() { return new ConstantBindingBuilderImpl(this, elements, getElementSource()); } + @Override public Provider getProvider(final Key key) { return getProvider(Dependency.get(key)); } + @Override public Provider getProvider(final Dependency dependency) { - final ProviderLookup element = new ProviderLookup(getElementSource(), dependency); + final ProviderLookup element = new ProviderLookup<>(getElementSource(), dependency); elements.add(element); return element.getProvider(); } + @Override public Provider getProvider(Class type) { return getProvider(Key.get(type)); } - public void convertToTypes(Matcher> typeMatcher, - TypeConverter converter) { + @Override + public void convertToTypes( + Matcher> typeMatcher, TypeConverter converter) { elements.add(new TypeConverterBinding(getElementSource(), typeMatcher, converter)); } - public RecordingBinder withSource(final Object source) { + @Override + public RecordingBinder withSource(final Object source) { return source == this.source ? this : new RecordingBinder(this, source, null); } + @Override public RecordingBinder skipSources(Class... classesToSkip) { // if a source is specified explicitly, we don't need to skip sources if (source != null) { @@ -457,6 +475,7 @@ elements.add(new ModuleAnnotatedMethodScannerBinding(getElementSource(), scanner)); } + @Override public void expose(Key key) { exposeInternal(key); } @@ -473,11 +492,14 @@ private AnnotatedElementBuilder exposeInternal(Key key) { if (privateElements == null) { - addError("Cannot expose %s on a standard binder. " - + "Exposed bindings are only applicable to private binders.", key); + addError( + "Cannot expose %s on a standard binder. " + + "Exposed bindings are only applicable to private binders.", + key); return new AnnotatedElementBuilder() { @Override public void annotatedWith(Class annotationType) {} + @Override public void annotatedWith(Annotation annotation) {} }; @@ -516,9 +538,9 @@ declaringSource = originalSource.getDeclaringSource(); } IncludeStackTraceOption stackTraceOption = getIncludeStackTraceOption(); - if (stackTraceOption == IncludeStackTraceOption.COMPLETE || - (stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE - && declaringSource == null)) { + if (stackTraceOption == IncludeStackTraceOption.COMPLETE + || (stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE + && declaringSource == null)) { callStack = new Throwable().getStackTrace(); } if (stackTraceOption == IncludeStackTraceOption.COMPLETE) { @@ -526,8 +548,8 @@ } if (declaringSource == null) { // So 'source' and 'originalSource' are null otherwise declaringSource has some value - if (stackTraceOption == IncludeStackTraceOption.COMPLETE || - stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE) { + if (stackTraceOption == IncludeStackTraceOption.COMPLETE + || stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE) { // With the above conditions and assignments 'callStack' is non-null declaringSource = sourceProvider.get(callStack); } else { // or if (stackTraceOption == IncludeStackTraceOptions.OFF) @@ -536,14 +558,13 @@ } } // Build the binding call stack - return new ElementSource( - originalSource, declaringSource, moduleSource, partialCallStack); + return new ElementSource(originalSource, declaringSource, moduleSource, partialCallStack); } /** * Removes the {@link #moduleSource} call stack from the beginning of current call stack. It - * also removes the last two elements in order to make {@link #install(Module)} the last call - * in the call stack. + * also removes the last two elements in order to make {@link #install(Module)} the last call in + * the call stack. */ private StackTraceElement[] getPartialCallStack(StackTraceElement[] callStack) { int toSkip = 0; @@ -558,7 +579,8 @@ return partialCallStack; } - @Override public String toString() { + @Override + public String toString() { return "Binder"; } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ElementSource.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ElementSource.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ElementSource.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ElementSource.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,79 +20,76 @@ import com.google.common.collect.ImmutableList; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement; - import java.util.List; /** - * Contains information about where and how an {@link Element element} was - * bound. - *

    - * The {@link #getDeclaringSource() declaring source} refers to a location in - * source code that defines the Guice {@link Element element}. For example, if - * the element is created from a method annotated by {@literal @Provides}, the - * declaring source of element would be the method itself. - *

    - * The {@link #getStackTrace()} refers to the sequence of calls ends at one of - * {@link com.google.inject.Binder} {@code bindXXX()} methods and eventually - * defines the element. Note that {@link #getStackTrace()} lists - * {@link StackTraceElement StackTraceElements} in reverse chronological order. - * The first element (index zero) is the last method call and the last element - * is the first method invocation. By default, the stack trace is not collected. - * The default behavior can be changed by setting the - * {@code guice_include_stack_traces} flag value. The value can be either - * {@code OFF}, {@code ONLY_FOR_DECLARING_SOURCE} or {@code COMPLETE}. Note that - * collecting stack traces for every binding can cause a performance hit when - * the injector is created. - *

    - * The sequence of class names of {@link com.google.inject.Module modules} - * involved in the element creation can be retrieved by - * {@link #getModuleClassNames()}. Similar to {@link #getStackTrace()}, the - * order is reverse chronological. The first module (index 0) is the module that - * installs the {@link Element element}. The last module is the root module. - *

    - * In order to support the cases where a Guice {@link Element element} is - * created from another Guice {@link Element element} (original) (e.g., by - * {@link Element#applyTo}), it also provides a reference to the original - * element source ({@link #getOriginalElementSource()}). + * Contains information about where and how an {@link Element element} was bound. + * + *

    The {@link #getDeclaringSource() declaring source} refers to a location in source code that + * defines the Guice {@link Element element}. For example, if the element is created from a method + * annotated by {@literal @Provides}, the declaring source of element would be the method itself. + * + *

    The {@link #getStackTrace()} refers to the sequence of calls ends at one of {@link + * com.google.inject.Binder} {@code bindXXX()} methods and eventually defines the element. Note that + * {@link #getStackTrace()} lists {@link StackTraceElement StackTraceElements} in reverse + * chronological order. The first element (index zero) is the last method call and the last element + * is the first method invocation. By default, the stack trace is not collected. The default + * behavior can be changed by setting the {@code guice_include_stack_traces} flag value. The value + * can be either {@code OFF}, {@code ONLY_FOR_DECLARING_SOURCE} or {@code COMPLETE}. Note that + * collecting stack traces for every binding can cause a performance hit when the injector is + * created. + * + *

    The sequence of class names of {@link com.google.inject.Module modules} involved in the + * element creation can be retrieved by {@link #getModuleClassNames()}. Similar to {@link + * #getStackTrace()}, the order is reverse chronological. The first module (index 0) is the module + * that installs the {@link Element element}. The last module is the root module. + * + *

    In order to support the cases where a Guice {@link Element element} is created from another + * Guice {@link Element element} (original) (e.g., by {@link Element#applyTo}), it also provides a + * reference to the original element source ({@link #getOriginalElementSource()}). * * @since 4.0 */ public final class ElementSource { - /** + /** * The {@link ElementSource source} of element that this element created from (if there is any), * otherwise {@code null}. */ final ElementSource originalElementSource; - + /** The {@link ModuleSource source} of module creates the element. */ final ModuleSource moduleSource; - - /** + + /** * The partial call stack that starts at the last module {@link Module#Configure(Binder) * configure(Binder)} call. The value is empty if stack trace collection is off. */ final InMemoryStackTraceElement[] partialCallStack; - - /** - * Refers to a single location in source code that causes the element creation. It can be any - * object such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, - * etc. For example, if the element is created from a method annotated by {@literal @Provides}, + + /** + * Refers to a single location in source code that causes the element creation. It can be any + * object such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, + * etc. For example, if the element is created from a method annotated by {@literal @Provides}, * the declaring source of element would be the method itself. */ final Object declaringSource; /** - * Creates a new {@ElementSource} from the given parameters. + * Creates a new {@ElementSource} from the given parameters. + * * @param originalElementSource The source of element that this element created from (if there is - * any), otherwise {@code null}. + * any), otherwise {@code null}. * @param declaringSource the source (in)directly declared the element. * @param moduleSource the moduleSource when the element is bound - * @param partialCallStack the partial call stack from the top module to where the element is - * bound + * @param partialCallStack the partial call stack from the top module to where the element is + * bound */ - ElementSource(/* @Nullable */ ElementSource originalSource, Object declaringSource, - ModuleSource moduleSource, StackTraceElement[] partialCallStack) { + ElementSource( + /* @Nullable */ ElementSource originalSource, + Object declaringSource, + ModuleSource moduleSource, + StackTraceElement[] partialCallStack) { Preconditions.checkNotNull(declaringSource, "declaringSource cannot be null."); Preconditions.checkNotNull(moduleSource, "moduleSource cannot be null."); Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null."); @@ -101,7 +98,7 @@ this.moduleSource = moduleSource; this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack); } - + /** * Returns the {@link ElementSource} of the element this was created or copied from. If this was * not created or copied from another element, returns {@code null}. @@ -109,22 +106,22 @@ public ElementSource getOriginalElementSource() { return originalElementSource; } - + /** - * Returns a single location in source code that defines the element. It can be any object - * such as {@link java.lang.reflect.Constructor}, {@link java.lang.reflect.Method}, - * {@link java.lang.reflect.Field}, {@link StackTraceElement}, etc. For - * example, if the element is created from a method annotated by {@literal @Provides}, the - * declaring source of element would be the method itself. + * Returns a single location in source code that defines the element. It can be any object such as + * {@link java.lang.reflect.Constructor}, {@link java.lang.reflect.Method}, {@link + * java.lang.reflect.Field}, {@link StackTraceElement}, etc. For example, if the element is + * created from a method annotated by {@literal @Provides}, the declaring source of element would + * be the method itself. */ public Object getDeclaringSource() { return declaringSource; } - + /** - * Returns the class names of modules involved in creating this {@link Element}. The first - * element (index 0) is the class name of module that defined the element, and the last element - * is the class name of root module. + * Returns the class names of modules involved in creating this {@link Element}. The first element + * (index 0) is the class name of module that defined the element, and the last element is the + * class name of root module. */ public List getModuleClassNames() { return moduleSource.getModuleClassNames(); @@ -134,18 +131,18 @@ * Returns the position of {@link com.google.inject.Module#configure configure(Binder)} method * call in the {@link #getStackTrace stack trace} for modules that their classes returned by * {@link #getModuleClassNames}. For example, if the stack trace looks like the following: - *

    - * {@code - * 0 - Binder.bind(), - * 1 - ModuleTwo.configure(), - * 2 - Binder.install(), - * 3 - ModuleOne.configure(), - * 4 - theRest(). - * } - *

    - * 1 and 3 are returned. - *

    - * In the cases where stack trace is not available (i.e., the stack trace was not collected), + * + *

      + *
    1. {@code Binder.bind()} + *
    2. {@code ModuleTwo.configure()} + *
    3. {@code Binder.install()} + *
    4. {@code ModuleOne.configure()} + *
    5. {@code theRest(). + *
    + * + *

    1 and 3 are returned. + * + *

    In the cases where stack trace is not available (i.e., the stack trace was not collected), * it returns -1 for all module positions. */ public List getModuleConfigurePositionsInStackTrace() { @@ -164,11 +161,11 @@ /** * Returns the sequence of method calls that ends at one of {@link com.google.inject.Binder} - * {@code bindXXX()} methods and eventually defines the element. Note that - * {@link #getStackTrace} lists {@link StackTraceElement StackTraceElements} in reverse - * chronological order. The first element (index zero) is the last method call and the last - * element is the first method invocation. In the cases where stack trace is not available - * (i.e.,the stack trace was not collected), it returns an empty array. + * {@code bindXXX()} methods and eventually defines the element. Note that {@link #getStackTrace} + * lists {@link StackTraceElement StackTraceElements} in reverse chronological order. The first + * element (index zero) is the last method call and the last element is the first method + * invocation. In the cases where stack trace is not available (i.e.,the stack trace was not + * collected), it returns an empty array. */ public StackTraceElement[] getStackTrace() { int modulesCallStackSize = moduleSource.getStackTraceSize(); @@ -176,15 +173,16 @@ int size = moduleSource.getStackTraceSize() + chunkSize; StackTraceElement[] callStack = new StackTraceElement[size]; System.arraycopy( - StackTraceElements.convertToStackTraceElement(partialCallStack), 0, callStack, 0, + StackTraceElements.convertToStackTraceElement(partialCallStack), + 0, + callStack, + 0, chunkSize); System.arraycopy(moduleSource.getStackTrace(), 0, callStack, chunkSize, modulesCallStackSize); return callStack; } - /** - * Returns {@code getDeclaringSource().toString()} value. - */ + /** Returns {@code getDeclaringSource().toString()} value. */ @Override public String toString() { return getDeclaringSource().toString(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ElementVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ElementVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ElementVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ElementVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,59 +23,42 @@ /** * Visit elements. * - * @param any type to be returned by the visit method. Use {@link Void} with - * {@code return null} if no return type is needed. - * + * @param any type to be returned by the visit method. Use {@link Void} with {@code return null} + * if no return type is needed. * @since 2.0 */ public interface ElementVisitor { /** - * Visit a mapping from a key (type and optional annotation) to the strategy for getting - * instances of the type. + * Visit a mapping from a key (type and optional annotation) to the strategy for getting instances + * of the type. */ V visit(Binding binding); /*if[AOP]*/ - /** - * Visit a registration of interceptors for matching methods of matching classes. - */ + /** Visit a registration of interceptors for matching methods of matching classes. */ V visit(InterceptorBinding binding); /*end[AOP]*/ - /** - * Visit a registration of a scope annotation with the scope that implements it. - */ + /** Visit a registration of a scope annotation with the scope that implements it. */ V visit(ScopeBinding binding); - /** - * Visit a registration of type converters for matching target types. - */ + /** Visit a registration of type converters for matching target types. */ V visit(TypeConverterBinding binding); - /** - * Visit a request to inject the instance fields and methods of an instance. - */ + /** Visit a request to inject the instance fields and methods of an instance. */ V visit(InjectionRequest request); - /** - * Visit a request to inject the static fields and methods of type. - */ + /** Visit a request to inject the static fields and methods of type. */ V visit(StaticInjectionRequest request); - /** - * Visit a lookup of the provider for a type. - */ + /** Visit a lookup of the provider for a type. */ V visit(ProviderLookup lookup); - /** - * Visit a lookup of the members injector. - */ + /** Visit a lookup of the members injector. */ V visit(MembersInjectorLookup lookup); - /** - * Visit an error message and the context in which it occured. - */ + /** Visit an error message and the context in which it occured. */ V visit(Message message); /** @@ -84,33 +67,33 @@ */ V visit(PrivateElements elements); - /** - * Visit an injectable type listener binding. - */ + /** Visit an injectable type listener binding. */ V visit(TypeListenerBinding binding); - + /** * Visit a provision listener binding. + * + * @since 4.0 */ V visit(ProvisionListenerBinding binding); - + /** * Visit a require explicit bindings command. - * + * * @since 3.0 */ V visit(RequireExplicitBindingsOption option); - + /** * Visit a disable circular proxies command. - * + * * @since 3.0 */ V visit(DisableCircularProxiesOption option); - + /** * Visit a require explicit {@literal @}{@link Inject} command. - * + * * @since 4.0 */ V visit(RequireAtInjectOnConstructorsOption option); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ExposedBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ExposedBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ExposedBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ExposedBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,13 +27,10 @@ */ public interface ExposedBinding extends Binding, HasDependencies { - /** - * Returns the enclosed environment that holds the original binding. - */ + /** Returns the enclosed environment that holds the original binding. */ PrivateElements getPrivateElements(); - /** - * Unsupported. Always throws {@link UnsupportedOperationException}. - */ + /** Unsupported. Always throws {@link UnsupportedOperationException}. */ + @Override void applyTo(Binder binder); -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/HasDependencies.java sisu-guice-4.2.0/core/src/com/google/inject/spi/HasDependencies.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/HasDependencies.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/HasDependencies.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,7 @@ * Returns the known dependencies for this type. If this has dependencies whose values are not * known statically, a dependency for the {@link com.google.inject.Injector Injector} will be * included in the returned set. - * + * * @return a possibly empty set */ Set> getDependencies(); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/InjectionPoint.java sisu-guice-4.2.0/core/src/com/google/inject/spi/InjectionPoint.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/InjectionPoint.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/InjectionPoint.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +18,11 @@ import static com.google.inject.internal.MoreTypes.getRawType; +import com.google.common.collect.ComparisonChain; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Key; @@ -30,7 +32,6 @@ import com.google.inject.internal.ErrorsException; import com.google.inject.internal.Nullability; import com.google.inject.internal.util.Classes; - import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; @@ -58,7 +59,7 @@ * @since 2.0 */ public final class InjectionPoint { - + private static final Logger logger = Logger.getLogger(InjectionPoint.class.getName()); private final boolean optional; @@ -77,8 +78,8 @@ this.member = constructor; this.declaringType = declaringType; this.optional = false; - this.dependencies = forMember( - constructor, declaringType, constructor.getParameterAnnotations()); + this.dependencies = + forMember(constructor, declaringType, constructor.getParameterAnnotations()); } InjectionPoint(TypeLiteral declaringType, Field field, boolean optional) { @@ -99,21 +100,21 @@ } errors.throwConfigurationExceptionIfErrorsExist(); - this.dependencies = ImmutableList.>of( - newDependency(key, Nullability.allowsNull(annotations), -1)); + this.dependencies = + ImmutableList.>of( + newDependency(key, Nullability.allowsNull(annotations), -1)); } - private ImmutableList> forMember(Member member, TypeLiteral type, - Annotation[][] paramterAnnotations) { + private ImmutableList> forMember( + Member member, TypeLiteral type, Annotation[][] paramterAnnotations) { Errors errors = new Errors(member); - Iterator annotationsIterator = Arrays.asList(paramterAnnotations).iterator(); List> dependencies = Lists.newArrayList(); int index = 0; for (TypeLiteral parameterType : type.getParameterTypes(member)) { try { - Annotation[] parameterAnnotations = annotationsIterator.next(); + Annotation[] parameterAnnotations = paramterAnnotations[index]; Key key = Annotations.getKey(parameterType, member, parameterAnnotations, errors); dependencies.add(newDependency(key, Nullability.allowsNull(parameterAnnotations), index)); index++; @@ -133,9 +134,7 @@ return new Dependency(this, key, allowsNull, parameterIndex); } - /** - * Returns the injected constructor, field, or method. - */ + /** Returns the injected constructor, field, or method. */ public Member getMember() { // TODO: Don't expose the original member (which probably has setAccessible(true)). return member; @@ -161,38 +160,41 @@ public boolean isOptional() { return optional; } - + /** * Returns true if the element is annotated with {@literal @}{@link Toolable}. - * + * * @since 3.0 */ public boolean isToolable() { - return ((AnnotatedElement)member).isAnnotationPresent(Toolable.class); + return ((AnnotatedElement) member).isAnnotationPresent(Toolable.class); } /** * Returns the generic type that defines this injection point. If the member exists on a * parameterized type, the result will include more type information than the member's {@link * Member#getDeclaringClass() raw declaring class}. - * + * * @since 3.0 */ public TypeLiteral getDeclaringType() { return declaringType; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { return o instanceof InjectionPoint && member.equals(((InjectionPoint) o).member) && declaringType.equals(((InjectionPoint) o).declaringType); } - @Override public int hashCode() { + @Override + public int hashCode() { return member.hashCode() ^ declaringType.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return Classes.toString(member); } @@ -202,7 +204,6 @@ * type literal. * * @param constructor any single constructor present on {@code type}. - * * @since 3.0 */ public static InjectionPoint forConstructor(Constructor constructor) { @@ -214,7 +215,6 @@ * * @param constructor any single constructor present on {@code type}. * @param type the concrete type that defines {@code constructor}. - * * @since 3.0 */ public static InjectionPoint forConstructor( @@ -307,13 +307,11 @@ } /** - * Returns a new injection point for the specified method of {@code type}. - * This is useful for extensions that need to build dependency graphs from - * arbitrary methods. + * Returns a new injection point for the specified method of {@code type}. This is useful for + * extensions that need to build dependency graphs from arbitrary methods. * * @param method any single method present on {@code type}. * @param type the concrete type that defines {@code method}. - * * @since 4.0 */ public static InjectionPoint forMethod(Method method, TypeLiteral type) { @@ -324,25 +322,25 @@ * Returns all static method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as - * a field with multiple binding annotations. The exception's {@link - * ConfigurationException#getPartialValue() partial value} is a {@code Set} - * of the valid injection points. + * a field with multiple binding annotations. The exception's {@link + * ConfigurationException#getPartialValue() partial value} is a {@code Set} of + * the valid injection points. */ public static Set forStaticMethodsAndFields(TypeLiteral type) { Errors errors = new Errors(); - + Set result; - + if (type.getRawType().isInterface()) { errors.staticInjectionOnInterface(type.getRawType()); result = null; } else { result = getInjectionPoints(type, true, errors); } - + if (errors.hasErrors()) { throw new ConfigurationException(errors.getMessages()).withPartialValue(result); } @@ -353,12 +351,12 @@ * Returns all static method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as - * a field with multiple binding annotations. The exception's {@link - * ConfigurationException#getPartialValue() partial value} is a {@code Set} - * of the valid injection points. + * a field with multiple binding annotations. The exception's {@link + * ConfigurationException#getPartialValue() partial value} is a {@code Set} of + * the valid injection points. */ public static Set forStaticMethodsAndFields(Class type) { return forStaticMethodsAndFields(TypeLiteral.get(type)); @@ -368,12 +366,12 @@ * Returns all instance method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as - * a field with multiple binding annotations. The exception's {@link - * ConfigurationException#getPartialValue() partial value} is a {@code Set} - * of the valid injection points. + * a field with multiple binding annotations. The exception's {@link + * ConfigurationException#getPartialValue() partial value} is a {@code Set} of + * the valid injection points. */ public static Set forInstanceMethodsAndFields(TypeLiteral type) { Errors errors = new Errors(); @@ -388,23 +386,22 @@ * Returns all instance method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as - * a field with multiple binding annotations. The exception's {@link - * ConfigurationException#getPartialValue() partial value} is a {@code Set} - * of the valid injection points. + * a field with multiple binding annotations. The exception's {@link + * ConfigurationException#getPartialValue() partial value} is a {@code Set} of + * the valid injection points. */ public static Set forInstanceMethodsAndFields(Class type) { return forInstanceMethodsAndFields(TypeLiteral.get(type)); } - /** - * Returns true if the binding annotation is in the wrong place. - */ + /** Returns true if the binding annotation is in the wrong place. */ private static boolean checkForMisplacedBindingAnnotations(Member member, Errors errors) { - Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation( - errors, member, ((AnnotatedElement) member).getAnnotations()); + Annotation misplacedBindingAnnotation = + Annotations.findBindingAnnotation( + errors, member, ((AnnotatedElement) member).getAnnotations()); if (misplacedBindingAnnotation == null) { return false; } @@ -424,10 +421,8 @@ return true; } - /** - * Node in the doubly-linked list of injectable members (fields and methods). - */ - static abstract class InjectableMember { + /** Node in the doubly-linked list of injectable members (fields and methods). */ + abstract static class InjectableMember { final TypeLiteral declaringType; final boolean optional; final boolean jsr330; @@ -452,8 +447,8 @@ static class InjectableField extends InjectableMember { final Field field; - InjectableField(TypeLiteral declaringType, Field field, - Annotation atInject) { + + InjectableField(TypeLiteral declaringType, Field field, Annotation atInject) { super(declaringType, atInject); this.field = field; } @@ -467,13 +462,12 @@ static class InjectableMethod extends InjectableMember { final Method method; /** - * true if this method overrode a method that was annotated - * with com.google.inject.Inject. used to allow different - * override behavior for guice inject vs javax.inject.Inject + * true if this method overrode a method that was annotated with com.google.inject.Inject. used + * to allow different override behavior for guice inject vs javax.inject.Inject */ boolean overrodeGuiceInject; - InjectableMethod(TypeLiteral declaringType, Method method, - Annotation atInject) { + + InjectableMethod(TypeLiteral declaringType, Method method, Annotation atInject) { super(declaringType, atInject); this.method = method; } @@ -493,9 +487,7 @@ return a == null ? member.getAnnotation(Inject.class) : a; } - /** - * Linked list of injectable members. - */ + /** Linked list of injectable members. */ static class InjectableMembers { InjectableMember head; InjectableMember tail; @@ -555,23 +547,19 @@ Signature lastSignature; /** - * Removes a method overridden by the given method, if present. In order to - * remain backwards compatible with prior Guice versions, this will *not* - * remove overridden methods if 'alwaysRemove' is false and the overridden - * signature was annotated with a com.google.inject.Inject. - * - * @param method - * The method used to determine what is overridden and should be - * removed. - * @param alwaysRemove - * true if overridden methods should be removed even if they were - * guice @Inject - * @param injectableMethod - * if this method overrode any guice @Inject methods, - * {@link InjectableMethod#overrodeGuiceInject} is set to true + * Removes a method overridden by the given method, if present. In order to remain backwards + * compatible with prior Guice versions, this will *not* remove overridden methods if + * 'alwaysRemove' is false and the overridden signature was annotated with a + * com.google.inject.Inject. + * + * @param method The method used to determine what is overridden and should be removed. + * @param alwaysRemove true if overridden methods should be removed even if they were + * guice @Inject + * @param injectableMethod if this method overrode any guice @Inject methods, {@link + * InjectableMethod#overrodeGuiceInject} is set to true */ - boolean removeIfOverriddenBy(Method method, boolean alwaysRemove, - InjectableMethod injectableMethod) { + boolean removeIfOverriddenBy( + Method method, boolean alwaysRemove, InjectableMethod injectableMethod) { if (position == Position.TOP) { // If we're at the top of the hierarchy, there's nothing to override. return false; @@ -580,13 +568,18 @@ if (bySignature == null) { // We encountered a method in a subclass. Time to index the // methods in the parent class. - bySignature = new HashMap>(); - for (InjectableMember member = injectableMembers.head; member != null; + bySignature = new HashMap<>(); + for (InjectableMember member = injectableMembers.head; + member != null; member = member.next) { - if (!(member instanceof InjectableMethod)) continue; + if (!(member instanceof InjectableMethod)) { + continue; + } InjectableMethod im = (InjectableMethod) member; - if (im.isFinal()) continue; - List methods = new ArrayList(); + if (im.isFinal()) { + continue; + } + List methods = new ArrayList<>(); methods.add(im); bySignature.put(new Signature(im.method), methods); } @@ -597,19 +590,18 @@ List methods = bySignature.get(signature); boolean removed = false; if (methods != null) { - for (Iterator iterator = methods.iterator(); - iterator.hasNext();) { + for (Iterator iterator = methods.iterator(); iterator.hasNext(); ) { InjectableMethod possiblyOverridden = iterator.next(); if (overrides(method, possiblyOverridden.method)) { boolean wasGuiceInject = - !possiblyOverridden.jsr330 || possiblyOverridden.overrodeGuiceInject; - if(injectableMethod != null) { + !possiblyOverridden.jsr330 || possiblyOverridden.overrodeGuiceInject; + if (injectableMethod != null) { injectableMethod.overrodeGuiceInject = wasGuiceInject; } // Only actually remove the methods if we want to force // remove or if the signature never specified @com.google.inject.Inject // somewhere. - if(alwaysRemove || !wasGuiceInject) { + if (alwaysRemove || !wasGuiceInject) { removed = true; iterator.remove(); injectableMembers.remove(possiblyOverridden); @@ -621,23 +613,25 @@ } /** - * Adds the given method to the list of injection points. Keeps track of it in this index - * in case it gets overridden. + * Adds the given method to the list of injection points. Keeps track of it in this index in + * case it gets overridden. */ void add(InjectableMethod injectableMethod) { injectableMembers.add(injectableMethod); - if (position == Position.BOTTOM - || injectableMethod.isFinal()) { + if (position == Position.BOTTOM || injectableMethod.isFinal()) { // This method can't be overridden, so there's no need to index it. return; } if (bySignature != null) { // Try to reuse the signature we created during removal - Signature signature = injectableMethod.method == lastMethod - ? lastSignature : new Signature(injectableMethod.method); + @SuppressWarnings("ReferenceEquality") + Signature signature = + injectableMethod.method == lastMethod + ? lastSignature + : new Signature(injectableMethod.method); List methods = bySignature.get(signature); if (methods == null) { - methods = new ArrayList(); + methods = new ArrayList<>(); bySignature.put(signature, methods); } methods.add(injectableMethod); @@ -648,13 +642,14 @@ /** * Returns an ordered, immutable set of injection points for the given type. Members in * superclasses come before members in subclasses. Within a class, fields come before methods. - * Overridden methods are filtered out. + * Overridden methods are filtered out. The order of fields/methods within a class is consistent + * but undefined. * * @param statics true is this method should return static members, false for instance members * @param errors used to record errors */ - private static Set getInjectionPoints(final TypeLiteral type, - boolean statics, Errors errors) { + private static Set getInjectionPoints( + final TypeLiteral type, boolean statics, Errors errors) { InjectableMembers injectableMembers = new InjectableMembers(); OverrideIndex overrideIndex = null; @@ -672,7 +667,7 @@ TypeLiteral current = hierarchy.get(i); - for (Field field : current.getRawType().getDeclaredFields()) { + for (Field field : getDeclaredFields(current)) { if (Modifier.isStatic(field.getModifiers()) == statics) { Annotation atInject = getAtInject(field); if (atInject != null) { @@ -685,22 +680,25 @@ } } - for (Method method : current.getRawType().getDeclaredMethods()) { + for (Method method : getDeclaredMethods(current)) { if (isEligibleForInjection(method, statics)) { Annotation atInject = getAtInject(method); if (atInject != null) { - InjectableMethod injectableMethod = new InjectableMethod( - current, method, atInject); + InjectableMethod injectableMethod = new InjectableMethod(current, method, atInject); if (checkForMisplacedBindingAnnotations(method, errors) || !isValidMethod(injectableMethod, errors)) { if (overrideIndex != null) { - boolean removed = overrideIndex.removeIfOverriddenBy(method, false, injectableMethod); - if(removed) { - logger.log(Level.WARNING, "Method: {0} is not a valid injectable method (" - + "because it either has misplaced binding annotations " - + "or specifies type parameters) but is overriding a method that is valid. " - + "Because it is not valid, the method will not be injected. " - + "To fix this, make the method a valid injectable method.", method); + boolean removed = + overrideIndex.removeIfOverriddenBy(method, false, injectableMethod); + if (removed) { + logger.log( + Level.WARNING, + "Method: {0} is not a valid injectable method (" + + "because it either has misplaced binding annotations " + + "or specifies type parameters) but is overriding a method that is " + + "valid. Because it is not valid, the method will not be injected. " + + "To fix this, make the method a valid injectable method.", + method); } } continue; @@ -717,20 +715,23 @@ */ overrideIndex = new OverrideIndex(injectableMembers); } else { - // Forcibly remove the overriden method, otherwise we'll inject + // Forcibly remove the overridden method, otherwise we'll inject // it twice. overrideIndex.removeIfOverriddenBy(method, true, injectableMethod); } overrideIndex.add(injectableMethod); } } else { - if(overrideIndex != null) { + if (overrideIndex != null) { boolean removed = overrideIndex.removeIfOverriddenBy(method, false, null); - if(removed) { - logger.log(Level.WARNING, "Method: {0} is not annotated with @Inject but " - + "is overriding a method that is annotated with @javax.inject.Inject. Because " - + "it is not annotated with @Inject, the method will not be injected. " - + "To fix this, annotate the method with @Inject.", method); + if (removed) { + logger.log( + Level.WARNING, + "Method: {0} is not annotated with @Inject but " + + "is overriding a method that is annotated with @javax.inject.Inject." + + "Because it is not annotated with @Inject, the method will not be " + + "injected. To fix this, annotate the method with @Inject.", + method); } } } @@ -743,8 +744,7 @@ } ImmutableSet.Builder builder = ImmutableSet.builder(); - for (InjectableMember im = injectableMembers.head; im != null; - im = im.next) { + for (InjectableMember im = injectableMembers.head; im != null; im = im.next) { try { builder.add(im.toInjectionPoint()); } catch (ConfigurationException ignorable) { @@ -756,22 +756,86 @@ return builder.build(); } - /** - * Returns true if the method is eligible to be injected. This is different than - * {@link #isValidMethod}, because ineligibility will not drop a method - * from being injected if a superclass was eligible & valid. - * Bridge & synthetic methods are excluded from eligibility for two reasons: - * - *

    Prior to Java8, javac would generate these methods in subclasses without - * annotations, which means this would accidentally stop injecting a method - * annotated with {@link javax.inject.Inject}, since the spec says to stop - * injecting if a subclass isn't annotated with it. - * - *

    Starting at Java8, javac copies the annotations to the generated subclass - * method, except it leaves out the generic types. If this considered it a valid - * injectable method, this would eject the parent's overridden method that had the - * proper generic types, and would use invalid injectable parameters as a result. - * + private static Field[] getDeclaredFields(TypeLiteral type) { + Field[] fields = type.getRawType().getDeclaredFields(); + Arrays.sort(fields, FIELD_ORDERING); + return fields; + } + + private static Method[] getDeclaredMethods(TypeLiteral type) { + Method[] methods = type.getRawType().getDeclaredMethods(); + Arrays.sort(methods, METHOD_ORDERING); + return methods; + } + + /** + * An ordering suitable for comparing two classes if they are loaded by the same classloader + * + *

    Within a single classloader there can only be one class with a given name, so we just + * compare the names. + */ + private static final Ordering> CLASS_ORDERING = + new Ordering>() { + @Override + public int compare(Class o1, Class o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + /** + * An ordering suitable for comparing two fields if they are owned by the same class. + * + *

    Within a single class it is sufficent to compare the non-generic field signature which + * consists of the field name and type. + */ + private static final Ordering FIELD_ORDERING = + new Ordering() { + @Override + public int compare(Field left, Field right) { + return ComparisonChain.start() + .compare(left.getName(), right.getName()) + .compare(left.getType(), right.getType(), CLASS_ORDERING) + .result(); + } + }; + + /** + * An ordering suitable for comparing two methods if they are owned by the same class. + * + *

    Within a single class it is sufficient to compare the non-generic method signature which + * consists of the name, return type and parameter types. + */ + private static final Ordering METHOD_ORDERING = + new Ordering() { + @Override + public int compare(Method left, Method right) { + return ComparisonChain.start() + .compare(left.getName(), right.getName()) + .compare(left.getReturnType(), right.getReturnType(), CLASS_ORDERING) + .compare( + Arrays.asList(left.getParameterTypes()), + Arrays.asList(right.getParameterTypes()), + CLASS_ORDERING.lexicographical()) + .result(); + } + }; + + /** + * Returns true if the method is eligible to be injected. This is different than {@link + * #isValidMethod}, because ineligibility will not drop a method from being injected if a + * superclass was eligible & valid. Bridge & synthetic methods are excluded from eligibility for + * two reasons: + * + *

    Prior to Java8, javac would generate these methods in subclasses without annotations, which + * means this would accidentally stop injecting a method annotated with {@link + * javax.inject.Inject}, since the spec says to stop injecting if a subclass isn't annotated with + * it. + * + *

    Starting at Java8, javac copies the annotations to the generated subclass method, except it + * leaves out the generic types. If this considered it a valid injectable method, this would eject + * the parent's overridden method that had the proper generic types, and would use invalid + * injectable parameters as a result. + * *

    The fix for both is simply to ignore these synthetic bridge methods. */ private static boolean isEligibleForInjection(Method method, boolean statics) { @@ -780,8 +844,7 @@ && !method.isSynthetic(); } - private static boolean isValidMethod(InjectableMethod injectableMethod, - Errors errors) { + private static boolean isValidMethod(InjectableMethod injectableMethod, Errors errors) { boolean result = true; if (injectableMethod.jsr330) { Method method = injectableMethod.method; @@ -798,7 +861,7 @@ } private static List> hierarchyFor(TypeLiteral type) { - List> hierarchy = new ArrayList>(); + List> hierarchy = new ArrayList<>(); TypeLiteral current = type; while (current.getRawType() != Object.class) { hierarchy.add(current); @@ -824,9 +887,7 @@ return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage()); } - /** - * A method signature. Used to handle method overridding. - */ + /** A method signature. Used to handle method overridding. */ static class Signature { final String name; @@ -845,11 +906,13 @@ this.hash = h; } - @Override public int hashCode() { + @Override + public int hashCode() { return this.hash; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (!(o instanceof Signature)) { return false; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/InjectionRequest.java sisu-guice-4.2.0/core/src/com/google/inject/spi/InjectionRequest.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/InjectionRequest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/InjectionRequest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,13 +21,13 @@ import com.google.inject.Binder; import com.google.inject.ConfigurationException; import com.google.inject.TypeLiteral; - import java.util.Set; /** * A request to inject the instance fields and methods of an instance. Requests are created * explicitly in a module using {@link com.google.inject.Binder#requestInjection(Object) * requestInjection()} statements: + * *

      *     requestInjection(serviceInstance);
    * @@ -46,6 +46,7 @@ this.instance = checkNotNull(instance, "instance"); } + @Override public Object getSource() { return source; } @@ -63,21 +64,23 @@ * this request. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on the class of {@code - * instance}, such as a field with multiple binding annotations. The exception's {@link - * ConfigurationException#getPartialValue() partial value} is a {@code Set} - * of the valid injection points. + * instance}, such as a field with multiple binding annotations. The exception's {@link + * ConfigurationException#getPartialValue() partial value} is a {@code Set} of + * the valid injection points. */ public Set getInjectionPoints() throws ConfigurationException { return InjectionPoint.forInstanceMethodsAndFields(instance.getClass()); } + @Override public R acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } + @Override public void applyTo(Binder binder) { binder.withSource(getSource()).requestInjection(type, instance); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/InstanceBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/InstanceBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/InstanceBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/InstanceBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.spi; import com.google.inject.Binding; - import java.util.Set; /** @@ -28,9 +27,7 @@ */ public interface InstanceBinding extends Binding, HasDependencies { - /** - * Returns the user-supplied instance. - */ + /** Returns the user-supplied instance. */ T getInstance(); /** @@ -40,5 +37,4 @@ * @return a possibly empty set */ Set getInjectionPoints(); - } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/InterceptorBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/InterceptorBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/InterceptorBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/InterceptorBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,16 +21,15 @@ import com.google.common.collect.ImmutableList; import com.google.inject.Binder; import com.google.inject.matcher.Matcher; - -import org.aopalliance.intercept.MethodInterceptor; - import java.lang.reflect.Method; import java.util.List; +import org.aopalliance.intercept.MethodInterceptor; /** * Registration of interceptors for matching methods of matching classes. Instances are created - * explicitly in a module using {@link com.google.inject.Binder#bindInterceptor( - * Matcher, Matcher, MethodInterceptor[]) bindInterceptor()} statements: + * explicitly in a module using {@link com.google.inject.Binder#bindInterceptor( Matcher, Matcher, + * MethodInterceptor[]) bindInterceptor()} statements: + * *
      *     bindInterceptor(Matchers.subclassesOf(MyAction.class),
      *         Matchers.annotatedWith(Transactional.class),
    @@ -59,6 +58,7 @@
         this.interceptors = ImmutableList.copyOf(interceptors);
       }
     
    +  @Override
       public Object getSource() {
         return source;
       }
    @@ -75,12 +75,18 @@
         return interceptors;
       }
     
    +  @Override
       public  T acceptVisitor(ElementVisitor visitor) {
         return visitor.visit(this);
       }
     
    +  @Override
       public void applyTo(Binder binder) {
    -    binder.withSource(getSource()).bindInterceptor(classMatcher, methodMatcher,
    -        interceptors.toArray(new MethodInterceptor[interceptors.size()]));
    +    binder
    +        .withSource(getSource())
    +        .bindInterceptor(
    +            classMatcher,
    +            methodMatcher,
    +            interceptors.toArray(new MethodInterceptor[interceptors.size()]));
       }
     }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/LinkedKeyBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/LinkedKeyBinding.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/LinkedKeyBinding.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/LinkedKeyBinding.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2008 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -32,5 +32,4 @@
        * injector using {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.
        */
       Key getLinkedKey();
    -
    -}
    \ No newline at end of file
    +}
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/MembersInjectorLookup.java sisu-guice-4.2.0/core/src/com/google/inject/spi/MembersInjectorLookup.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/MembersInjectorLookup.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/MembersInjectorLookup.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2009 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -26,6 +26,7 @@
     /**
      * A lookup of the members injector for a type. Lookups are created explicitly in a module using
      * {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements:
    + *
      * 
      *     MembersInjector<PaymentService> membersInjector
      *         = getMembersInjector(PaymentService.class);
    @@ -44,17 +45,17 @@ this.type = checkNotNull(type, "type"); } + @Override public Object getSource() { return source; } - /** - * Gets the type containing the members to be injected. - */ + /** Gets the type containing the members to be injected. */ public TypeLiteral getType() { return type; } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } @@ -69,14 +70,15 @@ this.delegate = checkNotNull(delegate, "delegate"); } + @Override public void applyTo(Binder binder) { initializeDelegate(binder.withSource(getSource()).getMembersInjector(type)); } /** - * Returns the delegate members injector, or {@code null} if it has not yet been initialized. - * The delegate will be initialized when this element is processed, or otherwise used to create - * an injector. + * Returns the delegate members injector, or {@code null} if it has not yet been initialized. The + * delegate will be initialized when this element is processed, or otherwise used to create an + * injector. */ public MembersInjector getDelegate() { return delegate; @@ -89,15 +91,20 @@ */ public MembersInjector getMembersInjector() { return new MembersInjector() { + @Override public void injectMembers(T instance) { - checkState(delegate != null, - "This MembersInjector cannot be used until the Injector has been created."); - delegate.injectMembers(instance); + MembersInjector local = delegate; + if (local == null) { + throw new IllegalStateException( + "This MembersInjector cannot be used until the Injector has been created."); + } + local.injectMembers(instance); } - @Override public String toString() { + @Override + public String toString() { return "MembersInjector<" + type + ">"; } }; } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/Message.java sisu-guice-4.2.0/core/src/com/google/inject/spi/Message.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/Message.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/Message.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.inject.Binder; import com.google.inject.internal.Errors; import com.google.inject.internal.util.SourceProvider; - import java.io.ObjectStreamException; import java.io.Serializable; import java.util.List; @@ -32,6 +31,7 @@ * An error message and the context in which it occured. Messages are usually created internally by * Guice and its extensions. Messages can be created explicitly in a module using {@link * com.google.inject.Binder#addError(Throwable) addError()} statements: + * *
      *     try {
      *       bindPropertiesFromFile();
    @@ -46,18 +46,14 @@
       private final Throwable cause;
       private final List sources;
     
    -  /**
    -   * @since 2.0
    -   */
    +  /** @since 2.0 */
       public Message(List sources, String message, Throwable cause) {
         this.sources = ImmutableList.copyOf(sources);
         this.message = checkNotNull(message, "message");
         this.cause = cause;
       }
     
    -  /**
    -   * @since 4.0
    -   */
    +  /** @since 4.0 */
       public Message(String message, Throwable cause) {
         this(ImmutableList.of(), message, cause);
       }
    @@ -70,6 +66,7 @@
         this(ImmutableList.of(), message, null);
       }
     
    +  @Override
       public String getSource() {
         return sources.isEmpty()
             ? SourceProvider.UNKNOWN_SOURCE.toString()
    @@ -81,21 +78,20 @@
         return sources;
       }
     
    -  /**
    -   * Gets the error message text.
    -   */
    +  /** Gets the error message text. */
       public String getMessage() {
         return message;
       }
     
       /** @since 2.0 */
    +  @Override
       public  T acceptVisitor(ElementVisitor visitor) {
         return visitor.visit(this);
       }
     
       /**
    -   * Returns the throwable that caused this message, or {@code null} if this
    -   * message was not caused by a throwable.
    +   * Returns the throwable that caused this message, or {@code null} if this message was not caused
    +   * by a throwable.
        *
        * @since 2.0
        */
    @@ -103,15 +99,18 @@
         return cause;
       }
     
    -  @Override public String toString() {
    +  @Override
    +  public String toString() {
         return message;
       }
     
    -  @Override public int hashCode() {
    -    return message.hashCode();
    +  @Override
    +  public int hashCode() {
    +    return Objects.hashCode(message, cause, sources);
       }
     
    -  @Override public boolean equals(Object o) {
    +  @Override
    +  public boolean equals(Object o) {
         if (!(o instanceof Message)) {
           return false;
         }
    @@ -120,6 +119,7 @@
       }
     
       /** @since 2.0 */
    +  @Override
       public void applyTo(Binder binder) {
         binder.withSource(getSource()).addError(this);
       }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2015 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -23,7 +23,7 @@
     
     /**
      * Represents a call to {@link Binder#scanModulesForAnnotatedMethods} in a module.
    - * 
    + *
      * @author sameb@google.com (Sam Berlin)
      * @since 4.0
      */
    @@ -36,6 +36,7 @@
         this.scanner = checkNotNull(scanner, "scanner");
       }
     
    +  @Override
       public Object getSource() {
         return source;
       }
    @@ -43,17 +44,24 @@
       public ModuleAnnotatedMethodScanner getScanner() {
         return scanner;
       }
    -  
    +
    +  @Override
       public  T acceptVisitor(ElementVisitor visitor) {
         return visitor.visit(this);
       }
     
    +  @Override
       public void applyTo(Binder binder) {
         binder.withSource(getSource()).scanModulesForAnnotatedMethods(scanner);
       }
     
    -  @Override public String toString() {
    -    return scanner + " which scans for " + scanner.annotationClasses()
    -        + " (bound at " + Errors.convert(source) + ")";
    +  @Override
    +  public String toString() {
    +    return scanner
    +        + " which scans for "
    +        + scanner.annotationClasses()
    +        + " (bound at "
    +        + Errors.convert(source)
    +        + ")";
       }
     }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2015 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -18,13 +18,12 @@
     
     import com.google.inject.Binder;
     import com.google.inject.Key;
    -
     import java.lang.annotation.Annotation;
     import java.util.Set;
     
     /**
    - * Allows extensions to scan modules for annotated methods and bind those methods
    - * as providers, similar to {@code @Provides} methods.
    + * Allows extensions to scan modules for annotated methods and bind those methods as providers,
    + * similar to {@code @Provides} methods.
      *
      * @since 4.0
      */
    @@ -40,16 +39,15 @@
       /**
        * Prepares a method for binding. This {@code key} parameter is the key discovered from looking at
        * the binding annotation and return value of the method. Implementations can modify the key to
    -   * instead bind to another key. For example, Multibinder may want to change
    -   * {@code @SetProvides String provideFoo()} to bind into a unique Key within the multibinder
    -   * instead of binding {@code String}.
    +   * instead bind to another key. For example, Multibinder may want to change {@code @SetProvides
    +   * String provideFoo()} to bind into a unique Key within the multibinder instead of binding {@code
    +   * String}.
        *
        * 

    The injection point and annotation are provided in case the implementation wants to set the * key based on the property of the annotation or if any additional preparation is needed for any * of the dependencies. The annotation is guaranteed to be an instance of one the classes returned * by {@link #annotationClasses}. */ - public abstract Key prepareMethod(Binder binder, Annotation annotation, Key key, - InjectionPoint injectionPoint); - + public abstract Key prepareMethod( + Binder binder, Annotation annotation, Key key, InjectionPoint injectionPoint); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ModuleSource.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ModuleSource.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ModuleSource.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ModuleSource.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ import com.google.inject.Module; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement; - import java.util.List; /** @@ -31,14 +30,10 @@ */ final class ModuleSource { - /** - * The class name of module that this {@link ModuleSource} associated to. - */ + /** The class name of module that this {@link ModuleSource} associated to. */ private final String moduleClassName; - /** - * The parent {@link ModuleSource module source}. - */ + /** The parent {@link ModuleSource module source}. */ private final ModuleSource parent; /** @@ -51,22 +46,24 @@ /** * Creates a new {@link ModuleSource} with a {@literal null} parent. + * * @param module the corresponding module * @param partialCallStack the chunk of call stack that starts from the parent module {@link - * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link - * Module#configure(Binder) configure(Binder)} method invocation + * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link + * Module#configure(Binder) configure(Binder)} method invocation */ ModuleSource(Object module, StackTraceElement[] partialCallStack) { this(null, module, partialCallStack); } - /** + /** * Creates a new {@link ModuleSource} Object. + * * @param parent the parent module {@link ModuleSource source} * @param module the corresponding module * @param partialCallStack the chunk of call stack that starts from the parent module {@link - * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link - * Module#configure(Binder) configure(Binder)} method invocation + * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link + * Module#configure(Binder) configure(Binder)} method invocation */ private ModuleSource( /* @Nullable */ ModuleSource parent, Object module, StackTraceElement[] partialCallStack) { @@ -96,27 +93,24 @@ return StackTraceElements.convertToStackTraceElement(partialCallStack); } - /** - * Returns the size of partial call stack if stack trace collection is on otherwise zero. - */ + /** Returns the size of partial call stack if stack trace collection is on otherwise zero. */ int getPartialCallStackSize() { return partialCallStack.length; } /** * Creates and returns a child {@link ModuleSource} corresponding to the {@link Module module}. + * * @param module the corresponding module * @param partialCallStack the chunk of call stack that starts from the parent module {@link - * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link - * Module#configure(Binder) configure(Binder)} method invocation + * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link + * Module#configure(Binder) configure(Binder)} method invocation */ ModuleSource createChild(Object module, StackTraceElement[] partialCallStack) { return new ModuleSource(this, module, partialCallStack); } - /** - * Returns the parent module {@link ModuleSource source}. - */ + /** Returns the parent module {@link ModuleSource source}. */ ModuleSource getParent() { return parent; } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/spi/package-info.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,8 +14,5 @@ * limitations under the License. */ -/** - * Guice service provider interface - */ - -package com.google.inject.spi; \ No newline at end of file +/** Guice service provider interface */ +package com.google.inject.spi; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/PrivateElements.java sisu-guice-4.2.0/core/src/com/google/inject/spi/PrivateElements.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/PrivateElements.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/PrivateElements.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.inject.Injector; import com.google.inject.Key; - import java.util.List; import java.util.Set; @@ -31,9 +30,7 @@ */ public interface PrivateElements extends Element { - /** - * Returns the configuration information in this private environment. - */ + /** Returns the configuration information in this private environment. */ List getElements(); /** @@ -42,9 +39,7 @@ */ Injector getInjector(); - /** - * Returns the unique exposed keys for these private elements. - */ + /** Returns the unique exposed keys for these private elements. */ Set> getExposedKeys(); /** diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,4 +35,4 @@ * Injector.getBinding(providedKey)} */ Key getProvidedKey(); -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderInstanceBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderInstanceBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderInstanceBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderInstanceBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.inject.Binding; import com.google.inject.Provider; - import java.util.Set; /** @@ -33,14 +32,15 @@ /** * If the user supplied a JSR330 binding, then this will wrap that one. To always return the * user-supplied provider, use {@link #getUserSuppliedProvider}. - * + * * @deprecated Use {@link #getUserSuppliedProvider} instead. */ @Deprecated Provider getProviderInstance(); - + /** * Returns the user-supplied, unscoped provider. + * * @since 4.0 */ javax.inject.Provider getUserSuppliedProvider(); @@ -52,5 +52,4 @@ * @return a possibly empty set */ Set getInjectionPoints(); - -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderKeyBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderKeyBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderKeyBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderKeyBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,5 +34,4 @@ * Injector.getBinding(providerKey)} */ Key> getProviderKey(); - -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderLookup.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderLookup.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderLookup.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderLookup.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,12 +24,12 @@ import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.util.Types; - import java.util.Set; /** - * A lookup of the provider for a type. Lookups are created explicitly in a module using - * {@link com.google.inject.Binder#getProvider(Class) getProvider()} statements: + * A lookup of the provider for a type. Lookups are created explicitly in a module using {@link + * com.google.inject.Binder#getProvider(Class) getProvider()} statements: + * *

      *     Provider<PaymentService> paymentServiceProvider
      *         = getProvider(PaymentService.class);
    @@ -52,6 +52,7 @@ this.dependency = checkNotNull(dependency, "dependency"); } + @Override public Object getSource() { return source; } @@ -60,10 +61,12 @@ return dependency.getKey(); } + /** @since 4.0 */ public Dependency getDependency() { return dependency; } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } @@ -78,6 +81,7 @@ this.delegate = checkNotNull(delegate, "delegate"); } + @Override public void applyTo(Binder binder) { initializeDelegate(binder.withSource(getSource()).getProvider(dependency)); } @@ -97,12 +101,17 @@ */ public Provider getProvider() { return new ProviderWithDependencies() { + @Override public T get() { - checkState(delegate != null, - "This Provider cannot be used until the Injector has been created."); - return delegate.get(); + Provider local = delegate; + if (local == null) { + throw new IllegalStateException( + "This Provider cannot be used until the Injector has been created."); + } + return local.get(); } + @Override public Set> getDependencies() { // We depend on Provider, not T directly. This is an important distinction // for dependency analysis tools that short-circuit on providers. @@ -110,7 +119,8 @@ return ImmutableSet.>of(Dependency.get(providerKey)); } - @Override public String toString() { + @Override + public String toString() { return "Provider<" + getKey().getTypeLiteral() + ">"; } }; diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderWithDependencies.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderWithDependencies.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderWithDependencies.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderWithDependencies.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,26 +20,25 @@ import com.google.inject.Provider; /** - * A Provider that is part of an extension which supports a custom - * BindingTargetVisitor. - *

    - * When an extension binds a provider instance, the provider can implement this - * interface to allow users using the - * {@link Binding#acceptTargetVisitor(BindingTargetVisitor)} method to visit a - * custom visitor designed for that extension. A typical implementation within - * the extension would look like - *

     
    + * A Provider that is part of an extension which supports a custom BindingTargetVisitor.
    + *
    + * 

    When an extension binds a provider instance, the provider can implement this interface to + * allow users using the {@link Binding#acceptTargetVisitor(BindingTargetVisitor)} method to visit a + * custom visitor designed for that extension. A typical implementation within the extension would + * look like + * + *

      * <V, B> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor, ProviderInstanceBinding<? extends B> binding) {
      *   if(visitor instanceof MyCustomExtensionVisitor) {
      *     return ((MyCustomExtensionVisitor<B, V>)visitor).visitCustomExtension(customProperties, binding);
      *   } else {
      *     return visitor.visit(binding);
      *   }
    - * }
    - * 'MyCustomExtensionVisitor' in the example above would be an interface the - * extension provides that users can implement in order to be notified of custom - * extension information. These visitor interfaces must extend from - * BindingTargetVisitor. + * }
    + * + * 'MyCustomExtensionVisitor' in the example above would be an interface the extension provides that + * users can implement in order to be notified of custom extension information. These visitor + * interfaces must extend from BindingTargetVisitor. * * @since 3.0 * @author sameb@google.com (Sam Berlin) @@ -47,15 +46,13 @@ public interface ProviderWithExtensionVisitor extends Provider { /** - * Instructs the extension determine if the visitor is an instance of a custom - * extension visitor, and if so, visit it using that method. If the visitor is - * not an instance of the custom extension visitor, this method MUST - * call visitor.visit(binding). - *

    - * Due to issues with generics, the type parameters of this method do not - * relate to the type of the provider. In practice, the 'B' type will always - * be a supertype of 'T'. + * Instructs the extension determine if the visitor is an instance of a custom extension visitor, + * and if so, visit it using that method. If the visitor is not an instance of the custom + * extension visitor, this method MUST call visitor.visit(binding). + * + *

    Due to issues with generics, the type parameters of this method do not relate to the type of + * the provider. In practice, the 'B' type will always be a supertype of 'T'. */ - V acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding); + V acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvidesMethodBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvidesMethodBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvidesMethodBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvidesMethodBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,33 +18,32 @@ import com.google.inject.Key; import com.google.inject.Provides; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** - * An {@literal @}{@link Provides} binding or binding produced by a - * {@link ModuleAnnotatedMethodScanner}. + * An {@literal @}{@link Provides} binding or binding produced by a {@link + * ModuleAnnotatedMethodScanner}. * * @since 4.0 * @author sameb@google.com (Sam Berlin) */ public interface ProvidesMethodBinding extends HasDependencies { - + /** Returns the method this binding uses. */ - Method getMethod(); - + Method getMethod(); + /** Returns the instance of the object the method is defined in. */ Object getEnclosingInstance(); - + /** Returns the key of the binding. */ Key getKey(); /** * Returns the annotation that caused this binding to be created. For {@code @Provides} methods, - * this is an instance of the {@code @Provides} annotation. For bindings from - * {@link ModuleAnnotatedMethodScanner}, this is the annotation that caused the scanner to produce - * the binding. + * this is an instance of the {@code @Provides} annotation. For bindings from {@link + * ModuleAnnotatedMethodScanner}, this is the annotation that caused the scanner to produce the + * binding. */ Annotation getAnnotation(); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,19 +17,18 @@ package com.google.inject.spi; import com.google.inject.Provides; -import com.google.inject.spi.BindingTargetVisitor; /** * A visitor for the {@literal @}{@link Provides} bindings. - *

    - * If your {@link BindingTargetVisitor} implements this interface, bindings created by using - * {@code @Provides} will be visited through this interface. + * + *

    If your {@link com.google.inject.spi.BindingTargetVisitor} implements this interface, bindings + * created by using {@code @Provides} will be visited through this interface. * * @since 4.0 * @author sameb@google.com (Sam Berlin) */ public interface ProvidesMethodTargetVisitor extends BindingTargetVisitor { - + /** * Visits an {@link ProvidesMethodBinding} created with an {@literal @}{@link Provides} method. */ diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvisionListenerBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvisionListenerBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvisionListenerBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvisionListenerBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,6 @@ import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.matcher.Matcher; - import java.util.List; /** @@ -36,9 +35,8 @@ private final Matcher> bindingMatcher; private final List listeners; - ProvisionListenerBinding(Object source, - Matcher> bindingMatcher, - ProvisionListener[] listeners) { + ProvisionListenerBinding( + Object source, Matcher> bindingMatcher, ProvisionListener[] listeners) { this.source = source; this.bindingMatcher = bindingMatcher; this.listeners = ImmutableList.copyOf(listeners); @@ -51,21 +49,25 @@ /** * Returns the binding matcher which chooses which bindings the listener should be notified of. - */ + */ public Matcher> getBindingMatcher() { return bindingMatcher; } + @Override public Object getSource() { return source; } + @Override public R acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } + @Override public void applyTo(Binder binder) { - binder.withSource(getSource()).bindListener(bindingMatcher, - listeners.toArray(new ProvisionListener[listeners.size()])); + binder + .withSource(getSource()) + .bindListener(bindingMatcher, listeners.toArray(new ProvisionListener[listeners.size()])); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvisionListener.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvisionListener.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ProvisionListener.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ProvisionListener.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,12 +1,12 @@ /* * Copyright (C) 2011 Google Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -20,32 +20,28 @@ import com.google.inject.Provider; import com.google.inject.Scope; -import java.util.List; - /** - * Listens for provisioning of objects. Useful for gathering timing information - * about provisioning, post-provision initialization, and more. - * + * Listens for provisioning of objects. Useful for gathering timing information about provisioning, + * post-provision initialization, and more. + * * @author sameb@google.com (Sam Berlin) * @since 4.0 */ public interface ProvisionListener { /** - * Invoked by Guice when an object requires provisioning. Provisioning occurs - * when Guice locates and injects the dependencies for a binding. For types - * bound to a Provider, provisioning encapsulates the {@link Provider#get} - * method. For toInstance or constant bindings, provisioning encapsulates - * the injecting of {@literal @}{@code Inject}ed fields or methods. - * For other types, provisioning encapsulates the construction of the - * object. If a type is bound within a {@link Scope}, provisioning depends on - * the scope. Types bound in Singleton scope will only be provisioned once. - * Types bound in no scope will be provisioned every time they are injected. + * Invoked by Guice when an object requires provisioning. Provisioning occurs when Guice locates + * and injects the dependencies for a binding. For types bound to a Provider, provisioning + * encapsulates the {@link Provider#get} method. For toInstance or constant bindings, provisioning + * encapsulates the injecting of {@literal @}{@code Inject}ed fields or methods. For other types, + * provisioning encapsulates the construction of the object. If a type is bound within a {@link + * Scope}, provisioning depends on the scope. Types bound in Singleton scope will only be + * provisioned once. Types bound in no scope will be provisioned every time they are injected. * Other scopes define their own behavior for provisioning. - *

    - * To perform the provision, call {@link ProvisionInvocation#provision()}. - * If you do not explicitly call provision, it will be automatically done after - * this method returns. It is an error to call provision more than once. + * + *

    To perform the provision, call {@link ProvisionInvocation#provision()}. If you do not + * explicitly call provision, it will be automatically done after this method returns. It is an + * error to call provision more than once. */ void onProvision(ProvisionInvocation provision); @@ -53,22 +49,57 @@ * Encapsulates a single act of provisioning. * * @since 4.0 - */ + */ public abstract static class ProvisionInvocation { /** * Returns the Binding this is provisioning. - *

    - * You must not call {@link Provider#get()} on the provider returned by - * {@link Binding#getProvider}, otherwise you will get confusing error messages. + * + *

    You must not call {@link Provider#get()} on the provider returned by {@link + * Binding#getProvider}, otherwise you will get confusing error messages. */ public abstract Binding getBinding(); /** Performs the provision, returning the object provisioned. */ public abstract T provision(); - - /** Returns the dependency chain that led to this object being provisioned. */ - public abstract List getDependencyChain(); - + + /** + * Returns the dependency chain that led to this object being provisioned. + * + * @deprecated This method is planned for removal in Guice 4.4. Some use cases can be replaced + * by inferring the current chain via ThreadLocals in the listener, other use cases can use + * the static dependency graph. For example, + *

    {@code
    +     *   bindListener(Matchers.any(), new MyListener());
    +     *   ...
    +     *
    +     *   private static final class MyListener implements ProvisionListener {
    +     *     private final ThreadLocal>> bindingStack =
    +     *         new ThreadLocal>>() {
    +     *           {@literal @}Override protected ArrayDeque> initialValue() {
    +     *             return new ArrayDeque<>();
    +     *           }
    +     *         };
    +     *     {@literal @}Override public  void onProvision(ProvisionInvocation invocation) {
    +     *       bindingStack.get().push(invocation.getBinding());
    +     *       try {
    +     *         invocation.provision();
    +     *       } finally {
    +     *         bindingStack.get().pop();
    +     *       }
    +     *       // Inspect the binding stack...
    +     *     }
    +     *   }
    +     *
    +     * }
    +     *
    +     * In this example the bindingStack thread local will contain a data structure that is very
    +     * similar to the data returned by this list.  The main differences are that linked keys are
    +     * not in the stack, but such edges do exist in the static dependency graph (inspectable via
    +     * {@link HasDependencies#getDependencies()}), so you could infer some of the missing edges..
    +     */
    +    @Deprecated
    +    public abstract java.util.List getDependencyChain();
    +
       }
     }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java sisu-guice-4.2.0/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2012 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -34,14 +34,17 @@
         this.source = checkNotNull(source, "source");
       }
     
    +  @Override
       public Object getSource() {
         return source;
       }
     
    +  @Override
       public void applyTo(Binder binder) {
         binder.withSource(getSource()).requireAtInjectOnConstructors();
       }
     
    +  @Override
       public  T acceptVisitor(ElementVisitor visitor) {
         return visitor.visit(this);
       }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java sisu-guice-4.2.0/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2010 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -33,14 +33,17 @@
         this.source = checkNotNull(source, "source");
       }
     
    +  @Override
       public Object getSource() {
         return source;
       }
     
    +  @Override
       public void applyTo(Binder binder) {
         binder.withSource(getSource()).requireExactBindingAnnotations();
       }
     
    +  @Override
       public  T acceptVisitor(ElementVisitor visitor) {
         return visitor.visit(this);
       }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java sisu-guice-4.2.0/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2010 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -33,14 +33,17 @@
         this.source = checkNotNull(source, "source");
       }
     
    +  @Override
       public Object getSource() {
         return source;
       }
     
    +  @Override
       public void applyTo(Binder binder) {
         binder.withSource(getSource()).requireExplicitBindings();
       }
     
    +  @Override
       public  T acceptVisitor(ElementVisitor visitor) {
         return visitor.visit(this);
       }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/ScopeBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/ScopeBinding.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/spi/ScopeBinding.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/ScopeBinding.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2008 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -20,13 +20,13 @@
     
     import com.google.inject.Binder;
     import com.google.inject.Scope;
    -
     import java.lang.annotation.Annotation;
     
     /**
      * Registration of a scope annotation with the scope that implements it. Instances are created
      * explicitly in a module using {@link com.google.inject.Binder#bindScope(Class, Scope) bindScope()}
      * statements:
    + *
      * 
      *     Scope recordScope = new RecordScope();
      *     bindScope(RecordScoped.class, new RecordScope());
    @@ -45,6 +45,7 @@ this.scope = checkNotNull(scope, "scope"); } + @Override public Object getSource() { return source; } @@ -57,10 +58,12 @@ return scope; } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } + @Override public void applyTo(Binder binder) { binder.withSource(getSource()).bindScope(annotationType, scope); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/StaticInjectionRequest.java sisu-guice-4.2.0/core/src/com/google/inject/spi/StaticInjectionRequest.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/StaticInjectionRequest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/StaticInjectionRequest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,13 +20,13 @@ import com.google.inject.Binder; import com.google.inject.ConfigurationException; - import java.util.Set; /** - * A request to inject the static fields and methods of a type. Requests are created - * explicitly in a module using {@link com.google.inject.Binder#requestStaticInjection(Class[]) + * A request to inject the static fields and methods of a type. Requests are created explicitly in a + * module using {@link com.google.inject.Binder#requestStaticInjection(Class[]) * requestStaticInjection()} statements: + * *
      *     requestStaticInjection(MyLegacyService.class);
    * @@ -42,6 +42,7 @@ this.type = checkNotNull(type, "type"); } + @Override public Object getSource() { return source; } @@ -55,21 +56,23 @@ * request. * * @return a possibly empty set of injection points. The set has a specified iteration order. All - * fields are returned and then all methods. Within the fields, supertype fields are returned - * before subtype fields. Similarly, supertype methods are returned before subtype methods. + * fields are returned and then all methods. Within the fields, supertype fields are returned + * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as - * a field with multiple binding annotations. The exception's {@link - * ConfigurationException#getPartialValue() partial value} is a {@code Set} - * of the valid injection points. + * a field with multiple binding annotations. The exception's {@link + * ConfigurationException#getPartialValue() partial value} is a {@code Set} of + * the valid injection points. */ public Set getInjectionPoints() throws ConfigurationException { return InjectionPoint.forStaticMethodsAndFields(type); } + @Override public void applyTo(Binder binder) { binder.withSource(getSource()).requestStaticInjection(type); } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/Toolable.java sisu-guice-4.2.0/core/src/com/google/inject/spi/Toolable.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/Toolable.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/Toolable.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ import com.google.inject.Injector; import com.google.inject.Stage; - import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -29,17 +28,16 @@ /** * Instructs an {@link Injector} running in {@link Stage#TOOL} that a method should be injected. * This is typically useful for for extensions to Guice that perform additional validation in an - * injected method or field. This only applies to objects that are already constructed when - * bindings are created (ie., something bound using {@link + * injected method or field. This only applies to objects that are already constructed when bindings + * are created (ie., something bound using {@link * com.google.inject.binder.LinkedBindingBuilder#toProvider toProvider}, {@link * com.google.inject.binder.LinkedBindingBuilder#toInstance toInstance}, or {@link * com.google.inject.Binder#requestInjection requestInjection}. - * + * * @author sberlin@gmail.com (Sam Berlin) * @since 3.0 */ -@Target({ METHOD }) +@Target({METHOD}) @Retention(RUNTIME) @Documented -public @interface Toolable { -} +public @interface Toolable {} diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeConverterBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeConverterBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeConverterBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeConverterBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,11 +24,13 @@ import com.google.inject.matcher.Matcher; /** - * Registration of type converters for matching target types. Instances are created - * explicitly in a module using {@link com.google.inject.Binder#convertToTypes(Matcher, - * TypeConverter) convertToTypes()} statements: + * Registration of type converters for matching target types. Instances are created explicitly in a + * module using {@link com.google.inject.Binder#convertToTypes(Matcher, TypeConverter) + * convertToTypes()} statements: + * *
    - *     convertToTypes(Matchers.only(TypeLiteral.get(DateTime.class)), new DateTimeConverter());
    + * convertToTypes(Matchers.only(TypeLiteral.get(DateTime.class)), new DateTimeConverter()); + *
    * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 @@ -39,13 +41,14 @@ private final TypeConverter typeConverter; /** @since 3.0 */ - public TypeConverterBinding(Object source, Matcher> typeMatcher, - TypeConverter typeConverter) { + public TypeConverterBinding( + Object source, Matcher> typeMatcher, TypeConverter typeConverter) { this.source = checkNotNull(source, "source"); this.typeMatcher = checkNotNull(typeMatcher, "typeMatcher"); this.typeConverter = checkNotNull(typeConverter, "typeConverter"); } + @Override public Object getSource() { return source; } @@ -58,16 +61,23 @@ return typeConverter; } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } + @Override public void applyTo(Binder binder) { binder.withSource(getSource()).convertToTypes(typeMatcher, typeConverter); } - @Override public String toString() { - return typeConverter + " which matches " + typeMatcher - + " (bound at " + Errors.convert(source) + ")"; + @Override + public String toString() { + return typeConverter + + " which matches " + + typeMatcher + + " (bound at " + + Errors.convert(source) + + ")"; } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeConverter.java sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeConverter.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeConverter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeConverter.java 2018-04-03 18:18:08.000000000 +0000 @@ -26,8 +26,6 @@ */ public interface TypeConverter { - /** - * Converts a string value. Throws an exception if a conversion error occurs. - */ + /** Converts a string value. Throws an exception if a conversion error occurs. */ Object convert(String value, TypeLiteral toType); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeEncounter.java sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeEncounter.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeEncounter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeEncounter.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,13 +21,12 @@ import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.matcher.Matcher; - import java.lang.reflect.Method; /** * Context of an injectable type encounter. Enables reporting errors, registering injection - * listeners and binding method interceptors for injectable type {@code I}. It is an error to use - * an encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has + * listeners and binding method interceptors for injectable type {@code I}. It is an error to use an + * encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has * returned. * * @param the injectable type encountered @@ -38,8 +37,8 @@ /** * Records an error message for type {@code I} which will be presented to the user at a later * time. Unlike throwing an exception, this enable us to continue configuring the Injector and - * discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments - * into the message. + * discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments into + * the message. */ void addError(String message, Object... arguments); @@ -50,9 +49,7 @@ */ void addError(Throwable t); - /** - * Records an error message to be presented to the user at a later time. - */ + /** Records an error message to be presented to the user at a later time. */ void addError(Message message); /** @@ -72,8 +69,8 @@ /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. The returned members injector will not be valid until the main - * injector has been created. The members injector will throw an {@code IllegalStateException} - * if you try to use it beforehand. + * injector has been created. The members injector will throw an {@code IllegalStateException} if + * you try to use it beforehand. * * @param typeLiteral type to get members injector for */ @@ -82,8 +79,8 @@ /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. The returned members injector will not be valid until the main - * injector has been created. The members injector will throw an {@code IllegalStateException} - * if you try to use it beforehand. + * injector has been created. The members injector will throw an {@code IllegalStateException} if + * you try to use it beforehand. * * @param type type to get members injector for */ @@ -103,20 +100,21 @@ /*if[AOP]*/ /** - * Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A - * method is eligible for interception if: + * Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A method + * is eligible for interception if: * *
      - *
    • Guice created the instance the method is on
    • - *
    • Neither the enclosing type nor the method is final
    • - *
    • And the method is package-private or more accessible
    • + *
    • Guice created the instance the method is on + *
    • Neither the enclosing type nor the method is final + *
    • And the method is package-private or more accessible *
    * - * @param methodMatcher matches methods the interceptor should apply to. For - * example: {@code annotatedWith(Transactional.class)}. + * @param methodMatcher matches methods the interceptor should apply to. For example: {@code + * annotatedWith(Transactional.class)}. * @param interceptors to bind */ - void bindInterceptor(Matcher methodMatcher, + void bindInterceptor( + Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors); /*end[AOP]*/ } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeListenerBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeListenerBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeListenerBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeListenerBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,8 +36,8 @@ private final Matcher> typeMatcher; private final TypeListener listener; - TypeListenerBinding(Object source, TypeListener listener, - Matcher> typeMatcher) { + TypeListenerBinding( + Object source, TypeListener listener, Matcher> typeMatcher) { this.source = source; this.listener = listener; this.typeMatcher = typeMatcher; @@ -53,14 +53,17 @@ return typeMatcher; } + @Override public Object getSource() { return source; } + @Override public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } + @Override public void applyTo(Binder binder) { binder.withSource(getSource()).bindListener(typeMatcher, listener); } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeListener.java sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeListener.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/TypeListener.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/TypeListener.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,24 +25,22 @@ * *

    Useful for extra type checking, {@linkplain TypeEncounter#register(InjectionListener) * registering injection listeners}, and {@linkplain TypeEncounter#bindInterceptor( - * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) - * binding method interceptors}. - * + * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) binding method + * interceptors}. + * * @since 2.0 */ public interface TypeListener { /** - * Invoked when Guice encounters a new type eligible for constructor or members injection. - * Called during injector creation (or afterwords if Guice encounters a type at run time and - * creates a JIT binding). + * Invoked when Guice encounters a new type eligible for constructor or members injection. Called + * during injector creation (or afterwards if Guice encounters a type at run time and creates a + * JIT binding). * * @param type encountered by Guice * @param encounter context of this encounter, enables reporting errors, registering injection * listeners and binding method interceptors for {@code type}. - * * @param the injectable type */ void hear(TypeLiteral type, TypeEncounter encounter); - } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/spi/UntargettedBinding.java sisu-guice-4.2.0/core/src/com/google/inject/spi/UntargettedBinding.java --- sisu-guice-3.2.6/core/src/com/google/inject/spi/UntargettedBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/spi/UntargettedBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/Stage.java sisu-guice-4.2.0/core/src/com/google/inject/Stage.java --- sisu-guice-3.2.6/core/src/com/google/inject/Stage.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/Stage.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +26,8 @@ /** * We're running in a tool (an IDE plugin for example). We need binding meta data but not a * functioning Injector. Do not inject members of instances. Do not load eager singletons. Do as - * little as possible so our tools run nice and snappy. Injectors created in this stage cannot - * be used to satisfy injections. + * little as possible so our tools run nice and snappy. Injectors created in this stage cannot be + * used to satisfy injections. */ TOOL, @@ -37,8 +37,6 @@ */ DEVELOPMENT, - /** - * We want to catch errors as early as possible and take performance hits up front. - */ + /** We want to catch errors as early as possible and take performance hits up front. */ PRODUCTION } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/TypeLiteral.java sisu-guice-4.2.0/core/src/com/google/inject/TypeLiteral.java --- sisu-guice-3.2.6/core/src/com/google/inject/TypeLiteral.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/TypeLiteral.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableList; import com.google.inject.internal.MoreTypes; import com.google.inject.util.Types; - import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; @@ -36,26 +35,25 @@ import java.util.List; /** - * Represents a generic type {@code T}. Java doesn't yet provide a way to - * represent generic types, so this class does. Forces clients to create a - * subclass of this class which enables retrieval the type information even at - * runtime. + * Represents a generic type {@code T}. Java doesn't yet provide a way to represent generic types, + * so this class does. Forces clients to create a subclass of this class which enables retrieval of + * the type information even at runtime. * - *

    For example, to create a type literal for {@code List}, you can - * create an empty anonymous inner class: + *

    For example, to create a type literal for {@code List}, you can create an empty + * anonymous inner class: * - *

    - * {@code TypeLiteral> list = new TypeLiteral>() {};} + *

    {@code TypeLiteral> list = new TypeLiteral>() {};} * - *

    Along with modeling generic types, this class can resolve type parameters. - * For example, to figure out what type {@code keySet()} returns on a {@code - * Map}, use this code:

       {@code
    + * 

    Along with modeling generic types, this class can resolve type parameters. For example, to + * figure out what type {@code keySet()} returns on a {@code Map}, use this code: * - * TypeLiteral> mapType - * = new TypeLiteral>() {}; - * TypeLiteral keySetType - * = mapType.getReturnType(Map.class.getMethod("keySet")); - * System.out.println(keySetType); // prints "Set"}

    + *
    {@code
    + * TypeLiteral> mapType
    + *     = new TypeLiteral>() {};
    + * TypeLiteral keySetType
    + *     = mapType.getReturnType(Map.class.getMethod("keySet"));
    + * System.out.println(keySetType); // prints "Set"
    + * }
    * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) @@ -67,12 +65,10 @@ final int hashCode; /** - * Constructs a new type literal. Derives represented class from type - * parameter. + * Constructs a new type literal. Derives represented class from type parameter. * - *

    Clients create an empty anonymous subclass. Doing so embeds the type - * parameter in the anonymous class's type hierarchy so we can reconstitute it - * at runtime despite erasure. + *

    Clients create an empty anonymous subclass. Doing so embeds the type parameter in the + * anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure. */ @SuppressWarnings("unchecked") protected TypeLiteral() { @@ -81,9 +77,7 @@ this.hashCode = type.hashCode(); } - /** - * Unsafe. Constructs a type literal manually. - */ + /** Unsafe. Constructs a type literal manually. */ @SuppressWarnings("unchecked") TypeLiteral(Type type) { this.type = canonicalize(checkNotNull(type, "type")); @@ -104,32 +98,26 @@ return canonicalize(parameterized.getActualTypeArguments()[0]); } - /** - * Gets type literal from super class's type parameter. - */ + /** Gets type literal from super class's type parameter. */ static TypeLiteral fromSuperclassTypeParameter(Class subclass) { return new TypeLiteral(getSuperclassTypeParameter(subclass)); } /** * Returns the raw (non-generic) type for this type. - * + * * @since 2.0 */ public final Class getRawType() { return rawType; } - /** - * Gets underlying {@code Type} instance. - */ + /** Gets underlying {@code Type} instance. */ public final Type getType() { return type; } - /** - * Gets the type of this type's provider. - */ + /** Gets the type of this type's provider. */ @SuppressWarnings("unchecked") final TypeLiteral> providerType() { // This cast is safe and wouldn't generate a warning if Type had a type @@ -137,34 +125,31 @@ return (TypeLiteral>) get(Types.providerOf(getType())); } - @Override public final int hashCode() { + @Override + public final int hashCode() { return this.hashCode; } - @Override public final boolean equals(Object o) { - return o instanceof TypeLiteral - && MoreTypes.equals(type, ((TypeLiteral) o).type); + @Override + public final boolean equals(Object o) { + return o instanceof TypeLiteral && MoreTypes.equals(type, ((TypeLiteral) o).type); } - @Override public final String toString() { + @Override + public final String toString() { return MoreTypes.typeToString(type); } - /** - * Gets type literal for the given {@code Type} instance. - */ + /** Gets type literal for the given {@code Type} instance. */ public static TypeLiteral get(Type type) { return new TypeLiteral(type); } - /** - * Gets type literal for the given {@code Class} instance. - */ + /** Gets type literal for the given {@code Class} instance. */ public static TypeLiteral get(Class type) { return new TypeLiteral(type); } - /** Returns an immutable list of the resolved types. */ private List> resolveAll(Type[] types) { TypeLiteral[] result = new TypeLiteral[types.length]; @@ -174,9 +159,7 @@ return ImmutableList.copyOf(result); } - /** - * Resolves known type parameters in {@code toResolve} and returns the result. - */ + /** Resolves known type parameters in {@code toResolve} and returns the result. */ TypeLiteral resolve(Type toResolve) { return TypeLiteral.get(resolveType(toResolve)); } @@ -195,9 +178,7 @@ GenericArrayType original = (GenericArrayType) toResolve; Type componentType = original.getGenericComponentType(); Type newComponentType = resolveType(componentType); - return componentType == newComponentType - ? original - : Types.arrayOf(newComponentType); + return componentType == newComponentType ? original : Types.arrayOf(newComponentType); } else if (toResolve instanceof ParameterizedType) { ParameterizedType original = (ParameterizedType) toResolve; @@ -254,8 +235,8 @@ * @since 2.0 */ public TypeLiteral getSupertype(Class supertype) { - checkArgument(supertype.isAssignableFrom(rawType), - "%s is not a supertype of %s", supertype, this.type); + checkArgument( + supertype.isAssignableFrom(rawType), "%s is not a supertype of %s", supertype, this.type); return resolve(MoreTypes.getGenericSupertype(type, rawType, supertype)); } @@ -266,8 +247,11 @@ * @since 2.0 */ public TypeLiteral getFieldType(Field field) { - checkArgument(field.getDeclaringClass().isAssignableFrom(rawType), - "%s is not defined by a supertype of %s", field, type); + checkArgument( + field.getDeclaringClass().isAssignableFrom(rawType), + "%s is not defined by a supertype of %s", + field, + type); return resolve(field.getGenericType()); } @@ -282,14 +266,20 @@ if (methodOrConstructor instanceof Method) { Method method = (Method) methodOrConstructor; - checkArgument(method.getDeclaringClass().isAssignableFrom(rawType), - "%s is not defined by a supertype of %s", method, type); + checkArgument( + method.getDeclaringClass().isAssignableFrom(rawType), + "%s is not defined by a supertype of %s", + method, + type); genericParameterTypes = method.getGenericParameterTypes(); } else if (methodOrConstructor instanceof Constructor) { Constructor constructor = (Constructor) methodOrConstructor; - checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType), - "%s does not construct a supertype of %s", constructor, type); + checkArgument( + constructor.getDeclaringClass().isAssignableFrom(rawType), + "%s does not construct a supertype of %s", + constructor, + type); genericParameterTypes = constructor.getGenericParameterTypes(); } else { @@ -310,14 +300,20 @@ if (methodOrConstructor instanceof Method) { Method method = (Method) methodOrConstructor; - checkArgument(method.getDeclaringClass().isAssignableFrom(rawType), - "%s is not defined by a supertype of %s", method, type); + checkArgument( + method.getDeclaringClass().isAssignableFrom(rawType), + "%s is not defined by a supertype of %s", + method, + type); genericExceptionTypes = method.getGenericExceptionTypes(); } else if (methodOrConstructor instanceof Constructor) { Constructor constructor = (Constructor) methodOrConstructor; - checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType), - "%s does not construct a supertype of %s", constructor, type); + checkArgument( + constructor.getDeclaringClass().isAssignableFrom(rawType), + "%s does not construct a supertype of %s", + constructor, + type); genericExceptionTypes = constructor.getGenericExceptionTypes(); } else { @@ -334,8 +330,11 @@ * @since 2.0 */ public TypeLiteral getReturnType(Method method) { - checkArgument(method.getDeclaringClass().isAssignableFrom(rawType), - "%s is not defined by a supertype of %s", method, type); + checkArgument( + method.getDeclaringClass().isAssignableFrom(rawType), + "%s is not defined by a supertype of %s", + method, + type); return resolve(method.getGenericReturnType()); } } diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/util/Modules.java sisu-guice-4.2.0/core/src/com/google/inject/util/Modules.java --- sisu-guice-3.2.6/core/src/com/google/inject/util/Modules.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/src/com/google/inject/util/Modules.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +39,6 @@ import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding; import com.google.inject.spi.PrivateElements; import com.google.inject.spi.ScopeBinding; - import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.LinkedHashSet; @@ -55,19 +54,22 @@ */ public final class Modules { private Modules() {} - + public static final Module EMPTY_MODULE = new EmptyModule(); + private static class EmptyModule implements Module { + @Override public void configure(Binder binder) {} } /** - * Returns a builder that creates a module that overlays override modules over the given - * modules. If a key is bound in both sets of modules, only the binding from the override modules - * is kept. If a single {@link PrivateModule} is supplied or all elements are from - * a single {@link PrivateBinder}, then this will overwrite the private bindings. - * Otherwise, private bindings will not be overwritten unless they are exposed. - * This can be used to replace the bindings of a production module with test bindings: + * Returns a builder that creates a module that overlays override modules over the given modules. + * If a key is bound in both sets of modules, only the binding from the override modules is kept. + * If a single {@link PrivateModule} is supplied or all elements are from a single {@link + * PrivateBinder}, then this will overwrite the private bindings. Otherwise, private bindings will + * not be overwritten unless they are exposed. This can be used to replace the bindings of a + * production module with test bindings: + * *
        * Module functionalTestModule
        *     = Modules.override(new ProductionModule()).with(new TestModule());
    @@ -82,12 +84,13 @@
       }
     
       /**
    -   * Returns a builder that creates a module that overlays override modules over the given
    -   * modules. If a key is bound in both sets of modules, only the binding from the override modules
    -   * is kept. If a single {@link PrivateModule} is supplied or all elements are from
    -   * a single {@link PrivateBinder}, then this will overwrite the private bindings.
    -   * Otherwise, private bindings will not be overwritten unless they are exposed. 
    -   * This can be used to replace the bindings of a production module with test bindings:
    +   * Returns a builder that creates a module that overlays override modules over the given modules.
    +   * If a key is bound in both sets of modules, only the binding from the override modules is kept.
    +   * If a single {@link PrivateModule} is supplied or all elements are from a single {@link
    +   * PrivateBinder}, then this will overwrite the private bindings. Otherwise, private bindings will
    +   * not be overwritten unless they are exposed. This can be used to replace the bindings of a
    +   * production module with test bindings:
    +   *
        * 
        * Module functionalTestModule
        *     = Modules.override(getProductionModules()).with(getTestModules());
    @@ -101,27 +104,24 @@
         return new RealOverriddenModuleBuilder(modules);
       }
     
    -  /**
    -   * Returns a new module that installs all of {@code modules}.
    -   */
    +  /** Returns a new module that installs all of {@code modules}. */
       public static Module combine(Module... modules) {
         return combine(ImmutableSet.copyOf(modules));
       }
     
    -  /**
    -   * Returns a new module that installs all of {@code modules}.
    -   */
    +  /** Returns a new module that installs all of {@code modules}. */
       public static Module combine(Iterable modules) {
         return new CombinedModule(modules);
       }
    -  
    +
       private static class CombinedModule implements Module {
         final Set modulesSet;
    -    
    +
         CombinedModule(Iterable modules) {
           this.modulesSet = ImmutableSet.copyOf(modules);
         }
    -    
    +
    +    @Override
         public void configure(Binder binder) {
           binder = binder.skipSources(getClass());
           for (Module module : modulesSet) {
    @@ -130,19 +130,13 @@
         }
       }
     
    -  /**
    -   * See the EDSL example at {@link Modules#override(Module[]) override()}.
    -   */
    +  /** See the EDSL example at {@link Modules#override(Module[]) override()}. */
       public interface OverriddenModuleBuilder {
     
    -    /**
    -     * See the EDSL example at {@link Modules#override(Module[]) override()}.
    -     */
    +    /** See the EDSL example at {@link Modules#override(Module[]) override()}. */
         Module with(Module... overrides);
     
    -    /**
    -     * See the EDSL example at {@link Modules#override(Module[]) override()}.
    -     */
    +    /** See the EDSL example at {@link Modules#override(Module[]) override()}. */
         Module with(Iterable overrides);
       }
     
    @@ -153,19 +147,21 @@
           this.baseModules = ImmutableSet.copyOf(baseModules);
         }
     
    +    @Override
         public Module with(Module... overrides) {
           return with(Arrays.asList(overrides));
         }
     
    +    @Override
         public Module with(Iterable overrides) {
           return new OverrideModule(overrides, baseModules);
         }
       }
    -  
    +
       static class OverrideModule extends AbstractModule {
         private final ImmutableSet overrides;
         private final ImmutableSet baseModules;
    -    
    +
         OverrideModule(Iterable overrides, ImmutableSet baseModules) {
           this.overrides = ImmutableSet.copyOf(overrides);
           this.baseModules = baseModules;
    @@ -179,24 +175,27 @@
           // If the sole element was a PrivateElements, we want to override
           // the private elements within that -- so refocus our elements
           // and binder.
    -      if(baseElements.size() == 1) {
    +      if (baseElements.size() == 1) {
             Element element = Iterables.getOnlyElement(baseElements);
    -        if(element instanceof PrivateElements) {
    -          PrivateElements privateElements = (PrivateElements)element;
    -          PrivateBinder privateBinder = baseBinder.newPrivateBinder().withSource(privateElements.getSource());
    -          for(Key exposed : privateElements.getExposedKeys()) {
    +        if (element instanceof PrivateElements) {
    +          PrivateElements privateElements = (PrivateElements) element;
    +          PrivateBinder privateBinder =
    +              baseBinder.newPrivateBinder().withSource(privateElements.getSource());
    +          for (Key exposed : privateElements.getExposedKeys()) {
                 privateBinder.withSource(privateElements.getExposedSource(exposed)).expose(exposed);
               }
               baseBinder = privateBinder;
               baseElements = privateElements.getElements();
             }
           }
    -      
    +
           final Binder binder = baseBinder.skipSources(this.getClass());
    -      final LinkedHashSet elements = new LinkedHashSet(baseElements);
    +      final LinkedHashSet elements = new LinkedHashSet<>(baseElements);
           final Module scannersModule = extractScanners(elements);
    -      final List overrideElements = Elements.getElements(currentStage(),
    -          ImmutableList.builder().addAll(overrides).add(scannersModule).build());
    +      final List overrideElements =
    +          Elements.getElements(
    +              currentStage(),
    +              ImmutableList.builder().addAll(overrides).add(scannersModule).build());
     
           final Set> overriddenKeys = Sets.newHashSet();
           final Map, ScopeBinding> overridesScopeAnnotations =
    @@ -204,17 +203,20 @@
     
           // execute the overrides module, keeping track of which keys and scopes are bound
           new ModuleWriter(binder) {
    -        @Override public  Void visit(Binding binding) {
    +        @Override
    +        public  Void visit(Binding binding) {
               overriddenKeys.add(binding.getKey());
               return super.visit(binding);
             }
     
    -        @Override public Void visit(ScopeBinding scopeBinding) {
    +        @Override
    +        public Void visit(ScopeBinding scopeBinding) {
               overridesScopeAnnotations.put(scopeBinding.getAnnotationType(), scopeBinding);
               return super.visit(scopeBinding);
             }
     
    -        @Override public Void visit(PrivateElements privateElements) {
    +        @Override
    +        public Void visit(PrivateElements privateElements) {
               overriddenKeys.addAll(privateElements.getExposedKeys());
               return super.visit(privateElements);
             }
    @@ -226,7 +228,8 @@
           final Map> scopeInstancesInUse = Maps.newHashMap();
           final List scopeBindings = Lists.newArrayList();
           new ModuleWriter(binder) {
    -        @Override public  Void visit(Binding binding) {
    +        @Override
    +        public  Void visit(Binding binding) {
               if (!overriddenKeys.remove(binding.getKey())) {
                 super.visit(binding);
     
    @@ -246,8 +249,8 @@
             }
     
             void rewrite(Binder binder, PrivateElements privateElements, Set> keysToSkip) {
    -          PrivateBinder privateBinder = binder.withSource(privateElements.getSource())
    -              .newPrivateBinder();
    +          PrivateBinder privateBinder =
    +              binder.withSource(privateElements.getSource()).newPrivateBinder();
     
               Set> skippedExposes = Sets.newHashSet();
     
    @@ -260,8 +263,7 @@
               }
     
               for (Element element : privateElements.getElements()) {
    -            if (element instanceof Binding
    -                && skippedExposes.remove(((Binding) element).getKey())) {
    +            if (element instanceof Binding && skippedExposes.remove(((Binding) element).getKey())) {
                   continue;
                 }
                 if (element instanceof PrivateElements) {
    @@ -272,12 +274,14 @@
               }
             }
     
    -        @Override public Void visit(PrivateElements privateElements) {
    +        @Override
    +        public Void visit(PrivateElements privateElements) {
               rewrite(binder, privateElements, overriddenKeys);
               return null;
             }
     
    -        @Override public Void visit(ScopeBinding scopeBinding) {
    +        @Override
    +        public Void visit(ScopeBinding scopeBinding) {
               scopeBindings.add(scopeBinding);
               return null;
             }
    @@ -286,7 +290,8 @@
           // execute the scope bindings, skipping scopes that have been overridden. Any scope that
           // is overridden and in active use will prompt an error
           new ModuleWriter(binder) {
    -        @Override public Void visit(ScopeBinding scopeBinding) {
    +        @Override
    +        public Void visit(ScopeBinding scopeBinding) {
               ScopeBinding overideBinding =
                   overridesScopeAnnotations.remove(scopeBinding.getAnnotationType());
               if (overideBinding == null) {
    @@ -294,13 +299,15 @@
               } else {
                 List usedSources = scopeInstancesInUse.get(scopeBinding.getScope());
                 if (usedSources != null) {
    -              StringBuilder sb = new StringBuilder(
    -                  "The scope for @%s is bound directly and cannot be overridden.");
    +              StringBuilder sb =
    +                  new StringBuilder(
    +                      "The scope for @%s is bound directly and cannot be overridden.");
                   sb.append("%n     original binding at " + Errors.convert(scopeBinding.getSource()));
                   for (Object usedSource : usedSources) {
                     sb.append("%n     bound directly at " + Errors.convert(usedSource) + "");
                   }
    -              binder.withSource(overideBinding.getSource())
    +              binder
    +                  .withSource(overideBinding.getSource())
                       .addError(sb.toString(), scopeBinding.getAnnotationType().getSimpleName());
                 }
               }
    @@ -310,11 +317,13 @@
         }
     
         private Scope getScopeInstanceOrNull(Binding binding) {
    -      return binding.acceptScopingVisitor(new DefaultBindingScopingVisitor() {
    -        @Override public Scope visitScope(Scope scope) {
    -          return scope;
    -        }
    -      });
    +      return binding.acceptScopingVisitor(
    +          new DefaultBindingScopingVisitor() {
    +            @Override
    +            public Scope visitScope(Scope scope) {
    +              return scope;
    +            }
    +          });
         }
       }
     
    @@ -325,7 +334,8 @@
           this.binder = binder.skipSources(this.getClass());
         }
     
    -    @Override protected Void visitOther(Element element) {
    +    @Override
    +    protected Void visitOther(Element element) {
           element.applyTo(binder);
           return null;
         }
    @@ -339,17 +349,20 @@
     
       private static Module extractScanners(Iterable elements) {
         final List scanners = Lists.newArrayList();
    -    ElementVisitor visitor = new DefaultElementVisitor() {
    -      @Override public Void visit(ModuleAnnotatedMethodScannerBinding binding) {
    -        scanners.add(binding);
    -        return null;
    -      }
    -    };
    +    ElementVisitor visitor =
    +        new DefaultElementVisitor() {
    +          @Override
    +          public Void visit(ModuleAnnotatedMethodScannerBinding binding) {
    +            scanners.add(binding);
    +            return null;
    +          }
    +        };
         for (Element element : elements) {
           element.acceptVisitor(visitor);
         }
         return new AbstractModule() {
    -      @Override protected void configure() {
    +      @Override
    +      protected void configure() {
             for (ModuleAnnotatedMethodScannerBinding scanner : scanners) {
               scanner.applyTo(binder());
             }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/util/package-info.java sisu-guice-4.2.0/core/src/com/google/inject/util/package-info.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/util/package-info.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/util/package-info.java	2018-04-03 18:18:08.000000000 +0000
    @@ -14,7 +14,5 @@
      * limitations under the License.
      */
     
    -/**
    - * Helper methods for working with Guice.
    - */
    -package com.google.inject.util;
    \ No newline at end of file
    +/** Helper methods for working with Guice. */
    +package com.google.inject.util;
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/util/Providers.java sisu-guice-4.2.0/core/src/com/google/inject/util/Providers.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/util/Providers.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/util/Providers.java	2018-04-03 18:18:08.000000000 +0000
    @@ -27,12 +27,10 @@
     import com.google.inject.spi.Dependency;
     import com.google.inject.spi.InjectionPoint;
     import com.google.inject.spi.ProviderWithDependencies;
    -
     import java.util.Set;
     
     /**
    - * Static utility methods for creating and working with instances of
    - * {@link Provider}.
    + * Static utility methods for creating and working with instances of {@link Provider}.
      *
      * @author Kevin Bourrillion (kevinb9n@gmail.com)
      * @since 2.0
    @@ -42,13 +40,12 @@
       private Providers() {}
     
       /**
    -   * Returns a provider which always provides {@code instance}.  This should not
    -   * be necessary to use in your application, but is helpful for several types
    -   * of unit tests.
    +   * Returns a provider which always provides {@code instance}. This should not be necessary to use
    +   * in your application, but is helpful for several types of unit tests.
        *
    -   * @param instance the instance that should always be provided.  This is also
    -   *     permitted to be null, to enable aggressive testing, although in real
    -   *     life a Guice-supplied Provider will never return null.
    +   * @param instance the instance that should always be provided. This is also permitted to be null,
    +   *     to enable aggressive testing, although in real life a Guice-supplied Provider will never
    +   *     return null.
        */
       public static  Provider of(final T instance) {
         return new ConstantProvider(instance);
    @@ -61,46 +58,50 @@
           this.instance = instance;
         }
     
    +    @Override
         public T get() {
           return instance;
         }
     
    -    @Override public String toString() {
    +    @Override
    +    public String toString() {
           return "of(" + instance + ")";
         }
     
    -    @Override public boolean equals(Object obj) {
    +    @Override
    +    public boolean equals(Object obj) {
           return (obj instanceof ConstantProvider)
               && Objects.equal(instance, ((ConstantProvider) obj).instance);
         }
     
    -    @Override public int hashCode() {
    +    @Override
    +    public int hashCode() {
           return Objects.hashCode(instance);
         }
       }
     
       /**
    -   * Returns a Guice-friendly {@code com.google.inject.Provider} for the given
    -   * JSR-330 {@code javax.inject.Provider}. The converse method is unnecessary,
    -   * since Guice providers directly implement the JSR-330 interface.
    -   * 
    +   * Returns a Guice-friendly {@code com.google.inject.Provider} for the given JSR-330 {@code
    +   * javax.inject.Provider}. The converse method is unnecessary, since Guice providers directly
    +   * implement the JSR-330 interface.
    +   *
        * @since 3.0
        */
       public static  Provider guicify(javax.inject.Provider provider) {
         if (provider instanceof Provider) {
           return (Provider) provider;
         }
    -  
    +
         final javax.inject.Provider delegate = checkNotNull(provider, "provider");
    -    
    +
         // Ensure that we inject all injection points from the delegate provider.
         Set injectionPoints =
             InjectionPoint.forInstanceMethodsAndFields(provider.getClass());
    -    if(injectionPoints.isEmpty()) {
    +    if (injectionPoints.isEmpty()) {
           return new GuicifiedProvider(delegate);
         } else {
           Set> mutableDeps = Sets.newHashSet();
    -      for(InjectionPoint ip : injectionPoints) {
    +      for (InjectionPoint ip : injectionPoints) {
             mutableDeps.addAll(ip.getDependencies());
           }
           final Set> dependencies = ImmutableSet.copyOf(mutableDeps);
    @@ -115,30 +116,34 @@
           this.delegate = delegate;
         }
     
    +    @Override
         public T get() {
           return delegate.get();
         }
     
    -    @Override public String toString() {
    +    @Override
    +    public String toString() {
           return "guicified(" + delegate + ")";
         }
     
    -    @Override public boolean equals(Object obj) {
    +    @Override
    +    public boolean equals(Object obj) {
           return (obj instanceof GuicifiedProvider)
               && Objects.equal(delegate, ((GuicifiedProvider) obj).delegate);
         }
     
    -    @Override public int hashCode() {
    +    @Override
    +    public int hashCode() {
           return Objects.hashCode(delegate);
         }
       }
     
    -  private static final class GuicifiedProviderWithDependencies
    -      extends GuicifiedProvider implements ProviderWithDependencies {
    +  private static final class GuicifiedProviderWithDependencies extends GuicifiedProvider
    +      implements ProviderWithDependencies {
         private final Set> dependencies;
     
    -    private GuicifiedProviderWithDependencies(Set> dependencies,
    -        javax.inject.Provider delegate) {
    +    private GuicifiedProviderWithDependencies(
    +        Set> dependencies, javax.inject.Provider delegate) {
           super(delegate);
           this.dependencies = dependencies;
         }
    @@ -149,6 +154,7 @@
           injector.injectMembers(delegate);
         }
     
    +    @Override
         public Set> getDependencies() {
           return dependencies;
         }
    diff -Nru sisu-guice-3.2.6/core/src/com/google/inject/util/Types.java sisu-guice-4.2.0/core/src/com/google/inject/util/Types.java
    --- sisu-guice-3.2.6/core/src/com/google/inject/util/Types.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/src/com/google/inject/util/Types.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2008 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -14,7 +14,6 @@
      * limitations under the License.
      */
     
    -
     package com.google.inject.util;
     
     import com.google.inject.Provider;
    @@ -22,11 +21,11 @@
     import com.google.inject.internal.MoreTypes.GenericArrayTypeImpl;
     import com.google.inject.internal.MoreTypes.ParameterizedTypeImpl;
     import com.google.inject.internal.MoreTypes.WildcardTypeImpl;
    -
     import java.lang.reflect.GenericArrayType;
     import java.lang.reflect.ParameterizedType;
     import java.lang.reflect.Type;
     import java.lang.reflect.WildcardType;
    +import java.util.Collection;
     import java.util.List;
     import java.util.Map;
     import java.util.Set;
    @@ -41,8 +40,8 @@
       private Types() {}
     
       /**
    -   * Returns a new parameterized type, applying {@code typeArguments} to
    -   * {@code rawType}. The returned type does not have an owner type.
    +   * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType}. The
    +   * returned type does not have an owner type.
        *
        * @return a {@link java.io.Serializable serializable} parameterized type.
        */
    @@ -51,8 +50,8 @@
       }
     
       /**
    -   * Returns a new parameterized type, applying {@code typeArguments} to
    -   * {@code rawType} and enclosed by {@code ownerType}.
    +   * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType} and
    +   * enclosed by {@code ownerType}.
        *
        * @return a {@link java.io.Serializable serializable} parameterized type.
        */
    @@ -62,8 +61,7 @@
       }
     
       /**
    -   * Returns an array type whose elements are all instances of
    -   * {@code componentType}.
    +   * Returns an array type whose elements are all instances of {@code componentType}.
        *
        * @return a {@link java.io.Serializable serializable} generic array type.
        */
    @@ -72,27 +70,25 @@
       }
     
       /**
    -   * Returns a type that represents an unknown type that extends {@code bound}.
    -   * For example, if {@code bound} is {@code CharSequence.class}, this returns
    -   * {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
    -   * this returns {@code ?}, which is shorthand for {@code ? extends Object}.
    +   * Returns a type that represents an unknown type that extends {@code bound}. For example, if
    +   * {@code bound} is {@code CharSequence.class}, this returns {@code ? extends CharSequence}. If
    +   * {@code bound} is {@code Object.class}, this returns {@code ?}, which is shorthand for {@code ?
    +   * extends Object}.
        */
       public static WildcardType subtypeOf(Type bound) {
    -    return new WildcardTypeImpl(new Type[] { bound }, MoreTypes.EMPTY_TYPE_ARRAY);
    +    return new WildcardTypeImpl(new Type[] {bound}, MoreTypes.EMPTY_TYPE_ARRAY);
       }
     
       /**
    -   * Returns a type that represents an unknown supertype of {@code bound}. For
    -   * example, if {@code bound} is {@code String.class}, this returns {@code ?
    -   * super String}.
    +   * Returns a type that represents an unknown supertype of {@code bound}. For example, if {@code
    +   * bound} is {@code String.class}, this returns {@code ? super String}.
        */
       public static WildcardType supertypeOf(Type bound) {
    -    return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound });
    +    return new WildcardTypeImpl(new Type[] {Object.class}, new Type[] {bound});
       }
     
       /**
    -   * Returns a type modelling a {@link List} whose elements are of type
    -   * {@code elementType}.
    +   * Returns a type modelling a {@link List} whose elements are of type {@code elementType}.
        *
        * @return a {@link java.io.Serializable serializable} parameterized type.
        */
    @@ -101,8 +97,16 @@
       }
     
       /**
    -   * Returns a type modelling a {@link Set} whose elements are of type
    -   * {@code elementType}.
    +   * Returns a type modelling a {@link Collection} whose elements are of type {@code elementType}.
    +   *
    +   * @return a {@link java.io.Serializable serializable} parameterized type.
    +   */
    +  public static ParameterizedType collectionOf(Type elementType) {
    +    return newParameterizedType(Collection.class, elementType);
    +  }
    +
    +  /**
    +   * Returns a type modelling a {@link Set} whose elements are of type {@code elementType}.
        *
        * @return a {@link java.io.Serializable serializable} parameterized type.
        */
    @@ -111,8 +115,8 @@
       }
     
       /**
    -   * Returns a type modelling a {@link Map} whose keys are of type
    -   * {@code keyType} and whose values are of type {@code valueType}.
    +   * Returns a type modelling a {@link Map} whose keys are of type {@code keyType} and whose values
    +   * are of type {@code valueType}.
        *
        * @return a {@link java.io.Serializable serializable} parameterized type.
        */
    @@ -123,12 +127,21 @@
       // for other custom collections types, use newParameterizedType()
     
       /**
    -   * Returns a type modelling a {@link Provider} that provides elements of type
    -   * {@code elementType}.
    +   * Returns a type modelling a {@link Provider} that provides elements of type {@code elementType}.
        *
        * @return a {@link java.io.Serializable serializable} parameterized type.
        */
       public static ParameterizedType providerOf(Type providedType) {
         return newParameterizedType(Provider.class, providedType);
       }
    -}
    \ No newline at end of file
    +
    +  /**
    +   * Returns a type modelling a {@link javax.inject.Provider} that provides elements of type {@code
    +   * elementType}.
    +   *
    +   * @return a {@link java.io.Serializable serializable} parameterized type.
    +   */
    +  public static Type javaxProviderOf(Type type) {
    +    return Types.newParameterizedType(javax.inject.Provider.class, type);
    +  }
    +}
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/AllTests.java sisu-guice-4.2.0/core/test/com/google/inject/AllTests.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/AllTests.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/AllTests.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -31,6 +31,7 @@
     import com.google.inject.spi.HasDependenciesTest;
     import com.google.inject.spi.InjectionPointTest;
     import com.google.inject.spi.InjectorSpiTest;
    +import com.google.inject.spi.MessageTest;
     import com.google.inject.spi.ModuleAnnotatedMethodScannerTest;
     import com.google.inject.spi.ModuleRewriterTest;
     import com.google.inject.spi.ModuleSourceTest;
    @@ -41,24 +42,18 @@
     import com.google.inject.util.OverrideModuleTest;
     import com.google.inject.util.ProvidersTest;
     import com.google.inject.util.TypesTest;
    -
     import com.googlecode.guice.GuiceTck;
     import com.googlecode.guice.Jsr330Test;
    -
     import junit.framework.Test;
     import junit.framework.TestSuite;
     
    -import java.util.Set;
    -
    -/**
    - * @author crazybob@google.com (Bob Lee)
    - */
    +/** @author crazybob@google.com (Bob Lee) */
     public class AllTests {
     
    -  private static final Set SUPPRESSED_TEST_NAMES = ImmutableSet.of(
    -      "testUnscopedProviderWorksOutsideOfRequestedScope(" + ScopesTest.class.getName() + ")",
    -      "testCannotConvertUnannotatedBindings(" + TypeConversionTest.class.getName() + ")"
    -  );
    +  private static final ImmutableSet SUPPRESSED_TEST_NAMES =
    +      ImmutableSet.of(
    +          "testUnscopedProviderWorksOutsideOfRequestedScope(" + ScopesTest.class.getName() + ")",
    +          "testCannotConvertUnannotatedBindings(" + TypeConversionTest.class.getName() + ")");
     
       public static Test suite() {
         TestSuite suite = new TestSuite();
    @@ -134,6 +129,7 @@
         suite.addTestSuite(ToolStageInjectorTest.class);
         suite.addTestSuite(ModuleSourceTest.class);
         suite.addTestSuite(ElementSourceTest.class);
    +    suite.addTestSuite(MessageTest.class);
     
         // tools
         // suite.addTestSuite(JmxTest.class); not a testcase
    @@ -154,6 +150,13 @@
         suite.addTestSuite(com.googlecode.guice.OSGiContainerTest.class);
         suite.addTestSuite(Jsr330Test.class);
     
    +    // multibindings tests
    +    suite.addTestSuite(com.google.inject.internal.MapBinderTest.class);
    +    suite.addTestSuite(com.google.inject.internal.MultibinderTest.class);
    +    suite.addTestSuite(com.google.inject.internal.OptionalBinderTest.class);
    +    suite.addTestSuite(com.google.inject.internal.RealElementTest.class);
    +    suite.addTestSuite(com.google.inject.multibindings.ProvidesIntoTest.class);
    +
         return SuiteUtils.removeSuppressedTests(suite, SUPPRESSED_TEST_NAMES);
       }
     }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/Asserts.java sisu-guice-4.2.0/core/test/com/google/inject/Asserts.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/Asserts.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/Asserts.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2008 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -14,10 +14,10 @@
      * limitations under the License.
      */
     
    -
     package com.google.inject;
     
    -import static com.google.inject.internal.InternalFlags.IncludeStackTraceOption;
    +import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_PATH;
    +import static com.google.common.base.StandardSystemProperty.PATH_SEPARATOR;
     import static com.google.inject.internal.InternalFlags.getIncludeStackTraceOption;
     import static junit.framework.Assert.assertEquals;
     import static junit.framework.Assert.assertNotNull;
    @@ -26,43 +26,51 @@
     
     import com.google.common.base.Function;
     import com.google.common.base.Joiner;
    +import com.google.common.base.Splitter;
     import com.google.common.collect.ImmutableList;
     import com.google.common.collect.Iterables;
     import com.google.common.testing.GcFinalization;
    -
    -import junit.framework.Assert;
    -
    +import com.google.inject.internal.InternalFlags.IncludeStackTraceOption;
     import java.io.ByteArrayInputStream;
     import java.io.ByteArrayOutputStream;
    +import java.io.File;
     import java.io.IOException;
     import java.io.NotSerializableException;
     import java.io.ObjectInputStream;
     import java.io.ObjectOutputStream;
     import java.lang.ref.ReferenceQueue;
     import java.lang.ref.WeakReference;
    +import java.net.MalformedURLException;
    +import java.net.URL;
    +import java.net.URLClassLoader;
    +import junit.framework.Assert;
     
    -/**
    - * @author jessewilson@google.com (Jesse Wilson)
    - */
    +/** @author jessewilson@google.com (Jesse Wilson) */
     public class Asserts {
    +
       private Asserts() {}
     
       /**
    -   * Returns the String that would appear in an error message for this chain of classes 
    -   * as modules.
    +   * Returns the String that would appear in an error message for this chain of classes as modules.
        */
       public static String asModuleChain(Class... classes) {
    -    return Joiner.on(" -> ").appendTo(new StringBuilder(" (via modules: "),
    -        Iterables.transform(ImmutableList.copyOf(classes), new Function() {
    -          @Override
    -          public String apply(Class input) {
    -            return input.getName();
    -          }
    -        })).append(")").toString();
    +    return Joiner.on(" -> ")
    +        .appendTo(
    +            new StringBuilder(" (via modules: "),
    +            Iterables.transform(
    +                ImmutableList.copyOf(classes),
    +                new Function() {
    +                  @Override
    +                  public String apply(Class input) {
    +                    return input.getName();
    +                  }
    +                }))
    +        .append(")")
    +        .toString();
       }
     
       /**
    -   * Returns the source file appears in error messages based on {@link 
    +   * Returns the source file appears in error messages based on {@link
        * #getIncludeStackTraceOption()} value.
        */
       public static String getDeclaringSourcePart(Class clazz) {
    @@ -89,9 +97,8 @@
       }
     
       /**
    -   * Fails unless {@code expected.equals(actual)}, {@code
    -   * actual.equals(expected)} and their hash codes are equal. This is useful
    -   * for testing the equals method itself.
    +   * Fails unless {@code expected.equals(actual)}, {@code actual.equals(expected)} and their hash
    +   * codes are equal. This is useful for testing the equals method itself.
        */
       public static void assertEqualsBothWays(Object expected, Object actual) {
         assertNotNull(expected);
    @@ -101,10 +108,16 @@
         assertEquals("hashCode", expected.hashCode(), actual.hashCode());
       }
     
    +  /** Fails unless {@code text} includes all {@code substrings}, in order, no duplicates */
    +  public static void assertContains(String text, String... substrings) {
    +    assertContains(text, false, substrings);
    +  }
    +
       /**
    -   * Fails unless {@code text} includes all {@code substrings}, in order.
    +   * Fails unless {@code text} includes all {@code substrings}, in order, and optionally {@code
    +   * allowDuplicates}.
        */
    -  public static void assertContains(String text, String... substrings) {
    +  public static void assertContains(String text, boolean allowDuplicates, String... substrings) {
         /*if[NO_AOP]
         // when we strip out bytecode manipulation, we lose the ability to generate some source lines.
         if (text.contains("(Unknown Source)")) {
    @@ -115,29 +128,29 @@
         int startingFrom = 0;
         for (String substring : substrings) {
           int index = text.indexOf(substring, startingFrom);
    -      assertTrue(String.format("Expected \"%s\" to contain substring \"%s\"", text, substring),
    +      assertTrue(
    +          String.format("Expected \"%s\" to contain substring \"%s\"", text, substring),
               index >= startingFrom);
           startingFrom = index + substring.length();
         }
     
    -    String lastSubstring = substrings[substrings.length - 1];
    -    assertTrue(String.format("Expected \"%s\" to contain substring \"%s\" only once),",
    -        text, lastSubstring), text.indexOf(lastSubstring, startingFrom) == -1);
    +    if (!allowDuplicates) {
    +      String lastSubstring = substrings[substrings.length - 1];
    +      assertTrue(
    +          String.format(
    +              "Expected \"%s\" to contain substring \"%s\" only once),", text, lastSubstring),
    +          text.indexOf(lastSubstring, startingFrom) == -1);
    +    }
       }
     
    -  /**
    -   * Fails unless {@code object} doesn't equal itself when reserialized.
    -   */
    -  public static void assertEqualWhenReserialized(Object object)
    -      throws IOException {
    +  /** Fails unless {@code object} doesn't equal itself when reserialized. */
    +  public static void assertEqualWhenReserialized(Object object) throws IOException {
         Object reserialized = reserialize(object);
         assertEquals(object, reserialized);
         assertEquals(object.hashCode(), reserialized.hashCode());
       }
     
    -  /**
    -   * Fails unless {@code object} has the same toString value when reserialized.
    -   */
    +  /** Fails unless {@code object} has the same toString value when reserialized. */
       public static void assertSimilarWhenReserialized(Object object) throws IOException {
         Object reserialized = reserialize(object);
         assertEquals(object.toString(), reserialized.toString());
    @@ -167,8 +180,8 @@
       public static void awaitFullGc() {
         // GcFinalization *should* do it, but doesn't work well in practice...
         // so we put a second latch and wait for a ReferenceQueue to tell us.
    -    ReferenceQueue queue = new ReferenceQueue();
    -    WeakReference ref = new WeakReference(new Object(), queue);
    +    ReferenceQueue queue = new ReferenceQueue<>();
    +    WeakReference ref = new WeakReference<>(new Object(), queue);
         GcFinalization.awaitFullGc();
         try {
           assertSame("queue didn't return ref in time", ref, queue.remove(5000));
    @@ -186,8 +199,8 @@
         ReferenceQueue queue = null;
         WeakReference extraRef = null;
         if (data != null) {
    -      queue = new ReferenceQueue();
    -      extraRef = new WeakReference(data, queue);
    +      queue = new ReferenceQueue<>();
    +      extraRef = new WeakReference<>(data, queue);
           data = null;
         }
         GcFinalization.awaitClear(ref);
    @@ -201,4 +214,27 @@
           }
         }
       }
    +
    +  /** Returns the URLs in the system class path. */
    +  // TODO(https://github.com/google/guava/issues/2956): Use a common API once that's available.
    +  public static URL[] getClassPathUrls() {
    +    if (Asserts.class.getClassLoader() instanceof URLClassLoader) {
    +      return ((URLClassLoader) Asserts.class.getClassLoader()).getURLs();
    +    }
    +    ImmutableList.Builder urls = ImmutableList.builder();
    +    for (String entry : Splitter.on(PATH_SEPARATOR.value()).split(JAVA_CLASS_PATH.value())) {
    +      try {
    +        try {
    +          urls.add(new File(entry).toURI().toURL());
    +        } catch (SecurityException e) { // File.toURI checks to see if the file is a directory
    +          urls.add(new URL("file", null, new File(entry).getAbsolutePath()));
    +        }
    +      } catch (MalformedURLException e) {
    +        AssertionError error = new AssertionError("malformed class path entry: " + entry);
    +        error.initCause(e);
    +        throw error;
    +      }
    +    }
    +    return urls.build().toArray(new URL[0]);
    +  }
     }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BinderTest.java sisu-guice-4.2.0/core/test/com/google/inject/BinderTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BinderTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BinderTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2007 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -20,17 +20,14 @@
     import static com.google.inject.Asserts.assertContains;
     import static com.google.inject.Asserts.assertNotSerializable;
     import static com.google.inject.Asserts.getDeclaringSourcePart;
    -import static com.google.inject.Asserts.isIncludeStackTraceOff;
     
     import com.google.common.collect.Iterables;
     import com.google.common.collect.Lists;
    +import com.google.inject.internal.Annotations;
     import com.google.inject.name.Named;
     import com.google.inject.name.Names;
     import com.google.inject.spi.Message;
     import com.google.inject.util.Providers;
    -
    -import junit.framework.TestCase;
    -
     import java.io.IOException;
     import java.util.Comparator;
     import java.util.Date;
    @@ -39,48 +36,57 @@
     import java.util.logging.Handler;
     import java.util.logging.LogRecord;
     import java.util.logging.Logger;
    +import junit.framework.TestCase;
     
    -/**
    - * @author crazybob@google.com (Bob Lee)
    - */
    +/** @author crazybob@google.com (Bob Lee) */
     public class BinderTest extends TestCase {
     
       private final Logger loggerToWatch = Logger.getLogger(Guice.class.getName());
     
       private final List logRecords = Lists.newArrayList();
    -  private final Handler fakeHandler = new Handler() {
    -    @Override
    -    public void publish(LogRecord logRecord) {
    -      logRecords.add(logRecord);
    -    }
    -    @Override
    -    public void flush() {}
    -    @Override
    -    public void close() throws SecurityException {}
    -  };
    +  private final Handler fakeHandler =
    +      new Handler() {
    +        @Override
    +        public void publish(LogRecord logRecord) {
    +          logRecords.add(logRecord);
    +        }
    +
    +        @Override
    +        public void flush() {}
    +
    +        @Override
    +        public void close() throws SecurityException {}
    +      };
     
       Provider fooProvider;
     
    -  @Override protected void setUp() throws Exception {
    +  @Override
    +  protected void setUp() throws Exception {
         super.setUp();
         loggerToWatch.addHandler(fakeHandler);
       }
     
    -  @Override protected void tearDown() throws Exception {
    +  @Override
    +  protected void tearDown() throws Exception {
         loggerToWatch.removeHandler(fakeHandler);
         super.tearDown();
       }
     
       public void testProviderFromBinder() {
    -    Guice.createInjector(new Module() {
    -      public void configure(Binder binder) {
    -        fooProvider = binder.getProvider(Foo.class);
    -
    -        try {
    -          fooProvider.get();
    -        } catch (IllegalStateException e) { /* expected */ }
    -      }
    -    });
    +    Guice.createInjector(
    +        new Module() {
    +          @Override
    +          public void configure(Binder binder) {
    +            fooProvider = binder.getProvider(Foo.class);
    +
    +            try {
    +              fooProvider.get();
    +              fail();
    +            } catch (IllegalStateException e) {
    +              /* expected */
    +            }
    +          }
    +        });
     
         assertNotNull(fooProvider.get());
       }
    @@ -89,55 +95,84 @@
     
       public void testMissingBindings() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        public void configure() {
    -          getProvider(Runnable.class);
    -          bind(Comparator.class);
    -          requireBinding(Key.get(new TypeLiteral>() {}));
    -          bind(Date.class).annotatedWith(Names.named("date"));
    -        }
    -      });
    +      Guice.createInjector(
    +          // We put each binding in a separate module so the order of the error messages doesn't
    +          // depend on line numbers
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              getProvider(Runnable.class);
    +            }
    +          },
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              bind(Comparator.class);
    +            }
    +          },
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              requireBinding(Key.get(new TypeLiteral>() {}));
    +            }
    +          },
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              bind(Date.class).annotatedWith(Names.named("date"));
    +            }
    +          });
    +      fail("Expected CreationException");
         } catch (CreationException e) {
           assertEquals(4, e.getErrorMessages().size());
    -      String segment1 = "No implementation for " + Comparator.class.getName() + " was bound.";
    -      String segment2 = "No implementation for java.util.Date annotated with @"
    -          + Named.class.getName() + "(value=date) was bound.";
    -      String segment3 = "No implementation for java.lang.Runnable was bound.";
    -      String segment4 = " No implementation for java.util.concurrent.Callable was"
    -          + " bound.";
    +      String segment1 = "No implementation for java.lang.Runnable was bound.";
    +      String segment2 = "No implementation for " + Comparator.class.getName() + " was bound.";
    +      String segment3 =
    +          "No implementation for java.util.concurrent.Callable was" + " bound.";
    +      String segment4 =
    +          "No implementation for java.util.Date annotated with @"
    +              + Named.class.getName()
    +              + "(value="
    +              + Annotations.memberValueString("date")
    +              + ") was bound.";
           String atSegment = "at " + getClass().getName();
           String sourceFileName = getDeclaringSourcePart(getClass());
    -      if (isIncludeStackTraceOff()) {
    -        assertContains(e.getMessage(),
    -            segment1, atSegment, sourceFileName,
    -            segment2, atSegment, sourceFileName,
    -            segment3, atSegment, sourceFileName,
    -            segment4, atSegment, sourceFileName);
    -      } else {
    -        assertContains(e.getMessage(),
    -            segment3, atSegment, sourceFileName,
    -            segment1, atSegment, sourceFileName,
    -            segment4, atSegment, sourceFileName,
    -            segment2, atSegment, sourceFileName);
    -      }
    +      assertContains(
    +          e.getMessage(),
    +          segment1,
    +          atSegment,
    +          sourceFileName,
    +          segment2,
    +          atSegment,
    +          sourceFileName,
    +          segment3,
    +          atSegment,
    +          sourceFileName,
    +          segment4,
    +          atSegment,
    +          sourceFileName);
         }
       }
     
       public void testMissingDependency() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        public void configure() {
    -          bind(NeedsRunnable.class);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              bind(NeedsRunnable.class);
    +            }
    +          });
    +      fail("Expected CreationException");
         } catch (CreationException e) {
           assertEquals(1, e.getErrorMessages().size());
    -      assertContains(e.getMessage(),
    +      assertContains(
    +          e.getMessage(),
               "No implementation for java.lang.Runnable was bound.",
    -          "for field at " + NeedsRunnable.class.getName(), ".runnable(BinderTest.java:",
    -          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
    +          "for field at " + NeedsRunnable.class.getName(),
    +          ".runnable(BinderTest.java:",
    +          "at " + getClass().getName(),
    +          getDeclaringSourcePart(getClass()));
         }
       }
     
    @@ -147,14 +182,17 @@
     
       public void testDanglingConstantBinding() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override public void configure() {
    -          bindConstant();
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              bindConstant();
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "1) Missing constant value. Please call to(...).",
               "at " + getClass().getName());
         }
    @@ -162,31 +200,38 @@
     
       public void testRecursiveBinding() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override public void configure() {
    -          bind(Runnable.class).to(Runnable.class);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              bind(Runnable.class).to(Runnable.class);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "1) Binding points to itself.",
    -          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
    +          "at " + getClass().getName(),
    +          getDeclaringSourcePart(getClass()));
         }
       }
     
       public void testBindingNullConstant() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override public void configure() {
    -          String none = null;
    -          bindConstant().annotatedWith(Names.named("nullOne")).to(none);
    -          bind(String.class).annotatedWith(Names.named("nullTwo")).toInstance(none);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              String none = null;
    +              bindConstant().annotatedWith(Names.named("nullOne")).to(none);
    +              bind(String.class).annotatedWith(Names.named("nullTwo")).toInstance(none);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "1) Binding to null instances is not allowed. Use toProvider(Providers.of(null))",
               "2) Binding to null instances is not allowed. Use toProvider(Providers.of(null))");
         }
    @@ -194,24 +239,29 @@
     
       public void testToStringOnBinderApi() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override public void configure() {
    -          assertEquals("Binder", binder().toString());
    -          assertEquals("Provider", getProvider(Integer.class).toString());
    -          assertEquals("Provider>",
    -              getProvider(Key.get(new TypeLiteral>() {})).toString());
    -
    -          assertEquals("BindingBuilder",
    -              bind(Integer.class).toString());
    -          assertEquals("BindingBuilder",
    -              bind(Integer.class).annotatedWith(Names.named("a")).toString());
    -          assertEquals("ConstantBindingBuilder", bindConstant().toString());
    -          assertEquals("ConstantBindingBuilder",
    -              bindConstant().annotatedWith(Names.named("b")).toString());
    -          assertEquals("AnnotatedElementBuilder",
    -              binder().newPrivateBinder().expose(Integer.class).toString());
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              assertEquals("Binder", binder().toString());
    +              assertEquals("Provider", getProvider(Integer.class).toString());
    +              assertEquals(
    +                  "Provider>",
    +                  getProvider(Key.get(new TypeLiteral>() {})).toString());
    +
    +              assertEquals("BindingBuilder", bind(Integer.class).toString());
    +              assertEquals(
    +                  "BindingBuilder",
    +                  bind(Integer.class).annotatedWith(Names.named("a")).toString());
    +              assertEquals("ConstantBindingBuilder", bindConstant().toString());
    +              assertEquals(
    +                  "ConstantBindingBuilder",
    +                  bindConstant().annotatedWith(Names.named("b")).toString());
    +              assertEquals(
    +                  "AnnotatedElementBuilder",
    +                  binder().newPrivateBinder().expose(Integer.class).toString());
    +            }
    +          });
           fail();
         } catch (CreationException ignored) {
         }
    @@ -219,42 +269,45 @@
     
       public void testNothingIsSerializableInBinderApi() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override public void configure() {
    -          try {
    -            assertNotSerializable(binder());
    -            assertNotSerializable(getProvider(Integer.class));
    -            assertNotSerializable(getProvider(Key.get(new TypeLiteral>() {})));
    -            assertNotSerializable(bind(Integer.class));
    -            assertNotSerializable(bind(Integer.class).annotatedWith(Names.named("a")));
    -            assertNotSerializable(bindConstant());
    -            assertNotSerializable(bindConstant().annotatedWith(Names.named("b")));
    -          } catch (IOException e) {
    -            fail(e.getMessage());
    -          }
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            public void configure() {
    +              try {
    +                assertNotSerializable(binder());
    +                assertNotSerializable(getProvider(Integer.class));
    +                assertNotSerializable(getProvider(Key.get(new TypeLiteral>() {})));
    +                assertNotSerializable(bind(Integer.class));
    +                assertNotSerializable(bind(Integer.class).annotatedWith(Names.named("a")));
    +                assertNotSerializable(bindConstant());
    +                assertNotSerializable(bindConstant().annotatedWith(Names.named("b")));
    +              } catch (IOException e) {
    +                fail(e.getMessage());
    +              }
    +            }
    +          });
           fail();
         } catch (CreationException ignored) {
         }
       }
     
       /**
    -   * Although {@code String[].class} isn't equal to {@code new
    -   * GenericArrayTypeImpl(String.class)}, Guice should treat these two types
    -   * interchangeably.
    +   * Although {@code String[].class} isn't equal to {@code new GenericArrayTypeImpl(String.class)},
    +   * Guice should treat these two types interchangeably.
        */
       public void testArrayTypeCanonicalization() {
    -    final String[] strings = new String[] { "A" };
    -    final Integer[] integers = new Integer[] { 1 };
    +    final String[] strings = new String[] {"A"};
    +    final Integer[] integers = new Integer[] {1};
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bind(String[].class).toInstance(strings);
    -        bind(new TypeLiteral() {}).toInstance(integers);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(String[].class).toInstance(strings);
    +                bind(new TypeLiteral() {}).toInstance(integers);
    +              }
    +            });
     
         assertSame(integers, injector.getInstance(Key.get(new TypeLiteral() {})));
         assertSame(integers, injector.getInstance(new Key() {}));
    @@ -264,154 +317,170 @@
         assertSame(strings, injector.getInstance(String[].class));
     
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          bind(String[].class).toInstance(new String[] { "A" });
    -          bind(new TypeLiteral() {}).toInstance(new String[] { "B" });
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(String[].class).toInstance(new String[] {"A"});
    +              bind(new TypeLiteral() {}).toInstance(new String[] {"B"});
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "1) A binding to java.lang.String[] was already configured at " + getClass().getName(),
    -          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
    +          "at " + getClass().getName(),
    +          getDeclaringSourcePart(getClass()));
           assertContains(expected.getMessage(), "1 error");
         }
     
         // passes because duplicates are ignored
    -    injector = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bind(String[].class).toInstance(strings);
    -        bind(new TypeLiteral() {}).toInstance(strings);
    -      }
    -    });
    +    injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(String[].class).toInstance(strings);
    +                bind(new TypeLiteral() {}).toInstance(strings);
    +              }
    +            });
         assertSame(strings, injector.getInstance(Key.get(new TypeLiteral() {})));
         assertSame(strings, injector.getInstance(new Key() {}));
         assertSame(strings, injector.getInstance(String[].class));
       }
     
       static class ParentModule extends AbstractModule {
    -    @Override protected void configure() {
    +    @Override
    +    protected void configure() {
           install(new FooModule());
           install(new BarModule());
         }
       }
    +
       static class FooModule extends AbstractModule {
    -    @Override protected void configure() {
    +    @Override
    +    protected void configure() {
           install(new ConstantModule("foo"));
         }
       }
    +
       static class BarModule extends AbstractModule {
    -    @Override protected void configure() {
    +    @Override
    +    protected void configure() {
           install(new ConstantModule("bar"));
         }
       }
    +
       static class ConstantModule extends AbstractModule {
         private final String constant;
    +
         ConstantModule(String constant) {
           this.constant = constant;
         }
    -    @Override protected void configure() {
    +
    +    @Override
    +    protected void configure() {
           bind(String.class).toInstance(constant);
         }
       }
     
    -  /**
    -   * Binding something to two different things should give an error.
    -   */
    +  /** Binding something to two different things should give an error. */
       public void testSettingBindingTwice() {
         try {
           Guice.createInjector(new ParentModule());
           fail();
    -    } catch(CreationException expected) {
    -      assertContains(expected.getMessage(),
    -        "1) A binding to java.lang.String was already configured at " + ConstantModule.class.getName(),
    -        asModuleChain(ParentModule.class, FooModule.class, ConstantModule.class),
    -        "at " + ConstantModule.class.getName(), getDeclaringSourcePart(getClass()),
    -        asModuleChain(ParentModule.class, BarModule.class, ConstantModule.class));
    +    } catch (CreationException expected) {
    +      assertContains(
    +          expected.getMessage(),
    +          "1) A binding to java.lang.String was already configured at "
    +              + ConstantModule.class.getName(),
    +          asModuleChain(ParentModule.class, FooModule.class, ConstantModule.class),
    +          "at " + ConstantModule.class.getName(),
    +          getDeclaringSourcePart(getClass()),
    +          asModuleChain(ParentModule.class, BarModule.class, ConstantModule.class));
           assertContains(expected.getMessage(), "1 error");
         }
       }
     
    -  /**
    -   * Binding an @ImplementedBy thing to something else should also fail.
    -   */
    +  /** Binding an @ImplementedBy thing to something else should also fail. */
       public void testSettingAtImplementedByTwice() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          bind(HasImplementedBy1.class);
    -          bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(HasImplementedBy1.class);
    +              bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
    +            }
    +          });
           fail();
    -    } catch(CreationException expected) {
    +    } catch (CreationException expected) {
           expected.printStackTrace();
    -      assertContains(expected.getMessage(),
    -        "1) A binding to " + HasImplementedBy1.class.getName()
    -        + " was already configured at " + getClass().getName(),
    -        "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
    +      assertContains(
    +          expected.getMessage(),
    +          "1) A binding to "
    +              + HasImplementedBy1.class.getName()
    +              + " was already configured at "
    +              + getClass().getName(),
    +          "at " + getClass().getName(),
    +          getDeclaringSourcePart(getClass()));
           assertContains(expected.getMessage(), "1 error");
         }
       }
     
    -  /**
    -   * See issue 614, Problem One
    -   * https://github.com/google/guice/issues/614
    -   */
    +  /** See issue 614, Problem One https://github.com/google/guice/issues/614 */
       public void testJitDependencyDoesntBlockOtherExplicitBindings() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bind(HasImplementedByThatNeedsAnotherImplementedBy.class);
    -        bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(HasImplementedByThatNeedsAnotherImplementedBy.class);
    +                bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
    +              }
    +            });
         injector.getAllBindings(); // just validate it doesn't throw.
         // Also validate that we're using the explicit (and not @ImplementedBy) implementation
    -    assertFalse(injector.getInstance(HasImplementedBy1.class) instanceof ImplementsHasImplementedBy1);
    +    assertFalse(
    +        injector.getInstance(HasImplementedBy1.class) instanceof ImplementsHasImplementedBy1);
       }
     
    -  /**
    -   * See issue 614, Problem Two
    -   * https://github.com/google/guice/issues/id=614
    -   */
    +  /** See issue 614, Problem Two https://github.com/google/guice/issues/id=614 */
       public void testJitDependencyCanUseExplicitDependencies() {
    -    Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bind(HasImplementedByThatWantsExplicit.class);
    -        bind(JustAnInterface.class).toInstance(new JustAnInterface() {});
    -      }
    -    });
    +    Guice.createInjector(
    +        new AbstractModule() {
    +          @Override
    +          protected void configure() {
    +            bind(HasImplementedByThatWantsExplicit.class);
    +            bind(JustAnInterface.class).toInstance(new JustAnInterface() {});
    +          }
    +        });
       }
     
       /**
    -   * Untargetted bindings should follow @ImplementedBy and @ProvidedBy
    -   * annotations if they exist. Otherwise the class should be constructed
    -   * directly.
    +   * Untargetted bindings should follow @ImplementedBy and @ProvidedBy annotations if they exist.
    +   * Otherwise the class should be constructed directly.
        */
       public void testUntargettedBinding() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bind(HasProvidedBy1.class);
    -        bind(HasImplementedBy1.class);
    -        bind(HasProvidedBy2.class);
    -        bind(HasImplementedBy2.class);
    -        bind(JustAClass.class);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(HasProvidedBy1.class);
    +                bind(HasImplementedBy1.class);
    +                bind(HasProvidedBy2.class);
    +                bind(HasImplementedBy2.class);
    +                bind(JustAClass.class);
    +              }
    +            });
     
         assertNotNull(injector.getInstance(HasProvidedBy1.class));
         assertNotNull(injector.getInstance(HasImplementedBy1.class));
    -    assertNotSame(HasProvidedBy2.class,
    -        injector.getInstance(HasProvidedBy2.class).getClass());
    -    assertSame(ExtendsHasImplementedBy2.class,
    -        injector.getInstance(HasImplementedBy2.class).getClass());
    +    assertNotSame(HasProvidedBy2.class, injector.getInstance(HasProvidedBy2.class).getClass());
    +    assertSame(
    +        ExtendsHasImplementedBy2.class, injector.getInstance(HasImplementedBy2.class).getClass());
         assertSame(JustAClass.class, injector.getInstance(JustAClass.class).getClass());
       }
     
    @@ -421,21 +490,25 @@
           injector.getInstance(MissingParameter.class);
           fail();
         } catch (ConfigurationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "1) Could not find a suitable constructor in " + NoInjectConstructor.class.getName(),
    -          "at " + MissingParameter.class.getName() + ".(BinderTest.java:");
    +          "for the 1st parameter of "
    +              + MissingParameter.class.getName()
    +              + ".(BinderTest.java:");
         }
       }
     
       public void testUserReportedError() {
         final Message message = new Message(getClass(), "Whoops!");
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          addError(message);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              addError(message);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
           assertSame(message, Iterables.getOnlyElement(expected.getErrorMessages()));
    @@ -444,48 +517,55 @@
     
       public void testUserReportedErrorsAreAlsoLogged() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          addError(new Message("Whoops!", new IllegalArgumentException()));
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              addError(new Message("Whoops!", new IllegalArgumentException()));
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
         }
     
         LogRecord logRecord = Iterables.getOnlyElement(this.logRecords);
    -    assertContains(logRecord.getMessage(),
    +    assertContains(
    +        logRecord.getMessage(),
             "An exception was caught and reported. Message: java.lang.IllegalArgumentException");
       }
     
       public void testBindingToProvider() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          bind(new TypeLiteral>() {}).toInstance(Providers.of("A"));
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(new TypeLiteral>() {}).toInstance(Providers.of("A"));
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "1) Binding to Provider is not allowed.",
    -          "at " + BinderTest.class.getName(), getDeclaringSourcePart(getClass()));
    +          "at " + BinderTest.class.getName(),
    +          getDeclaringSourcePart(getClass()));
         }
       }
     
       static class OuterCoreModule extends AbstractModule {
    -    @Override protected void configure() {
    +    @Override
    +    protected void configure() {
           install(new InnerCoreModule());
         }
       }
    +
       static class InnerCoreModule extends AbstractModule {
         final Named red = Names.named("red");
     
    -    @Override protected void configure() {
    -      bind(AbstractModule.class).annotatedWith(red)
    -      .toProvider(Providers.of(null));
    +    @Override
    +    protected void configure() {
    +      bind(AbstractModule.class).annotatedWith(red).toProvider(Providers.of(null));
           bind(Binder.class).annotatedWith(red).toProvider(Providers.of(null));
           bind(Binding.class).annotatedWith(red).toProvider(Providers.of(null));
           bind(Injector.class).annotatedWith(red).toProvider(Providers.of(null));
    @@ -498,52 +578,44 @@
           bind(new TypeLiteral>() {}).toProvider(Providers.>of(null));
         }
       }
    +
       public void testCannotBindToGuiceTypes() {
         try {
           Guice.createInjector(new OuterCoreModule());
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "Binding to core guice framework type is not allowed: AbstractModule.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Binder.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Binding.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Injector.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Key.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Module.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to Provider is not allowed.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Scope.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Stage.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: TypeLiteral.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
    -
               "Binding to core guice framework type is not allowed: Key.",
               "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
               asModuleChain(OuterCoreModule.class, InnerCoreModule.class));
    @@ -551,7 +623,8 @@
       }
     
       static class MissingParameter {
    -    @Inject MissingParameter(NoInjectConstructor noInjectConstructor) {}
    +    @Inject
    +    MissingParameter(NoInjectConstructor noInjectConstructor) {}
       }
     
       static class NoInjectConstructor {
    @@ -562,6 +635,7 @@
       interface HasProvidedBy1 {}
     
       static class HasProvidedBy1Provider implements Provider {
    +    @Override
         public HasProvidedBy1 get() {
           return new HasProvidedBy1() {};
         }
    @@ -576,6 +650,7 @@
       static class HasProvidedBy2 {}
     
       static class HasProvidedBy2Provider implements Provider {
    +    @Override
         public HasProvidedBy2 get() {
           return new HasProvidedBy2() {};
         }
    @@ -589,44 +664,46 @@
       static class JustAClass {}
     
       @ImplementedBy(ImplementsHasImplementedByThatNeedsAnotherImplementedBy.class)
    -  static interface HasImplementedByThatNeedsAnotherImplementedBy {
    -  }
    +  static interface HasImplementedByThatNeedsAnotherImplementedBy {}
     
       static class ImplementsHasImplementedByThatNeedsAnotherImplementedBy
    -    implements HasImplementedByThatNeedsAnotherImplementedBy {
    +      implements HasImplementedByThatNeedsAnotherImplementedBy {
         @Inject
    -    ImplementsHasImplementedByThatNeedsAnotherImplementedBy(
    -        HasImplementedBy1 h1n1) {}
    +    ImplementsHasImplementedByThatNeedsAnotherImplementedBy(HasImplementedBy1 h1n1) {}
       }
     
       @ImplementedBy(ImplementsHasImplementedByThatWantsExplicit.class)
    -  static interface HasImplementedByThatWantsExplicit {
    -  }
    +  static interface HasImplementedByThatWantsExplicit {}
     
       static class ImplementsHasImplementedByThatWantsExplicit
           implements HasImplementedByThatWantsExplicit {
    -    @Inject ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai) {}
    +    @Inject
    +    ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai) {}
       }
     
       static interface JustAnInterface {}
     
    -
    -//  public void testBindInterfaceWithoutImplementation() {
    -//    Guice.createInjector(new AbstractModule() {
    -//      protected void configure() {
    -//        bind(Runnable.class);
    -//      }
    -//    }).getInstance(Runnable.class);
    -//  }
    -
    -  enum Roshambo { ROCK, SCISSORS, PAPER }
    +  //  public void testBindInterfaceWithoutImplementation() {
    +  //    Guice.createInjector(new AbstractModule() {
    +  //      protected void configure() {
    +  //        bind(Runnable.class);
    +  //      }
    +  //    }).getInstance(Runnable.class);
    +  //  }
    +
    +  enum Roshambo {
    +    ROCK,
    +    SCISSORS,
    +    PAPER
    +  }
     
       public void testInjectRawProvider() {
         try {
           Guice.createInjector().getInstance(Provider.class);
           fail();
         } catch (ConfigurationException expected) {
    -      Asserts.assertContains(expected.getMessage(),
    +      Asserts.assertContains(
    +          expected.getMessage(),
               "1) Cannot inject a Provider that has no type parameter",
               "while locating " + Provider.class.getName());
         }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BinderTestSuite.java sisu-guice-4.2.0/core/test/com/google/inject/BinderTestSuite.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BinderTestSuite.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BinderTestSuite.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2008 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -28,20 +28,16 @@
     import com.google.inject.binder.ScopedBindingBuilder;
     import com.google.inject.name.Named;
     import com.google.inject.util.Providers;
    -
    -import junit.framework.Test;
    -import junit.framework.TestCase;
    -import junit.framework.TestSuite;
    -
     import java.lang.annotation.Retention;
     import java.lang.annotation.Target;
     import java.util.Collections;
     import java.util.List;
     import java.util.concurrent.atomic.AtomicInteger;
    +import junit.framework.Test;
    +import junit.framework.TestCase;
    +import junit.framework.TestSuite;
     
    -/**
    - * @author jessewilson@google.com (Jesse Wilson)
    - */
    +/** @author jessewilson@google.com (Jesse Wilson) */
     public class BinderTestSuite extends TestCase {
     
       public static Test suite() {
    @@ -49,32 +45,39 @@
     
         new Builder()
             .name("bind A")
    -        .module(new AbstractModule() {
    -          protected void configure() {
    -            bind(A.class);
    -          }
    -        })
    +        .module(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class);
    +              }
    +            })
             .creationException("No implementation for %s was bound", A.class.getName())
             .addToSuite(suite);
     
         new Builder()
             .name("bind PlainA named apple")
    -        .module(new AbstractModule() {
    -          protected void configure() {
    -            bind(PlainA.class).annotatedWith(named("apple"));
    -          }
    -        })
    -        .creationException("No implementation for %s annotated with %s was bound",
    +        .module(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(PlainA.class).annotatedWith(named("apple"));
    +              }
    +            })
    +        .creationException(
    +            "No implementation for %s annotated with %s was bound",
                 PlainA.class.getName(), named("apple"))
             .addToSuite(suite);
     
         new Builder()
             .name("bind A to new PlainA(1)")
    -        .module(new AbstractModule() {
    -          protected void configure() {
    -            bind(A.class).toInstance(new PlainA(1));
    -          }
    -        })
    +        .module(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class).toInstance(new PlainA(1));
    +              }
    +            })
             .creationTime(CreationTime.NONE)
             .expectedValues(new PlainA(1), new PlainA(1), new PlainA(1))
             .addToSuite(suite);
    @@ -97,24 +100,27 @@
     
         new Builder()
             .name("no binding, AWithProvidedBy named apple")
    -        .key(Key.get(AWithProvidedBy.class, named("apple")),
    -            InjectsAWithProvidedByNamedApple.class)
    -        .configurationException("No implementation for %s annotated with %s was bound",
    +        .key(Key.get(AWithProvidedBy.class, named("apple")), InjectsAWithProvidedByNamedApple.class)
    +        .configurationException(
    +            "No implementation for %s annotated with %s was bound",
                 AWithProvidedBy.class.getName(), named("apple"))
             .addToSuite(suite);
     
         new Builder()
             .name("no binding, AWithImplementedBy named apple")
    -        .key(Key.get(AWithImplementedBy.class, named("apple")),
    +        .key(
    +            Key.get(AWithImplementedBy.class, named("apple")),
                 InjectsAWithImplementedByNamedApple.class)
    -        .configurationException("No implementation for %s annotated with %s was bound",
    +        .configurationException(
    +            "No implementation for %s annotated with %s was bound",
                 AWithImplementedBy.class.getName(), named("apple"))
             .addToSuite(suite);
     
         new Builder()
             .name("no binding, ScopedA named apple")
             .key(Key.get(ScopedA.class, named("apple")), InjectsScopedANamedApple.class)
    -        .configurationException("No implementation for %s annotated with %s was bound",
    +        .configurationException(
    +            "No implementation for %s annotated with %s was bound",
                 ScopedA.class.getName(), named("apple"))
             .addToSuite(suite);
     
    @@ -122,134 +128,161 @@
           new Builder()
               .name("bind PlainA")
               .key(Key.get(PlainA.class), InjectsPlainA.class)
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              AnnotatedBindingBuilder abb = bind(PlainA.class);
    -              scoper.configure(abb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  AnnotatedBindingBuilder abb = bind(PlainA.class);
    +                  scoper.configure(abb);
    +                }
    +              })
               .scoper(scoper)
               .addToSuite(suite);
     
           new Builder()
               .name("bind A to PlainA")
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              ScopedBindingBuilder sbb = bind(A.class).to(PlainA.class);
    -              scoper.configure(sbb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  ScopedBindingBuilder sbb = bind(A.class).to(PlainA.class);
    +                  scoper.configure(sbb);
    +                }
    +              })
               .scoper(scoper)
               .addToSuite(suite);
     
           new Builder()
               .name("bind A to PlainAProvider.class")
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              ScopedBindingBuilder sbb = bind(A.class).toProvider(PlainAProvider.class);
    -              scoper.configure(sbb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  ScopedBindingBuilder sbb = bind(A.class).toProvider(PlainAProvider.class);
    +                  scoper.configure(sbb);
    +                }
    +              })
               .scoper(scoper)
               .addToSuite(suite);
     
           new Builder()
               .name("bind A to new PlainAProvider()")
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              ScopedBindingBuilder sbb = bind(A.class).toProvider(new PlainAProvider());
    -              scoper.configure(sbb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  ScopedBindingBuilder sbb = bind(A.class).toProvider(new PlainAProvider());
    +                  scoper.configure(sbb);
    +                }
    +              })
               .scoper(scoper)
               .addToSuite(suite);
     
           new Builder()
               .name("bind AWithProvidedBy")
               .key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class)
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              ScopedBindingBuilder sbb = bind(AWithProvidedBy.class);
    -              scoper.configure(sbb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  ScopedBindingBuilder sbb = bind(AWithProvidedBy.class);
    +                  scoper.configure(sbb);
    +                }
    +              })
               .scoper(scoper)
               .addToSuite(suite);
     
           new Builder()
               .name("bind AWithImplementedBy")
               .key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class)
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              ScopedBindingBuilder sbb = bind(AWithImplementedBy.class);
    -              scoper.configure(sbb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  ScopedBindingBuilder sbb = bind(AWithImplementedBy.class);
    +                  scoper.configure(sbb);
    +                }
    +              })
               .scoper(scoper)
               .addToSuite(suite);
     
           new Builder()
               .name("bind ScopedA")
               .key(Key.get(ScopedA.class), InjectsScopedA.class)
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              ScopedBindingBuilder sbb = bind(ScopedA.class);
    -              scoper.configure(sbb);
    -            }
    -          })
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  ScopedBindingBuilder sbb = bind(ScopedA.class);
    +                  scoper.configure(sbb);
    +                }
    +              })
               .expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202))
               .scoper(scoper)
               .addToSuite(suite);
     
    -
           new Builder()
               .name("bind AWithProvidedBy named apple")
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              scoper.configure(bind(AWithProvidedBy.class).annotatedWith(named("apple")));
    -            }
    -          })
    -          .creationException("No implementation for %s annotated with %s was bound",
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  scoper.configure(bind(AWithProvidedBy.class).annotatedWith(named("apple")));
    +                }
    +              })
    +          .creationException(
    +              "No implementation for %s annotated with %s was bound",
                   AWithProvidedBy.class.getName(), named("apple"))
               .addToSuite(suite);
     
           new Builder()
               .name("bind AWithImplementedBy named apple")
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              scoper.configure(bind(AWithImplementedBy.class).annotatedWith(named("apple")));
    -            }
    -          })
    -          .creationException("No implementation for %s annotated with %s was bound",
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  scoper.configure(bind(AWithImplementedBy.class).annotatedWith(named("apple")));
    +                }
    +              })
    +          .creationException(
    +              "No implementation for %s annotated with %s was bound",
                   AWithImplementedBy.class.getName(), named("apple"))
               .addToSuite(suite);
     
           new Builder()
               .name("bind ScopedA named apple")
    -          .module(new AbstractModule() {
    -            protected void configure() {
    -              scoper.configure(bind(ScopedA.class).annotatedWith(named("apple")));
    -            }
    -          })
    -          .creationException("No implementation for %s annotated with %s was bound",
    +          .module(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  scoper.configure(bind(ScopedA.class).annotatedWith(named("apple")));
    +                }
    +              })
    +          .creationException(
    +              "No implementation for %s annotated with %s was bound",
                   ScopedA.class.getName(), named("apple"))
               .addToSuite(suite);
    -
         }
    -    
    +
         return suite;
       }
    -  
    +
       enum Scoper {
         UNSCOPED {
    +      @Override
           void configure(ScopedBindingBuilder sbb) {}
    +
    +      @Override
           void apply(Builder builder) {}
         },
     
         EAGER_SINGLETON {
    +      @Override
           void configure(ScopedBindingBuilder sbb) {
             sbb.asEagerSingleton();
           }
    +
    +      @Override
           void apply(Builder builder) {
             builder.expectedValues(new PlainA(101), new PlainA(101), new PlainA(101));
             builder.creationTime(CreationTime.EAGER);
    @@ -257,61 +290,79 @@
         },
     
         SCOPES_SINGLETON {
    +      @Override
           void configure(ScopedBindingBuilder sbb) {
             sbb.in(Scopes.SINGLETON);
           }
    +
    +      @Override
           void apply(Builder builder) {
             builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201));
           }
         },
     
         SINGLETON_DOT_CLASS {
    +      @Override
           void configure(ScopedBindingBuilder sbb) {
             sbb.in(Singleton.class);
           }
    +
    +      @Override
           void apply(Builder builder) {
             builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201));
           }
         },
     
         TWO_AT_A_TIME_SCOPED_DOT_CLASS {
    +      @Override
           void configure(ScopedBindingBuilder sbb) {
             sbb.in(TwoAtATimeScoped.class);
           }
    +
    +      @Override
           void apply(Builder builder) {
             builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202));
           }
         },
     
         TWO_AT_A_TIME_SCOPE {
    +      @Override
           void configure(ScopedBindingBuilder sbb) {
             sbb.in(new TwoAtATimeScope());
           }
    +
    +      @Override
           void apply(Builder builder) {
             builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202));
           }
         };
     
         abstract void configure(ScopedBindingBuilder sbb);
    +
         abstract void apply(Builder builder);
       }
     
       /** When Guice creates a value, directly or via a provider */
       enum CreationTime {
    -    NONE, EAGER, LAZY
    +    NONE,
    +    EAGER,
    +    LAZY
       }
     
       public static class Builder {
         private String name = "test";
         private Key key = Key.get(A.class);
         private Class injectsKey = InjectsA.class;
    -    private List modules = Lists.newArrayList(new AbstractModule() {
    -      protected void configure() {
    -        bindScope(TwoAtATimeScoped.class, new TwoAtATimeScope());
    -      }
    -    });
    -    private List expectedValues = Lists.newArrayList(
    -        new PlainA(201), new PlainA(202), new PlainA(203));
    +    private List modules =
    +        Lists.newArrayList(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bindScope(TwoAtATimeScoped.class, new TwoAtATimeScope());
    +              }
    +            });
    +    private List expectedValues =
    +        Lists.newArrayList(new PlainA(201), new PlainA(202), new PlainA(203));
         private CreationTime creationTime = CreationTime.LAZY;
         private String creationException;
         private String configurationException;
    @@ -391,6 +442,7 @@
           expectedValues = ImmutableList.copyOf(builder.expectedValues);
         }
     
    +    @Override
         public String getName() {
           return name;
         }
    @@ -459,6 +511,7 @@
           creationException = builder.creationException;
         }
     
    +    @Override
         public String getName() {
           return "creation errors:" + name;
         }
    @@ -489,6 +542,7 @@
           configurationException = builder.configurationException;
         }
     
    +    @Override
         public String getName() {
           return "provision errors:" + name;
         }
    @@ -523,9 +577,12 @@
             newInjector().getInstance(injectsKey);
             fail();
           } catch (ConfigurationException expected) {
    -        assertContains(expected.getMessage(),
    -            configurationException, injectsKey.getName() + ".inject",
    -            configurationException, injectsKey.getName() + ".inject",
    +        assertContains(
    +            expected.getMessage(),
    +            configurationException,
    +            injectsKey.getName() + ".inject",
    +            configurationException,
    +            injectsKey.getName() + ".inject",
                 "2 errors");
           }
     
    @@ -534,9 +591,12 @@
             newInjector().injectMembers(injectable);
             fail();
           } catch (ConfigurationException expected) {
    -        assertContains(expected.getMessage(),
    -            configurationException, injectsKey.getName() + ".inject",
    -            configurationException, injectsKey.getName() + ".inject",
    +        assertContains(
    +            expected.getMessage(),
    +            configurationException,
    +            injectsKey.getName() + ".inject",
    +            configurationException,
    +            injectsKey.getName() + ".inject",
                 "2 errors");
           }
         }
    @@ -560,6 +620,7 @@
           creationTime = builder.creationTime;
         }
     
    +    @Override
         public String getName() {
           return "provision errors:" + name;
         }
    @@ -609,9 +670,12 @@
           try {
             nextId.set(-1);
             newInjector().getInstance(injectsKey);
    +        fail("Expected ProvisionException");
           } catch (ProvisionException expected) {
    -        assertContains(expected.getMessage(), "Illegal value: -1",
    -            "for parameter 0 at " + injectsKey.getName() + ".inject");
    +        assertContains(
    +            expected.getMessage(),
    +            "Illegal value: -1",
    +            "for the 1st parameter of " + injectsKey.getName() + ".inject");
           }
     
           nextId.set(201);
    @@ -620,8 +684,10 @@
             nextId.set(-1);
             newInjector().injectMembers(injectable);
           } catch (ProvisionException expected) {
    -        assertContains(expected.getMessage(), "Illegal value: -1",
    -            "for parameter 0 at " + injectsKey.getName() + ".inject");
    +        assertContains(
    +            expected.getMessage(),
    +            "Illegal value: -1",
    +            "for the 1st parameter of " + injectsKey.getName() + ".inject");
           }
     
           nextId.set(201);
    @@ -630,6 +696,7 @@
           try {
             nextId.set(-1);
             hasProvider.provider.get();
    +        // TODO(lukes): insert fail() call here
           } catch (ProvisionException expected) {
             assertContains(expected.getMessage(), "Illegal value: -1");
           }
    @@ -643,15 +710,18 @@
       interface AWithProvidedBy {}
     
       static class InjectsAWithProvidedBy extends Injectable {
    -    @Inject public void inject(AWithProvidedBy aWithProvidedBy,
    -        Provider aWithProvidedByProvider) {
    +    @Inject
    +    public void inject(
    +        AWithProvidedBy aWithProvidedBy, Provider aWithProvidedByProvider) {
           this.value = aWithProvidedBy;
           this.provider = aWithProvidedByProvider;
         }
       }
     
       static class InjectsAWithProvidedByNamedApple extends Injectable {
    -    @Inject public void inject(@Named("apple") AWithProvidedBy aWithProvidedBy,
    +    @Inject
    +    public void inject(
    +        @Named("apple") AWithProvidedBy aWithProvidedBy,
             @Named("apple") Provider aWithProvidedByProvider) {
           this.value = aWithProvidedBy;
           this.provider = aWithProvidedByProvider;
    @@ -662,7 +732,9 @@
       interface AWithImplementedBy {}
     
       static class InjectsAWithImplementedBy extends Injectable {
    -    @Inject public void inject(AWithImplementedBy aWithImplementedBy,
    +    @Inject
    +    public void inject(
    +        AWithImplementedBy aWithImplementedBy,
             Provider aWithImplementedByProvider) {
           this.value = aWithImplementedBy;
           this.provider = aWithImplementedByProvider;
    @@ -670,7 +742,9 @@
       }
     
       static class InjectsAWithImplementedByNamedApple extends Injectable {
    -    @Inject public void inject(@Named("apple") AWithImplementedBy aWithImplementedBy,
    +    @Inject
    +    public void inject(
    +        @Named("apple") AWithImplementedBy aWithImplementedBy,
             @Named("apple") Provider aWithImplementedByProvider) {
           this.value = aWithImplementedBy;
           this.provider = aWithImplementedByProvider;
    @@ -680,7 +754,8 @@
       interface A extends AWithProvidedBy, AWithImplementedBy {}
     
       static class InjectsA extends Injectable {
    -    @Inject public void inject(A a, Provider aProvider) {
    +    @Inject
    +    public void inject(A a, Provider aProvider) {
           this.value = a;
           this.provider = aProvider;
         }
    @@ -688,45 +763,57 @@
     
       static class PlainA implements A {
         final int value;
    +
         PlainA() {
           value = nextId.getAndIncrement();
           if (value < 0) {
             throw new RuntimeException("Illegal value: " + value);
           }
         }
    +
         PlainA(int value) {
           this.value = value;
         }
    +
    +    @Override
         public boolean equals(Object obj) {
    -      return obj instanceof PlainA
    -          && value == ((PlainA) obj).value;
    +      return obj instanceof PlainA && value == ((PlainA) obj).value;
         }
    +
    +    @Override
         public int hashCode() {
           return value;
         }
    +
    +    @Override
         public String toString() {
           return "PlainA#" + value;
         }
       }
     
       static class PlainAProvider implements Provider {
    +    @Override
         public A get() {
           return new PlainA();
         }
       }
     
       static class InjectsPlainA extends Injectable {
    -    @Inject public void inject(PlainA plainA, Provider plainAProvider) {
    +    @Inject
    +    public void inject(PlainA plainA, Provider plainAProvider) {
           this.value = plainA;
           this.provider = plainAProvider;
         }
       }
     
    -  /** This scope hands out each value exactly twice  */
    +  /** This scope hands out each value exactly twice */
       static class TwoAtATimeScope implements Scope {
    +    @Override
         public  Provider scope(Key key, final Provider unscoped) {
           return new Provider() {
             T instance;
    +
    +        @Override
             public T get() {
               if (instance == null) {
                 instance = unscoped.get();
    @@ -741,22 +828,26 @@
         }
       }
     
    -  @Target({ TYPE, METHOD }) @Retention(RUNTIME) @ScopeAnnotation
    +  @Target({TYPE, METHOD})
    +  @Retention(RUNTIME)
    +  @ScopeAnnotation
       public @interface TwoAtATimeScoped {}
     
       @TwoAtATimeScoped
       static class ScopedA extends PlainA {}
     
       static class InjectsScopedA extends Injectable {
    -    @Inject public void inject(ScopedA scopedA, Provider scopedAProvider) {
    +    @Inject
    +    public void inject(ScopedA scopedA, Provider scopedAProvider) {
           this.value = scopedA;
           this.provider = scopedAProvider;
         }
       }
     
       static class InjectsScopedANamedApple extends Injectable {
    -    @Inject public void inject(@Named("apple") ScopedA scopedA,
    -        @Named("apple") Provider scopedAProvider) {
    +    @Inject
    +    public void inject(
    +        @Named("apple") ScopedA scopedA, @Named("apple") Provider scopedAProvider) {
           this.value = scopedA;
           this.provider = scopedAProvider;
         }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BindingAnnotationTest.java sisu-guice-4.2.0/core/test/com/google/inject/BindingAnnotationTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BindingAnnotationTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BindingAnnotationTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -20,24 +20,23 @@
     import static com.google.inject.Asserts.getDeclaringSourcePart;
     import static java.lang.annotation.RetentionPolicy.RUNTIME;
     
    -import junit.framework.TestCase;
    -
     import java.lang.annotation.Annotation;
     import java.lang.annotation.Retention;
    +import junit.framework.TestCase;
     
    -/**
    - * @author crazybob@google.com (Bob Lee)
    - */
    +/** @author crazybob@google.com (Bob Lee) */
     public class BindingAnnotationTest extends TestCase {
     
       public void testAnnotationWithValueMatchesKeyWithTypeOnly() throws CreationException {
    -    Injector c = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bindConstant().annotatedWith(Blue.class).to("foo");
    -        bind(BlueFoo.class);
    -      }
    -    });
    +    Injector c =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bindConstant().annotatedWith(Blue.class).to("foo");
    +                bind(BlueFoo.class);
    +              }
    +            });
     
         BlueFoo foo = c.getInstance(BlueFoo.class);
     
    @@ -46,47 +45,57 @@
     
       public void testRequireExactAnnotationsDisablesFallback() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          binder().requireExactBindingAnnotations();
    -          bindConstant().annotatedWith(Blue.class).to("foo");
    -          bind(BlueFoo.class);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              binder().requireExactBindingAnnotations();
    +              bindConstant().annotatedWith(Blue.class).to("foo");
    +              bind(BlueFoo.class);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
    +      assertContains(
    +          expected.getMessage(),
    +          true,
    +          "No implementation for java.lang.String annotated with",
               "BindingAnnotationTest$Blue(value=5) was bound",
               "at " + BindingAnnotationTest.class.getName(),
               getDeclaringSourcePart(getClass()));
         }
       }
    -  
    +
       public void testRequireExactAnnotationsDoesntBreakIfDefaultsExist() {
    -       Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          binder().requireExactBindingAnnotations();
    -          bindConstant().annotatedWith(Red.class).to("foo");
    -          bind(RedFoo.class);
    -        }
    -      }).getInstance(RedFoo.class);      
    +    Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                binder().requireExactBindingAnnotations();
    +                bindConstant().annotatedWith(Red.class).to("foo");
    +                bind(RedFoo.class);
    +              }
    +            })
    +        .getInstance(RedFoo.class);
       }
     
       public void testRequireExactAnnotationsRequireAllOptionals() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          binder().requireExactBindingAnnotations();
    -          bindConstant().annotatedWith(Color.class).to("foo");
    -          bind(ColorFoo.class);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              binder().requireExactBindingAnnotations();
    +              bindConstant().annotatedWith(Color.class).to("foo");
    +              bind(ColorFoo.class);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
    +      assertContains(
    +          expected.getMessage(),
    +          true,
    +          "No implementation for java.lang.String annotated with",
               "BindingAnnotationTest$Color",
               "at " + BindingAnnotationTest.class.getName(),
               getDeclaringSourcePart(getClass()));
    @@ -95,17 +104,21 @@
     
       public void testAnnotationWithValueThatDoesntMatch() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          bindConstant().annotatedWith(createBlue(6)).to("six");
    -          bind(String.class).toInstance("bar");
    -          bind(BlueFoo.class);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bindConstant().annotatedWith(createBlue(6)).to("six");
    +              bind(String.class).toInstance("bar");
    +              bind(BlueFoo.class);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
    +      assertContains(
    +          expected.getMessage(),
    +          true,
    +          "No implementation for java.lang.String annotated with",
               "BindingAnnotationTest$Blue(value=5) was bound",
               "at " + BindingAnnotationTest.class.getName(),
               getDeclaringSourcePart(getClass()));
    @@ -113,15 +126,19 @@
       }
     
       static class BlueFoo {
    -    @Inject @Blue(5) String s; 
    +    @Inject
    +    @Blue(5)
    +    String s;
       }
    -  
    +
       static class RedFoo {
         @Inject @Red String s;
       }
    -  
    +
       static class ColorFoo {
    -    @Inject @Color(b=2) String s;
    +    @Inject
    +    @Color(b = 2)
    +    String s;
       }
     
       @Retention(RUNTIME)
    @@ -129,39 +146,46 @@
       @interface Blue {
         int value();
       }
    -  
    +
       @Retention(RUNTIME)
       @BindingAnnotation
       @interface Red {
         int r() default 42;
    +
         int g() default 42;
    +
         int b() default 42;
       }
    -  
    +
       @Retention(RUNTIME)
       @BindingAnnotation
       @interface Color {
         int r() default 0;
    +
         int g() default 0;
    +
         int b();
       }
     
       public Blue createBlue(final int value) {
         return new Blue() {
    +      @Override
           public int value() {
             return value;
           }
     
    +      @Override
           public Class annotationType() {
             return Blue.class;
           }
     
    -      @Override public boolean equals(Object o) {
    -        return o instanceof Blue
    -            && ((Blue) o).value() == value;
    +      @Override
    +      public boolean equals(Object o) {
    +        return o instanceof Blue && ((Blue) o).value() == value;
           }
     
    -      @Override public int hashCode() {
    +      @Override
    +      public int hashCode() {
             return 127 * "value".hashCode() ^ value;
           }
         };
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BindingOrderTest.java sisu-guice-4.2.0/core/test/com/google/inject/BindingOrderTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BindingOrderTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BindingOrderTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -16,41 +16,44 @@
     
     package com.google.inject;
     
    -
    -import junit.framework.TestCase;
    -
     import java.util.concurrent.CountDownLatch;
     import java.util.concurrent.atomic.AtomicReference;
    +import junit.framework.TestCase;
     
    -/**
    - * @author jessewilson@google.com (Jesse Wilson)
    - */
    +/** @author jessewilson@google.com (Jesse Wilson) */
     
     public class BindingOrderTest extends TestCase {
     
       public void testBindingOutOfOrder() {
    -    Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(BoundFirst.class);
    -        bind(BoundSecond.class).to(BoundSecondImpl.class);
    -      }
    -    });
    +    Guice.createInjector(
    +        new AbstractModule() {
    +          @Override
    +          protected void configure() {
    +            bind(BoundFirst.class);
    +            bind(BoundSecond.class).to(BoundSecondImpl.class);
    +          }
    +        });
       }
     
       public static class BoundFirst {
    -    @Inject public BoundFirst(BoundSecond boundSecond) { }
    +    @Inject
    +    public BoundFirst(BoundSecond boundSecond) {}
       }
     
    -  interface BoundSecond { }
    -  static class BoundSecondImpl implements BoundSecond { }
    +  interface BoundSecond {}
    +
    +  static class BoundSecondImpl implements BoundSecond {}
     
       public void testBindingOrderAndScopes() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(A.class);
    -        bind(B.class).asEagerSingleton();
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class);
    +                bind(B.class).asEagerSingleton();
    +              }
    +            });
     
         assertSame(injector.getInstance(A.class).b, injector.getInstance(A.class).b);
       }
    @@ -58,34 +61,39 @@
       public void testBindingWithExtraThreads() throws InterruptedException {
         final CountDownLatch ready = new CountDownLatch(1);
         final CountDownLatch done = new CountDownLatch(1);
    -    final AtomicReference ref = new AtomicReference();
    +    final AtomicReference ref = new AtomicReference<>();
     
    -    final Object createsAThread = new Object() {
    -      @Inject void createAnotherThread(final Injector injector) {
    -        new Thread() {
    -          public void run() {
    -            ready.countDown();
    -            A a = injector.getInstance(A.class);
    -            ref.set(a.b);
    -            done.countDown();
    +    final Object createsAThread =
    +        new Object() {
    +          @Inject
    +          void createAnotherThread(final Injector injector) {
    +            new Thread() {
    +              @Override
    +              public void run() {
    +                ready.countDown();
    +                A a = injector.getInstance(A.class);
    +                ref.set(a.b);
    +                done.countDown();
    +              }
    +            }.start();
    +
    +            // to encourage collisions, we make sure the other thread is running before returning
    +            try {
    +              ready.await();
    +            } catch (InterruptedException e) {
    +              throw new RuntimeException(e);
    +            }
               }
    -        }.start();
    +        };
     
    -        // to encourage collisions, we make sure the other thread is running before returning
    -        try {
    -          ready.await();
    -        } catch (InterruptedException e) {
    -          throw new RuntimeException(e);
    -        }
    -      }
    -    };
    -
    -    Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        requestInjection(createsAThread);
    -        bind(A.class).toInstance(new A());
    -      }
    -    });
    +    Guice.createInjector(
    +        new AbstractModule() {
    +          @Override
    +          protected void configure() {
    +            requestInjection(createsAThread);
    +            bind(A.class).toInstance(new A());
    +          }
    +        });
     
         done.await();
         assertNotNull(ref.get());
    @@ -95,5 +103,5 @@
         @Inject B b;
       }
     
    -  static class B { }
    +  static class B {}
     }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BindingTest.java sisu-guice-4.2.0/core/test/com/google/inject/BindingTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BindingTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BindingTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -22,7 +22,9 @@
     import com.google.common.collect.ImmutableSet;
     import com.google.common.collect.Sets;
     import com.google.common.util.concurrent.Runnables;
    +import com.google.inject.internal.Annotations;
     import com.google.inject.matcher.Matchers;
    +import com.google.inject.name.Named;
     import com.google.inject.spi.InjectionPoint;
     import com.google.inject.spi.TypeEncounter;
     import com.google.inject.spi.TypeListener;
    @@ -35,6 +37,7 @@
     /*end[AOP]*/
     
     import java.lang.reflect.Constructor;
    +import java.util.ArrayList;
     import java.util.Collection;
     import java.util.List;
     import java.util.Map;
    @@ -54,12 +57,15 @@
       }
     
       public void testExplicitCyclicDependency() {
    -    Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(A.class);
    -        bind(B.class);
    -      }
    -    }).getInstance(A.class);
    +    Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class);
    +                bind(B.class);
    +              }
    +            })
    +        .getInstance(A.class);
       }
     
       static class A { @Inject B b; }
    @@ -69,6 +75,7 @@
     
       static class MyModule extends AbstractModule {
     
    +    @Override
         protected void configure() {
           // Linked.
           bind(Object.class).to(Runnable.class).in(Scopes.SINGLETON);
    @@ -77,11 +84,15 @@
           bind(Runnable.class).toInstance(Runnables.doNothing());
     
           // Provider instance.
    -      bind(Foo.class).toProvider(new Provider() {
    -        public Foo get() {
    -          return new Foo();
    -        }
    -      }).in(Scopes.SINGLETON);
    +      bind(Foo.class)
    +          .toProvider(
    +              new Provider() {
    +                @Override
    +                public Foo get() {
    +                  return new Foo();
    +                }
    +              })
    +          .in(Scopes.SINGLETON);
     
           // Provider.
           bind(Foo.class)
    @@ -99,6 +110,7 @@
       static class Foo {}
     
       public static class FooProvider implements Provider {
    +    @Override
         public Foo get() {
           throw new UnsupportedOperationException();
         }
    @@ -108,11 +120,13 @@
     
       public void testBindToUnboundLinkedBinding() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        protected void configure() {
    -          bind(Collection.class).to(List.class);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(Collection.class).to(List.class);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
           assertContains(expected.getMessage(), "No implementation for java.util.List was bound.");
    @@ -124,18 +138,22 @@
        * not to what the key is linked to.
        */
       public void testScopeIsAppliedToKeyNotTarget() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(Integer.class).toProvider(Counter.class).asEagerSingleton();
    -        bind(Number.class).toProvider(Counter.class).asEagerSingleton();
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(Integer.class).toProvider(Counter.class).asEagerSingleton();
    +                bind(Number.class).toProvider(Counter.class).asEagerSingleton();
    +              }
    +            });
     
         assertNotSame(injector.getInstance(Integer.class), injector.getInstance(Number.class));
       }
     
       static class Counter implements Provider {
         static AtomicInteger next = new AtomicInteger(1);
    +    @Override
         public Integer get() {
           return next.getAndIncrement();
         }
    @@ -219,19 +237,26 @@
         }
       }
     
    +  @SuppressWarnings("InjectMultipleAtInjectConstructors")
       static class TooManyConstructors {
    -    @Inject TooManyConstructors(Injector i) {}
    -    @Inject TooManyConstructors() {}
    +    @Inject
    +    TooManyConstructors(Injector i) {}
    +
    +    @Inject
    +    TooManyConstructors() {}
       }
     
       public void testToConstructorBinding() throws NoSuchMethodException {
         final Constructor constructor = D.class.getConstructor(Stage.class);
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(Object.class).toConstructor(constructor);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(Object.class).toConstructor(constructor);
    +              }
    +            });
     
         D d = (D) injector.getInstance(Object.class);
         assertEquals(Stage.DEVELOPMENT, d.stage);
    @@ -242,12 +267,15 @@
         final Key s = new Key(named("s")) {};
         final Key i = new Key(named("i")) {};
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(s).toConstructor(constructor, new TypeLiteral>() {});
    -        bind(i).toConstructor(constructor, new TypeLiteral>() {});
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(s).toConstructor(constructor, new TypeLiteral>() {});
    +                bind(i).toConstructor(constructor, new TypeLiteral>() {});
    +              }
    +            });
     
         C one = (C) injector.getInstance(s);
         assertEquals(Stage.DEVELOPMENT, one.stage);
    @@ -264,11 +292,13 @@
         final Constructor constructor = C.class.getConstructor(Stage.class, Object.class);
     
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        protected void configure() {
    -          bind(Object.class).toConstructor(constructor);
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(Object.class).toConstructor(constructor);
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
           assertContains(expected.getMessage(),
    @@ -283,19 +313,24 @@
       public void testToConstructorAndMethodInterceptors() throws NoSuchMethodException {
         final Constructor constructor = D.class.getConstructor(Stage.class);
         final AtomicInteger count = new AtomicInteger();
    -    final MethodInterceptor countingInterceptor = new MethodInterceptor() {
    -      public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    -        count.incrementAndGet();
    -        return methodInvocation.proceed();
    -      }
    -    };
    -
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(Object.class).toConstructor(constructor);
    -        bindInterceptor(Matchers.any(), Matchers.any(), countingInterceptor);
    -      }
    -    });
    +    final MethodInterceptor countingInterceptor =
    +        new MethodInterceptor() {
    +          @Override
    +          public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    +            count.incrementAndGet();
    +            return methodInvocation.proceed();
    +          }
    +        };
    +
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(Object.class).toConstructor(constructor);
    +                bindInterceptor(Matchers.any(), Matchers.any(), countingInterceptor);
    +              }
    +            });
     
         D d = (D) injector.getInstance(Object.class);
         d.hashCode();
    @@ -307,11 +342,14 @@
       public void testInaccessibleConstructor() throws NoSuchMethodException {
         final Constructor constructor = E.class.getDeclaredConstructor(Stage.class);
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(E.class).toConstructor(constructor);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(E.class).toConstructor(constructor);
    +              }
    +            });
     
         E e = injector.getInstance(E.class);
         assertEquals(Stage.DEVELOPMENT, e.stage);
    @@ -325,14 +363,17 @@
         final Key n = Key.get(Object.class, named("N")); // "N" instances
         final Key r = Key.get(Object.class, named("R")); // a regular binding
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(d).toConstructor(constructor);
    -        bind(s).toConstructor(constructor).in(Singleton.class);
    -        bind(n).toConstructor(constructor).in(Scopes.NO_SCOPE);
    -        bind(r).to(F.class);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(d).toConstructor(constructor);
    +                bind(s).toConstructor(constructor).in(Singleton.class);
    +                bind(n).toConstructor(constructor).in(Scopes.NO_SCOPE);
    +                bind(r).to(F.class);
    +              }
    +            });
     
         assertDistinct(injector, 1, d, d, d, d);
         assertDistinct(injector, 1, s, s, s, s);
    @@ -353,21 +394,25 @@
         final Set> heardTypes = Sets.newHashSet();
     
         final Constructor constructor = D.class.getConstructor(Stage.class);
    -    final TypeListener listener = new TypeListener() {
    -      public  void hear(TypeLiteral type, TypeEncounter encounter) {
    -        if (!heardTypes.add(type)) {
    -          fail("Heard " + type + " multiple times!");
    -        }
    -      }
    -    };
    -
    -    Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(Object.class).toConstructor(constructor);
    -        bind(D.class).toConstructor(constructor);
    -        bindListener(Matchers.any(), listener);
    -      }
    -    });
    +    final TypeListener listener =
    +        new TypeListener() {
    +          @Override
    +          public  void hear(TypeLiteral type, TypeEncounter encounter) {
    +            if (!heardTypes.add(type)) {
    +              fail("Heard " + type + " multiple times!");
    +            }
    +          }
    +        };
    +
    +    Guice.createInjector(
    +        new AbstractModule() {
    +          @Override
    +          protected void configure() {
    +            bind(Object.class).toConstructor(constructor);
    +            bind(D.class).toConstructor(constructor);
    +            bindListener(Matchers.any(), listener);
    +          }
    +        });
         
         assertEquals(ImmutableSet.of(TypeLiteral.get(D.class)), heardTypes);
       }
    @@ -375,11 +420,14 @@
       public void testInterfaceToImplementationConstructor() throws NoSuchMethodException {
         final Constructor constructor = CFoo.class.getDeclaredConstructor();
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(IFoo.class).toConstructor(constructor);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(IFoo.class).toConstructor(constructor);
    +              }
    +            });
     
         injector.getInstance(IFoo.class);
       }
    @@ -388,13 +436,16 @@
       public static class CFoo implements IFoo {}
     
       public void testGetAllBindings() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(D.class).toInstance(new D(Stage.PRODUCTION));
    -        bind(Object.class).to(D.class);
    -        getProvider(new Key>() {});
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(D.class).toInstance(new D(Stage.PRODUCTION));
    +                bind(Object.class).to(D.class);
    +                getProvider(new Key>() {});
    +              }
    +            });
     
         Map,Binding> bindings = injector.getAllBindings();
         assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
    @@ -419,11 +470,14 @@
       }
     
       public void testGetAllServletBindings() throws Exception {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(F.class); // an explicit binding that uses a JIT binding for a constructor
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(F.class); // an explicit binding that uses a JIT binding for a constructor
    +              }
    +            });
         injector.getAllBindings();
       }
     
    @@ -469,6 +523,7 @@
           public void configure() {
             bind(Bacon.class).to(UncookedBacon.class);
             bind(Bacon.class).annotatedWith(named("Turkey")).to(TurkeyBacon.class);
    +        bind(Bacon.class).annotatedWith(named("Tofu")).to(TofuBacon.class);
             bind(Bacon.class).annotatedWith(named("Cooked")).toConstructor(
                 (Constructor)InjectionPoint.forConstructorOf(Bacon.class).getMember());
           }
    @@ -483,21 +538,129 @@
         
         Bacon cookedBacon = injector.getInstance(Key.get(Bacon.class, named("Cooked")));
         assertEquals(Food.PORK, cookedBacon.getMaterial());
    -    assertTrue(cookedBacon.isCooked());    
    +    assertTrue(cookedBacon.isCooked());
    +
    +    try {
    +      // Turkey typo, missing a letter...
    +      injector.getInstance(Key.get(Bacon.class, named("Turky")));
    +      fail();
    +    } catch (ConfigurationException e) {
    +      String msg = e.getMessage();
    +      assertContains(
    +          msg,
    +          "Guice configuration errors:",
    +          "1) No implementation for"
    +              + " com.google.inject.BindingTest$Bacon annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("Turky")
    +              + ") was bound.",
    +          "Did you mean?",
    +          "* com.google.inject.BindingTest$Bacon annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("Turkey")
    +              + ")",
    +          "* com.google.inject.BindingTest$Bacon annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("Tofu")
    +              + ")",
    +          "1 more binding with other annotations.",
    +          "while locating com.google.inject.BindingTest$Bacon annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("Turky")
    +              + ")");
    +    }
       }
    -  
    -  enum Food { TURKEY, PORK }
    -  
    +
    +  public void testMissingAnnotationOneChoice() {
    +    Injector injector = Guice.createInjector(new AbstractModule() {
    +      @SuppressWarnings("unchecked")
    +      @Override
    +      public void configure() {
    +        bind(Bacon.class).annotatedWith(named("Turkey")).to(TurkeyBacon.class);
    +      }
    +    });
    +
    +    try {
    +      // turkey typo (should be Upper case)...
    +      injector.getInstance(Key.get(Bacon.class, named("turkey")));
    +      fail();
    +    } catch (ConfigurationException e) {
    +      String msg = e.getMessage();
    +      assertContains(msg, "Guice configuration errors:");
    +      assertContains(
    +          msg,
    +          "1) No implementation for com.google.inject.BindingTest$Bacon"
    +              + " annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("turkey")
    +              + ") was bound.",
    +          "Did you mean?",
    +          "* com.google.inject.BindingTest$Bacon annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("Turkey")
    +              + ")",
    +          "while locating com.google.inject.BindingTest$Bacon annotated with"
    +              + " @com.google.inject.name.Named(value="
    +              + Annotations.memberValueString("turkey")
    +              + ")");
    +    }
    +  }
    +
    +  enum Food { TURKEY, PORK, TOFU }
    +
       private static class Bacon {
         public Food getMaterial() { return Food.PORK; }
         public boolean isCooked() { return true; }
       }
     
       private static class TurkeyBacon extends Bacon {
    +    @Override
         public Food getMaterial() { return Food.TURKEY; }
       }
     
    +  private static class TofuBacon extends Bacon {
    +    @Override
    +    public Food getMaterial() { return Food.TOFU; }
    +  }
    +
       private static class UncookedBacon extends Bacon {
    +    @Override
         public boolean isCooked() { return false; }
       }
    +
    +  public void testMissingAnnotationRelated() {
    +    try {
    +      final TypeLiteral> list = new TypeLiteral>() {};
    +
    +      Guice.createInjector(new AbstractModule() {
    +        @SuppressWarnings("unchecked")
    +        @Override
    +        public void configure() {
    +          bind(list).toInstance(butters);
    +          bind(Sandwitch.class).to(ButterSandwitch.class);
    +        }
    +      });
    +
    +      fail();
    +    } catch (CreationException e) {
    +      final String msg = e.getMessage();
    +      assertContains(msg, "Unable to create injector, see the following errors:",
    +          "Did you mean?",
    +          "java.util.List bound"
    +          + "  at com.google.inject.BindingTest$24.configure");
    +    }
    +  }
    +
    +  private static List butters = new ArrayList<>();
    +
    +  private static interface Sandwitch {};
    +
    +  private static interface Butter {};
    +
    +  private static class ButterSandwitch implements Sandwitch {
    +    private ButterSandwitch() {};
    +
    +    @Inject
    +    ButterSandwitch(@Named("unsalted") Butter butter) {};
    +  }
     }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BoundInstanceInjectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/BoundInstanceInjectionTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BoundInstanceInjectionTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BoundInstanceInjectionTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -22,32 +22,32 @@
     import static java.lang.annotation.RetentionPolicy.RUNTIME;
     
     import com.google.inject.name.Named;
    -
    -import junit.framework.TestCase;
    -
     import java.lang.annotation.Retention;
     import java.lang.annotation.Target;
    +import junit.framework.TestCase;
     
    -/**
    - * @author crazybob@google.com (Bob Lee)
    - */
    +/** @author crazybob@google.com (Bob Lee) */
     public class BoundInstanceInjectionTest extends TestCase {
     
       public void testInstancesAreInjected() throws CreationException {
         final O o = new O();
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(O.class).toInstance(o);
    -        bind(int.class).toInstance(5);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(O.class).toInstance(o);
    +                bind(int.class).toInstance(5);
    +              }
    +            });
     
         assertEquals(5, o.fromMethod);
       }
     
       static class O {
         int fromMethod;
    +
         @Inject
         void setInt(int i) {
           this.fromMethod = i;
    @@ -55,65 +55,87 @@
       }
     
       public void testProvidersAreInjected() throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(O.class).toProvider(new Provider() {
    -          @Inject int i;
    -          public O get() {
    -            O o = new O();
    -            o.setInt(i);
    -            return o;
    -          }
    -        });
    -        bind(int.class).toInstance(5);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(O.class)
    +                    .toProvider(
    +                        new Provider() {
    +                          @Inject int i;
    +
    +                          @Override
    +                          public O get() {
    +                            O o = new O();
    +                            o.setInt(i);
    +                            return o;
    +                          }
    +                        });
    +                bind(int.class).toInstance(5);
    +              }
    +            });
     
         assertEquals(5, injector.getInstance(O.class).fromMethod);
       }
     
       public void testMalformedInstance() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        protected void configure() {
    -          bind(Object.class).toInstance(new MalformedInjectable());
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(Object.class).toInstance(new MalformedInjectable());
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      Asserts.assertContains(expected.getMessage(), MalformedInjectable.class.getName(),
    -          ".doublyAnnotated() has more than one ", "annotation annotated with @BindingAnnotation: ",
    +      Asserts.assertContains(
    +          expected.getMessage(),
    +          MalformedInjectable.class.getName(),
    +          ".doublyAnnotated() has more than one ",
    +          "annotation annotated with @BindingAnnotation: ",
               Named.class.getName() + " and " + Another.class.getName());
         }
       }
     
       public void testMalformedProvider() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        protected void configure() {
    -          bind(String.class).toProvider(new MalformedProvider());
    -        }
    -      });
    +      Guice.createInjector(
    +          new AbstractModule() {
    +            @Override
    +            protected void configure() {
    +              bind(String.class).toProvider(new MalformedProvider());
    +            }
    +          });
           fail();
         } catch (CreationException expected) {
    -      Asserts.assertContains(expected.getMessage(), MalformedProvider.class.getName(),
    -          ".doublyAnnotated() has more than one ", "annotation annotated with @BindingAnnotation: ",
    +      Asserts.assertContains(
    +          expected.getMessage(),
    +          MalformedProvider.class.getName(),
    +          ".doublyAnnotated() has more than one ",
    +          "annotation annotated with @BindingAnnotation: ",
               Named.class.getName() + " and " + Another.class.getName());
         }
       }
     
       static class MalformedInjectable {
    -    @Inject void doublyAnnotated(@Named("a") @Another String unused) {}
    +    @Inject
    +    void doublyAnnotated(@Named("a") @Another String unused) {}
       }
     
       static class MalformedProvider implements Provider {
    -    @Inject void doublyAnnotated(@Named("a") @Another String s) {}
    +    @Inject
    +    void doublyAnnotated(@Named("a") @Another String s) {}
     
    +    @Override
         public String get() {
           return "a";
         }
       }
     
    -  @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
    +  @BindingAnnotation
    +  @Target({FIELD, PARAMETER, METHOD})
    +  @Retention(RUNTIME)
       public @interface Another {}
     }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/BoundProviderTest.java sisu-guice-4.2.0/core/test/com/google/inject/BoundProviderTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/BoundProviderTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/BoundProviderTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -18,17 +18,18 @@
     
     import junit.framework.TestCase;
     
    -/**
    - * @author crazybob@google.com (Bob Lee)
    - */
    +/** @author crazybob@google.com (Bob Lee) */
     public class BoundProviderTest extends TestCase {
     
       public void testFooProvider() throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(Foo.class).toProvider(FooProvider.class);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(Foo.class).toProvider(FooProvider.class);
    +              }
    +            });
     
         Foo a = injector.getInstance(Foo.class);
         Foo b = injector.getInstance(Foo.class);
    @@ -41,11 +42,14 @@
       }
     
       public void testSingletonFooProvider() throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(Foo.class).toProvider(SingletonFooProvider.class);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(Foo.class).toProvider(SingletonFooProvider.class);
    +              }
    +            });
     
         Foo a = injector.getInstance(Foo.class);
         Foo b = injector.getInstance(Foo.class);
    @@ -79,6 +83,7 @@
           this.bar = bar;
         }
     
    +    @Override
         public Foo get() {
           return new Foo(this.bar, count++);
         }
    @@ -95,6 +100,7 @@
           this.bar = bar;
         }
     
    +    @Override
         public Foo get() {
           return new Foo(this.bar, count++);
         }
    diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/CircularDependencyTest.java sisu-guice-4.2.0/core/test/com/google/inject/CircularDependencyTest.java
    --- sisu-guice-3.2.6/core/test/com/google/inject/CircularDependencyTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/core/test/com/google/inject/CircularDependencyTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -21,88 +21,108 @@
     
     import com.google.common.collect.Iterables;
     import com.google.common.collect.Maps;
    -
    -import junit.framework.TestCase;
    -
     import java.lang.annotation.ElementType;
     import java.lang.annotation.Retention;
     import java.lang.annotation.Target;
     import java.util.ArrayList;
     import java.util.List;
     import java.util.Map;
    +import junit.framework.TestCase;
     
     /**
      * @author crazybob@google.com (Bob Lee)
      * @author sameb@google.com (Sam Berlin)
      */
     public class CircularDependencyTest extends TestCase {
    -  
    +
       @Override
       protected void setUp() throws Exception {
         AImpl.nextId = 0;
         BImpl.nextId = 0;
       }
     
    -  public void testCircularlyDependentConstructors()
    -      throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(A.class).to(AImpl.class);
    -        bind(B.class).to(BImpl.class);
    -      }
    -    });
    +  public void testCircularlyDependentConstructors() throws CreationException {
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class).to(AImpl.class);
    +                bind(B.class).to(BImpl.class);
    +              }
    +            });
         assertCircularDependencies(injector);
       }
    -  
    -  public void testCircularlyDependentConstructorsWithProviderMethods()
    -      throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {}
    -      
    -      @Provides @Singleton A a(B b) { return new AImpl(b); }
    -      @Provides B b(A a) { return new BImpl(a); }
    -    });
    +
    +  public void testCircularlyDependentConstructorsWithProviderMethods() throws CreationException {
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +
    +              @Provides
    +              @Singleton
    +              A a(B b) {
    +                return new AImpl(b);
    +              }
    +
    +              @Provides
    +              B b(A a) {
    +                return new BImpl(a);
    +              }
    +            });
         assertCircularDependencies(injector);
       }
    -  
    -  public void testCircularlyDependentConstructorsWithProviderInstances()
    -      throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(A.class).toProvider(new Provider() {
    -          @Inject Provider bp;
    -          public A get() {
    -            return new AImpl(bp.get());
    -          }
    -        }).in(Singleton.class);
    -        bind(B.class).toProvider(new Provider() {
    -          @Inject Provider ap;
    -          public B get() {
    -            return new BImpl(ap.get());
    -          }
    -        });
    -      }
    -    });
    +
    +  public void testCircularlyDependentConstructorsWithProviderInstances() throws CreationException {
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class)
    +                    .toProvider(
    +                        new Provider() {
    +                          @Inject Provider bp;
    +
    +                          @Override
    +                          public A get() {
    +                            return new AImpl(bp.get());
    +                          }
    +                        })
    +                    .in(Singleton.class);
    +                bind(B.class)
    +                    .toProvider(
    +                        new Provider() {
    +                          @Inject Provider ap;
    +
    +                          @Override
    +                          public B get() {
    +                            return new BImpl(ap.get());
    +                          }
    +                        });
    +              }
    +            });
         assertCircularDependencies(injector);
       }
    -  
    -  public void testCircularlyDependentConstructorsWithProviderKeys()
    -      throws CreationException {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(A.class).toProvider(AP.class).in(Singleton.class);
    -        bind(B.class).toProvider(BP.class);
    -      }
    -    });
    +
    +  public void testCircularlyDependentConstructorsWithProviderKeys() throws CreationException {
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(A.class).toProvider(AP.class).in(Singleton.class);
    +                bind(B.class).toProvider(BP.class);
    +              }
    +            });
         assertCircularDependencies(injector);
       }
    -  
    -  public void testCircularlyDependentConstructorsWithProvidedBy()
    -      throws CreationException {
    +
    +  public void testCircularlyDependentConstructorsWithProvidedBy() throws CreationException {
         Injector injector = Guice.createInjector();
         assertCircularDependencies(injector);
       }
    -  
    +
       private void assertCircularDependencies(Injector injector) {
         A a = injector.getInstance(A.class);
         assertNotNull(a.getB().getA());
    @@ -117,6 +137,7 @@
       @ProvidedBy(AutoAP.class)
       public interface A {
         B getB();
    +
         int id();
       }
     
    @@ -124,31 +145,40 @@
       static class AImpl implements A {
         static int nextId;
         int id = nextId++;
    -    
    +
         final B b;
    -    @Inject public AImpl(B b) {
    +
    +    @Inject
    +    public AImpl(B b) {
           this.b = b;
         }
    +
    +    @Override
         public int id() {
           return id;
         }
    +
    +    @Override
         public B getB() {
           return b;
         }
       }
    -  
    +
       static class AP implements Provider {
         @Inject Provider bp;
    +
    +    @Override
         public A get() {
           return new AImpl(bp.get());
         }
       }
    -  
    +
       @Singleton
       static class AutoAP implements Provider {
         @Inject Provider bp;
         A a;
    -    
    +
    +    @Override
         public A get() {
           if (a == null) {
             a = new AImpl(bp.get());
    @@ -160,30 +190,41 @@
       @ProvidedBy(BP.class)
       public interface B {
         A getA();
    +
         int id();
       }
     
       static class BImpl implements B {
         static int nextId;
         int id = nextId++;
    -    
    +
         final A a;
    -    @Inject public BImpl(A a) {
    +
    +    @Inject
    +    public BImpl(A a) {
           this.a = a;
         }
    +
    +    @Override
         public int id() {
           return id;
         }
    +
    +    @Override
         public A getA() {
           return a;
         }
       }
    -  
    +
       static class BP implements Provider {
         Provider ap;
    -    @Inject BP(Provider ap) {
    +
    +    @Inject
    +    BP(Provider ap) {
           this.ap = ap;
         }
    +
    +    @Override
         public B get() {
           return new BImpl(ap.get());
         }
    @@ -194,180 +235,242 @@
           Guice.createInjector().getInstance(C.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
               "but it is not an interface.");
         }
       }
    -  
    +
       public void testUnresolvableCircularDependenciesWithProviderInstances() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override protected void configure() {}        
    -        @Provides C c(D d) { return null; }
    -        @Provides D d(C c) { return null; }
    -      }).getInstance(C.class);
    +      Guice.createInjector(
    +              new AbstractModule() {
    +
    +                @Provides
    +                C c(D d) {
    +                  return null;
    +                }
    +
    +                @Provides
    +                D d(C c) {
    +                  return null;
    +                }
    +              })
    +          .getInstance(C.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
               "but it is not an interface.");
         }
       }
    -  
    +
       public void testUnresolvableCircularDependenciesWithProviderKeys() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override protected void configure() {
    -          bind(C2.class).toProvider(C2P.class);
    -          bind(D2.class).toProvider(D2P.class);
    -        }
    -      }).getInstance(C2.class);
    +      Guice.createInjector(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  bind(C2.class).toProvider(C2P.class);
    +                  bind(D2.class).toProvider(D2P.class);
    +                }
    +              })
    +          .getInstance(C2.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
               "but it is not an interface.");
         }
       }
    -  
    +
       public void testUnresolvableCircularDependenciesWithProvidedBy() {
         try {
           Guice.createInjector().getInstance(C2.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    +      assertContains(
    +          expected.getMessage(),
               "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
               "but it is not an interface.");
         }
       }
     
       static class C {
    -    @Inject C(D d) {}
    +    @Inject
    +    C(D d) {}
       }
    +
       static class D {
    -    @Inject D(C c) {}
    +    @Inject
    +    D(C c) {}
       }
    -  
    +
       static class C2P implements Provider {
         @Inject Provider dp;
    +
    +    @Override
         public C2 get() {
           dp.get();
           return null;
         }
       }
    +
       static class D2P implements Provider {
         @Inject Provider cp;
    +
    +    @Override
         public D2 get() {
           cp.get();
           return null;
         }
       }
    +
       @ProvidedBy(C2P.class)
       static class C2 {
    -    @Inject C2(D2 d) {}
    +    @Inject
    +    C2(D2 d) {}
       }
    +
       @ProvidedBy(D2P.class)
       static class D2 {
    -    @Inject D2(C2 c) {}
    +    @Inject
    +    D2(C2 c) {}
       }
    -  
    +
       public void testDisabledCircularDependency() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          binder().disableCircularProxies();
    -        }
    -      }).getInstance(C.class);
    +      Guice.createInjector(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  binder().disableCircularProxies();
    +                }
    +              })
    +          .getInstance(C.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    -          "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
    -          "but circular proxies are disabled.");
    +      assertContains(
    +          expected.getMessage(),
    +          "Found a circular dependency involving "
    +              + C.class.getName()
    +              + ", and circular dependencies are disabled.");
         }
       }
    -  
    +
       public void testDisabledCircularDependenciesWithProviderInstances() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override protected void configure() {
    -          binder().disableCircularProxies();
    -        }        
    -        @Provides C c(D d) { return null; }
    -        @Provides D d(C c) { return null; }
    -      }).getInstance(C.class);
    +      Guice.createInjector(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  binder().disableCircularProxies();
    +                }
    +
    +                @Provides
    +                C c(D d) {
    +                  return null;
    +                }
    +
    +                @Provides
    +                D d(C c) {
    +                  return null;
    +                }
    +              })
    +          .getInstance(C.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    -          "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
    -          "but circular proxies are disabled.");
    +      assertContains(
    +          expected.getMessage(),
    +          "Found a circular dependency involving "
    +              + C.class.getName()
    +              + ", and circular dependencies are disabled.");
         }
       }
    -  
    +
       public void testDisabledCircularDependenciesWithProviderKeys() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override protected void configure() {
    -          binder().disableCircularProxies();
    -          bind(C2.class).toProvider(C2P.class);
    -          bind(D2.class).toProvider(D2P.class);
    -        }
    -      }).getInstance(C2.class);
    +      Guice.createInjector(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  binder().disableCircularProxies();
    +                  bind(C2.class).toProvider(C2P.class);
    +                  bind(D2.class).toProvider(D2P.class);
    +                }
    +              })
    +          .getInstance(C2.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    -          "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
    -          "but circular proxies are disabled.");
    +      assertContains(
    +          expected.getMessage(),
    +          "Found a circular dependency involving "
    +              + C2.class.getName()
    +              + ", and circular dependencies are disabled.");
         }
       }
    -  
    +
       public void testDisabledCircularDependenciesWithProvidedBy() {
         try {
    -      Guice.createInjector(new AbstractModule() {
    -        @Override
    -        protected void configure() {
    -          binder().disableCircularProxies();
    -        }
    -      }).getInstance(C2.class);
    +      Guice.createInjector(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  binder().disableCircularProxies();
    +                }
    +              })
    +          .getInstance(C2.class);
           fail();
         } catch (ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    -          "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
    -          "but circular proxies are disabled.");
    +      assertContains(
    +          expected.getMessage(),
    +          "Found a circular dependency involving "
    +              + C2.class.getName()
    +              + ", and circular dependencies are disabled.");
         }
       }
     
       /**
    -   * As reported by issue 349, we give a lousy trace when a class is circularly
    -   * dependent on itself in multiple ways.
    +   * As reported by issue 349, we give a lousy trace when a class is circularly dependent on itself
    +   * in multiple ways.
        */
       public void testCircularlyDependentMultipleWays() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        binder.bind(A.class).to(E.class);
    -        binder.bind(B.class).to(E.class);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                binder.bind(A.class).to(E.class);
    +                binder.bind(B.class).to(E.class);
    +              }
    +            });
         injector.getInstance(A.class);
       }
    -  
    -  public void testDisablingCircularProxies() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        binder().disableCircularProxies();
    -        binder.bind(A.class).to(E.class);
    -        binder.bind(B.class).to(E.class);
    -      }
    -    });
    -    
    +
    +  public void testDisablingCircularDependencies() {
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                binder().disableCircularProxies();
    +                binder.bind(A.class).to(E.class);
    +                binder.bind(B.class).to(E.class);
    +              }
    +            });
    +
         try {
           injector.getInstance(A.class);
           fail("expected exception");
    -    } catch(ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    -          "Tried proxying " + A.class.getName() + " to support a circular dependency, but circular proxies are disabled", 
    -          "Tried proxying " + B.class.getName() + " to support a circular dependency, but circular proxies are disabled");
    +    } catch (ProvisionException expected) {
    +      assertContains(
    +          expected.getMessage(),
    +          "Found a circular dependency involving "
    +              + A.class.getName()
    +              + ", and circular dependencies are disabled.");
         }
       }
     
    @@ -376,31 +479,35 @@
         @Inject
         public E(A a, B b) {}
     
    +    @Override
         public B getB() {
           return this;
         }
     
    +    @Override
         public A getA() {
           return this;
         }
    -    
    +
    +    @Override
         public int id() {
           return 0;
         }
       }
     
    -
       public void testCircularDependencyProxyDelegateNeverInitialized() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(F.class).to(RealF.class);
    -        bind(G.class).to(RealG.class);
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(F.class).to(RealF.class);
    +                bind(G.class).to(RealG.class);
    +              }
    +            });
         F f = injector.getInstance(F.class);
         assertEquals("F", f.g().f().toString());
         assertEquals("G", f.g().f().g().toString());
    -
       }
     
       public interface F {
    @@ -410,15 +517,19 @@
       @Singleton
       public static class RealF implements F {
         private final G g;
    -    @Inject RealF(G g) {
    +
    +    @Inject
    +    RealF(G g) {
           this.g = g;
         }
     
    +    @Override
         public G g() {
           return g;
         }
     
    -    @Override public String toString() {
    +    @Override
    +    public String toString() {
           return "F";
         }
       }
    @@ -430,109 +541,128 @@
       @Singleton
       public static class RealG implements G {
         private final F f;
    -    @Inject RealG(F f) {
    +
    +    @Inject
    +    RealG(F f) {
           this.f = f;
         }
     
    +    @Override
         public F f() {
           return f;
         }
     
    -    @Override public String toString() {
    +    @Override
    +    public String toString() {
           return "G";
         }
       }
    -  
    +
       /**
    -   * Tests that ProviderInternalFactory can detect circular dependencies
    -   * before it gets to Scopes.SINGLETON.  This is especially important
    -   * because the failure in Scopes.SINGLETON doesn't have enough context to
    -   * provide a decent error message.
    +   * Tests that ProviderInternalFactory can detect circular dependencies before it gets to
    +   * Scopes.SINGLETON. This is especially important because the failure in Scopes.SINGLETON doesn't
    +   * have enough context to provide a decent error message.
        */
       public void testCircularDependenciesDetectedEarlyWhenDependenciesHaveDifferentTypes() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        bind(Number.class).to(Integer.class);
    -      }
    -      
    -      @Provides @Singleton Integer provideInteger(List list) { 
    -        return new Integer(2);
    -      }
    -      
    -      @Provides List provideList(Integer integer) {
    -        return new ArrayList();
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(Number.class).to(Integer.class);
    +              }
    +
    +              @Provides
    +              @Singleton
    +              Integer provideInteger(List list) {
    +                return 2;
    +              }
    +
    +              @Provides
    +              List provideList(Integer integer) {
    +                return new ArrayList();
    +              }
    +            });
         try {
           injector.getInstance(Number.class);
           fail();
    -    } catch(ProvisionException expected) {
    -      assertContains(expected.getMessage(),
    +    } catch (ProvisionException expected) {
    +      assertContains(
    +          expected.getMessage(),
               "Tried proxying " + Integer.class.getName() + " to support a circular dependency, ",
    -          "but it is not an interface.");      
    +          "but it is not an interface.");
         }
       }
    -  
    +
       public void testPrivateModulesDontTriggerCircularErrorsInProviders() {
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -        install(new PrivateModule() {
    -          @Override
    -          protected void configure() {
    -            bind(Foo.class);
    -            expose(Foo.class);
    -          }
    -          @Provides String provideString(Bar bar) {
    -            return new String("private 1, " + bar.string);
    -          }
    -        });
    -        install(new PrivateModule() {
    -          @Override
    -          protected void configure() {
    -            bind(Bar.class);
    -            expose(Bar.class);
    -          }
    -          @Provides String provideString() {
    -            return new String("private 2");
    -          }
    -        });
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                install(
    +                    new PrivateModule() {
    +                      @Override
    +                      protected void configure() {
    +                        bind(Foo.class);
    +                        expose(Foo.class);
    +                      }
    +
    +                      @Provides
    +                      String provideString(Bar bar) {
    +                        return new String("private 1, " + bar.string);
    +                      }
    +                    });
    +                install(
    +                    new PrivateModule() {
    +                      @Override
    +                      protected void configure() {
    +                        bind(Bar.class);
    +                        expose(Bar.class);
    +                      }
    +
    +                      @Provides
    +                      String provideString() {
    +                        return new String("private 2");
    +                      }
    +                    });
    +              }
    +            });
         Foo foo = injector.getInstance(Foo.class);
         assertEquals("private 1, private 2", foo.string);
       }
    +
       static class Foo {
         @Inject String string;
       }
    +
       static class Bar {
         @Inject String string;
       }
    -  
    +
       /**
    -   * When Scope Providers call their unscoped Provider's get() methods are
    -   * called, it's possible that the result is a circular proxy designed for one
    -   * specific parameter (not for all possible parameters). But custom scopes
    -   * typically cache the results without checking to see if the result is a
    -   * proxy. This leads to caching a result that is unsuitable for reuse for
    -   * other parameters.
    -   * 
    -   * This means that custom proxies have to do an
    -   *   {@code if(Scopes.isCircularProxy(..))}
    -   * in order to avoid exceptions.
    +   * When Scope Providers call their unscoped Provider's get() methods are called, it's possible
    +   * that the result is a circular proxy designed for one specific parameter (not for all possible
    +   * parameters). But custom scopes typically cache the results without checking to see if the
    +   * result is a proxy. This leads to caching a result that is unsuitable for reuse for other
    +   * parameters.
    +   *
    +   * 

    This means that custom proxies have to do an {@code if(Scopes.isCircularProxy(..))} in order + * to avoid exceptions. */ public void testCustomScopeCircularProxies() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindScope(SimpleSingleton.class, new BasicSingleton()); - bind(H.class).to(HImpl.class); - bind(I.class).to(IImpl.class); - bind(J.class).to(JImpl.class); - } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(SimpleSingleton.class, new BasicSingleton()); + bind(H.class).to(HImpl.class); + bind(I.class).to(IImpl.class); + bind(J.class).to(JImpl.class); + } + }); + // The reason this happens is because the Scope gets these requests, in order: // entry: Key (1 - from getInstance call) // entry: Key @@ -540,47 +670,61 @@ // result of 2nd Key - a com.google.inject.$Proxy, because it's a circular proxy // result of Key - an HImpl // entry: Key - // entry: Key (3 - another circular dependency, this time from JImpl) + // entry: Key (3 - another circular dependency, this time from JImpl) // At this point, if the first Key result was cached, our cache would have // Key caching to an instanceof of I, but not an an instanceof of IImpl. // If returned this, it would result in cglib giving a ClassCastException or // java reflection giving an IllegalArgumentException when filling in parameters // for the constructor, because JImpl wants an IImpl, not an I. - + try { injector.getInstance(IImpl.class); fail(); - } catch(ProvisionException pe) { - assertContains(Iterables.getOnlyElement(pe.getErrorMessages()).getMessage(), - "Tried proxying " + IImpl.class.getName() - + " to support a circular dependency, but it is not an interface."); + } catch (ProvisionException pe) { + assertContains( + Iterables.getOnlyElement(pe.getErrorMessages()).getMessage(), + "Tried proxying " + + IImpl.class.getName() + + " to support a circular dependency, but it is not an interface."); } } - + interface H {} + interface I {} + interface J {} + @SimpleSingleton static class HImpl implements H { - @Inject HImpl(I i) {} + @Inject + HImpl(I i) {} } + @SimpleSingleton static class IImpl implements I { - @Inject IImpl(HImpl i, J j) {} + @Inject + IImpl(HImpl i, J j) {} } + @SimpleSingleton static class JImpl implements J { - @Inject JImpl(IImpl i) {} + @Inject + JImpl(IImpl i) {} } - - @Target({ ElementType.TYPE, ElementType.METHOD }) + + @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RUNTIME) @ScopeAnnotation public @interface SimpleSingleton {} + public static class BasicSingleton implements Scope { - private static Map cache = Maps.newHashMap(); + private static Map, Object> cache = Maps.newHashMap(); + + @Override public Provider scope(final Key key, final Provider unscoped) { return new Provider() { + @Override @SuppressWarnings("unchecked") public T get() { if (!cache.containsKey(key)) { @@ -590,9 +734,51 @@ } cache.put(key, t); } - return (T)cache.get(key); + return (T) cache.get(key); } }; } } + + public void testDisabledNonConstructorCircularDependencies() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().disableCircularProxies(); + } + }); + + try { + injector.getInstance(K.class); + fail("expected exception"); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "Found a circular dependency involving " + + K.class.getName() + + ", and circular dependencies are disabled."); + } + + try { + injector.getInstance(L.class); + fail("expected exception"); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "Found a circular dependency involving " + + L.class.getName() + + ", and circular dependencies are disabled."); + } + } + + static class K { + @Inject L l; + } + + static class L { + @Inject + void inject(K k) {} + } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/DuplicateBindingsTest.java sisu-guice-4.2.0/core/test/com/google/inject/DuplicateBindingsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/DuplicateBindingsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/DuplicateBindingsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,9 +25,6 @@ import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.util.Arrays; @@ -35,14 +32,15 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.logging.Logger; +import junit.framework.TestCase; /** * A suite of tests for duplicate bindings. - * + * * @author sameb@google.com (Sam Berlin) */ public class DuplicateBindingsTest extends TestCase { - + private FooImpl foo = new FooImpl(); private Provider pFoo = Providers.of(new FooImpl()); private Class> pclFoo = FooProvider.class; @@ -50,13 +48,13 @@ private Constructor cFoo = FooImpl.cxtor(); public void testDuplicateBindingsAreIgnored() { - Injector injector = Guice.createInjector( - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) - ); + Injector injector = + Guice.createInjector( + new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), + new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)); List> bindings = Lists.newArrayList(injector.getAllBindings().keySet()); removeBasicBindings(bindings); - + // Ensure only one binding existed for each type. assertTrue(bindings.remove(Key.get(Foo.class, named("instance")))); assertTrue(bindings.remove(Key.get(Foo.class, named("pInstance")))); @@ -66,88 +64,119 @@ assertTrue(bindings.remove(Key.get(Foo.class, named("constructor")))); assertTrue(bindings.remove(Key.get(FooProvider.class))); // JIT binding assertTrue(bindings.remove(Key.get(Foo.class, named("providerMethod")))); - + assertEquals(bindings.toString(), 0, bindings.size()); } - + public void testElementsDeduplicate() { - List elements = Elements.getElements( - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) - ); + List elements = + Elements.getElements( + new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), + new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)); assertEquals(14, elements.size()); assertEquals(7, new LinkedHashSet(elements).size()); } - + public void testProviderMethodsFailIfInstancesDiffer() { try { Guice.createInjector(new FailingProviderModule(), new FailingProviderModule()); fail("should have failed"); - } catch(CreationException ce) { - assertContains(ce.getMessage(), - "A binding to " + Foo.class.getName() + " was already configured " + - "at " + FailingProviderModule.class.getName(), - "at " + FailingProviderModule.class.getName() - ); + } catch (CreationException ce) { + assertContains( + ce.getMessage(), + "A binding to " + + Foo.class.getName() + + " was already configured " + + "at " + + FailingProviderModule.class.getName(), + "at " + FailingProviderModule.class.getName()); } } - + public void testSameScopeInstanceIgnored() { Guice.createInjector( new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo), - new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo) - ); - + new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo)); + Guice.createInjector( new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo), - new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo) - ); + new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo)); } - + public void testSameScopeAnnotationIgnored() { Guice.createInjector( new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo), - new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo) - ); + new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo)); } - + public void testMixedAnnotationAndScopeForSingletonIgnored() { Guice.createInjector( new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo), - new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo) - ); + new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo)); } - + public void testMixedScopeAndUnscopedIgnored() { Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), - new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo) - ); + new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo)); } public void testMixedScopeFails() { try { Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), - new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo) - ); + new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo)); fail("expected exception"); - } catch(CreationException ce) { - String segment1 = "A binding to " + Foo.class.getName() + " annotated with " - + named("pInstance") + " was already configured at " + SimpleModule.class.getName(); - String segment2 = "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") - + " was already configured at " + SimpleModule.class.getName(); - String segment3 = "A binding to " + Foo.class.getName() + " annotated with " - + named("constructor") + " was already configured at " + SimpleModule.class.getName(); - String segment4 = "A binding to " + FooImpl.class.getName() + " was already configured at " - + SimpleModule.class.getName(); + } catch (CreationException ce) { + String segment1 = + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("pInstance") + + " was already configured at " + + SimpleModule.class.getName(); + String segment2 = + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("pKey") + + " was already configured at " + + SimpleModule.class.getName(); + String segment3 = + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("constructor") + + " was already configured at " + + SimpleModule.class.getName(); + String segment4 = + "A binding to " + + FooImpl.class.getName() + + " was already configured at " + + SimpleModule.class.getName(); String atSegment = "at " + ScopedModule.class.getName(); if (isIncludeStackTraceOff()) { - assertContains(ce.getMessage(), segment1 , atSegment, segment2, atSegment, segment3, - atSegment, segment4, atSegment); + assertContains( + ce.getMessage(), + segment1, + atSegment, + segment2, + atSegment, + segment3, + atSegment, + segment4, + atSegment); } else { - assertContains(ce.getMessage(), segment1 , atSegment, segment2, atSegment, segment4, - atSegment, segment3, atSegment); + assertContains( + ce.getMessage(), + segment1, + atSegment, + segment2, + atSegment, + segment4, + atSegment, + segment3, + atSegment); } } } @@ -157,90 +186,138 @@ try { Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), - new SimpleModule(new FooImpl(), Providers.of(new FooImpl()), - (Class)BarProvider.class, (Class)Bar.class, (Constructor)Bar.cxtor()) - ); + new SimpleModule( + new FooImpl(), + Providers.of(new FooImpl()), + (Class) BarProvider.class, + (Class) Bar.class, + (Constructor) Bar.cxtor())); fail("expected exception"); - } catch(CreationException ce) { - assertContains(ce.getMessage(), - "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(), - "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(), - "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(), + } catch (CreationException ce) { + assertContains( + ce.getMessage(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("pInstance") + + " was already configured at " + + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("pKey") + + " was already configured at " + + SimpleModule.class.getName(), + "at " + SimpleModule.class.getName(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("linkedKey") + + " was already configured at " + + SimpleModule.class.getName(), + "at " + SimpleModule.class.getName(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("constructor") + + " was already configured at " + + SimpleModule.class.getName(), "at " + SimpleModule.class.getName()); } } - + public void testExceptionInEqualsThrowsCreationException() { try { Guice.createInjector(new ThrowingModule(), new ThrowingModule()); fail("expected exception"); - } catch(CreationException ce) { - assertContains(ce.getMessage(), - "A binding to " + Foo.class.getName() + " was already configured at " + ThrowingModule.class.getName(), + } catch (CreationException ce) { + assertContains( + ce.getMessage(), + "A binding to " + + Foo.class.getName() + + " was already configured at " + + ThrowingModule.class.getName(), "and an error was thrown while checking duplicate bindings. Error: java.lang.RuntimeException: Boo!", "at " + ThrowingModule.class.getName()); } } - + public void testChildInjectorDuplicateParentFail() { - Injector injector = Guice.createInjector( - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) - ); - + Injector injector = Guice.createInjector(new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)); + try { - injector.createChildInjector( - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) - ); + injector.createChildInjector(new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)); fail("expected exception"); - } catch(CreationException ce) { - assertContains(ce.getMessage(), - "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(), - "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(), - "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(), + } catch (CreationException ce) { + assertContains( + ce.getMessage(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("pInstance") + + " was already configured at " + + SimpleModule.class.getName(), + "at " + SimpleModule.class.getName(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("pKey") + + " was already configured at " + + SimpleModule.class.getName(), + "at " + SimpleModule.class.getName(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("linkedKey") + + " was already configured at " + + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(), + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("constructor") + + " was already configured at " + + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), - "A binding to " + Foo.class.getName() + " annotated with " + named("providerMethod") + " was already configured at " + SimpleProviderModule.class.getName(), - "at " + SimpleProviderModule.class.getName() - ); - } - - + "A binding to " + + Foo.class.getName() + + " annotated with " + + named("providerMethod") + + " was already configured at " + + SimpleProviderModule.class.getName(), + "at " + SimpleProviderModule.class.getName()); + } } - + public void testDuplicatesSolelyInChildIgnored() { Injector injector = Guice.createInjector(); injector.createChildInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), - new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) - ); + new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)); } - + public void testDifferentBindingTypesFail() { - List elements = Elements.getElements( - new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo) - ); - + List elements = Elements.getElements(new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo)); + // Make sure every combination of the elements with another element fails. // This ensures that duplication checks the kind of binding also. - for(Element e1 : elements) { - for(Element e2: elements) { + for (Element e1 : elements) { + for (Element e2 : elements) { // if they're the same, this shouldn't fail. try { Guice.createInjector(Elements.getModule(Arrays.asList(e1, e2))); - if(e1 != e2) { + if (e1 != e2) { fail("must fail!"); } - } catch(CreationException expected) { - if(e1 != e2) { - assertContains(expected.getMessage(), - "A binding to " + Foo.class.getName() + " was already configured at " + FailedModule.class.getName(), + } catch (CreationException expected) { + if (e1 != e2) { + assertContains( + expected.getMessage(), + "A binding to " + + Foo.class.getName() + + " was already configured at " + + FailedModule.class.getName(), "at " + FailedModule.class.getName()); } else { throw expected; @@ -249,155 +326,180 @@ } } } - + public void testJitBindingsAreCheckedAfterConversions() { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(A.class); - bind(A.class).to(RealA.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class); + bind(A.class).to(RealA.class); + } + }); } - + public void testEqualsNotCalledByDefaultOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(HashEqualsTester.class).toInstance(a); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(HashEqualsTester.class).toInstance(a); + } + }); } - + public void testEqualsNotCalledByDefaultOnProvider() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(Object.class).toProvider(a); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(Object.class).toProvider(a); + } + }); } - + public void testHashcodeNeverCalledOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; - + final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(HashEqualsTester.class).toInstance(a); - bind(HashEqualsTester.class).toInstance(b); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(HashEqualsTester.class).toInstance(a); + bind(HashEqualsTester.class).toInstance(b); + } + }); } - + public void testHashcodeNeverCalledOnProviderInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; - + final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(Object.class).toProvider(a); - bind(Object.class).toProvider(b); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(Object.class).toProvider(a); + bind(Object.class).toProvider(b); + } + }); } private static class RealA extends A {} - @ImplementedBy(RealA.class) private static class A {} - + + @ImplementedBy(RealA.class) + private static class A {} + private void removeBasicBindings(Collection> bindings) { bindings.remove(Key.get(Injector.class)); bindings.remove(Key.get(Logger.class)); bindings.remove(Key.get(Stage.class)); } - + private static class ThrowingModule extends AbstractModule { @Override protected void configure() { - bind(Foo.class).toInstance(new Foo() { - @Override - public boolean equals(Object obj) { - throw new RuntimeException("Boo!"); - } - }); + bind(Foo.class) + .toInstance( + new Foo() { + @Override + public boolean equals(Object obj) { + throw new RuntimeException("Boo!"); + } + + @Override + public int hashCode() { + throw new RuntimeException("Boo!"); + } + }); } } - - private static abstract class FooModule extends AbstractModule { + + private abstract static class FooModule extends AbstractModule { protected final FooImpl foo; protected final Provider pFoo; protected final Class> pclFoo; protected final Class clFoo; protected final Constructor cFoo; - - FooModule(FooImpl foo, Provider pFoo, Class> pclFoo, - Class clFoo, Constructor cFoo) { + + FooModule( + FooImpl foo, + Provider pFoo, + Class> pclFoo, + Class clFoo, + Constructor cFoo) { this.foo = foo; this.pFoo = pFoo; this.pclFoo = pclFoo; this.clFoo = clFoo; this.cFoo = cFoo; - } + } } - + private static class FailedModule extends FooModule { - FailedModule(FooImpl foo, Provider pFoo, Class> pclFoo, - Class clFoo, Constructor cFoo) { + FailedModule( + FooImpl foo, + Provider pFoo, + Class> pclFoo, + Class clFoo, + Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); } - + + @Override protected void configure() { // InstanceBinding bind(Foo.class).toInstance(foo); - + // ProviderInstanceBinding bind(Foo.class).toProvider(pFoo); - + // ProviderKeyBinding bind(Foo.class).toProvider(pclFoo); - + // LinkedKeyBinding bind(Foo.class).to(clFoo); - + // ConstructorBinding bind(Foo.class).toConstructor(cFoo); } - - @Provides Foo foo() { + + @Provides + Foo foo() { return null; } } - + private static class FailingProviderModule extends AbstractModule { - @Override protected void configure() {} - @Provides Foo foo() { + @Provides + Foo foo() { return null; } } private static class SimpleProviderModule extends AbstractModule { - @Override protected void configure() {} - @Provides @Named("providerMethod") Foo foo() { + @Provides + @Named("providerMethod") + Foo foo() { return null; } @@ -405,30 +507,35 @@ public boolean equals(Object obj) { return obj.getClass() == getClass(); } - } - + } + private static class SimpleModule extends FooModule { - SimpleModule(FooImpl foo, Provider pFoo, Class> pclFoo, - Class clFoo, Constructor cFoo) { + SimpleModule( + FooImpl foo, + Provider pFoo, + Class> pclFoo, + Class clFoo, + Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); } - + + @Override protected void configure() { // InstanceBinding bind(Foo.class).annotatedWith(named("instance")).toInstance(foo); - + // ProviderInstanceBinding bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo); - + // ProviderKeyBinding bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo); - + // LinkedKeyBinding bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo); - + // UntargettedBinding / ConstructorBinding bind(FooImpl.class); - + // ConstructorBinding bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo); @@ -438,68 +545,79 @@ install(Elements.getModule(Elements.getElements(new SimpleProviderModule()))); } } - + private static class ScopedModule extends FooModule { private final Scope scope; - ScopedModule(Scope scope, FooImpl foo, Provider pFoo, - Class> pclFoo, Class clFoo, + ScopedModule( + Scope scope, + FooImpl foo, + Provider pFoo, + Class> pclFoo, + Class clFoo, Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); this.scope = scope; } - + + @Override protected void configure() { // ProviderInstanceBinding bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope); - + // ProviderKeyBinding bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope); - + // LinkedKeyBinding bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope); - + // UntargettedBinding / ConstructorBinding bind(FooImpl.class).in(scope); - + // ConstructorBinding bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope); } } - + private static class AnnotatedScopeModule extends FooModule { private final Class scope; - AnnotatedScopeModule(Class scope, FooImpl foo, Provider pFoo, - Class> pclFoo, Class clFoo, + AnnotatedScopeModule( + Class scope, + FooImpl foo, + Provider pFoo, + Class> pclFoo, + Class clFoo, Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); this.scope = scope; } - - + + @Override protected void configure() { // ProviderInstanceBinding bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope); - + // ProviderKeyBinding bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope); - + // LinkedKeyBinding bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope); - + // UntargettedBinding / ConstructorBinding bind(FooImpl.class).in(scope); - + // ConstructorBinding bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope); } - } - + } + private static interface Foo {} + private static class FooImpl implements Foo { - @Inject public FooImpl() {} - + @Inject + public FooImpl() {} + private static Constructor cxtor() { try { return FooImpl.class.getConstructor(); @@ -509,16 +627,19 @@ throw new RuntimeException(e); } } - } + } + private static class FooProvider implements Provider { + @Override public Foo get() { return new FooImpl(); } } - + private static class Bar implements Foo { - @Inject public Bar() {} - + @Inject + public Bar() {} + private static Constructor cxtor() { try { return Bar.class.getConstructor(); @@ -528,28 +649,30 @@ throw new RuntimeException(e); } } - } + } + private static class BarProvider implements Provider { + @Override public Foo get() { return new Bar(); } } - + private static class HashEqualsTester implements Provider { private String equality; private boolean throwOnEquals; private boolean throwOnHashcode; - + @Override public boolean equals(Object obj) { if (throwOnEquals) { throw new RuntimeException(); } else if (obj instanceof HashEqualsTester) { - HashEqualsTester o = (HashEqualsTester)obj; - if(o.throwOnEquals) { + HashEqualsTester o = (HashEqualsTester) obj; + if (o.throwOnEquals) { throw new RuntimeException(); } - if(equality == null && o.equality == null) { + if (equality == null && o.equality == null) { return this == o; } else { return Objects.equal(equality, o.equality); @@ -558,19 +681,19 @@ return false; } } - + @Override public int hashCode() { - if(throwOnHashcode) { + if (throwOnHashcode) { throw new RuntimeException(); } else { return super.hashCode(); } } - + + @Override public Object get() { return new Object(); } } - } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/EagerSingletonTest.java sisu-guice-4.2.0/core/test/com/google/inject/EagerSingletonTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/EagerSingletonTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/EagerSingletonTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,37 +16,49 @@ package com.google.inject; +import static com.google.inject.Asserts.getClassPathUrls; + +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class EagerSingletonTest extends TestCase { - @Override public void setUp() { + @Override + public void setUp() { A.instanceCount = 0; B.instanceCount = 0; C.instanceCount = 0; } public void testJustInTimeEagerSingletons() { - Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { - protected void configure() { - // create a just-in-time binding for A - getProvider(A.class); - - // create a just-in-time binding for C - requestInjection(new Object() { - @Inject void inject(Injector injector) { - injector.getInstance(C.class); + Guice.createInjector( + Stage.PRODUCTION, + new AbstractModule() { + @Override + protected void configure() { + // create a just-in-time binding for A + getProvider(A.class); + + // create a just-in-time binding for C + requestInjection( + new Object() { + @Inject + void inject(Injector injector) { + injector.getInstance(C.class); + } + }); } }); - } - }); assertEquals(1, A.instanceCount); - assertEquals("Singletons discovered when creating singletons should not be built eagerly", - 0, B.instanceCount); + assertEquals( + "Singletons discovered when creating singletons should not be built eagerly", + 0, + B.instanceCount); assertEquals(1, C.instanceCount); } @@ -58,28 +70,121 @@ public void testChildEagerSingletons() { Injector parent = Guice.createInjector(Stage.PRODUCTION); - parent.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(D.class).to(C.class); - } - }); + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(D.class).to(C.class); + } + }); assertEquals(1, C.instanceCount); } + // there used to be a bug that caused a concurrent modification exception if jit bindings were + // loaded during eager singleton creation due to failur to apply the lock when iterating over + // all bindings. + + public void testJustInTimeEagerSingletons_multipleThreads() throws Exception { + // in order to make the data race more likely we need a lot of jit bindings. The easiest thing + // is just to 'copy' out class for B a bunch of times. + final List> jitBindings = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + jitBindings.add(copyClass(B.class)); + } + Guice.createInjector( + Stage.PRODUCTION, + new AbstractModule() { + @Override + protected void configure() { + // create a just-in-time binding for A + getProvider(A.class); + + // create a just-in-time binding for C + requestInjection( + new Object() { + @Inject + void inject(final Injector injector) throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + new Thread() { + @Override + public void run() { + latch.countDown(); + for (Class jitBinding : jitBindings) { + // this causes the binding to be created + injector.getProvider(jitBinding); + } + } + }.start(); + latch.await(); // make sure the thread is running before returning + } + }); + } + }); + + assertEquals(1, A.instanceCount); + // our thread runs in parallel with eager singleton loading so some there should be some number + // N such that 0<=N jitBinding : jitBindings) { + int instanceCount = (Integer) jitBinding.getDeclaredField("instanceCount").get(null); + if (instanceCount != 0 && instanceCount != 1) { + fail("Should only have created zero or one instances, got " + instanceCount); + } + if (prev == -1) { + prev = instanceCount; + } else if (prev != instanceCount) { + if (prev != 1 && instanceCount != 0) { + fail("initialized later JIT bindings before earlier ones at index " + index); + } + prev = instanceCount; + } + index++; + } + } + + /** Creates a copy of a class in a child classloader. */ + private static Class copyClass(final Class cls) { + // To create a copy of a class we create a new child class loader with the same data as our + // parent and override loadClass to always load a new copy of cls. + try { + return new URLClassLoader(getClassPathUrls(), EagerSingletonTest.class.getClassLoader()) { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + // This means for every class besides cls we delegate to our parent (so things like + // @Singleton and Object are well defined), but for this one class we load a new one in + // this loader. + if (name.equals(cls.getName())) { + Class c = findLoadedClass(name); + if (c == null) { + return super.findClass(name); + } + return c; + } + return super.loadClass(name); + } + }.loadClass(cls.getName()); + } catch (ClassNotFoundException cnfe) { + throw new AssertionError(cnfe); + } + } + @Singleton static class A { static int instanceCount = 0; int instanceId = instanceCount++; - @Inject A(Injector injector) { + @Inject + A(Injector injector) { injector.getProvider(B.class); } } @Singleton - static class B { - static int instanceCount = 0; + public static class B { + public static int instanceCount = 0; int instanceId = instanceCount++; } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ErrorHandlingTest.java sisu-guice-4.2.0/core/test/com/google/inject/ErrorHandlingTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ErrorHandlingTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ErrorHandlingTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,46 +20,46 @@ import com.google.inject.name.Named; import com.google.inject.name.Names; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.List; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ErrorHandlingTest { public static void main(String[] args) throws CreationException { try { Guice.createInjector(new MyModule()); - } - catch (CreationException e) { + } catch (CreationException e) { e.printStackTrace(); System.err.println("--"); } - Injector bad = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toProvider(new Provider() { - public String get() { - return null; - } - }); - } - }); + Injector bad = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class) + .toProvider( + new Provider() { + @Override + public String get() { + return null; + } + }); + } + }); try { bad.getInstance(String.class); - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); System.err.println("--"); } try { bad.getInstance(NeedsString.class); - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); System.err.println("--"); } @@ -69,29 +69,34 @@ @Inject String mofo; } - @Inject @Named("missing") + @Inject + @Named("missing") static List missing = null; static class Foo { @Inject public Foo(Runnable r) {} - @Inject void setNames(List names) {} + @Inject + void setNames(List names) {} } static class Bar { // Invalid constructor. Bar(String s) {} - @Inject void setNumbers(@Named("numbers") List numbers) {} + @Inject + void setNumbers(@Named("numbers") List numbers) {} - @Inject void bar(@Named("foo") String s) {} + @Inject + void bar(@Named("foo") String s) {} } static class Tee { @Inject String s; - @Inject void tee(String s, int i) {} + @Inject + void tee(String s, int i) {} @Inject Invalid invalid; } @@ -100,11 +105,11 @@ Invalid(String s) {} } - @SuppressWarnings("MoreThanOneScopeAnnotationOnClass") // suppress compiler error to test - @Singleton + // suppress compiler error to test + @SuppressWarnings({"MoreThanOneScopeAnnotationOnClass", "multiple-scope"}) + @Singleton @GoodScope - static class TooManyScopes { - } + static class TooManyScopes {} @Target(ElementType.TYPE) @Retention(RUNTIME) @@ -117,6 +122,7 @@ interface I {} static class MyModule extends AbstractModule { + @Override protected void configure() { bind(Runnable.class); bind(Foo.class); @@ -127,15 +133,18 @@ bind(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(); - } - }); + 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; diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java --- sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,76 +18,76 @@ import static junit.framework.Assert.assertTrue; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithDependencyInjection { -// 62 lines + // 62 lines -public interface Service { - void go(); -} + public interface Service { + void go(); + } -public static class ServiceImpl implements ClientServiceWithDependencyInjection.Service { - public void go() { - // ... + public static class ServiceImpl implements ClientServiceWithDependencyInjection.Service { + @Override + public void go() { + // ... + } } -} -public static class ServiceFactory { + public static class ServiceFactory { - private ServiceFactory() {} + private ServiceFactory() {} - private static final Service service = new ServiceImpl(); + private static final Service service = new ServiceImpl(); - public static Service getInstance() { - return service; + public static Service getInstance() { + return service; + } } -} -public static class Client { + public static class Client { - private final Service service; + private final Service service; - public Client(Service service) { - this.service = service; - } + public Client(Service service) { + this.service = service; + } - public void go() { - service.go(); + public void go() { + service.go(); + } } -} -public static class ClientFactory { + public static class ClientFactory { - private ClientFactory() {} + private ClientFactory() {} - public static Client getInstance() { - Service service = ServiceFactory.getInstance(); - return new Client(service); + public static Client getInstance() { + Service service = ServiceFactory.getInstance(); + return new Client(service); + } } -} -public void testClient() { - MockService mock = new MockService(); - Client client = new Client(mock); - client.go(); - assertTrue(mock.isGone()); -} + public void testClient() { + MockService mock = new MockService(); + Client client = new Client(mock); + client.go(); + assertTrue(mock.isGone()); + } -public static class MockService implements Service { + public static class MockService implements Service { - private boolean gone = false; + private boolean gone = false; - public void go() { - gone = true; - } + @Override + public void go() { + gone = true; + } - public boolean isGone() { - return gone; + public boolean isGone() { + return gone; + } } -} public static void main(String[] args) { new ClientServiceWithDependencyInjection().testClient(); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithFactories.java sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithFactories.java --- sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithFactories.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithFactories.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,72 +18,71 @@ import static junit.framework.Assert.assertTrue; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithFactories { -// 58 lines + // 58 lines -public interface Service { - void go(); -} + public interface Service { + void go(); + } -public static class ServiceImpl implements Service { - public void go() { - // ... + public static class ServiceImpl implements Service { + @Override + public void go() { + // ... + } } -} -public static class ServiceFactory { + public static class ServiceFactory { - private ServiceFactory() {} + private ServiceFactory() {} - private static Service instance = new ServiceImpl(); + private static Service instance = new ServiceImpl(); - public static Service getInstance() { - return instance; - } + public static Service getInstance() { + return instance; + } - public static void setInstance(Service service) { - instance = service; + public static void setInstance(Service service) { + instance = service; + } } -} -public static class Client { + public static class Client { - public void go() { - Service service = ServiceFactory.getInstance(); - service.go(); + public void go() { + Service service = ServiceFactory.getInstance(); + service.go(); + } } -} -public void testClient() { - Service previous = ServiceFactory.getInstance(); - try { - final MockService mock = new MockService(); - ServiceFactory.setInstance(mock); - Client client = new Client(); - client.go(); - assertTrue(mock.isGone()); + public void testClient() { + Service previous = ServiceFactory.getInstance(); + try { + final MockService mock = new MockService(); + ServiceFactory.setInstance(mock); + Client client = new Client(); + client.go(); + assertTrue(mock.isGone()); + } finally { + ServiceFactory.setInstance(previous); + } } - finally { - ServiceFactory.setInstance(previous); - } -} -public static class MockService implements Service { + public static class MockService implements Service { - private boolean gone = false; + private boolean gone = false; - public void go() { - gone = true; - } + @Override + public void go() { + gone = true; + } - public boolean isGone() { - return gone; + public boolean isGone() { + return gone; + } } -} public static void main(String[] args) { new ClientServiceWithFactories().testClient(); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java --- sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,65 +22,64 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; - import junit.framework.Assert; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithGuiceDefaults { -// 44 lines + // 44 lines -@ImplementedBy(ServiceImpl.class) -public interface Service { - void go(); -} + @ImplementedBy(ServiceImpl.class) + public interface Service { + void go(); + } -@Singleton -public static class ServiceImpl implements ClientServiceWithGuiceDefaults.Service { - public void go() { - // ... + @Singleton + public static class ServiceImpl implements ClientServiceWithGuiceDefaults.Service { + @Override + public void go() { + // ... + } } -} -public static class Client { + public static class Client { - private final Service service; + private final Service service; - @Inject - public Client(Service service) { - this.service = service; + @Inject + public Client(Service service) { + this.service = service; + } + + public void go() { + service.go(); + } } - public void go() { - service.go(); + public void testClient() { + MockService mock = new MockService(); + Client client = new Client(mock); + client.go(); + Assert.assertTrue(mock.isGone()); } -} -public void testClient() { - MockService mock = new MockService(); - Client client = new Client(mock); - client.go(); - Assert.assertTrue(mock.isGone()); -} - -public static class MockService implements Service { + public static class MockService implements Service { - private boolean gone = false; + private boolean gone = false; - public void go() { - gone = true; + @Override + public void go() { + gone = true; + } + + public boolean isGone() { + return gone; + } } - public boolean isGone() { - return gone; + public static void main(String[] args) throws CreationException { + new ClientServiceWithGuiceDefaults().testClient(); + Injector injector = Guice.createInjector(); + Client client = injector.getProvider(Client.class).get(); } } - -public static void main(String[] args) throws CreationException { - new ClientServiceWithGuiceDefaults().testClient(); - Injector injector = Guice.createInjector(); - Client client = injector.getProvider(Client.class).get(); -} -} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithGuice.java sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithGuice.java --- sisu-guice-3.2.6/core/test/com/google/inject/example/ClientServiceWithGuice.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/example/ClientServiceWithGuice.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,66 +25,67 @@ import com.google.inject.Injector; import com.google.inject.Scopes; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithGuice { -// 48 lines + // 48 lines -public interface Service { - void go(); -} + public interface Service { + void go(); + } -public static class ServiceImpl implements Service { - public void go() { - // ... + public static class ServiceImpl implements Service { + @Override + public void go() { + // ... + } } -} -public static class MyModule extends AbstractModule { - protected void configure() { - bind(Service.class).to(ServiceImpl.class).in(Scopes.SINGLETON); + public static class MyModule extends AbstractModule { + @Override + protected void configure() { + bind(Service.class).to(ServiceImpl.class).in(Scopes.SINGLETON); + } } -} -public static class Client { + public static class Client { + + private final Service service; - private final Service service; + @Inject + public Client(Service service) { + this.service = service; + } - @Inject - public Client(Service service) { - this.service = service; + public void go() { + service.go(); + } } - public void go() { - service.go(); + public void testClient() { + MockService mock = new MockService(); + Client client = new Client(mock); + client.go(); + assertTrue(mock.isGone()); } -} -public void testClient() { - MockService mock = new MockService(); - Client client = new Client(mock); - client.go(); - assertTrue(mock.isGone()); -} + public static class MockService implements Service { -public static class MockService implements Service { + private boolean gone = false; - private boolean gone = false; + @Override + public void go() { + gone = true; + } - public void go() { - gone = true; + public boolean isGone() { + return gone; + } } - public boolean isGone() { - return gone; + public static void main(String[] args) throws CreationException { + new ClientServiceWithGuice().testClient(); + Injector injector = Guice.createInjector(new MyModule()); + Client client = injector.getInstance(Client.class); } } - -public static void main(String[] args) throws CreationException { - new ClientServiceWithGuice().testClient(); - Injector injector = Guice.createInjector(new MyModule()); - Client client = injector.getInstance(Client.class); -} -} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/example/JndiProviderClient.java sisu-guice-4.2.0/core/test/com/google/inject/example/JndiProviderClient.java --- sisu-guice-3.2.6/core/test/com/google/inject/example/JndiProviderClient.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/example/JndiProviderClient.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; - import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; @@ -30,15 +29,17 @@ class JndiProviderClient { public static void main(String[] args) throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { -// Bind Context to the default InitialContext. -bind(Context.class).to(InitialContext.class); - -// Bind to DataSource from JNDI. -bind(DataSource.class) - .toProvider(fromJndi(DataSource.class, "...")); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + // Bind Context to the default InitialContext. + bind(Context.class).to(InitialContext.class); + + // Bind to DataSource from JNDI. + bind(DataSource.class).toProvider(fromJndi(DataSource.class, "...")); + } + }); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/example/JndiProvider.java sisu-guice-4.2.0/core/test/com/google/inject/example/JndiProvider.java --- sisu-guice-3.2.6/core/test/com/google/inject/example/JndiProvider.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/example/JndiProvider.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import com.google.inject.Inject; import com.google.inject.Provider; - import javax.naming.Context; import javax.naming.NamingException; @@ -33,21 +32,17 @@ this.type = type; } + @Override public T get() { try { return type.cast(context.lookup(name)); - } - catch (NamingException e) { + } catch (NamingException e) { throw new RuntimeException(e); } } - /** - * Creates a JNDI provider for the given - * type and name. - */ - static Provider fromJndi( - Class type, String name) { + /** Creates a JNDI provider for the given type and name. */ + static Provider fromJndi(Class type, String name) { return new JndiProvider(type, name); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/GenericInjectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/GenericInjectionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/GenericInjectionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/GenericInjectionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,28 +19,28 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.inject.util.Modules; - -import junit.framework.TestCase; - import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class GenericInjectionTest extends TestCase { public void testGenericInjection() throws CreationException { final List names = Arrays.asList("foo", "bar", "bob"); - Injector injector = Guice.createInjector((Module) new AbstractModule() { - protected void configure() { - bind(new TypeLiteral>() {}).toInstance(names); - } - }); + Injector injector = + Guice.createInjector( + (Module) + new AbstractModule() { + @Override + protected void configure() { + bind(new TypeLiteral>() {}).toInstance(names); + } + }); Foo foo = injector.getInstance(Foo.class); assertEquals(names, foo.names); @@ -51,108 +51,130 @@ } /** - * Although we may not have intended to support this behaviour, this test - * passes under Guice 1.0. The workaround is to add an explicit binding for - * the parameterized type. See {@link #testExplicitBindingOfGenericType()}. + * Although we may not have intended to support this behaviour, this test passes under Guice 1.0. + * The workaround is to add an explicit binding for the parameterized type. See {@link + * #testExplicitBindingOfGenericType()}. */ public void testImplicitBindingOfGenericType() { - Parameterized parameterized - = Guice.createInjector().getInstance(Key.get(new TypeLiteral>() {})); + Parameterized parameterized = + Guice.createInjector().getInstance(Key.get(new TypeLiteral>() {})); assertNotNull(parameterized); } public void testExplicitBindingOfGenericType() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Key.get(new TypeLiteral>() {})) - .to((Class) Parameterized.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Key.get(new TypeLiteral>() {})) + .to((Class) Parameterized.class); + } + }); - Parameterized parameterized - = injector.getInstance(Key.get(new TypeLiteral>() { })); + Parameterized parameterized = + injector.getInstance(Key.get(new TypeLiteral>() {})); assertNotNull(parameterized); } static class Parameterized { @Inject - Parameterized() { } + Parameterized() {} } public void testInjectingParameterizedDependenciesForImplicitBinding() { - assertParameterizedDepsInjected(new Key>() {}, - Modules.EMPTY_MODULE); + assertParameterizedDepsInjected( + new Key>() {}, Modules.EMPTY_MODULE); } public void testInjectingParameterizedDependenciesForBindingTarget() { - final TypeLiteral> type - = new TypeLiteral>() {}; + final TypeLiteral> type = + new TypeLiteral>() {}; - assertParameterizedDepsInjected(Key.get(Object.class), new AbstractModule() { - protected void configure() { - bind(Object.class).to(type); - } - }); + assertParameterizedDepsInjected( + Key.get(Object.class), + new AbstractModule() { + @Override + protected void configure() { + bind(Object.class).to(type); + } + }); } public void testInjectingParameterizedDependenciesForBindingSource() { - final TypeLiteral> type - = new TypeLiteral>() {}; + final TypeLiteral> type = + new TypeLiteral>() {}; - assertParameterizedDepsInjected(Key.get(type), new AbstractModule() { - protected void configure() { - bind(type); - } - }); + assertParameterizedDepsInjected( + Key.get(type), + new AbstractModule() { + @Override + protected void configure() { + bind(type); + } + }); } public void testBindingToSubtype() { - final TypeLiteral> type - = new TypeLiteral>() {}; + final TypeLiteral> type = + new TypeLiteral>() {}; - assertParameterizedDepsInjected(Key.get(type), new AbstractModule() { - protected void configure() { - bind(type).to(new TypeLiteral>() {}); - } - }); + assertParameterizedDepsInjected( + Key.get(type), + new AbstractModule() { + @Override + protected void configure() { + bind(type).to(new TypeLiteral>() {}); + } + }); } public void testBindingSubtype() { - final TypeLiteral> type - = new TypeLiteral>() {}; + final TypeLiteral> type = + new TypeLiteral>() {}; - assertParameterizedDepsInjected(Key.get(type), new AbstractModule() { - protected void configure() { - bind(type); - } - }); + assertParameterizedDepsInjected( + Key.get(type), + new AbstractModule() { + @Override + protected void configure() { + bind(type); + } + }); } @SuppressWarnings("unchecked") public void assertParameterizedDepsInjected(Key key, Module bindingModule) { - Module bindDataModule = new AbstractModule() { - protected void configure() {} - @Provides Map provideMap() { - return ImmutableMap.of("one", 1, "two", 2); - } - @Provides Set provideSet(Map map) { - return map.keySet(); - } - @Provides Collection provideCollection(Map map) { - return map.values(); - } - }; + Module bindDataModule = + new AbstractModule() { + + @Provides + Map provideMap() { + return ImmutableMap.of("one", 1, "two", 2); + } + + @Provides + Set provideSet(Map map) { + return map.keySet(); + } + + @Provides + Collection provideCollection(Map map) { + return map.values(); + } + }; Injector injector = Guice.createInjector(bindDataModule, bindingModule); - ParameterizedDeps parameterizedDeps - = (ParameterizedDeps) injector.getInstance(key); + ParameterizedDeps parameterizedDeps = + (ParameterizedDeps) injector.getInstance(key); assertEquals(ImmutableMap.of("one", 1, "two", 2), parameterizedDeps.map); assertEquals(ImmutableSet.of("one", "two"), parameterizedDeps.keys); assertEquals(ImmutableSet.of(1, 2), ImmutableSet.copyOf(parameterizedDeps.values)); } static class SubParameterizedDeps extends ParameterizedDeps { - @Inject SubParameterizedDeps(Set keys) { + @Inject + SubParameterizedDeps(Set keys) { super(keys); } } @@ -162,21 +184,26 @@ private Set keys; private Collection values; - @Inject ParameterizedDeps(Set keys) { + @Inject + ParameterizedDeps(Set keys) { this.keys = keys; } - @Inject void method(Collection values) { + @Inject + void method(Collection values) { this.values = values; } } public void testImmediateTypeVariablesAreInjected() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("tee"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("tee"); + } + }); InjectsT injectsT = injector.getInstance(new Key>() {}); assertEquals("tee", injectsT.t); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ImplicitBindingTest.java sisu-guice-4.2.0/core/test/com/google/inject/ImplicitBindingTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ImplicitBindingTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ImplicitBindingTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,17 +17,14 @@ package com.google.inject; import com.google.common.collect.Iterables; +import com.google.inject.internal.Annotations; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Message; - -import junit.framework.TestCase; - import java.util.List; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ImplicitBindingTest extends TestCase { public void testCircularDependency() throws CreationException { @@ -42,6 +39,7 @@ static class Bar { final Foo foo; + @Inject public Bar(Foo foo) { this.foo = foo; @@ -60,10 +58,12 @@ } static class IImpl implements I { + @Override public void go() {} } static class AlternateImpl implements I { + @Override public void go() {} } @@ -74,12 +74,14 @@ } public void testBindingOverridesImplementedBy() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(I.class).to(AlternateImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(I.class).to(AlternateImpl.class); + } + }); assertEquals(AlternateImpl.class, injector.getInstance(I.class).getClass()); } @@ -93,17 +95,28 @@ Guice.createInjector().getInstance(Key.get(I.class, Names.named("i"))); fail(); } catch (ConfigurationException expected) { - Asserts.assertContains(expected.getMessage(), + Asserts.assertContains( + expected.getMessage(), "1) No implementation for " + I.class.getName(), - "annotated with @" + Named.class.getName() + "(value=i) was bound.", + "annotated with @" + + Named.class.getName() + + "(value=" + + Annotations.memberValueString("i") + + ") was bound.", "while locating " + I.class.getName(), - " annotated with @" + Named.class.getName() + "(value=i)"); + " annotated with @" + + Named.class.getName() + + "(value=" + + Annotations.memberValueString("i") + + ")"); } } static class ProvidedProvider implements Provider { + @Override public Provided get() { return new Provided() { + @Override public void go() {} }; } @@ -113,20 +126,22 @@ * When we're building the binding for A, we temporarily insert that binding to support circular * dependencies. And so we can successfully create a binding for B. But later, when the binding * for A ultimately fails, we need to clean up the dependent binding for B. - * - * The test loops through linked bindings & bindings with constructor & member injections, - * to make sure that all are cleaned up and traversed. It also makes sure we don't touch - * explicit bindings. + * + *

    The test loops through linked bindings & bindings with constructor & member injections, to + * make sure that all are cleaned up and traversed. It also makes sure we don't touch explicit + * bindings. */ public void testCircularJitBindingsLeaveNoResidue() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Valid.class); - bind(Valid2.class); - } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Valid.class); + bind(Valid2.class); + } + }); + // Capture good bindings. Binding v1 = injector.getBinding(Valid.class); Binding v2 = injector.getBinding(Valid2.class); @@ -144,205 +159,230 @@ assertFailure(injector, InvalidProvidedBy2.class); assertFailure(injector, InvalidProvidedBy2Provider.class); assertFailure(injector, Invalid2.class); - + // Validate we didn't do anything to the valid explicit bindings. assertSame(v1, injector.getBinding(Valid.class)); assertSame(v2, injector.getBinding(Valid2.class)); - + // Validate that we didn't erase the valid JIT bindings assertSame(jv1, injector.getBinding(JitValid.class)); assertSame(jv2, injector.getBinding(JitValid2.class)); } - + @SuppressWarnings("unchecked") private void assertFailure(Injector injector, Class clazz) { try { injector.getBinding(clazz); fail("Shouldn't have been able to get binding of: " + clazz); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { Message msg = Iterables.getOnlyElement(expected.getErrorMessages()); - assertEquals("No implementation for " + InvalidInterface.class.getName() + " was bound.", - msg.getMessage()); + Asserts.assertContains( + msg.getMessage(), + "No implementation for " + InvalidInterface.class.getName() + " was bound."); List sources = msg.getSources(); // Assert that the first item in the sources if the key for the class we're looking up, // ensuring that each lookup is "new". assertEquals(Key.get(clazz).toString(), sources.get(0).toString()); // Assert that the last item in each lookup contains the InvalidInterface class - Asserts.assertContains(sources.get(sources.size()-1).toString(), - Key.get(InvalidInterface.class).toString()); + Asserts.assertContains( + sources.get(sources.size() - 1).toString(), Key.get(InvalidInterface.class).toString()); } } static class Invalid { @Inject Valid a; - @Inject JitValid b; - @Inject InvalidProvidedBy c; - @Inject Invalid(InvalidLinked a) {} - @Inject void foo(InvalidInterface a) {} - + @Inject JitValid b; + @Inject InvalidProvidedBy c; + + @Inject + Invalid(InvalidLinked a) {} + + @Inject + void foo(InvalidInterface a) {} } @ImplementedBy(InvalidLinkedImpl.class) static interface InvalidLinked {} + static class InvalidLinkedImpl implements InvalidLinked { @Inject InvalidLinked2 a; } - + @ImplementedBy(InvalidLinked2Impl.class) static interface InvalidLinked2 {} + static class InvalidLinked2Impl implements InvalidLinked2 { - @Inject InvalidLinked2Impl(Invalid2 a) {} + @Inject + InvalidLinked2Impl(Invalid2 a) {} } - + @ProvidedBy(InvalidProvidedByProvider.class) static interface InvalidProvidedBy {} + static class InvalidProvidedByProvider implements Provider { @Inject InvalidProvidedBy2 a; + + @Override public InvalidProvidedBy get() { return null; } } - + @ProvidedBy(InvalidProvidedBy2Provider.class) static interface InvalidProvidedBy2 {} + static class InvalidProvidedBy2Provider implements Provider { @Inject Invalid2 a; + + @Override public InvalidProvidedBy2 get() { return null; } - } - + } + static class Invalid2 { @Inject Invalid a; } interface InvalidInterface {} - - static class Valid { @Inject Valid2 a; } + + static class Valid { + @Inject Valid2 a; + } + static class Valid2 {} - - static class JitValid { @Inject JitValid2 a; } + + static class JitValid { + @Inject JitValid2 a; + } + static class JitValid2 {} - + /** * Regression test for https://github.com/google/guice/issues/319 - * - * The bug is that a class that asks for a provider for itself during injection time, - * where any one of the other types required to fulfill the object creation was bound - * in a child constructor, explodes when the injected Provider is called. - * - * It works just fine when the other types are bound in a main injector. - */ - public void testInstancesRequestingProvidersForThemselvesWithChildInjectors() { - final Module testModule = new AbstractModule() { - @Override - protected void configure() { - bind(String.class) - .toProvider(TestStringProvider.class); - } - }; - + * + *

    The bug is that a class that asks for a provider for itself during injection time, where any + * one of the other types required to fulfill the object creation was bound in a child + * constructor, explodes when the injected Provider is called. + * + *

    It works just fine when the other types are bound in a main injector. + */ + public void testInstancesRequestingProvidersForThemselvesWithChildInjectors() { + final Module testModule = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toProvider(TestStringProvider.class); + } + }; + // Verify it works when the type is setup in the parent. Injector parentSetupRootInjector = Guice.createInjector(testModule); Injector parentSetupChildInjector = parentSetupRootInjector.createChildInjector(); - assertEquals(TestStringProvider.TEST_VALUE, - parentSetupChildInjector.getInstance( - RequiresProviderForSelfWithOtherType.class).getValue()); - + assertEquals( + TestStringProvider.TEST_VALUE, + parentSetupChildInjector + .getInstance(RequiresProviderForSelfWithOtherType.class) + .getValue()); + // Verify it works when the type is setup in the child, not the parent. // If it still occurs, the bug will explode here. Injector childSetupRootInjector = Guice.createInjector(); - Injector childSetupChildInjector = childSetupRootInjector.createChildInjector(testModule); - assertEquals(TestStringProvider.TEST_VALUE, - childSetupChildInjector.getInstance( - RequiresProviderForSelfWithOtherType.class).getValue()); + Injector childSetupChildInjector = childSetupRootInjector.createChildInjector(testModule); + assertEquals( + TestStringProvider.TEST_VALUE, + childSetupChildInjector.getInstance(RequiresProviderForSelfWithOtherType.class).getValue()); } - + static class TestStringProvider implements Provider { static final String TEST_VALUE = "This is to verify it all works"; - + + @Override public String get() { return TEST_VALUE; - } - } - + } + } + static class RequiresProviderForSelfWithOtherType { private final Provider selfProvider; private final String providedStringValue; - - @Inject + + @Inject RequiresProviderForSelfWithOtherType( - String providedStringValue, - Provider selfProvider - ) { + String providedStringValue, Provider selfProvider) { this.providedStringValue = providedStringValue; - this.selfProvider = selfProvider; + this.selfProvider = selfProvider; } - + public String getValue() { // Attempt to get another instance of ourself. This pattern - // is possible for recursive processing. + // is possible for recursive processing. selfProvider.get(); - + return providedStringValue; } } /** - * Ensure that when we cleanup failed JIT bindings, we don't break. - * The test here requires a sequence of JIT bindings: - * A-> B - * B -> C, A - * C -> A, D - * D not JITable - * The problem was that C cleaned up A's binding and then handed control back to B, - * which tried to continue processing A.. but A was removed from the jitBindings Map, - * so it attempts to create a new JIT binding for A, but we haven't yet finished - * constructing the first JIT binding for A, so we get a recursive - * computation exception from ComputingConcurrentHashMap. - * - * We also throw in a valid JIT binding, E, to guarantee that if - * something fails in this flow, it can be recreated later if it's - * not from a failed sequence. + * Ensure that when we cleanup failed JIT bindings, we don't break. The test here requires a + * sequence of JIT bindings: + * + *

      + *
    1. A-> B + *
    2. B -> C, A + *
    3. C -> A, D + *
    4. D not JITable + *
    + * + *

    The problem was that C cleaned up A's binding and then handed control back to B, which tried + * to continue processing A.. but A was removed from the jitBindings Map, so it attempts to create + * a new JIT binding for A, but we haven't yet finished constructing the first JIT binding for A, + * so we get a recursive computation exception from ComputingConcurrentHashMap. + * + *

    We also throw in a valid JIT binding, E, to guarantee that if something fails in this flow, + * it can be recreated later if it's not from a failed sequence. */ public void testRecursiveJitBindingsCleanupCorrectly() throws Exception { Injector injector = Guice.createInjector(); try { injector.getInstance(A.class); fail("Expected failure"); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { Message msg = Iterables.getOnlyElement(expected.getErrorMessages()); - Asserts.assertContains(msg.getMessage(), - "Could not find a suitable constructor in " + D.class.getName()); + Asserts.assertContains( + msg.getMessage(), "Could not find a suitable constructor in " + D.class.getName()); } // Assert that we've removed all the bindings. assertNull(injector.getExistingBinding(Key.get(A.class))); assertNull(injector.getExistingBinding(Key.get(B.class))); assertNull(injector.getExistingBinding(Key.get(C.class))); assertNull(injector.getExistingBinding(Key.get(D.class))); - + // Confirm that we didn't prevent 'E' from working. assertNotNull(injector.getBinding(Key.get(E.class))); } static class A { - @Inject public A(B b) {} + @Inject + public A(B b) {} } static class B { - @Inject public B(C c, A a) {} + @Inject + public B(C c, A a) {} } static class C { - @Inject public C(A a, D d, E e) {} + @Inject + public C(A a, D d, E e) {} } static class D { public D(int i) {} } - + // Valid JITable binding - static class E { } + static class E {} public void testProvidedByNonEmptyEnum() { NonEmptyEnum cardSuit = Guice.createInjector().getInstance(NonEmptyEnum.class); @@ -356,7 +396,12 @@ } @ProvidedBy(NonEmptyEnumProvider.class) - enum NonEmptyEnum { HEARTS, DIAMONDS, CLUBS, SPADES } + enum NonEmptyEnum { + HEARTS, + DIAMONDS, + CLUBS, + SPADES + } static final class NonEmptyEnumProvider implements Provider { @Override @@ -382,14 +427,24 @@ try { injector.getInstance(EnumWithImplementedBy.class); fail("Expected failure"); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { Message msg = Iterables.getOnlyElement(expected.getErrorMessages()); - Asserts.assertContains(msg.getMessage(), + Asserts.assertContains( + msg.getMessage(), "No implementation for " + EnumWithImplementedBy.class.getName() + " was bound."); } } @ImplementedBy(EnumWithImplementedByEnum.class) enum EnumWithImplementedBy {} + private static class EnumWithImplementedByEnum {} + + public void testImplicitJdkBindings() { + Injector injector = Guice.createInjector(); + // String has a public nullary constructor, so Guice will call it. + assertEquals("", injector.getInstance(String.class)); + // InetAddress has a package private constructor. We probably shouldn't be calling it :( + assertNotNull(injector.getInstance(java.net.InetAddress.class)); + } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/InjectorTest.java sisu-guice-4.2.0/core/test/com/google/inject/InjectorTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/InjectorTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/InjectorTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,9 +20,6 @@ import static com.google.inject.Asserts.assertNotSerializable; import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.annotation.Retention; import java.util.concurrent.Callable; @@ -31,21 +28,23 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class InjectorTest extends TestCase { @Retention(RUNTIME) - @BindingAnnotation @interface Other {} + @BindingAnnotation + @interface Other {} @Retention(RUNTIME) - @BindingAnnotation @interface S {} + @BindingAnnotation + @interface S {} @Retention(RUNTIME) - @BindingAnnotation @interface I {} + @BindingAnnotation + @interface I {} public void testToStringDoesNotInfinitelyRecurse() { Injector injector = Guice.createInjector(Stage.TOOL); @@ -57,21 +56,20 @@ final SampleSingleton singleton = new SampleSingleton(); final SampleSingleton other = new SampleSingleton(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(SampleSingleton.class).toInstance(singleton); - bind(SampleSingleton.class) - .annotatedWith(Other.class) - .toInstance(other); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(SampleSingleton.class).toInstance(singleton); + bind(SampleSingleton.class).annotatedWith(Other.class).toInstance(other); + } + }); - assertSame(singleton, - injector.getInstance(Key.get(SampleSingleton.class))); + assertSame(singleton, injector.getInstance(Key.get(SampleSingleton.class))); assertSame(singleton, injector.getInstance(SampleSingleton.class)); - assertSame(other, - injector.getInstance(Key.get(SampleSingleton.class, Other.class))); + assertSame(other, injector.getInstance(Key.get(SampleSingleton.class, Other.class))); } static class SampleSingleton {} @@ -91,14 +89,16 @@ } private Injector createFooInjector() throws CreationException { - return Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Bar.class).to(BarImpl.class); - bind(Tee.class).to(TeeImpl.class); - bindConstant().annotatedWith(S.class).to("test"); - bindConstant().annotatedWith(I.class).to(5); - } - }); + return Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Bar.class).to(BarImpl.class); + bind(Tee.class).to(TeeImpl.class); + bindConstant().annotatedWith(S.class).to("test"); + bindConstant().annotatedWith(I.class).to(5); + } + }); } public void testGetInstance() throws CreationException { @@ -109,13 +109,15 @@ assertEquals(5, bar.getI()); } - public void testIntAndIntegerAreInterchangeable() - throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindConstant().annotatedWith(I.class).to(5); - } - }); + public void testIntAndIntegerAreInterchangeable() throws CreationException { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(I.class).to(5); + } + }); IntegerWrapper iw = injector.getInstance(IntegerWrapper.class); assertEquals(5, (int) iw.i); @@ -153,6 +155,7 @@ interface Bar { Tee getTee(); + int getI(); } @@ -168,10 +171,12 @@ this.tee = tee; } + @Override public Tee getTee() { return tee; } + @Override public int getI() { return i; } @@ -180,6 +185,7 @@ interface Tee { String getS(); + Bar getBar(); } @@ -193,23 +199,27 @@ this.s = s; } + @Override public String getS() { return s; } + @Override public Bar getBar() { return bar; } } public void testInjectStatics() throws CreationException { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bindConstant().annotatedWith(S.class).to("test"); - bindConstant().annotatedWith(I.class).to(5); - requestStaticInjection(Static.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(S.class).to("test"); + bindConstant().annotatedWith(I.class).to(5); + requestStaticInjection(Static.class); + } + }); assertEquals("test", Static.s); assertEquals(5, Static.i); @@ -217,17 +227,20 @@ public void testInjectStaticInterface() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - requestStaticInjection(Interface.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(Interface.class); + } + }); fail(); - } catch(CreationException ce) { + } catch (CreationException ce) { assertEquals(1, ce.getErrorMessages().size()); Asserts.assertContains( ce.getMessage(), - "1) " + Interface.class.getName() + "1) " + + Interface.class.getName() + " is an interface, but interfaces have no static injection points.", "at " + InjectorTest.class.getName(), "configure"); @@ -242,18 +255,22 @@ static String s; - @Inject static void setS(@S String s) { + @Inject + static void setS(@S String s) { Static.s = s; } } public void testPrivateInjection() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("foo"); - bind(int.class).toInstance(5); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("foo"); + bind(int.class).toInstance(5); + } + }); Private p = injector.getInstance(Private.class); assertEquals("foo", p.fromConstructor); @@ -276,12 +293,15 @@ } public void testProtectedInjection() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("foo"); - bind(int.class).toInstance(5); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("foo"); + bind(int.class).toInstance(5); + } + }); Protected p = injector.getInstance(Protected.class); assertEquals("foo", p.fromConstructor); @@ -304,15 +324,19 @@ } public void testInstanceInjectionHappensAfterFactoriesAreSetUp() { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Object.class).toInstance(new Object() { - @Inject Runnable r; - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Object.class) + .toInstance( + new Object() { + @Inject Runnable r; + }); - bind(Runnable.class).to(MyRunnable.class); - } - }); + bind(Runnable.class).to(MyRunnable.class); + } + }); } public void testSubtypeNotProvided() { @@ -320,10 +344,13 @@ Guice.createInjector().getInstance(Money.class); fail(); } catch (ProvisionException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), Tree.class.getName() + " doesn't provide instances of " + Money.class.getName(), - "while locating ", Tree.class.getName(), - "while locating ", Money.class.getName()); + "while locating ", + Tree.class.getName(), + "while locating ", + Money.class.getName()); } } @@ -332,9 +359,11 @@ Guice.createInjector().getInstance(PineTree.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), Tree.class.getName() + " doesn't extend " + PineTree.class.getName(), - "while locating ", PineTree.class.getName()); + "while locating ", + PineTree.class.getName()); } } @@ -343,9 +372,11 @@ Guice.createInjector().getInstance(SeaHorse.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "@ImplementedBy points to the same class it annotates.", - "while locating ", SeaHorse.class.getName()); + "while locating ", + SeaHorse.class.getName()); } } @@ -354,20 +385,24 @@ Guice.createInjector().getInstance(Chicken.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "@ProvidedBy points to the same class it annotates", - "while locating ", Chicken.class.getName()); + "while locating ", + Chicken.class.getName()); } } static class MyRunnable implements Runnable { - public void run() {} + @Override + public void run() {} } @ProvidedBy(Tree.class) static class Money {} static class Tree implements Provider { + @Override public Object get() { return "Money doesn't grow on trees"; } @@ -381,6 +416,7 @@ @ProvidedBy(Chicken.class) static class Chicken implements Provider { + @Override public Chicken get() { return this; } @@ -388,23 +424,30 @@ public void testJitBindingFromAnotherThreadDuringInjection() { final ExecutorService executorService = Executors.newSingleThreadExecutor(); - final AtomicReference got = new AtomicReference(); + final AtomicReference got = new AtomicReference<>(); - Guice.createInjector(new AbstractModule() { - protected void configure() { - requestInjection(new Object() { - @Inject void initialize(final Injector injector) - throws ExecutionException, InterruptedException { - Future future = executorService.submit(new Callable() { - public JustInTime call() throws Exception { - return injector.getInstance(JustInTime.class); - } - }); - got.set(future.get()); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestInjection( + new Object() { + @Inject + void initialize(final Injector injector) + throws ExecutionException, InterruptedException { + Future future = + executorService.submit( + new Callable() { + @Override + public JustInTime call() throws Exception { + return injector.getInstance(JustInTime.class); + } + }); + got.set(future.get()); + } + }); } }); - } - }); assertNotNull(got.get()); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/IntegrationTest.java sisu-guice-4.2.0/core/test/com/google/inject/IntegrationTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/IntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/IntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,24 +19,24 @@ import static com.google.inject.matcher.Matchers.any; import junit.framework.TestCase; - import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class IntegrationTest extends TestCase { public void testIntegration() throws CreationException { final CountingInterceptor counter = new CountingInterceptor(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class); - bindInterceptor(any(), any(), counter); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class); + bindInterceptor(any(), any(), counter); + } + }); Foo foo = injector.getInstance(Key.get(Foo.class)); foo.foo(); @@ -51,6 +51,7 @@ static class Foo { boolean invoked; + public void foo() { invoked = true; } @@ -60,10 +61,10 @@ int count; + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { count++; return methodInvocation.proceed(); } } - } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/Collector.java sisu-guice-4.2.0/core/test/com/google/inject/internal/Collector.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/Collector.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/Collector.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import com.google.inject.multibindings.MapBinderBinding; +import com.google.inject.multibindings.MultibinderBinding; +import com.google.inject.multibindings.MultibindingsTargetVisitor; +import com.google.inject.multibindings.OptionalBinderBinding; +import com.google.inject.spi.DefaultBindingTargetVisitor; + +class Collector extends DefaultBindingTargetVisitor + implements MultibindingsTargetVisitor { + MapBinderBinding mapbinding; + MultibinderBinding setbinding; + OptionalBinderBinding optionalbinding; + + @Override + public Object visit(MapBinderBinding mapbinding) { + this.mapbinding = mapbinding; + return null; + } + + @Override + public Object visit(MultibinderBinding multibinding) { + this.setbinding = multibinding; + return null; + } + + @Override + public Object visit(OptionalBinderBinding optionalbinding) { + this.optionalbinding = optionalbinding; + return null; + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/CycleDetectingLockTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/CycleDetectingLockTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/CycleDetectingLockTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/CycleDetectingLockTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,15 +1,20 @@ package com.google.inject.internal; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multimaps; import com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory; - -import junit.framework.TestCase; - +import com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory.ReentrantCycleDetectingLock; +import java.util.Collection; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import junit.framework.TestCase; public class CycleDetectingLockTest extends TestCase { @@ -27,75 +32,218 @@ * T1: Finishes locking B, unlocks B, unlocks A * * - *

    This should succeed, even though T1 was locked on T2 and T2 is locked on T1 when T2 locks - * A. Incorrect implementation detects a cycle waiting on S3. + *

    This should succeed, even though T1 was locked on T2 and T2 is locked on T1 when T2 locks A. + * Incorrect implementation detects a cycle waiting on S3. */ public void testSingletonThreadsRuntimeCircularDependency() throws Exception { final CyclicBarrier signal1 = new CyclicBarrier(2); final CyclicBarrier signal2 = new CyclicBarrier(2); final CyclicBarrier signal3 = new CyclicBarrier(2); - CycleDetectingLockFactory lockFactory = new CycleDetectingLockFactory(); + final CycleDetectingLockFactory lockFactory = new CycleDetectingLockFactory<>(); final CycleDetectingLock lockA = - lockFactory.new ReentrantCycleDetectingLock("A", new ReentrantLock() { - @Override - public void lock() { - if (Thread.currentThread().getName().equals("T2")) { - try { - signal3.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } catch (Exception e) { - throw new RuntimeException(e); + new ReentrantCycleDetectingLock( + lockFactory, + "A", + new ReentrantLock() { + @Override + public void lock() { + if (Thread.currentThread().getName().equals("T2")) { + try { + signal3.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + assertEquals("T1", Thread.currentThread().getName()); + } + super.lock(); } - } else { - assertEquals("T1", Thread.currentThread().getName()); - } - super.lock(); - } - }); + }); final CycleDetectingLock lockB = - lockFactory.new ReentrantCycleDetectingLock("B", new ReentrantLock() { - @Override - public void lock() { - if (Thread.currentThread().getName().equals("T1")) { - try { - signal2.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); - signal3.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } catch (Exception e) { - throw new RuntimeException(e); + new ReentrantCycleDetectingLock( + lockFactory, + "B", + new ReentrantLock() { + @Override + public void lock() { + if (Thread.currentThread().getName().equals("T1")) { + try { + signal2.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + signal3.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + assertEquals("T2", Thread.currentThread().getName()); + } + super.lock(); } - } else { - assertEquals("T2", Thread.currentThread().getName()); - } - super.lock(); - } - }); - Future firstThreadResult = Executors.newSingleThreadExecutor().submit( - new Callable() { - public Void call() throws Exception { - Thread.currentThread().setName("T1"); - signal1.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); - assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty()); - assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty()); - lockB.unlock(); - lockA.unlock(); - return null; - } - }); - Future secondThreadResult = Executors.newSingleThreadExecutor().submit( - new Callable() { - public Void call() throws Exception { - Thread.currentThread().setName("T2"); - assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty()); - signal1.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); - signal2.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); - lockB.unlock(); - assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty()); - lockA.unlock(); - return null; - } - }); + }); + Future firstThreadResult = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public Void call() throws Exception { + Thread.currentThread().setName("T1"); + signal1.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty()); + assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty()); + lockB.unlock(); + lockA.unlock(); + return null; + } + }); + Future secondThreadResult = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public Void call() throws Exception { + Thread.currentThread().setName("T2"); + assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty()); + signal1.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + signal2.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + lockB.unlock(); + assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty()); + lockA.unlock(); + return null; + } + }); + + firstThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS); + secondThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS); + } + + /** + * Verifies that factories do not deadlock each other. + * + *

    +   *   Thread A: lock a lock A (factory A)
    +   *   Thread B: lock a lock B (factory B)
    +   *   Thread A: lock a lock B (factory B)
    +   *   Thread B: lock a lock A (factory A)
    +   * 
    + * + *

    This should succeed even though from the point of view of each individual factory there are + * no deadlocks to detect. + */ + + public void testCycleDetectingLockFactoriesDoNotDeadlock() throws Exception { + final CycleDetectingLockFactory factoryA = new CycleDetectingLockFactory<>(); + final CycleDetectingLock lockA = factoryA.create("A"); + final CycleDetectingLockFactory factoryB = new CycleDetectingLockFactory<>(); + final CycleDetectingLock lockB = factoryB.create("B"); + final CyclicBarrier eachThreadAcquiredFirstLock = new CyclicBarrier(2); + Future threadA = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public Boolean call() throws Exception { + Thread.currentThread().setName("A"); + assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty()); + eachThreadAcquiredFirstLock.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + boolean isEmpty = lockB.lockOrDetectPotentialLocksCycle().isEmpty(); + if (isEmpty) { + lockB.unlock(); + } + lockA.unlock(); + return isEmpty; + } + }); + Future threadB = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public Boolean call() throws Exception { + Thread.currentThread().setName("B"); + assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty()); + eachThreadAcquiredFirstLock.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + boolean isEmpty = lockA.lockOrDetectPotentialLocksCycle().isEmpty(); + if (isEmpty) { + lockA.unlock(); + } + lockB.unlock(); + return isEmpty; + } + }); - firstThreadResult.get(); - secondThreadResult.get(); + boolean deadlockADetected = threadA.get(DEADLOCK_TIMEOUT_SECONDS * 2, TimeUnit.SECONDS); + boolean deadlockBDetected = threadB.get(DEADLOCK_TIMEOUT_SECONDS * 2, TimeUnit.SECONDS); + + assertTrue("Deadlock should get detected", deadlockADetected || deadlockBDetected); + assertTrue("One deadlock should get detected", deadlockADetected != deadlockBDetected); + } + + /** + * Verifies that factories deadlocks report the correct cycles. + * + *

    +   *   Thread 1: takes locks a, b
    +   *   Thread 2: takes locks b, c
    +   *   Thread 3: takes locks c, a
    +   * 
    + * + *

    In order to ensure a deadlock, each thread will wait on a barrier right after grabbing the + * first lock. + */ + + public void testCycleReporting() throws Exception { + final CycleDetectingLockFactory factory = new CycleDetectingLockFactory<>(); + final CycleDetectingLock lockA = factory.create("a"); + final CycleDetectingLock lockB = factory.create("b"); + final CycleDetectingLock lockC = factory.create("c"); + final CyclicBarrier barrier = new CyclicBarrier(3); + ImmutableList>> futures = + ImmutableList.of( + grabLocksInThread(lockA, lockB, barrier), + grabLocksInThread(lockB, lockC, barrier), + grabLocksInThread(lockC, lockA, barrier)); + + // At least one of the threads will report a lock cycle, it is possible that they all will, but + // there is no guarantee, so we just scan for the first thread that reported a cycle + ListMultimap cycle = null; + for (Future> future : futures) { + ListMultimap value = + future.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS); + if (!value.isEmpty()) { + cycle = value; + break; + } + } + // We don't really care about the keys in the multimap, but we want to make sure that all locks + // were reported in the right order. + assertEquals(6, cycle.size()); + Collection> edges = Multimaps.asMap(cycle).values(); + assertTrue(edges.contains(ImmutableList.of("a", "b"))); + assertTrue(edges.contains(ImmutableList.of("b", "c"))); + assertTrue(edges.contains(ImmutableList.of("c", "a"))); + } + + private static Future> grabLocksInThread( + final CycleDetectingLock lock1, + final CycleDetectingLock lock2, + final CyclicBarrier barrier) { + FutureTask> future = + new FutureTask>( + new Callable>() { + @Override + public ListMultimap call() throws Exception { + assertTrue(lock1.lockOrDetectPotentialLocksCycle().isEmpty()); + barrier.await(); + ListMultimap cycle = lock2.lockOrDetectPotentialLocksCycle(); + if (cycle == null) { + lock2.unlock(); + } + lock1.unlock(); + return cycle; + } + }); + Thread thread = new Thread(future); + thread.start(); + return future; } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/InternalProvisionExceptionTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/InternalProvisionExceptionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/InternalProvisionExceptionTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/InternalProvisionExceptionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.inject.internal; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.inject.internal.util.SourceProvider; +import junit.framework.TestCase; + +public final class InternalProvisionExceptionTest extends TestCase { + + public void testSourceFormatting() { + // Note that the duplicate source gets dropped as well as the unknown source + assertThat( + InternalProvisionException.create("An error") + .addSource("Source1") + .addSource(SourceProvider.UNKNOWN_SOURCE) + .addSource("Source2") + .addSource("Source2") + .toProvisionException() + .getMessage()) + .isEqualTo( + "" + + "Unable to provision, see the following errors:\n" + + "\n" + + "1) An error\n" + + " at Source1\n" + + " at Source2\n" + + "\n" + + "1 error"); + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/MapBinderTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/MapBinderTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/MapBinderTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/MapBinderTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,1590 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import static com.google.inject.Asserts.asModuleChain; +import static com.google.inject.Asserts.assertContains; +import static com.google.inject.internal.SpiUtils.VisitType.BOTH; +import static com.google.inject.internal.SpiUtils.VisitType.MODULE; +import static com.google.inject.internal.SpiUtils.assertMapVisitor; +import static com.google.inject.internal.SpiUtils.instance; +import static com.google.inject.internal.SpiUtils.providerInstance; +import static com.google.inject.name.Names.named; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.inject.AbstractModule; +import com.google.inject.Asserts; +import com.google.inject.Binding; +import com.google.inject.BindingAnnotation; +import com.google.inject.ConfigurationException; +import com.google.inject.CreationException; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.ProvisionException; +import com.google.inject.Stage; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.RealMapBinder.ProviderMapEntry; +import com.google.inject.multibindings.MapBinder; +import com.google.inject.multibindings.MapBinderBinding; +import com.google.inject.name.Names; +import com.google.inject.spi.DefaultElementVisitor; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.Elements; +import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.InstanceBinding; +import com.google.inject.spi.ProviderInstanceBinding; +import com.google.inject.util.Modules; +import com.google.inject.util.Providers; +import com.google.inject.util.Types; +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; + +/** @author dpb@google.com (David P. Baker) */ +public class MapBinderTest extends TestCase { + + private static final ImmutableSet> FRAMEWORK_KEYS = + ImmutableSet.of( + Key.get(java.util.logging.Logger.class), Key.get(Stage.class), Key.get(Injector.class)); + + final TypeLiteral>> mapOfStringJavaxProvider = + new TypeLiteral>>() {}; + final TypeLiteral>> mapOfStringProvider = + new TypeLiteral>>() {}; + final TypeLiteral> mapOfString = new TypeLiteral>() {}; + final TypeLiteral> mapOfIntString = + new TypeLiteral>() {}; + final TypeLiteral> mapOfInteger = new TypeLiteral>() {}; + final TypeLiteral>> mapOfSetOfString = + new TypeLiteral>>() {}; + + private final TypeLiteral stringType = TypeLiteral.get(String.class); + private final TypeLiteral intType = TypeLiteral.get(Integer.class); + + private Type javaxProviderOf(Type type) { + return Types.javaxProviderOf(type); + } + + private Type mapEntryOf(Type keyType, Type valueType) { + return Types.newParameterizedTypeWithOwner(Map.class, Map.Entry.class, keyType, valueType); + } + + private Type collectionOf(Type type) { + return Types.newParameterizedType(Collection.class, type); + } + + public void testAllBindings() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class).permitDuplicates(); + } + }; + + Injector injector = Guice.createInjector(module); + + Map, Binding> bindings = injector.getBindings(); + + ImmutableSet> expectedBindings = + ImmutableSet.>builder() + .add( + // Map + Key.get(Types.mapOf(String.class, String.class)), + // Map> + Key.get(Types.mapOf(String.class, Types.providerOf(String.class))), + // Map> + Key.get(Types.mapOf(String.class, javaxProviderOf(String.class))), + // Map> + Key.get(Types.mapOf(String.class, Types.setOf(String.class))), + // Map> + Key.get(Types.mapOf(String.class, Types.setOf(Types.providerOf(String.class)))), + // Map> + Key.get( + Types.mapOf(String.class, Types.setOf(Types.javaxProviderOf(String.class)))), + // Map> + Key.get( + Types.mapOf(String.class, Types.collectionOf(Types.providerOf(String.class)))), + // Map> + Key.get( + Types.mapOf( + String.class, Types.collectionOf(Types.javaxProviderOf(String.class)))), + // Set>> + Key.get(Types.setOf(mapEntryOf(String.class, Types.providerOf(String.class)))), + // Set>> + Key.get(Types.setOf(mapEntryOf(String.class, Types.javaxProviderOf(String.class)))), + // Collection>>> + Key.get( + collectionOf( + Types.providerOf( + mapEntryOf(String.class, Types.providerOf(String.class))))), + // Collection>>> + Key.get( + collectionOf( + Types.javaxProviderOf( + mapEntryOf(String.class, Types.providerOf(String.class))))), + // @Named(...) Boolean + Key.get( + Boolean.class, + named( + "Multibinder>> permits duplicates"))) + .addAll(FRAMEWORK_KEYS) + .build(); + + Set> missingBindings = Sets.difference(expectedBindings, bindings.keySet()); + Set> extraBindings = Sets.difference(bindings.keySet(), expectedBindings); + + assertTrue( + "There should be no missing bindings. Missing: " + missingBindings, + missingBindings.isEmpty()); + assertTrue( + "There should be no extra bindings. Extra: " + extraBindings, extraBindings.isEmpty()); + } + + public void testMapBinderAggregatesMultipleModules() { + Module abc = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + multibinder.addBinding("c").toInstance("C"); + } + }; + Module de = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("d").toInstance("D"); + multibinder.addBinding("e").toInstance("E"); + } + }; + + Injector injector = Guice.createInjector(abc, de); + Map abcde = injector.getInstance(Key.get(mapOfString)); + + assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E"), abcde); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(abc, de), + BOTH, + false, + 0, + instance("a", "A"), + instance("b", "B"), + instance("c", "C"), + instance("d", "D"), + instance("e", "E")); + + // just make sure these succeed + injector.getInstance(Key.get(mapOfStringProvider)); + injector.getInstance(Key.get(mapOfStringJavaxProvider)); + } + + public void testMapBinderAggregationForAnnotationInstance() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class, Names.named("abc")); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + + multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class, Names.named("abc")); + multibinder.addBinding("c").toInstance("C"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> key = Key.get(mapOfString, Names.named("abc")); + Map abc = injector.getInstance(key); + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); + assertMapVisitor( + key, + stringType, + stringType, + setOf(module), + BOTH, + false, + 0, + instance("a", "A"), + instance("b", "B"), + instance("c", "C")); + + // just make sure these succeed + injector.getInstance(Key.get(mapOfStringProvider, Names.named("abc"))); + injector.getInstance(Key.get(mapOfStringJavaxProvider, Names.named("abc"))); + } + + public void testMapBinderAggregationForAnnotationType() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class, Abc.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + + multibinder = MapBinder.newMapBinder(binder(), String.class, String.class, Abc.class); + multibinder.addBinding("c").toInstance("C"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> key = Key.get(mapOfString, Abc.class); + Map abc = injector.getInstance(key); + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); + assertMapVisitor( + key, + stringType, + stringType, + setOf(module), + BOTH, + false, + 0, + instance("a", "A"), + instance("b", "B"), + instance("c", "C")); + + // just make sure these succeed + injector.getInstance(Key.get(mapOfStringProvider, Abc.class)); + injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class)); + } + + public void testMapBinderWithMultipleAnnotationValueSets() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder abcMapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class, named("abc")); + abcMapBinder.addBinding("a").toInstance("A"); + abcMapBinder.addBinding("b").toInstance("B"); + abcMapBinder.addBinding("c").toInstance("C"); + + MapBinder deMapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class, named("de")); + deMapBinder.addBinding("d").toInstance("D"); + deMapBinder.addBinding("e").toInstance("E"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> abcKey = Key.get(mapOfString, named("abc")); + Map abc = injector.getInstance(abcKey); + Key> deKey = Key.get(mapOfString, named("de")); + Map de = injector.getInstance(deKey); + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); + assertEquals(mapOf("d", "D", "e", "E"), de); + assertMapVisitor( + abcKey, + stringType, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("a", "A"), + instance("b", "B"), + instance("c", "C")); + assertMapVisitor( + deKey, + stringType, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("d", "D"), + instance("e", "E")); + + // just make sure these succeed + injector.getInstance(Key.get(mapOfStringProvider, named("abc"))); + injector.getInstance(Key.get(mapOfStringJavaxProvider, named("abc"))); + injector.getInstance(Key.get(mapOfStringProvider, named("de"))); + injector.getInstance(Key.get(mapOfStringJavaxProvider, named("de"))); + } + + public void testMapBinderWithMultipleAnnotationTypeSets() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder abcMapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class, Abc.class); + abcMapBinder.addBinding("a").toInstance("A"); + abcMapBinder.addBinding("b").toInstance("B"); + abcMapBinder.addBinding("c").toInstance("C"); + + MapBinder deMapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class, De.class); + deMapBinder.addBinding("d").toInstance("D"); + deMapBinder.addBinding("e").toInstance("E"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> abcKey = Key.get(mapOfString, Abc.class); + Map abc = injector.getInstance(abcKey); + Key> deKey = Key.get(mapOfString, De.class); + Map de = injector.getInstance(deKey); + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); + assertEquals(mapOf("d", "D", "e", "E"), de); + assertMapVisitor( + abcKey, + stringType, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("a", "A"), + instance("b", "B"), + instance("c", "C")); + assertMapVisitor( + deKey, + stringType, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("d", "D"), + instance("e", "E")); + + // just make sure these succeed + injector.getInstance(Key.get(mapOfStringProvider, Abc.class)); + injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class)); + injector.getInstance(Key.get(mapOfStringProvider, De.class)); + injector.getInstance(Key.get(mapOfStringJavaxProvider, De.class)); + } + + public void testMapBinderWithMultipleTypes() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("a") + .toInstance("A"); + MapBinder.newMapBinder(binder(), String.class, Integer.class) + .addBinding("1") + .toInstance(1); + } + }; + Injector injector = Guice.createInjector(module); + + assertEquals(mapOf("a", "A"), injector.getInstance(Key.get(mapOfString))); + assertEquals(mapOf("1", 1), injector.getInstance(Key.get(mapOfInteger))); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("a", "A")); + assertMapVisitor( + Key.get(mapOfInteger), + stringType, + intType, + setOf(module), + BOTH, + false, + 1, + instance("1", 1)); + } + + public void testMapBinderWithEmptyMap() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class); + } + }; + Injector injector = Guice.createInjector(module); + + Map map = injector.getInstance(Key.get(mapOfString)); + assertEquals(Collections.emptyMap(), map); + assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0); + } + + public void testMapBinderMapIsUnmodifiable() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("a") + .toInstance("A"); + } + }); + + Map map = injector.getInstance(Key.get(mapOfString)); + try { + map.clear(); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + public void testMapBinderMapIsLazy() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, Integer.class) + .addBinding("num") + .toProvider( + new Provider() { + int nextValue = 1; + + @Override + public Integer get() { + return nextValue++; + } + }); + } + }; + Injector injector = Guice.createInjector(module); + + assertEquals(mapOf("num", 1), injector.getInstance(Key.get(mapOfInteger))); + assertEquals(mapOf("num", 2), injector.getInstance(Key.get(mapOfInteger))); + assertEquals(mapOf("num", 3), injector.getInstance(Key.get(mapOfInteger))); + assertMapVisitor( + Key.get(mapOfInteger), + stringType, + intType, + setOf(module), + BOTH, + false, + 0, + providerInstance("num", 1)); + } + + public void testMapBinderMapForbidsDuplicateKeys() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("a").toInstance("B"); + } + }; + try { + Guice.createInjector(module); + fail(); + } catch (CreationException expected) { + assertContains(expected.getMessage(), "Map injection failed due to duplicated key \"a\""); + } + + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(module), + MODULE, + false, + 0, + instance("a", "A"), + instance("a", "B")); + } + + public void testExhaustiveDuplicateErrorMessage() throws Exception { + class Module1 extends AbstractModule { + @Override + protected void configure() { + MapBinder mapbinder = + MapBinder.newMapBinder(binder(), String.class, Object.class); + mapbinder.addBinding("a").to(String.class); + } + } + class Module2 extends AbstractModule { + @Override + protected void configure() { + MapBinder mapbinder = + MapBinder.newMapBinder(binder(), String.class, Object.class); + mapbinder.addBinding("a").to(Integer.class); + mapbinder.addBinding("b").to(String.class); + } + } + class Module3 extends AbstractModule { + @Override + protected void configure() { + MapBinder mapbinder = + MapBinder.newMapBinder(binder(), String.class, Object.class); + mapbinder.addBinding("b").to(Integer.class); + } + } + class Main extends AbstractModule { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, Object.class); + install(new Module1()); + install(new Module2()); + install(new Module3()); + } + + @Provides + String provideString() { + return "foo"; + } + + @Provides + Integer provideInt() { + return 42; + } + } + try { + Guice.createInjector(new Main()); + fail(); + } catch (CreationException ce) { + assertContains( + ce.getMessage(), + "Map injection failed due to duplicated key \"a\", from bindings:", + asModuleChain(Main.class, Module1.class), + asModuleChain(Main.class, Module2.class), + "and key: \"b\", from bindings:", + asModuleChain(Main.class, Module2.class), + asModuleChain(Main.class, Module3.class), + "at " + Main.class.getName() + ".configure(", + asModuleChain(Main.class, RealMapBinder.class)); + assertEquals(1, ce.getErrorMessages().size()); + } + } + + public void testMapBinderMapPermitDuplicateElements() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + multibinder.permitDuplicates(); + } + }; + Module bc = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("b").toInstance("B"); + multibinder.addBinding("c").toInstance("C"); + multibinder.permitDuplicates(); + } + }; + Injector injector = Guice.createInjector(ab, bc); + + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injector.getInstance(Key.get(mapOfString))); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(ab, bc), + BOTH, + true, + 0, + instance("a", "A"), + instance("b", "B"), + instance("c", "C")); + } + + public void testMapBinderMapDoesNotDedupeDuplicateValues() { + class ValueType { + int keyPart; + int dataPart; + + private ValueType(int keyPart, int dataPart) { + this.keyPart = keyPart; + this.dataPart = dataPart; + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof ValueType) && (keyPart == ((ValueType) obj).keyPart); + } + + @Override + public int hashCode() { + return keyPart; + } + } + Module m1 = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, ValueType.class); + multibinder.addBinding("a").toInstance(new ValueType(1, 2)); + } + }; + Module m2 = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, ValueType.class); + multibinder.addBinding("b").toInstance(new ValueType(1, 3)); + } + }; + + Injector injector = Guice.createInjector(m1, m2); + Map map = injector.getInstance(new Key>() {}); + assertEquals(2, map.get("a").dataPart); + assertEquals(3, map.get("b").dataPart); + } + + public void testMapBinderMultimap() { + AbstractModule ab1c = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B1"); + multibinder.addBinding("c").toInstance("C"); + } + }; + AbstractModule b2c = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("b").toInstance("B2"); + multibinder.addBinding("c").toInstance("C"); + multibinder.permitDuplicates(); + } + }; + Injector injector = Guice.createInjector(ab1c, b2c); + + assertEquals( + mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")), + injector.getInstance(Key.get(mapOfSetOfString))); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(ab1c, b2c), + BOTH, + true, + 0, + instance("a", "A"), + instance("b", "B1"), + instance("b", "B2"), + instance("c", "C")); + } + + public void testMapBinderMultimapWithAnotation() { + AbstractModule ab1 = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class, Abc.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B1"); + } + }; + AbstractModule b2c = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class, Abc.class); + multibinder.addBinding("b").toInstance("B2"); + multibinder.addBinding("c").toInstance("C"); + multibinder.permitDuplicates(); + } + }; + Injector injector = Guice.createInjector(ab1, b2c); + + assertEquals( + mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")), + injector.getInstance(Key.get(mapOfSetOfString, Abc.class))); + try { + injector.getInstance(Key.get(mapOfSetOfString)); + fail(); + } catch (ConfigurationException expected) { + } + + assertMapVisitor( + Key.get(mapOfString, Abc.class), + stringType, + stringType, + setOf(ab1, b2c), + BOTH, + true, + 0, + instance("a", "A"), + instance("b", "B1"), + instance("b", "B2"), + instance("c", "C")); + } + + public void testMapBinderMultimapIsUnmodifiable() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + mapBinder.addBinding("a").toInstance("A"); + mapBinder.permitDuplicates(); + } + }); + + Map> map = injector.getInstance(Key.get(mapOfSetOfString)); + try { + map.clear(); + fail(); + } catch (UnsupportedOperationException expected) { + } + try { + map.get("a").clear(); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + public void testMapBinderMapForbidsNullKeys() { + try { + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class).addBinding(null); + } + }); + fail(); + } catch (CreationException expected) { + } + } + + public void testMapBinderMapForbidsNullValues() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("null") + .toProvider(Providers.of(null)); + } + }; + Injector injector = Guice.createInjector(m); + + try { + injector.getInstance(Key.get(mapOfString)); + fail(); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "1) Map injection failed due to null value for key \"null\", bound at: " + + m.getClass().getName() + + ".configure("); + } + } + + public void testMapBinderProviderIsScoped() { + final Provider counter = + new Provider() { + int next = 1; + + @Override + public Integer get() { + return next++; + } + }; + + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, Integer.class) + .addBinding("one") + .toProvider(counter) + .asEagerSingleton(); + } + }); + + assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one")); + assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one")); + } + + public void testSourceLinesInMapBindings() { + try { + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, Integer.class).addBinding("one"); + } + }); + fail(); + } catch (CreationException expected) { + assertContains( + expected.getMessage(), + "1) No implementation for java.lang.Integer", + "at " + getClass().getName()); + } + } + + /** Check that the dependencies are correct. */ + public void testMultibinderDependencies() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), Integer.class, String.class); + mapBinder.addBinding(1).toInstance("A"); + mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b"))); + + bindConstant().annotatedWith(Names.named("b")).to("B"); + } + }); + + Binding> binding = injector.getBinding(new Key>() {}); + HasDependencies withDependencies = (HasDependencies) binding; + Set> actualDependencies = withDependencies.getDependencies(); + + // We expect two dependencies, because the dependencies are annotated with + // Element, which has a uniqueId, it's difficult to directly compare them. + // Instead we will manually compare all the fields except the uniqueId + assertEquals(2, actualDependencies.size()); + for (Dependency dependency : actualDependencies) { + Key key = dependency.getKey(); + assertEquals(new TypeLiteral() {}, key.getTypeLiteral()); + Annotation annotation = dependency.getKey().getAnnotation(); + assertTrue(annotation instanceof Element); + Element element = (Element) annotation; + assertEquals("", element.setName()); + assertEquals(Element.Type.MAPBINDER, element.type()); + assertEquals("java.lang.Integer", element.keyType()); + } + + Set elements = Sets.newHashSet(); + elements.addAll(recurseForDependencies(injector, withDependencies)); + assertEquals(ImmutableSet.of("A", "B"), elements); + } + + private Set recurseForDependencies(Injector injector, HasDependencies hasDependencies) { + Set elements = Sets.newHashSet(); + for (Dependency dependency : hasDependencies.getDependencies()) { + Binding binding = injector.getBinding(dependency.getKey()); + HasDependencies deps = (HasDependencies) binding; + if (binding instanceof InstanceBinding) { + elements.add((String) ((InstanceBinding) binding).getInstance()); + } else { + elements.addAll(recurseForDependencies(injector, deps)); + } + } + return elements; + } + + /** Check that the dependencies are correct in the Tool Stage. */ + public void testMultibinderDependenciesInToolStage() { + Injector injector = + Guice.createInjector( + Stage.TOOL, + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), Integer.class, String.class); + mapBinder.addBinding(1).toInstance("A"); + mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b"))); + + bindConstant().annotatedWith(Names.named("b")).to("B"); + } + }); + + Binding> binding = injector.getBinding(new Key>() {}); + HasDependencies withDependencies = (HasDependencies) binding; + Set> actualDependencies = withDependencies.getDependencies(); + + // We expect two dependencies, because the dependencies are annotated with + // Element, which has a uniqueId, it's difficult to directly compare them. + // Instead we will manually compare all the fields except the uniqueId + assertEquals(2, actualDependencies.size()); + for (Dependency dependency : actualDependencies) { + Key key = dependency.getKey(); + assertEquals(new TypeLiteral() {}, key.getTypeLiteral()); + Annotation annotation = dependency.getKey().getAnnotation(); + assertTrue(annotation instanceof Element); + Element element = (Element) annotation; + assertEquals("", element.setName()); + assertEquals(Element.Type.MAPBINDER, element.type()); + assertEquals("java.lang.Integer", element.keyType()); + } + } + + /** Our implementation maintains order, but doesn't guarantee it in the API spec. */ + // TODO: specify the iteration order + public void testBindOrderEqualsIterationOrder() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + mapBinder.addBinding("leonardo").toInstance("blue"); + mapBinder.addBinding("donatello").toInstance("purple"); + install( + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("michaelangelo") + .toInstance("orange"); + } + }); + } + }, + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("raphael") + .toInstance("red"); + } + }); + + Map map = injector.getInstance(new Key>() {}); + Iterator> iterator = map.entrySet().iterator(); + assertEquals(Maps.immutableEntry("leonardo", "blue"), iterator.next()); + assertEquals(Maps.immutableEntry("donatello", "purple"), iterator.next()); + assertEquals(Maps.immutableEntry("michaelangelo", "orange"), iterator.next()); + assertEquals(Maps.immutableEntry("raphael", "red"), iterator.next()); + } + + /** With overrides, we should get the union of all map bindings. */ + public void testModuleOverrideAndMapBindings() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + } + }; + Module cd = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("c").toInstance("C"); + multibinder.addBinding("d").toInstance("D"); + } + }; + Module ef = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("e").toInstance("E"); + multibinder.addBinding("f").toInstance("F"); + } + }; + + Module abcd = Modules.override(ab).with(cd); + Injector injector = Guice.createInjector(abcd, ef); + assertEquals( + mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"), + injector.getInstance(Key.get(mapOfString))); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(abcd, ef), + BOTH, + false, + 0, + instance("a", "A"), + instance("b", "B"), + instance("c", "C"), + instance("d", "D"), + instance("e", "E"), + instance("f", "F")); + } + + public void testDeduplicateMapBindings() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapbinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + mapbinder.addBinding("a").toInstance("A"); + mapbinder.addBinding("a").toInstance("A"); + mapbinder.addBinding("b").toInstance("B"); + mapbinder.addBinding("b").toInstance("B"); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals(mapOf("a", "A", "b", "B"), injector.getInstance(Key.get(mapOfString))); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(module), + BOTH, + false, + 0, + instance("a", "A"), + instance("b", "B")); + } + + /** With overrides, we should get the union of all map bindings. */ + public void testModuleOverrideAndMapBindingsWithPermitDuplicates() { + Module abc = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + multibinder.addBinding("c").toInstance("C"); + multibinder.permitDuplicates(); + } + }; + Module cd = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("c").toInstance("C"); + multibinder.addBinding("d").toInstance("D"); + multibinder.permitDuplicates(); + } + }; + Module ef = + new AbstractModule() { + @Override + protected void configure() { + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("e").toInstance("E"); + multibinder.addBinding("f").toInstance("F"); + multibinder.permitDuplicates(); + } + }; + + Module abcd = Modules.override(abc).with(cd); + Injector injector = Guice.createInjector(abcd, ef); + assertEquals( + mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"), + injector.getInstance(Key.get(mapOfString))); + assertMapVisitor( + Key.get(mapOfString), + stringType, + stringType, + setOf(abcd, ef), + BOTH, + true, + 0, + instance("a", "A"), + instance("b", "B"), + instance("c", "C"), + instance("d", "D"), + instance("e", "E"), + instance("f", "F")); + } + + /** Ensure there are no initialization race conditions in basic map injection. */ + public void testBasicMapDependencyInjection() { + final AtomicReference> injectedMap = + new AtomicReference>(); + final Object anObject = + new Object() { + @Inject + void initialize(Map map) { + injectedMap.set(map); + } + }; + Module abc = + new AbstractModule() { + @Override + protected void configure() { + requestInjection(anObject); + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + multibinder.addBinding("c").toInstance("C"); + } + }; + Guice.createInjector(abc); + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injectedMap.get()); + } + + /** Ensure there are no initialization race conditions in provider multimap injection. */ + public void testProviderMultimapDependencyInjection() { + final AtomicReference>>> injectedMultimap = + new AtomicReference>>>(); + final Object anObject = + new Object() { + @Inject + void initialize(Map>> multimap) { + injectedMultimap.set(multimap); + } + }; + Module abc = + new AbstractModule() { + @Override + protected void configure() { + requestInjection(anObject); + MapBinder multibinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + multibinder.permitDuplicates(); + multibinder.addBinding("a").toInstance("A"); + multibinder.addBinding("b").toInstance("B"); + multibinder.addBinding("c").toInstance("C"); + } + }; + Guice.createInjector(abc); + Map map = + Maps.transformValues( + injectedMultimap.get(), + new Function>, String>() { + @Override + public String apply(Set> stringProvidersSet) { + return Iterables.getOnlyElement(stringProvidersSet).get(); + } + }); + assertEquals(mapOf("a", "A", "b", "B", "c", "C"), map); + } + + @Retention(RUNTIME) + @BindingAnnotation + @interface Abc {} + + @Retention(RUNTIME) + @BindingAnnotation + @interface De {} + + @SuppressWarnings("unchecked") + private Map mapOf(Object... elements) { + Map result = new HashMap<>(); + for (int i = 0; i < elements.length; i += 2) { + result.put((K) elements[i], (V) elements[i + 1]); + } + return result; + } + + @SuppressWarnings("unchecked") + private Set setOf(V... elements) { + return new HashSet(Arrays.asList(elements)); + } + + @BindingAnnotation + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) + private static @interface Marker {} + + @Marker + public void testMapBinderMatching() throws Exception { + Method m = MapBinderTest.class.getDeclaredMethod("testMapBinderMatching"); + assertNotNull(m); + final Annotation marker = m.getAnnotation(Marker.class); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + public void configure() { + MapBinder mb1 = + MapBinder.newMapBinder(binder(), Integer.class, Integer.class, Marker.class); + MapBinder mb2 = + MapBinder.newMapBinder(binder(), Integer.class, Integer.class, marker); + mb1.addBinding(1).toInstance(1); + mb2.addBinding(2).toInstance(2); + + // This assures us that the two binders are equivalent, so we expect the instance added to + // each to have been added to one set. + assertEquals(mb1, mb2); + } + }); + TypeLiteral> t = new TypeLiteral>() {}; + Map s1 = injector.getInstance(Key.get(t, Marker.class)); + Map s2 = injector.getInstance(Key.get(t, marker)); + + // This assures us that the two sets are in fact equal. They may not be same set (as in Java + // object identical), but we shouldn't expect that, since probably Guice creates the set each + // time in case the elements are dependent on scope. + assertEquals(s1, s2); + + // This ensures that MultiBinder is internally using the correct set name -- + // making sure that instances of marker annotations have the same set name as + // MarkerAnnotation.class. + Map expected = new HashMap<>(); + expected.put(1, 1); + expected.put(2, 2); + assertEquals(expected, s1); + } + + public void testTwoMapBindersAreDistinct() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("A") + .toInstance("a"); + + MapBinder.newMapBinder(binder(), Integer.class, String.class) + .addBinding(1) + .toInstance("b"); + } + }); + Collector collector = new Collector(); + Binding> map1 = injector.getBinding(Key.get(mapOfString)); + map1.acceptTargetVisitor(collector); + assertNotNull(collector.mapbinding); + MapBinderBinding map1Binding = collector.mapbinding; + + Binding> map2 = injector.getBinding(Key.get(mapOfIntString)); + map2.acceptTargetVisitor(collector); + assertNotNull(collector.mapbinding); + MapBinderBinding map2Binding = collector.mapbinding; + + List> bindings = injector.findBindingsByType(stringType); + assertEquals("should have two elements: " + bindings, 2, bindings.size()); + Binding a = bindings.get(0); + Binding b = bindings.get(1); + assertEquals("a", ((InstanceBinding) a).getInstance()); + assertEquals("b", ((InstanceBinding) b).getInstance()); + + // Make sure the correct elements belong to their own sets. + assertTrue(map1Binding.containsElement(a)); + assertFalse(map1Binding.containsElement(b)); + + assertFalse(map2Binding.containsElement(a)); + assertTrue(map2Binding.containsElement(b)); + } + + // Tests for com.google.inject.internal.WeakKeySet not leaking memory. + public void testWeakKeySet_integration_mapbinder() { + Key> mapKey = Key.get(new TypeLiteral>() {}); + + Injector parentInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("hi"); + } + }); + WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey); + + Injector childInjector = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + MapBinder binder = + MapBinder.newMapBinder(binder(), String.class, String.class); + binder.addBinding("bar").toInstance("foo"); + } + }); + WeakReference weakRef = new WeakReference<>(childInjector); + WeakKeySetUtils.assertBlacklisted(parentInjector, mapKey); + + // Clear the ref, GC, and ensure that we are no longer blacklisting. + childInjector = null; + + Asserts.awaitClear(weakRef); + WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey); + } + + @SuppressWarnings("rawtypes") + public void testGetEntries() { + List elements = + Elements.getElements(new MapBinderWithTwoEntriesModule()); + + // Get the MapBinderBinding + MapBinderBinding mapBinderBinding = getMapBinderBinding(elements); + + // Execute the call to getEntries + List>> mapEntries = mapBinderBinding.getEntries(elements); + + // Assert on the results + Map.Entry> firstEntry = mapEntries.get(0); + assertEquals("keyOne", firstEntry.getKey()); + Binding firstBinding = firstEntry.getValue(); + assertEquals("valueOne", ((InstanceBinding) firstBinding).getInstance()); + + Map.Entry> secondEntry = mapEntries.get(1); + assertEquals("keyTwo", secondEntry.getKey()); + Binding secondBinding = secondEntry.getValue(); + assertEquals("valueTwo", ((InstanceBinding) secondBinding).getInstance()); + } + + @SuppressWarnings("rawtypes") + public void testGetEntriesWithDuplicateKeys() { + // Set up the module + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + mapBinder.addBinding("A").toInstance("a1"); + mapBinder.addBinding("A").toInstance("a2"); + mapBinder.permitDuplicates(); + } + }; + + // Get the MapBinderBinding + List elements = Elements.getElements(module); + MapBinderBinding mapBinderBinding = getMapBinderBinding(elements); + + // Execute the call to getEntries + List>> mapEntries = mapBinderBinding.getEntries(elements); + + // Assert on the results + Map.Entry> firstEntry = mapEntries.get(0); + assertEquals("A", firstEntry.getKey()); + Binding firstBinding = firstEntry.getValue(); + assertEquals("a1", ((InstanceBinding) firstBinding).getInstance()); + + Map.Entry> secondEntry = mapEntries.get(1); + assertEquals("A", secondEntry.getKey()); + Binding secondBinding = secondEntry.getValue(); + assertEquals("a2", ((InstanceBinding) secondBinding).getInstance()); + } + + @SuppressWarnings("rawtypes") + public void testGetEntriesWithDuplicateValues() { + // Set up the module + Module module = + new AbstractModule() { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + mapBinder.addBinding("A").toInstance("a"); + mapBinder.addBinding("A").toInstance("a"); + } + }; + + // Get the MapBinderBinding + List elements = Elements.getElements(module); + MapBinderBinding mapBinderBinding = getMapBinderBinding(elements); + + // Execute the call to getEntries + List>> mapEntries = mapBinderBinding.getEntries(elements); + + // Assert on the results + Map.Entry> firstEntry = mapEntries.get(0); + assertEquals("A", firstEntry.getKey()); + Binding firstBinding = firstEntry.getValue(); + assertEquals("a", ((InstanceBinding) firstBinding).getInstance()); + + Map.Entry> secondEntry = mapEntries.get(1); + assertEquals("A", secondEntry.getKey()); + Binding secondBinding = secondEntry.getValue(); + assertEquals("a", ((InstanceBinding) secondBinding).getInstance()); + } + + @SuppressWarnings("rawtypes") + public void testGetEntriesMissingProviderMapEntry() { + List elements = + Lists.newArrayList(Elements.getElements(new MapBinderWithTwoEntriesModule())); + + // Get the MapBinderBinding + MapBinderBinding mapBinderBinding = getMapBinderBinding(elements); + + // Remove the ProviderMapEntry for "a" from the elements + com.google.inject.spi.Element providerMapEntryForA = getProviderMapEntry("keyOne", elements); + boolean removeSuccessful = elements.remove(providerMapEntryForA); + assertTrue(removeSuccessful); + + // Execute the call to getEntries, we expect it to fail + try { + mapBinderBinding.getEntries(elements); + fail(); + } catch (IllegalArgumentException expected) { + assertContains( + expected.getMessage(), + "Expected a 1:1 mapping from map keys to values.", + "Found these Bindings that were missing an associated entry:", + "java.lang.String", + "bound at:", + "MapBinderWithTwoEntriesModule"); + } + } + + /** + * Will find and return the {@link com.google.inject.spi.Element} that is a {@link + * ProviderMapEntry} with a key that matches the one supplied by the user in {@code k}. + * + *

    Will return {@code null} if it cannot be found. + */ + private static com.google.inject.spi.Element getProviderMapEntry( + Object kToFind, Iterable elements) { + for (com.google.inject.spi.Element element : elements) { + if (element instanceof ProviderInstanceBinding) { + javax.inject.Provider usp = + ((ProviderInstanceBinding) element).getUserSuppliedProvider(); + if (usp instanceof ProviderMapEntry) { + ProviderMapEntry pme = (ProviderMapEntry) usp; + + // Check if the key from the ProviderMapEntry matches the one we're looking for + if (kToFind.equals(pme.getKey())) { + return element; + } + } + } + } + // No matching ProviderMapEntry found + return null; + } + + @SuppressWarnings("rawtypes") + public void testGetEntriesMissingBindingForValue() { + List elements = + Lists.newArrayList(Elements.getElements(new MapBinderWithTwoEntriesModule())); + + // Get the MapBinderBinding + MapBinderBinding mapBinderBinding = getMapBinderBinding(elements); + + // Remove the ProviderMapEntry for "a" from the elements + com.google.inject.spi.Element bindingForA = getInstanceBindingForValue("valueOne", elements); + boolean removeSuccessful = elements.remove(bindingForA); + assertTrue(removeSuccessful); + + // Execute the call to getEntries, we expect it to fail + try { + mapBinderBinding.getEntries(elements); + fail(); + } catch (IllegalArgumentException expected) { + assertContains( + expected.getMessage(), + "Expected a 1:1 mapping from map keys to values.", + "Found these map keys without a corresponding value:", + "keyOne", + "bound at:", + "MapBinderWithTwoEntriesModule"); + } + } + + /** + * Will find and return the {@link com.google.inject.spi.Element} that is an {@link + * InstanceBinding} and binds {@code vToFind}. + */ + private static com.google.inject.spi.Element getInstanceBindingForValue( + Object vToFind, Iterable elements) { + for (com.google.inject.spi.Element element : elements) { + if (element instanceof InstanceBinding) { + Object instanceFromBinding = ((InstanceBinding) element).getInstance(); + if (vToFind.equals(instanceFromBinding)) { + return element; + } + } + } + // No matching binding found + return null; + } + + /** A simple module with a MapBinder with two entries. */ + private static final class MapBinderWithTwoEntriesModule extends AbstractModule { + @Override + protected void configure() { + MapBinder mapBinder = + MapBinder.newMapBinder(binder(), String.class, String.class); + mapBinder.addBinding("keyOne").toInstance("valueOne"); + mapBinder.addBinding("keyTwo").toInstance("valueTwo"); + } + } + + /** + * Given an {@link Iterable} of elements, return the one that is a {@link MapBinderBinding}, or + * {@code null} if it cannot be found. + */ + private static MapBinderBinding getMapBinderBinding( + Iterable elements) { + final Collector collector = new Collector(); + for (com.google.inject.spi.Element element : elements) { + element.acceptVisitor( + new DefaultElementVisitor() { + @Override + public Void visit(Binding binding) { + binding.acceptTargetVisitor(collector); + return null; + } + }); + } + return collector.mapbinding; + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/MoreTypesTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/MoreTypesTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/MoreTypesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/MoreTypesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,30 +17,32 @@ package com.google.inject.internal; import com.google.inject.TypeLiteral; - -import junit.framework.TestCase; - +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.List; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; -/** - * @author schmitt@google.com (Peter Schmitt) - */ +/** @author schmitt@google.com (Peter Schmitt) */ public class MoreTypesTest extends TestCase { public void testParameterizedTypeToString() { - TypeLiteral> innerString = new TypeLiteral>(){}; - assertEquals("com.google.inject.internal.MoreTypesTest$Inner", + TypeLiteral> innerString = new TypeLiteral>() {}; + assertEquals( + "com.google.inject.internal.MoreTypesTest$Inner", MoreTypes.typeToString(innerString.getType())); TypeLiteral>> mapInnerInteger = new TypeLiteral>>() {}; - assertEquals("java.util.Set>", + assertEquals( + "java.util.Set>", MoreTypes.typeToString(mapInnerInteger.getType())); TypeLiteral, Set>>> mapInnerLongToSetInnerLong = new TypeLiteral, Set>>>() {}; - assertEquals("java.util.Map, " + assertEquals( + "java.util.Map, " + "java.util.Set>>", MoreTypes.typeToString(mapInnerLongToSetInnerLong.getType())); } @@ -50,5 +52,13 @@ assertTrue(MoreTypes.equals(new TypeLiteral() {}.getType(), type)); } + public void testGetRawType_wildcard() throws Exception { + WildcardType wildcard = + (WildcardType) + ((ParameterizedType) new TypeLiteral>() {}.getType()) + .getActualTypeArguments()[0]; + assertEquals(Object.class, MoreTypes.getRawType(wildcard)); + } + public static class Inner {} } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/MultibinderTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/MultibinderTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/MultibinderTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/MultibinderTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,1537 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import static com.google.inject.Asserts.assertContains; +import static com.google.inject.internal.RealMultibinder.collectionOfJavaxProvidersOf; +import static com.google.inject.internal.SpiUtils.VisitType.BOTH; +import static com.google.inject.internal.SpiUtils.VisitType.MODULE; +import static com.google.inject.internal.SpiUtils.assertSetVisitor; +import static com.google.inject.internal.SpiUtils.instance; +import static com.google.inject.internal.SpiUtils.providerInstance; +import static com.google.inject.name.Names.named; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.common.base.Optional; +import com.google.common.base.Predicates; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.inject.AbstractModule; +import com.google.inject.Binding; +import com.google.inject.BindingAnnotation; +import com.google.inject.CreationException; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.ProvisionException; +import com.google.inject.Scopes; +import com.google.inject.Stage; +import com.google.inject.TypeLiteral; +import com.google.inject.multibindings.MapBinder; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.multibindings.OptionalBinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.Element; +import com.google.inject.spi.Elements; +import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.InstanceBinding; +import com.google.inject.spi.LinkedKeyBinding; +import com.google.inject.util.Modules; +import com.google.inject.util.Providers; +import com.google.inject.util.Types; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import junit.framework.TestCase; + +/** @author jessewilson@google.com (Jesse Wilson) */ +public class MultibinderTest extends TestCase { + + final TypeLiteral> optionalOfString = new TypeLiteral>() {}; + final TypeLiteral> mapOfStringString = + new TypeLiteral>() {}; + final TypeLiteral> setOfString = new TypeLiteral>() {}; + final TypeLiteral> setOfInteger = new TypeLiteral>() {}; + final TypeLiteral stringType = TypeLiteral.get(String.class); + final TypeLiteral intType = TypeLiteral.get(Integer.class); + final TypeLiteral> listOfStrings = new TypeLiteral>() {}; + final TypeLiteral>> setOfListOfStrings = new TypeLiteral>>() {}; + final TypeLiteral>> collectionOfProvidersOfStrings = + new TypeLiteral>>() {}; + + public void testMultibinderAggregatesMultipleModules() { + Module abc = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + multibinder.addBinding().toInstance("C"); + } + }; + Module de = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("D"); + multibinder.addBinding().toInstance("E"); + } + }; + + Injector injector = Guice.createInjector(abc, de); + Key> setKey = Key.get(setOfString); + Set abcde = injector.getInstance(setKey); + Set results = setOf("A", "B", "C", "D", "E"); + + assertEquals(results, abcde); + assertSetVisitor( + setKey, + stringType, + setOf(abc, de), + BOTH, + false, + 0, + instance("A"), + instance("B"), + instance("C"), + instance("D"), + instance("E")); + } + + public void testMultibinderAggregationForAnnotationInstance() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class, Names.named("abc")); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + + multibinder = Multibinder.newSetBinder(binder(), String.class, Names.named("abc")); + multibinder.addBinding().toInstance("C"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> setKey = Key.get(setOfString, Names.named("abc")); + Set abc = injector.getInstance(setKey); + Set results = setOf("A", "B", "C"); + assertEquals(results, abc); + assertSetVisitor( + setKey, + stringType, + setOf(module), + BOTH, + false, + 0, + instance("A"), + instance("B"), + instance("C")); + } + + public void testMultibinderAggregationForAnnotationType() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class, Abc.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + + multibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class); + multibinder.addBinding().toInstance("C"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> setKey = Key.get(setOfString, Abc.class); + Set abcde = injector.getInstance(setKey); + Set results = setOf("A", "B", "C"); + assertEquals(results, abcde); + assertSetVisitor( + setKey, + stringType, + setOf(module), + BOTH, + false, + 0, + instance("A"), + instance("B"), + instance("C")); + } + + public void testMultibinderWithMultipleAnnotationValueSets() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder abcMultibinder = + Multibinder.newSetBinder(binder(), String.class, named("abc")); + abcMultibinder.addBinding().toInstance("A"); + abcMultibinder.addBinding().toInstance("B"); + abcMultibinder.addBinding().toInstance("C"); + + Multibinder deMultibinder = + Multibinder.newSetBinder(binder(), String.class, named("de")); + deMultibinder.addBinding().toInstance("D"); + deMultibinder.addBinding().toInstance("E"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> abcSetKey = Key.get(setOfString, named("abc")); + Set abc = injector.getInstance(abcSetKey); + Key> deSetKey = Key.get(setOfString, named("de")); + Set de = injector.getInstance(deSetKey); + Set abcResults = setOf("A", "B", "C"); + assertEquals(abcResults, abc); + Set deResults = setOf("D", "E"); + assertEquals(deResults, de); + assertSetVisitor( + abcSetKey, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("A"), + instance("B"), + instance("C")); + assertSetVisitor( + deSetKey, stringType, setOf(module), BOTH, false, 1, instance("D"), instance("E")); + } + + public void testMultibinderWithMultipleAnnotationTypeSets() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder abcMultibinder = + Multibinder.newSetBinder(binder(), String.class, Abc.class); + abcMultibinder.addBinding().toInstance("A"); + abcMultibinder.addBinding().toInstance("B"); + abcMultibinder.addBinding().toInstance("C"); + + Multibinder deMultibinder = + Multibinder.newSetBinder(binder(), String.class, De.class); + deMultibinder.addBinding().toInstance("D"); + deMultibinder.addBinding().toInstance("E"); + } + }; + Injector injector = Guice.createInjector(module); + + Key> abcSetKey = Key.get(setOfString, Abc.class); + Set abc = injector.getInstance(abcSetKey); + Key> deSetKey = Key.get(setOfString, De.class); + Set de = injector.getInstance(deSetKey); + Set abcResults = setOf("A", "B", "C"); + assertEquals(abcResults, abc); + Set deResults = setOf("D", "E"); + assertEquals(deResults, de); + assertSetVisitor( + abcSetKey, + stringType, + setOf(module), + BOTH, + false, + 1, + instance("A"), + instance("B"), + instance("C")); + assertSetVisitor( + deSetKey, stringType, setOf(module), BOTH, false, 1, instance("D"), instance("E")); + } + + public void testMultibinderWithMultipleSetTypes() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("A"); + Multibinder.newSetBinder(binder(), Integer.class).addBinding().toInstance(1); + } + }; + Injector injector = Guice.createInjector(module); + + assertEquals(setOf("A"), injector.getInstance(Key.get(setOfString))); + assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger))); + assertSetVisitor( + Key.get(setOfString), stringType, setOf(module), BOTH, false, 1, instance("A")); + assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 1, instance(1)); + } + + public void testMultibinderWithEmptySet() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class); + } + }; + Injector injector = Guice.createInjector(module); + + Set set = injector.getInstance(Key.get(setOfString)); + assertEquals(Collections.emptySet(), set); + assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 0); + } + + public void testMultibinderSetIsUnmodifiable() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("A"); + } + }); + + Set set = injector.getInstance(Key.get(setOfString)); + try { + set.clear(); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + public void testMultibinderSetIsSerializable() throws IOException, ClassNotFoundException { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("A"); + } + }); + + Set set = injector.getInstance(Key.get(setOfString)); + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream); + try { + objectOutputStream.writeObject(set); + } finally { + objectOutputStream.close(); + } + ObjectInputStream objectInputStream = + new ObjectInputStream(new ByteArrayInputStream(byteStream.toByteArray())); + try { + Object setCopy = objectInputStream.readObject(); + assertEquals(set, setCopy); + } finally { + objectInputStream.close(); + } + } + + public void testMultibinderSetIsLazy() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), Integer.class) + .addBinding() + .toProvider( + new Provider() { + int nextValue = 1; + + @Override + public Integer get() { + return nextValue++; + } + }); + } + }; + Injector injector = Guice.createInjector(module); + + assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger))); + assertEquals(setOf(2), injector.getInstance(Key.get(setOfInteger))); + assertEquals(setOf(3), injector.getInstance(Key.get(setOfInteger))); + assertSetVisitor( + Key.get(setOfInteger), intType, setOf(module), BOTH, false, 0, providerInstance(1)); + } + + public void testMultibinderSetForbidsDuplicateElements() { + Module module1 = + new AbstractModule() { + @Override + protected void configure() { + final Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toProvider(Providers.of("A")); + } + }; + Module module2 = + new AbstractModule() { + @Override + protected void configure() { + final Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + } + }; + Injector injector = Guice.createInjector(module1, module2); + + try { + injector.getInstance(Key.get(setOfString)); + fail(); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "1) Set injection failed due to duplicated element \"A\"", + "Bound at " + module1.getClass().getName(), + "Bound at " + module2.getClass().getName()); + } + + // But we can still visit the module! + assertSetVisitor( + Key.get(setOfString), + stringType, + setOf(module1, module2), + MODULE, + false, + 0, + instance("A"), + instance("A")); + } + + public void testMultibinderSetShowsBothElementsIfToStringDifferent() { + // A simple example of a type whose toString returns more information than its equals method + // considers. + class ValueType { + int a; + int b; + + ValueType(int a, int b) { + this.a = a; + this.b = b; + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof ValueType) && (((ValueType) obj).a == a); + } + + @Override + public int hashCode() { + return a; + } + + @Override + public String toString() { + return String.format("ValueType(%d,%d)", a, b); + } + } + + Module module1 = + new AbstractModule() { + @Override + protected void configure() { + final Multibinder multibinder = + Multibinder.newSetBinder(binder(), ValueType.class); + multibinder.addBinding().toProvider(Providers.of(new ValueType(1, 2))); + } + }; + Module module2 = + new AbstractModule() { + @Override + protected void configure() { + final Multibinder multibinder = + Multibinder.newSetBinder(binder(), ValueType.class); + multibinder.addBinding().toInstance(new ValueType(1, 3)); + } + }; + Injector injector = Guice.createInjector(module1, module2); + + TypeLiteral valueType = TypeLiteral.get(ValueType.class); + TypeLiteral> setOfValueType = new TypeLiteral>() {}; + try { + injector.getInstance(Key.get(setOfValueType)); + fail(); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "1) Set injection failed due to multiple elements comparing equal:", + "\"ValueType(1,2)\"", + "bound at " + module1.getClass().getName(), + "\"ValueType(1,3)\"", + "bound at " + module2.getClass().getName()); + } + + // But we can still visit the module! + assertSetVisitor( + Key.get(setOfValueType), + valueType, + setOf(module1, module2), + MODULE, + false, + 0, + instance(new ValueType(1, 2)), + instance(new ValueType(1, 3))); + } + + public void testMultibinderSetPermitDuplicateElements() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + } + }; + Module bc = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.permitDuplicates(); + multibinder.addBinding().toInstance("B"); + multibinder.addBinding().toInstance("C"); + } + }; + Injector injector = Guice.createInjector(ab, bc); + + assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString))); + assertSetVisitor( + Key.get(setOfString), + stringType, + setOf(ab, bc), + BOTH, + true, + 0, + instance("A"), + instance("B"), + instance("C")); + } + + public void testMultibinderSetPermitDuplicateElementsFromOtherModule() { + // This module duplicates a binding for "B", which would normally be an error. + // Because module cd is also installed and the Multibinder + // in cd sets permitDuplicates, there should be no error. + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + multibinder.addBinding().toProvider(Providers.of("B")); + } + }; + Module cd = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.permitDuplicates(); + multibinder.addBinding().toInstance("C"); + multibinder.addBinding().toInstance("D"); + } + }; + Injector injector = Guice.createInjector(ab, cd); + + assertEquals(setOf("A", "B", "C", "D"), injector.getInstance(Key.get(setOfString))); + assertSetVisitor( + Key.get(setOfString), + stringType, + setOf(ab, cd), + BOTH, + true, + 0, + instance("A"), + instance("B"), + providerInstance("B"), + instance("C"), + instance("D")); + } + + public void testMultibinderSetPermitDuplicateCallsToPermitDuplicates() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.permitDuplicates(); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + } + }; + Module bc = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.permitDuplicates(); + multibinder.addBinding().toInstance("B"); + multibinder.addBinding().toInstance("C"); + } + }; + Injector injector = Guice.createInjector(ab, bc); + + assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString))); + assertSetVisitor( + Key.get(setOfString), + stringType, + setOf(ab, bc), + BOTH, + true, + 0, + instance("A"), + instance("B"), + instance("C")); + } + + public void testMultibinderSetForbidsNullElements() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class) + .addBinding() + .toProvider(Providers.of(null)); + } + }; + Injector injector = Guice.createInjector(m); + + try { + injector.getInstance(Key.get(setOfString)); + fail(); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "1) Set injection failed due to null element bound at: " + + m.getClass().getName() + + ".configure("); + } + } + + public void testSourceLinesInMultibindings() { + try { + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), Integer.class).addBinding(); + } + }); + fail(); + } catch (CreationException expected) { + assertContains( + expected.getMessage(), + true, + "No implementation for java.lang.Integer", + "at " + getClass().getName()); + } + } + + /** + * We just want to make sure that multibinder's binding depends on each of its values. We don't + * really care about the underlying structure of those bindings, which are implementation details. + */ + public void testMultibinderDependencies() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().to(Key.get(String.class, Names.named("b"))); + + bindConstant().annotatedWith(Names.named("b")).to("B"); + } + }); + + Binding> binding = injector.getBinding(new Key>() {}); + HasDependencies withDependencies = (HasDependencies) binding; + Set elements = Sets.newHashSet(); + for (Dependency dependency : withDependencies.getDependencies()) { + elements.add((String) injector.getInstance(dependency.getKey())); + } + assertEquals(ImmutableSet.of("A", "B"), elements); + } + + /** + * We just want to make sure that multibinder's binding depends on each of its values. We don't + * really care about the underlying structure of those bindings, which are implementation details. + */ + public void testMultibinderDependenciesInToolStage() { + Injector injector = + Guice.createInjector( + Stage.TOOL, + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().to(Key.get(String.class, Names.named("b"))); + + bindConstant().annotatedWith(Names.named("b")).to("B"); + } + }); + + Binding> binding = injector.getBinding(new Key>() {}); + HasDependencies withDependencies = (HasDependencies) binding; + InstanceBinding instanceBinding = null; + LinkedKeyBinding linkedBinding = null; + // The non-tool stage test can test this by calling injector.getInstance to ensure + // the right values are returned -- in tool stage we can't do that. It's also a + // little difficult to validate the dependencies & bindings, because they're + // bindings created internally within Multibinder. + // To workaround this, we just validate that the dependencies lookup to a single + // InstanceBinding whose value is "A" and another LinkedBinding whose target is + // the Key of @Named("b") String=B + for (Dependency dependency : withDependencies.getDependencies()) { + Binding b = injector.getBinding(dependency.getKey()); + if (b instanceof InstanceBinding) { + if (instanceBinding != null) { + fail( + "Already have an instance binding of: " + + instanceBinding + + ", and now want to add: " + + b); + } else { + instanceBinding = (InstanceBinding) b; + } + } else if (b instanceof LinkedKeyBinding) { + if (linkedBinding != null) { + fail( + "Already have a linked binding of: " + linkedBinding + ", and now want to add: " + b); + } else { + linkedBinding = (LinkedKeyBinding) b; + } + } else { + fail("Unexpected dependency of: " + dependency); + } + } + + assertNotNull(instanceBinding); + assertNotNull(linkedBinding); + + assertEquals("A", instanceBinding.getInstance()); + assertEquals(Key.get(String.class, Names.named("b")), linkedBinding.getLinkedKey()); + } + + /** + * Our implementation maintains order, but doesn't guarantee it in the API spec. TODO: specify the + * iteration order? + */ + public void testBindOrderEqualsIterationOrder() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("leonardo"); + multibinder.addBinding().toInstance("donatello"); + install( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class) + .addBinding() + .toInstance("michaelangelo"); + } + }); + } + }, + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("raphael"); + } + }); + + List inOrder = ImmutableList.copyOf(injector.getInstance(Key.get(setOfString))); + assertEquals(ImmutableList.of("leonardo", "donatello", "michaelangelo", "raphael"), inOrder); + } + + @Retention(RUNTIME) + @BindingAnnotation + @interface Abc {} + + @Retention(RUNTIME) + @BindingAnnotation + @interface De {} + + private Set setOf(T... elements) { + Set result = Sets.newHashSet(); + Collections.addAll(result, elements); + return result; + } + + /** With overrides, we should get the union of all multibindings. */ + public void testModuleOverrideAndMultibindings() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + } + }; + Module cd = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("C"); + multibinder.addBinding().toInstance("D"); + } + }; + Module ef = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("E"); + multibinder.addBinding().toInstance("F"); + } + }; + + Module abcd = Modules.override(ab).with(cd); + Injector injector = Guice.createInjector(abcd, ef); + assertEquals( + ImmutableSet.of("A", "B", "C", "D", "E", "F"), injector.getInstance(Key.get(setOfString))); + + assertSetVisitor( + Key.get(setOfString), + stringType, + setOf(abcd, ef), + BOTH, + false, + 0, + instance("A"), + instance("B"), + instance("C"), + instance("D"), + instance("E"), + instance("F")); + } + + /** With overrides, we should get the union of all multibindings. */ + public void testModuleOverrideAndMultibindingsWithPermitDuplicates() { + Module abc = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + multibinder.addBinding().toInstance("C"); + multibinder.permitDuplicates(); + } + }; + Module cd = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("C"); + multibinder.addBinding().toInstance("D"); + multibinder.permitDuplicates(); + } + }; + Module ef = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("E"); + multibinder.addBinding().toInstance("F"); + multibinder.permitDuplicates(); + } + }; + + Module abcd = Modules.override(abc).with(cd); + Injector injector = Guice.createInjector(abcd, ef); + assertEquals( + ImmutableSet.of("A", "B", "C", "D", "E", "F"), injector.getInstance(Key.get(setOfString))); + + assertSetVisitor( + Key.get(setOfString), + stringType, + setOf(abcd, ef), + BOTH, + true, + 0, + instance("A"), + instance("B"), + instance("C"), + instance("D"), + instance("E"), + instance("F")); + } + + /** Doubly-installed modules should not conflict, even when one is overridden. */ + public void testModuleOverrideRepeatedInstallsAndMultibindings_toInstance() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toInstance("A"); + multibinder.addBinding().toInstance("B"); + } + }; + + // Guice guarantees this assertion, as the same module cannot be installed twice. + assertEquals( + ImmutableSet.of("A", "B"), Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); + + // Guice will only guarantee this assertion if Multibinder ensures the bindings match. + Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); + assertEquals(ImmutableSet.of("A", "B"), injector.getInstance(Key.get(setOfString))); + } + + public void testModuleOverrideRepeatedInstallsAndMultibindings_toKey() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Key aKey = Key.get(String.class, Names.named("A_string")); + Key bKey = Key.get(String.class, Names.named("B_string")); + bind(aKey).toInstance("A"); + bind(bKey).toInstance("B"); + + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().to(aKey); + multibinder.addBinding().to(bKey); + } + }; + + // Guice guarantees this assertion, as the same module cannot be installed twice. + assertEquals( + ImmutableSet.of("A", "B"), Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); + + // Guice will only guarantee this assertion if Multibinder ensures the bindings match. + Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); + assertEquals(ImmutableSet.of("A", "B"), injector.getInstance(Key.get(setOfString))); + } + + public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderInstance() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toProvider(Providers.of("A")); + multibinder.addBinding().toProvider(Providers.of("B")); + } + }; + + // Guice guarantees this assertion, as the same module cannot be installed twice. + assertEquals( + ImmutableSet.of("A", "B"), Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); + + // Guice will only guarantee this assertion if Multibinder ensures the bindings match. + Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); + assertEquals(ImmutableSet.of("A", "B"), injector.getInstance(Key.get(setOfString))); + } + + private static class AStringProvider implements Provider { + @Override + public String get() { + return "A"; + } + } + + private static class BStringProvider implements Provider { + @Override + public String get() { + return "B"; + } + } + + public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderKey() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toProvider(Key.get(AStringProvider.class)); + multibinder.addBinding().toProvider(Key.get(BStringProvider.class)); + } + }; + + // Guice guarantees this assertion, as the same module cannot be installed twice. + assertEquals( + ImmutableSet.of("A", "B"), Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); + + // Guice will only guarantee this assertion if Multibinder ensures the bindings match. + Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); + assertEquals(ImmutableSet.of("A", "B"), injector.getInstance(Key.get(setOfString))); + } + + private static class StringGrabber { + private final String string; + + @SuppressWarnings("unused") // Found by reflection + public StringGrabber(@Named("A_string") String string) { + this.string = string; + } + + @SuppressWarnings("unused") // Found by reflection + public StringGrabber(@Named("B_string") String string, int unused) { + this.string = string; + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string); + } + + @Override + public String toString() { + return "StringGrabber(" + string + ")"; + } + + static Set values(Iterable grabbers) { + Set result = new HashSet<>(); + for (StringGrabber grabber : grabbers) { + result.add(grabber.string); + } + return result; + } + } + + public void testModuleOverrideRepeatedInstallsAndMultibindings_toConstructor() { + TypeLiteral> setOfStringGrabber = new TypeLiteral>() {}; + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Key aKey = Key.get(String.class, Names.named("A_string")); + Key bKey = Key.get(String.class, Names.named("B_string")); + bind(aKey).toInstance("A"); + bind(bKey).toInstance("B"); + bind(Integer.class).toInstance(0); // used to disambiguate constructors + + Multibinder multibinder = + Multibinder.newSetBinder(binder(), StringGrabber.class); + try { + multibinder + .addBinding() + .toConstructor(StringGrabber.class.getConstructor(String.class)); + multibinder + .addBinding() + .toConstructor(StringGrabber.class.getConstructor(String.class, int.class)); + } catch (NoSuchMethodException e) { + fail("No such method: " + e.getMessage()); + } + } + }; + + // Guice guarantees this assertion, as the same module cannot be installed twice. + assertEquals( + ImmutableSet.of("A", "B"), + StringGrabber.values( + Guice.createInjector(ab, ab).getInstance(Key.get(setOfStringGrabber)))); + + // Guice will only guarantee this assertion if Multibinder ensures the bindings match. + Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); + assertEquals( + ImmutableSet.of("A", "B"), + StringGrabber.values(injector.getInstance(Key.get(setOfStringGrabber)))); + } + + /** + * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or + * explicitly bound in {@link Scopes#NO_SCOPE}. + */ + public void testDuplicateUnscopedBindings() { + Module singleBinding = + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).to(Key.get(Integer.class, named("A"))); + bind(Integer.class).to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE); + } + + @Provides + @Named("A") + int provideInteger() { + return 5; + } + }; + Module multibinding = + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), Integer.class); + multibinder.addBinding().to(Key.get(Integer.class, named("A"))); + multibinder.addBinding().to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE); + } + }; + + assertEquals(5, (int) Guice.createInjector(singleBinding).getInstance(Integer.class)); + assertEquals( + ImmutableSet.of(5), + Guice.createInjector(singleBinding, multibinding).getInstance(Key.get(setOfInteger))); + } + + /** Ensure key hash codes are fixed at injection time, not binding time. */ + public void testKeyHashCodesFixedAtInjectionTime() { + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder> multibinder = + Multibinder.newSetBinder(binder(), listOfStrings); + List list = Lists.newArrayList(); + multibinder.addBinding().toInstance(list); + list.add("A"); + list.add("B"); + } + }; + + Injector injector = Guice.createInjector(ab); + for (Entry, Binding> entry : injector.getAllBindings().entrySet()) { + Key bindingKey = entry.getKey(); + Key clonedKey; + if (bindingKey.getAnnotation() != null) { + clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation()); + } else if (bindingKey.getAnnotationType() != null) { + clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType()); + } else { + clonedKey = Key.get(bindingKey.getTypeLiteral()); + } + assertEquals(bindingKey, clonedKey); + assertEquals( + "Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(), + bindingKey.hashCode(), + clonedKey.hashCode()); + } + } + + /** Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}. */ + public void testBindingKeysFixedOnReturnFromGetElements() { + final List list = Lists.newArrayList(); + Module ab = + new AbstractModule() { + @Override + protected void configure() { + Multibinder> multibinder = + Multibinder.newSetBinder(binder(), listOfStrings); + multibinder.addBinding().toInstance(list); + list.add("A"); + list.add("B"); + } + }; + + InstanceBinding binding = + Iterables.getOnlyElement(Iterables.filter(Elements.getElements(ab), InstanceBinding.class)); + Key keyBefore = binding.getKey(); + assertEquals(listOfStrings, keyBefore.getTypeLiteral()); + + list.add("C"); + Key keyAfter = binding.getKey(); + assertSame(keyBefore, keyAfter); + } + + /* + * Verify through gratuitous mutation that key hashCode snapshots and whatnot happens at the right + * times, by binding two lists that are different at injector creation, but compare equal when the + * module is configured *and* when the set is instantiated. + */ + public void testConcurrentMutation_bindingsDiffentAtInjectorCreation() { + // We initially bind two equal lists + final List list1 = Lists.newArrayList(); + final List list2 = Lists.newArrayList(); + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder> multibinder = + Multibinder.newSetBinder(binder(), listOfStrings); + multibinder.addBinding().toInstance(list1); + multibinder.addBinding().toInstance(list2); + } + }; + List elements = Elements.getElements(module); + + // Now we change the lists so they no longer match, and create the injector. + list1.add("A"); + list2.add("B"); + Injector injector = Guice.createInjector(Elements.getModule(elements)); + + // Now we change the lists so they compare equal again, and create the set. + list1.add(1, "B"); + list2.add(0, "A"); + try { + injector.getInstance(Key.get(setOfListOfStrings)); + fail(); + } catch (ProvisionException e) { + assertEquals(1, e.getErrorMessages().size()); + assertContains( + Iterables.getOnlyElement(e.getErrorMessages()).getMessage().toString(), + "Set injection failed due to duplicated element \"[A, B]\""); + } + + // Finally, we change the lists again so they are once more different, and ensure the set + // contains both. + list1.remove("A"); + list2.remove("B"); + Set> set = injector.getInstance(Key.get(setOfListOfStrings)); + assertEquals(ImmutableSet.of(ImmutableList.of("A"), ImmutableList.of("B")), set); + } + + /* + * Verify through gratuitous mutation that key hashCode snapshots and whatnot happen at the right + * times, by binding two lists that compare equal at injector creation, but are different when the + * module is configured *and* when the set is instantiated. + */ + public void testConcurrentMutation_bindingsSameAtInjectorCreation() { + // We initially bind two distinct lists + final List list1 = Lists.newArrayList("A"); + final List list2 = Lists.newArrayList("B"); + Module module = + new AbstractModule() { + @Override + protected void configure() { + Multibinder> multibinder = + Multibinder.newSetBinder(binder(), listOfStrings); + multibinder.addBinding().toInstance(list1); + multibinder.addBinding().toInstance(list2); + } + }; + List elements = Elements.getElements(module); + + // Now we change the lists so they compare equal, and create the injector. + list1.add(1, "B"); + list2.add(0, "A"); + Injector injector = Guice.createInjector(Elements.getModule(elements)); + + // Now we change the lists again so they are once more different, and create the set. + list1.remove("A"); + list2.remove("B"); + Set> set = injector.getInstance(Key.get(setOfListOfStrings)); + + // The set will contain just one of the two lists. + // (In fact, it will be the first one we bound, but we don't promise that, so we won't test it.) + assertTrue( + ImmutableSet.of(ImmutableList.of("A")).equals(set) + || ImmutableSet.of(ImmutableList.of("B")).equals(set)); + } + + @BindingAnnotation + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) + private static @interface Marker {} + + @Marker + public void testMultibinderMatching() throws Exception { + Method m = MultibinderTest.class.getDeclaredMethod("testMultibinderMatching"); + assertNotNull(m); + final Annotation marker = m.getAnnotation(Marker.class); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + public void configure() { + Multibinder mb1 = + Multibinder.newSetBinder(binder(), Integer.class, Marker.class); + Multibinder mb2 = + Multibinder.newSetBinder(binder(), Integer.class, marker); + mb1.addBinding().toInstance(1); + mb2.addBinding().toInstance(2); + + // This assures us that the two binders are equivalent, so we expect the instance added to + // each to have been added to one set. + assertEquals(mb1, mb2); + } + }); + TypeLiteral> t = new TypeLiteral>() {}; + Set s1 = injector.getInstance(Key.get(t, Marker.class)); + Set s2 = injector.getInstance(Key.get(t, marker)); + + // This assures us that the two sets are in fact equal. They may not be same set (as in Java + // object identical), but we shouldn't expect that, since probably Guice creates the set each + // time in case the elements are dependent on scope. + assertEquals(s1, s2); + + // This ensures that MultiBinder is internally using the correct set name -- + // making sure that instances of marker annotations have the same set name as + // MarkerAnnotation.class. + Set expected = new HashSet<>(); + expected.add(1); + expected.add(2); + assertEquals(expected, s1); + } + + // See issue 670 + public void testSetAndMapValueAreDistinct() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("A"); + + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("B") + .toInstance("b"); + + OptionalBinder.newOptionalBinder(binder(), String.class) + .setDefault() + .toInstance("C"); + OptionalBinder.newOptionalBinder(binder(), String.class) + .setBinding() + .toInstance("D"); + } + }); + + assertEquals(ImmutableSet.of("A"), injector.getInstance(Key.get(setOfString))); + assertEquals(ImmutableMap.of("B", "b"), injector.getInstance(Key.get(mapOfStringString))); + assertEquals(Optional.of("D"), injector.getInstance(Key.get(optionalOfString))); + } + + // See issue 670 + public void testSetAndMapValueAreDistinctInSpi() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("A"); + + MapBinder.newMapBinder(binder(), String.class, String.class) + .addBinding("B") + .toInstance("b"); + + OptionalBinder.newOptionalBinder(binder(), String.class) + .setDefault() + .toInstance("C"); + } + }); + Collector collector = new Collector(); + Binding> mapbinding = injector.getBinding(Key.get(mapOfStringString)); + mapbinding.acceptTargetVisitor(collector); + assertNotNull(collector.mapbinding); + + Binding> setbinding = injector.getBinding(Key.get(setOfString)); + setbinding.acceptTargetVisitor(collector); + assertNotNull(collector.setbinding); + + Binding> optionalbinding = injector.getBinding(Key.get(optionalOfString)); + optionalbinding.acceptTargetVisitor(collector); + assertNotNull(collector.optionalbinding); + + // There should only be three instance bindings for string types + // (but because of the OptionalBinder, there's 2 ProviderInstanceBindings also). + // We also know the InstanceBindings will be in the order: A, b, C because that's + // how we bound them, and binding order is preserved. + List> bindings = + FluentIterable.from(injector.findBindingsByType(stringType)) + .filter(Predicates.instanceOf(InstanceBinding.class)) + .toList(); + assertEquals(bindings.toString(), 3, bindings.size()); + Binding a = bindings.get(0); + Binding b = bindings.get(1); + Binding c = bindings.get(2); + assertEquals("A", ((InstanceBinding) a).getInstance()); + assertEquals("b", ((InstanceBinding) b).getInstance()); + assertEquals("C", ((InstanceBinding) c).getInstance()); + + // Make sure the correct elements belong to their own sets. + assertFalse(collector.mapbinding.containsElement(a)); + assertTrue(collector.mapbinding.containsElement(b)); + assertFalse(collector.mapbinding.containsElement(c)); + + assertTrue(collector.setbinding.containsElement(a)); + assertFalse(collector.setbinding.containsElement(b)); + assertFalse(collector.setbinding.containsElement(c)); + + assertFalse(collector.optionalbinding.containsElement(a)); + assertFalse(collector.optionalbinding.containsElement(b)); + assertTrue(collector.optionalbinding.containsElement(c)); + } + + public void testMultibinderCanInjectCollectionOfProviders() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + final Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class); + multibinder.addBinding().toProvider(Providers.of("A")); + multibinder.addBinding().toProvider(Providers.of("B")); + multibinder.addBinding().toInstance("C"); + } + }; + Collection expectedValues = ImmutableList.of("A", "B", "C"); + + Injector injector = Guice.createInjector(module); + + Collection> providers = + injector.getInstance(Key.get(collectionOfProvidersOfStrings)); + assertEquals(expectedValues, collectValues(providers)); + + Collection> javaxProviders = + injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType))); + assertEquals(expectedValues, collectValues(javaxProviders)); + } + + public void testMultibinderCanInjectCollectionOfProvidersWithAnnotation() { + final Annotation ann = Names.named("foo"); + Module module = + new AbstractModule() { + @Override + protected void configure() { + final Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class, ann); + multibinder.addBinding().toProvider(Providers.of("A")); + multibinder.addBinding().toProvider(Providers.of("B")); + multibinder.addBinding().toInstance("C"); + } + }; + Collection expectedValues = ImmutableList.of("A", "B", "C"); + + Injector injector = Guice.createInjector(module); + + Collection> providers = + injector.getInstance(Key.get(collectionOfProvidersOfStrings, ann)); + Collection values = collectValues(providers); + assertEquals(expectedValues, values); + + Collection> javaxProviders = + injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType), ann)); + assertEquals(expectedValues, collectValues(javaxProviders)); + } + + public void testMultibindingProviderDependencies() { + final Annotation setAnn = Names.named("foo"); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder multibinder = + Multibinder.newSetBinder(binder(), String.class, setAnn); + multibinder.addBinding().toInstance("a"); + multibinder.addBinding().toInstance("b"); + } + }); + HasDependencies providerBinding = + (HasDependencies) injector.getBinding(new Key>>(setAnn) {}); + HasDependencies setBinding = + (HasDependencies) injector.getBinding(new Key>(setAnn) {}); + // sanity check the size + assertEquals(setBinding.getDependencies().toString(), 2, setBinding.getDependencies().size()); + Set> expected = Sets.newHashSet(); + for (Dependency dep : setBinding.getDependencies()) { + Key key = dep.getKey(); + Dependency providerDependency = + Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType()))); + expected.add(providerDependency); + } + assertEquals(expected, providerBinding.getDependencies()); + } + + public void testEmptyMultibinder() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), String.class); + } + }); + assertEquals(ImmutableSet.of(), injector.getInstance(new Key>() {})); + assertEquals( + ImmutableList.of(), injector.getInstance(new Key>>() {})); + } + + private static final class ObjectWithInjectionPoint { + boolean setterHasBeenCalled; + + @Inject + void setter(String dummy) { + setterHasBeenCalled = true; + } + } + + // This tests for a behavior where InstanceBindingImpl.getProvider() would return uninitialized + // instances if called during injector creation (depending on the order of injection requests). + public void testMultibinderDependsOnInstanceBindingWithInjectionPoints() { + Guice.createInjector( + new AbstractModule() { + private Provider> provider; + + @Override + protected void configure() { + bind(Object.class).toInstance(this); // force setter() to be injected first + bind(String.class).toInstance("foo"); + this.provider = getProvider(new Key>() {}); + Multibinder.newSetBinder(binder(), ObjectWithInjectionPoint.class) + .addBinding() + .toInstance(new ObjectWithInjectionPoint()); + } + + @Inject + void setter(String s) { + for (ObjectWithInjectionPoint item : provider.get()) { + assertTrue(item.setterHasBeenCalled); + } + } + }); + } + + private Collection collectValues( + Collection> providers) { + Collection values = Lists.newArrayList(); + for (javax.inject.Provider provider : providers) { + values.add(provider.get()); + } + return values; + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/OptionalBinderTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/OptionalBinderTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/OptionalBinderTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/OptionalBinderTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,1476 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import static com.google.inject.Asserts.assertContains; +import static com.google.inject.internal.SpiUtils.assertOptionalVisitor; +import static com.google.inject.internal.SpiUtils.instance; +import static com.google.inject.internal.SpiUtils.linked; +import static com.google.inject.internal.SpiUtils.providerInstance; +import static com.google.inject.internal.SpiUtils.providerKey; +import static com.google.inject.name.Names.named; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.inject.AbstractModule; +import com.google.inject.Asserts; +import com.google.inject.Binding; +import com.google.inject.BindingAnnotation; +import com.google.inject.CreationException; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.SpiUtils.VisitType; +import com.google.inject.multibindings.OptionalBinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.Elements; +import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.InstanceBinding; +import com.google.inject.util.Modules; +import com.google.inject.util.Providers; +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import junit.framework.TestCase; + +/** @author sameb@google.com (Sam Berlin) */ +public class OptionalBinderTest extends TestCase { + + private static final boolean HAS_JAVA_OPTIONAL; + private static final Class JAVA_OPTIONAL_CLASS; + private static final Method JAVA_OPTIONAL_OR_ELSE; + + static { + Class optional = null; + Method orElse = null; + try { + optional = Class.forName("java.util.Optional"); + orElse = optional.getDeclaredMethod("orElse", Object.class); + } catch (ClassNotFoundException ignored) { + } catch (NoSuchMethodException ignored) { + } catch (SecurityException ignored) { + } + HAS_JAVA_OPTIONAL = optional != null; + JAVA_OPTIONAL_CLASS = optional; + JAVA_OPTIONAL_OR_ELSE = orElse; + } + + final Key stringKey = Key.get(String.class); + final TypeLiteral> optionalOfString = new TypeLiteral>() {}; + final TypeLiteral javaOptionalOfString = + HAS_JAVA_OPTIONAL ? RealOptionalBinder.javaOptionalOf(stringKey.getTypeLiteral()) : null; + final TypeLiteral>> optionalOfProviderString = + new TypeLiteral>>() {}; + final TypeLiteral javaOptionalOfProviderString = + HAS_JAVA_OPTIONAL + ? RealOptionalBinder.javaOptionalOfProvider(stringKey.getTypeLiteral()) + : null; + final TypeLiteral>> optionalOfJavaxProviderString = + new TypeLiteral>>() {}; + final TypeLiteral javaOptionalOfJavaxProviderString = + HAS_JAVA_OPTIONAL + ? RealOptionalBinder.javaOptionalOfJavaxProvider(stringKey.getTypeLiteral()) + : null; + + final Key intKey = Key.get(Integer.class); + final TypeLiteral> optionalOfInteger = new TypeLiteral>() {}; + final TypeLiteral javaOptionalOfInteger = + HAS_JAVA_OPTIONAL ? RealOptionalBinder.javaOptionalOf(intKey.getTypeLiteral()) : null; + final TypeLiteral>> optionalOfProviderInteger = + new TypeLiteral>>() {}; + final TypeLiteral javaOptionalOfProviderInteger = + HAS_JAVA_OPTIONAL ? RealOptionalBinder.javaOptionalOfProvider(intKey.getTypeLiteral()) : null; + final TypeLiteral>> optionalOfJavaxProviderInteger = + new TypeLiteral>>() {}; + final TypeLiteral javaOptionalOfJavaxProviderInteger = + HAS_JAVA_OPTIONAL + ? RealOptionalBinder.javaOptionalOfJavaxProvider(intKey.getTypeLiteral()) + : null; + + final TypeLiteral> listOfStrings = new TypeLiteral>() {}; + + public void testTypeNotBoundByDefault() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class); + requireBinding(new Key>() {}); // the above specifies this. + requireBinding(String.class); // but it doesn't specify this. + binder().requireExplicitBindings(); // need to do this, otherwise String will JIT + + if (HAS_JAVA_OPTIONAL) { + requireBinding(Key.get(javaOptionalOfString)); + } + } + }; + + try { + Guice.createInjector(module); + fail(); + } catch (CreationException ce) { + assertContains( + ce.getMessage(), + "1) Explicit bindings are required and java.lang.String is not explicitly bound."); + assertEquals(1, ce.getErrorMessages().size()); + } + } + + public void testOptionalIsAbsentByDefault() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class); + } + }; + + Injector injector = Guice.createInjector(module); + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertFalse(optional.isPresent()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertFalse(optionalP.isPresent()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertFalse(optionalJxP.isPresent()); + + assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, null, null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertFalse(optional.isPresent()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertFalse(optionalP.isPresent()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertFalse(optionalJxP.isPresent()); + } + } + + public void testUsesUserBoundValue() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class); + } + + @Provides + String provideString() { + return "foo"; + } + }; + + Injector injector = Guice.createInjector(module); + assertEquals("foo", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertEquals("foo", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertEquals("foo", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertEquals("foo", optionalJxP.get().get()); + + assertOptionalVisitor( + stringKey, setOf(module), VisitType.BOTH, 0, null, null, providerInstance("foo")); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertEquals("foo", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertEquals("foo", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertEquals("foo", optionalJxP.get().get()); + } + } + + public void testUsesUserBoundValueNullProvidersMakeAbsent() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class); + } + + @Provides + String provideString() { + return null; + } + }; + + Injector injector = Guice.createInjector(module); + assertEquals(null, injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertFalse(optional.isPresent()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertEquals(null, optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertEquals(null, optionalJxP.get().get()); + + assertOptionalVisitor( + stringKey, setOf(module), VisitType.BOTH, 0, null, null, providerInstance(null)); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertFalse(optional.isPresent()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertEquals(null, optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertEquals(null, optionalJxP.get().get()); + } + } + + private static class JitBinding { + @Inject + JitBinding() {} + } + + private static class DependsOnJitBinding { + @Inject + DependsOnJitBinding(JitBinding jitBinding) {} + } + + // A previous version of OptionalBinder would fail to find jit dependendencies that were created + // by other bindings + public void testOptionalBinderDependsOnJitBinding() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), JitBinding.class); + } + }; + + // Everything should be absent since nothing triggered discovery of the jit binding + Injector injector = Guice.createInjector(module); + assertFalse(injector.getInstance(optionalKey(JitBinding.class)).isPresent()); + assertNull(injector.getExistingBinding(Key.get(JitBinding.class))); + + // in this case, because jit bindings are allowed in this injector, the DependsOnJitBinding + // binding will get initialized and create jit bindings for its dependency. The optionalbinder + // should then pick it up + module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), JitBinding.class); + bind(DependsOnJitBinding.class); + } + }; + injector = Guice.createInjector(module); + assertTrue(injector.getInstance(optionalKey(JitBinding.class)).isPresent()); + assertNotNull(injector.getExistingBinding(Key.get(JitBinding.class))); + + // in this case, because the jit binding is discovered dynamically, the optionalbinder won't + // find it. In prior implementations of OptionalBinder this would depend on the exact + // sequencing of the installation of OptionalBinder vs. these injection points that trigger + // dynamic injection. In the current implementation it will consistently not find it. + module = + new AbstractModule() { + @Override + protected void configure() { + bind(Object.class) + .toProvider( + new Provider() { + @Inject + void setter(Injector injector) { + injector.getInstance(JitBinding.class); + } + + @Override + public Object get() { + return null; + } + }); + OptionalBinder.newOptionalBinder(binder(), JitBinding.class); + } + }; + injector = Guice.createInjector(module); + assertFalse(injector.getInstance(optionalKey(JitBinding.class)).isPresent()); + assertNotNull(injector.getExistingBinding(Key.get(JitBinding.class))); + } + + public Key> optionalKey(Class type) { + return Key.get(RealOptionalBinder.optionalOf(TypeLiteral.get(type))); + } + + public void testSetDefault() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals("a", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + + assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + } + } + + public void testSetBinding() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a"); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals("a", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + + assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + } + } + + public void testSetBindingOverridesDefault() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder optionalBinder = + OptionalBinder.newOptionalBinder(binder(), String.class); + optionalBinder.setDefault().toInstance("a"); + optionalBinder.setBinding().toInstance("b"); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals("b", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertTrue(optional.isPresent()); + assertEquals("b", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertEquals("b", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertEquals("b", optionalJxP.get().get()); + + assertOptionalVisitor( + stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), instance("b"), null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertTrue(optional.isPresent()); + assertEquals("b", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertEquals("b", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertEquals("b", optionalJxP.get().get()); + } + } + + public void testSpreadAcrossModules() throws Exception { + Module module1 = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class); + } + }; + Module module2 = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); + } + }; + Module module3 = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); + } + }; + + Injector injector = Guice.createInjector(module1, module2, module3); + assertEquals("b", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertTrue(optional.isPresent()); + assertEquals("b", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertEquals("b", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertEquals("b", optionalJxP.get().get()); + + assertOptionalVisitor( + stringKey, + setOf(module1, module2, module3), + VisitType.BOTH, + 0, + instance("a"), + instance("b"), + null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertTrue(optional.isPresent()); + assertEquals("b", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertEquals("b", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertEquals("b", optionalJxP.get().get()); + } + } + + public void testExactSameBindingCollapses_defaults() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class) + .setDefault() + .toInstance(new String("a")); // using new String to ensure .equals is checked. + OptionalBinder.newOptionalBinder(binder(), String.class) + .setDefault() + .toInstance(new String("a")); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals("a", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + + assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + } + } + + public void testExactSameBindingCollapses_actual() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class) + .setBinding() + .toInstance(new String("a")); // using new String to ensure .equals is checked. + OptionalBinder.newOptionalBinder(binder(), String.class) + .setBinding() + .toInstance(new String("a")); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals("a", injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + + assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertTrue(optional.isPresent()); + assertEquals("a", optional.get()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertEquals("a", optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertEquals("a", optionalJxP.get().get()); + } + } + + public void testDifferentBindingsFail_defaults() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b"); + } + }; + try { + Guice.createInjector(module); + fail(); + } catch (CreationException ce) { + assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "1) A binding to java.lang.String annotated with @" + + RealOptionalBinder.Default.class.getName() + + " was already configured at " + + module.getClass().getName() + + ".configure(", + "at " + module.getClass().getName() + ".configure("); + } + } + + public void testDifferentBindingsFail_actual() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a"); + OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); + } + }; + try { + Guice.createInjector(module); + fail(); + } catch (CreationException ce) { + assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "1) A binding to java.lang.String annotated with @" + + RealOptionalBinder.Actual.class.getName() + + " was already configured at " + + module.getClass().getName() + + ".configure(", + "at " + module.getClass().getName() + ".configure("); + } + } + + public void testDifferentBindingsFail_both() { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b"); + OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); + OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("c"); + } + }; + try { + Guice.createInjector(module); + fail(); + } catch (CreationException ce) { + assertEquals(ce.getMessage(), 2, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "1) A binding to java.lang.String annotated with @" + + RealOptionalBinder.Default.class.getName() + + " was already configured at " + + module.getClass().getName() + + ".configure(", + "at " + module.getClass().getName() + ".configure(", + "2) A binding to java.lang.String annotated with @" + + RealOptionalBinder.Actual.class.getName() + + " was already configured at " + + module.getClass().getName() + + ".configure(", + "at " + module.getClass().getName() + ".configure("); + } + } + + public void testQualifiedAggregatesTogether() throws Exception { + Module module1 = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))); + } + }; + Module module2 = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))) + .setDefault() + .toInstance("a"); + } + }; + Module module3 = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))) + .setBinding() + .toInstance("b"); + } + }; + + Injector injector = Guice.createInjector(module1, module2, module3); + assertEquals("b", injector.getInstance(Key.get(String.class, Names.named("foo")))); + + Optional optional = injector.getInstance(Key.get(optionalOfString, Names.named("foo"))); + assertTrue(optional.isPresent()); + assertEquals("b", optional.get()); + + Optional> optionalP = + injector.getInstance(Key.get(optionalOfProviderString, Names.named("foo"))); + assertTrue(optionalP.isPresent()); + assertEquals("b", optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString, Names.named("foo"))); + assertTrue(optionalJxP.isPresent()); + assertEquals("b", optionalJxP.get().get()); + + assertOptionalVisitor( + Key.get(String.class, Names.named("foo")), + setOf(module1, module2, module3), + VisitType.BOTH, + 0, + instance("a"), + instance("b"), + null); + + if (HAS_JAVA_OPTIONAL) { + optional = + toOptional(injector.getInstance(Key.get(javaOptionalOfString, Names.named("foo")))); + assertTrue(optional.isPresent()); + assertEquals("b", optional.get()); + + optionalP = + toOptional( + injector.getInstance(Key.get(javaOptionalOfProviderString, Names.named("foo")))); + assertTrue(optionalP.isPresent()); + assertEquals("b", optionalP.get().get()); + + optionalJxP = + toOptional( + injector.getInstance(Key.get(javaOptionalOfJavaxProviderString, Names.named("foo")))); + assertTrue(optionalJxP.isPresent()); + assertEquals("b", optionalJxP.get().get()); + } + } + + public void testMultipleDifferentOptionals() { + final Key bKey = Key.get(String.class, named("b")); + final Key cKey = Key.get(String.class, named("c")); + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); + OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(1); + + OptionalBinder.newOptionalBinder(binder(), bKey).setDefault().toInstance("b"); + OptionalBinder.newOptionalBinder(binder(), cKey).setDefault().toInstance("c"); + } + }; + Injector injector = Guice.createInjector(module); + assertEquals("a", injector.getInstance(String.class)); + assertEquals(1, injector.getInstance(Integer.class).intValue()); + assertEquals("b", injector.getInstance(bKey)); + assertEquals("c", injector.getInstance(cKey)); + + assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 3, instance("a"), null, null); + assertOptionalVisitor(intKey, setOf(module), VisitType.BOTH, 3, instance(1), null, null); + assertOptionalVisitor(bKey, setOf(module), VisitType.BOTH, 3, instance("b"), null, null); + assertOptionalVisitor(cKey, setOf(module), VisitType.BOTH, 3, instance("c"), null, null); + } + + public void testOptionalIsAppropriatelyLazy() throws Exception { + Module module = + new AbstractModule() { + int nextValue = 1; + + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), Integer.class) + .setDefault() + .to(Key.get(Integer.class, Names.named("foo"))); + } + + @Provides + @Named("foo") + int provideInt() { + return nextValue++; + } + }; + Injector injector = Guice.createInjector(module); + + Optional> optionalP = + injector.getInstance(Key.get(optionalOfProviderInteger)); + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderInteger)); + + assertEquals(1, injector.getInstance(Integer.class).intValue()); + assertEquals(2, injector.getInstance(Integer.class).intValue()); + + // Calling .get() on an Optional multiple times will keep giving the same thing + Optional optional = injector.getInstance(Key.get(optionalOfInteger)); + assertEquals(3, optional.get().intValue()); + assertEquals(3, optional.get().intValue()); + // But getting another Optional will give a new one. + assertEquals(4, injector.getInstance(Key.get(optionalOfInteger)).get().intValue()); + + // And the Optional will return a provider that gives a new value each time. + assertEquals(5, optionalP.get().get().intValue()); + assertEquals(6, optionalP.get().get().intValue()); + + assertEquals(7, optionalJxP.get().get().intValue()); + assertEquals(8, optionalJxP.get().get().intValue()); + + // and same rules with java.util.Optional + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger))); + assertEquals(9, optional.get().intValue()); + assertEquals(9, optional.get().intValue()); + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger))); + assertEquals(10, optional.get().intValue()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderInteger))); + assertEquals(11, optionalP.get().get().intValue()); + assertEquals(12, optionalP.get().get().intValue()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderInteger))); + assertEquals(13, optionalJxP.get().get().intValue()); + assertEquals(14, optionalJxP.get().get().intValue()); + } + } + + public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_default() + throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class) + .setDefault() + .toProvider(Providers.of(null)); + } + }; + Injector injector = Guice.createInjector(module); + assertNull(injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertFalse(optional.isPresent()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertNull(optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertNull(optionalJxP.get().get()); + + assertOptionalVisitor( + stringKey, + setOf(module), + VisitType.BOTH, + 0, + SpiUtils.providerInstance(null), + null, + null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertFalse(optional.isPresent()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertNull(optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertNull(optionalJxP.get().get()); + } + } + + public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_actual() + throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class) + .setBinding() + .toProvider(Providers.of(null)); + } + }; + Injector injector = Guice.createInjector(module); + assertNull(injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertFalse(optional.isPresent()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertNull(optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertNull(optionalJxP.get().get()); + + assertOptionalVisitor( + stringKey, + setOf(module), + VisitType.BOTH, + 0, + null, + SpiUtils.providerInstance(null), + null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertFalse(optional.isPresent()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertNull(optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertNull(optionalJxP.get().get()); + } + } + + // TODO(sameb): Maybe change this? + public void testLinkedToNullActualDoesntFallbackToDefault() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); + OptionalBinder.newOptionalBinder(binder(), String.class) + .setBinding() + .toProvider(Providers.of(null)); + } + }; + Injector injector = Guice.createInjector(module); + assertNull(injector.getInstance(String.class)); + + Optional optional = injector.getInstance(Key.get(optionalOfString)); + assertFalse(optional.isPresent()); + + Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); + assertTrue(optionalP.isPresent()); + assertNull(optionalP.get().get()); + + Optional> optionalJxP = + injector.getInstance(Key.get(optionalOfJavaxProviderString)); + assertTrue(optionalJxP.isPresent()); + assertNull(optionalP.get().get()); + + assertOptionalVisitor( + stringKey, + setOf(module), + VisitType.BOTH, + 0, + instance("a"), + SpiUtils.providerInstance(null), + null); + + if (HAS_JAVA_OPTIONAL) { + optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); + assertFalse(optional.isPresent()); + + optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); + assertTrue(optionalP.isPresent()); + assertNull(optionalP.get().get()); + + optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); + assertTrue(optionalJxP.isPresent()); + assertNull(optionalJxP.get().get()); + } + } + + public void testSourceLinesInException() { + try { + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault(); + } + }); + fail(); + } catch (CreationException expected) { + assertContains( + expected.getMessage(), + "No implementation for java.lang.Integer", + "at " + getClass().getName()); + } + } + + public void testDependencies_both() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder optionalbinder = + OptionalBinder.newOptionalBinder(binder(), String.class); + optionalbinder.setDefault().toInstance("A"); + optionalbinder.setBinding().to(Key.get(String.class, Names.named("b"))); + bindConstant().annotatedWith(Names.named("b")).to("B"); + } + }); + + Binding binding = injector.getBinding(Key.get(String.class)); + HasDependencies withDependencies = (HasDependencies) binding; + Set elements = Sets.newHashSet(); + elements.addAll(recurseForDependencies(injector, withDependencies)); + assertEquals(ImmutableSet.of("B"), elements); + } + + public void testDependencies_actual() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder optionalbinder = + OptionalBinder.newOptionalBinder(binder(), String.class); + optionalbinder.setBinding().to(Key.get(String.class, Names.named("b"))); + bindConstant().annotatedWith(Names.named("b")).to("B"); + } + }); + + Binding binding = injector.getBinding(Key.get(String.class)); + HasDependencies withDependencies = (HasDependencies) binding; + Set elements = Sets.newHashSet(); + elements.addAll(recurseForDependencies(injector, withDependencies)); + assertEquals(ImmutableSet.of("B"), elements); + } + + public void testDependencies_default() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder optionalbinder = + OptionalBinder.newOptionalBinder(binder(), String.class); + optionalbinder.setDefault().toInstance("A"); + } + }); + + Binding binding = injector.getBinding(Key.get(String.class)); + HasDependencies withDependencies = (HasDependencies) binding; + Set elements = Sets.newHashSet(); + elements.addAll(recurseForDependencies(injector, withDependencies)); + assertEquals(ImmutableSet.of("A"), elements); + } + + @SuppressWarnings("rawtypes") + private Set recurseForDependencies(Injector injector, HasDependencies hasDependencies) { + Set elements = Sets.newHashSet(); + for (Dependency dependency : hasDependencies.getDependencies()) { + Binding binding = injector.getBinding(dependency.getKey()); + HasDependencies deps = (HasDependencies) binding; + if (binding instanceof InstanceBinding) { + elements.add((String) ((InstanceBinding) binding).getInstance()); + } else { + elements.addAll(recurseForDependencies(injector, deps)); + } + } + return elements; + } + + /** Doubly-installed modules should not conflict, even when one is overridden. */ + public void testModuleOverrideRepeatedInstalls_toInstance() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); + b.setDefault().toInstance("A"); + b.setBinding().toInstance("B"); + } + }; + + assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); + + Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); + assertEquals("B", injector.getInstance(Key.get(String.class))); + + assertOptionalVisitor( + stringKey, + setOf(m, Modules.override(m).with(m)), + VisitType.BOTH, + 0, + instance("A"), + instance("B"), + null); + } + + public void testModuleOverrideRepeatedInstalls_toKey() { + final Key aKey = Key.get(String.class, Names.named("A_string")); + final Key bKey = Key.get(String.class, Names.named("B_string")); + Module m = + new AbstractModule() { + @Override + protected void configure() { + bind(aKey).toInstance("A"); + bind(bKey).toInstance("B"); + + OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); + b.setDefault().to(aKey); + b.setBinding().to(bKey); + } + }; + + assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); + + Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); + assertEquals("B", injector.getInstance(Key.get(String.class))); + + assertOptionalVisitor( + stringKey, + setOf(m, Modules.override(m).with(m)), + VisitType.BOTH, + 0, + linked(aKey), + linked(bKey), + null); + } + + public void testModuleOverrideRepeatedInstalls_toProviderInstance() { + // Providers#of() does not redefine equals/hashCode, so use the same one both times. + final Provider aProvider = Providers.of("A"); + final Provider bProvider = Providers.of("B"); + Module m = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); + b.setDefault().toProvider(aProvider); + b.setBinding().toProvider(bProvider); + } + }; + + assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); + + Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); + assertEquals("B", injector.getInstance(Key.get(String.class))); + + assertOptionalVisitor( + stringKey, + setOf(m, Modules.override(m).with(m)), + VisitType.BOTH, + 0, + providerInstance("A"), + providerInstance("B"), + null); + } + + private static class AStringProvider implements Provider { + @Override + public String get() { + return "A"; + } + } + + private static class BStringProvider implements Provider { + @Override + public String get() { + return "B"; + } + } + + public void testModuleOverrideRepeatedInstalls_toProviderKey() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); + b.setDefault().toProvider(Key.get(AStringProvider.class)); + b.setBinding().toProvider(Key.get(BStringProvider.class)); + } + }; + + assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); + + Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); + assertEquals("B", injector.getInstance(Key.get(String.class))); + + assertOptionalVisitor( + stringKey, + setOf(m, Modules.override(m).with(m)), + VisitType.BOTH, + 0, + providerKey(Key.get(AStringProvider.class)), + providerKey(Key.get(BStringProvider.class)), + null); + } + + private static class StringGrabber { + private final String string; + + @SuppressWarnings("unused") // Found by reflection + public StringGrabber(@Named("A_string") String string) { + this.string = string; + } + + @SuppressWarnings("unused") // Found by reflection + public StringGrabber(@Named("B_string") String string, int unused) { + this.string = string; + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string); + } + + @Override + public String toString() { + return "StringGrabber(" + string + ")"; + } + } + + public void testModuleOverrideRepeatedInstalls_toConstructor() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + Key aKey = Key.get(String.class, Names.named("A_string")); + Key bKey = Key.get(String.class, Names.named("B_string")); + bind(aKey).toInstance("A"); + bind(bKey).toInstance("B"); + bind(Integer.class).toInstance(0); // used to disambiguate constructors + + OptionalBinder b = + OptionalBinder.newOptionalBinder(binder(), StringGrabber.class); + try { + b.setDefault().toConstructor(StringGrabber.class.getConstructor(String.class)); + b.setBinding() + .toConstructor(StringGrabber.class.getConstructor(String.class, int.class)); + } catch (NoSuchMethodException e) { + fail("No such method: " + e.getMessage()); + } + } + }; + + assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(StringGrabber.class)).string); + + Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); + assertEquals("B", injector.getInstance(Key.get(StringGrabber.class)).string); + } + + /** + * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or + * explicitly bound in {@link Scopes#NO_SCOPE}. + */ + public void testDuplicateUnscopedBindings() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), Integer.class); + b.setDefault().to(Key.get(Integer.class, named("foo"))); + b.setDefault().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE); + b.setBinding().to(Key.get(Integer.class, named("foo"))); + b.setBinding().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE); + } + + @Provides + @Named("foo") + int provideInt() { + return 5; + } + }; + assertEquals(5, Guice.createInjector(m).getInstance(Integer.class).intValue()); + } + + /** Ensure key hash codes are fixed at injection time, not binding time. */ + public void testKeyHashCodesFixedAtInjectionTime() { + Module m = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder> b = + OptionalBinder.newOptionalBinder(binder(), listOfStrings); + List list = Lists.newArrayList(); + b.setDefault().toInstance(list); + b.setBinding().toInstance(list); + list.add("A"); + list.add("B"); + } + }; + + Injector injector = Guice.createInjector(m); + for (Entry, Binding> entry : injector.getAllBindings().entrySet()) { + Key bindingKey = entry.getKey(); + Key clonedKey; + if (bindingKey.getAnnotation() != null) { + clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation()); + } else if (bindingKey.getAnnotationType() != null) { + clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType()); + } else { + clonedKey = Key.get(bindingKey.getTypeLiteral()); + } + assertEquals(bindingKey, clonedKey); + assertEquals( + "Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(), + bindingKey.hashCode(), + clonedKey.hashCode()); + } + } + + /** Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}. */ + public void testBindingKeysFixedOnReturnFromGetElements() { + final List list = Lists.newArrayList(); + Module m = + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder> b = + OptionalBinder.newOptionalBinder(binder(), listOfStrings); + b.setDefault().toInstance(list); + list.add("A"); + list.add("B"); + } + }; + + InstanceBinding binding = + Iterables.getOnlyElement(Iterables.filter(Elements.getElements(m), InstanceBinding.class)); + Key keyBefore = binding.getKey(); + assertEquals(listOfStrings, keyBefore.getTypeLiteral()); + + list.add("C"); + Key keyAfter = binding.getKey(); + assertSame(keyBefore, keyAfter); + } + + @BindingAnnotation + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) + private static @interface Marker {} + + @Marker + public void testMatchingMarkerAnnotations() throws Exception { + Method m = OptionalBinderTest.class.getDeclaredMethod("testMatchingMarkerAnnotations"); + assertNotNull(m); + final Annotation marker = m.getAnnotation(Marker.class); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + public void configure() { + OptionalBinder mb1 = + OptionalBinder.newOptionalBinder( + binder(), Key.get(Integer.class, Marker.class)); + OptionalBinder mb2 = + OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, marker)); + mb1.setDefault().toInstance(1); + mb2.setBinding().toInstance(2); + + // This assures us that the two binders are equivalent, so we expect the instance added to + // each to have been added to one set. + assertEquals(mb1, mb2); + } + }); + Integer i1 = injector.getInstance(Key.get(Integer.class, Marker.class)); + Integer i2 = injector.getInstance(Key.get(Integer.class, marker)); + + // These must be identical, because the marker annotations collapsed to the same thing. + assertSame(i1, i2); + assertEquals(2, i2.intValue()); + } + + // Tests for com.google.inject.internal.WeakKeySet not leaking memory. + public void testWeakKeySet_integration() { + Injector parentInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("hi"); + } + }); + WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class)); + + Injector childInjector = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + OptionalBinder.newOptionalBinder(binder(), Integer.class) + .setDefault() + .toInstance(4); + } + }); + WeakReference weakRef = new WeakReference<>(childInjector); + WeakKeySetUtils.assertBlacklisted(parentInjector, Key.get(Integer.class)); + + // Clear the ref, GC, and ensure that we are no longer blacklisting. + childInjector = null; + + Asserts.awaitClear(weakRef); + WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class)); + } + + public void testCompareEqualsAgainstOtherAnnotation() { + RealOptionalBinder.Actual impl1 = new RealOptionalBinder.ActualImpl("foo"); + RealOptionalBinder.Actual other1 = Dummy.class.getAnnotation(RealOptionalBinder.Actual.class); + assertEquals(impl1, other1); + + RealOptionalBinder.Default impl2 = new RealOptionalBinder.DefaultImpl("foo"); + RealOptionalBinder.Default other2 = Dummy.class.getAnnotation(RealOptionalBinder.Default.class); + assertEquals(impl2, other2); + + assertFalse(impl1.equals(impl2)); + assertFalse(impl1.equals(other2)); + assertFalse(impl2.equals(other1)); + assertFalse(other1.equals(other2)); + } + + @RealOptionalBinder.Actual("foo") + @RealOptionalBinder.Default("foo") + static class Dummy {} + + @SuppressWarnings("unchecked") + private Set setOf(V... elements) { + return ImmutableSet.copyOf(elements); + } + + @SuppressWarnings("unchecked") + private Optional toOptional(Object object) throws Exception { + assertTrue( + "not a java.util.Optional: " + object.getClass(), JAVA_OPTIONAL_CLASS.isInstance(object)); + return Optional.fromNullable((T) JAVA_OPTIONAL_OR_ELSE.invoke(object, (Void) null)); + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/ProxyFactoryTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/ProxyFactoryTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/ProxyFactoryTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/ProxyFactoryTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,20 +24,15 @@ import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.spi.InjectionPoint; - -import junit.framework.TestCase; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationTargetException; import java.util.List; +import junit.framework.TestCase; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ProxyFactoryTest extends TestCase { List aspects = Lists.newArrayList(); @@ -48,7 +43,7 @@ InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Simple.class); aspects.add(new MethodAspect(any(), any(), interceptor)); - ProxyFactory factory = new ProxyFactory(injectionPoint, aspects); + ProxyFactory factory = new ProxyFactory<>(injectionPoint, aspects); ConstructionProxy constructionProxy = factory.create(); @@ -60,6 +55,7 @@ static class Simple { boolean invoked = false; + public void invoke() { invoked = true; } @@ -69,6 +65,7 @@ boolean invoked = false; + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { invoked = true; return methodInvocation.proceed(); @@ -81,10 +78,10 @@ aspects.add(new MethodAspect(only(Bar.class), annotatedWith(Intercept.class), interceptor)); - ConstructionProxy fooFactory - = new ProxyFactory(InjectionPoint.forConstructorOf(Foo.class), aspects).create(); - ConstructionProxy barFactory - = new ProxyFactory(InjectionPoint.forConstructorOf(Bar.class), aspects).create(); + ConstructionProxy fooFactory = + new ProxyFactory(InjectionPoint.forConstructorOf(Foo.class), aspects).create(); + ConstructionProxy barFactory = + new ProxyFactory(InjectionPoint.forConstructorOf(Bar.class), aspects).create(); Foo foo = fooFactory.newInstance(); Bar bar = barFactory.newInstance(); @@ -104,6 +101,7 @@ static class Foo { boolean fooCalled; + @Intercept void foo() { fooCalled = true; @@ -113,6 +111,7 @@ static class Bar { boolean barCalled; + void bar() { barCalled = true; } @@ -133,8 +132,8 @@ SimpleInterceptor interceptor = new SimpleInterceptor(); aspects.add(new MethodAspect(any(), any(), interceptor)); - ProxyFactory factory - = new ProxyFactory(InjectionPoint.forConstructorOf(A.class), aspects); + ProxyFactory factory = + new ProxyFactory(InjectionPoint.forConstructorOf(A.class), aspects); ConstructionProxy constructor = factory.create(); @@ -148,8 +147,8 @@ SimpleInterceptor interceptor = new SimpleInterceptor(); aspects.add(new MethodAspect(not(any()), not(any()), interceptor)); - ProxyFactory factory - = new ProxyFactory(InjectionPoint.forConstructorOf(A.class), aspects); + ProxyFactory factory = + new ProxyFactory(InjectionPoint.forConstructorOf(A.class), aspects); ConstructionProxy constructor = factory.create(); @@ -159,9 +158,12 @@ static class A { final int i; - @Inject public A(int i) { + + @Inject + public A(int i) { this.i = i; } + public void a() {} } @@ -171,8 +173,8 @@ CountingInterceptor countingInterceptor = new CountingInterceptor(); aspects.add(new MethodAspect(any(), any(), doubleInterceptor, countingInterceptor)); - ProxyFactory factory - = new ProxyFactory(InjectionPoint.forConstructorOf(Counter.class), aspects); + ProxyFactory factory = + new ProxyFactory(InjectionPoint.forConstructorOf(Counter.class), aspects); ConstructionProxy constructor = factory.create(); @@ -186,6 +188,7 @@ int count; + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { count++; return methodInvocation.proceed(); @@ -194,6 +197,7 @@ static class DoubleInterceptor implements MethodInterceptor { + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { methodInvocation.proceed(); return methodInvocation.proceed(); @@ -202,6 +206,7 @@ static class Counter { int count; + void inc() { count++; } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/RealElementTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/RealElementTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/RealElementTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/RealElementTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import com.google.inject.internal.Element.Type; +import junit.framework.TestCase; + +/** Tests for {@link com.google.inject.internal.RealElement}. */ +public class RealElementTest extends TestCase { + + private Element systemElement; + private RealElement realElement; + + @Override + protected void setUp() throws Exception { + this.systemElement = Holder.class.getAnnotation(Element.class); + this.realElement = new RealElement("b", Type.MULTIBINDER, "a", 1); + } + + public void testEquals() { + assertEquals(systemElement, realElement); + assertEquals(realElement, systemElement); + } + + public void testHashCode() { + assertEquals(systemElement.hashCode(), realElement.hashCode()); + } + + public void testProperties() { + assertEquals("a", realElement.keyType()); + assertEquals("b", realElement.setName()); + assertEquals(Type.MULTIBINDER, realElement.type()); + assertEquals(1, realElement.uniqueId()); + } + + @Element(keyType = "a", setName = "b", type = Type.MULTIBINDER, uniqueId = 1) + static class Holder {} +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/SpiUtils.java sisu-guice-4.2.0/core/test/com/google/inject/internal/SpiUtils.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/SpiUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/SpiUtils.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,1316 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal; + +import static com.google.inject.internal.RealMapBinder.entryOfJavaxProviderOf; +import static com.google.inject.internal.RealMapBinder.entryOfProviderOf; +import static com.google.inject.internal.RealMapBinder.mapOf; +import static com.google.inject.internal.RealMapBinder.mapOfCollectionOfJavaxProviderOf; +import static com.google.inject.internal.RealMapBinder.mapOfCollectionOfProviderOf; +import static com.google.inject.internal.RealMapBinder.mapOfJavaxProviderOf; +import static com.google.inject.internal.RealMapBinder.mapOfProviderOf; +import static com.google.inject.internal.RealMapBinder.mapOfSetOfJavaxProviderOf; +import static com.google.inject.internal.RealMapBinder.mapOfSetOfProviderOf; +import static com.google.inject.internal.RealMultibinder.collectionOfJavaxProvidersOf; +import static com.google.inject.internal.RealMultibinder.collectionOfProvidersOf; +import static com.google.inject.internal.RealMultibinder.setOf; +import static com.google.inject.internal.SpiUtils.BindType.INSTANCE; +import static com.google.inject.internal.SpiUtils.BindType.LINKED; +import static com.google.inject.internal.SpiUtils.BindType.PROVIDER_INSTANCE; +import static com.google.inject.internal.SpiUtils.BindType.PROVIDER_KEY; +import static com.google.inject.internal.SpiUtils.VisitType.BOTH; +import static com.google.inject.internal.SpiUtils.VisitType.INJECTOR; +import static com.google.inject.internal.SpiUtils.VisitType.MODULE; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; +import com.google.common.collect.Sets; +import com.google.inject.Binding; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.Indexer.IndexedBinding; +import com.google.inject.internal.RealMapBinder.ProviderMapEntry; +import com.google.inject.multibindings.MapBinderBinding; +import com.google.inject.multibindings.MultibinderBinding; +import com.google.inject.multibindings.MultibindingsTargetVisitor; +import com.google.inject.multibindings.OptionalBinderBinding; +import com.google.inject.spi.DefaultBindingTargetVisitor; +import com.google.inject.spi.Element; +import com.google.inject.spi.Elements; +import com.google.inject.spi.InstanceBinding; +import com.google.inject.spi.LinkedKeyBinding; +import com.google.inject.spi.ProviderInstanceBinding; +import com.google.inject.spi.ProviderKeyBinding; +import com.google.inject.spi.ProviderLookup; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Utilities for testing the Multibinder & MapBinder extension SPI. + * + * @author sameb@google.com (Sam Berlin) + */ +public class SpiUtils { + + private static final boolean HAS_JAVA_OPTIONAL; + + static { + Class optional = null; + try { + optional = Class.forName("java.util.Optional"); + } catch (ClassNotFoundException ignored) { + } + HAS_JAVA_OPTIONAL = optional != null; + } + + /** The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. */ + enum VisitType { + INJECTOR, + MODULE, + BOTH + } + + /** + * Asserts that MapBinderBinding visitors for work correctly. + * + * @param The type of the binding + * @param mapKey The key the map belongs to. + * @param keyType the TypeLiteral of the key of the map + * @param valueType the TypeLiteral of the value of the map + * @param modules The modules that define the mapbindings + * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) + * test, or both. + * @param allowDuplicates If duplicates are allowed. + * @param expectedMapBindings The number of other mapbinders we expect to see. + * @param results The kind of bindings contained in the mapbinder. + */ + static void assertMapVisitor( + Key mapKey, + TypeLiteral keyType, + TypeLiteral valueType, + Iterable modules, + VisitType visitType, + boolean allowDuplicates, + int expectedMapBindings, + MapResult... results) { + if (visitType == null) { + fail("must test something"); + } + + if (visitType == BOTH || visitType == INJECTOR) { + mapInjectorTest( + mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, results); + } + + if (visitType == BOTH || visitType == MODULE) { + mapModuleTest( + mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, results); + } + } + + @SuppressWarnings("unchecked") + private static void mapInjectorTest( + Key mapKey, + TypeLiteral keyType, + TypeLiteral valueType, + Iterable modules, + boolean allowDuplicates, + int expectedMapBindings, + MapResult... results) { + Injector injector = Guice.createInjector(modules); + Visitor visitor = new Visitor<>(); + Binding mapBinding = injector.getBinding(mapKey); + MapBinderBinding mapbinder = (MapBinderBinding) mapBinding.acceptTargetVisitor(visitor); + assertNotNull(mapbinder); + assertEquals(keyType, mapbinder.getKeyTypeLiteral()); + assertEquals(valueType, mapbinder.getValueTypeLiteral()); + assertEquals(allowDuplicates, mapbinder.permitsDuplicates()); + List>> entries = Lists.newArrayList(mapbinder.getEntries()); + List mapResults = Lists.newArrayList(results); + assertEquals( + "wrong entries, expected: " + mapResults + ", but was: " + entries, + mapResults.size(), + entries.size()); + + for (MapResult result : mapResults) { + Map.Entry> found = null; + for (Map.Entry> entry : entries) { + Object key = entry.getKey(); + Binding value = entry.getValue(); + if (key.equals(result.k) && matches(value, result.v)) { + found = entry; + break; + } + } + if (found == null) { + fail("Could not find entry: " + result + " in remaining entries: " + entries); + } else { + assertTrue( + "mapBinder doesn't contain: " + found.getValue(), + mapbinder.containsElement(found.getValue())); + entries.remove(found); + } + } + + if (!entries.isEmpty()) { + fail("Found all entries of: " + mapResults + ", but more were left over: " + entries); + } + + Key mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); + Key mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType)); + Key mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); + Key mapOfSetOfJavaxProvider = mapKey.ofType(mapOfSetOfJavaxProviderOf(keyType, valueType)); + Key mapOfCollectionOfProvider = + mapKey.ofType(mapOfCollectionOfProviderOf(keyType, valueType)); + Key mapOfCollectionOfJavaxProvider = + mapKey.ofType(mapOfCollectionOfJavaxProviderOf(keyType, valueType)); + Key mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType))); + Key setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType))); + Key setOfJavaxEntry = mapKey.ofType(setOf(entryOfJavaxProviderOf(keyType, valueType))); + Key collectionOfProvidersOfEntryOfProvider = + mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType))); + Key collectionOfJavaxProvidersOfEntryOfProvider = + mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType))); + boolean entrySetMatch = false; + boolean javaxEntrySetMatch = false; + boolean mapJavaxProviderMatch = false; + boolean mapProviderMatch = false; + boolean mapSetMatch = false; + boolean mapSetProviderMatch = false; + boolean mapSetJavaxProviderMatch = false; + boolean mapCollectionProviderMatch = false; + boolean mapCollectionJavaxProviderMatch = false; + boolean collectionOfProvidersOfEntryOfProviderMatch = false; + boolean collectionOfJavaxProvidersOfEntryOfProviderMatch = false; + List otherMapBindings = Lists.newArrayList(); + List otherMatches = Lists.newArrayList(); + Multimap indexedEntries = + MultimapBuilder.hashKeys().hashSetValues().build(); + Indexer indexer = new Indexer(injector); + int duplicates = 0; + for (Binding b : injector.getAllBindings().values()) { + boolean contains = mapbinder.containsElement(b); + Object visited = b.acceptTargetVisitor(visitor); + if (visited instanceof MapBinderBinding) { + if (visited.equals(mapbinder)) { + assertTrue(contains); + } else { + otherMapBindings.add(visited); + } + } else if (b.getKey().equals(mapOfProvider)) { + assertTrue(contains); + mapProviderMatch = true; + } else if (b.getKey().equals(mapOfJavaxProvider)) { + assertTrue(contains); + mapJavaxProviderMatch = true; + } else if (b.getKey().equals(mapOfSet)) { + assertTrue(contains); + mapSetMatch = true; + } else if (b.getKey().equals(mapOfSetOfProvider)) { + assertTrue(contains); + mapSetProviderMatch = true; + } else if (b.getKey().equals(mapOfSetOfJavaxProvider)) { + assertTrue(contains); + mapSetJavaxProviderMatch = true; + } else if (b.getKey().equals(mapOfCollectionOfProvider)) { + assertTrue(contains); + mapCollectionProviderMatch = true; + } else if (b.getKey().equals(mapOfCollectionOfJavaxProvider)) { + assertTrue(contains); + mapCollectionJavaxProviderMatch = true; + } else if (b.getKey().equals(setOfEntry)) { + assertTrue(contains); + entrySetMatch = true; + // Validate that this binding is also a MultibinderBinding. + assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); + } else if (b.getKey().equals(setOfJavaxEntry)) { + assertTrue(contains); + javaxEntrySetMatch = true; + } else if (b.getKey().equals(collectionOfProvidersOfEntryOfProvider)) { + assertTrue(contains); + collectionOfProvidersOfEntryOfProviderMatch = true; + } else if (b.getKey().equals(collectionOfJavaxProvidersOfEntryOfProvider)) { + assertTrue(contains); + collectionOfJavaxProvidersOfEntryOfProviderMatch = true; + } else if (contains) { + if (b instanceof ProviderInstanceBinding) { + ProviderInstanceBinding pib = (ProviderInstanceBinding) b; + if (pib.getUserSuppliedProvider() instanceof ProviderMapEntry) { + // weird casting required to workaround compilation issues with jdk6 + ProviderMapEntry pme = + (ProviderMapEntry) (Provider) pib.getUserSuppliedProvider(); + Binding valueBinding = injector.getBinding(pme.getValueKey()); + if (indexer.isIndexable(valueBinding) + && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) { + duplicates++; + } + } + } + otherMatches.add(b); + } + } + + int sizeOfOther = otherMatches.size(); + if (allowDuplicates) { + sizeOfOther--; // account for 1 duplicate binding + } + // Multiply by two because each has a value and Map.Entry. + int expectedSize = 2 * (mapResults.size() + duplicates); + assertEquals( + "Incorrect other matches:\n\t" + Joiner.on("\n\t").join(otherMatches), + expectedSize, + sizeOfOther); + assertTrue(entrySetMatch); + assertTrue(javaxEntrySetMatch); + assertTrue(mapProviderMatch); + assertTrue(mapJavaxProviderMatch); + assertTrue(collectionOfProvidersOfEntryOfProviderMatch); + assertTrue(collectionOfJavaxProvidersOfEntryOfProviderMatch); + assertEquals(allowDuplicates, mapSetMatch); + assertEquals(allowDuplicates, mapSetProviderMatch); + assertEquals(allowDuplicates, mapSetJavaxProviderMatch); + assertEquals(allowDuplicates, mapCollectionJavaxProviderMatch); + assertEquals(allowDuplicates, mapCollectionProviderMatch); + assertEquals( + "other MapBindings found: " + otherMapBindings, + expectedMapBindings, + otherMapBindings.size()); + } + + @SuppressWarnings("unchecked") + private static void mapModuleTest( + Key mapKey, + TypeLiteral keyType, + TypeLiteral valueType, + Iterable modules, + boolean allowDuplicates, + int expectedMapBindings, + MapResult... results) { + Set elements = ImmutableSet.copyOf(Elements.getElements(modules)); + Visitor visitor = new Visitor<>(); + MapBinderBinding mapbinder = null; + Map, Binding> keyMap = Maps.newHashMap(); + for (Element element : elements) { + if (element instanceof Binding) { + Binding binding = (Binding) element; + keyMap.put(binding.getKey(), binding); + if (binding.getKey().equals(mapKey)) { + mapbinder = (MapBinderBinding) ((Binding) binding).acceptTargetVisitor(visitor); + } + } + } + assertNotNull(mapbinder); + + List> mapResults = Lists.newArrayList(results); + + // Make sure the entries returned from getEntries(elements) are correct. + // Because getEntries() can return duplicates, make sure to continue searching, even + // after we find one match. + List>> entries = Lists.newArrayList(mapbinder.getEntries(elements)); + for (MapResult result : mapResults) { + List>> foundEntries = Lists.newArrayList(); + for (Map.Entry> entry : entries) { + Object key = entry.getKey(); + Binding value = entry.getValue(); + if (key.equals(result.k) && matches(value, result.v)) { + assertTrue( + "mapBinder doesn't contain: " + entry.getValue(), + mapbinder.containsElement(entry.getValue())); + foundEntries.add(entry); + } + } + assertTrue( + "Could not find entry: " + result + " in remaining entries: " + entries, + !foundEntries.isEmpty()); + + entries.removeAll(foundEntries); + } + + assertTrue( + "Found all entries of: " + mapResults + ", but more were left over: " + entries, + entries.isEmpty()); + + assertEquals(keyType, mapbinder.getKeyTypeLiteral()); + assertEquals(valueType, mapbinder.getValueTypeLiteral()); + + Key mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType)); + Key mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); + Key mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); + Key mapOfSetOfJavaxProvider = mapKey.ofType(mapOfSetOfJavaxProviderOf(keyType, valueType)); + Key mapOfCollectionOfProvider = + mapKey.ofType(mapOfCollectionOfProviderOf(keyType, valueType)); + Key mapOfCollectionOfJavaxProvider = + mapKey.ofType(mapOfCollectionOfJavaxProviderOf(keyType, valueType)); + Key mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType))); + Key setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType))); + Key setOfJavaxEntry = mapKey.ofType(setOf(entryOfJavaxProviderOf(keyType, valueType))); + Key collectionOfProvidersOfEntryOfProvider = + mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType))); + Key collectionOfJavaxProvidersOfEntryOfProvider = + mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType))); + boolean entrySetMatch = false; + boolean entrySetJavaxMatch = false; + boolean mapProviderMatch = false; + boolean mapJavaxProviderMatch = false; + boolean mapSetMatch = false; + boolean mapSetProviderMatch = false; + boolean mapSetJavaxProviderMatch = false; + boolean mapCollectionProviderMatch = false; + boolean mapCollectionJavaxProviderMatch = false; + boolean collectionOfProvidersOfEntryOfProviderMatch = false; + boolean collectionOfJavaxProvidersOfEntryOfProviderMatch = false; + List otherMapBindings = Lists.newArrayList(); + List otherMatches = Lists.newArrayList(); + List otherElements = Lists.newArrayList(); + Indexer indexer = new Indexer(null); + Multimap indexedEntries = + MultimapBuilder.hashKeys().hashSetValues().build(); + int duplicates = 0; + for (Element element : elements) { + boolean contains = mapbinder.containsElement(element); + if (!contains) { + otherElements.add(element); + } + boolean matched = false; + Key key = null; + Binding b = null; + if (element instanceof Binding) { + b = (Binding) element; + if (b instanceof ProviderInstanceBinding) { + ProviderInstanceBinding pb = (ProviderInstanceBinding) b; + if (pb.getUserSuppliedProvider() instanceof ProviderMapEntry) { + // weird casting required to workaround jdk6 compilation problems + ProviderMapEntry pme = + (ProviderMapEntry) (Provider) pb.getUserSuppliedProvider(); + Binding valueBinding = keyMap.get(pme.getValueKey()); + if (indexer.isIndexable(valueBinding) + && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) { + duplicates++; + } + } + } + + key = b.getKey(); + Object visited = b.acceptTargetVisitor(visitor); + if (visited instanceof MapBinderBinding) { + matched = true; + if (visited.equals(mapbinder)) { + assertTrue(contains); + } else { + otherMapBindings.add(visited); + } + } + } else if (element instanceof ProviderLookup) { + key = ((ProviderLookup) element).getKey(); + } + + if (!matched && key != null) { + if (key.equals(mapOfProvider)) { + matched = true; + assertTrue(contains); + mapProviderMatch = true; + } else if (key.equals(mapOfJavaxProvider)) { + matched = true; + assertTrue(contains); + mapJavaxProviderMatch = true; + } else if (key.equals(mapOfSet)) { + matched = true; + assertTrue(contains); + mapSetMatch = true; + } else if (key.equals(mapOfSetOfProvider)) { + matched = true; + assertTrue(contains); + mapSetProviderMatch = true; + } else if (key.equals(mapOfSetOfJavaxProvider)) { + matched = true; + assertTrue(contains); + mapSetJavaxProviderMatch = true; + } else if (key.equals(mapOfCollectionOfProvider)) { + matched = true; + assertTrue(contains); + mapCollectionProviderMatch = true; + } else if (key.equals(mapOfCollectionOfJavaxProvider)) { + matched = true; + assertTrue(contains); + mapCollectionJavaxProviderMatch = true; + } else if (key.equals(setOfEntry)) { + matched = true; + assertTrue(contains); + entrySetMatch = true; + // Validate that this binding is also a MultibinderBinding. + if (b != null) { + assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); + } + } else if (key.equals(setOfJavaxEntry)) { + matched = true; + assertTrue(contains); + entrySetJavaxMatch = true; + } else if (key.equals(collectionOfProvidersOfEntryOfProvider)) { + matched = true; + assertTrue(contains); + collectionOfProvidersOfEntryOfProviderMatch = true; + } else if (key.equals(collectionOfJavaxProvidersOfEntryOfProvider)) { + matched = true; + assertTrue(contains); + collectionOfJavaxProvidersOfEntryOfProviderMatch = true; + } + } + + if (!matched && contains) { + otherMatches.add(element); + } + } + + int otherMatchesSize = otherMatches.size(); + if (allowDuplicates) { + otherMatchesSize--; // allow for 1 duplicate binding + } + // Multiply by 2 because each has a value, and Map.Entry + int expectedSize = (mapResults.size() + duplicates) * 2; + assertEquals( + "incorrect number of contains, leftover matches:\n" + Joiner.on("\n\t").join(otherMatches), + expectedSize, + otherMatchesSize); + + assertTrue(entrySetMatch); + assertTrue(entrySetJavaxMatch); + assertTrue(mapProviderMatch); + assertTrue(mapJavaxProviderMatch); + assertTrue(collectionOfProvidersOfEntryOfProviderMatch); + assertTrue(collectionOfJavaxProvidersOfEntryOfProviderMatch); + assertEquals(allowDuplicates, mapSetMatch); + assertEquals(allowDuplicates, mapSetProviderMatch); + assertEquals(allowDuplicates, mapSetJavaxProviderMatch); + assertEquals(allowDuplicates, mapCollectionProviderMatch); + assertEquals(allowDuplicates, mapCollectionJavaxProviderMatch); + assertEquals( + "other MapBindings found: " + otherMapBindings, + expectedMapBindings, + otherMapBindings.size()); + + // Validate that we can construct an injector out of the remaining bindings. + Guice.createInjector(Elements.getModule(otherElements)); + } + + /** + * Asserts that MultibinderBinding visitors work correctly. + * + * @param The type of the binding + * @param setKey The key the set belongs to. + * @param elementType the TypeLiteral of the element + * @param modules The modules that define the multibindings + * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) + * test, or both. + * @param allowDuplicates If duplicates are allowed. + * @param expectedMultibindings The number of other multibinders we expect to see. + * @param results The kind of bindings contained in the multibinder. + */ + static void assertSetVisitor( + Key> setKey, + TypeLiteral elementType, + Iterable modules, + VisitType visitType, + boolean allowDuplicates, + int expectedMultibindings, + BindResult... results) { + if (visitType == null) { + fail("must test something"); + } + + if (visitType == BOTH || visitType == INJECTOR) { + setInjectorTest( + setKey, elementType, modules, allowDuplicates, expectedMultibindings, results); + } + + if (visitType == BOTH || visitType == MODULE) { + setModuleTest(setKey, elementType, modules, allowDuplicates, expectedMultibindings, results); + } + } + + @SuppressWarnings("unchecked") + private static void setInjectorTest( + Key> setKey, + TypeLiteral elementType, + Iterable modules, + boolean allowDuplicates, + int otherMultibindings, + BindResult... results) { + Key collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); + Key collectionOfJavaxProvidersKey = setKey.ofType(collectionOfJavaxProvidersOf(elementType)); + Injector injector = Guice.createInjector(modules); + Visitor> visitor = new Visitor<>(); + Binding> binding = injector.getBinding(setKey); + MultibinderBinding> multibinder = + (MultibinderBinding>) binding.acceptTargetVisitor(visitor); + assertNotNull(multibinder); + assertEquals(elementType, multibinder.getElementTypeLiteral()); + assertEquals(allowDuplicates, multibinder.permitsDuplicates()); + List> elements = Lists.newArrayList(multibinder.getElements()); + List bindResults = Lists.newArrayList(results); + assertEquals( + "wrong bind elements, expected: " + bindResults + ", but was: " + multibinder.getElements(), + bindResults.size(), + elements.size()); + + for (BindResult result : bindResults) { + Binding found = null; + for (Binding item : elements) { + if (matches(item, result)) { + found = item; + break; + } + } + if (found == null) { + fail("Could not find element: " + result + " in remaining elements: " + elements); + } else { + elements.remove(found); + } + } + + if (!elements.isEmpty()) { + fail("Found all elements of: " + bindResults + ", but more were left over: " + elements); + } + + Set setOfElements = new HashSet(multibinder.getElements()); + Set setOfIndexed = Sets.newHashSet(); + Indexer indexer = new Indexer(injector); + for (Binding oneBinding : setOfElements) { + setOfIndexed.add(oneBinding.acceptTargetVisitor(indexer)); + } + + List otherMultibinders = Lists.newArrayList(); + List otherContains = Lists.newArrayList(); + boolean collectionOfProvidersMatch = false; + boolean collectionOfJavaxProvidersMatch = false; + for (Binding b : injector.getAllBindings().values()) { + boolean contains = multibinder.containsElement(b); + Key key = b.getKey(); + Object visited = b.acceptTargetVisitor(visitor); + if (visited != null) { + if (visited.equals(multibinder)) { + assertTrue(contains); + } else { + otherMultibinders.add(visited); + } + } else if (setOfElements.contains(b)) { + assertTrue(contains); + } else if (key.equals(collectionOfProvidersKey)) { + assertTrue(contains); + collectionOfProvidersMatch = true; + } else if (key.equals(collectionOfJavaxProvidersKey)) { + assertTrue(contains); + collectionOfJavaxProvidersMatch = true; + } else if (contains) { + if (!indexer.isIndexable(b) || !setOfIndexed.contains(b.acceptTargetVisitor(indexer))) { + otherContains.add(b); + } + } + } + + assertTrue(collectionOfProvidersMatch); + assertTrue(collectionOfJavaxProvidersMatch); + + if (allowDuplicates) { + assertEquals("contained more than it should: " + otherContains, 1, otherContains.size()); + } else { + assertTrue("contained more than it should: " + otherContains, otherContains.isEmpty()); + } + assertEquals( + "other multibindings found: " + otherMultibinders, + otherMultibindings, + otherMultibinders.size()); + } + + @SuppressWarnings("unchecked") + private static void setModuleTest( + Key> setKey, + TypeLiteral elementType, + Iterable modules, + boolean allowDuplicates, + int otherMultibindings, + BindResult... results) { + Key collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); + Key collectionOfJavaxProvidersKey = setKey.ofType(collectionOfJavaxProvidersOf(elementType)); + List bindResults = Lists.newArrayList(results); + List elements = Elements.getElements(modules); + Visitor visitor = new Visitor<>(); + MultibinderBinding> multibinder = null; + for (Element element : elements) { + if (element instanceof Binding && ((Binding) element).getKey().equals(setKey)) { + multibinder = (MultibinderBinding>) ((Binding) element).acceptTargetVisitor(visitor); + break; + } + } + assertNotNull(multibinder); + + assertEquals(elementType, multibinder.getElementTypeLiteral()); + List otherMultibinders = Lists.newArrayList(); + Set otherContains = new HashSet<>(); + List otherElements = Lists.newArrayList(); + int duplicates = 0; + Set setOfIndexed = Sets.newHashSet(); + Indexer indexer = new Indexer(null); + boolean collectionOfProvidersMatch = false; + boolean collectionOfJavaxProvidersMatch = false; + for (Element element : elements) { + boolean contains = multibinder.containsElement(element); + if (!contains) { + otherElements.add(element); + } + boolean matched = false; + Key key = null; + if (element instanceof Binding) { + Binding binding = (Binding) element; + if (indexer.isIndexable(binding) + && !setOfIndexed.add((IndexedBinding) binding.acceptTargetVisitor(indexer))) { + duplicates++; + } + key = binding.getKey(); + Object visited = binding.acceptTargetVisitor(visitor); + if (visited != null) { + matched = true; + if (visited.equals(multibinder)) { + assertTrue(contains); + } else { + otherMultibinders.add(visited); + } + } + } + + if (collectionOfProvidersKey.equals(key)) { + assertTrue(contains); + assertFalse(matched); + collectionOfProvidersMatch = true; + } else if (collectionOfJavaxProvidersKey.equals(key)) { + assertTrue(contains); + assertFalse(matched); + collectionOfJavaxProvidersMatch = true; + } else if (!matched && contains) { + otherContains.add(element); + } + } + + if (allowDuplicates) { + assertEquals( + "wrong contained elements: " + otherContains, + bindResults.size() + 1 + duplicates, + otherContains.size()); + } else { + assertEquals( + "wrong contained elements: " + otherContains, + bindResults.size() + duplicates, + otherContains.size()); + } + + assertEquals( + "other multibindings found: " + otherMultibinders, + otherMultibindings, + otherMultibinders.size()); + assertTrue(collectionOfProvidersMatch); + assertTrue(collectionOfJavaxProvidersMatch); + + // Validate that we can construct an injector out of the remaining bindings. + Guice.createInjector(Elements.getModule(otherElements)); + } + + /** + * Asserts that OptionalBinderBinding visitors for work correctly. + * + * @param The type of the binding + * @param keyType The key OptionalBinder is binding + * @param modules The modules that define the bindings + * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) + * test, or both. + * @param expectedOtherOptionalBindings the # of other optional bindings we expect to see. + * @param expectedDefault the expected default binding, or null if none + * @param expectedActual the expected actual binding, or null if none + * @param expectedUserLinkedActual the user binding that is the actual binding, used if neither + * the default nor actual are set and a user binding existed for the type. + */ + static void assertOptionalVisitor( + Key keyType, + Iterable modules, + VisitType visitType, + int expectedOtherOptionalBindings, + BindResult expectedDefault, + BindResult expectedActual, + BindResult expectedUserLinkedActual) { + if (visitType == null) { + fail("must test something"); + } + + // if java.util.Optional is bound, there'll be twice as many as we expect. + if (HAS_JAVA_OPTIONAL) { + expectedOtherOptionalBindings *= 2; + } + + if (visitType == BOTH || visitType == INJECTOR) { + optionalInjectorTest( + keyType, + modules, + expectedOtherOptionalBindings, + expectedDefault, + expectedActual, + expectedUserLinkedActual); + } + + if (visitType == BOTH || visitType == MODULE) { + optionalModuleTest( + keyType, + modules, + expectedOtherOptionalBindings, + expectedDefault, + expectedActual, + expectedUserLinkedActual); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static void optionalInjectorTest( + Key keyType, + Iterable modules, + int expectedOtherOptionalBindings, + BindResult expectedDefault, + BindResult expectedActual, + BindResult expectedUserLinkedActual) { + if (expectedUserLinkedActual != null) { + assertNull("cannot have actual if expecting user binding", expectedActual); + assertNull("cannot have default if expecting user binding", expectedDefault); + } + + Key> optionalKey = + keyType.ofType(RealOptionalBinder.optionalOf(keyType.getTypeLiteral())); + Key javaOptionalKey = + HAS_JAVA_OPTIONAL + ? keyType.ofType(RealOptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) + : null; + Injector injector = Guice.createInjector(modules); + Binding> optionalBinding = injector.getBinding(optionalKey); + Visitor visitor = new Visitor(); + OptionalBinderBinding> optionalBinder = + (OptionalBinderBinding>) optionalBinding.acceptTargetVisitor(visitor); + assertNotNull(optionalBinder); + assertEquals(optionalKey, optionalBinder.getKey()); + + Binding javaOptionalBinding = null; + OptionalBinderBinding javaOptionalBinder = null; + if (HAS_JAVA_OPTIONAL) { + javaOptionalBinding = injector.getBinding(javaOptionalKey); + javaOptionalBinder = + (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor); + assertNotNull(javaOptionalBinder); + assertEquals(javaOptionalKey, javaOptionalBinder.getKey()); + } + + if (expectedDefault == null) { + assertNull("did not expect a default binding", optionalBinder.getDefaultBinding()); + if (HAS_JAVA_OPTIONAL) { + assertNull("did not expect a default binding", javaOptionalBinder.getDefaultBinding()); + } + } else { + assertTrue( + "expectedDefault: " + + expectedDefault + + ", actualDefault: " + + optionalBinder.getDefaultBinding(), + matches(optionalBinder.getDefaultBinding(), expectedDefault)); + if (HAS_JAVA_OPTIONAL) { + assertTrue( + "expectedDefault: " + + expectedDefault + + ", actualDefault: " + + javaOptionalBinder.getDefaultBinding(), + matches(javaOptionalBinder.getDefaultBinding(), expectedDefault)); + } + } + + if (expectedActual == null && expectedUserLinkedActual == null) { + assertNull(optionalBinder.getActualBinding()); + if (HAS_JAVA_OPTIONAL) { + assertNull(javaOptionalBinder.getActualBinding()); + } + } else if (expectedActual != null) { + assertTrue( + "expectedActual: " + + expectedActual + + ", actualActual: " + + optionalBinder.getActualBinding(), + matches(optionalBinder.getActualBinding(), expectedActual)); + if (HAS_JAVA_OPTIONAL) { + assertTrue( + "expectedActual: " + + expectedActual + + ", actualActual: " + + javaOptionalBinder.getActualBinding(), + matches(javaOptionalBinder.getActualBinding(), expectedActual)); + } + } else if (expectedUserLinkedActual != null) { + assertTrue( + "expectedUserLinkedActual: " + + expectedUserLinkedActual + + ", actualActual: " + + optionalBinder.getActualBinding(), + matches(optionalBinder.getActualBinding(), expectedUserLinkedActual)); + if (HAS_JAVA_OPTIONAL) { + assertTrue( + "expectedUserLinkedActual: " + + expectedUserLinkedActual + + ", actualActual: " + + javaOptionalBinder.getActualBinding(), + matches(javaOptionalBinder.getActualBinding(), expectedUserLinkedActual)); + } + } + + Key>> optionalJavaxProviderKey = + keyType.ofType(RealOptionalBinder.optionalOfJavaxProvider(keyType.getTypeLiteral())); + Key javaOptionalJavaxProviderKey = + HAS_JAVA_OPTIONAL + ? keyType.ofType( + RealOptionalBinder.javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) + : null; + Key>> optionalProviderKey = + keyType.ofType(RealOptionalBinder.optionalOfProvider(keyType.getTypeLiteral())); + Key javaOptionalProviderKey = + HAS_JAVA_OPTIONAL + ? keyType.ofType(RealOptionalBinder.javaOptionalOfProvider(keyType.getTypeLiteral())) + : null; + + boolean keyMatch = false; + boolean optionalKeyMatch = false; + boolean javaOptionalKeyMatch = false; + boolean optionalJavaxProviderKeyMatch = false; + boolean javaOptionalJavaxProviderKeyMatch = false; + boolean optionalProviderKeyMatch = false; + boolean javaOptionalProviderKeyMatch = false; + boolean defaultMatch = false; + boolean actualMatch = false; + List otherOptionalBindings = Lists.newArrayList(); + List otherMatches = Lists.newArrayList(); + for (Binding b : injector.getAllBindings().values()) { + boolean contains = optionalBinder.containsElement(b); + if (HAS_JAVA_OPTIONAL) { + assertEquals(contains, javaOptionalBinder.containsElement(b)); + } + Object visited = b.acceptTargetVisitor(visitor); + if (visited instanceof OptionalBinderBinding) { + if (visited.equals(optionalBinder)) { + assertTrue(contains); + } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) { + assertTrue(contains); + } else { + otherOptionalBindings.add(visited); + } + } + if (b.getKey().equals(keyType)) { + // keyType might match because a user bound it + // (which is possible in a purely absent OptionalBinder) + assertEquals(expectedDefault != null || expectedActual != null, contains); + if (contains) { + keyMatch = true; + } + } else if (b.getKey().equals(optionalKey)) { + assertTrue(contains); + optionalKeyMatch = true; + } else if (b.getKey().equals(javaOptionalKey)) { + assertTrue(contains); + javaOptionalKeyMatch = true; + } else if (b.getKey().equals(optionalJavaxProviderKey)) { + assertTrue(contains); + optionalJavaxProviderKeyMatch = true; + } else if (b.getKey().equals(javaOptionalJavaxProviderKey)) { + assertTrue(contains); + javaOptionalJavaxProviderKeyMatch = true; + } else if (b.getKey().equals(optionalProviderKey)) { + assertTrue(contains); + optionalProviderKeyMatch = true; + } else if (b.getKey().equals(javaOptionalProviderKey)) { + assertTrue(contains); + javaOptionalProviderKeyMatch = true; + } else if (expectedDefault != null && matches(b, expectedDefault)) { + assertTrue(contains); + defaultMatch = true; + } else if (expectedActual != null && matches(b, expectedActual)) { + assertTrue(contains); + actualMatch = true; + } else if (contains) { + otherMatches.add(b); + } + } + + assertEquals(otherMatches.toString(), 0, otherMatches.size()); + // only expect a keymatch if either default or actual are set + assertEquals(expectedDefault != null || expectedActual != null, keyMatch); + assertTrue(optionalKeyMatch); + assertTrue(optionalJavaxProviderKeyMatch); + assertTrue(optionalProviderKeyMatch); + assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch); + assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch); + assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch); + assertEquals(expectedDefault != null, defaultMatch); + assertEquals(expectedActual != null, actualMatch); + assertEquals( + "other OptionalBindings found: " + otherOptionalBindings, + expectedOtherOptionalBindings, + otherOptionalBindings.size()); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static void optionalModuleTest( + Key keyType, + Iterable modules, + int expectedOtherOptionalBindings, + BindResult expectedDefault, + BindResult expectedActual, + BindResult expectedUserLinkedActual) { + if (expectedUserLinkedActual != null) { + assertNull("cannot have actual if expecting user binding", expectedActual); + assertNull("cannot have default if expecting user binding", expectedDefault); + } + Set elements = ImmutableSet.copyOf(Elements.getElements(modules)); + Map, Binding> indexed = index(elements); + Key> optionalKey = + keyType.ofType(RealOptionalBinder.optionalOf(keyType.getTypeLiteral())); + Key javaOptionalKey = + HAS_JAVA_OPTIONAL + ? keyType.ofType(RealOptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) + : null; + Visitor visitor = new Visitor(); + OptionalBinderBinding> optionalBinder = null; + OptionalBinderBinding javaOptionalBinder = null; + Key defaultKey = null; + Key actualKey = null; + + Binding optionalBinding = indexed.get(optionalKey); + optionalBinder = + (OptionalBinderBinding>) optionalBinding.acceptTargetVisitor(visitor); + + if (HAS_JAVA_OPTIONAL) { + Binding javaOptionalBinding = indexed.get(javaOptionalKey); + javaOptionalBinder = (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor); + } + + // Locate the defaultKey & actualKey + for (Element element : elements) { + if (optionalBinder.containsElement(element) && element instanceof Binding) { + Binding binding = (Binding) element; + if (isSourceEntry(binding, RealOptionalBinder.Source.DEFAULT)) { + defaultKey = binding.getKey(); + } else if (isSourceEntry(binding, RealOptionalBinder.Source.ACTUAL)) { + actualKey = binding.getKey(); + } + } + } + assertNotNull(optionalBinder); + if (HAS_JAVA_OPTIONAL) { + assertNotNull(javaOptionalBinder); + } + assertEquals(expectedDefault == null, defaultKey == null); + assertEquals(expectedActual == null, actualKey == null); + + Key>> optionalJavaxProviderKey = + keyType.ofType(RealOptionalBinder.optionalOfJavaxProvider(keyType.getTypeLiteral())); + Key javaOptionalJavaxProviderKey = + HAS_JAVA_OPTIONAL + ? keyType.ofType( + RealOptionalBinder.javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) + : null; + Key>> optionalProviderKey = + keyType.ofType(RealOptionalBinder.optionalOfProvider(keyType.getTypeLiteral())); + Key javaOptionalProviderKey = + HAS_JAVA_OPTIONAL + ? keyType.ofType(RealOptionalBinder.javaOptionalOfProvider(keyType.getTypeLiteral())) + : null; + boolean keyMatch = false; + boolean optionalKeyMatch = false; + boolean javaOptionalKeyMatch = false; + boolean optionalJavaxProviderKeyMatch = false; + boolean javaOptionalJavaxProviderKeyMatch = false; + boolean optionalProviderKeyMatch = false; + boolean javaOptionalProviderKeyMatch = false; + boolean defaultMatch = false; + boolean actualMatch = false; + List otherOptionalElements = Lists.newArrayList(); + List otherContains = Lists.newArrayList(); + List nonContainedElements = Lists.newArrayList(); + for (Element element : elements) { + boolean contains = optionalBinder.containsElement(element); + if (HAS_JAVA_OPTIONAL) { + assertEquals(contains, javaOptionalBinder.containsElement(element)); + } + if (!contains) { + nonContainedElements.add(element); + } + Key key = null; + Binding b = null; + if (element instanceof Binding) { + b = (Binding) element; + key = b.getKey(); + Object visited = b.acceptTargetVisitor(visitor); + if (visited instanceof OptionalBinderBinding) { + if (visited.equals(optionalBinder)) { + assertTrue(contains); + } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) { + assertTrue(contains); + } else { + otherOptionalElements.add(visited); + } + } + } else if (element instanceof ProviderLookup) { + key = ((ProviderLookup) element).getKey(); + } + + if (key != null && key.equals(keyType)) { + // keyType might match because a user bound it + // (which is possible in a purely absent OptionalBinder) + assertEquals(expectedDefault != null || expectedActual != null, contains); + if (contains) { + keyMatch = true; + } + } else if (key != null && key.equals(optionalKey)) { + assertTrue(contains); + optionalKeyMatch = true; + } else if (key != null && key.equals(javaOptionalKey)) { + assertTrue(contains); + javaOptionalKeyMatch = true; + } else if (key != null && key.equals(optionalJavaxProviderKey)) { + assertTrue(contains); + optionalJavaxProviderKeyMatch = true; + } else if (key != null && key.equals(javaOptionalJavaxProviderKey)) { + assertTrue(contains); + javaOptionalJavaxProviderKeyMatch = true; + } else if (key != null && key.equals(optionalProviderKey)) { + assertTrue(contains); + optionalProviderKeyMatch = true; + } else if (key != null && key.equals(javaOptionalProviderKey)) { + assertTrue(contains); + javaOptionalProviderKeyMatch = true; + } else if (key != null && key.equals(defaultKey)) { + assertTrue(contains); + if (b != null) { // otherwise it might just be a ProviderLookup into it + assertTrue( + "expected: " + expectedDefault + ", but was: " + b, matches(b, expectedDefault)); + defaultMatch = true; + } + } else if (key != null && key.equals(actualKey)) { + assertTrue(contains); + if (b != null) { // otherwise it might just be a ProviderLookup into it + assertTrue("expected: " + expectedActual + ", but was: " + b, matches(b, expectedActual)); + actualMatch = true; + } + } else if (contains) { + otherContains.add(element); + } + } + + // only expect a keymatch if either default or actual are set + assertEquals(expectedDefault != null || expectedActual != null, keyMatch); + assertTrue(optionalKeyMatch); + assertTrue(optionalJavaxProviderKeyMatch); + assertTrue(optionalProviderKeyMatch); + assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch); + assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch); + assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch); + assertEquals(expectedDefault != null, defaultMatch); + assertEquals(expectedActual != null, actualMatch); + assertEquals(otherContains.toString(), 0, otherContains.size()); + assertEquals( + "other OptionalBindings found: " + otherOptionalElements, + expectedOtherOptionalBindings, + otherOptionalElements.size()); + + // Validate that we can construct an injector out of the remaining bindings. + Guice.createInjector(Elements.getModule(nonContainedElements)); + } + + private static boolean isSourceEntry(Binding b, RealOptionalBinder.Source type) { + switch (type) { + case ACTUAL: + return b.getKey().getAnnotation() instanceof RealOptionalBinder.Actual; + case DEFAULT: + return b.getKey().getAnnotation() instanceof RealOptionalBinder.Default; + default: + throw new IllegalStateException("invalid type: " + type); + } + } + + /** Returns the subset of elements that have keys, indexed by them. */ + private static Map, Binding> index(Iterable elements) { + ImmutableMap.Builder, Binding> builder = ImmutableMap.builder(); + for (Element element : elements) { + if (element instanceof Binding) { + builder.put(((Binding) element).getKey(), (Binding) element); + } + } + return builder.build(); + } + + static MapResult instance(K k, V v) { + return new MapResult(k, new BindResult(INSTANCE, v, null)); + } + + static MapResult linked(K k, Class clazz) { + return new MapResult(k, new BindResult(LINKED, null, Key.get(clazz))); + } + + static MapResult linked(K k, Key key) { + return new MapResult(k, new BindResult(LINKED, null, key)); + } + + static MapResult providerInstance(K k, V v) { + return new MapResult(k, new BindResult(PROVIDER_INSTANCE, v, null)); + } + + static class MapResult { + private final K k; + private final BindResult v; + + MapResult(K k, BindResult v) { + this.k = k; + this.v = v; + } + + @Override + public String toString() { + return "entry[key[" + k + "],value[" + v + "]]"; + } + } + + private static boolean matches(Binding item, BindResult result) { + switch (result.type) { + case INSTANCE: + if (item instanceof InstanceBinding + && ((InstanceBinding) item).getInstance().equals(result.instance)) { + return true; + } + break; + case LINKED: + if (item instanceof LinkedKeyBinding + && ((LinkedKeyBinding) item).getLinkedKey().equals(result.key)) { + return true; + } + break; + case PROVIDER_INSTANCE: + if (item instanceof ProviderInstanceBinding + && Objects.equal( + ((ProviderInstanceBinding) item).getUserSuppliedProvider().get(), + result.instance)) { + return true; + } + break; + case PROVIDER_KEY: + if (item instanceof ProviderKeyBinding + && ((ProviderKeyBinding) item).getProviderKey().equals(result.key)) { + return true; + } + break; + } + return false; + } + + static BindResult instance(T t) { + return new BindResult(INSTANCE, t, null); + } + + static BindResult linked(Class clazz) { + return new BindResult(LINKED, null, Key.get(clazz)); + } + + static BindResult linked(Key key) { + return new BindResult(LINKED, null, key); + } + + static BindResult providerInstance(T t) { + return new BindResult(PROVIDER_INSTANCE, t, null); + } + + static BindResult providerKey(Key key) { + return new BindResult(PROVIDER_KEY, null, key); + } + + /** The kind of binding. */ + static enum BindType { + INSTANCE, + LINKED, + PROVIDER_INSTANCE, + PROVIDER_KEY + } + /** The result of the binding. */ + static class BindResult { + private final BindType type; + private final Key key; + private final T instance; + + private BindResult(BindType type, T instance, Key key) { + this.type = type; + this.instance = instance; + this.key = key; + } + + @Override + public String toString() { + switch (type) { + case INSTANCE: + return "instance[" + instance + "]"; + case LINKED: + return "linkedKey[" + key + "]"; + case PROVIDER_INSTANCE: + return "providerInstance[" + instance + "]"; + case PROVIDER_KEY: + return "providerKey[" + key + "]"; + } + return null; + } + } + + private static class Visitor extends DefaultBindingTargetVisitor + implements MultibindingsTargetVisitor { + + @Override + public Object visit(MultibinderBinding multibinding) { + return multibinding; + } + + @Override + public Object visit(MapBinderBinding mapbinding) { + return mapbinding; + } + + @Override + public Object visit(OptionalBinderBinding optionalbinding) { + return optionalbinding; + } + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/UniqueAnnotationsTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/UniqueAnnotationsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/UniqueAnnotationsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/UniqueAnnotationsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,20 +14,17 @@ * limitations under the License. */ - package com.google.inject.internal; -import junit.framework.TestCase; - import java.lang.annotation.Annotation; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class UniqueAnnotationsTest extends TestCase { - @UniqueAnnotations.Internal(31) public Void unused; - + @UniqueAnnotations.Internal(31) + public Void unused; + public void testEqualsHashCodeToString() { Annotation actual = UniqueAnnotations.create(31); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/util/LineNumbersTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/util/LineNumbersTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/util/LineNumbersTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/util/LineNumbersTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,60 +24,69 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.matcher.Matchers; - -import junit.framework.TestCase; - import java.lang.reflect.Modifier; - import javax.inject.Inject; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class LineNumbersTest extends TestCase { public void testLineNumbers() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(A.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for " + B.class.getName() + " was bound.", - "for parameter 0 at " + A.class.getName() + ".(LineNumbersTest.java:", - "at " + LineNumbersTest.class.getName(), getDeclaringSourcePart(getClass())); + "for the 1st parameter of " + A.class.getName() + ".(LineNumbersTest.java:", + "at " + LineNumbersTest.class.getName(), + getDeclaringSourcePart(getClass())); } } static class A { - @Inject A(B b) {} + @Inject + A(B b) {} } + public interface B {} /*if[AOP]*/ public void testCanHandleLineNumbersForGuiceGeneratedClasses() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.only(A.class), Matchers.any(), - new org.aopalliance.intercept.MethodInterceptor() { - public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { - return null; - } - }); - - bind(A.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.only(A.class), + Matchers.any(), + new org.aopalliance.intercept.MethodInterceptor() { + @Override + public Object invoke( + org.aopalliance.intercept.MethodInvocation methodInvocation) { + return null; + } + }); + + bind(A.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for " + B.class.getName() + " was bound.", - "for parameter 0 at " + A.class.getName() + ".(LineNumbersTest.java:", - "at " + LineNumbersTest.class.getName(), getDeclaringSourcePart(getClass())); + "for the 1st parameter of " + A.class.getName() + ".(LineNumbersTest.java:", + "at " + LineNumbersTest.class.getName(), + getDeclaringSourcePart(getClass())); } } @@ -91,19 +100,27 @@ Class generate() { org.objectweb.asm.ClassWriter cw = new org.objectweb.asm.ClassWriter(org.objectweb.asm.ClassWriter.COMPUTE_MAXS); - cw.visit(org.objectweb.asm.Opcodes.V1_5, - Modifier.PUBLIC, name, null, - org.objectweb.asm.Type.getInternalName(Object.class), null); + cw.visit( + org.objectweb.asm.Opcodes.V1_5, + Modifier.PUBLIC, + name, + null, + org.objectweb.asm.Type.getInternalName(Object.class), + null); - String sig = "("+org.objectweb.asm.Type.getDescriptor(B.class)+")V"; + String sig = "(" + org.objectweb.asm.Type.getDescriptor(B.class) + ")V"; - org.objectweb.asm.MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "", sig, null, null); + org.objectweb.asm.MethodVisitor mv = + cw.visitMethod(Modifier.PUBLIC, "", sig, null, null); mv.visitAnnotation(org.objectweb.asm.Type.getDescriptor(Inject.class), true); mv.visitCode(); mv.visitVarInsn(org.objectweb.asm.Opcodes.ALOAD, 0); - mv.visitMethodInsn(org.objectweb.asm.Opcodes.INVOKESPECIAL, - org.objectweb.asm.Type.getInternalName(Object.class), "", "()V" ); + mv.visitMethodInsn( + org.objectweb.asm.Opcodes.INVOKESPECIAL, + org.objectweb.asm.Type.getInternalName(Object.class), + "", + "()V"); mv.visitInsn(org.objectweb.asm.Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -117,28 +134,35 @@ public void testUnavailableByteCodeShowsUnknownSource() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(new GeneratingClassLoader().generate()); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(new GeneratingClassLoader().generate()); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for " + B.class.getName() + " was bound.", - "for parameter 0 at " + GeneratingClassLoader.name + ".(Unknown Source)", - "at " + LineNumbersTest.class.getName(), getDeclaringSourcePart(getClass())); + "for the 1st parameter of " + GeneratingClassLoader.name + ".(Unknown Source)", + "at " + LineNumbersTest.class.getName(), + getDeclaringSourcePart(getClass())); } } - + public void testGeneratedClassesCanSucceed() { final Class generated = new GeneratingClassLoader().generate(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(generated); - bind(B.class).toInstance(new B() {}); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(generated); + bind(B.class).toInstance(new B() {}); + } + }); Object instance = injector.getInstance(generated); assertEquals(instance.getClass(), generated); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/WeakKeySetTest.java sisu-guice-4.2.0/core/test/com/google/inject/internal/WeakKeySetTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/WeakKeySetTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/WeakKeySetTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,20 +39,18 @@ import com.google.inject.spi.ScopeBinding; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.ref.WeakReference; import java.util.List; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; /** * Tests for {@link WeakKeySet}. - *

    - * Multibinding specific tests can be found in MultibinderTest and MapBinderTest. - * + * + *

    Multibinding specific tests can be found in MultibinderTest and MapBinderTest. + * * @author dweis@google.com (Daniel Weis) */ public class WeakKeySetTest extends TestCase { @@ -68,8 +66,8 @@ TestState state = new TestState(); Key key = Key.get(Integer.class); Object source = new Object(); - - WeakReference> weakKeyRef = new WeakReference>(key); + + WeakReference> weakKeyRef = new WeakReference<>(key); set.add(key, state, source); assertInSet(set, key, 1, source); @@ -84,13 +82,13 @@ key = null; awaitClear(weakKeyRef); } - + public void testEviction_nullSource() { TestState state = new TestState(); Key key = Key.get(Integer.class); Object source = null; - - WeakReference> weakKeyRef = new WeakReference>(key); + + WeakReference> weakKeyRef = new WeakReference<>(key); set.add(key, state, source); assertInSet(set, key, 1, source); @@ -120,10 +118,10 @@ set.add(key2, state2, source2); assertInSet(set, key2, 2, source1, source2); - WeakReference> weakKey1Ref = new WeakReference>(key1); - WeakReference> weakKey2Ref = new WeakReference>(key2); - WeakReference weakSource1Ref = new WeakReference(source1); - WeakReference weakSource2Ref = new WeakReference(source2); + WeakReference> weakKey1Ref = new WeakReference<>(key1); + WeakReference> weakKey2Ref = new WeakReference<>(key2); + WeakReference weakSource1Ref = new WeakReference<>(source1); + WeakReference weakSource2Ref = new WeakReference<>(source2); Key key = key1 = key2 = Key.get(Integer.class); state1 = null; @@ -134,11 +132,11 @@ assertInSet(set, key, 1, source2); source1 = source2 = null; - + awaitClear(weakSource1Ref); // Key1 will be referenced as the key in the sources backingSet and won't be // GC'd. - + // Should not be GC'd until state2 goes away. assertNotNull(weakSource2Ref.get()); @@ -153,7 +151,7 @@ // Now that the backing set is emptied, key1 is released. awaitClear(weakKey1Ref); } - + public void testNoEviction_keyOverlap_2x() { TestState state1 = new TestState(); TestState state2 = new TestState(); @@ -168,8 +166,8 @@ set.add(key2, state2, source2); assertInSet(set, key2, 2, source1, source2); - WeakReference> weakKey1Ref = new WeakReference>(key1); - WeakReference> weakKey2Ref = new WeakReference>(key2); + WeakReference> weakKey1Ref = new WeakReference<>(key1); + WeakReference> weakKey2Ref = new WeakReference<>(key2); Key key = key1 = key2 = Key.get(Integer.class); @@ -197,9 +195,9 @@ assertInSet(set, key2, 1, source); assertInSet(set, key1, 1, source); - WeakReference> weakKey1Ref = new WeakReference>(key1); - WeakReference> weakKey2Ref = new WeakReference>(key2); - WeakReference weakSourceRef = new WeakReference(source); + WeakReference> weakKey1Ref = new WeakReference<>(key1); + WeakReference> weakKey2Ref = new WeakReference<>(key2); + WeakReference weakSourceRef = new WeakReference<>(source); Key key = key1 = key2 = Key.get(Integer.class); state1 = null; @@ -224,7 +222,7 @@ // Now that the backing set is emptied, key1 is released. awaitClear(weakKey1Ref); } - + public void testEviction_keyAndSourceOverlap_nonNull() { TestState state1 = new TestState(); TestState state2 = new TestState(); @@ -239,19 +237,19 @@ // Same source so still only one value. assertInSet(set, key2, 1, source); - WeakReference> weakKey1Ref = new WeakReference>(key1); - WeakReference> weakKey2Ref = new WeakReference>(key2); - WeakReference weakSourceRef = new WeakReference(source); + WeakReference> weakKey1Ref = new WeakReference<>(key1); + WeakReference> weakKey2Ref = new WeakReference<>(key2); + WeakReference weakSourceRef = new WeakReference<>(source); Key key = key1 = key2 = Key.get(Integer.class); state1 = null; awaitFullGc(); - // Same source so still only one value. + // Same source so still only one value. assertInSet(set, key, 1, source); assertInSet(set, key1, 1, source); - + source = null; awaitFullGc(); @@ -291,12 +289,12 @@ set.add(key3, state3, source3); assertInSet(set, key1, 3, source1, source2, source3); - WeakReference> weakKey1Ref = new WeakReference>(key1); - WeakReference> weakKey2Ref = new WeakReference>(key2); - WeakReference> weakKey3Ref = new WeakReference>(key3); - WeakReference weakSource1Ref = new WeakReference(source1); - WeakReference weakSource2Ref = new WeakReference(source2); - WeakReference weakSource3Ref = new WeakReference(source3); + WeakReference> weakKey1Ref = new WeakReference<>(key1); + WeakReference> weakKey2Ref = new WeakReference<>(key2); + WeakReference> weakKey3Ref = new WeakReference<>(key3); + WeakReference weakSource1Ref = new WeakReference<>(source1); + WeakReference weakSource2Ref = new WeakReference<>(source2); + WeakReference weakSource3Ref = new WeakReference<>(source3); Key key = key1 = key2 = key3 = Key.get(Integer.class); state1 = null; @@ -316,7 +314,7 @@ assertInSet(set, key, 1, source3); awaitClear(weakKey2Ref); - + source2 = null; awaitClear(weakSource2Ref); // Key1 will be referenced as the key in the sources backingSet and won't be @@ -334,54 +332,69 @@ } public void testWeakKeySet_integration() { - Injector parentInjector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(4); - } - }); + Injector parentInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(4); + } + }); assertNotBlacklisted(parentInjector, Key.get(String.class)); - Injector childInjector = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("bar"); - } - }); - WeakReference weakRef = new WeakReference(childInjector); + Injector childInjector = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("bar"); + } + }); + WeakReference weakRef = new WeakReference<>(childInjector); assertBlacklisted(parentInjector, Key.get(String.class)); - + // Clear the ref, GC, and ensure that we are no longer blacklisting. childInjector = null; awaitClear(weakRef); assertNotBlacklisted(parentInjector, Key.get(String.class)); } - + public void testWeakKeySet_integration_multipleChildren() { - Injector parentInjector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(4); - } - }); + Injector parentInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(4); + } + }); assertNotBlacklisted(parentInjector, Key.get(String.class)); assertNotBlacklisted(parentInjector, Key.get(Long.class)); - Injector childInjector1 = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("foo"); - } - }); - WeakReference weakRef1 = new WeakReference(childInjector1); + Injector childInjector1 = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("foo"); + } + }); + WeakReference weakRef1 = new WeakReference<>(childInjector1); assertBlacklisted(parentInjector, Key.get(String.class)); assertNotBlacklisted(parentInjector, Key.get(Long.class)); - - Injector childInjector2 = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(Long.class).toInstance(6L); - } - }); - WeakReference weakRef2 = new WeakReference(childInjector2); + + Injector childInjector2 = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Long.class).toInstance(6L); + } + }); + WeakReference weakRef2 = new WeakReference<>(childInjector2); assertBlacklisted(parentInjector, Key.get(String.class)); assertBlacklisted(parentInjector, Key.get(Long.class)); - + // Clear ref1, GC, and ensure that we still blacklist. childInjector1 = null; awaitClear(weakRef1); @@ -394,31 +407,40 @@ assertNotBlacklisted(parentInjector, Key.get(String.class)); assertNotBlacklisted(parentInjector, Key.get(Long.class)); } - + public void testWeakKeySet_integration_multipleChildren_overlappingKeys() { - Injector parentInjector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(4); - } - }); + Injector parentInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(4); + } + }); assertNotBlacklisted(parentInjector, Key.get(String.class)); - Injector childInjector1 = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("foo"); - } - }); - WeakReference weakRef1 = new WeakReference(childInjector1); + Injector childInjector1 = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("foo"); + } + }); + WeakReference weakRef1 = new WeakReference<>(childInjector1); assertBlacklisted(parentInjector, Key.get(String.class)); - - Injector childInjector2 = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("bar"); - } - }); - WeakReference weakRef2 = new WeakReference(childInjector2); + + Injector childInjector2 = + parentInjector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("bar"); + } + }); + WeakReference weakRef2 = new WeakReference<>(childInjector2); assertBlacklisted(parentInjector, Key.get(String.class)); - + // Clear ref1, GC, and ensure that we still blacklist. childInjector1 = null; awaitClear(weakRef1); @@ -431,88 +453,108 @@ } private static class TestState implements State { + @Override public State parent() { return new TestState(); } + @Override public BindingImpl getExplicitBinding(Key key) { return null; } + @Override public Map, Binding> getExplicitBindingsThisLevel() { throw new UnsupportedOperationException(); } + @Override public void putBinding(Key key, BindingImpl binding) { throw new UnsupportedOperationException(); } + @Override public ScopeBinding getScopeBinding(Class scopingAnnotation) { return null; } + @Override public void putScopeBinding(Class annotationType, ScopeBinding scope) { throw new UnsupportedOperationException(); } + @Override public void addConverter(TypeConverterBinding typeConverterBinding) { throw new UnsupportedOperationException(); } - public TypeConverterBinding getConverter(String stringValue, TypeLiteral type, Errors errors, - Object source) { + @Override + public TypeConverterBinding getConverter( + String stringValue, TypeLiteral type, Errors errors, Object source) { throw new UnsupportedOperationException(); } + @Override public Iterable getConvertersThisLevel() { return ImmutableSet.of(); } /*if[AOP]*/ + @Override public void addMethodAspect(MethodAspect methodAspect) { throw new UnsupportedOperationException(); } + @Override public ImmutableList getMethodAspects() { return ImmutableList.of(); } /*end[AOP]*/ + @Override public void addTypeListener(TypeListenerBinding typeListenerBinding) { throw new UnsupportedOperationException(); } + @Override public List getTypeListenerBindings() { return ImmutableList.of(); } + @Override public void addProvisionListener(ProvisionListenerBinding provisionListenerBinding) { throw new UnsupportedOperationException(); } + @Override public List getProvisionListenerBindings() { return ImmutableList.of(); } + @Override public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) { throw new UnsupportedOperationException(); } + @Override public List getScannerBindings() { return ImmutableList.of(); } - public void blacklist(Key key, State state, Object source) { - } + @Override + public void blacklist(Key key, State state, Object source) {} + @Override public boolean isBlacklisted(Key key) { return true; } + @Override public Set getSourcesForBlacklistedKey(Key key) { throw new UnsupportedOperationException(); } + @Override public Object lock() { throw new UnsupportedOperationException(); } @@ -521,6 +563,7 @@ throw new UnsupportedOperationException(); } + @Override public Map, Scope> getScopes() { return ImmutableMap.of(); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/internal/WeakKeySetUtils.java sisu-guice-4.2.0/core/test/com/google/inject/internal/WeakKeySetUtils.java --- sisu-guice-3.2.6/core/test/com/google/inject/internal/WeakKeySetUtils.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/internal/WeakKeySetUtils.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except @@ -22,7 +22,6 @@ import com.google.inject.Injector; import com.google.inject.Key; - import java.util.Set; /** @@ -54,8 +53,8 @@ assertNull(set.getSources(Key.get(Integer.class))); } - public static void assertInSet(WeakKeySet set, Key key, int expectedSources, - Object... sources) { + public static void assertInSet( + WeakKeySet set, Key key, int expectedSources, Object... sources) { assertTrue(set.contains(key)); assertEquals(expectedSources, set.getSources(key).size()); for (Object source : sources) { diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/JitBindingsTest.java sisu-guice-4.2.0/core/test/com/google/inject/JitBindingsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/JitBindingsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/JitBindingsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -21,21 +21,20 @@ import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING; import static com.google.inject.JitBindingsTest.GetBindingCheck.FAIL_ALL; -import junit.framework.TestCase; - import java.util.Set; +import junit.framework.TestCase; /** * Some tests for {@link Binder#requireExplicitBindings()} - * + * * @author sberlin@gmail.com (Sam Berlin) */ public class JitBindingsTest extends TestCase { - + private String jitFailed(Class clazz) { return jitFailed(TypeLiteral.get(clazz)); } - + private String jitFailed(TypeLiteral clazz) { return "Explicit bindings are required and " + clazz + " is not explicitly bound."; } @@ -47,21 +46,23 @@ private String jitInParentFailed(TypeLiteral clazz) { return "Explicit bindings are required and " + clazz + " would be bound in a parent injector."; } - + private String inChildMessage(Class clazz) { return "Unable to create binding for " + clazz.getName() + ". It was already configured on one or more child injectors or private modules"; } - + public void testLinkedBindingWorks() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + } + }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, @@ -69,33 +70,37 @@ // of the binding ensureFails(injector, ALLOW_BINDING, FooImpl.class); } - + public void testMoreBasicsWork() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); - bind(Bar.class); - bind(FooBar.class); - } - }); - // Foo, Bar & FooBar was explicitly bound + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + bind(Bar.class); + bind(FooBar.class); + } + }); + // Foo, Bar & FooBar was explicitly bound ensureWorks(injector, FooBar.class, Bar.class, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider - // of the binding - ensureFails(injector, ALLOW_BINDING, FooImpl.class); + // of the binding + ensureFails(injector, ALLOW_BINDING, FooImpl.class); } - + public void testLinkedEagerSingleton() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class).asEagerSingleton(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class).asEagerSingleton(); + } + }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, @@ -103,116 +108,128 @@ // of the binding ensureFails(injector, ALLOW_BINDING, FooImpl.class); } - + public void testBasicsWithEagerSingleton() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class).asEagerSingleton(); - bind(Bar.class); - bind(FooBar.class); - } - }); - // Foo, Bar & FooBar was explicitly bound + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class).asEagerSingleton(); + bind(Bar.class); + bind(FooBar.class); + } + }); + // Foo, Bar & FooBar was explicitly bound ensureWorks(injector, FooBar.class, Bar.class, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider - // of the binding - ensureFails(injector, ALLOW_BINDING, FooImpl.class); - } - + // of the binding + ensureFails(injector, ALLOW_BINDING, FooImpl.class); + } + public void testLinkedToScoped() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder.requireExplicitBindings(); - bind(Foo.class).to(ScopedFooImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder.requireExplicitBindings(); + bind(Foo.class).to(ScopedFooImpl.class); + } + }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding - ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class); + ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class); } - + public void testBasicsWithScoped() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(ScopedFooImpl.class); - bind(Bar.class); - bind(FooBar.class); - } - }); - // Foo, Bar & FooBar was explicitly bound + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(ScopedFooImpl.class); + bind(Bar.class); + bind(FooBar.class); + } + }); + // Foo, Bar & FooBar was explicitly bound ensureWorks(injector, FooBar.class, Bar.class, Foo.class); // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider - // of the binding - ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class); + // of the binding + ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class); } - + public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(ScopedFooImpl.class); - bind(WantsScopedFooImpl.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(ScopedFooImpl.class); + bind(WantsScopedFooImpl.class); + } + }); fail(); - } catch(CreationException expected) { + } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(ScopedFooImpl.class)); assertEquals(1, expected.getErrorMessages().size()); } } - + public void testLinkedProviderBindingWorks() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).toProvider(FooProvider.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).toProvider(FooProvider.class); + } + }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooImpl was not bound at all (even implicitly), it is an error // to call getInstance, getProvider, or getBinding. ensureFails(injector, FAIL_ALL, FooImpl.class); } - + public void testJitGetFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - } - }).getInstance(Bar.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + } + }) + .getInstance(Bar.class); fail("should have failed"); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), jitFailed(Bar.class)); assertEquals(1, expected.getErrorMessages().size()); } } - + public void testJitInjectionFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); - bind(FooBar.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + bind(FooBar.class); + } + }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(Bar.class)); @@ -222,12 +239,14 @@ public void testJitProviderGetFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - } - }).getProvider(Bar.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + } + }) + .getProvider(Bar.class); fail("should have failed"); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), jitFailed(Bar.class)); @@ -237,97 +256,117 @@ public void testJitProviderInjectionFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); - bind(ProviderFooBar.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + bind(ProviderFooBar.class); + } + }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(Bar.class)); assertEquals(1, expected.getErrorMessages().size()); } } - + public void testImplementedBy() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(ImplBy.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(ImplBy.class); + } + }); ensureWorks(injector, ImplBy.class); ensureFails(injector, ALLOW_BINDING, ImplByImpl.class); } - + public void testImplementedBySomethingThatIsAnnotated() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(ImplByScoped.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(ImplByScoped.class); + } + }); ensureWorks(injector, ImplByScoped.class); - ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class); + ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class); } - + public void testProvidedBy() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(ProvBy.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(ProvBy.class); + } + }); ensureWorks(injector, ProvBy.class); ensureFails(injector, ALLOW_BINDING, ProvByProvider.class); } - + public void testProviderMethods() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - binder().requireExplicitBindings(); - } - @SuppressWarnings("unused") @Provides Foo foo() { return new FooImpl(); } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + } + + @SuppressWarnings("unused") + @Provides + Foo foo() { + return new FooImpl(); + } + }); ensureWorks(injector, Foo.class); } - + public void testChildInjectorInheritsOption() { - Injector parent = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Bar.class); - } - }); + Injector parent = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Bar.class); + } + }); ensureWorks(parent, Bar.class); ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class); - + try { - parent.createChildInjector(new AbstractModule() { - @Override - protected void configure() { - bind(FooBar.class); - } - }); + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(FooBar.class); + } + }); fail("should have failed"); - } catch(CreationException expected) { + } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(Foo.class)); assertEquals(1, expected.getErrorMessages().size()); } - - Injector child = parent.createChildInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Foo.class).to(FooImpl.class); - } - }); + + Injector child = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).to(FooImpl.class); + } + }); ensureWorks(child, Foo.class, Bar.class); ensureFails(child, ALLOW_BINDING, FooImpl.class); ensureInChild(parent, FooImpl.class, Foo.class); @@ -337,62 +376,71 @@ // FooBar was succesfully inserted into the child injector (and parent blacklist), but then // JIT bindings it depended on failed, making the child injector invalid. - Injector grandchild = child.createChildInjector(new AbstractModule() { - @Override - protected void configure() { - bind(FooBar.class); - } - }); + Injector grandchild = + child.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(FooBar.class); + } + }); ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class); ensureFails(grandchild, ALLOW_BINDING, FooImpl.class); ensureFails(child, ALLOW_BINDING, FooImpl.class); ensureInChild(parent, FooImpl.class, FooBar.class, Foo.class); } - + public void testChildInjectorAddsOption() { - Injector parent = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Bar.class); - } - }); + Injector parent = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Bar.class); + } + }); int totalParentBindings = parent.getAllBindings().size(); - + try { - parent.createChildInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(FooBar.class); - } - }); + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(FooBar.class); + } + }); fail("should have failed"); - } catch(CreationException expected) { + } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(Foo.class)); assertEquals(1, expected.getErrorMessages().size()); } assertEquals(totalParentBindings, parent.getAllBindings().size()); - - Injector child = parent.createChildInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); - bind(FooImpl.class); - } - }); + + Injector child = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + bind(FooImpl.class); + } + }); assertEquals(totalParentBindings, parent.getAllBindings().size()); ensureWorks(child, Foo.class, Bar.class); - - Injector grandchild = child.createChildInjector(new AbstractModule() { - @Override - protected void configure() { - bind(FooBar.class); - } - }); - assertEquals(totalParentBindings, parent.getAllBindings().size()); + + Injector grandchild = + child.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(FooBar.class); + } + }); + assertEquals(totalParentBindings, parent.getAllBindings().size()); ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class); - + // Make sure siblings of children don't inherit each others settings... // a new child should be able to get FooImpl. child = parent.createChildInjector(); @@ -401,114 +449,140 @@ public void testPrivateModulesInheritOptions() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); - - install(new PrivateModule() { - public void configure() { - bind(FooBar.class); - expose(FooBar.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(FooBar.class); + expose(FooBar.class); + } + }); } }); - } - }); fail("should have failed"); - } catch(CreationException expected) { + } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(Bar.class)); assertEquals(1, expected.getErrorMessages().size()); } - - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - binder().requireExplicitBindings(); - install(new PrivateModule() { - public void configure() { - bind(Foo.class).to(FooImpl.class); - expose(Foo.class); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(Foo.class).to(FooImpl.class); + expose(Foo.class); + } + }); + } + }); ensureInChild(injector, FooImpl.class); } - + public void testPrivateModuleAddsOption() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).to(FooImpl.class); - - // Fails because FooBar is in the private module, - // and it wants Bar, but Bar would be JIT. - install(new PrivateModule() { - public void configure() { - binder().requireExplicitBindings(); - bind(FooBar.class); - expose(FooBar.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).to(FooImpl.class); + + // Fails because FooBar is in the private module, + // and it wants Bar, but Bar would be JIT. + install( + new PrivateModule() { + @Override + public void configure() { + binder().requireExplicitBindings(); + bind(FooBar.class); + expose(FooBar.class); + } + }); } }); - } - }); fail("should have failed"); - } catch(CreationException expected) { + } catch (CreationException expected) { assertContains(expected.getMessage(), jitFailed(Bar.class)); assertEquals(1, expected.getErrorMessages().size()); } } public void testPrivateModuleSiblingsDontShareOption() { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).to(FooImpl.class); - - install(new PrivateModule() { - public void configure() { - binder().requireExplicitBindings(); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).to(FooImpl.class); - // This works, even though Bar is JIT, - // because the requireExplicitBindings isn't shared - // between sibling private modules. - install(new PrivateModule() { - public void configure() { - bind(FooBar.class); - expose(FooBar.class); + install( + new PrivateModule() { + @Override + public void configure() { + binder().requireExplicitBindings(); + } + }); + + // This works, even though Bar is JIT, + // because the requireExplicitBindings isn't shared + // between sibling private modules. + install( + new PrivateModule() { + @Override + public void configure() { + bind(FooBar.class); + expose(FooBar.class); + } + }); } }); - } - }); - } + } public void testTypeLiteralsCanBeInjected() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - binder().requireExplicitBindings(); - bind(new TypeLiteral>() {}); - bind(new TypeLiteral>() {}).toInstance(of("bar")); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(new TypeLiteral>() {}); + bind(new TypeLiteral>() {}).toInstance(of("bar")); + } + }); WantsTypeLiterals foo = injector.getInstance(new Key>() {}); assertEquals(foo.literal.getRawType(), String.class); assertEquals(of("bar"), foo.set); } - + public void testMembersInjectorsCanBeInjected() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - binder().requireExplicitBindings(); - } - - @Provides String data(MembersInjector mi) { - String data = "foo"; - mi.injectMembers(data); - return data; - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + } + + @Provides + String data(MembersInjector mi) { + String data = "foo"; + mi.injectMembers(data); + return data; + } + }); String data = injector.getInstance(String.class); assertEquals("foo", data); @@ -516,18 +590,20 @@ public void testJitLinkedBindingInParentFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(new PrivateModule() { + Guice.createInjector( + new AbstractModule() { @Override protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).to(FooImpl.class); + install( + new PrivateModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).to(FooImpl.class); + } + }); } }); - } - }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), jitInParentFailed(FooImpl.class)); @@ -537,18 +613,20 @@ public void testJitProviderBindingInParentFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(new PrivateModule() { + Guice.createInjector( + new AbstractModule() { @Override protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class).toProvider(FooProvider.class); + install( + new PrivateModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class).toProvider(FooProvider.class); + } + }); } }); - } - }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), jitInParentFailed(FooProvider.class)); @@ -558,18 +636,20 @@ public void testJitImplementedByBindingInParentFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(new PrivateModule() { + Guice.createInjector( + new AbstractModule() { @Override protected void configure() { - binder().requireExplicitBindings(); - bind(ImplBy.class); + install( + new PrivateModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(ImplBy.class); + } + }); } }); - } - }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), jitInParentFailed(ImplByImpl.class)); @@ -579,18 +659,20 @@ public void testJitProvidedByBindingInParentFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(new PrivateModule() { + Guice.createInjector( + new AbstractModule() { @Override protected void configure() { - binder().requireExplicitBindings(); - bind(ProvBy.class); + install( + new PrivateModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(ProvBy.class); + } + }); } }); - } - }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), jitInParentFailed(ProvByProvider.class)); @@ -599,32 +681,37 @@ } private void ensureWorks(Injector injector, Class... classes) { - for(int i = 0; i < classes.length; i++) { + for (int i = 0; i < classes.length; i++) { injector.getInstance(classes[i]); injector.getProvider(classes[i]).get(); injector.getBinding(classes[i]).getProvider().get(); } } - - enum GetBindingCheck { FAIL_ALL, ALLOW_BINDING, ALLOW_BINDING_PROVIDER } + + enum GetBindingCheck { + FAIL_ALL, + ALLOW_BINDING, + ALLOW_BINDING_PROVIDER + } + private void ensureFails(Injector injector, GetBindingCheck getBinding, Class... classes) { - for(int i = 0; i < classes.length; i++) { - try { + for (int i = 0; i < classes.length; i++) { + try { injector.getInstance(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), jitFailed(classes[i])); assertEquals(1, expected.getErrorMessages().size()); } - - try { + + try { injector.getProvider(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), jitFailed(classes[i])); assertEquals(1, expected.getErrorMessages().size()); } - + if (getBinding == GetBindingCheck.ALLOW_BINDING || getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) { Binding binding = injector.getBinding(classes[i]); @@ -633,7 +720,7 @@ if (getBinding != GetBindingCheck.ALLOW_BINDING_PROVIDER) { fail("should have failed trying to retrieve class: " + classes[i]); } - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { if (getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) { throw expected; } @@ -643,59 +730,80 @@ } else { try { injector.getBinding(classes[i]); - fail("should have failed tring to retrieve class: " + classes[i]); - } catch(ConfigurationException expected) { + fail("should have failed tring to retrieve class: " + classes[i]); + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), jitFailed(classes[i])); assertEquals(1, expected.getErrorMessages().size()); } } } } - + private void ensureInChild(Injector injector, Class... classes) { - for(int i = 0; i < classes.length; i++) { - try { + for (int i = 0; i < classes.length; i++) { + try { injector.getInstance(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), inChildMessage(classes[i])); assertEquals(1, expected.getErrorMessages().size()); } - - try { + + try { injector.getProvider(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), inChildMessage(classes[i])); assertEquals(1, expected.getErrorMessages().size()); } - + try { injector.getBinding(classes[i]); - fail("should have failed tring to retrieve class: " + classes[i]); - } catch(ConfigurationException expected) { + fail("should have failed tring to retrieve class: " + classes[i]); + } catch (ConfigurationException expected) { assertContains(expected.getMessage(), inChildMessage(classes[i])); assertEquals(1, expected.getErrorMessages().size()); } } } - + private static interface Foo {} + private static class FooImpl implements Foo {} - @Singleton private static class ScopedFooImpl implements Foo {} + + @Singleton + private static class ScopedFooImpl implements Foo {} + private static class WantsScopedFooImpl { - @SuppressWarnings("unused") @Inject ScopedFooImpl scopedFoo; + @SuppressWarnings("unused") + @Inject + ScopedFooImpl scopedFoo; } + private static class Bar {} + private static class FooBar { - @SuppressWarnings("unused") @Inject Foo foo; - @SuppressWarnings("unused") @Inject Bar bar; + @SuppressWarnings("unused") + @Inject + Foo foo; + + @SuppressWarnings("unused") + @Inject + Bar bar; } + private static class ProviderFooBar { - @SuppressWarnings("unused") @Inject Provider foo; - @SuppressWarnings("unused") @Inject Provider bar; + @SuppressWarnings("unused") + @Inject + Provider foo; + + @SuppressWarnings("unused") + @Inject + Provider bar; } + private static class FooProvider implements Provider { + @Override public Foo get() { return new FooImpl(); } @@ -703,29 +811,33 @@ @ImplementedBy(ImplByImpl.class) private static interface ImplBy {} + private static class ImplByImpl implements ImplBy {} - + @ImplementedBy(ImplByScopedImpl.class) private static interface ImplByScoped {} + @Singleton - private static class ImplByScopedImpl implements ImplByScoped {} + private static class ImplByScopedImpl implements ImplByScoped {} @ProvidedBy(ProvByProvider.class) private static interface ProvBy {} + private static class ProvByProvider implements Provider { + @Override public ProvBy get() { return new ProvBy() {}; } } - + private static class WantsTypeLiterals { TypeLiteral literal; Set set; - - @Inject WantsTypeLiterals(TypeLiteral literal, Set set) { + + @Inject + WantsTypeLiterals(TypeLiteral literal, Set set) { this.literal = literal; this.set = set; - } } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/KeyTest.java sisu-guice-4.2.0/core/test/com/google/inject/KeyTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/KeyTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/KeyTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,9 +26,6 @@ import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.util.Types; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -42,14 +39,15 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class KeyTest extends TestCase { public void foo(List a, List b) {} + public void bar(Provider> a) {} + @Foo String baz; List wildcardExtends; @@ -67,10 +65,11 @@ } public void testProviderKey() throws NoSuchMethodException { - Key actual = Key.get(getClass().getMethod("foo", List.class, List.class) - .getGenericParameterTypes()[0]).providerKey(); - Key expected = Key.get(getClass().getMethod("bar", Provider.class) - .getGenericParameterTypes()[0]); + Key actual = + Key.get(getClass().getMethod("foo", List.class, List.class).getGenericParameterTypes()[0]) + .providerKey(); + Key expected = + Key.get(getClass().getMethod("bar", Provider.class).getGenericParameterTypes()[0]); assertEqualsBothWays(expected, actual); assertEquals(expected.toString(), actual.toString()); } @@ -81,23 +80,37 @@ assertEquals(types[0], types[1]); Key> k = new Key>() {}; assertEquals(types[0], k.getTypeLiteral().getType()); - assertFalse(types[0].equals( - new Key>() {}.getTypeLiteral().getType())); + assertFalse(types[0].equals(new Key>() {}.getTypeLiteral().getType())); } /** - * Key canonicalizes {@link int.class} to {@code Integer.class}, and - * won't expose wrapper types. + * Key canonicalizes {@link int.class} to {@code Integer.class}, and won't expose wrapper types. */ public void testPrimitivesAndWrappersAreEqual() { - Class[] primitives = new Class[] { - boolean.class, byte.class, short.class, int.class, long.class, - float.class, double.class, char.class, void.class - }; - Class[] wrappers = new Class[] { - Boolean.class, Byte.class, Short.class, Integer.class, Long.class, - Float.class, Double.class, Character.class, Void.class - }; + Class[] primitives = + new Class[] { + boolean.class, + byte.class, + short.class, + int.class, + long.class, + float.class, + double.class, + char.class, + void.class + }; + Class[] wrappers = + new Class[] { + Boolean.class, + Byte.class, + Short.class, + Integer.class, + Long.class, + Float.class, + Double.class, + Character.class, + Void.class + }; for (int t = 0; t < primitives.length; t++) { @SuppressWarnings("unchecked") @@ -154,7 +167,9 @@ Key.get(String.class, Deprecated.class); fail(); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), "java.lang.Deprecated is not a binding annotation. ", + assertContains( + expected.getMessage(), + "java.lang.Deprecated is not a binding annotation. ", "Please annotate it with @BindingAnnotation."); } } @@ -164,7 +179,9 @@ Key.get(String.class, Bar.class); fail(); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), Bar.class.getName() + " is not retained at runtime.", + assertContains( + expected.getMessage(), + Bar.class.getName() + " is not retained at runtime.", "Please annotate it with @Retention(RUNTIME)."); } } @@ -173,16 +190,20 @@ /** Test for issue 186 */ public void testCannotCreateKeysWithTypeVariables() throws NoSuchMethodException { - ParameterizedType listOfTType = (ParameterizedType) getClass().getDeclaredMethod( - "parameterizedWithVariable", List.class).getGenericParameterTypes()[0]; + ParameterizedType listOfTType = + (ParameterizedType) + getClass() + .getDeclaredMethod("parameterizedWithVariable", List.class) + .getGenericParameterTypes()[ + 0]; TypeLiteral listOfT = TypeLiteral.get(listOfTType); try { Key.get(listOfT); fail("Guice should not allow keys for java.util.List"); } catch (ConfigurationException e) { - assertContains(e.getMessage(), - "java.util.List cannot be used as a key; It is not fully specified."); + assertContains( + e.getMessage(), "java.util.List cannot be used as a key; It is not fully specified."); } TypeVariable tType = (TypeVariable) listOfTType.getActualTypeArguments()[0]; @@ -191,8 +212,7 @@ Key.get(t); fail("Guice should not allow keys for T"); } catch (ConfigurationException e) { - assertContains(e.getMessage(), - "T cannot be used as a key; It is not fully specified."); + assertContains(e.getMessage(), "T cannot be used as a key; It is not fully specified."); } } @@ -202,8 +222,7 @@ Key.get(typeLiteral); fail("Guice should not allow keys for T"); } catch (ConfigurationException e) { - assertContains(e.getMessage(), - "T cannot be used as a key; It is not fully specified."); + assertContains(e.getMessage(), "T cannot be used as a key; It is not fully specified."); } } @@ -216,8 +235,7 @@ KeyTest.createKey(); fail("Guice should not allow keys for T"); } catch (ConfigurationException e) { - assertContains(e.getMessage(), - "T cannot be used as a key; It is not fully specified."); + assertContains(e.getMessage(), "T cannot be used as a key; It is not fully specified."); } } @@ -228,14 +246,18 @@ interface B {} @Retention(RUNTIME) - @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) - @BindingAnnotation @interface Foo {} - - @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) - @BindingAnnotation @interface Bar {} - - class HasTypeParameters & Runnable, C extends Runnable> { - A a; B b; C c; + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) + @BindingAnnotation + @interface Foo {} + + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) + @BindingAnnotation + @interface Bar {} + + static class HasTypeParameters & Runnable, C extends Runnable> { + A a; + B b; + C c; } public void testKeysWithDefaultAnnotations() { @@ -255,67 +277,79 @@ } @Retention(RUNTIME) - @BindingAnnotation @interface AllDefaults { + @BindingAnnotation + @interface AllDefaults { int v1() default 1; + String v2() default "foo"; } @Retention(RUNTIME) - @BindingAnnotation @interface SomeDefaults { + @BindingAnnotation + @interface SomeDefaults { int v1() default 1; + String v2() default "foo"; + Class clazz(); } @Retention(RUNTIME) - @BindingAnnotation @interface NoDefaults { + @BindingAnnotation + @interface NoDefaults { int value(); } @Retention(RUNTIME) - @BindingAnnotation @interface Marker { - } + @BindingAnnotation + @interface Marker {} @AllDefaults @Marker - class HasAnnotations {} + static class HasAnnotations {} public void testAnonymousClassesDontHoldRefs() { final AtomicReference>> stringProvider = new AtomicReference>>(); final AtomicReference>> intProvider = new AtomicReference>>(); - final Object foo = new Object() { - @SuppressWarnings("unused") @Inject List list; - }; - Module module = new AbstractModule() { - @Override protected void configure() { - bind(new Key>() {}).toInstance(new ArrayList()); - bind(new TypeLiteral>() {}).toInstance(new ArrayList()); - - stringProvider.set(getProvider(new Key>() {})); - intProvider.set(binder().getProvider(Dependency.get(new Key>() {}))); - - binder().requestInjection(new TypeLiteral() {}, foo); - } - }; - WeakReference moduleRef = new WeakReference(module); + final Object foo = + new Object() { + @SuppressWarnings("unused") + @Inject + List list; + }; + Module module = + new AbstractModule() { + @Override + protected void configure() { + bind(new Key>() {}).toInstance(new ArrayList()); + bind(new TypeLiteral>() {}).toInstance(new ArrayList()); + + stringProvider.set(getProvider(new Key>() {})); + intProvider.set(binder().getProvider(Dependency.get(new Key>() {}))); + + binder().requestInjection(new TypeLiteral() {}, foo); + } + }; + WeakReference moduleRef = new WeakReference<>(module); final Injector injector = Guice.createInjector(module); module = null; awaitClear(moduleRef); // Make sure anonymous keys & typeliterals don't hold the module. - Runnable runner = new Runnable() { - @Override public void run() { - injector.getInstance(new Key>() {}); - injector.getInstance(Key.get(new TypeLiteral>() {})); - } - }; - WeakReference runnerRef = new WeakReference(runner); + Runnable runner = + new Runnable() { + @Override + public void run() { + injector.getInstance(new Key>() {}); + injector.getInstance(Key.get(new TypeLiteral>() {})); + } + }; + WeakReference runnerRef = new WeakReference<>(runner); runner.run(); runner = null; awaitClear(runnerRef); // also make sure anonymous keys & typeliterals don't hold for JITs } static class Typed {} - } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/LoggerInjectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/LoggerInjectionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/LoggerInjectionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/LoggerInjectionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -3,10 +3,8 @@ import static com.google.inject.Asserts.assertContains; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.util.logging.Logger; +import junit.framework.TestCase; /** * Test built-in injection of loggers. @@ -22,21 +20,23 @@ injector.injectMembers(this); assertEquals("com.google.inject.LoggerInjectionTest", logger.getName()); } - + public void testLoggerInConstructor() { Injector injector = Guice.createInjector(); Foo foo = injector.getInstance(Foo.class); assertEquals("com.google.inject.LoggerInjectionTest$Foo", foo.logger.getName()); } - + private static class Foo { Logger logger; + @SuppressWarnings("unused") - @Inject Foo(Logger logger) { + @Inject + Foo(Logger logger) { this.logger = logger; } } - + public void testLoggerWithoutMember() { Injector injector = Guice.createInjector(); assertNull(injector.getInstance(Logger.class).getName()); @@ -46,28 +46,33 @@ } public void testCanBindAnnotatedLogger() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Logger.class) - .annotatedWith(Names.named("anonymous")) - .toInstance(Logger.getAnonymousLogger()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Logger.class) + .annotatedWith(Names.named("anonymous")) + .toInstance(Logger.getAnonymousLogger()); + } + }); assertNull(injector.getInstance(Key.get(Logger.class, Names.named("anonymous"))).getName()); } - + public void testCannotBindLogger() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Logger.class).toInstance(Logger.getAnonymousLogger()); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Logger.class).toInstance(Logger.getAnonymousLogger()); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), - "A binding to java.util.logging.Logger was already configured"); + assertContains( + expected.getMessage(), "A binding to java.util.logging.Logger was already configured"); } } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/matcher/MatcherTest.java sisu-guice-4.2.0/core/test/com/google/inject/matcher/MatcherTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/matcher/MatcherTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/matcher/MatcherTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,18 +30,14 @@ import com.google.inject.name.Named; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.AbstractList; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class MatcherTest extends TestCase { @@ -77,8 +73,7 @@ public void testAnnotatedWith() { assertTrue(annotatedWith(Foo.class).matches(Bar.class)); - assertFalse(annotatedWith(Foo.class).matches( - MatcherTest.class.getMethods()[0])); + assertFalse(annotatedWith(Foo.class).matches(MatcherTest.class.getMethods()[0])); assertEquals("annotatedWith(Foo.class)", annotatedWith(Foo.class).toString()); assertEqualsBothWays(annotatedWith(Foo.class), annotatedWith(Foo.class)); assertFalse(annotatedWith(Foo.class).equals(annotatedWith(Named.class))); @@ -134,15 +129,15 @@ assertFalse(inSubpackage(stringPackageName).matches(Matchers.class)); assertFalse(inSubpackage("jav").matches(Object.class)); assertEqualsBothWays(inSubpackage(stringPackageName), inSubpackage(stringPackageName)); - assertFalse(inSubpackage(stringPackageName).equals(inSubpackage(Matchers.class.getPackage().getName()))); + assertFalse( + inSubpackage(stringPackageName) + .equals(inSubpackage(Matchers.class.getPackage().getName()))); } public void testReturns() throws NoSuchMethodException { Matcher predicate = returns(only(String.class)); - assertTrue(predicate.matches( - Object.class.getMethod("toString"))); - assertFalse(predicate.matches( - Object.class.getMethod("hashCode"))); + assertTrue(predicate.matches(Object.class.getMethod("toString"))); + assertFalse(predicate.matches(Object.class.getMethod("hashCode"))); assertEquals("returns(only(class java.lang.String))", returns(only(String.class)).toString()); assertEqualsBothWays(predicate, returns(only(String.class))); assertFalse(predicate.equals(returns(only(Integer.class)))); @@ -163,7 +158,7 @@ assertEqualWhenReserialized(only("a").and(only("b"))); } - static abstract class MyRunnable implements Runnable {} + abstract static class MyRunnable implements Runnable {} @Retention(RetentionPolicy.RUNTIME) @interface Foo {} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/MembersInjectorTest.java sisu-guice-4.2.0/core/test/com/google/inject/MembersInjectorTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/MembersInjectorTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/MembersInjectorTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,70 +18,84 @@ import static com.google.inject.Asserts.assertContains; +import com.google.inject.internal.Annotations; import com.google.inject.name.Names; import com.google.inject.util.Providers; - +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; +import javax.inject.Inject; import junit.framework.AssertionFailedError; import junit.framework.TestCase; -import java.util.concurrent.atomic.AtomicReference; - -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class MembersInjectorTest extends TestCase { - private static final A uninjectableA = new A() { - @Override void doNothing() { - throw new AssertionFailedError(); - } - }; - - private static final B uninjectableB = new B() { - @Override void doNothing() { - throw new AssertionFailedError(); - } - }; - - private static final C myFavouriteC = new C(); + private static final long DEADLOCK_TIMEOUT_SECONDS = 1; - public void testMembersInjectorFromBinder() { - final AtomicReference>> aMembersInjectorReference - = new AtomicReference>>(); - final AtomicReference> bMembersInjectorReference - = new AtomicReference>(); - - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MembersInjector> aMembersInjector = getMembersInjector(new TypeLiteral>() {}); - try { - aMembersInjector.injectMembers(uninjectableA); - fail(); - } catch (IllegalStateException expected) { - assertContains(expected.getMessage(), - "This MembersInjector cannot be used until the Injector has been created."); + private static final A uninjectableA = + new A() { + @Inject + @Override + void doNothing() { + throw new AssertionFailedError(); } + }; - MembersInjector bMembersInjector = getMembersInjector(B.class); - try { - bMembersInjector.injectMembers(uninjectableB); - fail(); - } catch (IllegalStateException expected) { - assertContains(expected.getMessage(), - "This MembersInjector cannot be used until the Injector has been created."); + private static final B uninjectableB = + new B() { + @Inject + @Override + void doNothing() { + throw new AssertionFailedError(); } + }; - aMembersInjectorReference.set(aMembersInjector); - bMembersInjectorReference.set(bMembersInjector); - - assertEquals("MembersInjector", - getMembersInjector(String.class).toString()); + private static final C myFavouriteC = new C(); - bind(C.class).toInstance(myFavouriteC); - } - }); + public void testMembersInjectorFromBinder() { + final AtomicReference>> aMembersInjectorReference = + new AtomicReference>>(); + final AtomicReference> bMembersInjectorReference = + new AtomicReference>(); + + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + MembersInjector> aMembersInjector = getMembersInjector(new TypeLiteral>() {}); + try { + aMembersInjector.injectMembers(uninjectableA); + fail(); + } catch (IllegalStateException expected) { + assertContains( + expected.getMessage(), + "This MembersInjector cannot be used until the Injector has been created."); + } + + MembersInjector bMembersInjector = getMembersInjector(B.class); + try { + bMembersInjector.injectMembers(uninjectableB); + fail(); + } catch (IllegalStateException expected) { + assertContains( + expected.getMessage(), + "This MembersInjector cannot be used until the Injector has been created."); + } + + aMembersInjectorReference.set(aMembersInjector); + bMembersInjectorReference.set(bMembersInjector); + + assertEquals( + "MembersInjector", getMembersInjector(String.class).toString()); + + bind(C.class).toInstance(myFavouriteC); + } + }); - A injectableA = new A(); + A injectableA = new A<>(); aMembersInjectorReference.get().injectMembers(injectableA); assertSame(myFavouriteC, injectableA.t); assertSame(myFavouriteC, injectableA.b.c); @@ -96,17 +110,20 @@ } public void testMembersInjectorFromInjector() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(C.class).toInstance(myFavouriteC); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(C.class).toInstance(myFavouriteC); + } + }); - MembersInjector> aMembersInjector - = injector.getMembersInjector(new TypeLiteral>() {}); + MembersInjector> aMembersInjector = + injector.getMembersInjector(new TypeLiteral>() {}); MembersInjector bMembersInjector = injector.getMembersInjector(B.class); - A injectableA = new A(); + A injectableA = new A<>(); aMembersInjector.injectMembers(injectableA); assertSame(myFavouriteC, injectableA.t); assertSame(myFavouriteC, injectableA.b.c); @@ -119,15 +136,15 @@ bMembersInjector.injectMembers(anotherInjectableB); assertSame(myFavouriteC, anotherInjectableB.c); - assertEquals("MembersInjector", - injector.getMembersInjector(String.class).toString()); + assertEquals( + "MembersInjector", injector.getMembersInjector(String.class).toString()); } public void testMembersInjectorWithNonInjectedTypes() { Injector injector = Guice.createInjector(); - MembersInjector membersInjector - = injector.getMembersInjector(NoInjectedMembers.class); + MembersInjector membersInjector = + injector.getMembersInjector(NoInjectedMembers.class); membersInjector.injectMembers(new NoInjectedMembers()); membersInjector.injectMembers(new NoInjectedMembers()); @@ -136,14 +153,15 @@ public void testInjectionFailure() { Injector injector = Guice.createInjector(); - MembersInjector membersInjector - = injector.getMembersInjector(InjectionFailure.class); + MembersInjector membersInjector = + injector.getMembersInjector(InjectionFailure.class); try { membersInjector.injectMembers(new InjectionFailure()); fail(); } catch (ProvisionException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error injecting method, java.lang.ClassCastException: whoops, failure #1"); } } @@ -156,13 +174,17 @@ } public void testInjectingMembersInjector() { - InjectsMembersInjector injectsMembersInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(C.class).toInstance(myFavouriteC); - } - }).getInstance(InjectsMembersInjector.class); + InjectsMembersInjector injectsMembersInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(C.class).toInstance(myFavouriteC); + } + }) + .getInstance(InjectsMembersInjector.class); - A a = new A(); + A a = new A<>(); injectsMembersInjector.aMembersInjector.injectMembers(a); assertSame(myFavouriteC, a.t); assertSame(myFavouriteC, a.b.c); @@ -170,27 +192,33 @@ public void testCannotBindMembersInjector() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(MembersInjector.class).toProvider(Providers.of(null)); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(MembersInjector.class).toProvider(Providers.of(null)); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Binding to core guice framework type is not allowed: MembersInjector."); } try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(new TypeLiteral>>() {}) - .toProvider(Providers.>>of(null)); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(new TypeLiteral>>() {}) + .toProvider(Providers.>>of(null)); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Binding to core guice framework type is not allowed: MembersInjector."); } } @@ -200,7 +228,8 @@ Guice.createInjector().getInstance(InjectsBrokenMembersInjector.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for " + Unimplemented.class.getName() + " was bound.", "while locating " + Unimplemented.class.getName(), "for field at " + A.class.getName() + ".t(MembersInjectorTest.java:", @@ -211,20 +240,24 @@ } public void testLookupMembersInjectorBinding() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(C.class).toInstance(myFavouriteC); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(C.class).toInstance(myFavouriteC); + } + }); MembersInjector> membersInjector = injector.getInstance(new Key>>() {}); - A a = new A(); + A a = new A<>(); membersInjector.injectMembers(a); assertSame(myFavouriteC, a.t); assertSame(myFavouriteC, a.b.c); - assertEquals("MembersInjector", + assertEquals( + "MembersInjector", injector.getInstance(new Key>() {}).toString()); } @@ -234,8 +267,8 @@ injector.getInstance(MembersInjector.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), - "Cannot inject a MembersInjector that has no type parameter"); + assertContains( + expected.getMessage(), "Cannot inject a MembersInjector that has no type parameter"); } } @@ -245,21 +278,144 @@ injector.getInstance(new Key>(Names.named("foo")) {}); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for com.google.inject.MembersInjector " - + "annotated with @com.google.inject.name.Named(value=foo) was bound."); + + "annotated with @com.google.inject.name.Named(value=" + + Annotations.memberValueString("foo") + + ") was bound."); + } + } + + /** Callback for member injection. Uses a static type to be referable by getInstance(). */ + abstract static class AbstractParallelMemberInjectionCallback { + + volatile boolean called = false; + + private final Thread mainThread; + private final Class otherCallbackClass; + + AbstractParallelMemberInjectionCallback( + Class otherCallbackClass) { + this.mainThread = Thread.currentThread(); + this.otherCallbackClass = otherCallbackClass; + } + + @Inject + void callback(final Injector injector) throws Exception { + called = true; + if (mainThread != Thread.currentThread()) { + // only execute logic on the main thread + return; + } + // verify that other callback can be finished on a separate thread + AbstractParallelMemberInjectionCallback otherCallback = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public AbstractParallelMemberInjectionCallback call() throws Exception { + return injector.getInstance(otherCallbackClass); + } + }) + .get(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + assertTrue(otherCallback.called); + + try { + // other thread would wait for callback to finish on this thread first + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public Object call() throws Exception { + return injector.getInstance( + AbstractParallelMemberInjectionCallback.this.getClass()); + } + }) + .get(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + fail(); + } catch (TimeoutException expected) { + // recursive call from another thread should time out + // as it would be waiting for this thread to finish + } + } + } + + static class ParallelMemberInjectionCallback1 extends AbstractParallelMemberInjectionCallback { + + ParallelMemberInjectionCallback1() { + super(ParallelMemberInjectionCallback2.class); } } + static class ParallelMemberInjectionCallback2 extends AbstractParallelMemberInjectionCallback { + + ParallelMemberInjectionCallback2() { + super(ParallelMemberInjectionCallback1.class); + } + } + + /** + * Tests that member injections could happen in parallel. + * + *

    Additional check that when member injection happen other threads would wait for it to finish + * to provide proper resolution order semantics. + */ + + public void testMemberInjectorParallelization() throws Exception { + final ParallelMemberInjectionCallback1 c1 = new ParallelMemberInjectionCallback1(); + final ParallelMemberInjectionCallback2 c2 = new ParallelMemberInjectionCallback2(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(ParallelMemberInjectionCallback1.class).toInstance(c1); + bind(ParallelMemberInjectionCallback2.class).toInstance(c2); + } + }); + assertTrue(c1.called); + assertTrue(c2.called); + } + + /** Member injection callback that injects itself. */ + static class RecursiveMemberInjection { + boolean called = false; + + @Inject + void callback(RecursiveMemberInjection recursiveMemberInjection) { + if (called) { + fail("Should not be called twice"); + } + called = true; + } + } + + /** Verifies that member injection injecting itself would get a non initialized instance. */ + public void testRecursiveMemberInjector() throws Exception { + final RecursiveMemberInjection rmi = new RecursiveMemberInjection(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(RecursiveMemberInjection.class).toInstance(rmi); + } + }); + assertTrue("Member injection should happen", rmi.called); + } + static class A { @Inject B b; @Inject T t; - @Inject void doNothing() {} + + @Inject + void doNothing() {} } static class B { @Inject C c; - @Inject void doNothing() {} + + @Inject + void doNothing() {} } static class C {} @@ -269,7 +425,8 @@ static class InjectionFailure { int failures = 0; - @Inject void fail() { + @Inject + void fail() { throw new ClassCastException("whoops, failure #" + (++failures)); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/MethodInterceptionTest.java sisu-guice-4.2.0/core/test/com/google/inject/MethodInterceptionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/MethodInterceptionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/MethodInterceptionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,100 +25,121 @@ import com.google.inject.matcher.AbstractMatcher; import com.google.inject.matcher.Matchers; import com.google.inject.spi.ConstructorBinding; - -import junit.framework.TestCase; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Queue; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class MethodInterceptionTest extends TestCase { private AtomicInteger count = new AtomicInteger(); private final class CountingInterceptor implements MethodInterceptor { + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { count.incrementAndGet(); return methodInvocation.proceed(); } } - private final class ReturnNullInterceptor implements MethodInterceptor { + private static final class ReturnNullInterceptor implements MethodInterceptor { + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { return null; } } - - private final class NoOpInterceptor implements MethodInterceptor { + + private static final class NoOpInterceptor implements MethodInterceptor { + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { return methodInvocation.proceed(); } } public void testSharedProxyClasses() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)), - new ReturnNullInterceptor()); - } - }); - - Injector childOne = injector.createChildInjector(new AbstractModule() { - protected void configure() { - bind(Interceptable.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.returns(only(Foo.class)), new ReturnNullInterceptor()); + } + }); + + Injector childOne = + injector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Interceptable.class); + } + }); Interceptable nullFoosOne = childOne.getInstance(Interceptable.class); assertNotNull(nullFoosOne.bar()); assertNull(nullFoosOne.foo()); // confirm it's being intercepted - Injector childTwo = injector.createChildInjector(new AbstractModule() { - protected void configure() { - bind(Interceptable.class); - } - }); + Injector childTwo = + injector.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Interceptable.class); + } + }); Interceptable nullFoosTwo = childTwo.getInstance(Interceptable.class); assertNull(nullFoosTwo.foo()); // confirm it's being intercepted - assertSame("Child injectors should share proxy classes, otherwise memory leaks!", - nullFoosOne.getClass(), nullFoosTwo.getClass()); - - Injector injector2 = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)), - new ReturnNullInterceptor()); - } - }); + assertSame( + "Child injectors should share proxy classes, otherwise memory leaks!", + nullFoosOne.getClass(), + nullFoosTwo.getClass()); + + Injector injector2 = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.returns(only(Foo.class)), new ReturnNullInterceptor()); + } + }); Interceptable separateNullFoos = injector2.getInstance(Interceptable.class); assertNull(separateNullFoos.foo()); // confirm it's being intercepted - assertSame("different injectors should share proxy classes, otherwise memory leaks!", - nullFoosOne.getClass(), separateNullFoos.getClass()); + assertSame( + "different injectors should share proxy classes, otherwise memory leaks!", + nullFoosOne.getClass(), + separateNullFoos.getClass()); } public void testGetThis() { - final AtomicReference lastTarget = new AtomicReference(); + final AtomicReference lastTarget = new AtomicReference<>(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.any(), new MethodInterceptor() { - public Object invoke(MethodInvocation methodInvocation) throws Throwable { - lastTarget.set(methodInvocation.getThis()); - return methodInvocation.proceed(); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), + Matchers.any(), + new MethodInterceptor() { + @Override + public Object invoke(MethodInvocation methodInvocation) throws Throwable { + lastTarget.set(methodInvocation.getThis()); + return methodInvocation.proceed(); + } + }); + } + }); Interceptable interceptable = injector.getInstance(Interceptable.class); interceptable.foo(); @@ -126,22 +147,31 @@ } public void testInterceptingFinalClass() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.any(), new MethodInterceptor() { - public Object invoke(MethodInvocation methodInvocation) throws Throwable { - return methodInvocation.proceed(); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), + Matchers.any(), + new MethodInterceptor() { + @Override + public Object invoke(MethodInvocation methodInvocation) throws Throwable { + return methodInvocation.proceed(); + } + }); + } + }); try { injector.getInstance(NotInterceptable.class); fail(); - } catch(ConfigurationException ce) { - assertEquals("Unable to method intercept: " + NotInterceptable.class.getName(), + } catch (ConfigurationException ce) { + assertEquals( + "Unable to method intercept: " + NotInterceptable.class.getName(), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage().toString()); - assertEquals("Cannot subclass final class class " + NotInterceptable.class.getName(), + assertEquals( + "Cannot subclass final class " + NotInterceptable.class.getName(), ce.getCause().getMessage()); } } @@ -149,27 +179,34 @@ public void testSpiAccessToInterceptors() throws NoSuchMethodException { final MethodInterceptor countingInterceptor = new CountingInterceptor(); final MethodInterceptor returnNullInterceptor = new ReturnNullInterceptor(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(),Matchers.returns(only(Foo.class)), - countingInterceptor); - bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class).or(only(Bar.class))), - returnNullInterceptor); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.returns(only(Foo.class)), countingInterceptor); + bindInterceptor( + Matchers.any(), + Matchers.returns(only(Foo.class).or(only(Bar.class))), + returnNullInterceptor); + } + }); - ConstructorBinding interceptedBinding - = (ConstructorBinding) injector.getBinding(Interceptable.class); + ConstructorBinding interceptedBinding = + (ConstructorBinding) injector.getBinding(Interceptable.class); Method barMethod = Interceptable.class.getMethod("bar"); Method fooMethod = Interceptable.class.getMethod("foo"); - assertEquals(ImmutableMap.>of( - fooMethod, ImmutableList.of(countingInterceptor, returnNullInterceptor), - barMethod, ImmutableList.of(returnNullInterceptor)), + assertEquals( + ImmutableMap.>of( + fooMethod, ImmutableList.of(countingInterceptor, returnNullInterceptor), + barMethod, ImmutableList.of(returnNullInterceptor)), interceptedBinding.getMethodInterceptors()); - ConstructorBinding nonInterceptedBinding - = (ConstructorBinding) injector.getBinding(Foo.class); - assertEquals(ImmutableMap.>of(), + ConstructorBinding nonInterceptedBinding = + (ConstructorBinding) injector.getBinding(Foo.class); + assertEquals( + ImmutableMap.>of(), nonInterceptedBinding.getMethodInterceptors()); injector.getInstance(Interceptable.class).foo(); @@ -177,12 +214,15 @@ } public void testInterceptedMethodThrows() throws Exception { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor()); - bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor()); + bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor()); + } + }); Interceptable interceptable = injector.getInstance(Interceptable.class); try { @@ -199,14 +239,17 @@ } } } - + public void testNotInterceptedMethodsInInterceptedClassDontAddFrames() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)), - new NoOpInterceptor()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.returns(only(Foo.class)), new NoOpInterceptor()); + } + }); Interceptable interceptable = injector.getInstance(Interceptable.class); assertNull(interceptable.lastElements); @@ -220,7 +263,7 @@ } assertTrue(Arrays.toString(interceptable.lastElements), cglibFound); cglibFound = false; - + interceptable.bar(); for (int i = 0; i < interceptable.lastElements.length; i++) { if (interceptable.lastElements[i].toString().contains("cglib")) { @@ -232,19 +275,22 @@ } static class Foo {} + static class Bar {} public static class Interceptable { - StackTraceElement[] lastElements; - + StackTraceElement[] lastElements; + public Foo foo() { lastElements = Thread.currentThread().getStackTrace(); return new Foo() {}; } + public Bar bar() { lastElements = Thread.currentThread().getStackTrace(); return new Bar() {}; } + public String explode() throws Exception { lastElements = Thread.currentThread().getStackTrace(); throw new Exception("kaboom!", new RuntimeException("boom!")); @@ -252,76 +298,96 @@ } public static final class NotInterceptable {} - + public void testInterceptingNonBridgeWorks() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Interface.class).to(Impl.class); - bindInterceptor(Matchers.any(), new AbstractMatcher() { - public boolean matches(Method t) { - return !t.isBridge() && t.getDeclaringClass() != Object.class; - } - }, new CountingInterceptor()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Interface.class).to(Impl.class); + bindInterceptor( + Matchers.any(), + new AbstractMatcher() { + @Override + public boolean matches(Method t) { + return !t.isBridge() && t.getDeclaringClass() != Object.class; + } + }, + new CountingInterceptor()); + } + }); Interface intf = injector.getInstance(Interface.class); assertEquals(0, count.get()); intf.aMethod(null); assertEquals(1, count.get()); } - + static class ErasedType {} - static class RetType extends ErasedType {} - static abstract class Superclass { - public T aMethod(T t) { return null; } + + static class RetType extends ErasedType {} + + abstract static class Superclass { + public T aMethod(T t) { + return null; + } } + public interface Interface { - RetType aMethod(RetType obj); - } - public static class Impl extends Superclass implements Interface { + RetType aMethod(RetType obj); } - + + public static class Impl extends Superclass implements Interface {} + public void testInterceptionOrder() { final List callList = Lists.newArrayList(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.any(), - new NamedInterceptor("a", callList), - new NamedInterceptor("b", callList), - new NamedInterceptor("c", callList)); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), + Matchers.any(), + new NamedInterceptor("a", callList), + new NamedInterceptor("b", callList), + new NamedInterceptor("c", callList)); + } + }); Interceptable interceptable = injector.getInstance(Interceptable.class); assertEquals(0, callList.size()); interceptable.foo(); assertEquals(Arrays.asList("a", "b", "c"), callList); } - - private final class NamedInterceptor implements MethodInterceptor { + + private static final class NamedInterceptor implements MethodInterceptor { private final String name; final List called; - + NamedInterceptor(String name, List callList) { this.name = name; this.called = callList; } - + + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { called.add(name); return methodInvocation.proceed(); } } - + public void testDeDuplicateInterceptors() throws Exception { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - CountingInterceptor interceptor = new CountingInterceptor(); - bindInterceptor(Matchers.any(), Matchers.any(), interceptor); - bindInterceptor(Matchers.any(), Matchers.any(), interceptor); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + CountingInterceptor interceptor = new CountingInterceptor(); + bindInterceptor(Matchers.any(), Matchers.any(), interceptor); + bindInterceptor(Matchers.any(), Matchers.any(), interceptor); + } + }); Interceptable interceptable = injector.getInstance(Interceptable.class); interceptable.foo(); @@ -330,11 +396,14 @@ public void testCallLater() { final Queue queue = Lists.newLinkedList(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.any(), new CallLaterInterceptor(queue)); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor(Matchers.any(), Matchers.any(), new CallLaterInterceptor(queue)); + } + }); Interceptable interceptable = injector.getInstance(Interceptable.class); interceptable.foo(); @@ -345,24 +414,26 @@ assertNotNull(interceptable.lastElements); } - private final class CallLaterInterceptor implements MethodInterceptor { + private static final class CallLaterInterceptor implements MethodInterceptor { private final Queue queue; public CallLaterInterceptor(Queue queue) { this.queue = queue; } + @Override public Object invoke(final MethodInvocation methodInvocation) throws Throwable { - queue.add(new Runnable() { - @Override - public void run() { - try { - methodInvocation.proceed(); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }); + queue.add( + new Runnable() { + @Override + public void run() { + try { + methodInvocation.proceed(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }); return null; } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ModulesTest.java sisu-guice-4.2.0/core/test/com/google/inject/ModulesTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ModulesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ModulesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,14 +19,10 @@ import com.google.common.collect.ImmutableList; import com.google.inject.spi.ElementSource; import com.google.inject.util.Modules; - -import junit.framework.TestCase; - import java.util.Arrays; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class ModulesTest extends TestCase { public void testCombineVarargs() { @@ -36,7 +32,7 @@ assertEquals(2L, injector.getInstance(Long.class).longValue()); assertEquals(3, injector.getInstance(Short.class).shortValue()); } - + public void testCombineIterable() { Iterable modules = Arrays.asList(newModule(1), newModule(2L), newModule((short) 3)); Injector injector = Guice.createInjector(Modules.combine(modules)); @@ -45,31 +41,36 @@ assertEquals(3, injector.getInstance(Short.class).shortValue()); } - /** - * The module returned by Modules.combine shouldn't show up in binder sources. - */ + /** The module returned by Modules.combine shouldn't show up in binder sources. */ public void testCombineSources() { final Module m1 = newModule(1); final Module m2 = newModule(2L); final Module combined1 = Modules.combine(m1, m2); - Module skipSourcesModule = new AbstractModule() { - @Override protected void configure() { - install(combined1); - } - }; + Module skipSourcesModule = + new AbstractModule() { + @Override + protected void configure() { + install(combined1); + } + }; final Module combined2 = Modules.combine(skipSourcesModule); Injector injector = Guice.createInjector(combined2); ElementSource source = (ElementSource) injector.getBinding(Integer.class).getSource(); - assertEquals(source.getModuleClassNames().size(), 4); - assertEquals(ImmutableList.of(m1.getClass().getName(), - combined1.getClass().getName(), skipSourcesModule.getClass().getName(), - combined2.getClass().getName()), source.getModuleClassNames()); + assertEquals(4, source.getModuleClassNames().size()); + assertEquals( + ImmutableList.of( + m1.getClass().getName(), + combined1.getClass().getName(), + skipSourcesModule.getClass().getName(), + combined2.getClass().getName()), + source.getModuleClassNames()); StackTraceElement stackTraceElement = (StackTraceElement) source.getDeclaringSource(); assertEquals(skipSourcesModule.getClass().getName(), stackTraceElement.getClassName()); } private Module newModule(final T toBind) { return new AbstractModule() { + @Override protected void configure() { @SuppressWarnings("unchecked") // getClass always needs a cast Class tClass = (Class) toBind.getClass(); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ModuleTest.java sisu-guice-4.2.0/core/test/com/google/inject/ModuleTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ModuleTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ModuleTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -12,6 +12,7 @@ public class ModuleTest extends TestCase { static class A implements Module { + @Override public void configure(Binder binder) { binder.bind(X.class); binder.install(new B()); @@ -20,6 +21,7 @@ } static class B implements Module { + @Override public void configure(Binder binder) { binder.bind(Y.class); binder.install(new D()); @@ -27,6 +29,7 @@ } static class C implements Module { + @Override public void configure(Binder binder) { binder.bind(Z.class); binder.install(new D()); @@ -34,20 +37,28 @@ } static class D implements Module { + @Override public void configure(Binder binder) { binder.bind(W.class); } - @Override public boolean equals(Object obj) { + + @Override + public boolean equals(Object obj) { return obj.getClass() == D.class; // we're all equal in the eyes of guice } - @Override public int hashCode() { + + @Override + public int hashCode() { return D.class.hashCode(); } } static class X {} + static class Y {} + static class Z {} + static class W {} public void testDiamond() throws Exception { diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/multibindings/ProvidesIntoTest.java sisu-guice-4.2.0/core/test/com/google/inject/multibindings/ProvidesIntoTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/multibindings/ProvidesIntoTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/multibindings/ProvidesIntoTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.multibindings; + +import static com.google.inject.Asserts.assertContains; +import static com.google.inject.name.Names.named; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.CreationException; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.multibindings.ProvidesIntoOptional.Type; +import com.google.inject.name.Named; +import java.lang.annotation.Retention; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; +import junit.framework.TestCase; + +/** + * Tests the various @ProvidesInto annotations. + * + * @author sameb@google.com (Sam Berlin) + */ +public class ProvidesIntoTest extends TestCase { + + public void testAnnotation() throws Exception { + Injector injector = + Guice.createInjector( + MultibindingsScanner.asModule(), + new AbstractModule() { + + @ProvidesIntoSet + @Named("foo") + String setFoo() { + return "foo"; + } + + @ProvidesIntoSet + @Named("foo") + String setFoo2() { + return "foo2"; + } + + @ProvidesIntoSet + @Named("bar") + String setBar() { + return "bar"; + } + + @ProvidesIntoSet + @Named("bar") + String setBar2() { + return "bar2"; + } + + @ProvidesIntoSet + String setNoAnnotation() { + return "na"; + } + + @ProvidesIntoSet + String setNoAnnotation2() { + return "na2"; + } + + @ProvidesIntoMap + @StringMapKey("fooKey") + @Named("foo") + String mapFoo() { + return "foo"; + } + + @ProvidesIntoMap + @StringMapKey("foo2Key") + @Named("foo") + String mapFoo2() { + return "foo2"; + } + + @ProvidesIntoMap + @ClassMapKey(String.class) + @Named("bar") + String mapBar() { + return "bar"; + } + + @ProvidesIntoMap + @ClassMapKey(Number.class) + @Named("bar") + String mapBar2() { + return "bar2"; + } + + @ProvidesIntoMap + @TestEnumKey(TestEnum.A) + String mapNoAnnotation() { + return "na"; + } + + @ProvidesIntoMap + @TestEnumKey(TestEnum.B) + String mapNoAnnotation2() { + return "na2"; + } + + @ProvidesIntoMap + @WrappedKey(number = 1) + Number wrapped1() { + return 11; + } + + @ProvidesIntoMap + @WrappedKey(number = 2) + Number wrapped2() { + return 22; + } + + @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT) + @Named("foo") + String optionalDefaultFoo() { + return "foo"; + } + + @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL) + @Named("foo") + String optionalActualFoo() { + return "foo2"; + } + + @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT) + @Named("bar") + String optionalDefaultBar() { + return "bar"; + } + + @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL) + String optionalActualBar() { + return "na2"; + } + }); + + Set fooSet = injector.getInstance(new Key>(named("foo")) {}); + assertEquals(ImmutableSet.of("foo", "foo2"), fooSet); + + Set barSet = injector.getInstance(new Key>(named("bar")) {}); + assertEquals(ImmutableSet.of("bar", "bar2"), barSet); + + Set noAnnotationSet = injector.getInstance(new Key>() {}); + assertEquals(ImmutableSet.of("na", "na2"), noAnnotationSet); + + Map fooMap = + injector.getInstance(new Key>(named("foo")) {}); + assertEquals(ImmutableMap.of("fooKey", "foo", "foo2Key", "foo2"), fooMap); + + Map, String> barMap = + injector.getInstance(new Key, String>>(named("bar")) {}); + assertEquals(ImmutableMap.of(String.class, "bar", Number.class, "bar2"), barMap); + + Map noAnnotationMap = + injector.getInstance(new Key>() {}); + assertEquals(ImmutableMap.of(TestEnum.A, "na", TestEnum.B, "na2"), noAnnotationMap); + + Map wrappedMap = + injector.getInstance(new Key>() {}); + assertEquals(ImmutableMap.of(wrappedKeyFor(1), 11, wrappedKeyFor(2), 22), wrappedMap); + + Optional fooOptional = injector.getInstance(new Key>(named("foo")) {}); + assertEquals("foo2", fooOptional.get()); + + Optional barOptional = injector.getInstance(new Key>(named("bar")) {}); + assertEquals("bar", barOptional.get()); + + Optional noAnnotationOptional = injector.getInstance(new Key>() {}); + assertEquals("na2", noAnnotationOptional.get()); + } + + enum TestEnum { + A, + B + } + + @MapKey(unwrapValue = true) + @Retention(RUNTIME) + @interface TestEnumKey { + TestEnum value(); + } + + @MapKey(unwrapValue = false) + @Retention(RUNTIME) + @interface WrappedKey { + int number(); + } + + @SuppressWarnings("unused") + @WrappedKey(number = 1) + private static Object wrappedKey1Holder; + + @SuppressWarnings("unused") + @WrappedKey(number = 2) + private static Object wrappedKey2Holder; + + WrappedKey wrappedKeyFor(int number) throws Exception { + Field field; + switch (number) { + case 1: + field = ProvidesIntoTest.class.getDeclaredField("wrappedKey1Holder"); + break; + case 2: + field = ProvidesIntoTest.class.getDeclaredField("wrappedKey2Holder"); + break; + default: + throw new IllegalArgumentException("only 1 or 2 supported"); + } + return field.getAnnotation(WrappedKey.class); + } + + public void testDoubleScannerIsIgnored() { + Injector injector = + Guice.createInjector( + MultibindingsScanner.asModule(), + MultibindingsScanner.asModule(), + new AbstractModule() { + + @ProvidesIntoSet + String provideFoo() { + return "foo"; + } + }); + assertEquals(ImmutableSet.of("foo"), injector.getInstance(new Key>() {})); + } + + @MapKey(unwrapValue = true) + @Retention(RUNTIME) + @interface ArrayUnwrappedKey { + int[] value(); + } + + public void testArrayKeys_unwrapValuesTrue() { + Module m = + new AbstractModule() { + + @ProvidesIntoMap + @ArrayUnwrappedKey({1, 2}) + String provideFoo() { + return "foo"; + } + }; + try { + Guice.createInjector(MultibindingsScanner.asModule(), m); + fail(); + } catch (CreationException ce) { + assertEquals(1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "Array types are not allowed in a MapKey with unwrapValue=true: " + + ArrayUnwrappedKey.class.getName(), + "at " + m.getClass().getName() + ".provideFoo("); + } + } + + @MapKey(unwrapValue = false) + @Retention(RUNTIME) + @interface ArrayWrappedKey { + int[] number(); + } + + @SuppressWarnings("unused") + @ArrayWrappedKey(number = {1, 2}) + private static Object arrayWrappedKeyHolder12; + + @SuppressWarnings("unused") + @ArrayWrappedKey(number = {3, 4}) + private static Object arrayWrappedKeyHolder34; + + ArrayWrappedKey arrayWrappedKeyFor(int number) throws Exception { + Field field; + switch (number) { + case 12: + field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder12"); + break; + case 34: + field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder34"); + break; + default: + throw new IllegalArgumentException("only 1 or 2 supported"); + } + return field.getAnnotation(ArrayWrappedKey.class); + } + + public void testArrayKeys_unwrapValuesFalse() throws Exception { + Module m = + new AbstractModule() { + + @ProvidesIntoMap + @ArrayWrappedKey(number = {1, 2}) + String provideFoo() { + return "foo"; + } + + @ProvidesIntoMap + @ArrayWrappedKey(number = {3, 4}) + String provideBar() { + return "bar"; + } + }; + Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), m); + Map map = + injector.getInstance(new Key>() {}); + ArrayWrappedKey key12 = arrayWrappedKeyFor(12); + ArrayWrappedKey key34 = arrayWrappedKeyFor(34); + assertEquals("foo", map.get(key12)); + assertEquals("bar", map.get(key34)); + assertEquals(2, map.size()); + } + + public void testProvidesIntoSetWithMapKey() { + Module m = + new AbstractModule() { + + @ProvidesIntoSet + @TestEnumKey(TestEnum.A) + String provideFoo() { + return "foo"; + } + }; + try { + Guice.createInjector(MultibindingsScanner.asModule(), m); + fail(); + } catch (CreationException ce) { + assertEquals(1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "Found a MapKey annotation on non map binding at " + + m.getClass().getName() + + ".provideFoo"); + } + } + + public void testProvidesIntoOptionalWithMapKey() { + Module m = + new AbstractModule() { + + @ProvidesIntoOptional(Type.ACTUAL) + @TestEnumKey(TestEnum.A) + String provideFoo() { + return "foo"; + } + }; + try { + Guice.createInjector(MultibindingsScanner.asModule(), m); + fail(); + } catch (CreationException ce) { + assertEquals(1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "Found a MapKey annotation on non map binding at " + + m.getClass().getName() + + ".provideFoo"); + } + } + + public void testProvidesIntoMapWithoutMapKey() { + Module m = + new AbstractModule() { + + @ProvidesIntoMap + String provideFoo() { + return "foo"; + } + }; + try { + Guice.createInjector(MultibindingsScanner.asModule(), m); + fail(); + } catch (CreationException ce) { + assertEquals(1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "No MapKey found for map binding at " + m.getClass().getName() + ".provideFoo"); + } + } + + @MapKey(unwrapValue = true) + @Retention(RUNTIME) + @interface TestEnumKey2 { + TestEnum value(); + } + + public void testMoreThanOneMapKeyAnnotation() { + Module m = + new AbstractModule() { + + @ProvidesIntoMap + @TestEnumKey(TestEnum.A) + @TestEnumKey2(TestEnum.B) + String provideFoo() { + return "foo"; + } + }; + try { + Guice.createInjector(MultibindingsScanner.asModule(), m); + fail(); + } catch (CreationException ce) { + assertEquals(1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "Found more than one MapKey annotations on " + m.getClass().getName() + ".provideFoo"); + } + } + + @MapKey(unwrapValue = true) + @Retention(RUNTIME) + @interface MissingValueMethod {} + + public void testMapKeyMissingValueMethod() { + Module m = + new AbstractModule() { + + @ProvidesIntoMap + @MissingValueMethod + String provideFoo() { + return "foo"; + } + }; + try { + Guice.createInjector(MultibindingsScanner.asModule(), m); + fail(); + } catch (CreationException ce) { + assertEquals(1, ce.getErrorMessages().size()); + assertContains( + ce.getMessage(), + "No 'value' method in MapKey with unwrapValue=true: " + + MissingValueMethod.class.getName()); + } + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/name/NamedEquivalanceTest.java sisu-guice-4.2.0/core/test/com/google/inject/name/NamedEquivalanceTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/name/NamedEquivalanceTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/name/NamedEquivalanceTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,17 +27,16 @@ import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provides; - -import junit.framework.TestCase; - +import com.google.inject.internal.Annotations; import java.io.Serializable; import java.lang.annotation.Annotation; import java.util.Properties; +import junit.framework.TestCase; /** * Tests that {@code javax.inject.Named} and {@code com.google.inject.name.Named} are completely * interchangeable: bindings for one can be used to inject the other. - * + * * @author cgdecker@gmail.com (Colin Decker) */ public class NamedEquivalanceTest extends TestCase { @@ -45,21 +44,23 @@ private static final Module GUICE_BINDING_MODULE = moduleWithAnnotation(Names.named("foo")); private static final Module JSR330_BINDING_MODULE = moduleWithAnnotation(new JsrNamed("foo")); private static final Module GUICE_PROVIDER_METHOD_MODULE = getGuiceBindingProviderMethodModule(); - private static final Module JSR330_PROVIDER_METHOD_MODULE = getJsr330BindingProviderMethodModule(); + private static final Module JSR330_PROVIDER_METHOD_MODULE = + getJsr330BindingProviderMethodModule(); public void testKeysCreatedWithDifferentTypesAreEqual() { assertEquals(keyForAnnotation(new GuiceNamed("foo")), keyForAnnotation(new JsrNamed("foo"))); assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new GuiceNamed("foo"))); assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new JsrNamed("foo"))); - assertEquals(keyForAnnotationType(com.google.inject.name.Named.class), + assertEquals( + keyForAnnotationType(com.google.inject.name.Named.class), keyForAnnotationType(javax.inject.Named.class)); } private static Key keyForAnnotation(Annotation annotation) { return Key.get(String.class, annotation); } - + private static Key keyForAnnotationType(Class annotationType) { return Key.get(String.class, annotationType); } @@ -104,13 +105,15 @@ } public void testBindPropertiesWorksWithJsr330() { - assertInjectionsSucceed(new AbstractModule() { - @Override protected void configure() { - Properties properties = new Properties(); - properties.put("foo", "bar"); - Names.bindProperties(binder(), properties); - } - }); + assertInjectionsSucceed( + new AbstractModule() { + @Override + protected void configure() { + Properties properties = new Properties(); + properties.put("foo", "bar"); + Names.bindProperties(binder(), properties); + } + }); } private static void assertMissingBindingErrorMessageUsesType(Class clientType) { @@ -118,21 +121,28 @@ Guice.createInjector().getInstance(clientType); fail("should have thrown ConfigurationException"); } catch (ConfigurationException e) { - assertContains(e.getMessage(), - "No implementation for java.lang.String annotated with @com.google.inject.name.Named(value=foo) was bound."); + assertContains( + e.getMessage(), + "No implementation for java.lang.String annotated with " + + "@com.google.inject.name.Named(value=" + + Annotations.memberValueString("foo") + + ") was bound."); } } private static void assertDuplicateBinding(Module a, Module b, boolean fails) { try { Guice.createInjector(a, b); - if(fails) { + if (fails) { fail("should have thrown CreationException"); } } catch (CreationException e) { - if(fails) { - assertContains(e.getMessage(), - "A binding to java.lang.String annotated with @com.google.inject.name.Named(value=foo) was already configured"); + if (fails) { + assertContains( + e.getMessage(), + "A binding to java.lang.String annotated with @com.google.inject.name.Named(value=" + + Annotations.memberValueString("foo") + + ") was already configured"); } else { throw e; } @@ -141,7 +151,8 @@ private static Module moduleWithAnnotation(final Annotation annotation) { return new AbstractModule() { - @Override protected void configure() { + @Override + protected void configure() { bindConstant().annotatedWith(annotation).to("bar"); } }; @@ -149,8 +160,9 @@ private static void assertInjectionsSucceed(Module module) { Injector injector = Guice.createInjector(module); - assertInjected(injector.getInstance(GuiceNamedClient.class), injector - .getInstance(Jsr330NamedClient.class)); + assertInjected( + injector.getInstance(GuiceNamedClient.class), + injector.getInstance(Jsr330NamedClient.class)); } private static void assertInjected(GuiceNamedClient guiceClient, Jsr330NamedClient jsr330Client) { @@ -160,8 +172,11 @@ private static Module getJsr330BindingProviderMethodModule() { return new AbstractModule() { - @Override protected void configure() {} - @SuppressWarnings("unused") @Provides @javax.inject.Named("foo") String provideFoo() { + + @SuppressWarnings("unused") + @Provides + @javax.inject.Named("foo") + String provideFoo() { return "bar"; } }; @@ -169,19 +184,26 @@ private static Module getGuiceBindingProviderMethodModule() { return new AbstractModule() { - @Override protected void configure() {} - @SuppressWarnings("unused") @Provides @Named("foo") String provideFoo() { + + @SuppressWarnings("unused") + @Provides + @Named("foo") + String provideFoo() { return "bar"; } }; } private static class GuiceNamedClient { - @Inject @Named("foo") String foo; + @Inject + @Named("foo") + String foo; } private static class Jsr330NamedClient { - @Inject @javax.inject.Named("foo") String foo; + @Inject + @javax.inject.Named("foo") + String foo; } private static class JsrNamed implements javax.inject.Named, Serializable { @@ -191,15 +213,18 @@ this.value = value; } + @Override public String value() { return this.value; } + @Override public int hashCode() { // This is specified in java.lang.Annotation. return (127 * "value".hashCode()) ^ value.hashCode(); } + @Override public boolean equals(Object o) { if (!(o instanceof javax.inject.Named)) { return false; @@ -209,10 +234,16 @@ return value.equals(other.value()); } + @Override public String toString() { - return "@" + javax.inject.Named.class.getName() + "(value=" + value + ")"; + return "@" + + javax.inject.Named.class.getName() + + "(value=" + + Annotations.memberValueString(value) + + ")"; } + @Override public Class annotationType() { return javax.inject.Named.class; } @@ -222,20 +253,23 @@ private static class GuiceNamed implements com.google.inject.name.Named, Serializable { private final String value; - + public GuiceNamed(String value) { this.value = value; } - + + @Override public String value() { return this.value; } - + + @Override public int hashCode() { // This is specified in java.lang.Annotation. return (127 * "value".hashCode()) ^ value.hashCode(); } + @Override public boolean equals(Object o) { if (!(o instanceof com.google.inject.name.Named)) { return false; @@ -245,10 +279,16 @@ return value.equals(other.value()); } + @Override public String toString() { - return "@" + com.google.inject.name.Named.class.getName() + "(value=" + value + ")"; + return "@" + + com.google.inject.name.Named.class.getName() + + "(value=" + + Annotations.memberValueString(value) + + ")"; } + @Override public Class annotationType() { return com.google.inject.name.Named.class; } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/name/NamesTest.java sisu-guice-4.2.0/core/test/com/google/inject/name/NamesTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/name/NamesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/name/NamesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.google.inject.name; import static com.google.inject.Asserts.assertEqualWhenReserialized; @@ -25,21 +24,20 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Map; import java.util.Properties; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class NamesTest extends TestCase { - @Named("foo") private String foo; + @Named("foo") + private String foo; + private Named namedFoo; - + + @Override protected void setUp() throws Exception { super.setUp(); namedFoo = getClass().getDeclaredField("foo").getAnnotation(Named.class); @@ -60,25 +58,31 @@ teams.setProperty("SanJose", "Sharks"); teams.setProperty("Edmonton", "Oilers"); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - Names.bindProperties(binder(), teams); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Names.bindProperties(binder(), teams); + } + }); assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose")))); assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton")))); } public void testBindPropertiesUsingMap() { - final Map properties = ImmutableMap.of( - "SanJose", "Sharks", "Edmonton", "Oilers"); + final Map properties = + ImmutableMap.of("SanJose", "Sharks", "Edmonton", "Oilers"); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - Names.bindProperties(binder(), properties); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Names.bindProperties(binder(), properties); + } + }); assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose")))); assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton")))); @@ -93,11 +97,14 @@ teams.setProperty("SanJose", "Sharks"); teams.setProperty("Edmonton", "Oilers"); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - Names.bindProperties(binder(), teams); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Names.bindProperties(binder(), teams); + } + }); assertEquals("Pats", injector.getInstance(Key.get(String.class, Names.named("Regina")))); assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton")))); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/NullableInjectionPointTest.java sisu-guice-4.2.0/core/test/com/google/inject/NullableInjectionPointTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/NullableInjectionPointTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/NullableInjectionPointTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -3,28 +3,31 @@ import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.getDeclaringSourcePart; -import junit.framework.TestCase; - +import com.google.common.base.Optional; +import com.google.inject.multibindings.OptionalBinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import com.google.inject.util.Providers; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class NullableInjectionPointTest extends TestCase { public void testInjectNullIntoNotNullableConstructor() { try { createInjector().getInstance(FooConstructor.class); fail("Injecting null should fail with an error"); - } - catch (ProvisionException expected) { - assertContains(expected.getMessage(), + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), "null returned by binding at " + getClass().getName(), - "parameter 0 of " + FooConstructor.class.getName() + ".() is not @Nullable"); + "the 1st parameter of " + FooConstructor.class.getName() + ".(", + "is not @Nullable"); } } @@ -32,11 +35,12 @@ try { createInjector().getInstance(FooMethod.class); fail("Injecting null should fail with an error"); - } - catch (ProvisionException expected) { - assertContains(expected.getMessage(), + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), "null returned by binding at " + getClass().getName(), - "parameter 0 of " + FooMethod.class.getName() + ".setFoo() is not @Nullable"); + "the 1st parameter of " + FooMethod.class.getName() + ".setFoo(", + "is not @Nullable"); } } @@ -44,195 +48,222 @@ try { createInjector().getInstance(FooField.class); fail("Injecting null should fail with an error"); - } - catch (ProvisionException expected) { - assertContains(expected.getMessage(), + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), "null returned by binding at " + getClass().getName(), - " but " + FooField.class.getName() + ".foo is not @Nullable"); + " but " + FooField.class.getName() + ".foo", + " is not @Nullable"); } } - /** - * Provider.getInstance() is allowed to return null via direct calls to - * getInstance(). - */ + /** Provider.getInstance() is allowed to return null via direct calls to getInstance(). */ public void testGetInstanceOfNull() { assertNull(createInjector().getInstance(Foo.class)); } public void testInjectNullIntoNullableConstructor() { - NullableFooConstructor nfc - = createInjector().getInstance(NullableFooConstructor.class); + NullableFooConstructor nfc = createInjector().getInstance(NullableFooConstructor.class); assertNull(nfc.foo); } public void testInjectNullIntoNullableMethod() { - NullableFooMethod nfm - = createInjector().getInstance(NullableFooMethod.class); + NullableFooMethod nfm = createInjector().getInstance(NullableFooMethod.class); assertNull(nfm.foo); } public void testInjectNullIntoNullableField() { - NullableFooField nff - = createInjector().getInstance(NullableFooField.class); + NullableFooField nff = createInjector().getInstance(NullableFooField.class); assertNull(nff.foo); } - + public void testInjectNullIntoCustomNullableConstructor() { - CustomNullableFooConstructor nfc - = createInjector().getInstance(CustomNullableFooConstructor.class); + CustomNullableFooConstructor nfc = + createInjector().getInstance(CustomNullableFooConstructor.class); assertNull(nfc.foo); } public void testInjectNullIntoCustomNullableMethod() { - CustomNullableFooMethod nfm - = createInjector().getInstance(CustomNullableFooMethod.class); + CustomNullableFooMethod nfm = createInjector().getInstance(CustomNullableFooMethod.class); assertNull(nfm.foo); } public void testInjectNullIntoCustomNullableField() { - CustomNullableFooField nff - = createInjector().getInstance(CustomNullableFooField.class); + CustomNullableFooField nff = createInjector().getInstance(CustomNullableFooField.class); assertNull(nff.foo); - } + } private Injector createInjector() { return Guice.createInjector( new AbstractModule() { + @Override protected void configure() { - bind(Foo.class).toProvider(new Provider() { - public Foo get() { - return null; - } - }); + bind(Foo.class).toProvider(Providers.of(null)); } }); } - /** - * We haven't decided on what the desired behaviour of this test should be... - */ + /** We haven't decided on what the desired behaviour of this test should be... */ public void testBindNullToInstance() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).toInstance(null); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).toInstance(null); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "Binding to null instances is not allowed.", - "at " + getClass().getName(), getDeclaringSourcePart(getClass())); + "at " + getClass().getName(), + getDeclaringSourcePart(getClass())); } } public void testBindNullToProvider() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).toProvider(new Provider() { - public Foo get() { - return null; - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).toProvider(Providers.of(null)); + } + }); assertNull(injector.getInstance(NullableFooField.class).foo); assertNull(injector.getInstance(CustomNullableFooField.class).foo); try { injector.getInstance(FooField.class); - } - catch(ProvisionException expected) { + fail("Expected ProvisionException"); + } catch (ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at"); } } public void testBindScopedNull() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).toProvider(new Provider() { - public Foo get() { - return null; - } - }).in(Scopes.SINGLETON); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).toProvider(Providers.of(null)).in(Scopes.SINGLETON); + } + }); assertNull(injector.getInstance(NullableFooField.class).foo); assertNull(injector.getInstance(CustomNullableFooField.class).foo); try { injector.getInstance(FooField.class); - } - catch(ProvisionException expected) { + fail("Expected ProvisionException"); + } catch (ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at"); } } public void testBindNullAsEagerSingleton() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).toProvider(new Provider() { - public Foo get() { - return null; - } - }).asEagerSingleton(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).toProvider(Providers.of(null)).asEagerSingleton(); + } + }); assertNull(injector.getInstance(NullableFooField.class).foo); assertNull(injector.getInstance(CustomNullableFooField.class).foo); try { injector.getInstance(FooField.class); fail(); - } catch(ProvisionException expected) { - assertContains(expected.getMessage(), "null returned by binding " - + "at com.google.inject.NullableInjectionPointTest"); + } catch (ProvisionException expected) { + assertContains( + expected.getMessage(), + "null returned by binding " + "at com.google.inject.NullableInjectionPointTest"); } } - static class Foo { } + /** + * Tests for a regression where dependency objects were not updated properly and OptionalBinder + * was rejecting nulls from its dependencies. + */ + public void testBindNullAndLinkFromOptionalBinder() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).toProvider(Providers.of(null)); + OptionalBinder.newOptionalBinder(binder(), Foo.class); + } + + @Provides + @Named("throughProvidesMethod") + Foo provideFoo(Optional foo) { + return foo.orNull(); + } + }); + assertNull(injector.getInstance(Key.get(Foo.class, Names.named("throughProvidesMethod")))); + } + + static class Foo {} static class FooConstructor { - @Inject FooConstructor(Foo foo) { } + @Inject + FooConstructor(Foo foo) {} } + static class FooField { @Inject Foo foo; } + static class FooMethod { @Inject - void setFoo(Foo foo) { } + void setFoo(Foo foo) {} } static class NullableFooConstructor { Foo foo; - @Inject NullableFooConstructor(@Nullable Foo foo) { + + @Inject + NullableFooConstructor(@Nullable Foo foo) { this.foo = foo; } } + static class NullableFooField { @Inject @Nullable Foo foo; } + static class NullableFooMethod { Foo foo; - @Inject void setFoo(@Nullable Foo foo) { + + @Inject + void setFoo(@Nullable Foo foo) { this.foo = foo; } } - + static class CustomNullableFooConstructor { Foo foo; - @Inject CustomNullableFooConstructor(@Namespace.Nullable Foo foo) { + + @Inject + CustomNullableFooConstructor(@Namespace.Nullable Foo foo) { this.foo = foo; } } - + static class CustomNullableFooField { @Inject @Namespace.Nullable Foo foo; } + static class CustomNullableFooMethod { Foo foo; - @Inject void setFoo(@Namespace.Nullable Foo foo) { + + @Inject + void setFoo(@Namespace.Nullable Foo foo) { this.foo = foo; } } @@ -240,12 +271,12 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) - @interface Nullable { } - + @interface Nullable {} + static interface Namespace { @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) - @interface Nullable { } + @interface Nullable {} } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/OptionalBindingTest.java sisu-guice-4.2.0/core/test/com/google/inject/OptionalBindingTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/OptionalBindingTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/OptionalBindingTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +14,18 @@ * limitations under the License. */ - package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.name.Named; import com.google.inject.name.Names; - import junit.framework.TestCase; /** - * This test verifies the ways things are injected (ie. getInstance(), - * injectMembers(), bind to instance, and bind to provider instance) for all - * states of optional bindings (fields, methods, multiple-argument methods, - * provider fields, provider methods, constructors). + * This test verifies the ways things are injected (ie. getInstance(), injectMembers(), bind to + * instance, and bind to provider instance) for all states of optional bindings (fields, methods, + * multiple-argument methods, provider fields, provider methods, constructors). * * @author jessewilson@google.com (Jesse Wilson) */ @@ -42,44 +39,51 @@ private static final F injectF = new F() {}; private static final G injectG = new G() {}; - private Module everythingModule = new AbstractModule() { - protected void configure() { - bind(A.class).toInstance(injectA); - bind(B.class).toInstance(injectB); - bind(C.class).toInstance(injectC); - bind(D.class).toInstance(injectD); - bind(E.class).annotatedWith(Names.named("e")).toInstance(injectE); - bind(F.class).toInstance(injectF); - bind(G.class).toInstance(injectG); - } - }; - - private Module partialModule = new AbstractModule() { - protected void configure() { - bind(C.class).toInstance(new C() {}); - } - }; - - private Module toInstanceModule = new AbstractModule() { - protected void configure() { - bind(HasOptionalInjections.class) - .toInstance(new HasOptionalInjections()); - } - }; - - private Module toProviderInstanceModule = new AbstractModule() { - protected void configure() { - bind(HasOptionalInjections.class) - .toProvider(new HasOptionalInjectionsProvider()); - } - }; - - private Module toProviderModule = new AbstractModule() { - protected void configure() { - bind(HasOptionalInjections.class) - .toProvider(HasOptionalInjectionsProvider.class); - } - }; + private Module everythingModule = + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).toInstance(injectA); + bind(B.class).toInstance(injectB); + bind(C.class).toInstance(injectC); + bind(D.class).toInstance(injectD); + bind(E.class).annotatedWith(Names.named("e")).toInstance(injectE); + bind(F.class).toInstance(injectF); + bind(G.class).toInstance(injectG); + } + }; + + private Module partialModule = + new AbstractModule() { + @Override + protected void configure() { + bind(C.class).toInstance(new C() {}); + } + }; + + private Module toInstanceModule = + new AbstractModule() { + @Override + protected void configure() { + bind(HasOptionalInjections.class).toInstance(new HasOptionalInjections()); + } + }; + + private Module toProviderInstanceModule = + new AbstractModule() { + @Override + protected void configure() { + bind(HasOptionalInjections.class).toProvider(new HasOptionalInjectionsProvider()); + } + }; + + private Module toProviderModule = + new AbstractModule() { + @Override + protected void configure() { + bind(HasOptionalInjections.class).toProvider(HasOptionalInjectionsProvider.class); + } + }; public void testEverythingInjectorGetInstance() { Guice.createInjector(everythingModule) @@ -94,9 +98,7 @@ } public void testNothingInjectorGetInstance() { - Guice.createInjector() - .getInstance(HasOptionalInjections.class) - .assertNothingInjected(); + Guice.createInjector().getInstance(HasOptionalInjections.class).assertNothingInjected(); } public void testEverythingInjectorInjectMembers() { @@ -134,7 +136,7 @@ .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } - + public void testEverythingInjectorToProviderInstance() { Guice.createInjector(everythingModule, toProviderInstanceModule) .getInstance(HasOptionalInjections.class) @@ -173,36 +175,47 @@ static class HasOptionalInjections { A originalA = new A() {}; - @Inject(optional=true) A a = originalA; // field injection + + @Inject(optional = true) + A a = originalA; // field injection + B b; // method injection with one argument C c; // method injection with two arguments D d; // method injection with two arguments E e; // annotated injection - @Inject(optional=true) Provider fProvider; // provider + + @Inject(optional = true) + Provider fProvider; // provider + Provider gProvider; // method injection of provider boolean invoked0, invoked1, invoked2, invokedAnnotated, invokeProvider; - @Inject(optional=true) void methodInjectZeroArguments() { + @Inject(optional = true) + void methodInjectZeroArguments() { invoked0 = true; } - @Inject(optional=true) void methodInjectOneArgument(B b) { + @Inject(optional = true) + void methodInjectOneArgument(B b) { this.b = b; invoked1 = true; } - @Inject(optional=true) void methodInjectTwoArguments(C c, D d) { + @Inject(optional = true) + void methodInjectTwoArguments(C c, D d) { this.c = c; this.d = d; invoked2 = true; } - @Inject(optional=true) void methodInjectAnnotated(@Named("e") E e) { + @Inject(optional = true) + void methodInjectAnnotated(@Named("e") E e) { this.e = e; invokedAnnotated = true; } - @Inject(optional=true) void methodInjectProvider(Provider gProvider) { + @Inject(optional = true) + void methodInjectProvider(Provider gProvider) { this.gProvider = gProvider; invokeProvider = true; } @@ -237,8 +250,9 @@ } } - static class HasOptionalInjectionsProvider - extends HasOptionalInjections implements Provider { + static class HasOptionalInjectionsProvider extends HasOptionalInjections + implements Provider { + @Override public HasOptionalInjections get() { return this; } @@ -249,8 +263,10 @@ Guice.createInjector().getInstance(HasOptionalConstructor.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), "OptionalBindingTest$HasOptionalConstructor.() " - + "is annotated @Inject(optional=true), but constructors cannot be optional."); + assertContains( + expected.getMessage(), + "OptionalBindingTest$HasOptionalConstructor.() " + + "is annotated @Inject(optional=true), but constructors cannot be optional."); } } @@ -258,25 +274,27 @@ // Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations, // which catches optional injected constructors. @SuppressWarnings("InjectedConstructorAnnotations") - @Inject(optional=true) + @Inject(optional = true) HasOptionalConstructor() {} } - @Inject(optional=true) static A staticInjectA; + @Inject(optional = true) + static A staticInjectA; public void testStaticInjection() { staticInjectA = injectA; - Guice.createInjector(new AbstractModule() { - protected void configure() { - requestStaticInjection(OptionalBindingTest.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(OptionalBindingTest.class); + } + }); assertSame(staticInjectA, injectA); } /** - * Test for bug 107, where we weren't doing optional injection properly for - * indirect injections. + * Test for bug 107, where we weren't doing optional injection properly for indirect injections. */ public void testIndirectOptionalInjection() { Indirect indirect = Guice.createInjector().getInstance(Indirect.class); @@ -289,10 +307,16 @@ } interface A {} + interface B {} + interface C {} + interface D {} + interface E {} + interface F {} + interface G {} } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ParentInjectorTest.java sisu-guice-4.2.0/core/test/com/google/inject/ParentInjectorTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ParentInjectorTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ParentInjectorTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -26,16 +26,12 @@ import com.google.inject.matcher.Matchers; import com.google.inject.name.Names; import com.google.inject.spi.TypeConverter; - -import junit.framework.TestCase; - import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.List; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class ParentInjectorTest extends TestCase { public void testParentAndChildCannotShareExplicitBindings() { @@ -44,9 +40,17 @@ parent.createChildInjector(bindsA); fail("Created the same explicit binding on both parent and child"); } catch (CreationException e) { - assertContains(e.getMessage(), "A binding to ", A.class.getName(), " was already configured", - " at ", getClass().getName(), getDeclaringSourcePart(getClass()), - " at ", getClass().getName(), getDeclaringSourcePart(getClass())); + assertContains( + e.getMessage(), + "A binding to ", + A.class.getName(), + " was already configured", + " at ", + getClass().getName(), + getDeclaringSourcePart(getClass()), + " at ", + getClass().getName(), + getDeclaringSourcePart(getClass())); } } @@ -57,7 +61,8 @@ parent.getInstance(A.class); fail("Created a just-in-time binding on the parent that's the same as a child's binding"); } catch (ConfigurationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Unable to create binding for " + A.class.getName(), "It was already configured on one or more child injectors or private modules", "bound at " + bindsA.getClass().getName() + ".configure(", @@ -65,17 +70,20 @@ "while locating " + A.class.getName()); } } - + public void testChildCannotBindToAParentJitBinding() { Injector parent = Guice.createInjector(); parent.getInstance(A.class); try { parent.createChildInjector(bindsA); fail(); - } catch(CreationException ce) { - assertContains(Iterables.getOnlyElement(ce.getErrorMessages()).getMessage(), - "A just-in-time binding to " + A.class.getName() + " was already configured on a parent injector."); - } + } catch (CreationException ce) { + assertContains( + Iterables.getOnlyElement(ce.getErrorMessages()).getMessage(), + "A just-in-time binding to " + + A.class.getName() + + " was already configured on a parent injector."); + } } public void testJustInTimeBindingsAreSharedWithParentIfPossible() { @@ -116,40 +124,55 @@ } public void testScopesInherited() { - Injector parent = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(MyScope.class, Scopes.SINGLETON); - } - }); - Injector child = parent.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(A.class).in(MyScope.class); - } - }); + Injector parent = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(MyScope.class, Scopes.SINGLETON); + } + }); + Injector child = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).in(MyScope.class); + } + }); assertSame(child.getInstance(A.class), child.getInstance(A.class)); } /*if[AOP]*/ - private final org.aopalliance.intercept.MethodInterceptor returnNullInterceptor - = new org.aopalliance.intercept.MethodInterceptor() { - public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { - return null; - } - }; + private final org.aopalliance.intercept.MethodInterceptor returnNullInterceptor = + new org.aopalliance.intercept.MethodInterceptor() { + @Override + public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { + return null; + } + }; public void testInterceptorsInherited() { - Injector parent = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - super.bindInterceptor(Matchers.any(), Matchers.returns(Matchers.identicalTo(A.class)), - returnNullInterceptor); - } - }); - - Injector child = parent.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(C.class); - } - }); + Injector parent = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + super.bindInterceptor( + Matchers.any(), + Matchers.returns(Matchers.identicalTo(A.class)), + returnNullInterceptor); + } + }); + + Injector child = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(C.class); + } + }); assertNull(child.getInstance(C.class).interceptedMethod()); } @@ -176,11 +199,14 @@ public void testInjectorInjectionSpanningInjectors() { Injector parent = Guice.createInjector(); - Injector child = parent.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bind(D.class); - } - }); + Injector child = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(D.class); + } + }); D d = child.getInstance(D.class); assertSame(d.injector, child); @@ -194,7 +220,7 @@ Injector left = top.createChildInjector(); Injector leftLeft = left.createChildInjector(bindsD); Injector right = top.createChildInjector(bindsD); - + assertSame(leftLeft, leftLeft.getInstance(D.class).injector); assertSame(right, right.getInstance(D.class).injector); assertSame(top, leftLeft.getInstance(E.class).injector); @@ -218,33 +244,40 @@ public void testScopeBoundInChildInjectorOnly() { Injector parent = Guice.createInjector(); - Injector child = parent.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(MyScope.class, Scopes.SINGLETON); - } - }); + Injector child = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(MyScope.class, Scopes.SINGLETON); + } + }); try { parent.getProvider(F.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "No scope is bound to com.google.inject.ParentInjectorTest$MyScope.", "at " + F.class.getName() + ".class(ParentInjectorTest.java", " while locating " + F.class.getName()); } - + assertNotNull(child.getProvider(F.class).get()); } public void testErrorInParentButOkayInChild() { Injector parent = Guice.createInjector(); - Injector childInjector = parent.createChildInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(MyScope.class, Scopes.SINGLETON); - bind(Object.class).to(F.class); - } - }); + Injector childInjector = + parent.createChildInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(MyScope.class, Scopes.SINGLETON); + bind(Object.class).to(F.class); + } + }); Object one = childInjector.getInstance(Object.class); Object two = childInjector.getInstance(Object.class); assertSame(one, two); @@ -257,8 +290,10 @@ try { childInjector.getInstance(G.class); fail(); - } catch(ConfigurationException expected) { - assertContains(expected.getMessage(), "No scope is bound to " + MyScope.class.getName(), + } catch (ConfigurationException expected) { + assertContains( + expected.getMessage(), + "No scope is bound to " + MyScope.class.getName(), "at " + F.class.getName() + ".class(ParentInjectorTest.java:", " while locating " + G.class.getName()); } @@ -267,41 +302,54 @@ @Singleton static class A {} - private final Module bindsA = new AbstractModule() { - @Override protected void configure() { - bind(A.class).toInstance(new A()); - } - }; + private final Module bindsA = + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).toInstance(new A()); + } + }; interface B {} - static class RealB implements B {} - private final Module bindsB = new AbstractModule() { - @Override protected void configure() { - bind(B.class).to(RealB.class); - } - }; + static class RealB implements B {} - @Target(TYPE) @Retention(RUNTIME) @ScopeAnnotation + private final Module bindsB = + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).to(RealB.class); + } + }; + + @Target(TYPE) + @Retention(RUNTIME) + @ScopeAnnotation public @interface MyScope {} - private final TypeConverter listConverter = new TypeConverter() { - public Object convert(String value, TypeLiteral toType) { - return ImmutableList.of(); - } - }; - - private final Module bindListConverterModule = new AbstractModule() { - @Override protected void configure() { - convertToTypes(Matchers.any(), listConverter); - } - }; - - private final Module bindStringNamedB = new AbstractModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(Names.named("B")).toInstance("buzz"); - } - }; + private final TypeConverter listConverter = + new TypeConverter() { + @Override + public Object convert(String value, TypeLiteral toType) { + return ImmutableList.of(); + } + }; + + private final Module bindListConverterModule = + new AbstractModule() { + @Override + protected void configure() { + convertToTypes(Matchers.any(), listConverter); + } + }; + + private final Module bindStringNamedB = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(Names.named("B")).toInstance("buzz"); + } + }; public static class C { public A interceptedMethod() { @@ -317,11 +365,13 @@ @Inject Injector injector; } - private final Module bindsD = new AbstractModule() { - @Override protected void configure() { - bind(D.class); - } - }; + private final Module bindsD = + new AbstractModule() { + @Override + protected void configure() { + bind(D.class); + } + }; @MyScope static class F implements G {} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/PerformanceComparison.java sisu-guice-4.2.0/core/test/com/google/inject/PerformanceComparison.java --- sisu-guice-3.2.6/core/test/com/google/inject/PerformanceComparison.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/PerformanceComparison.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,21 +20,19 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertSame; +import java.lang.annotation.Retention; +import java.text.DecimalFormat; +import java.util.concurrent.Callable; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; -import java.lang.annotation.Retention; -import java.text.DecimalFormat; -import java.util.concurrent.Callable; - /** - * A semi-useless microbenchmark. Spring and Guice constuct the same object - * graph a bunch of times, and we see who can construct the most per second. - * As of this writing Guice is more than 50X faster. Also useful for comparing - * pure Java configuration options. + * A semi-useless microbenchmark. Spring and Guice constuct the same object graph a bunch of times, + * and we see who can construct the most per second. As of this writing Guice is more than 50X + * faster. Also useful for comparing pure Java configuration options. * * @author crazybob@google.com (Bob Lee) */ @@ -49,7 +47,7 @@ for (int i2 = 0; i2 < 10; i2++) { iterate(springFactory, "Spring: "); - iterate(juiceFactory, "Guice: "); + iterate(juiceFactory, "Guice: "); iterate(byHandFactory, "By Hand: "); System.err.println(); @@ -59,88 +57,99 @@ for (int i2 = 0; i2 < 10; i2++) { concurrentlyIterate(springFactory, "Spring: "); - concurrentlyIterate(juiceFactory, "Guice: "); + concurrentlyIterate(juiceFactory, "Guice: "); concurrentlyIterate(byHandFactory, "By Hand: "); System.err.println(); } } - static final Callable springFactory = new Callable() { + static final Callable springFactory = + new Callable() { - final DefaultListableBeanFactory beanFactory; + final DefaultListableBeanFactory beanFactory; - { - beanFactory = new DefaultListableBeanFactory(); + { + beanFactory = new DefaultListableBeanFactory(); - RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true); - tee.setLazyInit(true); - ConstructorArgumentValues teeValues = new ConstructorArgumentValues(); - teeValues.addGenericArgumentValue("test"); - tee.setConstructorArgumentValues(teeValues); - - RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false); - ConstructorArgumentValues barValues = new ConstructorArgumentValues(); - barValues.addGenericArgumentValue(new RuntimeBeanReference("tee")); - barValues.addGenericArgumentValue(5); - bar.setConstructorArgumentValues(barValues); - - RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false); - MutablePropertyValues fooValues = new MutablePropertyValues(); - fooValues.addPropertyValue("i", 5); - fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar")); - fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar")); - fooValues.addPropertyValue("s", "test"); - foo.setPropertyValues(fooValues); - - beanFactory.registerBeanDefinition("foo", foo); - beanFactory.registerBeanDefinition("bar", bar); - beanFactory.registerBeanDefinition("tee", tee); - } - - public Foo call() throws Exception { - return (Foo) beanFactory.getBean("foo"); - } - }; - - static final Callable juiceFactory = new Callable() { - final Provider fooProvider; - { - Injector injector; - try { - injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Tee.class).to(TeeImpl.class); - bind(Bar.class).to(BarImpl.class); - bind(Foo.class); - bindConstant().annotatedWith(I.class).to(5); - bindConstant().annotatedWith(S.class).to("test"); + RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true); + tee.setLazyInit(true); + ConstructorArgumentValues teeValues = new ConstructorArgumentValues(); + teeValues.addGenericArgumentValue("test"); + tee.setConstructorArgumentValues(teeValues); + + RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false); + ConstructorArgumentValues barValues = new ConstructorArgumentValues(); + barValues.addGenericArgumentValue(new RuntimeBeanReference("tee")); + barValues.addGenericArgumentValue(5); + bar.setConstructorArgumentValues(barValues); + + RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false); + MutablePropertyValues fooValues = new MutablePropertyValues(); + fooValues.addPropertyValue("i", 5); + fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar")); + fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar")); + fooValues.addPropertyValue("s", "test"); + foo.setPropertyValues(fooValues); + + beanFactory.registerBeanDefinition("foo", foo); + beanFactory.registerBeanDefinition("bar", bar); + beanFactory.registerBeanDefinition("tee", tee); + } + + @Override + public Foo call() throws Exception { + return (Foo) beanFactory.getBean("foo"); + } + }; + + static final Callable juiceFactory = + new Callable() { + final Provider fooProvider; + + { + Injector injector; + try { + injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Tee.class).to(TeeImpl.class); + bind(Bar.class).to(BarImpl.class); + bind(Foo.class); + bindConstant().annotatedWith(I.class).to(5); + bindConstant().annotatedWith(S.class).to("test"); + } + }); + } catch (CreationException e) { + throw new RuntimeException(e); } - }); - } catch (CreationException e) { - throw new RuntimeException(e); - } - fooProvider = injector.getProvider(Foo.class); - } + fooProvider = injector.getProvider(Foo.class); + } - public Foo call() throws Exception { - return fooProvider.get(); - } - }; + @Override + public Foo call() throws Exception { + return fooProvider.get(); + } + }; - static final Callable byHandFactory = new Callable() { - final Tee tee = new TeeImpl("test"); - public Foo call() throws Exception { - Foo foo = new Foo(); - foo.setI(5); - foo.setS("test"); - Bar bar = new BarImpl(tee, 5); - Bar copy = new BarImpl(tee, 5); - foo.setBar(bar); - foo.setCopy(copy); - return foo; - } - }; + static final Callable byHandFactory = + new Callable() { + final Tee tee = new TeeImpl("test"); + + @Override + public Foo call() throws Exception { + Foo foo = new Foo(); + foo.setI(5); + foo.setS("test"); + Bar bar = new BarImpl(tee, 5); + Bar copy = new BarImpl(tee, 5); + foo.setBar(bar); + foo.setCopy(copy); + return foo; + } + }; static void validate(Callable t) throws Exception { Foo foo = t.call(); @@ -161,16 +170,14 @@ for (int i = 0; i < count; i++) { try { callable.call(); - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException(e); } } time = System.currentTimeMillis() - time; - System.err.println(label - + format.format(count * 1000 / time) + " creations/s"); + System.err.println(label + format.format(count * 1000 / time) + " creations/s"); } static void concurrentlyIterate(final Callable callable, String label) { @@ -180,21 +187,21 @@ Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { - threads[i] = new Thread() { - public void run() { - for (int i = 0; i < count; i++) { - try { - validate(callable); - } - catch (Exception e) { - throw new RuntimeException(e); + threads[i] = + new Thread() { + @Override + public void run() { + for (int i = 0; i < count; i++) { + try { + validate(callable); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } - } - } - }; + }; } - long time = System.currentTimeMillis(); for (int i = 0; i < threadCount; i++) { @@ -204,16 +211,14 @@ for (int i = 0; i < threadCount; i++) { try { threads[i].join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { throw new RuntimeException(e); } } time = System.currentTimeMillis() - time; - System.err.println(label - + format.format(count * 1000 / time) + " creations/s"); + System.err.println(label + format.format(count * 1000 / time) + " creations/s"); } public static class Foo { @@ -247,6 +252,7 @@ interface Bar { Tee getTee(); + int getI(); } @@ -261,10 +267,12 @@ this.i = i; } + @Override public Tee getTee() { return tee; } + @Override public int getI() { return i; } @@ -285,14 +293,17 @@ this.s = s; } + @Override public String getS() { return s; } } @Retention(RUNTIME) - @BindingAnnotation @interface I {} + @BindingAnnotation + @interface I {} @Retention(RUNTIME) - @BindingAnnotation @interface S {} + @BindingAnnotation + @interface S {} } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/PrivateModuleTest.java sisu-guice-4.2.0/core/test/com/google/inject/PrivateModuleTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/PrivateModuleTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/PrivateModuleTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,48 +22,52 @@ import static com.google.inject.name.Names.named; import com.google.common.collect.ImmutableSet; +import com.google.inject.internal.Annotations; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.PrivateElements; import com.google.inject.util.Types; - -import junit.framework.TestCase; - import java.util.ArrayList; import java.util.Collection; import java.util.List; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class PrivateModuleTest extends TestCase { public void testBasicUsage() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(named("a")).toInstance("public"); - - install(new PrivateModule() { - @Override public void configure() { - bind(String.class).annotatedWith(named("b")).toInstance("i"); - - bind(AB.class).annotatedWith(named("one")).to(AB.class); - expose(AB.class).annotatedWith(named("one")); - } - }); - - install(new PrivateModule() { - @Override public void configure() { - bind(String.class).annotatedWith(named("b")).toInstance("ii"); - - bind(AB.class).annotatedWith(named("two")).to(AB.class); - expose(AB.class).annotatedWith(named("two")); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("public"); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(String.class).annotatedWith(named("b")).toInstance("i"); + + bind(AB.class).annotatedWith(named("one")).to(AB.class); + expose(AB.class).annotatedWith(named("one")); + } + }); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(String.class).annotatedWith(named("b")).toInstance("ii"); + + bind(AB.class).annotatedWith(named("two")).to(AB.class); + expose(AB.class).annotatedWith(named("two")); + } + }); + } + }); AB ab1 = injector.getInstance(Key.get(AB.class, named("one"))); assertEquals("public", ab1.a); @@ -73,21 +77,24 @@ assertEquals("public", ab2.a); assertEquals("ii", ab2.b); } - + public void testWithoutPrivateModules() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - PrivateBinder bindA = binder().newPrivateBinder(); - bindA.bind(String.class).annotatedWith(named("a")).toInstance("i"); - bindA.expose(String.class).annotatedWith(named("a")); - bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A"); - - PrivateBinder bindB = binder().newPrivateBinder(); - bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii"); - bindB.expose(String.class).annotatedWith(named("b")); - bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + PrivateBinder bindA = binder().newPrivateBinder(); + bindA.bind(String.class).annotatedWith(named("a")).toInstance("i"); + bindA.expose(String.class).annotatedWith(named("a")); + bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A"); + + PrivateBinder bindB = binder().newPrivateBinder(); + bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii"); + bindB.expose(String.class).annotatedWith(named("b")); + bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B"); + } + }); assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); assertEquals("ii", injector.getInstance(Key.get(String.class, named("b")))); @@ -95,80 +102,105 @@ public void testMisplacedExposedAnnotation() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() {} + Guice.createInjector( + new AbstractModule() { - @Provides @Exposed - String provideString() { - return "i"; - } - }); + @Provides + @Exposed + String provideString() { + return "i"; + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ", + assertContains( + expected.getMessage(), + "Cannot expose java.lang.String on a standard binder. ", "Exposed bindings are only applicable to private binders.", - " at " + PrivateModuleTest.class.getName(), "provideString(PrivateModuleTest.java:"); + " at " + PrivateModuleTest.class.getName(), + "provideString(PrivateModuleTest.java:"); } } public void testMisplacedExposeStatement() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a")); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a")); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ", + assertContains( + expected.getMessage(), + "Cannot expose java.lang.String on a standard binder. ", "Exposed bindings are only applicable to private binders.", - " at " + PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass())); + " at " + PrivateModuleTest.class.getName(), + getDeclaringSourcePart(getClass())); } } public void testPrivateModulesAndProvidesMethods() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - install(new PrivateModule() { - @Override public void configure() { - expose(String.class).annotatedWith(named("a")); - } - - @Provides @Named("a") String providePublicA() { - return "i"; - } - - @Provides @Named("b") String providePrivateB() { - return "private"; - } - }); - - install(new PrivateModule() { - @Override public void configure() {} - - @Provides @Named("c") String providePrivateC() { - return "private"; - } - - @Provides @Exposed @Named("d") String providePublicD() { - return "ii"; - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install( + new PrivateModule() { + @Override + public void configure() { + expose(String.class).annotatedWith(named("a")); + } + + @Provides + @Named("a") + String providePublicA() { + return "i"; + } + + @Provides + @Named("b") + String providePrivateB() { + return "private"; + } + }); + + install( + new PrivateModule() { + @Override + public void configure() {} + + @Provides + @Named("c") + String providePrivateC() { + return "private"; + } + + @Provides + @Exposed + @Named("d") + String providePublicD() { + return "ii"; + } + }); + } + }); assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); try { injector.getInstance(Key.get(String.class, named("b"))); fail(); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { } try { injector.getInstance(Key.get(String.class, named("c"))); fail(); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { } assertEquals("ii", injector.getInstance(Key.get(String.class, named("d")))); @@ -176,139 +208,181 @@ public void testCannotBindAKeyExportedByASibling() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - install(new PrivateModule() { - @Override public void configure() { - bind(String.class).toInstance("public"); - expose(String.class); - } - }); - - install(new PrivateModule() { - @Override public void configure() { - bind(String.class).toInstance("private"); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install( + new PrivateModule() { + @Override + public void configure() { + bind(String.class).toInstance("public"); + expose(String.class); + } + }); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(String.class).toInstance("private"); + } + }); } }); - } - }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "A binding to java.lang.String was already configured at ", - getClass().getName(), getDeclaringSourcePart(getClass()), - " at " + getClass().getName(), getDeclaringSourcePart(getClass())); + getClass().getName(), + getDeclaringSourcePart(getClass()), + " at " + getClass().getName(), + getDeclaringSourcePart(getClass())); } } public void testExposeButNoBind() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(named("a")).toInstance("a"); - bind(String.class).annotatedWith(named("b")).toInstance("b"); - - install(new PrivateModule() { - @Override public void configure() { - expose(AB.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("a"); + bind(String.class).annotatedWith(named("b")).toInstance("b"); + + install( + new PrivateModule() { + @Override + public void configure() { + expose(AB.class); + } + }); } }); - } - }); fail("AB was exposed but not bound"); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "Could not expose() " + AB.class.getName() + ", it must be explicitly bound", getDeclaringSourcePart(getClass())); } } /** - * Ensure that when we've got errors in different private modules, Guice presents all errors - * in a unified message. + * Ensure that when we've got errors in different private modules, Guice presents all errors in a + * unified message. */ public void testMessagesFromPrivateModulesAreNicelyIntegrated() { try { Guice.createInjector( new PrivateModule() { - @Override public void configure() { + @Override + public void configure() { bind(C.class); } }, new PrivateModule() { - @Override public void configure() { + @Override + public void configure() { bind(AB.class); } - } - ); + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for " + C.class.getName() + " was bound.", - "at " + getClass().getName(), getDeclaringSourcePart(getClass()), - "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.", + "at " + getClass().getName(), + getDeclaringSourcePart(getClass()), + "2) No implementation for " + String.class.getName(), + "Named(value=" + Annotations.memberValueString("a") + ") was bound.", "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:", - "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.", + "3) No implementation for " + String.class.getName(), + "Named(value=" + Annotations.memberValueString("b") + ") was bound.", "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:", "3 errors"); } } public void testNestedPrivateInjectors() { - Injector injector = Guice.createInjector(new PrivateModule() { - @Override public void configure() { - expose(String.class); - - install(new PrivateModule() { - @Override public void configure() { - bind(String.class).toInstance("nested"); - expose(String.class); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + public void configure() { + expose(String.class); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(String.class).toInstance("nested"); + expose(String.class); + } + }); + } + }); assertEquals("nested", injector.getInstance(String.class)); } public void testInstallingRegularModulesFromPrivateModules() { - Injector injector = Guice.createInjector(new PrivateModule() { - @Override public void configure() { - expose(String.class); - - install(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("nested"); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + public void configure() { + expose(String.class); + + install( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("nested"); + } + }); + } + }); assertEquals("nested", injector.getInstance(String.class)); } public void testNestedPrivateModulesWithSomeKeysUnexposed() { - Injector injector = Guice.createInjector(new PrivateModule() { - @Override public void configure() { - bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo"); - expose(String.class).annotatedWith(named("bound outer, exposed outer")); - bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen"); - expose(String.class).annotatedWith(named("bound inner, exposed both")); - - install(new PrivateModule() { - @Override public void configure() { - bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb"); - expose(String.class).annotatedWith(named("bound inner, exposed both")); - bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien"); - } - }); - } - }); - - assertEquals("boeo", - injector.getInstance(Key.get(String.class, named("bound outer, exposed outer")))); - assertEquals("bieb", - injector.getInstance(Key.get(String.class, named("bound inner, exposed both")))); + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + public void configure() { + bind(String.class) + .annotatedWith(named("bound outer, exposed outer")) + .toInstance("boeo"); + expose(String.class).annotatedWith(named("bound outer, exposed outer")); + bind(String.class) + .annotatedWith(named("bound outer, exposed none")) + .toInstance("boen"); + expose(String.class).annotatedWith(named("bound inner, exposed both")); + + install( + new PrivateModule() { + @Override + public void configure() { + bind(String.class) + .annotatedWith(named("bound inner, exposed both")) + .toInstance("bieb"); + expose(String.class).annotatedWith(named("bound inner, exposed both")); + bind(String.class) + .annotatedWith(named("bound inner, exposed none")) + .toInstance("bien"); + } + }); + } + }); + + assertEquals( + "boeo", injector.getInstance(Key.get(String.class, named("bound outer, exposed outer")))); + assertEquals( + "bieb", injector.getInstance(Key.get(String.class, named("bound inner, exposed both")))); try { injector.getInstance(Key.get(String.class, named("bound outer, exposed none"))); @@ -324,145 +398,204 @@ } public void testDependenciesBetweenPrivateAndPublic() { - Injector injector = Guice.createInjector( - new PrivateModule() { - @Override protected void configure() {} - - @Provides @Exposed @Named("a") String provideA() { - return "A"; - } - - @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { - return ab + "C"; - } - }, - new AbstractModule() { - @Override protected void configure() {} - - @Provides @Named("ab") String provideAb(@Named("a") String a) { - return a + "B"; - } - - @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { - return abc + "D"; - } - } - ); + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + protected void configure() {} + + @Provides + @Exposed + @Named("a") + String provideA() { + return "A"; + } + + @Provides + @Exposed + @Named("abc") + String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }, + new AbstractModule() { + + @Provides + @Named("ab") + String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides + @Named("abcd") + String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + }); assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd")))); } public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() { - Injector injector = Guice.createInjector( - new PrivateModule() { - @Override protected void configure() {} - - @Provides @Exposed @Named("a") String provideA() { - return "A"; - } - - @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { - return ab + "C"; - } - }, - new AbstractModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { - @Inject @Named("abcd") String abcd; - - public String get() { - return abcd + "E"; - } - }).asEagerSingleton(); - } - - @Provides @Named("ab") String provideAb(@Named("a") String a) { - return a + "B"; - } - - @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { - return abc + "D"; - } - } - ); + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + protected void configure() {} + + @Provides + @Exposed + @Named("a") + String provideA() { + return "A"; + } + + @Provides + @Exposed + @Named("abc") + String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }, + new AbstractModule() { + @Override + protected void configure() { + bind(String.class) + .annotatedWith(named("abcde")) + .toProvider( + new Provider() { + @Inject + @Named("abcd") + String abcd; + + @Override + public String get() { + return abcd + "E"; + } + }) + .asEagerSingleton(); + } + + @Provides + @Named("ab") + String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides + @Named("abcd") + String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + }); assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); } public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() { - Injector injector = Guice.createInjector( - new AbstractModule() { - @Override protected void configure() {} - - @Provides @Named("ab") String provideAb(@Named("a") String a) { - return a + "B"; - } - - @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { - return abc + "D"; - } - }, - new PrivateModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { - @Inject @Named("abcd") String abcd; - - public String get() { - return abcd + "E"; - } - }).asEagerSingleton(); - expose(String.class).annotatedWith(named("abcde")); - } - - @Provides @Exposed @Named("a") String provideA() { - return "A"; - } - - @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { - return ab + "C"; - } - } - ); + Injector injector = + Guice.createInjector( + new AbstractModule() { + + @Provides + @Named("ab") + String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides + @Named("abcd") + String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + }, + new PrivateModule() { + @Override + protected void configure() { + bind(String.class) + .annotatedWith(named("abcde")) + .toProvider( + new Provider() { + @Inject + @Named("abcd") + String abcd; + + @Override + public String get() { + return abcd + "E"; + } + }) + .asEagerSingleton(); + expose(String.class).annotatedWith(named("abcde")); + } + + @Provides + @Exposed + @Named("a") + String provideA() { + return "A"; + } + + @Provides + @Exposed + @Named("abc") + String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }); assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); } static class AB { - @Inject @Named("a") String a; - @Inject @Named("b") String b; + @Inject + @Named("a") + String a; + + @Inject + @Named("b") + String b; } interface C {} public void testSpiAccess() { - Injector injector = Guice.createInjector(new PrivateModule() { - @Override public void configure() { - bind(String.class).annotatedWith(named("a")).toInstance("private"); - bind(String.class).annotatedWith(named("b")).toInstance("exposed"); - expose(String.class).annotatedWith(named("b")); - } - }); - - ExposedBinding binding - = (ExposedBinding) injector.getBinding(Key.get(String.class, Names.named("b"))); - assertEquals(ImmutableSet.>of(Dependency.get(Key.get(Injector.class))), + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + public void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("private"); + bind(String.class).annotatedWith(named("b")).toInstance("exposed"); + expose(String.class).annotatedWith(named("b")); + } + }); + + ExposedBinding binding = + (ExposedBinding) injector.getBinding(Key.get(String.class, Names.named("b"))); + assertEquals( + ImmutableSet.>of(Dependency.get(Key.get(Injector.class))), binding.getDependencies()); PrivateElements privateElements = binding.getPrivateElements(); - assertEquals(ImmutableSet.>of(Key.get(String.class, named("b"))), + assertEquals( + ImmutableSet.>of(Key.get(String.class, named("b"))), privateElements.getExposedKeys()); - assertContains(privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(), - PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass())); + assertContains( + privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(), + PrivateModuleTest.class.getName(), + getDeclaringSourcePart(getClass())); Injector privateInjector = privateElements.getInjector(); assertEquals("private", privateInjector.getInstance(Key.get(String.class, Names.named("a")))); } - + public void testParentBindsSomethingInPrivate() { try { Guice.createInjector(new FailingModule()); fail(); - } catch(CreationException expected) { + } catch (CreationException expected) { assertEquals(1, expected.getErrorMessages().size()); - assertContains(expected.toString(), + assertContains( + expected.toString(), "Unable to create binding for java.util.List.", "It was already configured on one or more child injectors or private modules", "bound at " + FailingPrivateModule.class.getName() + ".configure(", @@ -474,15 +607,16 @@ "at " + FailingModule.class.getName() + ".configure("); } } - + public void testParentBindingToPrivateLinkedJitBinding() { Injector injector = Guice.createInjector(new ManyPrivateModules()); try { injector.getBinding(Key.get(Types.providerOf(List.class))); fail(); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertEquals(1, expected.getErrorMessages().size()); - assertContains(expected.toString(), + assertContains( + expected.toString(), "Unable to create binding for com.google.inject.Provider.", "It was already configured on one or more child injectors or private modules", "bound at " + FailingPrivateModule.class.getName() + ".configure(", @@ -493,15 +627,16 @@ "while locating com.google.inject.Provider"); } } - + public void testParentBindingToPrivateJitBinding() { Injector injector = Guice.createInjector(new ManyPrivateModules()); try { injector.getBinding(PrivateFoo.class); fail(); - } catch(ConfigurationException expected) { + } catch (ConfigurationException expected) { assertEquals(1, expected.getErrorMessages().size()); - assertContains(expected.toString(), + assertContains( + expected.toString(), "Unable to create binding for " + PrivateFoo.class.getName(), "It was already configured on one or more child injectors or private modules", "(bound by a just-in-time binding)", @@ -511,14 +646,16 @@ } private static class FailingModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bind(Collection.class).to(List.class); install(new ManyPrivateModules()); } } private static class ManyPrivateModules extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { // make sure duplicate sources are collapsed install(new FailingPrivateModule()); install(new FailingPrivateModule()); @@ -528,37 +665,39 @@ } private static class FailingPrivateModule extends PrivateModule { - @Override protected void configure() { + @Override + protected void configure() { bind(List.class).toInstance(new ArrayList()); - + // Add the Provider binding, created just-in-time, // to make sure our linked JIT bindings have the correct source. getProvider(Key.get(Types.providerOf(List.class))); - + // Request a JIT binding for PrivateFoo, which can only // be created in the private module because it depends // on List. getProvider(PrivateFoo.class); } } - + /** A second class, so we can see another name in the source list. */ private static class SecondFailingPrivateModule extends PrivateModule { - @Override protected void configure() { + @Override + protected void configure() { bind(List.class).toInstance(new ArrayList()); - + // Add the Provider binding, created just-in-time, // to make sure our linked JIT bindings have the correct source. getProvider(Key.get(Types.providerOf(List.class))); - + // Request a JIT binding for PrivateFoo, which can only // be created in the private module because it depends // on List. getProvider(PrivateFoo.class); } } - + private static class PrivateFoo { @Inject List list; - } + } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ProviderInjectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/ProviderInjectionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ProviderInjectionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ProviderInjectionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,24 +19,23 @@ import static com.google.inject.name.Names.named; import com.google.inject.name.Named; - -import junit.framework.TestCase; - import java.util.Arrays; import java.util.List; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ProviderInjectionTest extends TestCase { public void testProviderInjection() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Bar.class); - bind(SampleSingleton.class).in(Scopes.SINGLETON); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Bar.class); + bind(SampleSingleton.class).in(Scopes.SINGLETON); + } + }); Foo foo = injector.getInstance(Foo.class); @@ -51,107 +50,143 @@ /** Test for bug 155. */ public void testProvidersAreInjectedWhenBound() { - Module m = new AbstractModule() { - @Override - protected void configure() { - bind(Bar.class).toProvider(new Provider() { - @SuppressWarnings("unused") - @Inject void cantBeCalled(Baz baz) { - fail("Can't have called this method since Baz is not bound."); - } - public Bar get() { - return new Bar() {}; + Module m = + new AbstractModule() { + @Override + protected void configure() { + bind(Bar.class) + .toProvider( + new Provider() { + @SuppressWarnings("unused") + @Inject + void cantBeCalled(Baz baz) { + fail("Can't have called this method since Baz is not bound."); + } + + @Override + public Bar get() { + return new Bar() {}; + } + }); } - }); - } - }; + }; try { Guice.createInjector(m); fail("Should have thrown a CreationException"); - } - catch (CreationException expected) { + } catch (CreationException expected) { } } /** - * When custom providers are used at injector creation time, they should be - * injected before use. In this testcase, we verify that a provider for - * List.class is injected before it is used. + * When custom providers are used at injector creation time, they should be injected before use. + * In this testcase, we verify that a provider for List.class is injected before it is used. */ public void testProvidersAreInjectedBeforeTheyAreUsed() { - Injector injector = Guice.createInjector(new AbstractModule() { - public void configure() { - // should bind String to "[true]" - bind(String.class).toProvider(new Provider() { - private String value; - @Inject void initialize(List list) { - value = list.toString(); - } - public String get() { - return value; - } - }); - - // should bind List to [true] - bind(List.class).toProvider(new Provider() { - @Inject Boolean injectedYet = Boolean.FALSE; - public List get() { - return Arrays.asList(injectedYet); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + public void configure() { + // should bind String to "[true]" + bind(String.class) + .toProvider( + new Provider() { + private String value; + + @Inject + void initialize(List list) { + value = list.toString(); + } + + @Override + public String get() { + return value; + } + }); + + // should bind List to [true] + bind(List.class) + .toProvider( + new Provider() { + @Inject Boolean injectedYet = Boolean.FALSE; + + @Override + public List get() { + return Arrays.asList(injectedYet); + } + }); + + // should bind Boolean to true + bind(Boolean.class).toInstance(Boolean.TRUE); + } + }); - // should bind Boolean to true - bind(Boolean.class).toInstance(Boolean.TRUE); - } - }); - - assertEquals("Providers not injected before use", - "[true]", - injector.getInstance(String.class)); + assertEquals("Providers not injected before use", "[true]", injector.getInstance(String.class)); } /** - * This test ensures that regardless of binding order, instances are injected - * before they are used. It injects mutable Count objects and records their - * value at the time that they're injected. + * This test ensures that regardless of binding order, instances are injected before they are + * used. It injects mutable Count objects and records their value at the time that they're + * injected. */ public void testCreationTimeInjectionOrdering() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - // instance injection - bind(Count.class).annotatedWith(named("a")).toInstance(new Count(0) { - @Inject void initialize(@Named("b") Count bCount) { - value = bCount.value + 1; - } - }); - - // provider injection - bind(Count.class).annotatedWith(named("b")).toProvider(new Provider() { - Count count; - @Inject void initialize(@Named("c") Count cCount) { - count = new Count(cCount.value + 2); - } - public Count get() { - return count; - } - }); - - // field and method injection, fields first - bind(Count.class).annotatedWith(named("c")).toInstance(new Count(0) { - @Inject @Named("d") Count dCount; - @Inject void initialize(@Named("e") Count eCount) { - value = dCount.value + eCount.value + 4; - } - }); - - // static injection - requestStaticInjection(StaticallyInjectable.class); - - bind(Count.class).annotatedWith(named("d")).toInstance(new Count(8)); - bind(Count.class).annotatedWith(named("e")).toInstance(new Count(16)); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + // instance injection + bind(Count.class) + .annotatedWith(named("a")) + .toInstance( + new Count(0) { + @Inject + void initialize(@Named("b") Count bCount) { + value = bCount.value + 1; + } + }); + + // provider injection + bind(Count.class) + .annotatedWith(named("b")) + .toProvider( + new Provider() { + Count count; + + @Inject + void initialize(@Named("c") Count cCount) { + count = new Count(cCount.value + 2); + } + + @Override + public Count get() { + return count; + } + }); + + // field and method injection, fields first + bind(Count.class) + .annotatedWith(named("c")) + .toInstance( + new Count(0) { + @Inject + @Named("d") + Count dCount; + + @Inject + void initialize(@Named("e") Count eCount) { + value = dCount.value + eCount.value + 4; + } + }); + + // static injection + requestStaticInjection(StaticallyInjectable.class); + + bind(Count.class).annotatedWith(named("d")).toInstance(new Count(8)); + bind(Count.class).annotatedWith(named("e")).toInstance(new Count(16)); + } + }); assertEquals(28, injector.getInstance(Key.get(Count.class, named("c"))).value); assertEquals(30, injector.getInstance(Key.get(Count.class, named("b"))).value); @@ -161,6 +196,7 @@ static class Count { int value; + Count(int value) { this.value = value; } @@ -168,7 +204,9 @@ static class StaticallyInjectable { static int cCountAtInjectionTime; - @Inject static void initialize(@Named("c") Count cCount) { + + @Inject + static void initialize(@Named("c") Count cCount) { cCountAtInjectionTime = cCount.value; } } @@ -182,6 +220,5 @@ static class SampleSingleton {} - interface Baz { } - + interface Baz {} } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ProvisionExceptionsTest.java sisu-guice-4.2.0/core/test/com/google/inject/ProvisionExceptionsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ProvisionExceptionsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ProvisionExceptionsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,13 +16,11 @@ package com.google.inject; -import com.google.inject.internal.Errors; +import com.google.inject.internal.Messages; import com.google.inject.name.Named; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.io.IOException; +import junit.framework.TestCase; /** * Tests that ProvisionExceptions are readable and clearly indicate to the user what went wrong with @@ -31,148 +29,174 @@ * @author sameb@google.com (Sam Berlin) */ public class ProvisionExceptionsTest extends TestCase { - + public void testConstructorRuntimeException() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(Names.named("runtime")).to(true); - bind(Exploder.class).to(Explosion.class); - bind(Tracer.class).to(TracerImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(Names.named("runtime")).to(true); + bind(Exploder.class).to(Explosion.class); + bind(Tracer.class).to(TracerImpl.class); + } + }); try { injector.getInstance(Tracer.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { // Make sure our initial error message gives the user exception. - Asserts.assertContains(pe.getMessage(), - "1) Error injecting constructor", "java.lang.IllegalStateException: boom!"); + Asserts.assertContains( + pe.getMessage(), + "1) Error injecting constructor", + "java.lang.IllegalStateException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IllegalStateException.class, pe.getCause().getClass()); - assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); + assertEquals( + IllegalStateException.class, Messages.getOnlyCause(pe.getErrorMessages()).getClass()); } } - + public void testConstructorCheckedException() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(Names.named("runtime")).to(false); - bind(Exploder.class).to(Explosion.class); - bind(Tracer.class).to(TracerImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(Names.named("runtime")).to(false); + bind(Exploder.class).to(Explosion.class); + bind(Tracer.class).to(TracerImpl.class); + } + }); try { injector.getInstance(Tracer.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { // Make sure our initial error message gives the user exception. - Asserts.assertContains(pe.getMessage(), - "1) Error injecting constructor", "java.io.IOException: boom!"); + Asserts.assertContains( + pe.getMessage(), "1) Error injecting constructor", "java.io.IOException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IOException.class, pe.getCause().getClass()); - assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); + assertEquals(IOException.class, Messages.getOnlyCause(pe.getErrorMessages()).getClass()); } } - + public void testCustomProvidersRuntimeException() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Exploder.class).toProvider(new Provider() { - public Exploder get() { - return Explosion.createRuntime(); - } - }); - bind(Tracer.class).to(TracerImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Exploder.class) + .toProvider( + new Provider() { + @Override + public Exploder get() { + return Explosion.createRuntime(); + } + }); + bind(Tracer.class).to(TracerImpl.class); + } + }); try { injector.getInstance(Tracer.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { // Make sure our initial error message gives the user exception. - Asserts.assertContains(pe.getMessage(), - "1) Error in custom provider", "java.lang.IllegalStateException: boom!"); + Asserts.assertContains( + pe.getMessage(), "1) Error in custom provider", "java.lang.IllegalStateException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IllegalStateException.class, pe.getCause().getClass()); - assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); + assertEquals( + IllegalStateException.class, Messages.getOnlyCause(pe.getErrorMessages()).getClass()); } } - + public void testProviderMethodRuntimeException() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Tracer.class).to(TracerImpl.class); - } - @Provides Exploder exploder() { - return Explosion.createRuntime(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Tracer.class).to(TracerImpl.class); + } + + @Provides + Exploder exploder() { + return Explosion.createRuntime(); + } + }); try { injector.getInstance(Tracer.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { // Make sure our initial error message gives the user exception. - Asserts.assertContains(pe.getMessage(), - "1) Error in custom provider", "java.lang.IllegalStateException: boom!"); + Asserts.assertContains( + pe.getMessage(), "1) Error in custom provider", "java.lang.IllegalStateException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IllegalStateException.class, pe.getCause().getClass()); - assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); + assertEquals( + IllegalStateException.class, Messages.getOnlyCause(pe.getErrorMessages()).getClass()); } } - + public void testProviderMethodCheckedException() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Tracer.class).to(TracerImpl.class); - } - @Provides Exploder exploder() throws IOException { - return Explosion.createChecked(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Tracer.class).to(TracerImpl.class); + } + + @Provides + Exploder exploder() throws IOException { + return Explosion.createChecked(); + } + }); try { injector.getInstance(Tracer.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { pe.printStackTrace(); // Make sure our initial error message gives the user exception. - Asserts.assertContains(pe.getMessage(), - "1) Error in custom provider", "java.io.IOException: boom!"); + Asserts.assertContains( + pe.getMessage(), "1) Error in custom provider", "java.io.IOException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IOException.class, pe.getCause().getClass()); - assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); + assertEquals(IOException.class, Messages.getOnlyCause(pe.getErrorMessages()).getClass()); } } - + private static interface Exploder {} + public static class Explosion implements Exploder { - @Inject public Explosion(@Named("runtime") boolean runtime) throws IOException { - if(runtime) { + @Inject + public Explosion(@Named("runtime") boolean runtime) throws IOException { + if (runtime) { throw new IllegalStateException("boom!"); } else { throw new IOException("boom!"); } } - + public static Explosion createRuntime() { try { return new Explosion(true); - } catch(IOException iox) { + } catch (IOException iox) { throw new RuntimeException(); - } + } } - + public static Explosion createChecked() throws IOException { return new Explosion(false); } } + private static interface Tracer {} + private static class TracerImpl implements Tracer { - @Inject TracerImpl(Exploder explosion) { - } + @Inject + TracerImpl(Exploder explosion) {} } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ProvisionExceptionTest.java sisu-guice-4.2.0/core/test/com/google/inject/ProvisionExceptionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ProvisionExceptionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ProvisionExceptionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,28 +25,29 @@ import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import junit.framework.TestCase; - +import com.google.common.base.Throwables; +import com.google.inject.spi.Message; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ @SuppressWarnings("UnusedDeclaration") public class ProvisionExceptionTest extends TestCase { public void testExceptionsCollapsed() { try { Guice.createInjector().getInstance(A.class); - fail(); + fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); - assertContains(e.getMessage(), "Error injecting constructor", - "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD", + assertContains( + e.getMessage(), + "Error injecting constructor", + "for the 1st parameter of com.google.inject.ProvisionExceptionTest$C.setD", "for field at com.google.inject.ProvisionExceptionTest$B.c", - "for parameter 0 at com.google.inject.ProvisionExceptionTest$A"); + "for the 1st parameter of com.google.inject.ProvisionExceptionTest$A"); } } @@ -56,19 +57,24 @@ */ public void testExceptionsCollapsedWithScopes() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).in(Scopes.SINGLETON); - } - }).getInstance(A.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).in(Scopes.SINGLETON); + } + }) + .getInstance(A.class); fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); assertFalse(e.getMessage().contains("custom provider")); - assertContains(e.getMessage(), "Error injecting constructor", - "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD", + assertContains( + e.getMessage(), + "Error injecting constructor", + "for the 1st parameter of com.google.inject.ProvisionExceptionTest$C.setD", "for field at com.google.inject.ProvisionExceptionTest$B.c", - "for parameter 0 at com.google.inject.ProvisionExceptionTest$A"); + "for the 1st parameter of com.google.inject.ProvisionExceptionTest$A"); } } @@ -78,22 +84,28 @@ fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); - assertContains(e.getMessage(), "Error injecting method", + assertContains( + e.getMessage(), + "Error injecting method", "at " + E.class.getName() + ".setObject(ProvisionExceptionTest.java:"); } } public void testBindToProviderInstanceExceptions() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(D.class).toProvider(new DProvider()); - } - }).getInstance(D.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(D.class).toProvider(new DProvider()); + } + }) + .getInstance(D.class); fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error in custom provider, java.lang.UnsupportedOperationException", "at " + ProvisionExceptionTest.class.getName(), getDeclaringSourcePart(getClass())); @@ -108,36 +120,50 @@ Guice.createInjector().getInstance(F.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), "1) User Exception", + assertContains( + e.getMessage(), + "1) User Exception", "at " + F.class.getName() + ".(ProvisionExceptionTest.java:"); } } public void testProvisionExceptionsAreWrappedForBindToProviderType() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(F.class).toProvider(FProvider.class); - } - }).getInstance(F.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(F.class).toProvider(FProvider.class); + } + }) + .getInstance(F.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), "1) User Exception", - "while locating ", FProvider.class.getName(), - "while locating ", F.class.getName()); + assertContains( + e.getMessage(), + "1) User Exception", + "while locating ", + FProvider.class.getName(), + "while locating ", + F.class.getName()); } } public void testProvisionExceptionsAreWrappedForBindToProviderInstance() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(F.class).toProvider(new FProvider()); - } - }).getInstance(F.class); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(F.class).toProvider(new FProvider()); + } + }) + .getInstance(F.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), "1) User Exception", + assertContains( + e.getMessage(), + "1) User Exception", "at " + ProvisionExceptionTest.class.getName(), getDeclaringSourcePart(getClass())); } @@ -149,29 +175,47 @@ fail(); } catch (ProvisionException expected) { ProvisionException reserialized = reserialize(expected); - assertContains(reserialized.getMessage(), + assertContains( + reserialized.getMessage(), "1) Error injecting constructor, java.lang.UnsupportedOperationException", - "at com.google.inject.ProvisionExceptionTest$RealD.()", - "at Key[type=com.google.inject.ProvisionExceptionTest$RealD, annotation=[none]]", - "@com.google.inject.ProvisionExceptionTest$C.setD()[0]", - "at Key[type=com.google.inject.ProvisionExceptionTest$C, annotation=[none]]", - "@com.google.inject.ProvisionExceptionTest$B.c", - "at Key[type=com.google.inject.ProvisionExceptionTest$B, annotation=[none]]", - "@com.google.inject.ProvisionExceptionTest$A.()[0]", - "at Key[type=com.google.inject.ProvisionExceptionTest$A, annotation=[none]]"); + "at com.google.inject.ProvisionExceptionTest$RealD.()", + "at Key[type=com.google.inject.ProvisionExceptionTest$RealD, annotation=[none]]", + "@com.google.inject.ProvisionExceptionTest$C.setD()[0]", + "at Key[type=com.google.inject.ProvisionExceptionTest$C, annotation=[none]]", + "@com.google.inject.ProvisionExceptionTest$B.c", + "at Key[type=com.google.inject.ProvisionExceptionTest$B, annotation=[none]]", + "@com.google.inject.ProvisionExceptionTest$A.()[0]", + "at Key[type=com.google.inject.ProvisionExceptionTest$A, annotation=[none]]"); } } + // The only way to trigger an exception with _multiple_ user controlled throwables is by + // triggering errors during injector creation. public void testMultipleCauses() { try { - Guice.createInjector().getInstance(G.class); - fail(); - } catch (ProvisionException e) { - assertContains(e.getMessage(), - "1) Error injecting method, java.lang.IllegalArgumentException", + Guice.createInjector( + Stage.PRODUCTION, + new AbstractModule() { + @Provides + @Singleton + String injectFirst() { + throw new IllegalArgumentException(new UnsupportedOperationException("Unsupported")); + } + + @Provides + @Singleton + Object injectSecond() { + throw new NullPointerException("can't inject second either"); + } + }); + fail(); + } catch (CreationException e) { + assertContains( + e.getMessage(), + "1) Error in custom provider, java.lang.IllegalArgumentException", "Caused by: java.lang.IllegalArgumentException: java.lang.UnsupportedOperationException", "Caused by: java.lang.UnsupportedOperationException: Unsupported", - "2) Error injecting method, java.lang.NullPointerException: can't inject second either", + "2) Error in custom provider, java.lang.NullPointerException: can't inject second either", "Caused by: java.lang.NullPointerException: can't inject second either", "2 errors"); } @@ -183,7 +227,8 @@ injector.getInstance(InnerClass.class); fail(); } catch (Exception expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "Injecting into inner classes is not supported.", "while locating " + InnerClass.class.getName()); } @@ -197,7 +242,8 @@ injector.getInstance(LocalClass.class); fail(); } catch (Exception expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "Injecting into inner classes is not supported.", "while locating " + LocalClass.class.getName()); } @@ -209,8 +255,10 @@ injector.getInstance(MethodWithBindingAnnotation.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), MethodWithBindingAnnotation.class.getName() - + ".injectMe() is annotated with @", Green.class.getName() + "(), ", + assertContains( + expected.getMessage(), + MethodWithBindingAnnotation.class.getName() + ".injectMe() is annotated with @", + Green.class.getName() + "(), ", "but binding annotations should be applied to its parameters instead.", "while locating " + MethodWithBindingAnnotation.class.getName()); } @@ -219,8 +267,10 @@ Guice.createInjector().getInstance(ConstructorWithBindingAnnotation.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), ConstructorWithBindingAnnotation.class.getName() - + ".() is annotated with @", Green.class.getName() + "(), ", + assertContains( + expected.getMessage(), + ConstructorWithBindingAnnotation.class.getName() + ".() is annotated with @", + Green.class.getName() + "(), ", "but binding annotations should be applied to its parameters instead.", "at " + ConstructorWithBindingAnnotation.class.getName() + ".class", "while locating " + ConstructorWithBindingAnnotation.class.getName()); @@ -228,26 +278,33 @@ } public void testBindingAnnotationWarningForScala() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).annotatedWith(Green.class).toInstance("lime!"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(Green.class).toInstance("lime!"); + } + }); injector.getInstance(LikeScala.class); } public void testLinkedBindings() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(D.class).to(RealD.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(D.class).to(RealD.class); + } + }); try { injector.getInstance(D.class); fail(); } catch (ProvisionException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "at " + RealD.class.getName() + ".(ProvisionExceptionTest.java:", "while locating " + RealD.class.getName(), "while locating " + D.class.getName()); @@ -255,50 +312,118 @@ } public void testProviderKeyBindings() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(D.class).toProvider(DProvider.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(D.class).toProvider(DProvider.class); + } + }); try { injector.getInstance(D.class); fail(); } catch (ProvisionException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "while locating " + DProvider.class.getName(), "while locating " + D.class.getName()); } } + public void testDuplicateCausesCollapsed() { + final RuntimeException sharedException = new RuntimeException("fail"); + try { + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + addError(sharedException); + addError(sharedException); + } + }); + fail(); + } catch (CreationException ce) { + assertEquals(sharedException, ce.getCause()); + assertEquals(2, ce.getErrorMessages().size()); + for (Message message : ce.getErrorMessages()) { + assertEquals(sharedException, message.getCause()); + } + } + } + + public void testMultipleDuplicates() { + final RuntimeException exception1 = new RuntimeException("fail"); + final RuntimeException exception2 = new RuntimeException("abort"); + try { + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + addError(exception1); + addError(exception1); + addError(exception2); + addError(exception2); + } + }); + fail(); + } catch (CreationException ce) { + assertNull(ce.getCause()); + assertEquals(4, ce.getErrorMessages().size()); + + String e1 = Throwables.getStackTraceAsString(exception1); + String e2 = Throwables.getStackTraceAsString(exception2); + assertContains( + ce.getMessage(), + "\n1) ", + e1, + "\n2) ", + "(same stack trace as error #1)", + "\n3) ", + e2, + "\n4) ", + "(same stack trace as error #3)"); + } + } + + @SuppressWarnings("ClassCanBeStatic") private class InnerClass {} static class A { @Inject - A(B b) { } + A(B b) {} } + static class B { @Inject C c; } + static class C { @Inject - void setD(RealD d) { } + void setD(RealD d) {} } + static class E { - @Inject void setObject(Object o) { + @Inject + void setObject(Object o) { throw new UnsupportedOperationException(); } } static class MethodWithBindingAnnotation { - @Inject @Green void injectMe(String greenString) {} + @Inject + @Green + void injectMe(String greenString) {} } static class ConstructorWithBindingAnnotation { // Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations, // which catches injected constructors with binding annotations. @SuppressWarnings("InjectedConstructorAnnotations") - @Inject @Green ConstructorWithBindingAnnotation(String greenString) {} + @Inject + @Green + ConstructorWithBindingAnnotation(String greenString) {} } /** @@ -307,46 +432,46 @@ */ static class LikeScala { @Inject @Green String green; - @Inject @Green String green() { return green; } + + @Inject + @Green + String green() { + return green; + } } @Retention(RUNTIME) - @Target({ FIELD, PARAMETER, CONSTRUCTOR, METHOD }) + @Target({FIELD, PARAMETER, CONSTRUCTOR, METHOD}) @BindingAnnotation @interface Green {} interface D {} static class RealD implements D { - @Inject RealD() { + @Inject + RealD() { throw new UnsupportedOperationException(); } } static class DProvider implements Provider { + @Override public D get() { throw new UnsupportedOperationException(); } } static class F { - @Inject public F() { + @Inject + public F() { throw new ProvisionException("User Exception", new RuntimeException()); } } static class FProvider implements Provider { + @Override public F get() { return new F(); } } - - static class G { - @Inject void injectFirst() { - throw new IllegalArgumentException(new UnsupportedOperationException("Unsupported")); - } - @Inject void injectSecond() { - throw new NullPointerException("can't inject second either"); - } - } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ProvisionListenerTest.java sisu-guice-4.2.0/core/test/com/google/inject/ProvisionListenerTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ProvisionListenerTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ProvisionListenerTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,130 +17,151 @@ package com.google.inject; import static com.google.common.collect.ImmutableList.of; +import static com.google.common.truth.Truth.assertThat; import static com.google.inject.Asserts.assertContains; import static com.google.inject.name.Names.named; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.inject.matcher.AbstractMatcher; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import com.google.inject.name.Named; -import com.google.inject.spi.DependencyAndSource; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.ProvisionListener; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; /** * Tests for {@link Binder#bindListener(Matcher, ProvisionListener...)} - * + * * @author sameb@google.com (Sam Berlin) */ // TODO(sameb): Add some tests for private modules & child injectors. public class ProvisionListenerTest extends TestCase { public void testExceptionInListenerBeforeProvisioning() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new FailBeforeProvision()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new FailBeforeProvision()); + } + }); try { injector.getInstance(Foo.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), - "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName() - + " of " + Foo.class.getName(), + assertContains( + pe.getMessage(), + "1) Error notifying ProvisionListener " + + FailBeforeProvision.class.getName() + + " of " + + Foo.class.getName(), "Reason: java.lang.RuntimeException: boo", "while locating " + Foo.class.getName()); assertEquals("boo", pe.getCause().getMessage()); } } - + public void testExceptionInListenerAfterProvisioning() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new FailAfterProvision()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new FailAfterProvision()); + } + }); try { injector.getInstance(Foo.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), - "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName() - + " of " + Foo.class.getName(), + assertContains( + pe.getMessage(), + "1) Error notifying ProvisionListener " + + FailAfterProvision.class.getName() + + " of " + + Foo.class.getName(), "Reason: java.lang.RuntimeException: boo", "while locating " + Foo.class.getName()); assertEquals("boo", pe.getCause().getMessage()); } } - + public void testExceptionInProvisionExplicitlyCalled() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new JustProvision()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new JustProvision()); + } + }); try { injector.getInstance(FooBomb.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), + assertContains( + pe.getMessage(), "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail", " at " + FooBomb.class.getName(), " while locating " + FooBomb.class.getName()); assertEquals("Retry, Abort, Fail", pe.getCause().getMessage()); } } - + public void testExceptionInProvisionAutomaticallyCalled() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new NoProvision()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new NoProvision()); + } + }); try { injector.getInstance(FooBomb.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), + assertContains( + pe.getMessage(), "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail", " at " + FooBomb.class.getName(), " while locating " + FooBomb.class.getName()); assertEquals("Retry, Abort, Fail", pe.getCause().getMessage()); } } - + public void testExceptionInFieldProvision() throws Exception { final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(new AbstractMatcher>() { - @Override public boolean matches(Binding binding) { - return binding.getKey().getRawType().equals(DependsOnFooBombInField.class); - } - }, listener); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + new AbstractMatcher>() { + @Override + public boolean matches(Binding binding) { + return binding.getKey().getRawType().equals(DependsOnFooBombInField.class); + } + }, + listener); + } + }); assertEquals(0, listener.beforeProvision); String expectedMsg = null; try { @@ -148,29 +169,48 @@ fail(); } catch (ProvisionException expected) { assertEquals(1, expected.getErrorMessages().size()); - expectedMsg = expected.getMessage(); - assertContains(listener.capture.get().getMessage(), + expectedMsg = Iterables.getOnlyElement(expected.getErrorMessages()).getMessage(); + assertContains( + expected.getMessage(), "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail", " at " + FooBomb.class.getName(), " while locating " + FooBomb.class.getName(), " while locating " + DependsOnFooBombInField.class.getName()); + assertContains( + listener.capture.get().getMessage(), + "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail", + " at " + FooBomb.class.getName(), + " while locating " + FooBomb.class.getName()); + // The message that is captures by the provision listener does not show what is depending on + // the thing being listened to. + assertThat(listener.capture.get().getMessage()) + .doesNotContain(" while locating " + DependsOnFooBombInField.class.getName()); } assertEquals(1, listener.beforeProvision); - assertEquals(expectedMsg, listener.capture.get().getMessage()); + assertEquals( + expectedMsg, + Iterables.getOnlyElement(((ProvisionException) listener.capture.get()).getErrorMessages()) + .getMessage()); assertEquals(0, listener.afterProvision); } - + public void testExceptionInCxtorProvision() throws Exception { final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(new AbstractMatcher>() { - @Override public boolean matches(Binding binding) { - return binding.getKey().getRawType().equals(DependsOnFooBombInCxtor.class); - } - }, listener); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + new AbstractMatcher>() { + @Override + public boolean matches(Binding binding) { + return binding.getKey().getRawType().equals(DependsOnFooBombInCxtor.class); + } + }, + listener); + } + }); assertEquals(0, listener.beforeProvision); String expectedMsg = null; try { @@ -178,177 +218,215 @@ fail(); } catch (ProvisionException expected) { assertEquals(1, expected.getErrorMessages().size()); - expectedMsg = expected.getMessage(); - assertContains(listener.capture.get().getMessage(), + expectedMsg = Iterables.getOnlyElement(expected.getErrorMessages()).getMessage(); + assertContains( + expected.getMessage(), "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail", " at " + FooBomb.class.getName(), " while locating " + FooBomb.class.getName(), " while locating " + DependsOnFooBombInCxtor.class.getName()); + assertContains( + listener.capture.get().getMessage(), + "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail", + " at " + FooBomb.class.getName(), + " while locating " + FooBomb.class.getName()); + // The message that is captures by the provision listener does not show what is depending on + // the thing being listened to. + assertThat(listener.capture.get().getMessage()) + .doesNotContain(" while locating " + DependsOnFooBombInField.class.getName()); } assertEquals(1, listener.beforeProvision); - assertEquals(expectedMsg, listener.capture.get().getMessage()); + assertEquals( + expectedMsg, + Iterables.getOnlyElement(((ProvisionException) listener.capture.get()).getErrorMessages()) + .getMessage()); assertEquals(0, listener.afterProvision); } public void testListenerCallsProvisionTwice() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new ProvisionTwice()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new ProvisionTwice()); + } + }); try { injector.getInstance(Foo.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), - "1) Error notifying ProvisionListener " + ProvisionTwice.class.getName() - + " of " + Foo.class.getName(), + assertContains( + pe.getMessage(), + "1) Error notifying ProvisionListener " + + ProvisionTwice.class.getName() + + " of " + + Foo.class.getName(), "Reason: java.lang.IllegalStateException: Already provisioned in this listener.", "while locating " + Foo.class.getName()); - assertEquals("Already provisioned in this listener.", pe.getCause().getMessage()); + assertEquals("Already provisioned in this listener.", pe.getCause().getMessage()); } } - + public void testCachedInScopePreventsProvisionNotify() { final Counter count1 = new Counter(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), count1); - bind(Foo.class).in(Scopes.SINGLETON); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), count1); + bind(Foo.class).in(Scopes.SINGLETON); + } + }); Foo foo = injector.getInstance(Foo.class); assertNotNull(foo); assertEquals(1, count1.count); - + // not notified the second time because nothing is provisioned // (it's cached in the scope) count1.count = 0; assertSame(foo, injector.getInstance(Foo.class)); assertEquals(0, count1.count); } - + public void testCombineAllBindListenerCalls() { final Counter count1 = new Counter(); final Counter count2 = new Counter(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), count1); - bindListener(Matchers.any(), count2); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), count1); + bindListener(Matchers.any(), count2); + } + }); assertNotNull(injector.getInstance(Foo.class)); assertEquals(1, count1.count); assertEquals(1, count2.count); } - + public void testNotifyEarlyListenersIfFailBeforeProvision() { final Counter count1 = new Counter(); final Counter count2 = new Counter(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), count1, new FailBeforeProvision(), count2); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), count1, new FailBeforeProvision(), count2); + } + }); try { injector.getInstance(Foo.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), - "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName() - + " of " + Foo.class.getName(), + assertContains( + pe.getMessage(), + "1) Error notifying ProvisionListener " + + FailBeforeProvision.class.getName() + + " of " + + Foo.class.getName(), "Reason: java.lang.RuntimeException: boo", "while locating " + Foo.class.getName()); assertEquals("boo", pe.getCause().getMessage()); - + assertEquals(1, count1.count); assertEquals(0, count2.count); } } - + public void testNotifyLaterListenersIfFailAfterProvision() { final Counter count1 = new Counter(); final Counter count2 = new Counter(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), count1, new FailAfterProvision(), count2); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), count1, new FailAfterProvision(), count2); + } + }); try { injector.getInstance(Foo.class); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertEquals(1, pe.getErrorMessages().size()); - assertContains(pe.getMessage(), - "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName() - + " of " + Foo.class.getName(), + assertContains( + pe.getMessage(), + "1) Error notifying ProvisionListener " + + FailAfterProvision.class.getName() + + " of " + + Foo.class.getName(), "Reason: java.lang.RuntimeException: boo", "while locating " + Foo.class.getName()); assertEquals("boo", pe.getCause().getMessage()); - + assertEquals(1, count1.count); assertEquals(1, count2.count); } } - + public void testNotifiedKeysOfAllBindTypes() { final Capturer capturer = new Capturer(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), capturer); - bind(Foo.class).annotatedWith(named("pk")).toProvider(FooP.class); - try { - bind(Foo.class).annotatedWith(named("cxtr")).toConstructor(Foo.class.getDeclaredConstructor()); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - bind(LinkedFoo.class).to(Foo.class); - bind(Interface.class).toInstance(new Implementation()); - bindConstant().annotatedWith(named("constant")).to("MyConstant"); - } - - @Provides @Named("pi") Foo provideFooBar() { - return new Foo(); - } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), capturer); + bind(Foo.class).annotatedWith(named("pk")).toProvider(FooP.class); + try { + bind(Foo.class) + .annotatedWith(named("cxtr")) + .toConstructor(Foo.class.getDeclaredConstructor()); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + bind(LinkedFoo.class).to(Foo.class); + bind(Interface.class).toInstance(new Implementation()); + bindConstant().annotatedWith(named("constant")).to("MyConstant"); + } + + @Provides + @Named("pi") + Foo provideFooBar() { + return new Foo(); + } + }); + // toInstance & constant bindings are notified in random order, at the very beginning. assertEquals( ImmutableSet.of(Key.get(Interface.class), Key.get(String.class, named("constant"))), capturer.getAsSetAndClear()); - + // simple binding assertNotNull(injector.getInstance(Foo.class)); assertEquals(of(Key.get(Foo.class)), capturer.getAndClear()); - + // provider key binding -- notifies about provider & the object, always assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk")))); assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear()); assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk")))); assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear()); - + // JIT provider key binding -- notifies about provider & the object, always assertNotNull(injector.getInstance(JitFoo2.class)); assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear()); assertNotNull(injector.getInstance(JitFoo2.class)); assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear()); - + // provider instance binding -- just the object (not the provider) assertNotNull(injector.getInstance(Key.get(Foo.class, named("pi")))); assertEquals(of(Key.get(Foo.class, named("pi"))), capturer.getAndClear()); - + // toConstructor binding assertNotNull(injector.getInstance(Key.get(Foo.class, named("cxtr")))); assertEquals(of(Key.get(Foo.class, named("cxtr"))), capturer.getAndClear()); - + // linked binding -- notifies about the target (that's what's provisioned), not the link assertNotNull(injector.getInstance(LinkedFoo.class)); assertEquals(of(Key.get(Foo.class)), capturer.getAndClear()); @@ -357,20 +435,24 @@ assertNotNull(injector.getInstance(JitFoo.class)); assertEquals(of(Key.get(Foo.class)), capturer.getAndClear()); } - + public void testSingletonMatcher() { final Counter counter = new Counter(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(new AbstractMatcher>() { - @Override - public boolean matches(Binding t) { - return Scopes.isSingleton(t); - } - }, counter); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + new AbstractMatcher>() { + @Override + public boolean matches(Binding t) { + return Scopes.isSingleton(t); + } + }, + counter); + } + }); assertEquals(0, counter.count); // no increment for getting Many. injector.getInstance(Many.class); @@ -379,81 +461,102 @@ injector.getInstance(Sole.class); assertEquals(1, counter.count); } - + public void testCallingBindingDotGetProviderDotGet() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new ProvisionListener() { - @Override - public void onProvision(ProvisionInvocation provision) { - provision.getBinding().getProvider().get(); // AGH! - } - }); - } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + Matchers.any(), + new ProvisionListener() { + @Override + public void onProvision(ProvisionInvocation provision) { + provision.getBinding().getProvider().get(); // AGH! + } + }); + } + }); + try { injector.getInstance(Sole.class); fail(); - } catch(ProvisionException expected) { + } catch (ProvisionException expected) { // We don't really care what kind of error you get, we only care you get an error. } - + try { injector.getInstance(Many.class); fail(); - } catch(ProvisionException expected) { + } catch (ProvisionException expected) { // We don't really care what kind of error you get, we only care you get an error. } } - + interface Interface {} - class Implementation implements Interface {} - - @Singleton static class Sole {} + + static class Implementation implements Interface {} + + @Singleton + static class Sole {} + static class Many {} - - @ImplementedBy(Foo.class) static interface JitFoo {} - @ProvidedBy(JitFoo2P.class) static class JitFoo2 {} + + @ImplementedBy(Foo.class) + static interface JitFoo {} + + @ProvidedBy(JitFoo2P.class) + static class JitFoo2 {} + static interface LinkedFoo {} + static class Foo implements JitFoo, LinkedFoo {} + static class FooP implements Provider { + @Override public Foo get() { return new Foo(); } } + static class JitFoo2P implements Provider { + @Override public JitFoo2 get() { return new JitFoo2(); } } - + static class FooBomb { FooBomb() { throw new RuntimeException("Retry, Abort, Fail"); } } - + static class DependsOnFooBombInField { @Inject FooBomb fooBomb; } - + static class DependsOnFooBombInCxtor { - @Inject DependsOnFooBombInCxtor(FooBomb fooBomb) {} + @Inject + DependsOnFooBombInCxtor(FooBomb fooBomb) {} } - + private static class Counter implements ProvisionListener { int count = 0; + + @Override public void onProvision(ProvisionInvocation provision) { count++; } } - + private static class CountAndCaptureExceptionListener implements ProvisionListener { int beforeProvision = 0; int afterProvision = 0; - AtomicReference capture = new AtomicReference(); + AtomicReference capture = new AtomicReference<>(); + + @Override public void onProvision(ProvisionInvocation provision) { beforeProvision++; try { @@ -465,9 +568,11 @@ afterProvision++; } } - + private static class Capturer implements ProvisionListener { - List keys = Lists.newArrayList(); + List keys = Lists.newArrayList(); + + @Override public void onProvision(ProvisionInvocation provision) { keys.add(provision.getBinding().getKey()); T provisioned = provision.provision(); @@ -477,19 +582,20 @@ // with a toConstructor binding... but we don't use that in our tests. if (provision.getBinding() instanceof InstanceBinding) { Class expected = provision.getBinding().getKey().getRawType(); - assertTrue("expected instanceof: " + expected + ", but was: " + provisioned, + assertTrue( + "expected instanceof: " + expected + ", but was: " + provisioned, expected.isInstance(provisioned)); } else { assertEquals(provision.getBinding().getKey().getRawType(), provisioned.getClass()); } } - + Set getAsSetAndClear() { Set copy = ImmutableSet.copyOf(keys); keys.clear(); return copy; } - + List getAndClear() { List copy = ImmutableList.copyOf(keys); keys.clear(); @@ -498,51 +604,62 @@ } private static class FailBeforeProvision implements ProvisionListener { + @Override public void onProvision(ProvisionInvocation provision) { throw new RuntimeException("boo"); } - } + } + private static class FailAfterProvision implements ProvisionListener { + @Override public void onProvision(ProvisionInvocation provision) { provision.provision(); throw new RuntimeException("boo"); } - } + } + private static class JustProvision implements ProvisionListener { + @Override public void onProvision(ProvisionInvocation provision) { provision.provision(); } - } + } + private static class NoProvision implements ProvisionListener { - public void onProvision(ProvisionInvocation provision) { - } + @Override + public void onProvision(ProvisionInvocation provision) {} } + private static class ProvisionTwice implements ProvisionListener { + @Override public void onProvision(ProvisionInvocation provision) { provision.provision(); provision.provision(); } } - + private static class ChainAsserter implements ProvisionListener { private final List> provisionList; + private final List> expected; - + public ChainAsserter(List> provisionList, Iterable> expected) { this.provisionList = provisionList; this.expected = ImmutableList.copyOf(expected); } - + + @Override public void onProvision(ProvisionInvocation provision) { List> actual = Lists.newArrayList(); - for (DependencyAndSource dep : provision.getDependencyChain()) { + for (com.google.inject.spi.DependencyAndSource dep : provision.getDependencyChain()) { actual.add(dep.getDependency().getKey().getRawType()); } assertEquals(expected, actual); + provisionList.add(provision.getBinding().getKey().getRawType()); } } - + private static Matcher> keyMatcher(final Class clazz) { return new AbstractMatcher>() { @Override @@ -551,55 +668,62 @@ } }; } - + @SuppressWarnings("unchecked") public void testDependencyChain() { final List> pList = Lists.newArrayList(); final List> totalList = Lists.newArrayList(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Instance.class).toInstance(new Instance()); - bind(B.class).to(BImpl.class); - bind(D.class).toProvider(DP.class); - - bindListener(Matchers.any(), new ProvisionListener() { - public void onProvision(ProvisionInvocation provision) { - totalList.add(provision.getBinding().getKey().getRawType()); - } - }); - - // Build up a list of asserters for our dependency chains. - ImmutableList.Builder> chain = ImmutableList.builder(); - chain.add(Instance.class); - bindListener(keyMatcher(Instance.class), new ChainAsserter(pList, chain.build())); - - chain.add(A.class); - bindListener(keyMatcher(A.class), new ChainAsserter(pList, chain.build())); - - chain.add(B.class).add(BImpl.class); - bindListener(keyMatcher(BImpl.class), new ChainAsserter(pList, chain.build())); - - chain.add(C.class); - bindListener(keyMatcher(C.class), new ChainAsserter(pList, chain.build())); - - // the chain has D before DP even though DP is provisioned & notified first - // because we do DP because of D, and need DP to provision D. - chain.add(D.class).add(DP.class); - bindListener(keyMatcher(D.class), new ChainAsserter(pList, chain.build())); - bindListener(keyMatcher(DP.class), new ChainAsserter(pList, chain.build())); - - chain.add(E.class); - bindListener(keyMatcher(E.class), new ChainAsserter(pList, chain.build())); - - chain.add(F.class); - bindListener(keyMatcher(F.class), new ChainAsserter(pList, chain.build())); - } - @Provides C c(D d) { - return new C() {}; - } - }); - Instance instance = injector.getInstance(Instance.class); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Instance.class).toInstance(new Instance()); + bind(B.class).to(BImpl.class); + bind(D.class).toProvider(DP.class); + + bindListener( + Matchers.any(), + new ProvisionListener() { + @Override + public void onProvision(ProvisionInvocation provision) { + totalList.add(provision.getBinding().getKey().getRawType()); + } + }); + + // Build up a list of asserters for our dependency chains. + ImmutableList.Builder> chain = ImmutableList.builder(); + chain.add(Instance.class); + bindListener(keyMatcher(Instance.class), new ChainAsserter(pList, chain.build())); + + chain.add(A.class); + bindListener(keyMatcher(A.class), new ChainAsserter(pList, chain.build())); + + chain.add(B.class).add(BImpl.class); + bindListener(keyMatcher(BImpl.class), new ChainAsserter(pList, chain.build())); + + chain.add(C.class); + bindListener(keyMatcher(C.class), new ChainAsserter(pList, chain.build())); + + // the chain has D before DP even though DP is provisioned & notified first + // because we do DP because of D, and need DP to provision D. + chain.add(D.class).add(DP.class); + bindListener(keyMatcher(D.class), new ChainAsserter(pList, chain.build())); + bindListener(keyMatcher(DP.class), new ChainAsserter(pList, chain.build())); + + chain.add(E.class); + bindListener(keyMatcher(E.class), new ChainAsserter(pList, chain.build())); + + chain.add(F.class); + bindListener(keyMatcher(F.class), new ChainAsserter(pList, chain.build())); + } + + @Provides + C c(D d) { + return new C() {}; + } + }); + injector.getInstance(Instance.class); // make sure we're checking all of the chain asserters.. assertEquals( of(Instance.class, A.class, BImpl.class, C.class, DP.class, D.class, E.class, F.class), @@ -607,116 +731,147 @@ // and make sure that nothing else was notified that we didn't expect. assertEquals(totalList, pList); } - + public void testModuleRequestInjection() { - final AtomicBoolean notified = new AtomicBoolean(); - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - requestInjection(new Object() { - @Inject Foo foo; + final AtomicBoolean notified = new AtomicBoolean(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestInjection( + new Object() { + @Inject Foo foo; + }); + bindListener( + Matchers.any(), + new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified)); + } }); - bindListener(Matchers.any(), - new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified)); - } - }); assertTrue(notified.get()); } - + public void testToProviderInstance() { - final AtomicBoolean notified = new AtomicBoolean(); - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Object.class).toProvider(new Provider() { - @Inject Foo foo; - public Object get() { - return null; + final AtomicBoolean notified = new AtomicBoolean(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Object.class) + .toProvider( + new Provider() { + @Inject Foo foo; + + @Override + public Object get() { + return null; + } + }); + bindListener( + Matchers.any(), + new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified)); } }); - bindListener(Matchers.any(), - new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified)); - } - }); assertTrue(notified.get()); } - + public void testInjectorInjectMembers() { - final Object object = new Object() { - @Inject Foo foo; - }; - final AtomicBoolean notified = new AtomicBoolean(); - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), - new SpecialChecker(Foo.class, object.getClass().getName(), notified)); - } - }).injectMembers(object); + final Object object = + new Object() { + @Inject Foo foo; + }; + final AtomicBoolean notified = new AtomicBoolean(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + Matchers.any(), + new SpecialChecker(Foo.class, object.getClass().getName(), notified)); + } + }) + .injectMembers(object); assertTrue(notified.get()); } - + private static class SpecialChecker implements ProvisionListener { private final Class notifyType; + private final String firstSource; + private final AtomicBoolean notified; - + public SpecialChecker(Class notifyType, String firstSource, AtomicBoolean notified) { this.notifyType = notifyType; this.firstSource = firstSource; this.notified = notified; } - + + @Override public void onProvision(ProvisionInvocation provision) { notified.set(true); - assertEquals(notifyType, provision.getBinding().getKey().getRawType()); + assertEquals(notifyType, provision.getBinding().getKey().getRawType()); assertEquals(2, provision.getDependencyChain().size()); - + assertNull(provision.getDependencyChain().get(0).getDependency()); assertContains(provision.getDependencyChain().get(0).getBindingSource(), firstSource); - - assertEquals(notifyType, - provision.getDependencyChain().get(1).getDependency().getKey().getRawType()); - assertContains(provision.getDependencyChain().get(1).getBindingSource(), + + assertEquals( + notifyType, provision.getDependencyChain().get(1).getDependency().getKey().getRawType()); + assertContains( + provision.getDependencyChain().get(1).getBindingSource(), notifyType.getName() + ".class("); + } } - + private static class Instance { @Inject A a; } + private static class A { - @Inject A(B b) {} + @Inject + A(B b) {} } + private interface B {} + private static class BImpl implements B { - @Inject void inject(C c) {} + @Inject + void inject(C c) {} } + private interface C {} + private interface D {} + private static class DP implements Provider { @Inject Provider ep; + + @Override public D get() { ep.get(); return new D() {}; } } + private static class E { @SuppressWarnings("unused") - @Inject F f; - } - private static class F { + @Inject + F f; } + private static class F {} + public void testBindToInjectorWithListeningGivesSaneException() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new Counter()); - bind(Injector.class).toProvider(Providers.of(null)); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new Counter()); + bind(Injector.class).toProvider(Providers.of(null)); + } + }); fail(); } catch (CreationException ce) { assertContains( @@ -725,39 +880,44 @@ } public void testProvisionIsNotifiedAfterContextsClear() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), new ProvisionListener() { - @Override - public void onProvision(ProvisionInvocation provision) { - Object provisioned = provision.provision(); - if (provisioned instanceof X) { - ((X)provisioned).init(); - } else if (provisioned instanceof Y) { - X.createY = false; - ((Y)provisioned).init(); - } - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + Matchers.any(), + new ProvisionListener() { + @Override + public void onProvision(ProvisionInvocation provision) { + Object provisioned = provision.provision(); + if (provisioned instanceof X) { + ((X) provisioned).init(); + } else if (provisioned instanceof Y) { + X.createY = false; + ((Y) provisioned).init(); + } + } + }); + } + }); X.createY = true; X x = injector.getInstance(X.class); assertNotSame(x, x.y.x); - assertFalse("x.ID: " + x.ID + ", x.y.x.iD: " + x.y.x.ID, x.ID == x.y.x.ID); + assertFalse("x.id: " + x.id + ", x.y.x.id: " + x.y.x.id, x.id == x.y.x.id); } private static class X { - final static AtomicInteger COUNTER = new AtomicInteger(); + static final AtomicInteger COUNTER = new AtomicInteger(); static boolean createY; - final int ID = COUNTER.getAndIncrement(); + final int id = COUNTER.getAndIncrement(); final Provider yProvider; Y y; - @Inject X(Provider yProvider) { + @Inject + X(Provider yProvider) { this.yProvider = yProvider; } @@ -772,7 +932,8 @@ final Provider xProvider; X x; - @Inject Y(Provider xProvider) { + @Inject + Y(Provider xProvider) { this.xProvider = xProvider; } @@ -780,16 +941,18 @@ this.x = xProvider.get(); } } - + public void testDeDuplicateProvisionListeners() { final Counter counter = new Counter(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(Matchers.any(), counter); - bindListener(Matchers.any(), counter); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), counter); + bindListener(Matchers.any(), counter); + } + }); injector.getInstance(Many.class); assertEquals("ProvisionListener not de-duplicated", 1, counter.count); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ReflectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/ReflectionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ReflectionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ReflectionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,27 +19,27 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.spi.ElementSource; - -import junit.framework.TestCase; - import java.lang.annotation.Retention; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ReflectionTest extends TestCase { @Retention(RUNTIME) - @BindingAnnotation @interface I {} + @BindingAnnotation + @interface I {} public void testNormalBinding() throws CreationException { final Foo foo = new Foo(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class).toInstance(foo); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class).toInstance(foo); + } + }); Binding fooBinding = injector.getBinding(Key.get(Foo.class)); assertSame(foo, fooBinding.getProvider().get()); @@ -49,11 +49,14 @@ } public void testConstantBinding() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindConstant().annotatedWith(I.class).to(5); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(I.class).to(5); + } + }); Binding i = injector.getBinding(Key.get(int.class, I.class)); assertEquals(5, i.getProvider().get()); @@ -65,12 +68,15 @@ public void testLinkedBinding() throws CreationException { final Bar bar = new Bar(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Bar.class).toInstance(bar); - bind(Key.get(Foo.class)).to(Key.get(Bar.class)); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Bar.class).toInstance(bar); + bind(Key.get(Foo.class)).to(Key.get(Bar.class)); + } + }); Binding fooBinding = injector.getBinding(Key.get(Foo.class)); assertSame(bar, fooBinding.getProvider().get()); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/RequestInjectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/RequestInjectionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/RequestInjectionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/RequestInjectionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,21 +23,19 @@ import com.google.inject.matcher.Matchers; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; - -import junit.framework.TestCase; - import java.lang.annotation.Retention; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class RequestInjectionTest extends TestCase { @Retention(RUNTIME) - @BindingAnnotation @interface ForField {} + @BindingAnnotation + @interface ForField {} @Retention(RUNTIME) - @BindingAnnotation @interface ForMethod {} + @BindingAnnotation + @interface ForMethod {} @Override protected void setUp() throws Exception { @@ -49,14 +47,15 @@ public void testInjectMembers() { final HasInjections hi = new HasInjections(); - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(ForMethod.class).to("test"); - bindConstant().annotatedWith(ForField.class).to(5); - requestInjection(hi); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(ForMethod.class).to("test"); + bindConstant().annotatedWith(ForField.class).to(5); + requestInjection(hi); + } + }); assertEquals("test", hi.instanceMethod); assertEquals(5, hi.instanceField); @@ -65,31 +64,33 @@ } public void testInjectStatics() throws CreationException { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(ForMethod.class).to("test"); - bindConstant().annotatedWith(ForField.class).to(5); - requestStaticInjection(HasInjections.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(ForMethod.class).to("test"); + bindConstant().annotatedWith(ForField.class).to(5); + requestStaticInjection(HasInjections.class); + } + }); assertEquals("test", HasInjections.staticMethod); assertEquals(5, HasInjections.staticField); } - + public void testInjectMembersAndStatics() { final HasInjections hi = new HasInjections(); - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(ForMethod.class).to("test"); - bindConstant().annotatedWith(ForField.class).to(5); - requestStaticInjection(HasInjections.class); - requestInjection(hi); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(ForMethod.class).to("test"); + bindConstant().annotatedWith(ForField.class).to(5); + requestStaticInjection(HasInjections.class); + requestInjection(hi); + } + }); assertEquals("test", hi.instanceMethod); assertEquals(5, hi.instanceField); @@ -99,51 +100,63 @@ public void testValidationErrorOnInjectedMembers() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - requestInjection(new NeedsRunnable()); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestInjection(new NeedsRunnable()); + } + }); + fail("Expected CreationException"); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No implementation for java.lang.Runnable was bound", - "at " + NeedsRunnable.class.getName(), ".runnable(RequestInjectionTest.java:"); + "at " + NeedsRunnable.class.getName(), + ".runnable(RequestInjectionTest.java:"); } } public void testInjectionErrorOnInjectedMembers() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Runnable.class).toProvider(new Provider() { - public Runnable get() { - throw new UnsupportedOperationException(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Runnable.class) + .toProvider( + new Provider() { + @Override + public Runnable get() { + throw new UnsupportedOperationException(); + } + }); + requestInjection(new NeedsRunnable()); } }); - requestInjection(new NeedsRunnable()); - } - }); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error in custom provider, java.lang.UnsupportedOperationException", "for field at " + NeedsRunnable.class.getName() + ".runnable(RequestInjectionTest.java:", - "at " + getClass().getName(), getDeclaringSourcePart(getClass())); + "at " + getClass().getName(), + getDeclaringSourcePart(getClass())); } } public void testUserExceptionWhileInjectingInstance() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - requestInjection(new BlowsUpOnInject()); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestInjection(new BlowsUpOnInject()); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error injecting method, java.lang.UnsupportedOperationException: Pop", "at " + BlowsUpOnInject.class.getName() + ".injectInstance(RequestInjectionTest.java:"); } @@ -151,15 +164,17 @@ public void testUserExceptionWhileInjectingStatically() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - requestStaticInjection(BlowsUpOnInject.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(BlowsUpOnInject.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error injecting method, java.lang.UnsupportedOperationException: Snap", "at " + BlowsUpOnInject.class.getName() + ".injectStatically(RequestInjectionTest.java:"); } @@ -177,59 +192,72 @@ static String staticMethod; String instanceMethod; - @Inject static void setStaticMethod(@ForMethod String staticMethod) { + @Inject + static void setStaticMethod(@ForMethod String staticMethod) { HasInjections.staticMethod = staticMethod; } - @Inject void setInstanceS(@ForMethod String instanceS) { + @Inject + void setInstanceS(@ForMethod String instanceS) { this.instanceMethod = instanceS; } } static class BlowsUpOnInject { - @Inject void injectInstance() { + @Inject + void injectInstance() { throw new UnsupportedOperationException("Pop"); } - @Inject static void injectStatically() { + @Inject + static void injectStatically() { throw new UnsupportedOperationException("Snap"); } } - + /* * Tests that initializables of the same instance don't clobber * membersInjectors in InitializableReference, so that they ultimately * can be requested in any order. */ public void testEarlyInjectableReferencesWithSameIdentity() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - // Add a listener to trigger all toInstance bindings to get an Initializable. - bindListener(Matchers.any(), new TypeListener() { - @Override - public void hear(TypeLiteral type, TypeEncounter encounter) { - } - }); - - // Bind two different Keys to the IDENTITICAL object - // ORDER MATTERS! We want the String binding to push out the Object one - String fail = new String("better not fail!"); - bind(Object.class).toInstance(fail); - bind(String.class).toInstance(fail); - - // Then try to inject those objects in a requestInjection, - // letting us get into InjectableReference.get before it has - // finished running through all its injections. - // Each of these technically has its own InjectableReference internally. - // ORDER MATTERS!.. because Object is injected first, that InjectableReference - // attempts to process its members injector, but it wasn't initialized, - // because String pushed it out of the queue! - requestInjection(new Object() { - @SuppressWarnings("unused") @Inject Object obj; - @SuppressWarnings("unused") @Inject String str; - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + // Add a listener to trigger all toInstance bindings to get an Initializable. + bindListener( + Matchers.any(), + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) {} + }); + + // Bind two different Keys to the IDENTITICAL object + // ORDER MATTERS! We want the String binding to push out the Object one + String fail = new String("better not fail!"); + bind(Object.class).toInstance(fail); + bind(String.class).toInstance(fail); + + // Then try to inject those objects in a requestInjection, + // letting us get into InjectableReference.get before it has + // finished running through all its injections. + // Each of these technically has its own InjectableReference internally. + // ORDER MATTERS!.. because Object is injected first, that InjectableReference + // attempts to process its members injector, but it wasn't initialized, + // because String pushed it out of the queue! + requestInjection( + new Object() { + @SuppressWarnings("unused") + @Inject + Object obj; + + @SuppressWarnings("unused") + @Inject + String str; + }); + } + }); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java sisu-guice-4.2.0/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,189 +14,230 @@ * limitations under the License. */ - package com.google.inject; import junit.framework.TestCase; /** * Tests for {@link Binder#requireAtInjectOnConstructors()} - * + * * @author sameb@google.com (Sam Berlin) */ public class RequireAtInjectOnConstructorsTest extends TestCase { - + public void testNoCxtors_explicitBinding() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(NoCxtors.class); - binder().requireAtInjectOnConstructors(); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(NoCxtors.class); + binder().requireAtInjectOnConstructors(); + } + }); fail(); } catch (CreationException ce) { assertEquals(1, ce.getErrorMessages().size()); - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + NoCxtors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); + + NoCxtors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure"); } } - + public void testNoCxtors_jitBinding() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireAtInjectOnConstructors(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireAtInjectOnConstructors(); + } + }); try { injector.getInstance(NoCxtors.class); fail(); } catch (ConfigurationException ce) { - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + NoCxtors.class.getName() + " has no constructors annotated with @Inject", + + NoCxtors.class.getName() + + " has no constructors annotated with @Inject", "while locating " + NoCxtors.class.getName()); } } - + public void testNoCxtors_implicitBinding() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Interface.class).to(NoCxtors.class); - binder().requireAtInjectOnConstructors(); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Interface.class).to(NoCxtors.class); + binder().requireAtInjectOnConstructors(); + } + }); fail(); } catch (CreationException ce) { assertEquals(1, ce.getErrorMessages().size()); - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + NoCxtors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); + + NoCxtors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure"); } } - + public void testNoCxtors_inheritedByPrivateModules() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - binder().requireAtInjectOnConstructors(); - install(new PrivateModule() { + Guice.createInjector( + new AbstractModule() { @Override protected void configure() { - bind(NoCxtors.class); + binder().requireAtInjectOnConstructors(); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(NoCxtors.class); + } + }); } }); - } - }); fail(); } catch (CreationException ce) { assertEquals(1, ce.getErrorMessages().size()); - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + NoCxtors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); + + NoCxtors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure"); } } - + public void testNoCxtors_accumulatesAllErrors() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(NoCxtors.class); - bind(AnotherNoCxtors.class); - binder().requireAtInjectOnConstructors(); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(NoCxtors.class); + bind(AnotherNoCxtors.class); + binder().requireAtInjectOnConstructors(); + } + }); fail(); } catch (CreationException ce) { assertEquals(2, ce.getErrorMessages().size()); - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + NoCxtors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure", + + NoCxtors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure", "2) Explicit @Inject annotations are required on constructors, but " - + AnotherNoCxtors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); + + AnotherNoCxtors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure"); } } - + public void testNoCxtors_separateOptionsForPrivateModules() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(AnotherNoCxtors.class); - install(new PrivateModule() { + Guice.createInjector( + new AbstractModule() { @Override protected void configure() { - binder().requireAtInjectOnConstructors(); - bind(NoCxtors.class); + bind(AnotherNoCxtors.class); + install( + new PrivateModule() { + @Override + protected void configure() { + binder().requireAtInjectOnConstructors(); + bind(NoCxtors.class); + } + }); } }); - } - }); fail(); } catch (CreationException ce) { // This is testing that the parent module doesn't fail because it isn't included // in the error message. assertEquals(1, ce.getErrorMessages().size()); - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + NoCxtors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); + + NoCxtors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure"); } } - + public void testManyConstructorsButNoneWithAtInject() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(ManyConstructors.class); - binder().requireAtInjectOnConstructors(); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(ManyConstructors.class); + binder().requireAtInjectOnConstructors(); + } + }); fail(); } catch (CreationException ce) { assertEquals(1, ce.getErrorMessages().size()); - Asserts.assertContains(ce.getMessage(), + Asserts.assertContains( + ce.getMessage(), "1) Explicit @Inject annotations are required on constructors, but " - + ManyConstructors.class.getName() + " has no constructors annotated with @Inject", - "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); + + ManyConstructors.class.getName() + + " has no constructors annotated with @Inject", + "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", + "configure"); } } - + public void testRequireAtInjectStillAllowsToConstructorBindings() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - try { - bind(ManyConstructors.class) - .toConstructor(ManyConstructors.class.getDeclaredConstructor()); - } catch (Exception e) { - throw new RuntimeException(e); - } - binder().requireAtInjectOnConstructors(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + try { + bind(ManyConstructors.class) + .toConstructor(ManyConstructors.class.getDeclaredConstructor()); + } catch (Exception e) { + throw new RuntimeException(e); + } + binder().requireAtInjectOnConstructors(); + } + }); injector.getInstance(ManyConstructors.class); } - + private static interface Interface {} - private static class NoCxtors implements Interface {} + + private static class NoCxtors implements Interface {} + private static class AnotherNoCxtors {} + private static class ManyConstructors { - @SuppressWarnings("unused") ManyConstructors() {} - @SuppressWarnings("unused") ManyConstructors(String a) {} - @SuppressWarnings("unused") ManyConstructors(int a) {} + @SuppressWarnings("unused") + ManyConstructors() {} + + @SuppressWarnings("unused") + ManyConstructors(String a) {} + + @SuppressWarnings("unused") + ManyConstructors(int a) {} } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/ScopesTest.java sisu-guice-4.2.0/core/test/com/google/inject/ScopesTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/ScopesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/ScopesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,26 +22,27 @@ import static com.google.inject.name.Names.named; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import com.google.common.base.Joiner; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; +import com.google.common.collect.ListMultimap; import com.google.common.collect.Maps; +import com.google.inject.matcher.Matchers; import com.google.inject.name.Named; +import com.google.inject.spi.DefaultBindingScopingVisitor; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; +import com.google.inject.spi.Message; import com.google.inject.spi.PrivateElements; +import com.google.inject.spi.ProvisionListener; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -50,29 +51,32 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ScopesTest extends TestCase { static final long DEADLOCK_TIMEOUT_SECONDS = 1; - private final AbstractModule singletonsModule = new AbstractModule() { - @Override protected void configure() { - bind(BoundAsSingleton.class).in(Scopes.SINGLETON); - bind(AnnotatedSingleton.class); - bind(EagerSingleton.class).asEagerSingleton(); - bind(LinkedSingleton.class).to(RealLinkedSingleton.class); - bind(DependsOnJustInTimeSingleton.class); - bind(NotASingleton.class); - bind(ImplementedBySingleton.class).in(Scopes.SINGLETON); - bind(ProvidedBySingleton.class).in(Scopes.SINGLETON); - } - }; + private final AbstractModule singletonsModule = + new AbstractModule() { + @Override + protected void configure() { + bind(BoundAsSingleton.class).in(Scopes.SINGLETON); + bind(AnnotatedSingleton.class); + bind(EagerSingleton.class).asEagerSingleton(); + bind(LinkedSingleton.class).to(RealLinkedSingleton.class); + bind(DependsOnJustInTimeSingleton.class); + bind(NotASingleton.class); + bind(ImplementedBySingleton.class).in(Scopes.SINGLETON); + bind(ProvidedBySingleton.class).in(Scopes.SINGLETON); + } + }; - @Override protected void setUp() throws Exception { + @Override + protected void setUp() throws Exception { AnnotatedSingleton.nextInstanceId = 0; BoundAsSingleton.nextInstanceId = 0; EagerSingleton.nextInstanceId = 0; @@ -88,28 +92,24 @@ Injector injector = Guice.createInjector(singletonsModule); assertSame( - injector.getInstance(BoundAsSingleton.class), - injector.getInstance(BoundAsSingleton.class)); + injector.getInstance(BoundAsSingleton.class), injector.getInstance(BoundAsSingleton.class)); assertSame( injector.getInstance(AnnotatedSingleton.class), injector.getInstance(AnnotatedSingleton.class)); assertSame( - injector.getInstance(EagerSingleton.class), - injector.getInstance(EagerSingleton.class)); + injector.getInstance(EagerSingleton.class), injector.getInstance(EagerSingleton.class)); assertSame( - injector.getInstance(LinkedSingleton.class), - injector.getInstance(LinkedSingleton.class)); + injector.getInstance(LinkedSingleton.class), injector.getInstance(LinkedSingleton.class)); assertSame( injector.getInstance(JustInTimeSingleton.class), injector.getInstance(JustInTimeSingleton.class)); assertNotSame( - injector.getInstance(NotASingleton.class), - injector.getInstance(NotASingleton.class)); + injector.getInstance(NotASingleton.class), injector.getInstance(NotASingleton.class)); assertSame( injector.getInstance(ImplementedBySingleton.class), @@ -135,11 +135,14 @@ } public void testOverriddingAnnotation() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(AnnotatedSingleton.class).in(Scopes.NO_SCOPE); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(AnnotatedSingleton.class).in(Scopes.NO_SCOPE); + } + }); assertNotSame( injector.getInstance(AnnotatedSingleton.class), @@ -148,14 +151,17 @@ public void testScopingAnnotationsOnAbstractTypeViaBind() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(A.class).to(AImpl.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).to(AImpl.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), A.class.getName() + " is annotated with " + Singleton.class.getName(), "but scope annotations are not supported for abstract types.", "at " + A.class.getName() + ".class(ScopesTest.java:"); @@ -164,6 +170,7 @@ @Singleton interface A {} + static class AImpl implements A {} @Retention(RUNTIME) @@ -172,14 +179,17 @@ @Component @Singleton interface ComponentAnnotationTest {} + static class ComponentAnnotationTestImpl implements ComponentAnnotationTest {} public void testScopingAnnotationsOnAbstractTypeIsValidForComponent() { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(ComponentAnnotationTest.class).to(ComponentAnnotationTestImpl.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(ComponentAnnotationTest.class).to(ComponentAnnotationTestImpl.class); + } + }); } public void testScopingAnnotationsOnAbstractTypeViaImplementedBy() { @@ -187,15 +197,18 @@ Guice.createInjector().getInstance(D.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), D.class.getName() + " is annotated with " + Singleton.class.getName(), "but scope annotations are not supported for abstract types.", "at " + D.class.getName() + ".class(ScopesTest.java:"); } } - @Singleton @ImplementedBy(DImpl.class) + @Singleton + @ImplementedBy(DImpl.class) interface D {} + static class DImpl implements D {} public void testScopingAnnotationsOnAbstractTypeViaProvidedBy() { @@ -203,16 +216,20 @@ Guice.createInjector().getInstance(E.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), E.class.getName() + " is annotated with " + Singleton.class.getName(), "but scope annotations are not supported for abstract types.", "at " + E.class.getName() + ".class(ScopesTest.java:"); } } - @Singleton @ProvidedBy(EProvider.class) + @Singleton + @ProvidedBy(EProvider.class) interface E {} + static class EProvider implements Provider { + @Override public E get() { return null; } @@ -220,17 +237,21 @@ public void testScopeUsedButNotBound() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(B.class).in(CustomScoped.class); - bind(C.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).in(CustomScoped.class); + bind(C.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) No scope is bound to " + CustomScoped.class.getName(), - "at " + getClass().getName(), getDeclaringSourcePart(getClass()), + "at " + getClass().getName(), + getDeclaringSourcePart(getClass()), "2) No scope is bound to " + CustomScoped.class.getName(), "at " + C.class.getName() + ".class"); } @@ -274,12 +295,15 @@ public void testUnscopedProviderWorksOutsideOfRequestedScope() { final RememberProviderScope scope = new RememberProviderScope(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(CustomScoped.class, scope); - bind(List.class).to(ArrayList.class).in(CustomScoped.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(CustomScoped.class, scope); + bind(List.class).to(ArrayList.class).in(CustomScoped.class); + } + }); injector.getInstance(List.class); Provider listProvider = scope.providers.get(Key.get(List.class)); @@ -290,22 +314,28 @@ } static class OuterRuntimeModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new InnerRuntimeModule()); } } + static class InnerRuntimeModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bindScope(NotRuntimeRetainedScoped.class, Scopes.NO_SCOPE); } } + public void testScopeAnnotationWithoutRuntimeRetention() { try { Guice.createInjector(new OuterRuntimeModule()); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), - "1) Please annotate " + NotRuntimeRetainedScoped.class.getName() + assertContains( + expected.getMessage(), + "1) Please annotate " + + NotRuntimeRetainedScoped.class.getName() + " with @Retention(RUNTIME).", "at " + InnerRuntimeModule.class.getName() + getDeclaringSourcePart(getClass()), asModuleChain(OuterRuntimeModule.class, InnerRuntimeModule.class)); @@ -313,21 +343,26 @@ } static class OuterDeprecatedModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new InnerDeprecatedModule()); } } + static class InnerDeprecatedModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bindScope(Deprecated.class, Scopes.NO_SCOPE); } } + public void testBindScopeToAnnotationWithoutScopeAnnotation() { try { Guice.createInjector(new OuterDeprecatedModule()); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Please annotate " + Deprecated.class.getName() + " with @ScopeAnnotation.", "at " + InnerDeprecatedModule.class.getName() + getDeclaringSourcePart(getClass()), asModuleChain(OuterDeprecatedModule.class, InnerDeprecatedModule.class)); @@ -335,18 +370,23 @@ } static class OuterScopeModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new CustomNoScopeModule()); install(new CustomSingletonModule()); } } + static class CustomNoScopeModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bindScope(CustomScoped.class, Scopes.NO_SCOPE); } } + static class CustomSingletonModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bindScope(CustomScoped.class, Scopes.SINGLETON); } } @@ -356,23 +396,31 @@ Guice.createInjector(new OuterScopeModule()); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), - "1) Scope Scopes.NO_SCOPE is already bound to " + CustomScoped.class.getName() - + " at " + CustomNoScopeModule.class.getName() + getDeclaringSourcePart(getClass()), + assertContains( + expected.getMessage(), + "1) Scope Scopes.NO_SCOPE is already bound to " + + CustomScoped.class.getName() + + " at " + + CustomNoScopeModule.class.getName() + + getDeclaringSourcePart(getClass()), asModuleChain(OuterScopeModule.class, CustomNoScopeModule.class), "Cannot bind Scopes.SINGLETON.", - "at " + ScopesTest.class.getName(), getDeclaringSourcePart(getClass()), + "at " + ScopesTest.class.getName(), + getDeclaringSourcePart(getClass()), asModuleChain(OuterScopeModule.class, CustomSingletonModule.class)); } } public void testBindDuplicateScope() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(CustomScoped.class, Scopes.SINGLETON); - bindScope(CustomScoped.class, Scopes.SINGLETON); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(CustomScoped.class, Scopes.SINGLETON); + bindScope(CustomScoped.class, Scopes.SINGLETON); + } + }); assertSame( injector.getInstance(AnnotatedCustomScoped.class), @@ -380,33 +428,39 @@ } public void testDuplicateScopeAnnotations() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(CustomScoped.class, Scopes.NO_SCOPE); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(CustomScoped.class, Scopes.NO_SCOPE); + } + }); try { injector.getInstance(SingletonAndCustomScoped.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) More than one scope annotation was found: ", "while locating " + SingletonAndCustomScoped.class.getName()); } } public void testNullScopedAsASingleton() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() {} - - final Iterator values = Arrays.asList(null, "A").iterator(); - - @Provides @Singleton String provideString() { - return values.next(); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + + final Iterator values = Arrays.asList(null, "A").iterator(); + + @Provides + @Singleton + String provideString() { + return values.next(); + } + }); assertNull(injector.getInstance(String.class)); assertNull(injector.getInstance(String.class)); @@ -415,6 +469,8 @@ class RememberProviderScope implements Scope { final Map, Provider> providers = Maps.newHashMap(); + + @Override public Provider scope(Key key, Provider unscoped) { providers.put(key, unscoped); return unscoped; @@ -423,27 +479,34 @@ public void testSingletonAnnotationOnParameterizedType() { Injector injector = Guice.createInjector(); - assertSame(injector.getInstance(new Key>() {}), + assertSame( + injector.getInstance(new Key>() {}), injector.getInstance(new Key>() {})); - assertSame(injector.getInstance(new Key>() {}), + assertSame( + injector.getInstance(new Key>() {}), injector.getInstance(new Key>() {})); } - @ImplementedBy(Injected.class) public interface In {} - @Singleton public static class Injected implements In {} + @ImplementedBy(Injected.class) + public interface In {} + + @Singleton + public static class Injected implements In {} - @Target({ ElementType.TYPE, ElementType.METHOD }) + @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RUNTIME) @ScopeAnnotation public @interface CustomScoped {} - static final Scope CUSTOM_SCOPE = new Scope() { - public Provider scope(Key key, Provider unscoped) { - return Scopes.SINGLETON.scope(key, unscoped); - } - }; + static final Scope CUSTOM_SCOPE = + new Scope() { + @Override + public Provider scope(Key key, Provider unscoped) { + return Scopes.SINGLETON.scope(key, unscoped); + } + }; - @Target({ ElementType.TYPE, ElementType.METHOD }) + @Target({ElementType.TYPE, ElementType.METHOD}) @ScopeAnnotation public @interface NotRuntimeRetainedScoped {} @@ -489,7 +552,8 @@ final int instanceId = nextInstanceId++; } - @SuppressWarnings("MoreThanOneScopeAnnotationOnClass") // suppress compiler error for testing + // suppress compiler error for testing + @SuppressWarnings({"MoreThanOneScopeAnnotationOnClass", "multiple-scope"}) @Singleton @CustomScoped static class SingletonAndCustomScoped {} @@ -509,21 +573,25 @@ } static class ImplementationProvider implements Provider { + @Override public ProvidedBySingleton get() { return new ProvidedBySingleton(); } } public void testScopeThatGetsAnUnrelatedObject() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(B.class); - bind(C.class); - ProviderGetScope providerGetScope = new ProviderGetScope(); - requestInjection(providerGetScope); - bindScope(CustomScoped.class, providerGetScope); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class); + bind(C.class); + ProviderGetScope providerGetScope = new ProviderGetScope(); + requestInjection(providerGetScope); + bindScope(CustomScoped.class, providerGetScope); + } + }); injector.getInstance(C.class); } @@ -531,8 +599,10 @@ class ProviderGetScope implements Scope { @Inject Provider bProvider; + @Override public Provider scope(Key key, final Provider unscoped) { return new Provider() { + @Override public T get() { bProvider.get(); return unscoped.get(); @@ -552,27 +622,34 @@ final Key h = Key.get(Object.class, named("H")); final Key i = Key.get(String.class, named("I")); - Module singletonBindings = new AbstractModule() { - @Override protected void configure() { - bind(a).to(b); - bind(b).to(c); - bind(c).toProvider(Providers.of("c")).in(Scopes.SINGLETON); - bind(d).toInstance("d"); - bind(e).toProvider(Providers.of("e")).asEagerSingleton(); - bind(f).toProvider(Providers.of("f")).in(Singleton.class); - bind(h).to(AnnotatedSingleton.class); - install(new PrivateModule() { - @Override protected void configure() { - bind(i).toProvider(Providers.of("i")).in(Singleton.class); - expose(i); + Module singletonBindings = + new AbstractModule() { + @Override + protected void configure() { + bind(a).to(b); + bind(b).to(c); + bind(c).toProvider(Providers.of("c")).in(Scopes.SINGLETON); + bind(d).toInstance("d"); + bind(e).toProvider(Providers.of("e")).asEagerSingleton(); + bind(f).toProvider(Providers.of("f")).in(Singleton.class); + bind(h).to(AnnotatedSingleton.class); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(i).toProvider(Providers.of("i")).in(Singleton.class); + expose(i); + } + }); } - }); - } - @Provides @Named("G") @Singleton String provideG() { - return "g"; - } - }; + @Provides + @Named("G") + @Singleton + String provideG() { + return "g"; + } + }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(singletonBindings); @@ -607,25 +684,32 @@ final Key e = Key.get(String.class, named("E")); final Key f = Key.get(String.class, named("F")); - Module singletonBindings = new AbstractModule() { - @Override protected void configure() { - bind(a).to(b); - bind(b).to(c); - bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); - bind(d).toProvider(Providers.of("d")).in(CustomScoped.class); - bindScope(CustomScoped.class, Scopes.NO_SCOPE); - install(new PrivateModule() { - @Override protected void configure() { - bind(f).toProvider(Providers.of("f")).in(CustomScoped.class); - expose(f); + Module singletonBindings = + new AbstractModule() { + @Override + protected void configure() { + bind(a).to(b); + bind(b).to(c); + bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); + bind(d).toProvider(Providers.of("d")).in(CustomScoped.class); + bindScope(CustomScoped.class, Scopes.NO_SCOPE); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(f).toProvider(Providers.of("f")).in(CustomScoped.class); + expose(f); + } + }); } - }); - } - @Provides @Named("E") @CustomScoped String provideE() { - return "e"; - } - }; + @Provides + @Named("E") + @CustomScoped + String provideE() { + return "e"; + } + }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(singletonBindings); @@ -655,26 +739,33 @@ final Key f = Key.get(Object.class, named("F")); final Key g = Key.get(String.class, named("G")); - Module customBindings = new AbstractModule() { - @Override protected void configure() { - bindScope(CustomScoped.class, CUSTOM_SCOPE); - bind(a).to(b); - bind(b).to(c); - bind(c).toProvider(Providers.of("c")).in(CUSTOM_SCOPE); - bind(d).toProvider(Providers.of("d")).in(CustomScoped.class); - bind(f).to(AnnotatedCustomScoped.class); - install(new PrivateModule() { - @Override protected void configure() { - bind(g).toProvider(Providers.of("g")).in(CustomScoped.class); - expose(g); + Module customBindings = + new AbstractModule() { + @Override + protected void configure() { + bindScope(CustomScoped.class, CUSTOM_SCOPE); + bind(a).to(b); + bind(b).to(c); + bind(c).toProvider(Providers.of("c")).in(CUSTOM_SCOPE); + bind(d).toProvider(Providers.of("d")).in(CustomScoped.class); + bind(f).to(AnnotatedCustomScoped.class); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(g).toProvider(Providers.of("g")).in(CustomScoped.class); + expose(g); + } + }); } - }); - } - @Provides @Named("E") @CustomScoped String provideE() { - return "e"; - } - }; + @Provides + @Named("E") + @CustomScoped + String provideE() { + return "e"; + } + }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(customBindings); @@ -707,27 +798,33 @@ final Key g = Key.get(String.class, named("G")); final Key h = Key.get(String.class, named("H")); - Module customBindings = new AbstractModule() { - @Override protected void configure() { - bind(a).to(b); - bind(b).to(c); - bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); - bind(d).toProvider(Providers.of("d")).in(Singleton.class); - install(new PrivateModule() { + Module customBindings = + new AbstractModule() { @Override protected void configure() { - bind(f).toProvider(Providers.of("f")).in(Singleton.class); - expose(f); + bind(a).to(b); + bind(b).to(c); + bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); + bind(d).toProvider(Providers.of("d")).in(Singleton.class); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(f).toProvider(Providers.of("f")).in(Singleton.class); + expose(f); + } + }); + bind(g).toInstance("g"); + bind(h).toProvider(Providers.of("h")).asEagerSingleton(); } - }); - bind(g).toInstance("g"); - bind(h).toProvider(Providers.of("h")).asEagerSingleton(); - } - @Provides @Named("E") @Singleton String provideE() { - return "e"; - } - }; + @Provides + @Named("E") + @Singleton + String provideE() { + return "e"; + } + }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(customBindings); @@ -763,9 +860,9 @@ Binding binding = (Binding) element; builder.put(binding.getKey(), binding); } else if (element instanceof PrivateElements) { - PrivateElements privateElements = (PrivateElements)element; + PrivateElements privateElements = (PrivateElements) element; Map, Binding> privateBindings = indexBindings(privateElements.getElements()); - for(Key exposed : privateElements.getExposedKeys()) { + for (Key exposed : privateElements.getExposedKeys()) { builder.put(exposed, privateBindings.get(exposed)); } } @@ -809,8 +906,7 @@ */ static class S { - private S(int preventInjectionWithoutProvider) { - } + private S(int preventInjectionWithoutProvider) {} } /** @@ -823,14 +919,19 @@ volatile boolean barrierPassed = false; SBarrierProvider(int nThreads) { - barrier = new CyclicBarrier(nThreads, new Runnable() { - public void run() { - // would finish before returning from await() for any thread - barrierPassed = true; - } - }); + barrier = + new CyclicBarrier( + nThreads, + new Runnable() { + @Override + public void run() { + // would finish before returning from await() for any thread + barrierPassed = true; + } + }); } + @Override public S get() { try { if (!barrierPassed) { @@ -847,33 +948,41 @@ /** * Tests that different injectors should not affect each other. * - *

    This creates a second thread to work in parallel, to create two instances of - * {@link S} as the same time. If the lock if not granular enough (i.e. JVM-wide) - * then they would block each other creating a deadlock and await timeout. + *

    This creates a second thread to work in parallel, to create two instances of {@link S} as + * the same time. If the lock if not granular enough (i.e. JVM-wide) then they would block each + * other creating a deadlock and await timeout. */ public void testInjectorsDontDeadlockOnSingletons() throws Exception { final Provider provider = new SBarrierProvider(2); - final Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - Thread.currentThread().setName("S.class[1]"); - bind(S.class).toProvider(provider).in(Scopes.SINGLETON); - } - }); - final Injector secondInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - Thread.currentThread().setName("S.class[2]"); - bind(S.class).toProvider(provider).in(Scopes.SINGLETON); - } - }); - - Future secondThreadResult = Executors.newSingleThreadExecutor().submit(new Callable() { - public S call() { - return secondInjector.getInstance(S.class); - } - }); + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Thread.currentThread().setName("S.class[1]"); + bind(S.class).toProvider(provider).in(Scopes.SINGLETON); + } + }); + final Injector secondInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + Thread.currentThread().setName("S.class[2]"); + bind(S.class).toProvider(provider).in(Scopes.SINGLETON); + } + }); + + Future secondThreadResult = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public S call() { + return secondInjector.getInstance(S.class); + } + }); S firstS = injector.getInstance(S.class); S secondS = secondThreadResult.get(); @@ -882,18 +991,14 @@ } @ImplementedBy(GImpl.class) - interface G { - - } + interface G {} @Singleton static class GImpl implements G { final H h; - /** - * Relies on Guice implementation to inject S first and H later, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first and H later, which provides a barrier . */ @Inject GImpl(S synchronizationBarrier, H h) { this.h = h; @@ -901,18 +1006,14 @@ } @ImplementedBy(HImpl.class) - interface H { - - } + interface H {} @Singleton static class HImpl implements H { final G g; - /** - * Relies on Guice implementation to inject S first and G later, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first and G later, which provides a barrier . */ @Inject HImpl(S synchronizationBarrier, G g) throws Exception { this.g = g; @@ -922,35 +1023,45 @@ /** * Tests that injector can create two singletons with circular dependency in parallel. * - *

    This creates two threads to work in parallel, to create instances of - * {@link G} and {@link H}. Creation is synchronized by injection of {@link S}, - * first thread would block until second would be inside a singleton creation as well. + *

    This creates two threads to work in parallel, to create instances of {@link G} and {@link + * H}. Creation is synchronized by injection of {@link S}, first thread would block until second + * would be inside a singleton creation as well. * - *

    Both instances are created by sibling injectors, that share singleton scope. - * Verifies that exactly one circular proxy object is created. + *

    Both instances are created by sibling injectors, that share singleton scope. Verifies that + * exactly one circular proxy object is created. */ public void testSiblingInjectorGettingCircularSingletonsOneCircularProxy() throws Exception { final Provider provider = new SBarrierProvider(2); - final Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(S.class).toProvider(provider); - } - }); - - Future firstThreadResult = Executors.newSingleThreadExecutor().submit(new Callable() { - public G call() { - Thread.currentThread().setName("G.class"); - return injector.createChildInjector().getInstance(G.class); - } - }); - Future secondThreadResult = Executors.newSingleThreadExecutor().submit(new Callable() { - public H call() { - Thread.currentThread().setName("H.class"); - return injector.createChildInjector().getInstance(H.class); - } - }); + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(S.class).toProvider(provider); + } + }); + + Future firstThreadResult = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public G call() { + Thread.currentThread().setName("G.class"); + return injector.createChildInjector().getInstance(G.class); + } + }); + Future secondThreadResult = + Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public H call() { + Thread.currentThread().setName("H.class"); + return injector.createChildInjector().getInstance(H.class); + } + }); // using separate threads to avoid potential deadlock on the main thread // waiting twice as much to be sure that both would time out in their respective barriers @@ -974,143 +1085,115 @@ @Singleton static class I0 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - I0(I1 i) { - } + I0(I1 i) {} } @Singleton static class I1 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - I1(S synchronizationBarrier, I2 i) { - } + I1(S synchronizationBarrier, I2 i) {} } @Singleton static class I2 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - I2(J1 j) { - } + I2(J1 j) {} } @Singleton static class J0 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - J0(J1 j) { - } + J0(J1 j) {} } @Singleton static class J1 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - J1(S synchronizationBarrier, J2 j) { - } + J1(S synchronizationBarrier, J2 j) {} } @Singleton static class J2 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - J2(K1 k) { - } + J2(K1 k) {} } @Singleton static class K0 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - K0(K1 k) { - } + K0(K1 k) {} } @Singleton static class K1 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - K1(S synchronizationBarrier, K2 k) { - } + K1(S synchronizationBarrier, K2 k) {} } @Singleton static class K2 { - /** - * Relies on Guice implementation to inject S first, which provides a barrier . - */ + /** Relies on Guice implementation to inject S first, which provides a barrier . */ @Inject - K2(I1 i) { - } + K2(I1 i) {} } /** * Check that circular dependencies on non-interfaces are correctly resolved in multi-threaded * case. And that an error message constructed is a good one. * - *

    I0 -> I1 -> I2 -> J1 and J0 -> J1 -> J2 -> K1 and K0 -> K1 -> K2, - * where I1, J1 and K1 are created in parallel. + *

    I0 -> I1 -> I2 -> J1 and J0 -> J1 -> J2 -> K1 and K0 -> K1 -> K2, where I1, J1 and K1 are + * created in parallel. * *

    Creation is synchronized by injection of {@link S}, first thread would block until second * would be inside a singleton creation as well. * - *

    Verifies that provision results in an error, that spans two threads and - * has a dependency cycle. + *

    Verifies that provision results in an error, that spans two threads and has a dependency + * cycle. */ public void testUnresolvableSingletonCircularDependencyErrorMessage() throws Exception { final Provider provider = new SBarrierProvider(3); - final Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(S.class).toProvider(provider); - } - }); - - Future firstThreadResult = Executors.newSingleThreadExecutor().submit(new Callable() { - public I0 call() { - Thread.currentThread().setName("I0.class"); - return injector.getInstance(I0.class); - } - }); - Future secondThreadResult = Executors.newSingleThreadExecutor().submit(new Callable() { - public J0 call() { - Thread.currentThread().setName("J0.class"); - return injector.getInstance(J0.class); - } - }); - Future thirdThreadResult = Executors.newSingleThreadExecutor().submit(new Callable() { - public K0 call() { - Thread.currentThread().setName("K0.class"); - return injector.getInstance(K0.class); - } - }); + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(S.class).toProvider(provider); + } + }); + + FutureTask firstThreadResult = new FutureTask<>(fetchClass(injector, I0.class)); + Thread i0Thread = new Thread(firstThreadResult, "I0.class"); + // we need to call toString() now, because the toString() changes after the thread exits. + String i0ThreadString = i0Thread.toString(); + i0Thread.start(); + + FutureTask secondThreadResult = new FutureTask<>(fetchClass(injector, J0.class)); + Thread j0Thread = new Thread(secondThreadResult, "J0.class"); + String j0ThreadString = j0Thread.toString(); + j0Thread.start(); + + FutureTask thirdThreadResult = new FutureTask<>(fetchClass(injector, K0.class)); + Thread k0Thread = new Thread(thirdThreadResult, "K0.class"); + String k0ThreadString = k0Thread.toString(); + k0Thread.start(); // using separate threads to avoid potential deadlock on the main thread // waiting twice as much to be sure that both would time out in their respective barriers @@ -1137,56 +1220,160 @@ } // verification of error messages generated - assertEquals(firstException.getClass(), ProvisionException.class); - assertEquals(secondException.getClass(), ProvisionException.class); - assertEquals(thirdException.getClass(), ProvisionException.class); - List errorMessages = Lists.newArrayList( - String.format("%s\n%s\n%s", - firstException.getMessage(), secondException.getMessage(), thirdException.getMessage()) - .split("\\n\\n")); - Collections.sort(errorMessages, new Comparator() { - @Override - public int compare(String s1, String s2) { - return s2.length() - s1.length(); + List errors = new ArrayList<>(); + errors.addAll(((ProvisionException) firstException).getErrorMessages()); + errors.addAll(((ProvisionException) secondException).getErrorMessages()); + errors.addAll(((ProvisionException) thirdException).getErrorMessages()); + // We want to find the longest error reported for a cycle spanning multiple threads + Message spanningError = null; + for (Message error : errors) { + if (error.getMessage().contains("Encountered circular dependency spanning several threads")) { + if (spanningError == null + || spanningError.getMessage().length() < error.getMessage().length()) { + spanningError = error; + } } - }); - // this is brittle, but turns out that second to longest message spans all threads - String errorMessage = errorMessages.get(1); - assertContains(errorMessage, + } + if (spanningError == null) { + fail( + "Couldn't find multi thread circular dependency error: " + + Joiner.on("\n\n").join(errors)); + } + + String errorMessage = spanningError.getMessage(); + assertContains( + errorMessage, "Encountered circular dependency spanning several threads. Tried proxying " + this.getClass().getName()); - assertFalse("Both I0 and J0 can not be a part of a dependency cycle", + assertFalse( + "Both I0 and J0 can not be a part of a dependency cycle", errorMessage.contains(I0.class.getName()) && errorMessage.contains(J0.class.getName())); - assertFalse("Both J0 and K0 can not be a part of a dependency cycle", + assertFalse( + "Both J0 and K0 can not be a part of a dependency cycle", errorMessage.contains(J0.class.getName()) && errorMessage.contains(K0.class.getName())); - assertFalse("Both K0 and I0 can not be a part of a dependency cycle", + assertFalse( + "Both K0 and I0 can not be a part of a dependency cycle", errorMessage.contains(K0.class.getName()) && errorMessage.contains(I0.class.getName())); - List firstErrorLineForThread = new ArrayList(); - boolean addNextLine = false; + ListMultimap threadToSingletons = ArrayListMultimap.create(); + boolean inSingletonsList = false; + String currentThread = null; for (String errorLine : errorMessage.split("\\n")) { - if (errorLine.contains("in thread")) { - addNextLine = true; - firstErrorLineForThread.add(errorLine); - } else if (addNextLine) { - addNextLine = false; - firstErrorLineForThread.add(errorLine); + if (errorLine.startsWith("Thread[")) { + inSingletonsList = true; + currentThread = + errorLine.substring( + 0, errorLine.indexOf(" is holding locks the following singletons in the cycle:")); + } else if (inSingletonsList) { + if (errorLine.startsWith("\tat ")) { + inSingletonsList = false; + } else { + threadToSingletons.put(currentThread, errorLine); + } + } + } + + assertEquals("All threads should be in the cycle", 3, threadToSingletons.keySet().size()); + + // NOTE: J0,K0,I0 are not reported because their locks are not part of the cycle. + assertEquals( + threadToSingletons.get(j0ThreadString), + ImmutableList.of(J1.class.getName(), J2.class.getName(), K1.class.getName())); + assertEquals( + threadToSingletons.get(k0ThreadString), + ImmutableList.of(K1.class.getName(), K2.class.getName(), I1.class.getName())); + assertEquals( + threadToSingletons.get(i0ThreadString), + ImmutableList.of(I1.class.getName(), I2.class.getName(), J1.class.getName())); + } + + private static Callable fetchClass(final Injector injector, final Class clazz) { + return new Callable() { + @Override + public T call() { + return injector.getInstance(clazz); } + }; + } + + // Test for https://github.com/google/guice/issues/1032 + + public void testScopeAppliedByUserInsteadOfScoping() throws Exception { + Injector injector = + java.util.concurrent.Executors.newSingleThreadExecutor() + .submit( + new Callable() { + @Override + public Injector call() { + return Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(Matchers.any(), new ScopeMutatingProvisionListener()); + bind(SingletonClass.class); + } + }); + } + }) + .get(); + injector.getInstance(SingletonClass.class); // will fail here with NPE + } + + @Singleton + static class SingletonClass {} + + /** Uses Scope's public API to add a 'marker' into the provisioned instance's scope. */ + private static final class ScopeMutatingProvisionListener implements ProvisionListener { + private static class ScopeMarker { + static final Provider PROVIDER = + new Provider() { + @Override + public ScopeMarker get() { + return new ScopeMarker(); + } + }; + } + + @Override + public void onProvision(final ProvisionInvocation provisionInvocation) { + provisionInvocation.provision(); + provisionInvocation + .getBinding() + .acceptScopingVisitor( + new DefaultBindingScopingVisitor() { + @Override + public Void visitScope(Scope scope) { + scope.scope(Key.get(ScopeMarker.class), ScopeMarker.PROVIDER); + return null; + } + }); } - assertEquals("we expect to see [T1, $A, T2, $B, T3, $C, T1, $A]", - 8, firstErrorLineForThread.size()); - assertEquals("first four elements should be different", - 6, new HashSet(firstErrorLineForThread.subList(0, 6)).size()); - assertEquals(firstErrorLineForThread.get(6), firstErrorLineForThread.get(0)); - assertEquals(firstErrorLineForThread.get(7), firstErrorLineForThread.get(1)); - assertFalse("K0 thread could not be blocked by J0", - firstErrorLineForThread.get(0).contains("J0") - && firstErrorLineForThread.get(2).contains("K0")); - assertFalse("J0 thread could not be blocked by I0", - firstErrorLineForThread.get(0).contains("I0") - && firstErrorLineForThread.get(2).contains("J0")); - assertFalse("I0 thread could not be blocked by K0", - firstErrorLineForThread.get(0).contains("K0") - && firstErrorLineForThread.get(2).contains("I0")); + } + + public void testForInstanceOfNoScopingReturnsUnscoped() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(AImpl.class).in(Scopes.NO_SCOPE); + } + }); + + assertTrue( + injector + .getBinding(Key.get(AImpl.class)) + .acceptScopingVisitor( + new DefaultBindingScopingVisitor() { + @Override + protected Boolean visitOther() { + return false; + } + + @Override + public Boolean visitNoScoping() { + return true; + } + })); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/SerializationTest.java sisu-guice-4.2.0/core/test/com/google/inject/SerializationTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/SerializationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/SerializationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,28 +14,24 @@ * limitations under the License. */ - package com.google.inject; import static com.google.inject.Asserts.assertSimilarWhenReserialized; -import junit.framework.AssertionFailedError; -import junit.framework.TestCase; - import java.io.IOException; import java.io.Serializable; import java.util.List; +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class SerializationTest extends TestCase { public void testAbstractModuleIsSerializable() throws IOException { Asserts.reserialize(new MyAbstractModule()); } + static class MyAbstractModule extends AbstractModule implements Serializable { - protected void configure() {} } public void testCreationExceptionIsSerializable() throws IOException { @@ -44,11 +40,13 @@ private CreationException createCreationException() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(List.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(List.class); + } + }); throw new AssertionFailedError(); } catch (CreationException e) { return e; diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/BindingTargetVisitorTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/BindingTargetVisitorTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/BindingTargetVisitorTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/BindingTargetVisitorTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,10 @@ import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; - import junit.framework.TestCase; /** - * Simple little test that should compile. Ensures that wildcards on the - * generics are correct. + * Simple little test that should compile. Ensures that wildcards on the generics are correct. * * @author phopkins@gmail.com */ diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ElementApplyToTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ElementApplyToTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ElementApplyToTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ElementApplyToTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +18,7 @@ import com.google.inject.Module; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class ElementApplyToTest extends ElementsTest { @Override @@ -28,4 +26,4 @@ // convert from module to elements and back super.checkModule(Elements.getModule(Elements.getElements(module)), visitors); } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ElementSourceTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ElementSourceTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ElementSourceTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ElementSourceTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -8,37 +8,43 @@ import com.google.inject.Binding; import com.google.inject.BindingAnnotation; import com.google.inject.Module; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.List; +import junit.framework.TestCase; -/** - * Tests for {@link ElementSource}. - */ +/** Tests for {@link ElementSource}. */ public class ElementSourceTest extends TestCase { - private static final StackTraceElement BINDER_INSTALL = - new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", - "Unknown Source", 234 /* line number*/); - + private static final StackTraceElement BINDER_INSTALL = + new StackTraceElement( + "com.google.inject.spi.Elements$RecordingBinder", + "install", + "Unknown Source", + 234 /* line number*/); + public void testCallStackSize() { ModuleSource moduleSource = createModuleSource(); StackTraceElement[] bindingCallStack = new StackTraceElement[3]; - bindingCallStack[0] = new StackTraceElement( - "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 200); - bindingCallStack[1] = new StackTraceElement( - "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 100); - bindingCallStack[2] = new StackTraceElement( - "com.google.inject.spi.moduleSourceTest$C", "configure", "Unknown Source", 100); - ElementSource elementSource = new ElementSource( - null /* No original element source */, "" /* Don't care */, moduleSource, bindingCallStack); + bindingCallStack[0] = + new StackTraceElement( + "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 200); + bindingCallStack[1] = + new StackTraceElement( + "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 100); + bindingCallStack[2] = + new StackTraceElement( + "com.google.inject.spi.moduleSourceTest$C", "configure", "Unknown Source", 100); + ElementSource elementSource = + new ElementSource( + null /* No original element source */, + "" /* Don't care */, + moduleSource, + bindingCallStack); assertEquals(10 /* call stack size */, elementSource.getStackTrace().length); - } + } public void testGetCallStack_IntegrationTest() throws Exception { List elements = Elements.getElements(new A()); @@ -57,93 +63,87 @@ // Module A assertEquals("com.google.inject.spi.ElementSourceTest$A", moduleClassNames.get(2)); StackTraceElement[] callStack = elementSource.getStackTrace(); - switch(getIncludeStackTraceOption()) { + switch (getIncludeStackTraceOption()) { case OFF: // Check declaring source - StackTraceElement stackTraceElement = + StackTraceElement stackTraceElement = (StackTraceElement) elementSource.getDeclaringSource(); - assertEquals(new StackTraceElement( - "com.google.inject.spi.ElementSourceTest$C", "configure", null, -1), + assertEquals( + new StackTraceElement( + "com.google.inject.spi.ElementSourceTest$C", "configure", null, -1), stackTraceElement); // Check call stack assertEquals(0, callStack.length); return; case ONLY_FOR_DECLARING_SOURCE: - // Check call stack - assertEquals(0, callStack.length); - return; + // Check call stack + assertEquals(0, callStack.length); + return; case COMPLETE: // Check call stack int skippedCallStackSize = new Throwable().getStackTrace().length - 1; assertEquals(skippedCallStackSize + 15, elementSource.getStackTrace().length); - assertEquals("com.google.inject.spi.Elements$RecordingBinder", - callStack[0].getClassName()); - assertEquals("com.google.inject.spi.Elements$RecordingBinder", - callStack[1].getClassName()); - assertEquals("com.google.inject.AbstractModule", - callStack[2].getClassName()); + assertEquals( + "com.google.inject.spi.Elements$RecordingBinder", callStack[0].getClassName()); + assertEquals( + "com.google.inject.spi.Elements$RecordingBinder", callStack[1].getClassName()); + assertEquals("com.google.inject.AbstractModule", callStack[2].getClassName()); // Module C - assertEquals("com.google.inject.spi.ElementSourceTest$C", - callStack[3].getClassName()); - assertEquals("configure", - callStack[3].getMethodName()); - assertEquals("Unknown Source", - callStack[3].getFileName()); - assertEquals("com.google.inject.AbstractModule", - callStack[4].getClassName()); - assertEquals("com.google.inject.spi.Elements$RecordingBinder", - callStack[5].getClassName()); + assertEquals( + "com.google.inject.spi.ElementSourceTest$C", callStack[3].getClassName()); + assertEquals("configure", callStack[3].getMethodName()); + assertEquals("Unknown Source", callStack[3].getFileName()); + assertEquals("com.google.inject.AbstractModule", callStack[4].getClassName()); + assertEquals( + "com.google.inject.spi.Elements$RecordingBinder", callStack[5].getClassName()); // Module B - assertEquals("com.google.inject.spi.ElementSourceTest$B", - callStack[6].getClassName()); - assertEquals("com.google.inject.spi.Elements$RecordingBinder", - callStack[7].getClassName()); + assertEquals( + "com.google.inject.spi.ElementSourceTest$B", callStack[6].getClassName()); + assertEquals( + "com.google.inject.spi.Elements$RecordingBinder", callStack[7].getClassName()); // Module A - assertEquals("com.google.inject.AbstractModule", - callStack[8].getClassName()); - assertEquals("com.google.inject.spi.ElementSourceTest$A", - callStack[9].getClassName()); - assertEquals("com.google.inject.AbstractModule", - callStack[10].getClassName()); - assertEquals("com.google.inject.spi.Elements$RecordingBinder", - callStack[11].getClassName()); - assertEquals("com.google.inject.spi.Elements", - callStack[12].getClassName()); - assertEquals("com.google.inject.spi.Elements", - callStack[13].getClassName()); - assertEquals("com.google.inject.spi.ElementSourceTest", - callStack[14].getClassName()); + assertEquals("com.google.inject.AbstractModule", callStack[8].getClassName()); + assertEquals( + "com.google.inject.spi.ElementSourceTest$A", callStack[9].getClassName()); + assertEquals("com.google.inject.AbstractModule", callStack[10].getClassName()); + assertEquals( + "com.google.inject.spi.Elements$RecordingBinder", callStack[11].getClassName()); + assertEquals("com.google.inject.spi.Elements", callStack[12].getClassName()); + assertEquals("com.google.inject.spi.Elements", callStack[13].getClassName()); + assertEquals("com.google.inject.spi.ElementSourceTest", callStack[14].getClassName()); // Check modules index List indexes = elementSource.getModuleConfigurePositionsInStackTrace(); - assertEquals((int) indexes.get(0), 4); - assertEquals((int) indexes.get(1), 6); - assertEquals((int) indexes.get(2), 10); + assertEquals(4, (int) indexes.get(0)); + assertEquals(6, (int) indexes.get(1)); + assertEquals(10, (int) indexes.get(2)); return; } } } } fail("The test should not reach this line."); - } + } private ModuleSource createModuleSource() { // First module StackTraceElement[] partialCallStack = new StackTraceElement[1]; - partialCallStack[0] = BINDER_INSTALL; + partialCallStack[0] = BINDER_INSTALL; ModuleSource moduleSource = new ModuleSource(new A(), partialCallStack); - // Second module + // Second module partialCallStack = new StackTraceElement[2]; partialCallStack[0] = BINDER_INSTALL; - partialCallStack[1] = new StackTraceElement( - "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100); - moduleSource = moduleSource.createChild(new B(), partialCallStack); + partialCallStack[1] = + new StackTraceElement( + "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100); + moduleSource = moduleSource.createChild(new B(), partialCallStack); // Third module partialCallStack = new StackTraceElement[4]; partialCallStack[0] = BINDER_INSTALL; partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1); partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2); - partialCallStack[3] = new StackTraceElement( - "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200); + partialCallStack[3] = + new StackTraceElement( + "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200); return moduleSource.createChild(new C(), partialCallStack); } @@ -153,23 +153,23 @@ install(new B()); } } - + private static class B implements Module { @Override public void configure(Binder binder) { binder.install(new C()); } } - + @Retention(RUNTIME) - @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @BindingAnnotation - @interface SampleAnnotation { } + @interface SampleAnnotation {} private static class C extends AbstractModule { @Override public void configure() { bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("the value"); } - } + } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ElementsTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ElementsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ElementsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ElementsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,9 +47,6 @@ import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -67,10 +64,9 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class ElementsTest extends TestCase { // Binder fidelity tests @@ -78,75 +74,78 @@ public void testAddMessageErrorCommand() { checkModule( new AbstractModule() { - @Override protected void configure() { + @Override + protected void configure() { addError("Message %s %d %s", "A", 5, "C"); } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { + @Override + public Void visit(Message command) { assertEquals("Message A 5 C", command.getMessage()); assertNull(command.getCause()); - assertContains(command.getSources().toString(), + assertContains( + command.getSources().toString(), ElementsTest.class.getName(), getDeclaringSourcePart(ElementsTest.class)); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testAddThrowableErrorCommand() { checkModule( new AbstractModule() { + @Override protected void configure() { addError(new Exception("A")); } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { + @Override + public Void visit(Message command) { assertEquals("A", command.getCause().getMessage()); - assertEquals(command.getMessage(), - "An exception was caught and reported. Message: A"); + assertEquals("An exception was caught and reported. Message: A", command.getMessage()); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testErrorsAddedWhenExceptionsAreThrown() { checkModule( new AbstractModule() { + @Override protected void configure() { - install(new AbstractModule() { - protected void configure() { - throw new RuntimeException("Throwing RuntimeException in AbstractModule.configure()."); - } - }); + install( + new AbstractModule() { + @Override + protected void configure() { + throw new RuntimeException( + "Throwing RuntimeException in AbstractModule.configure()."); + } + }); addError("Code after the exception still gets executed"); } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { - assertEquals("Throwing RuntimeException in AbstractModule.configure().", + @Override + public Void visit(Message command) { + assertEquals( + "Throwing RuntimeException in AbstractModule.configure().", command.getCause().getMessage()); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { - assertEquals("Code after the exception still gets executed", - command.getMessage()); + @Override + public Void visit(Message command) { + assertEquals("Code after the exception still gets executed", command.getMessage()); return null; } - } - ); + }); } private T getInstance(Binding binding) { @@ -156,35 +155,36 @@ public void testBindConstantAnnotations() { checkModule( new AbstractModule() { + @Override protected void configure() { bindConstant().annotatedWith(SampleAnnotation.class).to("A"); bindConstant().annotatedWith(Names.named("Bee")).to("B"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); assertEquals("A", getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class, Names.named("Bee")), command.getKey()); assertEquals("B", getInstance(command)); return null; } - } - ); + }); } public void testBindConstantTypes() { checkModule( new AbstractModule() { + @Override protected void configure() { bindConstant().annotatedWith(Names.named("String")).to("A"); bindConstant().annotatedWith(Names.named("int")).to(2); @@ -199,118 +199,120 @@ bindConstant().annotatedWith(Names.named("Enum")).to(CoinSide.TAILS); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class, Names.named("String")), command.getKey()); assertEquals("A", getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Integer.class, Names.named("int")), command.getKey()); assertEquals(2, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Long.class, Names.named("long")), command.getKey()); assertEquals(3L, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Boolean.class, Names.named("boolean")), command.getKey()); assertEquals(false, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Double.class, Names.named("double")), command.getKey()); assertEquals(5.0d, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Float.class, Names.named("float")), command.getKey()); assertEquals(6.0f, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Short.class, Names.named("short")), command.getKey()); assertEquals((short) 7, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Character.class, Names.named("char")), command.getKey()); assertEquals('h', getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Byte.class, Names.named("byte")), command.getKey()); assertEquals((byte) 8, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Class.class, Names.named("Class")), command.getKey()); assertEquals(Iterator.class, getInstance(command)); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(CoinSide.class, Names.named("Enum")), command.getKey()); assertEquals(CoinSide.TAILS, getInstance(command)); return null; } - } - ); + }); } public void testBindKeysNoAnnotations() { - FailingElementVisitor keyChecker = new FailingElementVisitor() { - @Override public Void visit(Binding command) { - assertEquals(Key.get(String.class), command.getKey()); - return null; - } - }; + FailingElementVisitor keyChecker = + new FailingElementVisitor() { + @Override + public Void visit(Binding command) { + assertEquals(Key.get(String.class), command.getKey()); + return null; + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class).toInstance("A"); bind(new TypeLiteral() {}).toInstance("B"); @@ -319,74 +321,85 @@ }, keyChecker, keyChecker, - keyChecker - ); + keyChecker); } public void testBindKeysWithAnnotationType() { - FailingElementVisitor annotationChecker = new FailingElementVisitor() { - @Override public Void visit(Binding command) { - assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); - return null; - } - }; + FailingElementVisitor annotationChecker = + new FailingElementVisitor() { + @Override + public Void visit(Binding command) { + assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); + return null; + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("A"); - bind(new TypeLiteral() {}).annotatedWith(SampleAnnotation.class).toInstance("B"); + bind(new TypeLiteral() {}) + .annotatedWith(SampleAnnotation.class) + .toInstance("B"); } }, annotationChecker, - annotationChecker - ); + annotationChecker); } public void testBindKeysWithAnnotationInstance() { - FailingElementVisitor annotationChecker = new FailingElementVisitor() { - @Override public Void visit(Binding command) { - assertEquals(Key.get(String.class, Names.named("a")), command.getKey()); - return null; - } - }; - + FailingElementVisitor annotationChecker = + new FailingElementVisitor() { + @Override + public Void visit(Binding command) { + assertEquals(Key.get(String.class, Names.named("a")), command.getKey()); + return null; + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class).annotatedWith(Names.named("a")).toInstance("B"); bind(new TypeLiteral() {}).annotatedWith(Names.named("a")).toInstance("C"); } }, annotationChecker, - annotationChecker - ); + annotationChecker); } public void testBindToProvider() { - final Provider aProvider = new Provider() { - public String get() { - return "A"; - } - }; - - final javax.inject.Provider intJavaxProvider = new javax.inject.Provider() { - public Integer get() { - return 42; - } - }; - - final javax.inject.Provider doubleJavaxProvider = new javax.inject.Provider() { - @javax.inject.Inject String string; - - public Double get() { - return 42.42; - } - }; + final Provider aProvider = + new Provider() { + @Override + public String get() { + return "A"; + } + }; + + final javax.inject.Provider intJavaxProvider = + new javax.inject.Provider() { + @Override + public Integer get() { + return 42; + } + }; + + final javax.inject.Provider doubleJavaxProvider = + new javax.inject.Provider() { + @javax.inject.Inject String string; + + @Override + public Double get() { + return 42.42; + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class).toProvider(aProvider); bind(Integer.class).toProvider(intJavaxProvider); @@ -396,186 +409,203 @@ bind(Iterable.class).toProvider(new TypeLiteral>() {}); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof ProviderInstanceBinding); assertEquals(Key.get(String.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit( - ProviderInstanceBinding binding) { - assertSame(aProvider, binding.getUserSuppliedProvider()); - assertSame(aProvider, binding.getProviderInstance()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderInstanceBinding binding) { + assertSame(aProvider, binding.getUserSuppliedProvider()); + assertSame(aProvider, binding.getProviderInstance()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof ProviderInstanceBinding); assertEquals(Key.get(Integer.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit( - ProviderInstanceBinding binding) { - assertSame(intJavaxProvider, binding.getUserSuppliedProvider()); - assertEquals(42, binding.getProviderInstance().get()); - // we don't wrap this w/ dependencies if there were none. - assertFalse(binding.getProviderInstance() instanceof HasDependencies); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderInstanceBinding binding) { + assertSame(intJavaxProvider, binding.getUserSuppliedProvider()); + assertEquals(42, binding.getProviderInstance().get()); + // we don't wrap this w/ dependencies if there were none. + assertFalse(binding.getProviderInstance() instanceof HasDependencies); + return null; + } + }); return null; } - }, - + }, new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof ProviderInstanceBinding); assertEquals(Key.get(Double.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit( - ProviderInstanceBinding binding) { - assertSame(doubleJavaxProvider, binding.getUserSuppliedProvider()); - assertEquals(42.42, binding.getProviderInstance().get()); - // we do wrap it with dependencies if there were some. - assertTrue(binding.getProviderInstance() instanceof HasDependencies); - Set> deps = - ((HasDependencies) binding.getProviderInstance()).getDependencies(); - assertEquals(1, deps.size()); - assertEquals(String.class, - deps.iterator().next().getKey().getTypeLiteral().getRawType()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderInstanceBinding binding) { + assertSame(doubleJavaxProvider, binding.getUserSuppliedProvider()); + assertEquals(42.42, binding.getProviderInstance().get()); + // we do wrap it with dependencies if there were some. + assertTrue(binding.getProviderInstance() instanceof HasDependencies); + Set> deps = + ((HasDependencies) binding.getProviderInstance()).getDependencies(); + assertEquals(1, deps.size()); + assertEquals( + String.class, + deps.iterator().next().getKey().getTypeLiteral().getRawType()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof ProviderKeyBinding); assertEquals(Key.get(List.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ProviderKeyBinding binding) { - assertEquals(Key.get(ListProvider.class), binding.getProviderKey()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderKeyBinding binding) { + assertEquals(Key.get(ListProvider.class), binding.getProviderKey()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof ProviderKeyBinding); assertEquals(Key.get(Collection.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ProviderKeyBinding binding) { - assertEquals(Key.get(ListProvider.class), binding.getProviderKey()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderKeyBinding binding) { + assertEquals(Key.get(ListProvider.class), binding.getProviderKey()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof ProviderKeyBinding); assertEquals(Key.get(Iterable.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ProviderKeyBinding binding) { - assertEquals(new Key>() {}, binding.getProviderKey()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderKeyBinding binding) { + assertEquals(new Key>() {}, binding.getProviderKey()); + return null; + } + }); return null; } - } - ); + }); } public void testBindToLinkedBinding() { checkModule( new AbstractModule() { + @Override protected void configure() { bind(List.class).to(ArrayList.class); bind(Map.class).to(new TypeLiteral>() {}); bind(Set.class).to(Key.get(TreeSet.class, SampleAnnotation.class)); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof LinkedKeyBinding); assertEquals(Key.get(List.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(LinkedKeyBinding binding) { - assertEquals(Key.get(ArrayList.class), binding.getLinkedKey()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(LinkedKeyBinding binding) { + assertEquals(Key.get(ArrayList.class), binding.getLinkedKey()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof LinkedKeyBinding); assertEquals(Key.get(Map.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(LinkedKeyBinding binding) { - assertEquals(Key.get(new TypeLiteral>() {}), - binding.getLinkedKey()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(LinkedKeyBinding binding) { + assertEquals( + Key.get(new TypeLiteral>() {}), + binding.getLinkedKey()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof LinkedKeyBinding); assertEquals(Key.get(Set.class), command.getKey()); - command.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(LinkedKeyBinding binding) { - assertEquals(Key.get(TreeSet.class, SampleAnnotation.class), - binding.getLinkedKey()); - return null; - } - }); + command.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(LinkedKeyBinding binding) { + assertEquals( + Key.get(TreeSet.class, SampleAnnotation.class), binding.getLinkedKey()); + return null; + } + }); return null; } - } - ); + }); } public void testBindToInstance() { checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class).toInstance("A"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class), command.getKey()); assertEquals("A", getInstance(command)); return null; } - } - ); + }); } public void testBindInScopes() { checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class); bind(List.class).to(ArrayList.class).in(Scopes.SINGLETON); @@ -583,269 +613,291 @@ bind(Set.class).to(TreeSet.class).asEagerSingleton(); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(String.class), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitNoScoping() { - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitNoScoping() { + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(List.class), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitScope(Scope scope) { - assertEquals(Scopes.SINGLETON, scope); - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitScope(Scope scope) { + assertEquals(Scopes.SINGLETON, scope); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(Map.class), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitScopeAnnotation(Class annotation) { - assertEquals(Singleton.class, annotation); - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitScopeAnnotation(Class annotation) { + assertEquals(Singleton.class, annotation); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(Set.class), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - public Void visitEagerSingleton() { - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitEagerSingleton() { + return null; + } + }); return null; } - } - ); + }); } public void testBindToInstanceInScope() { checkModule( new AbstractModule() { + @Override protected void configure() { AnnotatedBindingBuilder b = bind(String.class); b.toInstance("A"); b.in(Singleton.class); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { - assertEquals("Setting the scope is not permitted when binding to a single instance.", + @Override + public Void visit(Message command) { + assertEquals( + "Setting the scope is not permitted when binding to a single instance.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testBindToInstanceScope() { checkModule( new AbstractModule() { + @Override protected void configure() { bind(String.class).toInstance("A"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals(Key.get(String.class), binding.getKey()); - binding.acceptScopingVisitor(new FailingBindingScopingVisitor() { - public Void visitEagerSingleton() { - return null; - } - }); + binding.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitEagerSingleton() { + return null; + } + }); return null; } - } - ); + }); } /*if[AOP]*/ public void testBindIntercepor() { final Matcher classMatcher = Matchers.subclassesOf(List.class); final Matcher methodMatcher = Matchers.any(); - final org.aopalliance.intercept.MethodInterceptor methodInterceptor - = new org.aopalliance.intercept.MethodInterceptor() { - public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { - return null; - } - }; + final org.aopalliance.intercept.MethodInterceptor methodInterceptor = + new org.aopalliance.intercept.MethodInterceptor() { + @Override + public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { + return null; + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { bindInterceptor(classMatcher, methodMatcher, methodInterceptor); } }, - new FailingElementVisitor() { - @Override public Void visit(InterceptorBinding command) { + @Override + public Void visit(InterceptorBinding command) { assertSame(classMatcher, command.getClassMatcher()); assertSame(methodMatcher, command.getMethodMatcher()); assertEquals(Arrays.asList(methodInterceptor), command.getInterceptors()); return null; } - } - ); + }); } /*end[AOP]*/ public void testBindScope() { checkModule( new AbstractModule() { + @Override protected void configure() { bindScope(SampleAnnotation.class, Scopes.NO_SCOPE); } }, - new FailingElementVisitor() { - @Override public Void visit(ScopeBinding command) { + @Override + public Void visit(ScopeBinding command) { assertSame(SampleAnnotation.class, command.getAnnotationType()); assertSame(Scopes.NO_SCOPE, command.getScope()); return null; } - } - ); + }); } public void testBindListener() { final Matcher typeMatcher = Matchers.only(TypeLiteral.get(String.class)); - final TypeListener listener = new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - throw new UnsupportedOperationException(); - } - }; - + final TypeListener listener = + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + throw new UnsupportedOperationException(); + } + }; + checkModule( new AbstractModule() { + @Override protected void configure() { bindListener(typeMatcher, listener); } }, - new FailingElementVisitor() { - @Override public Void visit(TypeListenerBinding binding) { + @Override + public Void visit(TypeListenerBinding binding) { assertSame(typeMatcher, binding.getTypeMatcher()); assertSame(listener, binding.getListener()); return null; } - } - ); + }); } public void testConvertToTypes() { - final TypeConverter typeConverter = new TypeConverter() { - public Object convert(String value, TypeLiteral toType) { - return value; - } - }; + final TypeConverter typeConverter = + new TypeConverter() { + @Override + public Object convert(String value, TypeLiteral toType) { + return value; + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { convertToTypes(Matchers.any(), typeConverter); } }, - new FailingElementVisitor() { - @Override public Void visit(TypeConverterBinding command) { + @Override + public Void visit(TypeConverterBinding command) { assertSame(typeConverter, command.getTypeConverter()); assertSame(Matchers.any(), command.getTypeMatcher()); return null; } - } - ); + }); } public void testGetProvider() { checkModule( new AbstractModule() { + @Override protected void configure() { - Provider keyGetProvider - = getProvider(Key.get(String.class, SampleAnnotation.class)); + Provider keyGetProvider = + getProvider(Key.get(String.class, SampleAnnotation.class)); try { keyGetProvider.get(); + fail("Expected IllegalStateException"); } catch (IllegalStateException e) { - assertEquals("This Provider cannot be used until the Injector has been created.", + assertEquals( + "This Provider cannot be used until the Injector has been created.", e.getMessage()); } Provider typeGetProvider = getProvider(String.class); try { typeGetProvider.get(); + fail("Expected IllegalStateException"); } catch (IllegalStateException e) { - assertEquals("This Provider cannot be used until the Injector has been created.", + assertEquals( + "This Provider cannot be used until the Injector has been created.", e.getMessage()); } } }, - new FailingElementVisitor() { - @Override public Void visit(ProviderLookup command) { + @Override + public Void visit(ProviderLookup command) { assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); assertNull(command.getDelegate()); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(ProviderLookup command) { + @Override + public Void visit(ProviderLookup command) { assertEquals(Key.get(String.class), command.getKey()); assertNull(command.getDelegate()); return null; } - } - ); + }); } - + public void testElementInitialization() { - final AtomicReference> providerFromBinder - = new AtomicReference>(); - final AtomicReference> membersInjectorFromBinder - = new AtomicReference>(); - - final AtomicReference lastInjected = new AtomicReference(); - final MembersInjector stringInjector = new MembersInjector() { - public void injectMembers(String instance) { - lastInjected.set(instance); - } - }; + final AtomicReference> providerFromBinder = + new AtomicReference>(); + final AtomicReference> membersInjectorFromBinder = + new AtomicReference>(); + + final AtomicReference lastInjected = new AtomicReference<>(); + final MembersInjector stringInjector = + new MembersInjector() { + @Override + public void injectMembers(String instance) { + lastInjected.set(instance); + } + }; checkModule( new AbstractModule() { + @Override protected void configure() { providerFromBinder.set(getProvider(String.class)); membersInjectorFromBinder.set(getMembersInjector(String.class)); } }, - new FailingElementVisitor() { + @Override public Void visit(ProviderLookup providerLookup) { @SuppressWarnings("unchecked") // we know that T is a String here ProviderLookup stringLookup = (ProviderLookup) providerLookup; @@ -855,9 +907,9 @@ return null; } }, - new FailingElementVisitor() { - @Override public Void visit(MembersInjectorLookup lookup) { + @Override + public Void visit(MembersInjectorLookup lookup) { @SuppressWarnings("unchecked") // we know that T is a String here MembersInjectorLookup stringLookup = (MembersInjectorLookup) lookup; stringLookup.initializeDelegate(stringInjector); @@ -872,11 +924,13 @@ public void testGetMembersInjector() { checkModule( new AbstractModule() { + @Override protected void configure() { - MembersInjector> typeMembersInjector - = getMembersInjector(new TypeLiteral>() {}); + MembersInjector> typeMembersInjector = + getMembersInjector(new TypeLiteral>() {}); try { typeMembersInjector.injectMembers(new A()); + fail("Expected IllegalStateException"); } catch (IllegalStateException e) { assertEquals( "This MembersInjector cannot be used until the Injector has been created.", @@ -886,6 +940,7 @@ MembersInjector classMembersInjector = getMembersInjector(String.class); try { classMembersInjector.injectMembers("hello"); + fail("Expected IllegalStateException"); } catch (IllegalStateException e) { assertEquals( "This MembersInjector cannot be used until the Injector has been created.", @@ -893,23 +948,22 @@ } } }, - new FailingElementVisitor() { - @Override public Void visit(MembersInjectorLookup command) { + @Override + public Void visit(MembersInjectorLookup command) { assertEquals(new TypeLiteral>() {}, command.getType()); assertNull(command.getDelegate()); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(MembersInjectorLookup command) { + @Override + public Void visit(MembersInjectorLookup command) { assertEquals(TypeLiteral.get(String.class), command.getType()); assertNull(command.getDelegate()); return null; } - } - ); + }); } public void testRequestInjection() { @@ -918,43 +972,43 @@ checkModule( new AbstractModule() { + @Override protected void configure() { requestInjection(firstObject); requestInjection(secondObject); } }, - new FailingElementVisitor() { - @Override public Void visit(InjectionRequest command) { + @Override + public Void visit(InjectionRequest command) { assertEquals(firstObject, command.getInstance()); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(InjectionRequest command) { + @Override + public Void visit(InjectionRequest command) { assertEquals(secondObject, command.getInstance()); return null; } - } - ); + }); } public void testRequestStaticInjection() { checkModule( new AbstractModule() { + @Override protected void configure() { requestStaticInjection(ArrayList.class); } }, - new FailingElementVisitor() { - @Override public Void visit(StaticInjectionRequest command) { + @Override + public Void visit(StaticInjectionRequest command) { assertEquals(ArrayList.class, command.getType()); return null; } - } - ); + }); } public void testNewPrivateBinder() { @@ -968,189 +1022,191 @@ checkModule( new AbstractModule() { + @Override protected void configure() { PrivateBinder one = binder().newPrivateBinder(); one.expose(ArrayList.class); one.expose(Collection.class).annotatedWith(SampleAnnotation.class); one.bind(List.class).to(ArrayList.class); - PrivateBinder two = binder().withSource("1 FooBar") - .newPrivateBinder().withSource("2 FooBar"); + PrivateBinder two = + binder().withSource("1 FooBar").newPrivateBinder().withSource("2 FooBar"); two.expose(String.class).annotatedWith(Names.named("a")); two.expose(b); two.bind(List.class).to(ArrayList.class); } }, - new FailingElementVisitor() { - @Override public Void visit(PrivateElements one) { + @Override + public Void visit(PrivateElements one) { assertEquals(collections, one.getExposedKeys()); - checkElements(one.getElements(), + checkElements( + one.getElements(), new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals(Key.get(List.class), binding.getKey()); return null; } - } - ); + }); return null; } }, - new ExternalFailureVisitor() { - @Override public Void visit(PrivateElements two) { + @Override + public Void visit(PrivateElements two) { assertEquals(ab, two.getExposedKeys()); assertEquals("1 FooBar", two.getSource().toString()); - checkElements(two.getElements(), + checkElements( + two.getElements(), new ExternalFailureVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals("2 FooBar", binding.getSource().toString()); assertEquals(Key.get(List.class), binding.getKey()); return null; } - } - ); + }); return null; } - } - ); + }); } public void testBindWithMultipleAnnotationsAddsError() { checkModule( new AbstractModule() { + @Override protected void configure() { AnnotatedBindingBuilder abb = bind(String.class); abb.annotatedWith(SampleAnnotation.class); abb.annotatedWith(Names.named("A")); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { - assertEquals("More than one annotation is specified for this binding.", - command.getMessage()); + @Override + public Void visit(Message command) { + assertEquals( + "More than one annotation is specified for this binding.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testBindWithMultipleTargetsAddsError() { checkModule( new AbstractModule() { + @Override protected void configure() { AnnotatedBindingBuilder abb = bind(String.class); abb.toInstance("A"); abb.toInstance("B"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { + @Override + public Void visit(Message command) { assertEquals("Implementation is set more than once.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testBindWithMultipleScopesAddsError() { checkModule( new AbstractModule() { + @Override protected void configure() { ScopedBindingBuilder sbb = bind(List.class).to(ArrayList.class); sbb.in(Scopes.NO_SCOPE); sbb.asEagerSingleton(); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { + @Override + public Void visit(Message command) { assertEquals("Scope is set more than once.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testBindConstantWithMultipleAnnotationsAddsError() { checkModule( new AbstractModule() { + @Override protected void configure() { AnnotatedConstantBindingBuilder cbb = bindConstant(); cbb.annotatedWith(SampleAnnotation.class).to("A"); cbb.annotatedWith(Names.named("A")); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message command) { - assertEquals("More than one annotation is specified for this binding.", - command.getMessage()); + @Override + public Void visit(Message command) { + assertEquals( + "More than one annotation is specified for this binding.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testBindConstantWithMultipleTargetsAddsError() { checkModule( new AbstractModule() { + @Override protected void configure() { ConstantBindingBuilder cbb = bindConstant().annotatedWith(SampleAnnotation.class); cbb.to("A"); cbb.to("B"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Message message) { + @Override + public Void visit(Message message) { assertEquals("Constant value is set more than once.", message.getMessage()); assertNull(message.getCause()); assertContains(message.getSource(), getDeclaringSourcePart(ElementsTest.class)); return null; } - } - ); + }); } public void testBindToConstructor() throws NoSuchMethodException, NoSuchFieldException { @@ -1160,56 +1216,66 @@ checkModule( new AbstractModule() { + @Override protected void configure() { bind(A.class).toConstructor(aConstructor); - bind(B.class).toConstructor(bConstructor, new TypeLiteral>() {}) + bind(B.class) + .toConstructor(bConstructor, new TypeLiteral>() {}) .in(Singleton.class); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals(new Key() {}, binding.getKey()); - return binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ConstructorBinding constructorBinding) { - InjectionPoint injectionPoint = constructorBinding.getConstructor(); - assertEquals(aConstructor, injectionPoint.getMember()); - assertEquals(new TypeLiteral() {}, injectionPoint.getDeclaringType()); - return null; - } - }); + return binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ConstructorBinding constructorBinding) { + InjectionPoint injectionPoint = constructorBinding.getConstructor(); + assertEquals(aConstructor, injectionPoint.getMember()); + assertEquals(new TypeLiteral() {}, injectionPoint.getDeclaringType()); + return null; + } + }); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals(new Key() {}, binding.getKey()); - binding.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitScopeAnnotation(Class annotation) { - assertEquals(Singleton.class, annotation); - return null; - } - }); - - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ConstructorBinding constructorBinding) { - assertEquals(bConstructor, constructorBinding.getConstructor().getMember()); - assertEquals(Key.get(Integer.class), - getOnlyElement(constructorBinding.getConstructor().getDependencies()).getKey()); - assertEquals(field, - getOnlyElement(constructorBinding.getInjectableMembers()).getMember()); - assertEquals(2, constructorBinding.getDependencies().size()); -/*if[AOP]*/ - assertEquals(ImmutableMap.of(), constructorBinding.getMethodInterceptors()); -/*end[AOP]*/ - return null; - } - }); + binding.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitScopeAnnotation(Class annotation) { + assertEquals(Singleton.class, annotation); + return null; + } + }); + + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ConstructorBinding constructorBinding) { + assertEquals(bConstructor, constructorBinding.getConstructor().getMember()); + assertEquals( + Key.get(Integer.class), + getOnlyElement(constructorBinding.getConstructor().getDependencies()) + .getKey()); + assertEquals( + field, + getOnlyElement(constructorBinding.getInjectableMembers()).getMember()); + assertEquals(2, constructorBinding.getDependencies().size()); + /*if[AOP]*/ + assertEquals(ImmutableMap.of(), constructorBinding.getMethodInterceptors()); + /*end[AOP]*/ + return null; + } + }); return null; } - } - ); + }); } public void testBindToMalformedConstructor() throws NoSuchMethodException, NoSuchFieldException { @@ -1217,67 +1283,73 @@ checkModule( new AbstractModule() { + @Override protected void configure() { bind(C.class).toConstructor(constructor); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals(Key.get(C.class), binding.getKey()); assertTrue(binding instanceof UntargettedBinding); return null; } }, - new ExternalFailureVisitor() { - @Override public Void visit(Message message) { - assertContains(message.getMessage(), + @Override + public Void visit(Message message) { + assertContains( + message.getMessage(), C.class.getName() + ".a has more than one annotation ", - Named.class.getName(), SampleAnnotation.class.getName()); + Named.class.getName(), + SampleAnnotation.class.getName()); return null; } }, - new ExternalFailureVisitor() { - @Override public Void visit(Message message) { - assertContains(message.getMessage(), + @Override + public Void visit(Message message) { + assertContains( + message.getMessage(), C.class.getName() + ".() has more than one annotation ", - Named.class.getName(), SampleAnnotation.class.getName()); + Named.class.getName(), + SampleAnnotation.class.getName()); return null; } - } - ); + }); } // Business logic tests public void testModulesAreInstalledAtMostOnce() { final AtomicInteger aConfigureCount = new AtomicInteger(0); - final Module a = new AbstractModule() { - public void configure() { - aConfigureCount.incrementAndGet(); - } - }; + final Module a = + new AbstractModule() { + @Override + public void configure() { + aConfigureCount.incrementAndGet(); + } + }; Elements.getElements(a, a); assertEquals(1, aConfigureCount.get()); aConfigureCount.set(0); - Module b = new AbstractModule() { - protected void configure() { - install(a); - install(a); - } - }; + Module b = + new AbstractModule() { + @Override + protected void configure() { + install(a); + install(a); + } + }; Elements.getElements(b); assertEquals(1, aConfigureCount.get()); } - /** - * Ensures the module performs the commands consistent with {@code visitors}. - */ + /** Ensures the module performs the commands consistent with {@code visitors}. */ protected void checkModule(Module module, ElementVisitor... visitors) { List elements = Elements.getElements(module); assertEquals(elements.size(), visitors.length); @@ -1289,13 +1361,13 @@ ElementVisitor visitor = visitors[i]; Element element = elements.get(i); if (!(element instanceof Message)) { - ElementSource source = (ElementSource) element.getSource(); - assertFalse(source.getModuleClassNames().isEmpty()); - if (isIncludeStackTraceComplete()) { - assertTrue(source.getStackTrace().length > 0); - } else { - assertEquals(0, source.getStackTrace().length); - } + ElementSource source = (ElementSource) element.getSource(); + assertFalse(source.getModuleClassNames().isEmpty()); + if (isIncludeStackTraceComplete()) { + assertTrue(source.getStackTrace().length > 0); + } else { + assertEquals(0, source.getStackTrace().length); + } } if (!(visitor instanceof ExternalFailureVisitor)) { assertContains(element.getSource().toString(), getDeclaringSourcePart(ElementsTest.class)); @@ -1305,12 +1377,14 @@ } private static class ListProvider implements Provider { + @Override public List get() { return new ArrayList(); } } private static class TProvider implements Provider { + @Override public T get() { return null; } @@ -1320,14 +1394,17 @@ * By extending this interface rather than FailingElementVisitor, the source of the error doesn't * need to contain the string {@code ElementsTest.java}. */ - abstract class ExternalFailureVisitor extends FailingElementVisitor {} + abstract static class ExternalFailureVisitor extends FailingElementVisitor {} @Retention(RUNTIME) - @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @BindingAnnotation - public @interface SampleAnnotation { } + public @interface SampleAnnotation {} - public enum CoinSide { HEADS, TAILS } + public enum CoinSide { + HEADS, + TAILS + } static class A { @Inject Stage stage; @@ -1335,11 +1412,16 @@ static class B { @Inject Stage stage; + B(T t) {} } static class C { - @Inject @Named("foo") @SampleAnnotation String a; + @Inject + @Named("foo") + @SampleAnnotation + String a; + C(@Named("bar") @SampleAnnotation Integer b) {} } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java sisu-guice-4.2.0/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,26 +17,28 @@ package com.google.inject.spi; import com.google.inject.Scope; - -import junit.framework.AssertionFailedError; - import java.lang.annotation.Annotation; +import junit.framework.AssertionFailedError; public class FailingBindingScopingVisitor implements BindingScopingVisitor { + @Override public Void visitEagerSingleton() { throw new AssertionFailedError(); } + @Override public Void visitScope(Scope scope) { throw new AssertionFailedError(); } + @Override public Void visitScopeAnnotation(Class scopeAnnotation) { throw new AssertionFailedError(); } + @Override public Void visitNoScoping() { throw new AssertionFailedError(); } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/FailingElementVisitor.java sisu-guice-4.2.0/core/test/com/google/inject/spi/FailingElementVisitor.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/FailingElementVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/FailingElementVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,8 @@ import junit.framework.AssertionFailedError; class FailingElementVisitor extends DefaultElementVisitor { - @Override protected Void visitOther(Element element) { + @Override + protected Void visitOther(Element element) { throw new AssertionFailedError(); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/FailingTargetVisitor.java sisu-guice-4.2.0/core/test/com/google/inject/spi/FailingTargetVisitor.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/FailingTargetVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/FailingTargetVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,11 @@ package com.google.inject.spi; import com.google.inject.Binding; - import junit.framework.AssertionFailedError; public class FailingTargetVisitor extends DefaultBindingTargetVisitor { - @Override protected Void visitOther(Binding binding) { + @Override + protected Void visitOther(Binding binding) { throw new AssertionFailedError(); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/HasDependenciesTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/HasDependenciesTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/HasDependenciesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/HasDependenciesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,37 +24,38 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; - -import junit.framework.TestCase; - import java.util.Set; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class HasDependenciesTest extends TestCase { - /** - * When an instance implements HasDependencies, the injected dependencies aren't used. - */ + /** When an instance implements HasDependencies, the injected dependencies aren't used. */ public void testInstanceWithDependencies() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(A.class).toInstance(new AWithDependencies()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).toInstance(new AWithDependencies()); + } + }); InstanceBinding binding = (InstanceBinding) injector.getBinding(A.class); - assertEquals(ImmutableSet.>of(Dependency.get(Key.get(Integer.class))), + assertEquals( + ImmutableSet.>of(Dependency.get(Key.get(Integer.class))), binding.getDependencies()); } public void testInstanceWithoutDependencies() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(A.class).toInstance(new A()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).toInstance(new A()); + } + }); InstanceBinding binding = (InstanceBinding) injector.getBinding(A.class); Dependency onlyDependency = Iterables.getOnlyElement(binding.getDependencies()); @@ -62,11 +63,14 @@ } public void testProvider() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(A.class).toProvider(new ProviderOfA()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(A.class).toProvider(new ProviderOfA()); + } + }); ProviderInstanceBinding binding = (ProviderInstanceBinding) injector.getBinding(A.class); Dependency onlyDependency = Iterables.getOnlyElement(binding.getDependencies()); @@ -74,25 +78,30 @@ } static class A { - @Inject void injectUnusedDependencies(String unused) {} + @Inject + void injectUnusedDependencies(String unused) {} } static class ProviderOfA implements Provider { - @Inject void injectUnusedDependencies(String unused) {} + @Inject + void injectUnusedDependencies(String unused) {} + @Override public A get() { throw new UnsupportedOperationException(); } } static class AWithDependencies extends A implements HasDependencies { + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Integer.class))); } } - static class ProviderOfAWithDependencies - extends ProviderOfA implements ProviderWithDependencies { + static class ProviderOfAWithDependencies extends ProviderOfA + implements ProviderWithDependencies { + @Override public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Integer.class))); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/InjectionPointTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/InjectionPointTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/InjectionPointTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/InjectionPointTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,6 +17,7 @@ package com.google.inject.spi; import static com.google.common.collect.Iterables.getOnlyElement; +import static com.google.common.truth.Truth.assertThat; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertEqualsBothWays; import static com.google.inject.Asserts.assertNotSerializable; @@ -29,12 +30,10 @@ import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; +import com.google.inject.internal.Annotations; import com.google.inject.internal.ErrorsException; import com.google.inject.name.Named; import com.google.inject.spi.InjectionPoint.Signature; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -43,17 +42,18 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class InjectionPointTest extends TestCase { public @Inject @Named("a") String foo; + public @Inject void bar(@Named("b") String param) {} public static class Constructable { - @Inject public Constructable(@Named("c") String param) {} + @Inject + public Constructable(@Named("c") String param) {} } public void testFieldInjectionPoint() throws NoSuchFieldException, IOException, ErrorsException { @@ -68,14 +68,20 @@ assertNotSerializable(injectionPoint); Dependency dependency = getOnlyElement(injectionPoint.getDependencies()); - assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=a)]@" - + getClass().getName() + ".foo", dependency.toString()); + assertEquals( + "Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=" + + Annotations.memberValueString("a") + + ")]@" + + getClass().getName() + + ".foo", + dependency.toString()); assertEquals(fooField, dependency.getInjectionPoint().getMember()); assertEquals(-1, dependency.getParameterIndex()); assertEquals(Key.get(String.class, named("a")), dependency.getKey()); assertFalse(dependency.isNullable()); assertNotSerializable(dependency); - assertEqualsBothWays(dependency, + assertEqualsBothWays( + dependency, getOnlyElement(new InjectionPoint(typeLiteral, fooField, false).getDependencies())); } @@ -91,19 +97,25 @@ assertNotSerializable(injectionPoint); Dependency dependency = getOnlyElement(injectionPoint.getDependencies()); - assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=b)]@" - + getClass().getName() + ".bar()[0]", dependency.toString()); + assertEquals( + "Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=" + + Annotations.memberValueString("b") + + ")]@" + + getClass().getName() + + ".bar()[0]", + dependency.toString()); assertEquals(barMethod, dependency.getInjectionPoint().getMember()); assertEquals(0, dependency.getParameterIndex()); assertEquals(Key.get(String.class, named("b")), dependency.getKey()); assertFalse(dependency.isNullable()); assertNotSerializable(dependency); - assertEqualsBothWays(dependency, + assertEqualsBothWays( + dependency, getOnlyElement(new InjectionPoint(typeLiteral, barMethod, false).getDependencies())); } - public void testConstructorInjectionPoint() throws NoSuchMethodException, IOException, - ErrorsException { + public void testConstructorInjectionPoint() + throws NoSuchMethodException, IOException, ErrorsException { TypeLiteral typeLiteral = TypeLiteral.get(Constructable.class); Constructor constructor = Constructable.class.getConstructor(String.class); @@ -115,20 +127,28 @@ assertNotSerializable(injectionPoint); Dependency dependency = getOnlyElement(injectionPoint.getDependencies()); - assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=c)]@" - + Constructable.class.getName() + ".()[0]", dependency.toString()); + assertEquals( + "Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=" + + Annotations.memberValueString("c") + + ")]@" + + Constructable.class.getName() + + ".()[0]", + dependency.toString()); assertEquals(constructor, dependency.getInjectionPoint().getMember()); assertEquals(0, dependency.getParameterIndex()); assertEquals(Key.get(String.class, named("c")), dependency.getKey()); assertFalse(dependency.isNullable()); assertNotSerializable(dependency); - assertEqualsBothWays(dependency, - getOnlyElement(new InjectionPoint(typeLiteral, constructor).getDependencies())); + assertEqualsBothWays( + dependency, getOnlyElement(new InjectionPoint(typeLiteral, constructor).getDependencies())); } public void testUnattachedDependency() throws IOException { Dependency dependency = Dependency.get(Key.get(String.class, named("d"))); - assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=d)]", + assertEquals( + "Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=" + + Annotations.memberValueString("d") + + ")]", dependency.toString()); assertNull(dependency.getInjectionPoint()); assertEquals(-1, dependency.getParameterIndex()); @@ -149,16 +169,22 @@ try { InjectionPoint.forConstructor(constructor, new TypeLiteral>() {}); + fail("Expected ConfigurationException"); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), "java.util.LinkedHashSet", + assertContains( + expected.getMessage(), + "java.util.LinkedHashSet", " does not define java.util.HashSet.()", " while locating java.util.LinkedHashSet"); } try { InjectionPoint.forConstructor((Constructor) constructor, new TypeLiteral>() {}); + fail("Expected ConfigurationException"); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), "java.util.Set", + assertContains( + expected.getMessage(), + "java.util.Set", " does not define java.util.HashSet.()", " while locating java.util.Set"); } @@ -172,39 +198,66 @@ public void testAddForInstanceMethodsAndFields() throws Exception { Method instanceMethod = HasInjections.class.getMethod("instanceMethod", String.class); Field instanceField = HasInjections.class.getField("instanceField"); + Field instanceField2 = HasInjections.class.getField("instanceField2"); TypeLiteral type = TypeLiteral.get(HasInjections.class); - assertEquals(ImmutableSet.of( - new InjectionPoint(type, instanceMethod, false), - new InjectionPoint(type, instanceField, false)), - InjectionPoint.forInstanceMethodsAndFields(HasInjections.class)); + Set injectionPoints = + InjectionPoint.forInstanceMethodsAndFields(HasInjections.class); + // there is a defined order. assert on it + assertThat(injectionPoints) + .containsExactly( + new InjectionPoint(type, instanceField, false), + new InjectionPoint(type, instanceField2, false), + new InjectionPoint(type, instanceMethod, false)) + .inOrder(); } public void testAddForStaticMethodsAndFields() throws Exception { Method staticMethod = HasInjections.class.getMethod("staticMethod", String.class); Field staticField = HasInjections.class.getField("staticField"); + Field staticField2 = HasInjections.class.getField("staticField2"); - Set injectionPoints = InjectionPoint.forStaticMethodsAndFields( - HasInjections.class); - assertEquals(ImmutableSet.of( - new InjectionPoint(TypeLiteral.get(HasInjections.class), staticMethod, false), - new InjectionPoint(TypeLiteral.get(HasInjections.class), staticField, false)), - injectionPoints); + Set injectionPoints = + InjectionPoint.forStaticMethodsAndFields(HasInjections.class); + TypeLiteral type = TypeLiteral.get(HasInjections.class); + assertThat(injectionPoints) + .containsExactly( + new InjectionPoint(type, staticField, false), + new InjectionPoint(type, staticField2, false), + new InjectionPoint(type, staticMethod, false)) + .inOrder(); } static class HasInjections { - @Inject public static void staticMethod(@Named("a") String a) {} - @Inject @Named("c") public static String staticField; - @Inject public void instanceMethod(@Named("d") String d) {} - @Inject @Named("f") public String instanceField; + @Inject + public static void staticMethod(@Named("a") String a) {} + + @Inject + @Named("c") + public static String staticField; + + @Inject + @Named("c") + public static String staticField2; + + @Inject + public void instanceMethod(@Named("d") String d) {} + + @Inject + @Named("f") + public String instanceField; + + @Inject + @Named("f") + public String instanceField2; } public void testAddForParameterizedInjections() { TypeLiteral type = new TypeLiteral>() {}; InjectionPoint constructor = InjectionPoint.forConstructorOf(type); - assertEquals(new Key>() {}, - getOnlyElement(constructor.getDependencies()).getKey()); + assertEquals( + new Key>() {}, getOnlyElement(constructor.getDependencies()).getKey()); InjectionPoint field = getOnlyElement(InjectionPoint.forInstanceMethodsAndFields(type)); assertEquals(new Key>() {}, getOnlyElement(field.getDependencies()).getKey()); @@ -212,15 +265,15 @@ static class ParameterizedInjections { @Inject Set setOfTees; - @Inject public ParameterizedInjections(Map map) {} + + @Inject + public ParameterizedInjections(Map map) {} } public void testSignature() throws Exception { - Signature fooA = new Signature(Foo.class.getDeclaredMethod( - "a", String.class, int.class)); + Signature fooA = new Signature(Foo.class.getDeclaredMethod("a", String.class, int.class)); Signature fooB = new Signature(Foo.class.getDeclaredMethod("b")); - Signature barA = new Signature(Bar.class.getDeclaredMethod( - "a", String.class, int.class)); + Signature barA = new Signature(Bar.class.getDeclaredMethod("a", String.class, int.class)); Signature barB = new Signature(Bar.class.getDeclaredMethod("b")); assertEquals(fooA.hashCode(), barA.hashCode()); @@ -231,22 +284,32 @@ static class Foo { void a(String s, int i) {} + int b() { return 0; } } + static class Bar { public void a(String s, int i) {} + void b() {} } - + public void testOverrideBehavior() { Set points; points = InjectionPoint.forInstanceMethodsAndFields(Super.class); assertEquals(points.toString(), 6, points.size()); - assertPoints(points, Super.class, "atInject", "gInject", "privateAtAndPublicG", - "privateGAndPublicAt", "atFirstThenG", "gFirstThenAt"); + assertPoints( + points, + Super.class, + "atInject", + "gInject", + "privateAtAndPublicG", + "privateGAndPublicAt", + "atFirstThenG", + "gFirstThenAt"); points = InjectionPoint.forInstanceMethodsAndFields(Sub.class); assertEquals(points.toString(), 7, points.size()); @@ -255,9 +318,14 @@ assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject"); // Subclass also has the "private" methods, but they do not override // the superclass' methods, and it now owns the inject2 methods. - assertPoints(points, Sub.class, "privateAtAndPublicG", "privateGAndPublicAt", - "atFirstThenG", "gFirstThenAt"); - + assertPoints( + points, + Sub.class, + "privateAtAndPublicG", + "privateGAndPublicAt", + "atFirstThenG", + "gFirstThenAt"); + points = InjectionPoint.forInstanceMethodsAndFields(SubSub.class); assertEquals(points.toString(), 6, points.size()); // Superclass still has all the injection points it did before.. @@ -266,39 +334,36 @@ // javax.inject.Inject and was overrode without an annotation, which means it // disappears. (It was guice @Inject in Super, but it was private there, so it doesn't // effect the annotations of the subclasses.) - assertPoints(points, Sub.class, "privateAtAndPublicG", "atFirstThenG", "gFirstThenAt"); + assertPoints(points, Sub.class, "privateAtAndPublicG", "atFirstThenG", "gFirstThenAt"); } - + /** - * This test serves two purposes: - * 1) It makes sure that the bridge methods javax generates don't stop - * us from injecting superclass methods in the case of javax.inject.Inject. - * This would happen prior to java8 (where javac didn't copy annotations - * from the superclass into the subclass method when it generated the - * bridge methods). - * - * 2) It makes sure that the methods we're going to inject have the correct - * generic types. Java8 copies the annotations from super to subclasses, - * but it doesn't copy the generic type information. Guice would naively - * consider the subclass an injectable method and eject the superclass - * from the 'overrideIndex', leaving only a class with improper generic types. + * This test serves two purposes: 1) It makes sure that the bridge methods javax generates don't + * stop us from injecting superclass methods in the case of javax.inject.Inject. This would happen + * prior to java8 (where javac didn't copy annotations from the superclass into the subclass + * method when it generated the bridge methods). + * + *

    2) It makes sure that the methods we're going to inject have the correct generic types. + * Java8 copies the annotations from super to subclasses, but it doesn't copy the generic type + * information. Guice would naively consider the subclass an injectable method and eject the + * superclass from the 'overrideIndex', leaving only a class with improper generic types. */ public void testSyntheticBridgeMethodsInSubclasses() { Set points; - + points = InjectionPoint.forInstanceMethodsAndFields(RestrictedSuper.class); assertPointDependencies(points, new TypeLiteral>() {}); assertEquals(points.toString(), 2, points.size()); assertPoints(points, RestrictedSuper.class, "jInject", "gInject"); - + points = InjectionPoint.forInstanceMethodsAndFields(ExposedSub.class); assertPointDependencies(points, new TypeLiteral>() {}); assertEquals(points.toString(), 2, points.size()); assertPoints(points, RestrictedSuper.class, "jInject", "gInject"); } - - private void assertPoints(Iterable points, Class clazz, - String... methodNames) { + + private void assertPoints( + Iterable points, Class clazz, String... methodNames) { Set methods = new HashSet(); for (InjectionPoint point : points) { if (point.getDeclaringType().getRawType() == clazz) { @@ -307,10 +372,10 @@ } assertEquals(points.toString(), ImmutableSet.copyOf(methodNames), methods); } - + /** Asserts that each injection point has the specified dependencies, in the given order. */ - private void assertPointDependencies(Iterable points, - TypeLiteral... literals) { + private void assertPointDependencies( + Iterable points, TypeLiteral... literals) { for (InjectionPoint point : points) { assertEquals(literals.length, point.getDependencies().size()); for (Dependency dep : point.getDependencies()) { @@ -318,47 +383,77 @@ } } } - + static class Super { - @javax.inject.Inject public void atInject() {} - @com.google.inject.Inject public void gInject() {} + @javax.inject.Inject + public void atInject() {} + + @com.google.inject.Inject + public void gInject() {} + + @javax.inject.Inject + private void privateAtAndPublicG() {} - @javax.inject.Inject private void privateAtAndPublicG() {} - @com.google.inject.Inject private void privateGAndPublicAt() {} + @com.google.inject.Inject + private void privateGAndPublicAt() {} + + @javax.inject.Inject + public void atFirstThenG() {} - @javax.inject.Inject public void atFirstThenG() {} - @com.google.inject.Inject public void gFirstThenAt() {} + @com.google.inject.Inject + public void gFirstThenAt() {} } - + static class Sub extends Super { + @Override + @SuppressWarnings("OverridesJavaxInjectableMethod") public void atInject() {} + + @Override + @SuppressWarnings("OverridesGuiceInjectableMethod") public void gInject() {} - - @com.google.inject.Inject public void privateAtAndPublicG() {} - @javax.inject.Inject public void privateGAndPublicAt() {} - + @com.google.inject.Inject - @Override + public void privateAtAndPublicG() {} + + @javax.inject.Inject + public void privateGAndPublicAt() {} + + @com.google.inject.Inject + @Override public void atFirstThenG() {} - + @javax.inject.Inject - @Override + @Override public void gFirstThenAt() {} } - + static class SubSub extends Sub { - @Override public void privateAtAndPublicG() {} - @Override public void privateGAndPublicAt() {} - - @Override public void atFirstThenG() {} - @Override public void gFirstThenAt() {} + @SuppressWarnings("OverridesGuiceInjectableMethod") + @Override + public void privateAtAndPublicG() {} + + @SuppressWarnings("OverridesJavaxInjectableMethod") + @Override + public void privateGAndPublicAt() {} + + @SuppressWarnings("OverridesGuiceInjectableMethod") + @Override + public void atFirstThenG() {} + + @SuppressWarnings("OverridesGuiceInjectableMethod") + @Override + public void gFirstThenAt() {} } - + static class RestrictedSuper { - @com.google.inject.Inject public void gInject(Provider p) {} - @javax.inject.Inject public void jInject(Provider p) {} + @com.google.inject.Inject + public void gInject(Provider p) {} + + @javax.inject.Inject + public void jInject(Provider p) {} } - + public static class ExposedSub extends RestrictedSuper { // The subclass may generate bridge/synthetic methods to increase the visibility // of the superclass methods, since the superclass was package-private but this is public. diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/InjectorSpiTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/InjectorSpiTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/InjectorSpiTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/InjectorSpiTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -8,67 +8,71 @@ import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; - -import junit.framework.TestCase; - import java.util.Map; +import junit.framework.TestCase; -/** - * @author sberlin@gmail.com (Sam Berlin) - */ +/** @author sberlin@gmail.com (Sam Berlin) */ public class InjectorSpiTest extends TestCase { public void testExistingBinding() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Foo.class); - bind(Baz.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class); + bind(Baz.class); + } + }); // Sanity check -- ensure we return the proper binding for all existing bindings. - for(Map.Entry, Binding> entry : injector.getAllBindings().entrySet()) { + for (Map.Entry, Binding> entry : injector.getAllBindings().entrySet()) { assertSame(entry.getValue(), injector.getExistingBinding(entry.getKey())); } - + // Now run through specifics... Binding binding; - + // 1) non-Provider Foo.class binding = injector.getExistingBinding(Key.get(Foo.class)); assertNotNull(binding); assertEquals(Foo.class, binding.getKey().getTypeLiteral().getRawType()); - + // 2) Provider class (should already exist, because Baz @Injects it). // the assertTrue is a bit stricter than necessary, but makes sure this works for pre-existing Provider bindings assertTrue(injector.getAllBindings().containsKey(Key.get(new TypeLiteral>() {}))); binding = injector.getExistingBinding(Key.get(new TypeLiteral>() {})); assertNotNull(binding); assertEquals(Provider.class, binding.getKey().getTypeLiteral().getRawType()); - assertEquals(Foo.class, ((Provider)binding.getProvider().get()).get().getClass()); - + assertEquals(Foo.class, ((Provider) binding.getProvider().get()).get().getClass()); + // 3) non-Provider Baz.class binding = injector.getExistingBinding(Key.get(Baz.class)); assertNotNull(binding); assertEquals(Baz.class, binding.getKey().getTypeLiteral().getRawType()); - + // 4) Provider class (should not already exist, because nothing used it yet). // the assertFalse is a bit stricter than necessary, but makes sure this works for non-pre-existing Provider bindings - assertFalse(injector.getAllBindings().containsKey(Key.get(new TypeLiteral>() {}))); + assertFalse( + injector.getAllBindings().containsKey(Key.get(new TypeLiteral>() {}))); binding = injector.getExistingBinding(Key.get(new TypeLiteral>() {})); assertNotNull(binding); assertEquals(Provider.class, binding.getKey().getTypeLiteral().getRawType()); - assertEquals(Baz.class, ((Provider)binding.getProvider().get()).get().getClass()); - + assertEquals(Baz.class, ((Provider) binding.getProvider().get()).get().getClass()); + // 5) non-Provider Bar, doesn't exist. assertNull(injector.getExistingBinding(Key.get(Bar.class))); - + // 6) Provider Bar, doesn't exist. assertNull(injector.getExistingBinding(Key.get(new TypeLiteral>() {}))); } - + private static class Foo {} + private static class Bar {} - private static class Baz { @SuppressWarnings("unused") @Inject Provider fooP; } - + + private static class Baz { + @SuppressWarnings("unused") + @Inject + Provider fooP; + } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/MessageTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/MessageTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/MessageTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/MessageTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,25 @@ +package com.google.inject.spi; + +import com.google.common.collect.Lists; +import java.util.List; +import junit.framework.TestCase; + +/** Tests for {@link Message}. */ +public class MessageTest extends TestCase { + + public void testMessageHashCodeVariesWithSource() { + String innerMessage = "This is the message."; + Message firstMessage = new Message(1, innerMessage); + Message secondMessage = new Message(2, innerMessage); + assertFalse(firstMessage.hashCode() == secondMessage.hashCode()); + } + + public void testMessageHashCodeVariesWithCause() { + String innerMessage = "This is the message."; + List sourceList = Lists.newArrayList(new Object()); + // the throwable argument of each Message below do not have value equality + Message firstMessage = new Message(sourceList, innerMessage, new Exception(innerMessage)); + Message secondMessage = new Message(sourceList, innerMessage, new Exception(innerMessage)); + assertFalse(firstMessage.hashCode() == secondMessage.hashCode()); + } +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,30 +36,32 @@ import com.google.inject.internal.util.StackTraceElements; import com.google.inject.name.Named; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.Set; +import junit.framework.TestCase; /** Tests for {@link ModuleAnnotatedMethodScanner} usage. */ public class ModuleAnnotatedMethodScannerTest extends TestCase { public void testScanning() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() {} + Module module = + new AbstractModule() { + + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } - @TestProvides @Named("foo") String foo() { - return "foo"; - } - - @TestProvides @Named("foo2") String foo2() { - return "foo2"; - } - }; + @TestProvides + @Named("foo2") + String foo2() { + return "foo2"; + } + }; Injector injector = Guice.createInjector(module, NamedMunger.module()); // assert no bindings named "foo" or "foo2" exist -- they were munged. @@ -69,76 +71,103 @@ Binding fooBinding = injector.getBinding(Key.get(String.class, named("foo-munged"))); Binding foo2Binding = injector.getBinding(Key.get(String.class, named("foo2-munged"))); // Validate the provider has a sane toString - assertEquals(methodName(TestProvides.class, "foo", module), - fooBinding.getProvider().toString()); - assertEquals(methodName(TestProvides.class, "foo2", module), - foo2Binding.getProvider().toString()); + assertEquals( + methodName(TestProvides.class, "foo", module), fooBinding.getProvider().toString()); + assertEquals( + methodName(TestProvides.class, "foo2", module), foo2Binding.getProvider().toString()); } public void testSkipSources() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - binder().skipSources(getClass()).install(new AbstractModule() { - @Override protected void configure() {} - - @TestProvides @Named("foo") String foo() { return "foo"; } - }); - } - }; + Module module = + new AbstractModule() { + @Override + protected void configure() { + binder() + .skipSources(getClass()) + .install( + new AbstractModule() { + + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }; Injector injector = Guice.createInjector(module, NamedMunger.module()); assertMungedBinding(injector, String.class, "foo", "foo"); } - + public void testWithSource() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - binder().withSource("source").install(new AbstractModule() { - @Override protected void configure() {} - - @TestProvides @Named("foo") String foo() { return "foo"; } - }); - } - }; + Module module = + new AbstractModule() { + @Override + protected void configure() { + binder() + .withSource("source") + .install( + new AbstractModule() { + + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }; Injector injector = Guice.createInjector(module, NamedMunger.module()); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testMoreThanOneClaimedAnnotationFails() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() {} + Module module = + new AbstractModule() { - @TestProvides @TestProvides2 String foo() { - return "foo"; - } - }; + @TestProvides + @TestProvides2 + String foo() { + return "foo"; + } + }; try { Guice.createInjector(module, NamedMunger.module()); fail(); - } catch(CreationException expected) { + } catch (CreationException expected) { assertEquals(1, expected.getErrorMessages().size()); - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "More than one annotation claimed by NamedMunger on method " - + module.getClass().getName() + ".foo(). Methods can only have " + + module.getClass().getName() + + ".foo(). Methods can only have " + "one annotation claimed per scanner."); } } private String methodName(Class annotation, String method, Object container) throws Exception { - return "@" + annotation.getName() + " " + return "@" + + annotation.getName() + + " " + StackTraceElements.forMember(container.getClass().getDeclaredMethod(method)); } - @Documented @Target(METHOD) @Retention(RUNTIME) + @Documented + @Target(METHOD) + @Retention(RUNTIME) private @interface TestProvides {} - @Documented @Target(METHOD) @Retention(RUNTIME) + @Documented + @Target(METHOD) + @Retention(RUNTIME) private @interface TestProvides2 {} private static class NamedMunger extends ModuleAnnotatedMethodScanner { static Module module() { return new AbstractModule() { - @Override protected void configure() { + @Override + protected void configure() { binder().scanModulesForAnnotatedMethods(new NamedMunger()); } }; @@ -155,15 +184,15 @@ } @Override - public Key prepareMethod(Binder binder, Annotation annotation, Key key, - InjectionPoint injectionPoint) { - return Key.get(key.getTypeLiteral(), - Names.named(((Named) key.getAnnotation()).value() + "-munged")); + public Key prepareMethod( + Binder binder, Annotation annotation, Key key, InjectionPoint injectionPoint) { + return Key.get( + key.getTypeLiteral(), Names.named(((Named) key.getAnnotation()).value() + "-munged")); } } - private void assertMungedBinding(Injector injector, Class clazz, String originalName, - Object expectedValue) { + private void assertMungedBinding( + Injector injector, Class clazz, String originalName, Object expectedValue) { assertNull(injector.getExistingBinding(Key.get(clazz, named(originalName)))); Binding fooBinding = injector.getBinding(Key.get(clazz, named(originalName + "-munged"))); assertEquals(expectedValue, fooBinding.getProvider().get()); @@ -176,13 +205,13 @@ } catch (CreationException expected) { Message m = Iterables.getOnlyElement(expected.getErrorMessages()); assertEquals( - "An exception was caught and reported. Message: Failing in the scanner.", - m.getMessage()); + "An exception was caught and reported. Message: Failing in the scanner.", m.getMessage()); assertEquals(IllegalStateException.class, m.getCause().getClass()); ElementSource source = (ElementSource) Iterables.getOnlyElement(m.getSources()); - assertEquals(SomeModule.class.getName(), - Iterables.getOnlyElement(source.getModuleClassNames())); - assertEquals(String.class.getName() + " " + SomeModule.class.getName() + ".aString()", + assertEquals( + SomeModule.class.getName(), Iterables.getOnlyElement(source.getModuleClassNames())); + assertEquals( + String.class.getName() + " " + SomeModule.class.getName() + ".aString()", source.toString()); } } @@ -190,51 +219,58 @@ public static class FailingScanner extends ModuleAnnotatedMethodScanner { static Module module() { return new AbstractModule() { - @Override protected void configure() { + @Override + protected void configure() { binder().scanModulesForAnnotatedMethods(new FailingScanner()); } }; } - @Override public Set> annotationClasses() { + @Override + public Set> annotationClasses() { return ImmutableSet.of(TestProvides.class); } - @Override public Key prepareMethod( + @Override + public Key prepareMethod( Binder binder, Annotation rawAnnotation, Key key, InjectionPoint injectionPoint) { throw new IllegalStateException("Failing in the scanner."); } } static class SomeModule extends AbstractModule { - @TestProvides String aString() { + @TestProvides + String aString() { return "Foo"; } - @Override protected void configure() {} } public void testChildInjectorInheritsScanner() { Injector parent = Guice.createInjector(NamedMunger.module()); - Injector child = parent.createChildInjector(new AbstractModule() { - @Override protected void configure() {} - - @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); + Injector child = + parent.createChildInjector( + new AbstractModule() { + + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); assertMungedBinding(child, String.class, "foo", "foo"); } public void testChildInjectorScannersDontImpactSiblings() { - Module module = new AbstractModule() { - @Override - protected void configure() {} - - @TestProvides @Named("foo") String foo() { - return "foo"; - } - }; + Module module = + new AbstractModule() { + + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }; Injector parent = Guice.createInjector(); Injector child = parent.createChildInjector(NamedMunger.module(), module); assertMungedBinding(child, String.class, "foo", "foo"); @@ -246,149 +282,245 @@ } public void testPrivateModuleInheritScanner_usingPrivateModule() { - Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() { - @Override protected void configure() {} - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new PrivateModule() { + @Override + protected void configure() {} + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModule_skipSourcesWithinPrivateModule() { - Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() { - @Override protected void configure() { - binder().skipSources(getClass()).install(new AbstractModule() { - @Override protected void configure() {} - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - } - }); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new PrivateModule() { + @Override + protected void configure() { + binder() + .skipSources(getClass()) + .install( + new AbstractModule() { + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModule_skipSourcesForPrivateModule() { - Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() { - @Override protected void configure() { - binder().skipSources(getClass()).install(new PrivateModule() { - @Override protected void configure() {} - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - }}); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new AbstractModule() { + @Override + protected void configure() { + binder() + .skipSources(getClass()) + .install( + new PrivateModule() { + @Override + protected void configure() {} + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModuleInheritScanner_usingPrivateBinder() { - Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() { - @Override protected void configure() { - binder().newPrivateBinder().install(new AbstractModule() { - @Override protected void configure() {} - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - } - }); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new AbstractModule() { + @Override + protected void configure() { + binder() + .newPrivateBinder() + .install( + new AbstractModule() { + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModuleInheritScanner_skipSourcesFromPrivateBinder() { - Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() { - @Override protected void configure() { - binder().newPrivateBinder().skipSources(getClass()).install(new AbstractModule() { - @Override protected void configure() {} - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - } - }); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new AbstractModule() { + @Override + protected void configure() { + binder() + .newPrivateBinder() + .skipSources(getClass()) + .install( + new AbstractModule() { + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModuleInheritScanner_skipSourcesFromPrivateBinder2() { - Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() { - @Override protected void configure() { - binder().skipSources(getClass()).newPrivateBinder().install(new AbstractModule() { - @Override protected void configure() {} - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - } - }); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new AbstractModule() { + @Override + protected void configure() { + binder() + .skipSources(getClass()) + .newPrivateBinder() + .install( + new AbstractModule() { + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModuleScannersDontImpactSiblings_usingPrivateModule() { - Injector injector = Guice.createInjector(new PrivateModule() { - @Override protected void configure() { - install(NamedMunger.module()); - } - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }, new PrivateModule() { - @Override protected void configure() {} - - // ignored! (because the scanner doesn't run over this module) - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); + Injector injector = + Guice.createInjector( + new PrivateModule() { + @Override + protected void configure() { + install(NamedMunger.module()); + } + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }, + new PrivateModule() { + @Override + protected void configure() {} + + // ignored! (because the scanner doesn't run over this module) + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModuleScannersDontImpactSiblings_usingPrivateBinder() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - binder().newPrivateBinder().install(new AbstractModule() { - @Override protected void configure() { - install(NamedMunger.module()); - } - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - } - }, new AbstractModule() { - @Override protected void configure() { - binder().newPrivateBinder().install(new AbstractModule() { - @Override protected void configure() {} - - // ignored! (because the scanner doesn't run over this module) - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - }}); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder() + .newPrivateBinder() + .install( + new AbstractModule() { + @Override + protected void configure() { + install(NamedMunger.module()); + } + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }, + new AbstractModule() { + @Override + protected void configure() { + binder() + .newPrivateBinder() + .install( + new AbstractModule() { + + // ignored! (because the scanner doesn't run over this module) + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } public void testPrivateModuleWithinPrivateModule() { - Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() { - @Override protected void configure() { - expose(Key.get(String.class, named("foo-munged"))); - install(new PrivateModule() { - @Override protected void configure() {} - - @Exposed @TestProvides @Named("foo") String foo() { - return "foo"; - } - }); - } - }); + Injector injector = + Guice.createInjector( + NamedMunger.module(), + new PrivateModule() { + @Override + protected void configure() { + expose(Key.get(String.class, named("foo-munged"))); + install( + new PrivateModule() { + @Override + protected void configure() {} + + @Exposed + @TestProvides + @Named("foo") + String foo() { + return "foo"; + } + }); + } + }); assertMungedBinding(injector, String.class, "foo", "foo"); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ModuleRewriterTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ModuleRewriterTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ModuleRewriterTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ModuleRewriterTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,24 +27,22 @@ import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.util.List; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class ModuleRewriterTest extends TestCase { public void testRewriteBindings() { // create a module the binds String.class and CharSequence.class - Module module = new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("Pizza"); - bind(CharSequence.class).toInstance("Wine"); - } - }; + Module module = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("Pizza"); + bind(CharSequence.class).toInstance("Wine"); + } + }; // record the elements from that module List elements = Elements.getElements(module); @@ -52,17 +50,19 @@ // create a rewriter that rewrites the binding to 'Wine' with a binding to 'Beer' List rewritten = Lists.newArrayList(); for (Element element : elements) { - element = element.acceptVisitor(new DefaultElementVisitor() { - @Override public Element visit(Binding binding) { - T target = binding.acceptTargetVisitor(Elements.getInstanceVisitor()); - if ("Wine".equals(target)) { - return null; - } - else { - return binding; - } - } - }); + element = + element.acceptVisitor( + new DefaultElementVisitor() { + @Override + public Element visit(Binding binding) { + T target = binding.acceptTargetVisitor(Elements.getInstanceVisitor()); + if ("Wine".equals(target)) { + return null; + } else { + return binding; + } + } + }); if (element != null) { rewritten.add(element); } @@ -81,25 +81,32 @@ } public void testGetProviderAvailableAtInjectMembersTime() { - Module module = new AbstractModule() { - public void configure() { - final Provider stringProvider = getProvider(String.class); + Module module = + new AbstractModule() { + @Override + public void configure() { + final Provider stringProvider = getProvider(String.class); + + bind(String.class) + .annotatedWith(Names.named("2")) + .toProvider( + new Provider() { + private String value; + + @Inject + void initialize() { + value = stringProvider.get(); + } + + @Override + public String get() { + return value; + } + }); - bind(String.class).annotatedWith(Names.named("2")).toProvider(new Provider() { - private String value; - - @Inject void initialize() { - value = stringProvider.get(); + bind(String.class).toInstance("A"); } - - public String get() { - return value; - } - }); - - bind(String.class).toInstance("A"); - } - }; + }; // the module works fine normally Injector injector = Guice.createInjector(module); diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ModuleSourceTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ModuleSourceTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ModuleSourceTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ModuleSourceTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -3,30 +3,30 @@ import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Module; - import junit.framework.TestCase; -/** - * Tests for {@link ModuleSource}. - */ +/** Tests for {@link ModuleSource}. */ public class ModuleSourceTest extends TestCase { - private static final StackTraceElement BINDER_INSTALL = - new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", - "Unknown Source", 235 /* line number*/); - + private static final StackTraceElement BINDER_INSTALL = + new StackTraceElement( + "com.google.inject.spi.Elements$RecordingBinder", + "install", + "Unknown Source", + 235 /* line number*/); + public void testOneModule() { ModuleSource moduleSource = createWithSizeOne(); - checkSizeOne(moduleSource); + checkSizeOne(moduleSource); } - + public void testTwoModules() { ModuleSource moduleSource = createWithSizeTwo(); checkSizeTwo(moduleSource); moduleSource = moduleSource.getParent(); checkSizeOne(moduleSource); } - + public void testThreeModules() { ModuleSource moduleSource = createWithSizeThree(); checkSizeThree(moduleSource); @@ -41,66 +41,68 @@ assertEquals(1, moduleSource.getStackTraceSize()); // Check call stack StackTraceElement[] callStack = moduleSource.getStackTrace(); - assertEquals(BINDER_INSTALL, callStack[0]); + assertEquals(BINDER_INSTALL, callStack[0]); } - + private void checkSizeTwo(ModuleSource moduleSource) { assertEquals(2, moduleSource.size()); assertEquals(3, moduleSource.getStackTraceSize()); // Check call stack StackTraceElement[] callStack = moduleSource.getStackTrace(); - assertEquals(BINDER_INSTALL, callStack[0]); + assertEquals(BINDER_INSTALL, callStack[0]); assertEquals( new StackTraceElement( "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100), callStack[1]); - assertEquals(BINDER_INSTALL, callStack[2]); + assertEquals(BINDER_INSTALL, callStack[2]); } - + private void checkSizeThree(ModuleSource moduleSource) { assertEquals(3, moduleSource.size()); assertEquals(7, moduleSource.getStackTraceSize()); // Check call stack StackTraceElement[] callStack = moduleSource.getStackTrace(); - assertEquals(BINDER_INSTALL, callStack[0]); + assertEquals(BINDER_INSTALL, callStack[0]); assertEquals(new StackTraceElement("class1", "method1", "Unknown Source", 1), callStack[1]); - assertEquals(new StackTraceElement("class2", "method2", "Unknown Source", 2), callStack[2]); + assertEquals(new StackTraceElement("class2", "method2", "Unknown Source", 2), callStack[2]); assertEquals( new StackTraceElement( "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200), - callStack[3]); - assertEquals(BINDER_INSTALL, callStack[4]); + callStack[3]); + assertEquals(BINDER_INSTALL, callStack[4]); assertEquals( new StackTraceElement( "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100), callStack[5]); - assertEquals(BINDER_INSTALL, callStack[6]); + assertEquals(BINDER_INSTALL, callStack[6]); } - + private ModuleSource createWithSizeOne() { StackTraceElement[] partialCallStack = new StackTraceElement[1]; - partialCallStack[0] = BINDER_INSTALL; + partialCallStack[0] = BINDER_INSTALL; return new ModuleSource(new A(), partialCallStack); } - + private ModuleSource createWithSizeTwo() { ModuleSource moduleSource = createWithSizeOne(); StackTraceElement[] partialCallStack = new StackTraceElement[2]; partialCallStack[0] = BINDER_INSTALL; - partialCallStack[1] = new StackTraceElement( - "com.google.inject.spi.moduleSourceTest$A", "configure", "moduleSourceTest.java", 100); + partialCallStack[1] = + new StackTraceElement( + "com.google.inject.spi.moduleSourceTest$A", "configure", "moduleSourceTest.java", 100); return moduleSource.createChild(new B(), partialCallStack); } - + private ModuleSource createWithSizeThree() { ModuleSource moduleSource = createWithSizeTwo(); StackTraceElement[] partialCallStack = new StackTraceElement[4]; partialCallStack[0] = BINDER_INSTALL; partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1); partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2); - partialCallStack[3] = new StackTraceElement( - "com.google.inject.spi.moduleSourceTest$B", "configure", "moduleSourceTest.java", 200); + partialCallStack[3] = + new StackTraceElement( + "com.google.inject.spi.moduleSourceTest$B", "configure", "moduleSourceTest.java", 200); return moduleSource.createChild(new C(), partialCallStack); } @@ -110,16 +112,14 @@ install(new B()); } } - + private static class B implements Module { @Override public void configure(Binder binder) { binder.install(new C()); } } - + private static class C extends AbstractModule { - @Override - public void configure() {} } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ProviderMethodsTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ProviderMethodsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ProviderMethodsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ProviderMethodsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +33,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; +import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.ProvisionException; import com.google.inject.Singleton; @@ -46,9 +47,6 @@ import com.google.inject.name.Names; import com.google.inject.util.Providers; import com.google.inject.util.Types; - -import junit.framework.TestCase; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -62,10 +60,10 @@ import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.Logger; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ +@SuppressWarnings("ProvidesMethodOutsideOfModule") public class ProviderMethodsTest extends TestCase implements Module { @SuppressWarnings("unchecked") @@ -82,16 +80,15 @@ assertSame(bob.getDaughter(), clone.getDaughter()); Key soleBobKey = Key.get(Bob.class, Sole.class); - assertSame( - injector.getInstance(soleBobKey), - injector.getInstance(soleBobKey) - ); + assertSame(injector.getInstance(soleBobKey), injector.getInstance(soleBobKey)); } + @Override public void configure(Binder binder) {} interface Bob { String getName(); + Dagny getDaughter(); } @@ -102,10 +99,12 @@ @Provides Bob provideBob(final Dagny dagny) { return new Bob() { + @Override public String getName() { return "A Bob"; } + @Override public Dagny getDaughter() { return dagny; } @@ -117,10 +116,12 @@ @Sole Bob provideSoleBob(final Dagny dagny) { return new Bob() { + @Override public String getName() { return "Only Bob"; } + @Override public Dagny getDaughter() { return dagny; } @@ -131,6 +132,7 @@ @Singleton Dagny provideDagny() { return new Dagny() { + @Override public int getAge() { return 1; } @@ -138,100 +140,106 @@ } @Retention(RUNTIME) - @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @BindingAnnotation @interface Sole {} + public void testCircularDependency() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + + @Provides + Foo newFoo(final Bar bar) { + return new Foo() { + + @Override + public Bar getBar() { + return bar; + } + + @Override + public int getI() { + return 5; + } + }; + } + + @Provides + Bar newBar(final Foo foo) { + return new Bar() { + + @Override + public Foo getFoo() { + return foo; + } + + @Override + public int getI() { + return 10; + } + }; + } + }); + + Foo foo = injector.getInstance(Foo.class); + assertEquals(5, foo.getI()); + assertEquals(10, foo.getBar().getI()); + assertEquals(5, foo.getBar().getFoo().getI()); + } + + public interface Foo { + Bar getBar(); + int getI(); + } -// We'll have to make getProvider() support circular dependencies before this -// will work. -// -// public void testCircularDependency() { -// Injector injector = Guice.createInjector(new Module() { -// public void configure(Binder binder) { -// binder.install(ProviderMethods.from(ProviderMethodsTest.this)); -// } -// }); -// -// Foo foo = injector.getInstance(Foo.class); -// assertEquals(5, foo.getI()); -// assertEquals(10, foo.getBar().getI()); -// assertEquals(5, foo.getBar().getFoo().getI()); -// } -// -// interface Foo { -// Bar getBar(); -// int getI(); -// } -// -// interface Bar { -// Foo getFoo(); -// int getI(); -// } -// -// @Provides Foo newFoo(final Bar bar) { -// return new Foo() { -// -// public Bar getBar() { -// return bar; -// } -// -// public int getI() { -// return 5; -// } -// }; -// } -// -// @Provides Bar newBar(final Foo foo) { -// return new Bar() { -// -// public Foo getFoo() { -// return foo; -// } -// -// public int getI() { -// return 10; -// } -// }; -// } + public interface Bar { + Foo getFoo(); + int getI(); + } public void testMultipleBindingAnnotations() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() {} + Guice.createInjector( + new AbstractModule() { - @Provides @Named("A") @Blue - public String provideString() { - return "a"; - } - }); + @Provides + @Named("A") + @Blue + public String provideString() { + return "a"; + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), - "more than one annotation annotated with @BindingAnnotation:", "Named", "Blue", - "at " + getClass().getName(), ".provideString(ProviderMethodsTest.java:"); + assertContains( + expected.getMessage(), + "more than one annotation annotated with @BindingAnnotation:", + "Named", + "Blue", + "at " + getClass().getName(), + ".provideString(ProviderMethodsTest.java:"); } - } @Retention(RUNTIME) - @BindingAnnotation @interface Blue {} + @BindingAnnotation + @interface Blue {} public void testGenericProviderMethods() { - Injector injector = Guice.createInjector( - new ProvideTs("A", "B") {}, new ProvideTs(1, 2) {}); + Injector injector = + Guice.createInjector(new ProvideTs("A", "B") {}, new ProvideTs(1, 2) {}); assertEquals("A", injector.getInstance(Key.get(String.class, Names.named("First")))); assertEquals("B", injector.getInstance(Key.get(String.class, Names.named("Second")))); - assertEquals(ImmutableSet.of("A", "B"), - injector.getInstance(Key.get(Types.setOf(String.class)))); + assertEquals( + ImmutableSet.of("A", "B"), injector.getInstance(Key.get(Types.setOf(String.class)))); assertEquals(1, injector.getInstance(Key.get(Integer.class, Names.named("First"))).intValue()); assertEquals(2, injector.getInstance(Key.get(Integer.class, Names.named("Second"))).intValue()); - assertEquals(ImmutableSet.of(1, 2), - injector.getInstance(Key.get(Types.setOf(Integer.class)))); + assertEquals(ImmutableSet.of(1, 2), injector.getInstance(Key.get(Types.setOf(Integer.class)))); } abstract class ProvideTs extends AbstractModule { @@ -243,31 +251,38 @@ this.second = second; } - @Override protected void configure() {} - - @Named("First") @Provides T provideFirst() { + @Named("First") + @Provides + T provideFirst() { return first; } - @Named("Second") @Provides T provideSecond() { + @Named("Second") + @Provides + T provideSecond() { return second; } - @Provides Set provideBoth(@Named("First") T first, @Named("Second") T second) { + @Provides + Set provideBoth(@Named("First") T first, @Named("Second") T second) { return ImmutableSet.of(first, second); } } public void testAutomaticProviderMethods() { - Injector injector = Guice.createInjector((Module) new AbstractModule() { - @Override protected void configure() { } - private int next = 1; - - @Provides @Named("count") - public Integer provideCount() { - return next++; - } - }); + Injector injector = + Guice.createInjector( + (Module) + new AbstractModule() { + + private int next = 1; + + @Provides + @Named("count") + public Integer provideCount() { + return next++; + } + }); assertEquals(1, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue()); assertEquals(2, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue()); @@ -279,15 +294,19 @@ * binding of the provider methods' types. */ public void testAutomaticProviderMethodsDoNotCauseDoubleBinding() { - Module installsSelf = new AbstractModule() { - @Override protected void configure() { - install(this); - bind(Integer.class).toInstance(5); - } - @Provides public String provideString(Integer count) { - return "A" + count; - } - }; + Module installsSelf = + new AbstractModule() { + @Override + protected void configure() { + install(this); + bind(Integer.class).toInstance(5); + } + + @Provides + public String provideString(Integer count) { + return "A" + count; + } + }; Injector injector = Guice.createInjector(installsSelf); assertEquals("A5", injector.getInstance(String.class)); @@ -297,20 +316,28 @@ final List strings = ImmutableList.of("A", "B", "C"); final List numbers = ImmutableList.of(1, 2, 3); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - @SuppressWarnings("unchecked") - Key> listOfSupertypesOfInteger = (Key>) - Key.get(Types.listOf(Types.supertypeOf(Integer.class))); - bind(listOfSupertypesOfInteger).toInstance(numbers); - } - @Provides public List provideCharSequences() { - return strings; - } - @Provides public Class provideType() { - return Float.class; - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + @SuppressWarnings("unchecked") + Key> listOfSupertypesOfInteger = + (Key>) + Key.get(Types.listOf(Types.supertypeOf(Integer.class))); + bind(listOfSupertypesOfInteger).toInstance(numbers); + } + + @Provides + public List provideCharSequences() { + return strings; + } + + @Provides + public Class provideType() { + return Float.class; + } + }); assertSame(strings, injector.getInstance(HasWildcardInjection.class).charSequences); assertSame(numbers, injector.getInstance(HasWildcardInjection.class).numbers); @@ -324,40 +351,52 @@ } public void testProviderMethodDependenciesAreExposed() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(50); - bindConstant().annotatedWith(Names.named("units")).to("Kg"); - } - @Provides @Named("weight") String provideWeight(Integer count, @Named("units") String units) { - return count + units; - } - }; + Module module = + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(50); + bindConstant().annotatedWith(Names.named("units")).to("Kg"); + } + + @Provides + @Named("weight") + String provideWeight(Integer count, @Named("units") String units) { + return count + units; + } + }; Injector injector = Guice.createInjector(module); - ProviderInstanceBinding binding = (ProviderInstanceBinding) injector.getBinding( - Key.get(String.class, Names.named("weight"))); + ProviderInstanceBinding binding = + (ProviderInstanceBinding) + injector.getBinding(Key.get(String.class, Names.named("weight"))); Method method = - module.getClass().getDeclaredMethod("provideWeight", Integer.class, String.class); + module.getClass().getDeclaredMethod("provideWeight", Integer.class, String.class); InjectionPoint point = new InjectionPoint(TypeLiteral.get(module.getClass()), method, false); - assertEquals(ImmutableSet.>of( - new Dependency(point, Key.get(Integer.class), false, 0), - new Dependency(point, Key.get(String.class, Names.named("units")), false, 1)), - binding.getDependencies()); + assertEquals( + ImmutableSet.>of( + new Dependency(point, Key.get(Integer.class), false, 0), + new Dependency(point, Key.get(String.class, Names.named("units")), false, 1)), + binding.getDependencies()); } public void testNonModuleProviderMethods() { - final Object methodsObject = new Object() { - @Provides @Named("foo") String provideFoo() { - return "foo-value"; - } - }; - - Module module = new AbstractModule() { - @Override protected void configure() { - install(ProviderMethodsModule.forObject(methodsObject)); - } - }; + final Object methodsObject = + new Object() { + @Provides + @Named("foo") + String provideFoo() { + return "foo-value"; + } + }; + + Module module = + new AbstractModule() { + @Override + protected void configure() { + install(ProviderMethodsModule.forObject(methodsObject)); + } + }; Injector injector = Guice.createInjector(module); @@ -369,7 +408,8 @@ assertEquals(1, elements.size()); Element element = elements.get(0); - assertTrue(element + " instanceof ProviderInstanceBinding", + assertTrue( + element + " instanceof ProviderInstanceBinding", element instanceof ProviderInstanceBinding); ProviderInstanceBinding binding = (ProviderInstanceBinding) element; @@ -381,21 +421,24 @@ public void testVoidProviderMethods() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() {} + Guice.createInjector( + new AbstractModule() { - @Provides void provideFoo() {} - }); + @Provides + void provideFoo() {} + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Provider methods must return a value. Do not return void.", - getClass().getName(), ".provideFoo(ProviderMethodsTest.java:"); + getClass().getName(), + ".provideFoo(ProviderMethodsTest.java:"); } } public void testInjectsJustOneLogger() { - AtomicReference loggerRef = new AtomicReference(); + AtomicReference loggerRef = new AtomicReference<>(); Injector injector = Guice.createInjector(new FooModule(loggerRef)); assertNull(loggerRef.get()); @@ -415,59 +458,67 @@ this.loggerRef = loggerRef; } - @Override protected void configure() {} - @SuppressWarnings("unused") - @Provides Integer foo(Logger logger) { + @Provides + Integer foo(Logger logger) { loggerRef.set(logger); return 42; } } public void testSpi() throws Exception { - Module m1 = new AbstractModule() { - @Override protected void configure() {} - @Provides @Named("foo") String provideFoo(Integer dep) { return "foo"; } - }; - Module m2 = new AbstractModule() { - @Override protected void configure() {} - @Provides Integer provideInt(@Named("foo") String dep) { return 42; } - }; + Module m1 = + new AbstractModule() { + + @Provides + @Named("foo") + String provideFoo(Integer dep) { + return "foo"; + } + }; + Module m2 = + new AbstractModule() { + + @Provides + Integer provideInt(@Named("foo") String dep) { + return 42; + } + }; Injector injector = Guice.createInjector(m1, m2); - Binding stringBinding = - injector.getBinding(Key.get(String.class, Names.named("foo"))); + Binding stringBinding = injector.getBinding(Key.get(String.class, Names.named("foo"))); ProvidesMethodBinding stringMethod = stringBinding.acceptTargetVisitor(new BindingCapturer()); assertEquals(m1, stringMethod.getEnclosingInstance()); - assertEquals(m1.getClass().getDeclaredMethod("provideFoo", Integer.class), - stringMethod.getMethod()); - assertEquals(((HasDependencies) stringBinding).getDependencies(), - stringMethod.getDependencies()); + assertEquals( + m1.getClass().getDeclaredMethod("provideFoo", Integer.class), stringMethod.getMethod()); + assertEquals( + ((HasDependencies) stringBinding).getDependencies(), stringMethod.getDependencies()); assertEquals(Key.get(String.class, Names.named("foo")), stringMethod.getKey()); Binding intBinding = injector.getBinding(Integer.class); ProvidesMethodBinding intMethod = intBinding.acceptTargetVisitor(new BindingCapturer()); assertEquals(m2, intMethod.getEnclosingInstance()); - assertEquals(m2.getClass().getDeclaredMethod("provideInt", String.class), - intMethod.getMethod()); - assertEquals(((HasDependencies) intBinding).getDependencies(), - intMethod.getDependencies()); + assertEquals( + m2.getClass().getDeclaredMethod("provideInt", String.class), intMethod.getMethod()); + assertEquals(((HasDependencies) intBinding).getDependencies(), intMethod.getDependencies()); assertEquals(Key.get(Integer.class), intMethod.getKey()); - } - private static class BindingCapturer extends DefaultBindingTargetVisitor> + private static class BindingCapturer + extends DefaultBindingTargetVisitor> implements ProvidesMethodTargetVisitor> { + @Override @SuppressWarnings("unchecked") public ProvidesMethodBinding visit( ProvidesMethodBinding providesMethodBinding) { - return (ProvidesMethodBinding)providesMethodBinding; + return (ProvidesMethodBinding) providesMethodBinding; } - @Override protected ProvidesMethodBinding visitOther(Binding binding) { + @Override + protected ProvidesMethodBinding visitOther(Binding binding) { throw new IllegalStateException("unexpected visit of: " + binding); } } @@ -477,30 +528,33 @@ assertEquals(42, injector.getInstance(Integer.class).intValue()); assertEquals(42L, injector.getInstance(Long.class).longValue()); - assertEquals(42D, injector.getInstance(Double.class).doubleValue()); - assertEquals(42F, injector.getInstance(Float.class).floatValue()); + assertEquals(42D, injector.getInstance(Double.class).doubleValue(), 0.0); + assertEquals(42F, injector.getInstance(Float.class).floatValue(), 0.0f); } private static class VisibilityModule extends AbstractModule { - @Override protected void configure() {} @SuppressWarnings("unused") - @Provides Integer foo() { + @Provides + Integer foo() { return 42; } @SuppressWarnings("unused") - @Provides private Long bar() { + @Provides + private Long bar() { return 42L; } @SuppressWarnings("unused") - @Provides protected Double baz() { + @Provides + protected Double baz() { return 42D; } @SuppressWarnings("unused") - @Provides public Float quux() { + @Provides + public Float quux() { return 42F; } } @@ -511,7 +565,8 @@ fail("Expected injector creation failure"); } catch (CreationException expected) { // both of our super class bindings cause errors - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "A binding to java.lang.Long was already configured", "A binding to java.lang.Integer was already configured"); } @@ -521,29 +576,32 @@ Injector injector = Guice.createInjector(new Sub1Module()); assertEquals(42, injector.getInstance(Integer.class).intValue()); assertEquals(42L, injector.getInstance(Long.class).longValue()); - assertEquals(42D, injector.getInstance(Double.class).doubleValue()); + assertEquals(42D, injector.getInstance(Double.class).doubleValue(), 0.0); } private static class BaseModule extends AbstractModule { - @Override protected void configure() {} - @Provides Integer foo() { + @Provides + Integer foo() { return 42; } - @Provides Long bar() { + @Provides + Long bar() { return 42L; } } private static class Sub1Module extends BaseModule { - @Provides Double baz() { + @Provides + Double baz() { return 42D; } } private static class Sub2Module extends BaseModule { - @Provides Float quux() { + @Provides + Float quux() { return 42F; } } @@ -561,14 +619,16 @@ String barCallerClass = "not_set_bar"; String fooCallerClass = "not_set_foo"; - @Override protected void configure() {} - - @Provides @Singleton Integer foo() { + @Provides + @Singleton + Integer foo() { this.fooCallerClass = new Exception().getStackTrace()[1].getClassName(); return 42; } - @Provides @Singleton Long bar() { + @Provides + @Singleton + Long bar() { this.barCallerClass = new Exception().getStackTrace()[1].getClassName(); return 42L; } @@ -577,21 +637,25 @@ public void testShareFastClassWithSuperClass() { CallerInspecterSubClassModule module = new CallerInspecterSubClassModule(); Guice.createInjector(Stage.PRODUCTION, module); - assertEquals("Expected provider methods in the same class to share fastclass classes", - module.fooCallerClass, module.barCallerClass); + assertEquals( + "Expected provider methods in the same class to share fastclass classes", + module.fooCallerClass, + module.barCallerClass); assertFalse( "Did not expect provider methods in the subclasses to share fastclass classes " + "with their parent classes", module.bazCallerClass.equals(module.barCallerClass)); } - private static class CallerInspecterSubClassModule extends CallerInspecterModule { String bazCallerClass; - @Override protected void configure() {} + @Override + protected void configure() {} - @Provides @Singleton Double baz() { + @Provides + @Singleton + Double baz() { this.bazCallerClass = new Exception().getStackTrace()[1].getClassName(); return 42D; } @@ -599,33 +663,47 @@ /*end[AOP]*/ static class SuperClassModule extends AbstractModule { - @Override protected void configure() {} - @Provides Number providerMethod() { + + @Provides + Number providerMethod() { return 1D; } - @Provides @Named("rawlist") List rawProvider(@Named("list") List f) { + + @Provides + @Named("rawlist") + List rawProvider(@Named("list") List f) { return f; } - @Provides @Named("unrawlist") List rawParameterProvider(@Named("rawlist") List f) { + @Provides + @Named("unrawlist") + List rawParameterProvider(@Named("rawlist") List f) { return f; } - @Provides @Named("list") List annotatedGenericProviderMethod() { + @Provides + @Named("list") + List annotatedGenericProviderMethod() { return new ArrayList(); } - @Provides @Named("collection") Collection annotatedGenericParameterProviderMethod( - @Named("list") List foo) { + + @Provides + @Named("collection") + Collection annotatedGenericParameterProviderMethod(@Named("list") List foo) { return foo; } - @Provides private String privateProviderMethod() { + + @Provides + private String privateProviderMethod() { return "hello"; } } public void testOverrideProviderMethod_overrideHasProvides() { class SubClassModule extends SuperClassModule { - @Override @Provides Number providerMethod() { + @Override + @Provides + Number providerMethod() { return 2D; } } @@ -633,7 +711,8 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()", "overridden by: " + SubClassModule.class.getName() + ".providerMethod()"); @@ -642,7 +721,10 @@ public void testOverrideProviderMethod_overrideHasProvides_withNewAnnotation() { class SubClassModule extends SuperClassModule { - @Override @Provides @Named("foo") Number providerMethod() { + @Override + @Provides + @Named("foo") + Number providerMethod() { return 2D; } } @@ -650,7 +732,8 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()", "overridden by: " + SubClassModule.class.getName() + ".providerMethod()"); @@ -659,7 +742,8 @@ public void testOverrideProviderMethod_overrideDoesntHaveProvides() { class SubClassModule extends SuperClassModule { - @Override Number providerMethod() { + @Override + Number providerMethod() { return 2D; } } @@ -667,15 +751,19 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()", "overridden by: " + SubClassModule.class.getName() + ".providerMethod()"); } } + public void testOverrideProviderMethod_overrideDoesntHaveProvides_withNewAnnotation() { class SubClassModule extends SuperClassModule { - @Override @Named("foo") Number providerMethod() { + @Override + @Named("foo") + Number providerMethod() { return 2D; } } @@ -683,17 +771,18 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()", "overridden by: " + SubClassModule.class.getName() + ".providerMethod()"); } } - public void testOverrideProviderMethod_covariantOverrideDoesntHaveProvides() { class SubClassModule extends SuperClassModule { - @Override Double providerMethod() { + @Override + Double providerMethod() { return 2D; } } @@ -701,7 +790,8 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()", "overridden by: " + SubClassModule.class.getName() + ".providerMethod()"); @@ -710,7 +800,9 @@ public void testOverrideProviderMethod_covariantOverrideHasProvides() { class SubClassModule extends SuperClassModule { - @Override @Provides Double providerMethod() { + @Override + @Provides + Double providerMethod() { return 2D; } } @@ -718,7 +810,8 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()", "overridden by: " + SubClassModule.class.getName() + ".providerMethod()"); @@ -737,7 +830,8 @@ public void testOverrideProviderMethod_subclassRawTypes_returnType() { class SubClassModule extends SuperClassModule { - @Override List annotatedGenericProviderMethod() { + @Override + List annotatedGenericProviderMethod() { return super.annotatedGenericProviderMethod(); } } @@ -745,9 +839,11 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", - "@Provides method: " + SuperClassModule.class.getName() + "@Provides method: " + + SuperClassModule.class.getName() + ".annotatedGenericProviderMethod()", "overridden by: " + SubClassModule.class.getName() + ".annotatedGenericProviderMethod()"); } @@ -755,7 +851,8 @@ public void testOverrideProviderMethod_subclassRawTypes_parameterType() { class SubClassModule extends SuperClassModule { - @Override Collection annotatedGenericParameterProviderMethod(List foo) { + @Override + Collection annotatedGenericParameterProviderMethod(List foo) { return super.annotatedGenericParameterProviderMethod(foo); } } @@ -763,11 +860,14 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", - "@Provides method: " + SuperClassModule.class.getName() + "@Provides method: " + + SuperClassModule.class.getName() + ".annotatedGenericParameterProviderMethod()", - "overridden by: " + SubClassModule.class.getName() + "overridden by: " + + SubClassModule.class.getName() + ".annotatedGenericParameterProviderMethod()"); } } @@ -775,7 +875,8 @@ public void testOverrideProviderMethod_superclassRawTypes_returnType() { class SubClassModule extends SuperClassModule { // remove the rawtype from the override - @Override List rawProvider(List f) { + @Override + List rawProvider(List f) { return f; } } @@ -783,7 +884,8 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + SuperClassModule.class.getName() + ".rawProvider()", "overridden by: " + SubClassModule.class.getName() + ".rawProvider()"); @@ -791,7 +893,8 @@ } abstract static class GenericSuperModule extends AbstractModule { - @Provides String provide(T thing) { + @Provides + String provide(T thing) { return thing.toString(); } } @@ -800,11 +903,13 @@ // bridge method) public void testOverrideProviderMethod_erasureBasedOverrides() { class SubClassModule extends GenericSuperModule { - @Override String provide(Integer thing) { + @Override + String provide(Integer thing) { return thing.toString(); } - @Override protected void configure() { + @Override + protected void configure() { bind(Integer.class).toInstance(3); } } @@ -812,19 +917,23 @@ Guice.createInjector(new SubClassModule()); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Overriding @Provides methods is not allowed.", "@Provides method: " + GenericSuperModule.class.getName() + ".provide()", "overridden by: " + SubClassModule.class.getName() + ".provide()"); } } - class RestrictedSuper extends AbstractModule { - @Provides public String provideFoo() { return "foo"; } - @Override protected void configure() {} + static class RestrictedSuper extends AbstractModule { + @Provides + public String provideFoo() { + return "foo"; + } + } - public class ExposedSub extends RestrictedSuper {} + public static class ExposedSub extends RestrictedSuper {} public void testOverrideProviderMethod_increasedVisibility() { // ensure we don't detect the synthetic provideFoo method in ExposedSub as an override (it is, @@ -837,11 +946,15 @@ } static class ModuleImpl extends AbstractModule implements ProviderInterface { - @Override protected void configure() {} - @Provides public String getT() { + + @Override + @Provides + public String getT() { return "string"; } - @Provides public Object getObject() { + + @Provides + public Object getObject() { return new Object(); } /* javac will synthesize a bridge method for getT with the types erased, equivalent to: @@ -853,29 +966,53 @@ Guice.createInjector(new ModuleImpl()); } - public void testNullability() throws Exception { - Module module = new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toProvider(Providers.of(null)); - } - - @SuppressWarnings("unused") - @Provides - Integer fail(String foo) { - return 1; - } + public void testScopedProviderMethodThrowsException() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + + @Provides + @Singleton + int provideInt() { + throw new RuntimeException("boom"); + } + }); + Provider intProvider = injector.getProvider(Integer.class); + try { + intProvider.get(); + fail(); + } catch (ProvisionException pe) { + // by default assertContains asserts that the last item doesn't repeat... which is the main + // thing we are testing for + assertContains(pe.getMessage(), "java.lang.RuntimeException: boom", "provideInt"); + } + } - @SuppressWarnings("unused") - @Provides - Long succeed(@Nullable String foo) { - return 2L; - } - }; + public void testNullability() throws Exception { + Module module = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toProvider(Providers.of(null)); + } + + @SuppressWarnings("unused") + @Provides + Integer fail(String foo) { + return 1; + } + + @SuppressWarnings("unused") + @Provides + Long succeed(@Nullable String foo) { + return 2L; + } + }; Injector injector = Guice.createInjector(module); - InjectionPoint fooPoint = InjectionPoint.forMethod( - module.getClass().getDeclaredMethod("fail", String.class), - TypeLiteral.get(module.getClass())); + InjectionPoint fooPoint = + InjectionPoint.forMethod( + module.getClass().getDeclaredMethod("fail", String.class), + TypeLiteral.get(module.getClass())); Dependency fooDependency = Iterables.getOnlyElement(fooPoint.getDependencies()); runNullableTest(injector, fooDependency, module); @@ -883,6 +1020,33 @@ injector.getInstance(Long.class); } + public void testModuleBindings() throws Exception { + Module module = + new AbstractModule() { + + @Provides + Integer fail() { + return 1; + } + }; + // sanity check that the injector works + Injector injector = Guice.createInjector(module); + assertEquals(1, injector.getInstance(Integer.class).intValue()); + ProviderInstanceBinding injectorBinding = + (ProviderInstanceBinding) injector.getBinding(Integer.class); + assertEquals(1, injectorBinding.getUserSuppliedProvider().get()); + + ProviderInstanceBinding moduleBinding = + (ProviderInstanceBinding) Iterables.getOnlyElement(Elements.getElements(module)); + try { + moduleBinding.getUserSuppliedProvider().get(); + fail(); + } catch (IllegalStateException ise) { + assertEquals( + "This Provider cannot be used until the Injector has been created.", ise.getMessage()); + } + } + private void runNullableTest(Injector injector, Dependency dependency, Module module) { switch (InternalFlags.getNullableProvidesOption()) { case ERROR: @@ -902,11 +1066,13 @@ injector.getInstance(Integer.class); fail(); } catch (ProvisionException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) null returned by binding at " + module.getClass().getName() + ".configure(", - "but parameter 0 of " + module.getClass().getName() + ".fail() is not @Nullable", + "but the 1st parameter of " + module.getClass().getName() + ".fail(", + "is not @Nullable", "while locating java.lang.String", - "for parameter 0 at " + module.getClass().getName() + ".fail(", + "for the 1st parameter of " + module.getClass().getName() + ".fail(", "while locating java.lang.Integer"); assertEquals(1, expected.getErrorMessages().size()); @@ -919,29 +1085,29 @@ private void validateNullableWarns(Injector injector, Dependency dependency) { final List logRecords = Lists.newArrayList(); - final Handler fakeHandler = new Handler() { - @Override - public void publish(LogRecord logRecord) { - logRecords.add(logRecord); - } - @Override - public void flush() {} - @Override - public void close() throws SecurityException {} - }; + final Handler fakeHandler = + new Handler() { + @Override + public void publish(LogRecord logRecord) { + logRecords.add(logRecord); + } + + @Override + public void flush() {} + + @Override + public void close() throws SecurityException {} + }; Logger.getLogger(Guice.class.getName()).addHandler(fakeHandler); try { injector.getInstance(Integer.class); // no exception, but assert it does log. LogRecord record = Iterables.getOnlyElement(logRecords); assertEquals( - "Guice injected null into parameter {0} of {1} (a {2}), please mark it @Nullable." + "Guice injected null into {0} (a {1}), please mark it @Nullable." + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an" + " error.", record.getMessage()); - assertEquals(dependency.getParameterIndex(), record.getParameters()[0]); - assertEquals(Errors.convert(dependency.getInjectionPoint().getMember()), - record.getParameters()[1]); - assertEquals(Errors.convert(dependency.getKey()), record.getParameters()[2]); + assertEquals(Errors.convert(dependency.getKey()), record.getParameters()[1]); } finally { Logger.getLogger(Guice.class.getName()).removeHandler(fakeHandler); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/SpiBindingsTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/SpiBindingsTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/SpiBindingsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/SpiBindingsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,10 +35,6 @@ import com.google.inject.Singleton; import com.google.inject.Stage; import com.google.inject.name.Names; - -import junit.framework.AssertionFailedError; -import junit.framework.TestCase; - import java.lang.reflect.Constructor; import java.util.Collections; import java.util.Comparator; @@ -46,58 +42,62 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class SpiBindingsTest extends TestCase { public void testBindConstant() { checkInjector( new AbstractModule() { + @Override protected void configure() { bindConstant().annotatedWith(Names.named("one")).to(1); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof InstanceBinding); assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey()); return null; } - } - ); + }); } public void testToInstanceBinding() { checkInjector( new AbstractModule() { + @Override protected void configure() { bind(String.class).toInstance("A"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof InstanceBinding); checkBindingSource(binding); assertEquals(Key.get(String.class), binding.getKey()); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(InstanceBinding binding) { - assertEquals("A", binding.getInstance()); - return null; - } - }); - binding.acceptScopingVisitor(new FailingBindingScopingVisitor() { - public Void visitEagerSingleton() { - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(InstanceBinding binding) { + assertEquals("A", binding.getInstance()); + return null; + } + }); + binding.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitEagerSingleton() { + return null; + } + }); return null; } - } - ); + }); } public void testToProviderBinding() { @@ -105,52 +105,55 @@ checkInjector( new AbstractModule() { + @Override protected void configure() { bind(String.class).toProvider(stringProvider); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof ProviderInstanceBinding); checkBindingSource(binding); assertEquals(Key.get(String.class), binding.getKey()); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit( - ProviderInstanceBinding binding) { - assertSame(stringProvider, binding.getUserSuppliedProvider()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderInstanceBinding binding) { + assertSame(stringProvider, binding.getUserSuppliedProvider()); + return null; + } + }); return null; } - } - ); + }); } public void testToProviderKeyBinding() { checkInjector( new AbstractModule() { + @Override protected void configure() { bind(String.class).toProvider(StringProvider.class); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof ProviderKeyBinding); checkBindingSource(binding); assertEquals(Key.get(String.class), binding.getKey()); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ProviderKeyBinding binding) { - assertEquals(Key.get(StringProvider.class), binding.getProviderKey()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ProviderKeyBinding binding) { + assertEquals(Key.get(StringProvider.class), binding.getProviderKey()); + return null; + } + }); return null; } - } - ); + }); } public void testToKeyBinding() { @@ -159,225 +162,262 @@ checkInjector( new AbstractModule() { + @Override protected void configure() { bind(aKey).to(bKey); bind(bKey).toInstance("B"); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof LinkedKeyBinding); checkBindingSource(binding); assertEquals(aKey, binding.getKey()); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(LinkedKeyBinding binding) { - assertEquals(bKey, binding.getLinkedKey()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(LinkedKeyBinding binding) { + assertEquals(bKey, binding.getLinkedKey()); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertEquals(bKey, binding.getKey()); return null; } - } - ); + }); } public void testToConstructorBinding() { checkInjector( new AbstractModule() { + @Override protected void configure() { bind(D.class); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof ConstructorBinding); checkBindingSource(binding); assertEquals(Key.get(D.class), binding.getKey()); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(ConstructorBinding binding) { - Constructor expected = D.class.getDeclaredConstructors()[0]; - assertEquals(expected, binding.getConstructor().getMember()); - assertEquals(ImmutableSet.of(), binding.getInjectableMembers()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ConstructorBinding binding) { + Constructor expected = D.class.getDeclaredConstructors()[0]; + assertEquals(expected, binding.getConstructor().getMember()); + assertEquals(ImmutableSet.of(), binding.getInjectableMembers()); + return null; + } + }); return null; } - } - ); + }); } public void testConstantBinding() { checkInjector( new AbstractModule() { + @Override protected void configure() { bindConstant().annotatedWith(Names.named("one")).to(1); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding binding) { + @Override + public Void visit(Binding binding) { assertTrue(binding instanceof InstanceBinding); checkBindingSource(binding); assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey()); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit(InstanceBinding binding) { - assertEquals(1, binding.getInstance()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(InstanceBinding binding) { + assertEquals(1, binding.getInstance()); + return null; + } + }); return null; } - } - ); + }); } public void testConvertedConstantBinding() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bindConstant().annotatedWith(Names.named("one")).to("1"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(Names.named("one")).to("1"); + } + }); Binding binding = injector.getBinding(Key.get(Integer.class, Names.named("one"))); assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey()); checkBindingSource(binding); assertTrue(binding instanceof ConvertedConstantBinding); - binding.acceptTargetVisitor(new FailingTargetVisitor() { - @Override public Void visit( - ConvertedConstantBinding binding) { - assertEquals((Integer) 1, binding.getValue()); - assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(ConvertedConstantBinding binding) { + assertEquals((Integer) 1, binding.getValue()); + assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey()); + return null; + } + }); } public void testProviderBinding() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("A"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A"); + } + }); Key> providerOfStringKey = new Key>() {}; Binding> binding = injector.getBinding(providerOfStringKey); assertEquals(providerOfStringKey, binding.getKey()); checkBindingSource(binding); assertTrue(binding instanceof ProviderBinding); - binding.acceptTargetVisitor(new FailingTargetVisitor>() { - @Override public Void visit( - ProviderBinding> binding) { - assertEquals(Key.get(String.class), binding.getProvidedKey()); - return null; - } - }); + binding.acceptTargetVisitor( + new FailingTargetVisitor>() { + @Override + public Void visit(ProviderBinding> binding) { + assertEquals(Key.get(String.class), binding.getProvidedKey()); + return null; + } + }); } public void testScopes() { checkInjector( new AbstractModule() { + @Override protected void configure() { - bind(String.class).annotatedWith(Names.named("a")) - .toProvider(StringProvider.class).in(Singleton.class); - bind(String.class).annotatedWith(Names.named("b")) - .toProvider(StringProvider.class).in(Scopes.SINGLETON); - bind(String.class).annotatedWith(Names.named("c")) - .toProvider(StringProvider.class).asEagerSingleton(); - bind(String.class).annotatedWith(Names.named("d")) - .toProvider(StringProvider.class); + bind(String.class) + .annotatedWith(Names.named("a")) + .toProvider(StringProvider.class) + .in(Singleton.class); + bind(String.class) + .annotatedWith(Names.named("b")) + .toProvider(StringProvider.class) + .in(Scopes.SINGLETON); + bind(String.class) + .annotatedWith(Names.named("c")) + .toProvider(StringProvider.class) + .asEagerSingleton(); + bind(String.class).annotatedWith(Names.named("d")).toProvider(StringProvider.class); } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("a")), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitScope(Scope scope) { - // even though we bound with an annotation, the injector always uses instances - assertSame(Scopes.SINGLETON, scope); - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitScope(Scope scope) { + // even though we bound with an annotation, the injector always uses instances + assertSame(Scopes.SINGLETON, scope); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("b")), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitScope(Scope scope) { - assertSame(Scopes.SINGLETON, scope); - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitScope(Scope scope) { + assertSame(Scopes.SINGLETON, scope); + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("c")), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitEagerSingleton() { - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitEagerSingleton() { + return null; + } + }); return null; } }, - new FailingElementVisitor() { - @Override public Void visit(Binding command) { + @Override + public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("d")), command.getKey()); - command.acceptScopingVisitor(new FailingBindingScopingVisitor() { - @Override public Void visitNoScoping() { - return null; - } - }); + command.acceptScopingVisitor( + new FailingBindingScopingVisitor() { + @Override + public Void visitNoScoping() { + return null; + } + }); return null; } - } - ); + }); } - + public void testExtensionSpi() { final AtomicBoolean visiting = new AtomicBoolean(false); - - final Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toProvider(new ProviderWithExtensionVisitor() { - public V acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - assertSame(this, binding.getUserSuppliedProvider()); - // We can't always check for FailingSpiTargetVisitor, - // because constructing the injector visits here, and we need - // to process the binding as normal - if(visiting.get()) { - assertTrue("visitor: " + visitor, visitor instanceof FailingSpiTargetVisitor); - return (V)"visited"; - } else { - return visitor.visit(binding); - } - } - - public String get() { - return "FooBar"; - } - }); - } - }); - + + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class) + .toProvider( + new ProviderWithExtensionVisitor() { + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, + ProviderInstanceBinding binding) { + assertSame(this, binding.getUserSuppliedProvider()); + // We can't always check for FailingSpiTargetVisitor, + // because constructing the injector visits here, and we need + // to process the binding as normal + if (visiting.get()) { + assertTrue( + "visitor: " + visitor, + visitor instanceof FailingSpiTargetVisitor); + return (V) "visited"; + } else { + return visitor.visit(binding); + } + } + + @Override + public String get() { + return "FooBar"; + } + }); + } + }); + visiting.set(true); // Check for Provider binding -- that is still a ProviderBinding. @@ -386,13 +426,15 @@ assertEquals(providerOfStringKey, providerBinding.getKey()); checkBindingSource(providerBinding); assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding); - providerBinding.acceptTargetVisitor(new FailingTargetVisitor>() { - @Override public Void visit(ProviderBinding> binding) { - assertEquals(Key.get(String.class), binding.getProvidedKey()); - return null; - } - }); - + providerBinding.acceptTargetVisitor( + new FailingTargetVisitor>() { + @Override + public Void visit(ProviderBinding> binding) { + assertEquals(Key.get(String.class), binding.getProvidedKey()); + return null; + } + }); + // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked Binding binding = injector.getBinding(String.class); assertEquals(Key.get(String.class), binding.getKey()); @@ -418,7 +460,7 @@ assertEquals(0, source.getStackTrace().length); } } - + public void checkInjector(Module module, ElementVisitor... visitors) { Injector injector = Guice.createInjector(module); @@ -440,24 +482,28 @@ } } - private final ImmutableSet> BUILT_IN_BINDINGS = ImmutableSet.of( - Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class)); + private final ImmutableSet> BUILT_IN_BINDINGS = + ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class)); - private final Comparator> orderByKey = new Comparator>() { - public int compare(Binding a, Binding b) { - return a.getKey().toString().compareTo(b.getKey().toString()); - } - }; + private final Comparator> orderByKey = + new Comparator>() { + @Override + public int compare(Binding a, Binding b) { + return a.getKey().toString().compareTo(b.getKey().toString()); + } + }; private static class StringProvider implements Provider { + @Override public String get() { return "A"; } } - private static class C { } + private static class C {} private static class D extends C { - @Inject public D(Injector unused) { } + @Inject + public D(Injector unused) {} } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/spi/ToolStageInjectorTest.java sisu-guice-4.2.0/core/test/com/google/inject/spi/ToolStageInjectorTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/spi/ToolStageInjectorTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/spi/ToolStageInjectorTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -9,14 +9,11 @@ import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Stage; -import com.google.inject.spi.Toolable; - -import junit.framework.TestCase; - import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; public class ToolStageInjectorTest extends TestCase { @@ -58,108 +55,157 @@ } catch (UnsupportedOperationException expected) { } } - + public void testToolStageDoesntInjectInstances() { final Foo foo = new Foo(); - Guice.createInjector(Stage.TOOL, new AbstractModule() { - @Override - protected void configure() { - requestStaticInjection(Foo.class); - requestInjection(foo); - } - }); + Guice.createInjector( + Stage.TOOL, + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(Foo.class); + requestInjection(foo); + } + }); assertNull(Foo.s); assertNull(Foo.sm); assertNull(foo.f); assertNull(foo.m); } - + public void testToolStageDoesntInjectProviders() { final Foo foo = new Foo(); - Guice.createInjector(Stage.TOOL, new AbstractModule() { - @Override - protected void configure() { - requestStaticInjection(Foo.class); - bind(Object.class).toProvider(foo); - } - }); + Guice.createInjector( + Stage.TOOL, + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(Foo.class); + bind(Object.class).toProvider(foo); + } + }); assertNull(Foo.s); assertNull(Foo.sm); assertNull(foo.f); assertNull(foo.m); } - + public void testToolStageWarnsOfMissingObjectGraph() { final Bar bar = new Bar(); try { - Guice.createInjector(Stage.TOOL, new AbstractModule() { - @Override - protected void configure() { - requestStaticInjection(Bar.class); - requestInjection(bar); - } - }); + Guice.createInjector( + Stage.TOOL, + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(Bar.class); + requestInjection(bar); + } + }); fail("expected exception"); - } catch(CreationException expected) { - Asserts.assertContains(expected.toString(), "No implementation for java.util.Collection was bound.", + } catch (CreationException expected) { + Asserts.assertContains( + expected.toString(), + "No implementation for java.util.Collection was bound.", "No implementation for java.util.Map was bound.", "No implementation for java.util.List was bound.", "No implementation for java.util.Set was bound."); } } - + public void testToolStageInjectsTooledMethods() { final Tooled tooled = new Tooled(); - Guice.createInjector(Stage.TOOL, new AbstractModule() { - @Override - protected void configure() { - requestStaticInjection(Tooled.class); - bind(Object.class).toProvider(tooled); - } - }); + Guice.createInjector( + Stage.TOOL, + new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection(Tooled.class); + bind(Object.class).toProvider(tooled); + } + }); assertNull(Tooled.s); assertNotNull(Tooled.sm); assertNull(tooled.f); assertNotNull(tooled.m); } - + @SuppressWarnings("unchecked") private static class Bar { - @SuppressWarnings("unused") @Inject private static List list; - @SuppressWarnings("unused") @Inject private Set set; - @SuppressWarnings("unused") @Inject void method(Collection c) {} - @SuppressWarnings("unused") @Inject static void staticMethod(Map map) {} + @SuppressWarnings("unused") + @Inject + private static List list; + + @SuppressWarnings("unused") + @Inject + private Set set; + + @SuppressWarnings("unused") + @Inject + void method(Collection c) {} + + @SuppressWarnings("unused") + @Inject + static void staticMethod(Map map) {} } - + private static class Foo implements Provider { - @Inject private static S s; + @Inject private static S s; @Inject private F f; private M m; - @SuppressWarnings("unused") @Inject void method(M m) { this.m = m; } + + @SuppressWarnings("unused") + @Inject + void method(M m) { + this.m = m; + } + private static SM sm; - @SuppressWarnings("unused") @Inject static void staticMethod(SM sm) { Tooled.sm = sm; } - + + @SuppressWarnings("unused") + @Inject + static void staticMethod(SM sm) { + Tooled.sm = sm; + } + + @Override public Object get() { return null; } } - + private static class Tooled implements Provider { - @Inject private static S s; + @Inject private static S s; @Inject private F f; private M m; - @Toolable @SuppressWarnings("unused") @Inject void method(M m) { this.m = m; } + + @Toolable + @SuppressWarnings("unused") + @Inject + void method(M m) { + this.m = m; + } + private static SM sm; - @Toolable @SuppressWarnings("unused") @Inject static void staticMethod(SM sm) { Tooled.sm = sm; } - + + @Toolable + @SuppressWarnings("unused") + @Inject + static void staticMethod(SM sm) { + Tooled.sm = sm; + } + + @Override public Object get() { return null; } } - + private static class S {} + private static class F {} + private static class M {} - private static class SM {} + private static class SM {} } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/SuiteUtils.java sisu-guice-4.2.0/core/test/com/google/inject/SuiteUtils.java --- sisu-guice-3.2.6/core/test/com/google/inject/SuiteUtils.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/SuiteUtils.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,32 +16,30 @@ package com.google.inject; -import junit.framework.Test; -import junit.framework.TestSuite; - import java.util.Enumeration; import java.util.Set; +import junit.framework.Test; +import junit.framework.TestSuite; public class SuiteUtils { public static TestSuite removeSuppressedTests(TestSuite suite, Set suppressedTestNames) { TestSuite result = new TestSuite(suite.getName()); - - for(Enumeration e = suite.tests(); e.hasMoreElements(); ) { + + for (Enumeration e = suite.tests(); e.hasMoreElements(); ) { Test test = (Test) e.nextElement(); - + if (suppressedTestNames.contains(test.toString())) { continue; } - + if (test instanceof TestSuite) { result.addTest(removeSuppressedTests((TestSuite) test, suppressedTestNames)); } else { result.addTest(test); } } - + return result; } - } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/SuperclassTest.java sisu-guice-4.2.0/core/test/com/google/inject/SuperclassTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/SuperclassTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/SuperclassTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,17 +18,18 @@ import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class SuperclassTest extends TestCase { public void testSuperclassInjection() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Foo.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Foo.class); + } + }); Provider creator = injector.getProvider(Sub.class); Sub sub = creator.get(); @@ -40,17 +41,18 @@ assertNotNull(sub.fromMethod); } - static abstract class Super { + abstract static class Super { @Inject Foo field; Foo fromMethod; - @Inject void setC(Foo foo) { + + @Inject + void setC(Foo foo) { fromMethod = foo; } } - static class Sub extends Super { - } + static class Sub extends Super {} static class Foo {} } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/TypeConversionTest.java sisu-guice-4.2.0/core/test/com/google/inject/TypeConversionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/TypeConversionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/TypeConversionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,29 +26,29 @@ import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeConverterBinding; - -import junit.framework.AssertionFailedError; -import junit.framework.TestCase; - import java.lang.annotation.Retention; import java.util.Date; +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class TypeConversionTest extends TestCase { @Retention(RUNTIME) - @BindingAnnotation @interface NumericValue {} + @BindingAnnotation + @interface NumericValue {} @Retention(RUNTIME) - @BindingAnnotation @interface BooleanValue {} + @BindingAnnotation + @interface BooleanValue {} @Retention(RUNTIME) - @BindingAnnotation @interface EnumValue {} + @BindingAnnotation + @interface EnumValue {} @Retention(RUNTIME) - @BindingAnnotation @interface ClassName {} + @BindingAnnotation + @interface ClassName {} public static class Foo { @Inject @BooleanValue Boolean booleanField; @@ -70,16 +70,21 @@ } public enum Bar { - TEE, BAZ, BOB + TEE, + BAZ, + BOB } public void testOneConstantInjection() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindConstant().annotatedWith(NumericValue.class).to("5"); - bind(Simple.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(NumericValue.class).to("5"); + bind(Simple.class); + } + }); Simple simple = injector.getInstance(Simple.class); assertEquals(5, simple.i); @@ -90,64 +95,68 @@ } public void testConstantInjection() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindConstant().annotatedWith(NumericValue.class).to("5"); - bindConstant().annotatedWith(BooleanValue.class).to("true"); - bindConstant().annotatedWith(EnumValue.class).to("TEE"); - bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(NumericValue.class).to("5"); + bindConstant().annotatedWith(BooleanValue.class).to("true"); + bindConstant().annotatedWith(EnumValue.class).to("TEE"); + bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName()); + } + }); Foo foo = injector.getInstance(Foo.class); checkNumbers( - foo.integerField, - foo.primitiveIntField, - foo.longField, - foo.primitiveLongField, - foo.byteField, - foo.primitiveByteField, - foo.shortField, - foo.primitiveShortField, - foo.floatField, - foo.primitiveFloatField, - foo.doubleField, - foo.primitiveDoubleField - ); + foo.integerField, + foo.primitiveIntField, + foo.longField, + foo.primitiveLongField, + foo.byteField, + foo.primitiveByteField, + foo.shortField, + foo.primitiveShortField, + foo.floatField, + foo.primitiveFloatField, + foo.doubleField, + foo.primitiveDoubleField); assertEquals(Bar.TEE, foo.enumField); assertEquals(Foo.class, foo.classField); } public void testConstantInjectionWithExplicitBindingsRequired() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - binder().requireExplicitBindings(); - bind(Foo.class); - bindConstant().annotatedWith(NumericValue.class).to("5"); - bindConstant().annotatedWith(BooleanValue.class).to("true"); - bindConstant().annotatedWith(EnumValue.class).to("TEE"); - bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + bind(Foo.class); + bindConstant().annotatedWith(NumericValue.class).to("5"); + bindConstant().annotatedWith(BooleanValue.class).to("true"); + bindConstant().annotatedWith(EnumValue.class).to("TEE"); + bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName()); + } + }); Foo foo = injector.getInstance(Foo.class); checkNumbers( - foo.integerField, - foo.primitiveIntField, - foo.longField, - foo.primitiveLongField, - foo.byteField, - foo.primitiveByteField, - foo.shortField, - foo.primitiveShortField, - foo.floatField, - foo.primitiveFloatField, - foo.doubleField, - foo.primitiveDoubleField - ); + foo.integerField, + foo.primitiveIntField, + foo.longField, + foo.primitiveLongField, + foo.byteField, + foo.primitiveByteField, + foo.shortField, + foo.primitiveShortField, + foo.floatField, + foo.primitiveFloatField, + foo.doubleField, + foo.primitiveDoubleField); assertEquals(Bar.TEE, foo.enumField); assertEquals(Foo.class, foo.classField); @@ -160,13 +169,15 @@ } static class OuterErrorModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new InnerErrorModule()); } } static class InnerErrorModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bindConstant().annotatedWith(NumericValue.class).to("invalid"); } } @@ -177,8 +188,10 @@ injector.getInstance(InvalidInteger.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), - "Error converting 'invalid' (bound at " + InnerErrorModule.class.getName() + assertContains( + expected.getMessage(), + "Error converting 'invalid' (bound at " + + InnerErrorModule.class.getName() + getDeclaringSourcePart(getClass()), asModuleChain(OuterErrorModule.class, InnerErrorModule.class), "using TypeConverter which matches identicalTo(class java.lang.Integer)" @@ -192,11 +205,14 @@ } public void testInvalidCharacter() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindConstant().annotatedWith(NumericValue.class).to("invalid"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(NumericValue.class).to("invalid"); + } + }); try { injector.getInstance(InvalidCharacter.class); @@ -213,11 +229,14 @@ } public void testInvalidEnum() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindConstant().annotatedWith(NumericValue.class).to("invalid"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(NumericValue.class).to("invalid"); + } + }); try { injector.getInstance(InvalidEnum.class); @@ -234,12 +253,15 @@ } public void testToInstanceIsTreatedLikeConstant() throws CreationException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("5"); - bind(LongHolder.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("5"); + bind(LongHolder.class); + } + }); assertEquals(5L, (long) injector.getInstance(LongHolder.class).foo); } @@ -251,27 +273,33 @@ public void testCustomTypeConversion() throws CreationException { final Date result = new Date(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - convertToTypes(Matchers.only(TypeLiteral.get(Date.class)) , mockTypeConverter(result)); - bindConstant().annotatedWith(NumericValue.class).to("Today"); - bind(DateHolder.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + convertToTypes( + Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(result)); + bindConstant().annotatedWith(NumericValue.class).to("Today"); + bind(DateHolder.class); + } + }); assertSame(result, injector.getInstance(DateHolder.class).date); Binding binding = injector.getBinding(Key.get(Date.class, NumericValue.class)); assertTrue(binding instanceof ConvertedConstantBinding); - TypeConverterBinding converterBinding = ((ConvertedConstantBinding)binding).getTypeConverterBinding(); + TypeConverterBinding converterBinding = + ((ConvertedConstantBinding) binding).getTypeConverterBinding(); assertEquals("CustomConverter", converterBinding.getTypeConverter().toString()); assertTrue(injector.getTypeConverterBindings().contains(converterBinding)); } static class InvalidCustomValueModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), failingTypeConverter()); bindConstant().annotatedWith(NumericValue.class).to("invalid"); bind(DateHolder.class); @@ -286,11 +314,15 @@ } catch (CreationException expected) { Throwable cause = Iterables.getOnlyElement(expected.getErrorMessages()).getCause(); assertTrue(cause instanceof UnsupportedOperationException); - assertContains(expected.getMessage(), - "1) Error converting 'invalid' (bound at ", getClass().getName(), - getDeclaringSourcePart(getClass()), "to java.util.Date", + assertContains( + expected.getMessage(), + "1) Error converting 'invalid' (bound at ", + getClass().getName(), + getDeclaringSourcePart(getClass()), + "to java.util.Date", "using BrokenConverter which matches only(java.util.Date) ", - "(bound at " + getClass().getName(), getDeclaringSourcePart(getClass()), + "(bound at " + getClass().getName(), + getDeclaringSourcePart(getClass()), "Reason: java.lang.UnsupportedOperationException: Cannot convert", "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:"); } @@ -298,22 +330,26 @@ static class OuterModule extends AbstractModule { private final Module converterModule; + OuterModule(Module converterModule) { this.converterModule = converterModule; } - @Override protected void configure() { + @Override + protected void configure() { install(new InnerModule(converterModule)); } } static class InnerModule extends AbstractModule { private final Module converterModule; + InnerModule(Module converterModule) { this.converterModule = converterModule; } - @Override protected void configure() { + @Override + protected void configure() { install(converterModule); bindConstant().annotatedWith(NumericValue.class).to("foo"); bind(DateHolder.class); @@ -321,7 +357,8 @@ } class ConverterNullModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(null)); } } @@ -331,7 +368,8 @@ Guice.createInjector(new OuterModule(new ConverterNullModule())); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Received null converting 'foo' (bound at ", getClass().getName(), getDeclaringSourcePart(getClass()), @@ -347,7 +385,8 @@ } class ConverterCustomModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(-1)); } } @@ -357,7 +396,8 @@ Guice.createInjector(new OuterModule(new ConverterCustomModule())); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Type mismatch converting 'foo' (bound at ", getClass().getName(), getDeclaringSourcePart(getClass()), @@ -374,23 +414,29 @@ } public void testStringIsConvertedOnlyOnce() { - final TypeConverter converter = new TypeConverter() { - boolean converted = false; - public Object convert(String value, TypeLiteral toType) { - if (converted) { - throw new AssertionFailedError("converted multiple times!"); - } - converted = true; - return new Date(); - } - }; - - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), converter); - bindConstant().annotatedWith(NumericValue.class).to("unused"); - } - }); + final TypeConverter converter = + new TypeConverter() { + boolean converted = false; + + @Override + public Object convert(String value, TypeLiteral toType) { + if (converted) { + throw new AssertionFailedError("converted multiple times!"); + } + converted = true; + return new Date(); + } + }; + + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), converter); + bindConstant().annotatedWith(NumericValue.class).to("unused"); + } + }); Date first = injector.getInstance(Key.get(Date.class, NumericValue.class)); Date second = injector.getInstance(Key.get(Date.class, NumericValue.class)); @@ -398,13 +444,15 @@ } class OuterAmbiguousModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new InnerAmbiguousModule()); } } class InnerAmbiguousModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new Ambiguous1Module()); install(new Ambiguous2Module()); bindConstant().annotatedWith(NumericValue.class).to("foo"); @@ -413,13 +461,15 @@ } class Ambiguous1Module extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date())); } } class Ambiguous2Module extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date())); } } @@ -429,8 +479,10 @@ Guice.createInjector(new OuterAmbiguousModule()); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), - "1) Multiple converters can convert 'foo' (bound at ", getClass().getName(), + assertContains( + expected.getMessage(), + "1) Multiple converters can convert 'foo' (bound at ", + getClass().getName(), getDeclaringSourcePart(getClass()), asModuleChain(OuterAmbiguousModule.class, InnerAmbiguousModule.class), "to java.util.Date:", @@ -452,11 +504,13 @@ TypeConverter mockTypeConverter(final Object result) { return new TypeConverter() { + @Override public Object convert(String value, TypeLiteral toType) { return result; } - @Override public String toString() { + @Override + public String toString() { return "CustomConverter"; } }; @@ -464,10 +518,13 @@ private static TypeConverter failingTypeConverter() { return new TypeConverter() { + @Override public Object convert(String value, TypeLiteral toType) { throw new UnsupportedOperationException("Cannot convert"); } - @Override public String toString() { + + @Override + public String toString() { return "BrokenConverter"; } }; @@ -478,18 +535,21 @@ } public void testCannotConvertUnannotatedBindings() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("55"); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("55"); + } + }); try { injector.getInstance(Integer.class); fail("Converted an unannotated String to an Integer"); } catch (ConfigurationException expected) { - Asserts.assertContains(expected.getMessage(), - "Could not find a suitable constructor in java.lang.Integer."); + Asserts.assertContains( + expected.getMessage(), "Could not find a suitable constructor in java.lang.Integer."); } } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/TypeListenerTest.java sisu-guice-4.2.0/core/test/com/google/inject/TypeListenerTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/TypeListenerTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/TypeListenerTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,97 +31,115 @@ import com.google.inject.spi.Message; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; - -import junit.framework.TestCase; - import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class TypeListenerTest extends TestCase { - private final Matcher onlyAbcd = Matchers.only(new TypeLiteral() {}) - .or(only(new TypeLiteral() {})) - .or(only(new TypeLiteral() {})) - .or(only(new TypeLiteral() {})); - - final TypeListener failingTypeListener = new TypeListener() { - int failures = 0; - - public void hear(TypeLiteral type, TypeEncounter encounter) { - throw new ClassCastException("whoops, failure #" + (++failures)); - } - - @Override public String toString() { - return "clumsy"; - } - }; - - final InjectionListener failingInjectionListener = new InjectionListener() { - int failures = 0; + private final Matcher onlyAbcd = + Matchers.only(new TypeLiteral() {}) + .or(only(new TypeLiteral() {})) + .or(only(new TypeLiteral() {})) + .or(only(new TypeLiteral() {})); + + final TypeListener failingTypeListener = + new TypeListener() { + int failures = 0; + + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + throw new ClassCastException("whoops, failure #" + (++failures)); + } - public void afterInjection(Object injectee) { - throw new ClassCastException("whoops, failure #" + (++failures)); - } + @Override + public String toString() { + return "clumsy"; + } + }; - @Override public String toString() { - return "goofy"; - } - }; + final InjectionListener failingInjectionListener = + new InjectionListener() { + int failures = 0; + + @Override + public void afterInjection(Object injectee) { + throw new ClassCastException("whoops, failure #" + (++failures)); + } - final MembersInjector failingMembersInjector = new MembersInjector() { - int failures = 0; + @Override + public String toString() { + return "goofy"; + } + }; - public void injectMembers(Object instance) { - throw new ClassCastException("whoops, failure #" + (++failures)); - } + final MembersInjector failingMembersInjector = + new MembersInjector() { + int failures = 0; + + @Override + public void injectMembers(Object instance) { + throw new ClassCastException("whoops, failure #" + (++failures)); + } - @Override public String toString() { - return "awkward"; - } - }; + @Override + public String toString() { + return "awkward"; + } + }; public void testTypeListenersAreFired() { final AtomicInteger firedCount = new AtomicInteger(); - final TypeListener typeListener = new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - assertEquals(new TypeLiteral() {}, type); - firedCount.incrementAndGet(); - } - }; + final TypeListener typeListener = + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + assertEquals(new TypeLiteral() {}, type); + firedCount.incrementAndGet(); + } + }; - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, typeListener); - bind(A.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(onlyAbcd, typeListener); + bind(A.class); + } + }); assertEquals(1, firedCount.get()); } public void testInstallingInjectionListener() { final List injectees = Lists.newArrayList(); - final InjectionListener injectionListener = new InjectionListener() { - public void afterInjection(Object injectee) { - injectees.add(injectee); - } - }; - - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounter.register(injectionListener); + final InjectionListener injectionListener = + new InjectionListener() { + @Override + public void afterInjection(Object injectee) { + injectees.add(injectee); } - }); - bind(A.class); - } - }); + }; + + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + onlyAbcd, + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounter.register(injectionListener); + } + }); + bind(A.class); + } + }); assertEquals(ImmutableList.of(), injectees); @@ -140,11 +158,12 @@ A a4 = aProvider.get(); assertEquals(ImmutableList.of(a1, a2, b1, a3, a4), injectees); } - + /*if[AOP]*/ private static org.aopalliance.intercept.MethodInterceptor prefixInterceptor( final String prefix) { return new org.aopalliance.intercept.MethodInterceptor() { + @Override public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) throws Throwable { return prefix + methodInvocation.proceed(); @@ -155,19 +174,25 @@ public void testAddingInterceptors() throws NoSuchMethodException { final Matcher buzz = only(C.class.getMethod("buzz")); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindInterceptor(any(), buzz, prefixInterceptor("ka")); - bindInterceptor(any(), any(), prefixInterceptor("fe")); - - bindListener(onlyAbcd, new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounter.bindInterceptor(any(), prefixInterceptor("li")); - encounter.bindInterceptor(buzz, prefixInterceptor("no")); - } - }); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor(any(), buzz, prefixInterceptor("ka")); + bindInterceptor(any(), any(), prefixInterceptor("fe")); + + bindListener( + onlyAbcd, + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounter.bindInterceptor(any(), prefixInterceptor("li")); + encounter.bindInterceptor(buzz, prefixInterceptor("no")); + } + }); + } + }); // interceptors must be invoked in the order they're bound. C c = injector.getInstance(C.class); @@ -177,27 +202,32 @@ /*end[AOP]*/ class OuterThrowsModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new InnerThrowsModule()); } } + class InnerThrowsModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bindListener(onlyAbcd, failingTypeListener); bind(B.class); bind(C.class); } } + public void testTypeListenerThrows() { try { Guice.createInjector(new OuterThrowsModule()); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(), getDeclaringSourcePart(getClass()), asModuleChain(OuterThrowsModule.class, InnerThrowsModule.class), - "of " + B.class.getName(), + "of " + B.class.getName(), "Reason: java.lang.ClassCastException: whoops, failure #1", "2) Error notifying TypeListener clumsy (bound at " + getClass().getName(), getDeclaringSourcePart(getClass()), @@ -205,17 +235,21 @@ "of " + C.class.getName(), "Reason: java.lang.ClassCastException: whoops, failure #2"); } - - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, failingTypeListener); - } - }); + + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(onlyAbcd, failingTypeListener); + } + }); try { injector.getProvider(B.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(), getDeclaringSourcePart(getClass()), "of " + B.class.getName(), @@ -227,7 +261,8 @@ injector.getInstance(B.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(), getDeclaringSourcePart(getClass()), "of " + B.class.getName(), @@ -239,22 +274,29 @@ } public void testInjectionListenerThrows() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounter.register(failingInjectionListener); - } - }); - bind(B.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + onlyAbcd, + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounter.register(failingInjectionListener); + } + }); + bind(B.class); + } + }); try { injector.getInstance(A.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error notifying InjectionListener goofy of " + A.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #1"); } @@ -264,7 +306,8 @@ injector.getInstance(A.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error notifying InjectionListener goofy of " + A.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #2"); } @@ -275,7 +318,8 @@ bProvider.get(); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error notifying InjectionListener goofy of " + B.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #3"); } @@ -286,17 +330,21 @@ public void testInjectMembersTypeListenerFails() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - getMembersInjector(A.class); - bindListener(onlyAbcd, failingTypeListener); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + getMembersInjector(A.class); + bindListener(onlyAbcd, failingTypeListener); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at ", - TypeListenerTest.class.getName(), getDeclaringSourcePart(getClass()), + TypeListenerTest.class.getName(), + getDeclaringSourcePart(getClass()), "of " + A.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #1"); } @@ -306,27 +354,35 @@ final AtomicInteger typeEncounters = new AtomicInteger(); final AtomicInteger injections = new AtomicInteger(); - final InjectionListener listener = new InjectionListener() { - public void afterInjection(A injectee) { - injections.incrementAndGet(); - assertNotNull(injectee.injector); - } - }; - - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, new TypeListener() { - @SuppressWarnings("unchecked") - public void hear(TypeLiteral type, TypeEncounter encounter) { - typeEncounters.incrementAndGet(); - encounter.register((InjectionListener) listener); + final InjectionListener listener = + new InjectionListener() { + @Override + public void afterInjection(A injectee) { + injections.incrementAndGet(); + assertNotNull(injectee.injector); } - }); + }; - bind(A.class); - getMembersInjector(A.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + onlyAbcd, + new TypeListener() { + @Override + @SuppressWarnings("unchecked") + public void hear(TypeLiteral type, TypeEncounter encounter) { + typeEncounters.incrementAndGet(); + encounter.register((InjectionListener) listener); + } + }); + + bind(A.class); + getMembersInjector(A.class); + } + }); // creating the injector shouldn't trigger injections assertEquals(0, injections.getAndSet(0)); @@ -359,107 +415,130 @@ } public void testLookupsAtInjectorCreateTime() { - final AtomicReference> bProviderReference = new AtomicReference>(); - final AtomicReference> aMembersInjectorReference - = new AtomicReference>(); - - final InjectionListener lookupsTester = new InjectionListener() { - public void afterInjection(Object injectee) { - assertNotNull(bProviderReference.get().get()); - - A a = new A(); - aMembersInjectorReference.get().injectMembers(a); - assertNotNull(a.injector); - } - }; + final AtomicReference> bProviderReference = new AtomicReference<>(); + final AtomicReference> aMembersInjectorReference = new AtomicReference<>(); - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(only(TypeLiteral.get(C.class)), new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - Provider bProvider = encounter.getProvider(B.class); - try { - bProvider.get(); - fail(); - } catch (IllegalStateException expected) { - assertEquals("This Provider cannot be used until the Injector has been created.", - expected.getMessage()); - } - bProviderReference.set(bProvider); + final InjectionListener lookupsTester = + new InjectionListener() { + @Override + public void afterInjection(Object injectee) { + assertNotNull(bProviderReference.get().get()); - MembersInjector aMembersInjector = encounter.getMembersInjector(A.class); - try { - aMembersInjector.injectMembers(new A()); - fail(); - } catch (IllegalStateException expected) { - assertEquals( - "This MembersInjector cannot be used until the Injector has been created.", - expected.getMessage()); - } - aMembersInjectorReference.set(aMembersInjector); + A a = new A(); + aMembersInjectorReference.get().injectMembers(a); + assertNotNull(a.injector); + } + }; - encounter.register(lookupsTester); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + only(TypeLiteral.get(C.class)), + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + Provider bProvider = encounter.getProvider(B.class); + try { + bProvider.get(); + fail(); + } catch (IllegalStateException expected) { + assertEquals( + "This Provider cannot be used until the Injector has been created.", + expected.getMessage()); + } + bProviderReference.set(bProvider); + + MembersInjector aMembersInjector = encounter.getMembersInjector(A.class); + try { + aMembersInjector.injectMembers(new A()); + fail(); + } catch (IllegalStateException expected) { + assertEquals( + "This MembersInjector cannot be used until the Injector has been created.", + expected.getMessage()); + } + aMembersInjectorReference.set(aMembersInjector); + + encounter.register(lookupsTester); + } + }); + + // this ensures the type listener fires, and also the afterInjection() listener + bind(C.class).asEagerSingleton(); } }); - // this ensures the type listener fires, and also the afterInjection() listener - bind(C.class).asEagerSingleton(); - } - }); - lookupsTester.afterInjection(null); } public void testLookupsPostCreate() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(only(TypeLiteral.get(C.class)), new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - assertNotNull(encounter.getProvider(B.class).get()); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + only(TypeLiteral.get(C.class)), + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + assertNotNull(encounter.getProvider(B.class).get()); + + A a = new A(); + encounter.getMembersInjector(A.class).injectMembers(a); + assertNotNull(a.injector); + } + }); + } + }); - A a = new A(); - encounter.getMembersInjector(A.class).injectMembers(a); - assertNotNull(a.injector); - } - }); - } - }); - injector.getInstance(C.class); } public void testMembersInjector() { - final MembersInjector membersInjector = new MembersInjector() { - public void injectMembers(D instance) { - instance.userInjected++; - assertEquals(instance.guiceInjected, instance.userInjected); - } - }; - - final InjectionListener injectionListener = new InjectionListener() { - public void afterInjection(D injectee) { - assertTrue(injectee.userInjected > 0); - injectee.listenersNotified++; - assertEquals(injectee.guiceInjected, injectee.listenersNotified); - } - }; + final MembersInjector membersInjector = + new MembersInjector() { + @Override + public void injectMembers(D instance) { + instance.userInjected++; + assertEquals(instance.guiceInjected, instance.userInjected); + } + }; - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, new TypeListener() { - @SuppressWarnings("unchecked") - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounter.register((MembersInjector) membersInjector); - encounter.register((InjectionListener) injectionListener); + final InjectionListener injectionListener = + new InjectionListener() { + @Override + public void afterInjection(D injectee) { + assertTrue(injectee.userInjected > 0); + injectee.listenersNotified++; + assertEquals(injectee.guiceInjected, injectee.listenersNotified); } - }); + }; - D boundThreeTimes = new D(); - bind(D.class).annotatedWith(named("i")).toInstance(boundThreeTimes); - bind(D.class).annotatedWith(named("ii")).toInstance(boundThreeTimes); - bind(D.class).annotatedWith(named("iii")).toInstance(boundThreeTimes); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + onlyAbcd, + new TypeListener() { + @Override + @SuppressWarnings("unchecked") + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounter.register((MembersInjector) membersInjector); + encounter.register((InjectionListener) injectionListener); + } + }); + + D boundThreeTimes = new D(); + bind(D.class).annotatedWith(named("i")).toInstance(boundThreeTimes); + bind(D.class).annotatedWith(named("ii")).toInstance(boundThreeTimes); + bind(D.class).annotatedWith(named("iii")).toInstance(boundThreeTimes); + } + }); D boundThreeTimes = injector.getInstance(Key.get(D.class, named("iii"))); boundThreeTimes.assertAllCounts(1); @@ -480,22 +559,29 @@ } public void testMembersInjectorThrows() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounter.register(failingMembersInjector); - } - }); - bind(B.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + onlyAbcd, + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounter.register(failingMembersInjector); + } + }); + bind(B.class); + } + }); try { injector.getInstance(A.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error injecting " + A.class.getName() + " using awkward.", "Reason: java.lang.ClassCastException: whoops, failure #1"); } @@ -505,7 +591,8 @@ injector.getInstance(A.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error injecting " + A.class.getName() + " using awkward.", "Reason: java.lang.ClassCastException: whoops, failure #2"); } @@ -516,7 +603,8 @@ bProvider.get(); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) Error injecting " + B.class.getName() + " using awkward.", "Reason: java.lang.ClassCastException: whoops, failure #3"); } @@ -533,53 +621,69 @@ public void testTypesWithNoInjectableMembersAreNotified() { final AtomicInteger notificationCount = new AtomicInteger(); - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(onlyAbcd, new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - notificationCount.incrementAndGet(); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + onlyAbcd, + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + notificationCount.incrementAndGet(); + } + }); + + bind(C.class).toInstance(new C()); } }); - bind(C.class).toInstance(new C()); - } - }); - assertEquals(1, notificationCount.get()); } public void testEncounterCannotBeUsedAfterHearReturns() { - final AtomicReference> encounterReference = new AtomicReference>(); + final AtomicReference> encounterReference = + new AtomicReference>(); - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindListener(any(), new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounterReference.set(encounter); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener( + any(), + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounterReference.set(encounter); + } + }); + + bind(C.class); } }); - - bind(C.class); - } - }); TypeEncounter encounter = encounterReference.get(); try { - encounter.register(new InjectionListener() { - public void afterInjection(Object injectee) {} - }); + encounter.register( + new InjectionListener() { + @Override + public void afterInjection(Object injectee) {} + }); fail(); } catch (IllegalStateException expected) { } /*if[AOP]*/ try { - encounter.bindInterceptor(any(), new org.aopalliance.intercept.MethodInterceptor() { - public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) - throws Throwable { - return methodInvocation.proceed(); - } - }); + encounter.bindInterceptor( + any(), + new org.aopalliance.intercept.MethodInterceptor() { + @Override + public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) + throws Throwable { + return methodInvocation.proceed(); + } + }); fail(); } catch (IllegalStateException expected) { } @@ -606,22 +710,28 @@ public void testAddErrors() { try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - requestInjection(new Object()); - bindListener(Matchers.any(), new TypeListener() { - public void hear(TypeLiteral type, TypeEncounter encounter) { - encounter.addError("There was an error on %s", type); - encounter.addError(new IllegalArgumentException("whoops!")); - encounter.addError(new Message("And another problem")); - encounter.addError(new IllegalStateException()); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + requestInjection(new Object()); + bindListener( + Matchers.any(), + new TypeListener() { + @Override + public void hear(TypeLiteral type, TypeEncounter encounter) { + encounter.addError("There was an error on %s", type); + encounter.addError(new IllegalArgumentException("whoops!")); + encounter.addError(new Message("And another problem")); + encounter.addError(new IllegalStateException()); + } + }); } }); - } - }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) There was an error on java.lang.Object", "2) An exception was caught and reported. Message: whoops!", "3) And another problem", @@ -631,12 +741,14 @@ } private static class CountingMembersInjector implements MembersInjector { + @Override public void injectMembers(D instance) { ++instance.userInjected; } } private static class CountingInjectionListener implements InjectionListener { + @Override public void afterInjection(D injectee) { ++injectee.listenersNotified; } @@ -645,6 +757,7 @@ private static class DuplicatingTypeListener implements TypeListener { int count = 0; + @Override @SuppressWarnings({"rawtypes", "unchecked"}) public void hear(TypeLiteral type, TypeEncounter encounter) { ++count; @@ -661,13 +774,15 @@ public void testDeDuplicateTypeListeners() { final DuplicatingTypeListener typeListener = new DuplicatingTypeListener(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindListener(any(), typeListener); - bindListener(only(new TypeLiteral() {}), typeListener); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindListener(any(), typeListener); + bindListener(only(new TypeLiteral() {}), typeListener); + } + }); D d = injector.getInstance(D.class); d.assertAllCounts(1); assertEquals(1, typeListener.count); @@ -697,7 +812,8 @@ int userInjected = 0; int listenersNotified = 0; - @Inject void guiceInjected() { + @Inject + void guiceInjected() { guiceInjected++; } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/TypeLiteralInjectionTest.java sisu-guice-4.2.0/core/test/com/google/inject/TypeLiteralInjectionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/TypeLiteralInjectionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/TypeLiteralInjectionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,43 +20,47 @@ import static com.google.inject.util.Types.listOf; import com.google.inject.util.Types; - -import junit.framework.TestCase; - import java.util.List; +import junit.framework.TestCase; /** * Demonstrates type reification. - * + * * @author jessewilson@google.com (Jesse Wilson) */ public class TypeLiteralInjectionTest extends TestCase { public void testBindingToRawTypeLiteralIsNotAllowed() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(TypeLiteral.class).toInstance(TypeLiteral.get(String.class)); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(TypeLiteral.class).toInstance(TypeLiteral.get(String.class)); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "Binding to core guice framework type is not allowed: TypeLiteral"); } } public void testBindingToParameterizedTypeLiteralIsNotAllowed() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(new TypeLiteral>() {}) - .toInstance(TypeLiteral.get(String.class)); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(new TypeLiteral>() {}) + .toInstance(TypeLiteral.get(String.class)); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "Binding to core guice framework type is not allowed: TypeLiteral"); } } @@ -70,8 +74,11 @@ Guice.createInjector().getInstance(B.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), TypeLiteral.class.getName() + "> " - + "cannot be used as a key; It is not fully specified."); + assertContains( + expected.getMessage(), + TypeLiteral.class.getName() + + "> " + + "cannot be used as a key; It is not fully specified."); } } @@ -88,8 +95,8 @@ Guice.createInjector().getInstance(TypeLiteral.class); fail(); } catch (ConfigurationException expected) { - assertContains(expected.getMessage(), - "Cannot inject a TypeLiteral that has no type parameter"); + assertContains( + expected.getMessage(), "Cannot inject a TypeLiteral that has no type parameter"); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/TypeLiteralTest.java sisu-guice-4.2.0/core/test/com/google/inject/TypeLiteralTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/TypeLiteralTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/TypeLiteralTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,23 +21,18 @@ import com.google.common.collect.ImmutableList; import com.google.inject.util.Types; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class TypeLiteralTest extends TestCase { public void testWithParameterizedType() { TypeLiteral> a = new TypeLiteral>() {}; - TypeLiteral> b = new TypeLiteral>( - Types.listOf(String.class)) {}; + TypeLiteral> b = new TypeLiteral>(Types.listOf(String.class)) {}; assertEqualsBothWays(a, b); } @@ -79,15 +74,16 @@ try { new TypeLiteral() {}; fail(); - } catch (RuntimeException e) { /* expected */ } + } catch (RuntimeException e) { + /* expected */ + } } public void testTypesInvolvingArraysForEquality() { TypeLiteral stringArray = new TypeLiteral() {}; assertEquals(stringArray, new TypeLiteral() {}); - TypeLiteral> listOfStringArray - = new TypeLiteral>() {}; + TypeLiteral> listOfStringArray = new TypeLiteral>() {}; assertEquals(listOfStringArray, new TypeLiteral>() {}); } @@ -104,29 +100,39 @@ } public void testTypeLiteralsMustHaveRawTypes() { - try { - TypeLiteral.get(Types.subtypeOf(Runnable.class)); - fail(); - } catch (IllegalArgumentException expected) { - Asserts.assertContains(expected.getMessage(), "Expected a Class, ParameterizedType, or " - + "GenericArrayType, but is of type " - + "com.google.inject.internal.MoreTypes$WildcardTypeImpl"); - } + // kind of weird, but wildcards and type variables always go to Object + assertEquals(Object.class, TypeLiteral.get(Types.subtypeOf(Runnable.class)).getRawType()); } /** - * Unlike Key, TypeLiteral retains full type information and differentiates - * between {@code int.class} and {@code Integer.class}. + * Unlike Key, TypeLiteral retains full type information and differentiates between {@code + * int.class} and {@code Integer.class}. */ public void testDifferentiationBetweenWrappersAndPrimitives() { - Class[] primitives = new Class[] { - boolean.class, byte.class, short.class, int.class, long.class, - float.class, double.class, char.class, void.class - }; - Class[] wrappers = new Class[] { - Boolean.class, Byte.class, Short.class, Integer.class, Long.class, - Float.class, Double.class, Character.class, Void.class - }; + Class[] primitives = + new Class[] { + boolean.class, + byte.class, + short.class, + int.class, + long.class, + float.class, + double.class, + char.class, + void.class + }; + Class[] wrappers = + new Class[] { + Boolean.class, + Byte.class, + Short.class, + Integer.class, + Long.class, + Float.class, + Double.class, + Character.class, + Void.class + }; for (int t = 0; t < primitives.length; t++) { @SuppressWarnings("unchecked") @@ -147,8 +153,8 @@ } public void testTypeVariableWithNoBound() { - TypeVariable>[] typeVariables - = HasTypeParameters.class.getTypeParameters(); + TypeVariable>[] typeVariables = + HasTypeParameters.class.getTypeParameters(); TypeLiteral aTl = TypeLiteral.get(typeVariables[0]); assertEquals(Object.class, aTl.getRawType()); @@ -162,8 +168,8 @@ } public void testTypeVariablesWithSingleBound() { - TypeVariable>[] typeVariables - = HasTypeParameters.class.getTypeParameters(); + TypeVariable>[] typeVariables = + HasTypeParameters.class.getTypeParameters(); TypeLiteral cTl = TypeLiteral.get(typeVariables[2]); assertEquals(Object.class, cTl.getRawType()); @@ -177,8 +183,8 @@ } public void testTypeVariableWithMultipleBounds() { - TypeVariable>[] typeVariables - = HasTypeParameters.class.getTypeParameters(); + TypeVariable>[] typeVariables = + HasTypeParameters.class.getTypeParameters(); TypeLiteral bTl = TypeLiteral.get(typeVariables[1]); assertEquals(Object.class, bTl.getRawType()); @@ -186,13 +192,16 @@ TypeVariable bTv = (TypeVariable) bTl.getType(); assertEquals(HasTypeParameters.class, bTv.getGenericDeclaration()); assertEquals("B", bTv.getName()); - assertEquals(ImmutableList.of(Types.listOf(typeVariables[0]), Runnable.class), + assertEquals( + ImmutableList.of(Types.listOf(typeVariables[0]), Runnable.class), ImmutableList.copyOf(bTv.getBounds())); assertEquals("B", bTv.toString()); assertEqualsBothWays(bTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[1])); } - class HasTypeParameters & Runnable, C extends Runnable> { - A a; B b; C c; + static class HasTypeParameters & Runnable, C extends Runnable> { + A a; + B b; + C c; } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java sisu-guice-4.2.0/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,9 +26,6 @@ import com.google.common.collect.ImmutableList; import com.google.inject.util.Types; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -43,6 +40,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; /** * This test checks that TypeLiteral can perform type resolution on its members. @@ -51,20 +49,20 @@ */ public class TypeLiteralTypeResolutionTest extends TestCase { Type arrayListOfString = newParameterizedType(ArrayList.class, String.class); - Type hasGenericFieldsOfShort = newParameterizedTypeWithOwner( - getClass(), HasGenericFields.class, Short.class); - Type hasGenericConstructorOfShort = newParameterizedTypeWithOwner( - getClass(), GenericConstructor.class, Short.class); - Type throwerOfNpe = newParameterizedTypeWithOwner( - getClass(), Thrower.class, NullPointerException.class); + Type hasGenericFieldsOfShort = + newParameterizedTypeWithOwner(getClass(), HasGenericFields.class, Short.class); + Type hasGenericConstructorOfShort = + newParameterizedTypeWithOwner(getClass(), GenericConstructor.class, Short.class); + Type throwerOfNpe = + newParameterizedTypeWithOwner(getClass(), Thrower.class, NullPointerException.class); Type hasArrayOfShort = newParameterizedTypeWithOwner(getClass(), HasArray.class, Short.class); - Type hasRelatedOfString = newParameterizedTypeWithOwner( - getClass(), HasRelated.class, String.class, String.class); + Type hasRelatedOfString = + newParameterizedTypeWithOwner(getClass(), HasRelated.class, String.class, String.class); Type mapK = Map.class.getTypeParameters()[0]; Type hashMapK = HashMap.class.getTypeParameters()[0]; Type setEntryKV; - Type entryStringInteger = setOf(newParameterizedTypeWithOwner( - Map.class, Map.Entry.class, String.class, Integer.class)); + Type entryStringInteger = + setOf(newParameterizedTypeWithOwner(Map.class, Map.Entry.class, String.class, Integer.class)); Field list; Field instance; Constructor newHasGenericConstructor; @@ -77,7 +75,8 @@ Method echo; Method throwS; - @Override protected void setUp() throws Exception { + @Override + protected void setUp() throws Exception { super.setUp(); list = HasGenericFields.class.getField("list"); @@ -96,19 +95,24 @@ public void testDirectInheritance() throws NoSuchMethodException { TypeLiteral resolver = TypeLiteral.get(arrayListOfString); - assertEquals(listOf(String.class), + assertEquals( + listOf(String.class), resolver.getReturnType(List.class.getMethod("subList", int.class, int.class)).getType()); - assertEquals(ImmutableList.>of(TypeLiteral.get(String.class)), + assertEquals( + ImmutableList.>of(TypeLiteral.get(String.class)), resolver.getParameterTypes(Collection.class.getMethod("add", Object.class))); } - + public void testGenericSupertype() { TypeLiteral resolver = TypeLiteral.get(arrayListOfString); - assertEquals(newParameterizedType(Collection.class, String.class), + assertEquals( + newParameterizedType(Collection.class, String.class), resolver.getSupertype(Collection.class).getType()); - assertEquals(newParameterizedType(Iterable.class, String.class), + assertEquals( + newParameterizedType(Iterable.class, String.class), resolver.getSupertype(Iterable.class).getType()); - assertEquals(newParameterizedType(AbstractList.class, String.class), + assertEquals( + newParameterizedType(AbstractList.class, String.class), resolver.getSupertype(AbstractList.class).getType()); assertEquals(Object.class, resolver.getSupertype(Object.class).getType()); } @@ -122,11 +126,13 @@ static class MyInteger implements MyComparable { int value; + + @Override public int compareTo(MyInteger o) { return value - o.value; } } - + public void testFields() { TypeLiteral resolver = TypeLiteral.get(hasGenericFieldsOfShort); assertEquals(listOf(Short.class), resolver.getFieldType(list).getType()); @@ -140,8 +146,8 @@ public void testGenericConstructor() throws NoSuchMethodException { TypeLiteral resolver = TypeLiteral.get(hasGenericConstructorOfShort); - assertEquals(Short.class, - resolver.getParameterTypes(newHasGenericConstructor).get(0).getType()); + assertEquals( + Short.class, resolver.getParameterTypes(newHasGenericConstructor).get(0).getType()); } static class GenericConstructor { @@ -157,6 +163,7 @@ static class Thrower { public Thrower() throws S {} + public void throwS() throws S {} } @@ -168,6 +175,7 @@ static interface HasArray { T[] getArray(); + Set getSetOfArray(); } @@ -183,17 +191,20 @@ /** Ensure the cache doesn't cache too much */ public void testCachingAndReindexing() throws NoSuchMethodException { - TypeLiteral resolver = TypeLiteral.get( - newParameterizedTypeWithOwner(getClass(), HasLists.class, String.class, Short.class)); - assertEquals(listOf(String.class), - resolver.getReturnType(HasLists.class.getMethod("listS")).getType()); - assertEquals(listOf(Short.class), - resolver.getReturnType(HasLists.class.getMethod("listT")).getType()); + TypeLiteral resolver = + TypeLiteral.get( + newParameterizedTypeWithOwner(getClass(), HasLists.class, String.class, Short.class)); + assertEquals( + listOf(String.class), resolver.getReturnType(HasLists.class.getMethod("listS")).getType()); + assertEquals( + listOf(Short.class), resolver.getReturnType(HasLists.class.getMethod("listT")).getType()); } interface HasLists { List listS(); + List listT(); + List> listEntries(); } @@ -204,43 +215,54 @@ resolver.getExceptionTypes(stringIndexOf); fail(); } catch (IllegalArgumentException e) { - assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a " - + "supertype of java.util.ArrayList", e.getMessage()); + assertEquals( + "public int java.lang.String.indexOf(java.lang.String) is not defined by a " + + "supertype of java.util.ArrayList", + e.getMessage()); } try { resolver.getParameterTypes(stringIndexOf); fail(); } catch (Exception e) { - assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a " - + "supertype of java.util.ArrayList", e.getMessage()); + assertEquals( + "public int java.lang.String.indexOf(java.lang.String) is not defined by a " + + "supertype of java.util.ArrayList", + e.getMessage()); } try { resolver.getReturnType(stringIndexOf); fail(); } catch (Exception e) { - assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a " - + "supertype of java.util.ArrayList", e.getMessage()); + assertEquals( + "public int java.lang.String.indexOf(java.lang.String) is not defined by a " + + "supertype of java.util.ArrayList", + e.getMessage()); } try { resolver.getSupertype(String.class); fail(); } catch (Exception e) { - assertEquals("class java.lang.String is not a supertype of " - + "java.util.ArrayList", e.getMessage()); + assertEquals( + "class java.lang.String is not a supertype of " + "java.util.ArrayList", + e.getMessage()); } try { resolver.getExceptionTypes(newString); fail(); } catch (Exception e) { - assertEquals("public java.lang.String(java.lang.String) does not construct " - + "a supertype of java.util.ArrayList", e.getMessage()); + assertEquals( + "public java.lang.String(java.lang.String) does not construct " + + "a supertype of java.util.ArrayList", + e.getMessage()); } try { resolver.getParameterTypes(newString); fail(); } catch (Exception e) { - assertEquals("public java.lang.String(java.lang.String) does not construct " - + "a supertype of java.util.ArrayList", e.getMessage()); + assertEquals( + "public java.lang.String(java.lang.String) does not construct " + + "a supertype of java.util.ArrayList", + e.getMessage()); } } @@ -250,8 +272,8 @@ typeResolver = new TypeLiteral>() {}; assertEquals(String.class, typeResolver.resolveType(mapK)); - assertEquals(Types.mapOf(String.class, Integer.class), - typeResolver.getSupertype(Map.class).getType()); + assertEquals( + Types.mapOf(String.class, Integer.class), typeResolver.getSupertype(Map.class).getType()); typeResolver = new TypeLiteral>() {}; assertEquals(String.class, typeResolver.resolveType(mapK)); @@ -277,17 +299,21 @@ } interface StringIntegerMap extends Map {} + interface BetterMap extends Map {} + interface BestMap extends BetterMap {} + static class StringIntegerHashMap extends HashMap {} public void testGetSupertype() { TypeLiteral> listOfString = new TypeLiteral>() {}; - assertEquals(Types.newParameterizedType(AbstractCollection.class, String.class), + assertEquals( + Types.newParameterizedType(AbstractCollection.class, String.class), listOfString.getSupertype(AbstractCollection.class).getType()); - TypeLiteral arrayListOfE = TypeLiteral.get(newParameterizedType( - ArrayList.class, ArrayList.class.getTypeParameters())); + TypeLiteral arrayListOfE = + TypeLiteral.get(newParameterizedType(ArrayList.class, ArrayList.class.getTypeParameters())); assertEquals( newParameterizedType(AbstractCollection.class, ArrayList.class.getTypeParameters()), arrayListOfE.getSupertype(AbstractCollection.class).getType()); @@ -297,18 +323,22 @@ Class arraysAsListClass = Arrays.asList().getClass(); Type anotherE = arraysAsListClass.getTypeParameters()[0]; TypeLiteral type = TypeLiteral.get(newParameterizedType(AbstractList.class, anotherE)); - assertEquals(newParameterizedType(AbstractCollection.class, anotherE), + assertEquals( + newParameterizedType(AbstractCollection.class, anotherE), type.getSupertype(AbstractCollection.class).getType()); } public void testWildcards() throws NoSuchFieldException { TypeLiteral> ofString = new TypeLiteral>() {}; - assertEquals(new TypeLiteral>() {}.getType(), + assertEquals( + new TypeLiteral>() {}.getType(), ofString.getFieldType(Parameterized.class.getField("t")).getType()); - assertEquals(new TypeLiteral>() {}.getType(), + assertEquals( + new TypeLiteral>() {}.getType(), ofString.getFieldType(Parameterized.class.getField("extendsT")).getType()); - assertEquals(new TypeLiteral>() {}.getType(), + assertEquals( + new TypeLiteral>() {}.getType(), ofString.getFieldType(Parameterized.class.getField("superT")).getType()); } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/util/NoopOverrideTest.java sisu-guice-4.2.0/core/test/com/google/inject/util/NoopOverrideTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/util/NoopOverrideTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/util/NoopOverrideTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,13 +20,12 @@ import com.google.inject.spi.ElementVisitor; import com.google.inject.spi.ElementsTest; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class NoopOverrideTest extends ElementsTest { + @Override protected void checkModule(Module module, ElementVisitor... visitors) { Module overridden = Modules.override(module).with(Modules.EMPTY_MODULE); super.checkModule(overridden, visitors); } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/util/OverrideModuleTest.java sisu-guice-4.2.0/core/test/com/google/inject/util/OverrideModuleTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/util/OverrideModuleTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/util/OverrideModuleTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,9 +45,6 @@ import com.google.inject.name.Names; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.ModuleAnnotatedMethodScanner; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -55,18 +52,19 @@ import java.util.Date; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import junit.framework.TestCase; -/** - * @author sberlin@gmail.com (Sam Berlin) - */ +/** @author sberlin@gmail.com (Sam Berlin) */ public class OverrideModuleTest extends TestCase { private static final Key key2 = Key.get(String.class, named("2")); private static final Key key3 = Key.get(String.class, named("3")); - private static final Module EMPTY_MODULE = new Module() { - public void configure(Binder binder) {} - }; + private static final Module EMPTY_MODULE = + new Module() { + @Override + public void configure(Binder binder) {} + }; public void testOverride() { Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B"))); @@ -74,13 +72,14 @@ } public void testOverrideMultiple() { - Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f)) - .with(newModule("B"), newModule(2), newModule(1.5d)); + Module module = + Modules.override(newModule("A"), newModule(1), newModule(0.5f)) + .with(newModule("B"), newModule(2), newModule(1.5d)); Injector injector = createInjector(module); assertEquals("B", injector.getInstance(String.class)); assertEquals(2, injector.getInstance(Integer.class).intValue()); - assertEquals(0.5f, injector.getInstance(Float.class)); - assertEquals(1.5d, injector.getInstance(Double.class)); + assertEquals(0.5f, injector.getInstance(Float.class), 0.0f); + assertEquals(1.5d, injector.getInstance(Double.class), 0.0); } public void testOverrideUnmatchedTolerated() { @@ -89,29 +88,35 @@ } public void testOverrideConstant() { - Module original = new AbstractModule() { - @Override protected void configure() { - bindConstant().annotatedWith(named("Test")).to("A"); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(named("Test")).to("A"); + } + }; - Module replacements = new AbstractModule() { - @Override protected void configure() { - bindConstant().annotatedWith(named("Test")).to("B"); - } - }; + Module replacements = + new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(named("Test")).to("B"); + } + }; Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals("B", injector.getInstance(Key.get(String.class, named("Test")))); } public void testGetProviderInModule() { - Module original = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("A"); - bind(key2).toProvider(getProvider(String.class)); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A"); + bind(key2).toProvider(getProvider(String.class)); + } + }; Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE)); assertEquals("A", injector.getInstance(String.class)); @@ -119,12 +124,14 @@ } public void testOverrideWhatGetProviderProvided() { - Module original = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("A"); - bind(key2).toProvider(getProvider(String.class)); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A"); + bind(key2).toProvider(getProvider(String.class)); + } + }; Module replacements = newModule("B"); @@ -134,18 +141,22 @@ } public void testOverrideUsingOriginalsGetProvider() { - Module original = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("A"); - bind(key2).toInstance("B"); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A"); + bind(key2).toInstance("B"); + } + }; - Module replacements = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toProvider(getProvider(key2)); - } - }; + Module replacements = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toProvider(getProvider(key2)); + } + }; Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals("B", injector.getInstance(String.class)); @@ -153,29 +164,35 @@ } public void testOverrideOfOverride() { - Module original = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("A1"); - bind(key2).toInstance("A2"); - bind(key3).toInstance("A3"); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A1"); + bind(key2).toInstance("A2"); + bind(key3).toInstance("A3"); + } + }; - Module replacements1 = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("B1"); - bind(key2).toInstance("B2"); - } - }; + Module replacements1 = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("B1"); + bind(key2).toInstance("B2"); + } + }; Module overrides = Modules.override(original).with(replacements1); - Module replacements2 = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("C1"); - bind(key3).toInstance("C3"); - } - }; + Module replacements2 = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("C1"); + bind(key3).toInstance("C3"); + } + }; Injector injector = createInjector(Modules.override(overrides).with(replacements2)); assertEquals("C1", injector.getInstance(String.class)); @@ -184,16 +201,20 @@ } static class OuterReplacementsModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { install(new InnerReplacementsModule()); } } + static class InnerReplacementsModule extends AbstractModule { - @Override protected void configure() { + @Override + protected void configure() { bind(String.class).toInstance("B"); bind(String.class).toInstance("C"); } } + public void testOverridesTwiceFails() { Module original = newModule("A"); Module replacements = new OuterReplacementsModule(); @@ -202,30 +223,39 @@ createInjector(module); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "A binding to java.lang.String was already configured at " + InnerReplacementsModule.class.getName(), - asModuleChain(Modules.OverrideModule.class, - OuterReplacementsModule.class, InnerReplacementsModule.class), + asModuleChain( + Modules.OverrideModule.class, + OuterReplacementsModule.class, + InnerReplacementsModule.class), "at " + InnerReplacementsModule.class.getName(), - asModuleChain(Modules.OverrideModule.class, - OuterReplacementsModule.class, InnerReplacementsModule.class)); + asModuleChain( + Modules.OverrideModule.class, + OuterReplacementsModule.class, + InnerReplacementsModule.class)); } } public void testOverridesDoesntFixTwiceBoundInOriginal() { - Module original = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("A"); - bind(String.class).toInstance("B"); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A"); + bind(String.class).toInstance("B"); + } + }; - Module replacements = new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("C"); - } - }; + Module replacements = + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("C"); + } + }; Module module = Modules.override(original).with(replacements); try { @@ -234,7 +264,8 @@ } catch (CreationException expected) { // The replacement comes first because we replace A with C, // then we encounter B and freak out. - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) A binding to java.lang.String was already configured at " + replacements.getClass().getName(), asModuleChain(Modules.OverrideModule.class, replacements.getClass()), @@ -246,12 +277,14 @@ public void testStandardScopeAnnotation() { final SingleUseScope scope = new SingleUseScope(); - Module module = new AbstractModule() { - @Override protected void configure() { - bindScope(TestScopeAnnotation.class, scope); - bind(String.class).in(TestScopeAnnotation.class); - } - }; + Module module = + new AbstractModule() { + @Override + protected void configure() { + bindScope(TestScopeAnnotation.class, scope); + bind(String.class).in(TestScopeAnnotation.class); + } + }; assertFalse(scope.used); Guice.createInjector(module); @@ -259,43 +292,53 @@ } public void testOverrideUntargettedBinding() { - Module original = new AbstractModule() { - @Override protected void configure() { - bind(Date.class); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bind(Date.class); + } + }; - Module replacements = new AbstractModule() { - @Override protected void configure() { - bind(Date.class).toInstance(new Date(0)); - } - }; + Module replacements = + new AbstractModule() { + @Override + protected void configure() { + bind(Date.class).toInstance(new Date(0)); + } + }; Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals(0, injector.getInstance(Date.class).getTime()); } public void testOverrideScopeAnnotation() { - final Scope scope = new Scope() { - public Provider scope(Key key, Provider unscoped) { - throw new AssertionError("Should not be called"); - } - }; + final Scope scope = + new Scope() { + @Override + public Provider scope(Key key, Provider unscoped) { + throw new AssertionError("Should not be called"); + } + }; final SingleUseScope replacementScope = new SingleUseScope(); - Module original = new AbstractModule() { - @Override protected void configure() { - bindScope(TestScopeAnnotation.class, scope); - bind(Date.class).in(TestScopeAnnotation.class); - } - }; + Module original = + new AbstractModule() { + @Override + protected void configure() { + bindScope(TestScopeAnnotation.class, scope); + bind(Date.class).in(TestScopeAnnotation.class); + } + }; - Module replacements = new AbstractModule() { - @Override protected void configure() { - bindScope(TestScopeAnnotation.class, replacementScope); - } - }; + Module replacements = + new AbstractModule() { + @Override + protected void configure() { + bindScope(TestScopeAnnotation.class, replacementScope); + } + }; Injector injector = createInjector(Modules.override(original).with(replacements)); injector.getInstance(Date.class); @@ -303,63 +346,80 @@ } public void testFailsIfOverridenScopeInstanceHasBeenUsed() { - final Scope scope = new Scope() { - public Provider scope(Key key, Provider unscoped) { - return unscoped; - } + final Scope scope = + new Scope() { + @Override + public Provider scope(Key key, Provider unscoped) { + return unscoped; + } - @Override public String toString() { - return "ORIGINAL SCOPE"; - } - }; + @Override + public String toString() { + return "ORIGINAL SCOPE"; + } + }; - final Module original = new AbstractModule() { - @Override protected void configure() { - bindScope(TestScopeAnnotation.class, scope); - bind(Date.class).in(scope); - bind(String.class).in(scope); - } - }; - Module originalWrapper = new AbstractModule() { - @Override protected void configure() { - install(original); - } - }; + final Module original = + new AbstractModule() { + @Override + protected void configure() { + bindScope(TestScopeAnnotation.class, scope); + bind(Date.class).in(scope); + bind(String.class).in(scope); + } + }; + Module originalWrapper = + new AbstractModule() { + @Override + protected void configure() { + install(original); + } + }; - Module replacements = new AbstractModule() { - @Override protected void configure() { - bindScope(TestScopeAnnotation.class, new SingleUseScope()); - } - }; + Module replacements = + new AbstractModule() { + @Override + protected void configure() { + bindScope(TestScopeAnnotation.class, new SingleUseScope()); + } + }; try { createInjector(Modules.override(originalWrapper).with(replacements)); fail("Exception expected"); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.", "original binding at " + original.getClass().getName() + ".configure(", asModuleChain(originalWrapper.getClass(), original.getClass()), "bound directly at " + original.getClass().getName() + ".configure(", asModuleChain(originalWrapper.getClass(), original.getClass()), "bound directly at " + original.getClass().getName() + ".configure(", - asModuleChain(originalWrapper.getClass(), original.getClass()), - "at ", replacements.getClass().getName() + ".configure(", + asModuleChain(originalWrapper.getClass(), original.getClass()), + "at ", + replacements.getClass().getName() + ".configure(", asModuleChain(Modules.OverrideModule.class, replacements.getClass())); } } public void testOverrideIsLazy() { - final AtomicReference value = new AtomicReference("A"); - Module overridden = Modules.override(new AbstractModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(named("original")).toInstance(value.get()); - } - }).with(new AbstractModule() { - @Override protected void configure() { - bind(String.class).annotatedWith(named("override")).toInstance(value.get()); - } - }); + final AtomicReference value = new AtomicReference<>("A"); + Module overridden = + Modules.override( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(named("original")).toInstance(value.get()); + } + }) + .with( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(named("override")).toInstance(value.get()); + } + }); // the value.get() call should be deferred until Guice.createInjector value.set("B"); @@ -369,46 +429,58 @@ } public void testOverridePrivateModuleOverPrivateModule() { - Module exposes5and6 = new AbstractModule() { - @Override protected void configure() { - install(new PrivateModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(5); - expose(Integer.class); - - bind(Character.class).toInstance('E'); - } - }); - - install(new PrivateModule() { - @Override protected void configure() { - bind(Long.class).toInstance(6L); - expose(Long.class); - - bind(Character.class).toInstance('F'); + Module exposes5and6 = + new AbstractModule() { + @Override + protected void configure() { + install( + new PrivateModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(5); + expose(Integer.class); + + bind(Character.class).toInstance('E'); + } + }); + + install( + new PrivateModule() { + @Override + protected void configure() { + bind(Long.class).toInstance(6L); + expose(Long.class); + + bind(Character.class).toInstance('F'); + } + }); } - }); - } - }; - - AbstractModule exposes15 = new AbstractModule() { - @Override protected void configure() { - install(new PrivateModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(15); - expose(Integer.class); + }; - bind(Character.class).toInstance('G'); + AbstractModule exposes15 = + new AbstractModule() { + @Override + protected void configure() { + install( + new PrivateModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(15); + expose(Integer.class); + + bind(Character.class).toInstance('G'); + } + }); + + install( + new PrivateModule() { + @Override + protected void configure() { + bind(Character.class).toInstance('H'); + } + }); } - }); - - install(new PrivateModule() { - @Override protected void configure() { - bind(Character.class).toInstance('H'); - } - }); - } - }; + }; // override forwards Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15)); @@ -422,18 +494,22 @@ } public void testOverrideModuleAndPrivateModule() { - Module exposes5 = new PrivateModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(5); - expose(Integer.class); - } - }; + Module exposes5 = + new PrivateModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(5); + expose(Integer.class); + } + }; - Module binds15 = new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(15); - } - }; + Module binds15 = + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(15); + } + }; Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15)); assertEquals(15, injector.getInstance(Integer.class).intValue()); @@ -443,22 +519,26 @@ } public void testOverrideDeepExpose() { - final AtomicReference> charAProvider - = new AtomicReference>(); + final AtomicReference> charAProvider = + new AtomicReference>(); - Module exposes5 = new PrivateModule() { - @Override protected void configure() { - install(new PrivateModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(5); + Module exposes5 = + new PrivateModule() { + @Override + protected void configure() { + install( + new PrivateModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(5); + expose(Integer.class); + charAProvider.set(getProvider(Character.class)); + bind(Character.class).toInstance('A'); + } + }); expose(Integer.class); - charAProvider.set(getProvider(Character.class)); - bind(Character.class).toInstance('A'); } - }); - expose(Integer.class); - } - }; + }; Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE)); assertEquals(5, injector.getInstance(Integer.class).intValue()); @@ -468,21 +548,25 @@ assertEquals(5, injector.getInstance(Integer.class).intValue()); assertEquals('A', charAProvider.getAndSet(null).get().charValue()); - final AtomicReference> charBProvider - = new AtomicReference>(); + final AtomicReference> charBProvider = + new AtomicReference>(); + + Module binds15 = + new AbstractModule() { + @Override + protected void configure() { + bind(Integer.class).toInstance(15); - Module binds15 = new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).toInstance(15); - - install(new PrivateModule() { - @Override protected void configure() { - charBProvider.set(getProvider(Character.class)); - bind(Character.class).toInstance('B'); + install( + new PrivateModule() { + @Override + protected void configure() { + charBProvider.set(getProvider(Character.class)); + bind(Character.class).toInstance('B'); + } + }); } - }); - } - }; + }; injector = Guice.createInjector(Modules.override(binds15).with(exposes5)); assertEquals(5, injector.getInstance(Integer.class).intValue()); @@ -502,21 +586,26 @@ private static class SingleUseScope implements Scope { boolean used = false; + + @Override public Provider scope(Key key, Provider unscoped) { assertFalse(used); used = true; return unscoped; } } - + static class NewModule extends AbstractModule { private final T bound; + NewModule(T bound) { this.bound = bound; } - @Override protected void configure() { + + @Override + protected void configure() { @SuppressWarnings("unchecked") - Class type = (Class)bound.getClass(); + Class type = (Class) bound.getClass(); bind(type).toInstance(bound); } } @@ -524,7 +613,7 @@ private static Module newModule(final T bound) { return new NewModule(bound); } - + private static final String RESULT = "RESULT"; private static final String PRIVATE_INPUT = "PRIVATE_INPUT"; private static final String OVERRIDDEN_INPUT = "FOO"; @@ -533,117 +622,138 @@ private static final Key INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT)); public void testExposedBindingOverride() throws Exception { - Injector inj = Guice.createInjector( - Modules.override(new ExampleModule()).with( - new AbstractModule() { - @Override protected void configure() { - bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT); - } - })); - assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT); + Injector inj = + Guice.createInjector( + Modules.override(new ExampleModule()) + .with( + new AbstractModule() { + @Override + protected void configure() { + bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT); + } + })); + assertEquals(OVERRIDDEN_RESULT, inj.getInstance(RESULT_KEY)); } public void testPrivateBindingOverride() throws Exception { - Injector inj = Guice.createInjector( - Modules.override(new ExampleModule()).with( - new AbstractModule() { - @Override protected void configure() { - bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT); - } - })); - assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT); + Injector inj = + Guice.createInjector( + Modules.override(new ExampleModule()) + .with( + new AbstractModule() { + @Override + protected void configure() { + bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT); + } + })); + assertEquals(OVERRIDDEN_RESULT, inj.getInstance(RESULT_KEY)); } public static class ExampleModule extends PrivateModule { - @Provides @Exposed @Named(RESULT) + @Provides + @Exposed + @Named(RESULT) public String provideResult(@Named(PRIVATE_INPUT) String input) { return "Size: " + input.length(); } - @Provides @Named(PRIVATE_INPUT) + @Provides + @Named(PRIVATE_INPUT) public String provideInput() { return "Hello World"; } - @Override protected void configure() { - } - } - + @Override + protected void configure() {} + } + public void testEqualsNotCalledByDefaultOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; - Guice.createInjector(Modules.override(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(HashEqualsTester.class).toInstance(a); - } - }).with()); + Guice.createInjector( + Modules.override( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(HashEqualsTester.class).toInstance(a); + } + }) + .with()); } - + public void testEqualsNotCalledByDefaultOnProvider() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; - Guice.createInjector(Modules.override(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(Object.class).toProvider(a); - } - }).with()); + Guice.createInjector( + Modules.override( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(Object.class).toProvider(a); + } + }) + .with()); } - + public void testHashcodeNeverCalledOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; - + final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; - Guice.createInjector(Modules.override(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(HashEqualsTester.class).toInstance(a); - bind(HashEqualsTester.class).toInstance(b); - } - }).with()); + Guice.createInjector( + Modules.override( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(HashEqualsTester.class).toInstance(a); + bind(HashEqualsTester.class).toInstance(b); + } + }) + .with()); } - + public void testHashcodeNeverCalledOnProviderInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; - + final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; - Guice.createInjector(Modules.override(new AbstractModule() { - @Override - protected void configure() { - bind(String.class); - bind(Object.class).toProvider(a); - bind(Object.class).toProvider(b); - } - }).with()); + Guice.createInjector( + Modules.override( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class); + bind(Object.class).toProvider(a); + bind(Object.class).toProvider(b); + } + }) + .with()); } - + private static class HashEqualsTester implements Provider { private String equality; private boolean throwOnEquals; private boolean throwOnHashcode; - + @Override public boolean equals(Object obj) { if (throwOnEquals) { throw new RuntimeException(); } else if (obj instanceof HashEqualsTester) { - HashEqualsTester o = (HashEqualsTester)obj; - if(o.throwOnEquals) { + HashEqualsTester o = (HashEqualsTester) obj; + if (o.throwOnEquals) { throw new RuntimeException(); } - if(equality == null && o.equality == null) { + if (equality == null && o.equality == null) { return this == o; } else { return Objects.equal(equality, o.equality); @@ -652,16 +762,17 @@ return false; } } - + @Override public int hashCode() { - if(throwOnHashcode) { + if (throwOnHashcode) { throw new RuntimeException(); } else { return super.hashCode(); } } - + + @Override public Object get() { return new Object(); } @@ -669,43 +780,57 @@ public void testCorrectStage() { final Stage stage = Stage.PRODUCTION; - Module module = Modules.override(new AbstractModule() { - @Override - protected void configure() { - if (currentStage() != Stage.PRODUCTION) { - addError("Wronge stage in overridden module:" + currentStage()); - } - } - }).with(new AbstractModule() { - @Override - protected void configure() { - if (currentStage() != Stage.PRODUCTION) { - addError("Wronge stage in overriding module:" + currentStage()); - } - } - }); + Module module = + Modules.override( + new AbstractModule() { + @Override + protected void configure() { + if (currentStage() != Stage.PRODUCTION) { + addError("Wronge stage in overridden module:" + currentStage()); + } + } + }) + .with( + new AbstractModule() { + @Override + protected void configure() { + if (currentStage() != Stage.PRODUCTION) { + addError("Wronge stage in overriding module:" + currentStage()); + } + } + }); Guice.createInjector(stage, module); } public void testOverridesApplyOriginalScanners() { Injector injector = - Guice.createInjector(Modules.override(NamedMunger.module()).with(new AbstractModule() { - @Override protected void configure() {} - @TestProvides @Named("test") String provideString() { return "foo"; } - })); + Guice.createInjector( + Modules.override(NamedMunger.module()) + .with( + new AbstractModule() { + + @TestProvides + @Named("test") + String provideString() { + return "foo"; + } + })); assertNull(injector.getExistingBinding(Key.get(String.class, named("test")))); Binding binding = injector.getBinding(Key.get(String.class, named("test-munged"))); assertEquals("foo", binding.getProvider().get()); } - @Documented @Target(METHOD) @Retention(RUNTIME) + @Documented + @Target(METHOD) + @Retention(RUNTIME) private @interface TestProvides {} private static class NamedMunger extends ModuleAnnotatedMethodScanner { static Module module() { return new AbstractModule() { - @Override protected void configure() { + @Override + protected void configure() { binder().scanModulesForAnnotatedMethods(new NamedMunger()); } }; @@ -722,10 +847,10 @@ } @Override - public Key prepareMethod(Binder binder, Annotation annotation, Key key, - InjectionPoint injectionPoint) { - return Key.get(key.getTypeLiteral(), - Names.named(((Named) key.getAnnotation()).value() + "-munged")); + public Key prepareMethod( + Binder binder, Annotation annotation, Key key, InjectionPoint injectionPoint) { + return Key.get( + key.getTypeLiteral(), Names.named(((Named) key.getAnnotation()).value() + "-munged")); } } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/util/ProvidersTest.java sisu-guice-4.2.0/core/test/com/google/inject/util/ProvidersTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/util/ProvidersTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/util/ProvidersTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -19,10 +19,8 @@ import com.google.common.base.Objects; import com.google.common.testing.EqualsTester; import com.google.inject.Provider; - -import junit.framework.TestCase; - import javax.inject.Inject; +import junit.framework.TestCase; /** * Unit tests for {@link Providers}. @@ -42,68 +40,69 @@ Provider p = Providers.of(null); assertNull(p.get()); } - + public void testOfEquality() { new EqualsTester() - .addEqualityGroup( - Providers.of(null), - Providers.of(null)) - .addEqualityGroup( - Providers.of("Hello"), - Providers.of("Hello")) + .addEqualityGroup(Providers.of(null), Providers.of(null)) + .addEqualityGroup(Providers.of("Hello"), Providers.of("Hello")) .testEquals(); } - + public void testGuicifyEquality() { new EqualsTester() .addEqualityGroup( - Providers.guicify(new JavaxProvider(10)), - Providers.guicify(new JavaxProvider(10))) + Providers.guicify(new JavaxProvider(10)), Providers.guicify(new JavaxProvider(10))) .addEqualityGroup( - Providers.guicify(new JavaxProvider(11)), - Providers.guicify(new JavaxProvider(11))) + Providers.guicify(new JavaxProvider(11)), Providers.guicify(new JavaxProvider(11))) .addEqualityGroup( Providers.guicify(new JavaxProviderWithDependencies()), Providers.guicify(new JavaxProviderWithDependencies())) .testEquals(); } - + private static class JavaxProvider implements javax.inject.Provider { private final int value; public JavaxProvider(int value) { this.value = value; } - + + @Override public Integer get() { return value; } - @Override public int hashCode() { + @Override + public int hashCode() { return Objects.hashCode(value); } - @Override public boolean equals(Object obj) { + @Override + public boolean equals(Object obj) { return (obj instanceof JavaxProvider) && (value == ((JavaxProvider) obj).value); } } - + private static class JavaxProviderWithDependencies implements javax.inject.Provider { private int value; - - @Inject void setValue(int value) { + + @Inject + void setValue(int value) { this.value = value; } - + + @Override public Integer get() { return value; } - @Override public int hashCode() { + @Override + public int hashCode() { return 42; } - @Override public boolean equals(Object obj) { + @Override + public boolean equals(Object obj) { return (obj instanceof JavaxProviderWithDependencies); } } diff -Nru sisu-guice-3.2.6/core/test/com/google/inject/util/TypesTest.java sisu-guice-4.2.0/core/test/com/google/inject/util/TypesTest.java --- sisu-guice-3.2.6/core/test/com/google/inject/util/TypesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/google/inject/util/TypesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.google.inject.util; import static com.google.inject.Asserts.assertContains; @@ -25,10 +24,6 @@ import com.google.inject.TypeLiteral; import com.google.inject.internal.MoreTypes; - -import junit.framework.Assert; -import junit.framework.TestCase; - import java.io.IOException; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; @@ -37,10 +32,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import junit.framework.Assert; +import junit.framework.TestCase; -/** - * @author jessewilson@google.com (Jesse Wilson) - */ +/** @author jessewilson@google.com (Jesse Wilson) */ public class TypesTest extends TestCase { // generic types for comparison @@ -78,7 +73,7 @@ } public void testDefensiveCopies() { - Type[] arguments = new Type[] { String.class, Integer.class }; + Type[] arguments = new Type[] {String.class, Integer.class}; ParameterizedType parameterizedType = Types.newParameterizedType(Map.class, arguments); arguments[0] = null; assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]); @@ -87,17 +82,20 @@ } public void testTypeWithOwnerType() { - ParameterizedType actual = Types.newParameterizedTypeWithOwner( - TypesTest.class, Inner.class, Float.class, Double.class); + ParameterizedType actual = + Types.newParameterizedTypeWithOwner( + TypesTest.class, Inner.class, Float.class, Double.class); assertEquals(TypesTest.class, actual.getOwnerType()); assertEqualsBothWays(innerFloatDouble, actual); // The JDK prints this out as: // com.google.inject.util.TypesTest.com.google.inject.util.TypesTest$Inner // and we think that's wrong, so the assertEquals comparison is worthless. :-( -// assertEquals(innerFloatDouble.toString(), actual.toString()); - + // assertEquals(innerFloatDouble.toString(), actual.toString()); + // We think the correct comparison is: - assertEquals("com.google.inject.util.TypesTest$Inner", actual.toString()); + assertEquals( + "com.google.inject.util.TypesTest$Inner", + actual.toString()); } public void testTypeParametersMustNotBePrimitives() { @@ -105,8 +103,8 @@ Types.newParameterizedType(Map.class, String.class, int.class); fail(); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), - "Primitive types are not allowed in type parameters: int"); + assertContains( + expected.getMessage(), "Primitive types are not allowed in type parameters: int"); } } @@ -126,22 +124,22 @@ assertEqualWhenReserialized(supertypeOf(CharSequence.class)); assertEqualWhenReserialized(subtypeOf(CharSequence.class)); } - + public void testWildcardBoundsMustNotBePrimitives() { try { supertypeOf(int.class); fail(); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), - "Primitive types are not allowed in wildcard bounds: int"); + assertContains( + expected.getMessage(), "Primitive types are not allowed in wildcard bounds: int"); } try { subtypeOf(int.class); fail(); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), - "Primitive types are not allowed in wildcard bounds: int"); + assertContains( + expected.getMessage(), "Primitive types are not allowed in wildcard bounds: int"); } } @@ -151,13 +149,13 @@ } public void testEqualsAndHashcode() { - ParameterizedType parameterizedType - = Types.newParameterizedType(Map.class, String.class, Integer.class); + ParameterizedType parameterizedType = + Types.newParameterizedType(Map.class, String.class, Integer.class); assertEqualsBothWays(mapStringInteger, parameterizedType); assertEquals(mapStringInteger.toString(), parameterizedType.toString()); - GenericArrayType genericArrayType = Types.arrayOf(Types.arrayOf( - Types.newParameterizedType(Set.class, String.class))); + GenericArrayType genericArrayType = + Types.arrayOf(Types.arrayOf(Types.newParameterizedType(Set.class, String.class))); assertEqualsBothWays(setStringArray, genericArrayType); assertEquals(setStringArray.toString(), genericArrayType.toString()); } @@ -165,40 +163,37 @@ public void testToString() { Assert.assertEquals("java.lang.String", MoreTypes.typeToString(String.class)); assertEquals("java.util.Set[][]", MoreTypes.typeToString(setStringArray)); - assertEquals("java.util.Map", + assertEquals( + "java.util.Map", MoreTypes.typeToString(mapStringInteger)); - assertEquals("java.util.List[][]>", + assertEquals( + "java.util.List[][]>", MoreTypes.typeToString(listSetStringArray)); - assertEquals(innerFloatDouble.toString(), - MoreTypes.typeToString(innerFloatDouble)); + assertEquals(innerFloatDouble.toString(), MoreTypes.typeToString(innerFloatDouble)); } static class Owning {} - /** - * Ensure that owning types are required when necessary, and forbidden - * otherwise. - */ + /** Ensure that owning types are required when necessary, and forbidden otherwise. */ public void testCanonicalizeRequiresOwnerTypes() { try { Types.newParameterizedType(Owning.class, String.class); fail(); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), - "No owner type for enclosed " + Owning.class); + assertContains(expected.getMessage(), "No owner type for enclosed " + Owning.class); } try { Types.newParameterizedTypeWithOwner(Object.class, Set.class, String.class); + fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { - assertContains(expected.getMessage(), - "Owner type for unenclosed " + Set.class); + assertContains(expected.getMessage(), "Owner type for unenclosed " + Set.class); } } @SuppressWarnings("UnusedDeclaration") class Inner {} - + public void testInnerParameterizedEvenWithZeroArgs() { TypeLiteral.Inner> type = new TypeLiteral.Inner>() {}; assertEqualsBothWays(outerInner, type.getType()); @@ -210,6 +205,7 @@ } static class Outer { + @SuppressWarnings("ClassCanBeStatic") class Inner {} } } diff -Nru sisu-guice-3.2.6/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java sisu-guice-4.2.0/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java --- sisu-guice-3.2.6/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,23 +24,21 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.matcher.AbstractMatcher; - +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Random; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Random; - /** * Test Guice from inside an OSGi bundle activator. - * + * * @author mcculls@gmail.com (Stuart McCulloch) */ -@SuppressWarnings("unused") public class OSGiTestActivator - implements BundleActivator { +@SuppressWarnings("unused") +public class OSGiTestActivator implements BundleActivator { // varying visibilities to test our code-generation support @@ -54,18 +52,21 @@ private interface D {} - public static class AA - implements A { + public static class AA implements A { public AA() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -76,18 +77,21 @@ @Inject private Undefined d; } - protected static class AB - implements A { + protected static class AB implements A { public AB() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -98,18 +102,21 @@ @Inject private Undefined d; } - static class AC - implements A { + static class AC implements A { public AC() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -120,18 +127,21 @@ @Inject private Undefined d; } - private static class AD - implements A { + private static class AD implements A { public AD() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -142,18 +152,21 @@ @Inject private Undefined d; } - public static class BA - implements B { + public static class BA implements B { protected BA() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -164,18 +177,21 @@ @Inject private Undefined d; } - protected static class BB - implements B { + protected static class BB implements B { protected BB() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -186,18 +202,21 @@ @Inject private Undefined d; } - static class BC - implements B { + static class BC implements B { protected BC() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -208,18 +227,21 @@ @Inject private Undefined d; } - private static class BD - implements B { + private static class BD implements B { protected BD() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -230,18 +252,21 @@ @Inject private Undefined d; } - public static class CA - implements C { + public static class CA implements C { CA() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -252,18 +277,21 @@ @Inject private Undefined d; } - protected static class CB - implements C { + protected static class CB implements C { CB() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -274,18 +302,21 @@ @Inject private Undefined d; } - static class CC - implements C { + static class CC implements C { CC() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -296,18 +327,21 @@ @Inject private Undefined d; } - private static class CD - implements C { + private static class CD implements C { CD() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -318,18 +352,22 @@ @Inject private Undefined d; } - public static class DA - implements D { + public static class DA implements D { - @Inject private DA() {} + @Inject + private DA() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -340,18 +378,22 @@ @Inject private Undefined d; } - protected static class DB - implements D { + protected static class DB implements D { - @Inject private DB() {} + @Inject + private DB() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -362,18 +404,22 @@ @Inject private Undefined d; } - static class DC - implements D { + static class DC implements D { - @Inject private DC() {} + @Inject + private DC() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -384,18 +430,21 @@ @Inject private Undefined d; } - private static class DD - implements D { + private static class DD implements D { private DD() {} - @Inject public void setA(Undefined undefined) {} + @Inject + public void setA(Undefined undefined) {} - @Inject protected void setB(Undefined undefined) {} + @Inject + protected void setB(Undefined undefined) {} - @Inject void setC(Undefined undefined) {} + @Inject + void setC(Undefined undefined) {} - @Inject private void setD(Undefined undefined) {} + @Inject + private void setD(Undefined undefined) {} @Inject public Undefined a; @@ -407,14 +456,16 @@ } enum Visibility { - PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE + PUBLIC, + PROTECTED, + PACKAGE_PRIVATE, + PRIVATE } static final Class[] TEST_CLAZZES = {A.class, B.class, C.class, D.class}; // registers all the class combinations - static class TestModule - extends AbstractModule { + static class TestModule extends AbstractModule { final Bundle bundle; @@ -422,7 +473,9 @@ this.bundle = bundle; } - @Override @SuppressWarnings("unchecked") protected void configure() { + @Override + @SuppressWarnings("unchecked") + protected void configure() { for (Class api : TEST_CLAZZES) { for (Visibility visibility : Visibility.values()) { try { @@ -440,72 +493,77 @@ } } -/*if[AOP]*/ + /*if[AOP]*/ // applies method-interception to classes with enough visibility - static class InterceptorModule - extends AbstractModule { - @Override protected void configure() { - bindInterceptor(new AbstractMatcher>() { - public boolean matches(Class clazz) { - try { - - // the class and constructor must be visible - int clazzModifiers = clazz.getModifiers(); - int ctorModifiers = clazz.getConstructor().getModifiers(); - return (clazzModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 - && (ctorModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0; - - } catch (NoSuchMethodException e) { - return false; - } - } - }, new AbstractMatcher() { - public boolean matches(Method method) { - - // the intercepted method must also be visible - int methodModifiers = method.getModifiers(); - return (methodModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0; - - } - }, new org.aopalliance.intercept.MethodInterceptor() { - public Object invoke(org.aopalliance.intercept.MethodInvocation mi) - throws Throwable { - - return mi.proceed(); - } - }); + static class InterceptorModule extends AbstractModule { + @Override + protected void configure() { + bindInterceptor( + new AbstractMatcher>() { + @Override + public boolean matches(Class clazz) { + try { + + // the class and constructor must be visible + int clazzModifiers = clazz.getModifiers(); + int ctorModifiers = clazz.getConstructor().getModifiers(); + return (clazzModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 + && (ctorModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0; + + } catch (NoSuchMethodException e) { + return false; + } + } + }, + new AbstractMatcher() { + @Override + public boolean matches(Method method) { + + // the intercepted method must also be visible + int methodModifiers = method.getModifiers(); + return (methodModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0; + } + }, + new org.aopalliance.intercept.MethodInterceptor() { + @Override + public Object invoke(org.aopalliance.intercept.MethodInvocation mi) throws Throwable { + + return mi.proceed(); + } + }); } } -/*end[AOP]*/ + /*end[AOP]*/ // called from OSGi when bundle starts - public void start(BundleContext context) - throws BundleException { + @Override + public void start(BundleContext context) throws BundleException { final Bundle bundle = context.getBundle(); Injector injector = Guice.createInjector(new TestModule(bundle)); -/*if[AOP]*/ + /*if[AOP]*/ Injector aopInjector = Guice.createInjector(new TestModule(bundle), new InterceptorModule()); -/*end[AOP]*/ + /*end[AOP]*/ // test code-generation support for (Class api : TEST_CLAZZES) { for (Visibility vis : Visibility.values()) { injector.getInstance(Key.get(api, named(vis.name()))); -/*if[AOP]*/ + /*if[AOP]*/ aopInjector.getInstance(Key.get(api, named(vis.name()))); -/*end[AOP]*/ + /*end[AOP]*/ } } // test injection of system class (issue 343) injector.getInstance(Random.class); -/*if[AOP]*/ + /*if[AOP]*/ aopInjector.getInstance(Random.class); -/*end[AOP]*/ + /*end[AOP]*/ } // called from OSGi when bundle stops + @Override public void stop(BundleContext context) {} } diff -Nru sisu-guice-3.2.6/core/test/com/googlecode/guice/BytecodeGenTest.java sisu-guice-4.2.0/core/test/com/googlecode/guice/BytecodeGenTest.java --- sisu-guice-3.2.6/core/test/com/googlecode/guice/BytecodeGenTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/googlecode/guice/BytecodeGenTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,33 +16,27 @@ package com.googlecode.guice; +import static com.google.inject.Asserts.getClassPathUrls; import static com.google.inject.matcher.Matchers.any; +import com.google.common.testing.GcFinalization; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.googlecode.guice.PackageVisibilityTestModule.PublicUserOfPackagePrivate; - -import junit.framework.TestCase; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import java.io.File; -import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; import java.net.URLClassLoader; -import java.util.concurrent.TimeoutException; +import javax.inject.Inject; +import junit.framework.TestCase; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; /** - * This test is in a separate package so we can test package-level visibility - * with confidence. + * This test is in a separate package so we can test package-level visibility with confidence. * * @author mcculls@gmail.com (Stuart McCulloch) */ @@ -50,27 +44,37 @@ private final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); - private final Module interceptorModule = new AbstractModule() { - protected void configure() { - bindInterceptor(any(), any(), new MethodInterceptor() { - public Object invoke(MethodInvocation chain) - throws Throwable { - return chain.proceed() + " WORLD"; + private final Module interceptorModule = + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + any(), + any(), + new MethodInterceptor() { + @Override + public Object invoke(MethodInvocation chain) throws Throwable { + return chain.proceed() + " WORLD"; + } + }); } - }); - } - }; + }; - private final Module noopInterceptorModule = new AbstractModule() { - protected void configure() { - bindInterceptor(any(), any(), new MethodInterceptor() { - public Object invoke(MethodInvocation chain) - throws Throwable { - return chain.proceed(); - } - }); - } - }; + private final Module noopInterceptorModule = + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + any(), + any(), + new MethodInterceptor() { + @Override + public Object invoke(MethodInvocation chain) throws Throwable { + return chain.proceed(); + } + }); + } + }; public void testPackageVisibility() { Injector injector = Guice.createInjector(new PackageVisibilityTestModule()); @@ -85,45 +89,32 @@ public void testEnhancerNaming() { Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule()); PublicUserOfPackagePrivate pupp = injector.getInstance(PublicUserOfPackagePrivate.class); - assertTrue(pupp.getClass().getName().startsWith( - PublicUserOfPackagePrivate.class.getName() + "$$EnhancerByGuice$$")); + assertTrue( + pupp.getClass() + .getName() + .startsWith(PublicUserOfPackagePrivate.class.getName() + "$$EnhancerByGuice$$")); } // TODO(sameb): Figure out how to test FastClass naming tests. - /** - * Custom URL classloader with basic visibility rules - */ - static class TestVisibilityClassLoader - extends URLClassLoader { + /** Custom URL classloader with basic visibility rules */ + static class TestVisibilityClassLoader extends URLClassLoader { - boolean hideInternals; + final boolean hideInternals; - public TestVisibilityClassLoader(boolean hideInternals) { - super(new URL[0]); + TestVisibilityClassLoader(boolean hideInternals) { + this(TestVisibilityClassLoader.class.getClassLoader(), hideInternals); + } + TestVisibilityClassLoader(ClassLoader classloader, boolean hideInternals) { + super(getClassPathUrls(), classloader); this.hideInternals = hideInternals; - - final String[] classpath = System.getProperty("java.class.path").split(File.pathSeparator); - for (final String element : classpath) { - try { - // is it a remote/local URL? - addURL(new URL(element)); - } catch (final MalformedURLException e1) { - try { - // nope - perhaps it's a filename? - addURL(new File(element).toURI().toURL()); - } catch (final MalformedURLException e2) { - throw new RuntimeException(e1); - } - } - } } /** - * Classic parent-delegating classloaders are meant to override findClass. - * However, non-delegating classloaders (as used in OSGi) instead override - * loadClass to provide support for "class-space" separation. + * Classic parent-delegating classloaders are meant to override findClass. However, + * non-delegating classloaders (as used in OSGi) instead override loadClass to provide support + * for "class-space" separation. */ @Override protected Class loadClass(final String name, final boolean resolve) @@ -167,9 +158,11 @@ /** as loaded by another class loader */ private Class proxyTestClass; + private Class realClass; private Module testModule; + @Override @SuppressWarnings("unchecked") protected void setUp() throws Exception { super.setUp(); @@ -178,11 +171,13 @@ proxyTestClass = (Class) testClassLoader.loadClass(ProxyTest.class.getName()); realClass = (Class) testClassLoader.loadClass(ProxyTestImpl.class.getName()); - testModule = new AbstractModule() { - public void configure() { - bind(proxyTestClass).to(realClass); - } - }; + testModule = + new AbstractModule() { + @Override + public void configure() { + bind(proxyTestClass).to(realClass); + } + }; } interface ProxyTest { @@ -190,10 +185,10 @@ } /** - * Note: this class must be marked as public or protected so that the Guice - * custom classloader will intercept it. Private and implementation classes - * are not intercepted by the custom classloader. - * + * Note: this class must be marked as public or protected so that the Guice custom classloader + * will intercept it. Private and implementation classes are not intercepted by the custom + * classloader. + * * @see com.google.inject.internal.BytecodeGen.Visibility */ public static class ProxyTestImpl implements ProxyTest { @@ -202,14 +197,15 @@ //System.out.println(ProxyTestImpl.class.getClassLoader()); } + @Override public String sayHello() { return "HELLO"; } } public void testProxyClassLoading() throws Exception { - Object testObject = Guice.createInjector(interceptorModule, testModule) - .getInstance(proxyTestClass); + Object testObject = + Guice.createInjector(interceptorModule, testModule).getInstance(proxyTestClass); // verify method interception still works Method m = realClass.getMethod("sayHello"); @@ -217,11 +213,16 @@ } public void testSystemClassLoaderIsUsedIfProxiedClassUsesIt() { - ProxyTest testProxy = Guice.createInjector(interceptorModule, new Module() { - public void configure(Binder binder) { - binder.bind(ProxyTest.class).to(ProxyTestImpl.class); - } - }).getInstance(ProxyTest.class); + ProxyTest testProxy = + Guice.createInjector( + interceptorModule, + new Module() { + @Override + public void configure(Binder binder) { + binder.bind(ProxyTest.class).to(ProxyTestImpl.class); + } + }) + .getInstance(ProxyTest.class); if (ProxyTest.class.getClassLoader() == systemClassLoader) { assertSame(testProxy.getClass().getClassLoader(), systemClassLoader); @@ -231,13 +232,13 @@ } public void testProxyClassUnloading() { - Object testObject = Guice.createInjector(interceptorModule, testModule) - .getInstance(proxyTestClass); + Object testObject = + Guice.createInjector(interceptorModule, testModule).getInstance(proxyTestClass); assertNotNull(testObject.getClass().getClassLoader()); assertNotSame(testObject.getClass().getClassLoader(), systemClassLoader); // take a weak reference to the generated proxy class - Reference> clazzRef = new WeakReference>(testObject.getClass()); + WeakReference> clazzRef = new WeakReference>(testObject.getClass()); assertNotNull(clazzRef.get()); @@ -248,17 +249,7 @@ * this should be enough to queue the weak reference * unless something is holding onto it accidentally. */ - final int MAX_COUNT = 100; - String[] buf; - System.gc(); - //TODO(cgruber): Use com.google.common.testing.GcFinalization and a countdown latch to un-flake. - for (int count = 0 ; clazzRef.get() != null ; count++) { - buf = new String[8 * 1024 * 1024]; - buf = null; - System.gc(); - assertTrue("Timeout waiting for class to be unloaded. This may be a flaky result.", - count <= MAX_COUNT); - } + GcFinalization.awaitClear(clazzRef); // This test could be somewhat flaky when the GC isn't working. // If it fails, run the test again to make sure it's failing reliably. @@ -290,8 +281,7 @@ } } - static class Hidden { - } + static class Hidden {} public static class HiddenMethodReturn { public Hidden method() { @@ -300,15 +290,15 @@ } public static class HiddenMethodParameter { - public void method(Hidden h) { - } + public void method(Hidden h) {} } public void testClassLoaderBridging() throws Exception { ClassLoader testClassLoader = new TestVisibilityClassLoader(false); Class hiddenMethodReturnClass = testClassLoader.loadClass(HiddenMethodReturn.class.getName()); - Class hiddenMethodParameterClass = testClassLoader.loadClass(HiddenMethodParameter.class.getName()); + Class hiddenMethodParameterClass = + testClassLoader.loadClass(HiddenMethodParameter.class.getName()); Injector injector = Guice.createInjector(noopInterceptorModule); @@ -325,4 +315,140 @@ Object o2 = injector.getInstance(hiddenMethodReturnClass); o2.getClass().getDeclaredMethod("method").invoke(o2); } + + // This tests for a situation where a osgi bundle contains a version of guice. When guice + // generates a fast class it will use a bridge classloader + public void testFastClassUsesBridgeClassloader() throws Throwable { + Injector injector = Guice.createInjector(); + // These classes are all in the same classloader as guice itself, so other than the private one + // they can all be fast class invoked + injector.getInstance(PublicInject.class).assertIsFastClassInvoked(); + injector.getInstance(ProtectedInject.class).assertIsFastClassInvoked(); + injector.getInstance(PackagePrivateInject.class).assertIsFastClassInvoked(); + injector.getInstance(PrivateInject.class).assertIsReflectionInvoked(); + + // This classloader will load the types in an loader with a different version of guice/cglib + // this prevents the use of fastclass for all but the public types (where the bridge + // classloader can be used). + MultipleVersionsOfGuiceClassLoader fakeLoader = new MultipleVersionsOfGuiceClassLoader(); + injector + .getInstance(fakeLoader.loadLogCreatorType(PublicInject.class)) + .assertIsFastClassInvoked(); + injector + .getInstance(fakeLoader.loadLogCreatorType(ProtectedInject.class)) + .assertIsReflectionInvoked(); + injector + .getInstance(fakeLoader.loadLogCreatorType(PackagePrivateInject.class)) + .assertIsReflectionInvoked(); + injector + .getInstance(fakeLoader.loadLogCreatorType(PrivateInject.class)) + .assertIsReflectionInvoked(); + } + + // This classloader simulates an OSGI environment where a bundle has a conflicting definition of + // cglib (or guice). This is sort of the opposite of the BridgeClassloader and is meant to test + // its use. + static class MultipleVersionsOfGuiceClassLoader extends URLClassLoader { + MultipleVersionsOfGuiceClassLoader() { + this(MultipleVersionsOfGuiceClassLoader.class.getClassLoader()); + } + + MultipleVersionsOfGuiceClassLoader(ClassLoader classloader) { + super(getClassPathUrls(), classloader); + } + + public Class loadLogCreatorType(Class cls) + throws ClassNotFoundException { + return loadClass(cls.getName()).asSubclass(LogCreator.class); + } + + /** + * Classic parent-delegating classloaders are meant to override findClass. However, + * non-delegating classloaders (as used in OSGi) instead override loadClass to provide support + * for "class-space" separation. + */ + @Override + protected Class loadClass(final String name, final boolean resolve) + throws ClassNotFoundException { + + synchronized (this) { + // check our local cache to avoid duplicates + final Class clazz = findLoadedClass(name); + if (clazz != null) { + return clazz; + } + } + + if (name.startsWith("java.") + || name.startsWith("javax.") + || name.equals(LogCreator.class.getName()) + || (!name.startsWith("com.google.inject.") + && !name.contains(".cglib.") + && !name.startsWith("com.googlecode.guice"))) { + + // standard parent delegation + return super.loadClass(name, resolve); + + } else { + // load a new copy of the class + final Class clazz = findClass(name); + if (resolve) { + resolveClass(clazz); + } + return clazz; + } + } + } + + public static class LogCreator { + final Throwable caller; + + public LogCreator() { + this.caller = new Throwable(); + } + + void assertIsFastClassInvoked() throws Throwable { + // 2 because the first 2 elements are + // LogCreator.() + // Subclass.() + if (!caller.getStackTrace()[2].getClassName().contains("$$FastClassByGuice$$")) { + throw new AssertionError("Caller was not FastClass").initCause(caller); + } + } + + void assertIsReflectionInvoked() throws Throwable { + // Scan for a call to Constructor.newInstance, but stop if we see the test itself. + for (StackTraceElement element : caller.getStackTrace()) { + if (element.getClassName().equals(BytecodeGenTest.class.getName())) { + // break when we hit the test method. + break; + } + if (element.getClassName().equals(Constructor.class.getName()) + && element.getMethodName().equals("newInstance")) { + return; + } + } + throw new AssertionError("Caller was not Constructor.newInstance").initCause(caller); + } + } + + public static class PublicInject extends LogCreator { + @Inject + public PublicInject() {} + } + + static class PackagePrivateInject extends LogCreator { + @Inject + PackagePrivateInject() {} + } + + protected static class ProtectedInject extends LogCreator { + @Inject + protected ProtectedInject() {} + } + + private static class PrivateInject extends LogCreator { + @Inject + private PrivateInject() {} + } } diff -Nru sisu-guice-3.2.6/core/test/com/googlecode/guice/GuiceTck.java sisu-guice-4.2.0/core/test/com/googlecode/guice/GuiceTck.java --- sisu-guice-3.2.6/core/test/com/googlecode/guice/GuiceTck.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/googlecode/guice/GuiceTck.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,10 +19,9 @@ import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Provides; - +import javax.inject.Named; import junit.framework.Test; import junit.framework.TestCase; - import org.atinject.tck.Tck; import org.atinject.tck.auto.Car; import org.atinject.tck.auto.Convertible; @@ -36,25 +35,31 @@ import org.atinject.tck.auto.accessories.Cupholder; import org.atinject.tck.auto.accessories.SpareTire; -import javax.inject.Named; - public class GuiceTck extends TestCase { public static Test suite() { - return Tck.testsFor(Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(Car.class).to(Convertible.class); - bind(Seat.class).annotatedWith(Drivers.class).to(DriversSeat.class); - bind(Engine.class).to(V8Engine.class); - bind(Cupholder.class); - bind(Tire.class); - bind(FuelTank.class); - requestStaticInjection(Convertible.class, SpareTire.class); - } - - @Provides @Named("spare") Tire provideSpareTire(SpareTire spare) { - return spare; - } - }).getInstance(Car.class), true, true); + return Tck.testsFor( + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(Car.class).to(Convertible.class); + bind(Seat.class).annotatedWith(Drivers.class).to(DriversSeat.class); + bind(Engine.class).to(V8Engine.class); + bind(Cupholder.class); + bind(Tire.class); + bind(FuelTank.class); + requestStaticInjection(Convertible.class, SpareTire.class); + } + + @Provides + @Named("spare") + Tire provideSpareTire(SpareTire spare) { + return spare; + } + }) + .getInstance(Car.class), + true, + true); } } diff -Nru sisu-guice-3.2.6/core/test/com/googlecode/guice/Jsr330Test.java sisu-guice-4.2.0/core/test/com/googlecode/guice/Jsr330Test.java --- sisu-guice-3.2.6/core/test/com/googlecode/guice/Jsr330Test.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/googlecode/guice/Jsr330Test.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,18 +33,15 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.util.Set; - import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import junit.framework.TestCase; public class Jsr330Test extends TestCase { @@ -53,21 +50,25 @@ private final D d = new D(); private final E e = new E(); - @Override protected void setUp() throws Exception { + @Override + protected void setUp() throws Exception { J.nextInstanceId = 0; K.nextInstanceId = 0; } public void testInject() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).toInstance(b); - bind(C.class).toInstance(c); - bind(D.class).toInstance(d); - bind(E.class).toInstance(e); - bind(A.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).toInstance(b); + bind(C.class).toInstance(c); + bind(D.class).toInstance(d); + bind(E.class).toInstance(e); + bind(A.class); + } + }); A a = injector.getInstance(A.class); assertSame(b, a.b); @@ -77,15 +78,18 @@ } public void testQualifiedInject() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b); - bind(C.class).annotatedWith(Red.class).toInstance(c); - bind(D.class).annotatedWith(RED).toInstance(d); - bind(E.class).annotatedWith(Names.named("jesse")).toInstance(e); - bind(F.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b); + bind(C.class).annotatedWith(Red.class).toInstance(c); + bind(D.class).annotatedWith(RED).toInstance(d); + bind(E.class).annotatedWith(Names.named("jesse")).toInstance(e); + bind(F.class); + } + }); F f = injector.getInstance(F.class); assertSame(b, f.b); @@ -95,15 +99,18 @@ } public void testProviderInject() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b); - bind(C.class).toInstance(c); - bind(D.class).annotatedWith(RED).toInstance(d); - bind(E.class).toInstance(e); - bind(G.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b); + bind(C.class).toInstance(c); + bind(D.class).annotatedWith(RED).toInstance(d); + bind(E.class).toInstance(e); + bind(G.class); + } + }); G g = injector.getInstance(G.class); assertSame(b, g.bProvider.get()); @@ -115,13 +122,16 @@ public void testScopeAnnotation() { final TestScope scope = new TestScope(); - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).in(scope); - bind(C.class).in(TestScoped.class); - bindScope(TestScoped.class, scope); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).in(scope); + bind(C.class).in(TestScoped.class); + bindScope(TestScoped.class, scope); + } + }); B b = injector.getInstance(B.class); assertSame(b, injector.getInstance(B.class)); @@ -141,13 +151,16 @@ assertNotSame(c, injector.getInstance(C.class)); assertNotSame(h, injector.getInstance(H.class)); } - + public void testSingleton() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).in(Singleton.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).in(Singleton.class); + } + }); B b = injector.getInstance(B.class); assertSame(b, injector.getInstance(B.class)); @@ -159,24 +172,30 @@ } public void testEagerSingleton() { - Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { - protected void configure() { - bind(J.class); - bind(K.class).in(Singleton.class); - } - }); + Guice.createInjector( + Stage.PRODUCTION, + new AbstractModule() { + @Override + protected void configure() { + bind(J.class); + bind(K.class).in(Singleton.class); + } + }); assertEquals(1, J.nextInstanceId); assertEquals(1, K.nextInstanceId); } - + public void testScopesIsSingleton() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(J.class); - bind(K.class).in(Singleton.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(J.class); + bind(K.class).in(Singleton.class); + } + }); assertTrue(Scopes.isSingleton(injector.getBinding(J.class))); assertTrue(Scopes.isSingleton(injector.getBinding(K.class))); @@ -184,70 +203,86 @@ public void testInjectingFinalFieldsIsForbidden() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(L.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(L.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), - "1) Injected field " + L.class.getName() + ".b cannot be final."); + assertContains( + expected.getMessage(), "1) Injected field " + L.class.getName() + ".b cannot be final."); } } public void testInjectingAbstractMethodsIsForbidden() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(M.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(M.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), + assertContains( + expected.getMessage(), "1) Injected method " + AbstractM.class.getName() + ".setB() cannot be abstract."); } } public void testInjectingMethodsWithTypeParametersIsForbidden() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(N.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(N.class); + } + }); fail(); } catch (CreationException expected) { - assertContains(expected.getMessage(), "1) Injected method " + N.class.getName() - + ".setB() cannot declare type parameters of its own."); + assertContains( + expected.getMessage(), + "1) Injected method " + + N.class.getName() + + ".setB() cannot declare type parameters of its own."); } } public void testInjectingMethodsWithNonVoidReturnTypes() { - Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(P.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(P.class); + } + }); } /** - * This test verifies that we can compile bindings to provider instances - * whose compile-time type implements javax.inject.Provider but not - * com.google.inject.Provider. For binary compatibility, we don't (and won't) - * support binding to instances of javax.inject.Provider. + * This test verifies that we can compile bindings to provider instances whose compile-time type + * implements javax.inject.Provider but not com.google.inject.Provider. For binary compatibility, + * we don't (and won't) support binding to instances of javax.inject.Provider. */ public void testBindProviderClass() { - Injector injector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(B.class).toProvider(BProvider.class); - bind(B.class).annotatedWith(Names.named("1")).toProvider(BProvider.class); - bind(B.class).annotatedWith(Names.named("2")).toProvider(Key.get(BProvider.class)); - bind(B.class).annotatedWith(Names.named("3")).toProvider(TypeLiteral.get(BProvider.class)); - } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(B.class).toProvider(BProvider.class); + bind(B.class).annotatedWith(Names.named("1")).toProvider(BProvider.class); + bind(B.class).annotatedWith(Names.named("2")).toProvider(Key.get(BProvider.class)); + bind(B.class) + .annotatedWith(Names.named("3")) + .toProvider(TypeLiteral.get(BProvider.class)); + } + }); + injector.getInstance(Key.get(B.class)); injector.getInstance(Key.get(B.class, Names.named("1"))); injector.getInstance(Key.get(B.class, Names.named("2"))); @@ -255,15 +290,18 @@ } public void testGuicify330Provider() { - Provider jsr330Provider = new Provider() { - public String get() { - return "A"; - } + Provider jsr330Provider = + new Provider() { + @Override + public String get() { + return "A"; + } - @Override public String toString() { - return "jsr330Provider"; - } - }; + @Override + public String toString() { + return "jsr330Provider"; + } + }; com.google.inject.Provider guicified = Providers.guicify(jsr330Provider); assertEquals("guicified(jsr330Provider)", guicified.toString()); @@ -271,51 +309,56 @@ // when you guicify the Guice-friendly, it's a no-op assertSame(guicified, Providers.guicify(guicified)); - + assertFalse(guicified instanceof HasDependencies); } - + public void testGuicifyWithDependencies() { - Provider jsr330Provider = new Provider() { - @Inject double d; - int i; - @Inject void injectMe(int i) { - this.i = i; - } - - public String get() { - return d + "-" + i; - } - }; - - final com.google.inject.Provider guicified = - Providers.guicify(jsr330Provider); + Provider jsr330Provider = + new Provider() { + @Inject double d; + int i; + + @Inject + void injectMe(int i) { + this.i = i; + } + + @Override + public String get() { + return d + "-" + i; + } + }; + + final com.google.inject.Provider guicified = Providers.guicify(jsr330Provider); assertTrue(guicified instanceof HasDependencies); - Set> actual = ((HasDependencies)guicified).getDependencies(); + Set> actual = ((HasDependencies) guicified).getDependencies(); validateDependencies(actual, jsr330Provider.getClass()); - - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toProvider(guicified); - bind(int.class).toInstance(1); - bind(double.class).toInstance(2.0d); - } - }); - + + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toProvider(guicified); + bind(int.class).toInstance(1); + bind(double.class).toInstance(2.0d); + } + }); + Binding binding = injector.getBinding(String.class); assertEquals("2.0-1", binding.getProvider().get()); validateDependencies(actual, jsr330Provider.getClass()); } - + private void validateDependencies(Set> actual, Class owner) { assertEquals(actual.toString(), 2, actual.size()); Dependency dDep = null; Dependency iDep = null; - for(Dependency dep : actual) { - if(dep.getKey().equals(Key.get(Double.class))) { + for (Dependency dep : actual) { + if (dep.getKey().equals(Key.get(Double.class))) { dDep = dep; - } else if(dep.getKey().equals(Key.get(Integer.class))) { + } else if (dep.getKey().equals(Key.get(Integer.class))) { iDep = dep; } } @@ -324,7 +367,7 @@ assertEquals(TypeLiteral.get(owner), dDep.getInjectionPoint().getDeclaringType()); assertEquals("d", dDep.getInjectionPoint().getMember().getName()); assertEquals(-1, dDep.getParameterIndex()); - + assertEquals(TypeLiteral.get(owner), iDep.getInjectionPoint().getDeclaringType()); assertEquals("injectMe", iDep.getInjectionPoint().getMember().getName()); assertEquals(0, iDep.getParameterIndex()); @@ -336,19 +379,24 @@ D d; E e; - @Inject A(B b) { + @Inject + A(B b) { this.b = b; } - @Inject void injectD(D d, E e) { + @Inject + void injectD(D d, E e) { this.d = d; this.e = e; } } static class B {} + static class C {} + static class D {} + static class E {} static class F { @@ -357,32 +405,39 @@ D d; E e; - @Inject F(@Named("jodie") B b) { + @Inject + F(@Named("jodie") B b) { this.b = b; } - @Inject void injectD(@Red D d, @Named("jesse") E e) { + @Inject + void injectD(@Red D d, @Named("jesse") E e) { this.d = d; this.e = e; } } - @Qualifier @Retention(RUNTIME) + @Qualifier + @Retention(RUNTIME) @interface Red {} - public static final Red RED = new Red() { - public Class annotationType() { - return Red.class; - } + public static final Red RED = + new Red() { + @Override + public Class annotationType() { + return Red.class; + } - @Override public boolean equals(Object obj) { - return obj instanceof Red; - } + @Override + public boolean equals(Object obj) { + return obj instanceof Red; + } - @Override public int hashCode() { - return 0; - } - }; + @Override + public int hashCode() { + return 0; + } + }; static class G { final Provider bProvider; @@ -390,28 +445,33 @@ Provider dProvider; Provider eProvider; - @Inject G(@Named("jodie") Provider bProvider) { + @Inject + G(@Named("jodie") Provider bProvider) { this.bProvider = bProvider; } - @Inject void injectD(@Red Provider dProvider, Provider eProvider) { + @Inject + void injectD(@Red Provider dProvider, Provider eProvider) { this.dProvider = dProvider; this.eProvider = eProvider; } } - @javax.inject.Scope @Retention(RUNTIME) + @javax.inject.Scope + @Retention(RUNTIME) @interface TestScoped {} static class TestScope implements Scope { private int now = 0; - public com.google.inject.Provider scope(Key key, - final com.google.inject.Provider unscoped) { + @Override + public com.google.inject.Provider scope( + Key key, final com.google.inject.Provider unscoped) { return new com.google.inject.Provider() { private T value; private int snapshotTime = -1; + @Override public T get() { if (snapshotTime != now) { value = unscoped.get(); @@ -447,27 +507,32 @@ final B b = null; } - static abstract class AbstractM { - @SuppressWarnings("InjectJavaxInjectOnAbstractMethod") + abstract static class AbstractM { + @SuppressWarnings("JavaxInjectOnAbstractMethod") @Inject abstract void setB(B b); } static class M extends AbstractM { + @Override + @SuppressWarnings("OverridesJavaxInjectableMethod") void setB(B b) {} } static class N { - @Inject void setB(B b) {} + @Inject + void setB(B b) {} } static class P { - @Inject B setB(B b) { + @Inject + B setB(B b) { return b; } } static class BProvider implements Provider { + @Override public B get() { return new B(); } diff -Nru sisu-guice-3.2.6/core/test/com/googlecode/guice/OSGiContainerTest.java sisu-guice-4.2.0/core/test/com/googlecode/guice/OSGiContainerTest.java --- sisu-guice-3.2.6/core/test/com/googlecode/guice/OSGiContainerTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/googlecode/guice/OSGiContainerTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,34 +16,26 @@ package com.googlecode.guice; - import aQute.bnd.main.bnd; - import com.googlecode.guice.bundle.OSGiTestActivator; - -import junit.framework.TestCase; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.launch.Framework; -import org.osgi.framework.launch.FrameworkFactory; - import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.Iterator; import java.util.Properties; - -import javax.imageio.spi.ServiceRegistry; +import java.util.ServiceLoader; +import junit.framework.TestCase; +import org.osgi.framework.BundleContext; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; /** * Run various tests inside one or more OSGi containers. * * @author mcculls@gmail.com (Stuart McCulloch) */ -public class OSGiContainerTest - extends TestCase { +public class OSGiContainerTest extends TestCase { // build properties passed from Ant static final String VERSION = System.getProperty("version", "snapshot"); @@ -54,34 +46,36 @@ static final String GUICE_JAR = BUILD_DIST_DIR + "/guice-" + VERSION + ".jar"; -/*if[AOP]*/ - static final String AOPALLIANCE_JAR = System.getProperty("aopalliance.jar", "lib/aopalliance.jar"); -/*end[AOP]*/ - static final String JAVAX_INJECT_JAR = System.getProperty("javax.inject.jar", "lib/javax.inject.jar"); - static final String GUAVA_JAR = System.getProperty("guava.jar", "lib/guava-16.0.1.jar"); + /*if[AOP]*/ + static final String AOPALLIANCE_JAR = + System.getProperty("aopalliance.jar", "lib/aopalliance.jar"); + /*end[AOP]*/ + static final String JAVAX_INJECT_JAR = + System.getProperty("javax.inject.jar", "lib/javax.inject.jar"); + static final String GUAVA_JAR = System.getProperty("guava.jar", "lib/guava-19.0.jar"); // dynamically build test bundles - @Override protected void setUp() - throws Exception { + @Override + protected void setUp() throws Exception { // verify properties assertTrue(failMsg(), new File(BUILD_DIR).isDirectory()); assertTrue(failMsg(), new File(GUICE_JAR).isFile()); -/*if[AOP]*/ + /*if[AOP]*/ assertTrue(failMsg(), new File(AOPALLIANCE_JAR).isFile()); -/*end[AOP]*/ + /*end[AOP]*/ assertTrue(failMsg(), new File(JAVAX_INJECT_JAR).isFile()); assertTrue(failMsg(), new File(GUAVA_JAR).isFile()); Properties instructions = new Properties(); -/*if[AOP]*/ + /*if[AOP]*/ // aopalliance is an API bundle --> export the full API instructions.setProperty("Export-Package", "org.aopalliance.*"); buildBundle("aopalliance", instructions, AOPALLIANCE_JAR); instructions.clear(); -/*end[AOP]*/ + /*end[AOP]*/ // javax.inject is an API bundle --> export the full API instructions.setProperty("Export-Package", "javax.inject.*"); @@ -95,11 +89,13 @@ instructions.clear(); // strict imports to make sure test bundle only has access to these packages - instructions.setProperty("Import-Package", "org.osgi.framework," -/*if[AOP]*/ - + "org.aopalliance.intercept," -/*end[AOP]*/ - + "com.google.inject(|.binder|.matcher|.name)"); + instructions.setProperty( + "Import-Package", + "org.osgi.framework," + /*if[AOP]*/ + + "org.aopalliance.intercept," + /*end[AOP]*/ + + "com.google.inject(|.binder|.matcher|.name)"); // test bundle should only contain the local test classes, nothing else instructions.setProperty("Bundle-Activator", OSGiTestActivator.class.getName()); @@ -119,20 +115,19 @@ os.close(); // assemble bundle, use -failok switch to avoid early exit - bnd.main(new String[]{"-failok", "build", "-classpath", classpath, bndFileName}); + bnd.main(new String[] {"-failok", "build", "-classpath", classpath, bndFileName}); } private String failMsg() { return "This test may fail if it is not run from ant, or if it is not run after ant has " - + "compiled & built jars. This is because the test is validating that the Guice jar " - + "is properly setup to load in an OSGi container"; + + "compiled & built jars. This is because the test is validating that the Guice jar " + + "is properly setup to load in an OSGi container"; } //This test may fail if it is not run from ant, or if it is not run after ant has //compiled & built jars. This is because the test is validating that the Guice jar //is properly setup to load in an OSGi container - public void testGuiceWorksInOSGiContainer() - throws Throwable { + public void testGuiceWorksInOSGiContainer() throws Throwable { // ask framework to clear cache on startup Properties properties = new Properties(); @@ -140,17 +135,16 @@ properties.setProperty("org.osgi.framework.storage.clean", "onFirstInit"); // test each available OSGi framework in turn - Iterator f = ServiceRegistry.lookupProviders(FrameworkFactory.class); - while (f.hasNext()) { - Framework framework = f.next().newFramework(properties); + for (FrameworkFactory frameworkFactory : ServiceLoader.load(FrameworkFactory.class)) { + Framework framework = frameworkFactory.newFramework(properties); framework.start(); BundleContext systemContext = framework.getBundleContext(); // load all the necessary bundles and start the OSGi test bundle -/*if[AOP]*/ + /*if[AOP]*/ systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/aopalliance.jar"); -/*end[AOP]*/ + /*end[AOP]*/ systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/javax.inject.jar"); systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/guava.jar"); systemContext.installBundle("reference:file:" + GUICE_JAR); diff -Nru sisu-guice-3.2.6/core/test/com/googlecode/guice/PackageVisibilityTestModule.java sisu-guice-4.2.0/core/test/com/googlecode/guice/PackageVisibilityTestModule.java --- sisu-guice-3.2.6/core/test/com/googlecode/guice/PackageVisibilityTestModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/core/test/com/googlecode/guice/PackageVisibilityTestModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -11,8 +11,11 @@ } public static class PublicUserOfPackagePrivate { - @Inject public PublicUserOfPackagePrivate(PackagePrivateInterface ppi) {} - @Inject public void acceptPackagePrivateParameter(PackagePrivateInterface ppi) {} + @Inject + public PublicUserOfPackagePrivate(PackagePrivateInterface ppi) {} + + @Inject + public void acceptPackagePrivateParameter(PackagePrivateInterface ppi) {} } interface PackagePrivateInterface {} diff -Nru sisu-guice-3.2.6/debian/changelog sisu-guice-4.2.0/debian/changelog --- sisu-guice-3.2.6/debian/changelog 2017-11-21 08:34:57.000000000 +0000 +++ sisu-guice-4.2.0/debian/changelog 2018-04-18 14:07:34.000000000 +0000 @@ -1,3 +1,14 @@ +sisu-guice (4.2.0-1) unstable; urgency=medium + + * New upstream release + * Ignore testlib extension + * Remove obsolete maven2 patch + * Update uploaders (Closes: #889392) + * Standards-Version updated to 4.1.4 (get-orig-source rules target removed) + * Switch to debhelper level 11 + + -- Eugene Zhukov Wed, 18 Apr 2018 14:07:34 +0000 + sisu-guice (3.2.6-4) unstable; urgency=medium * Removed the unused dependency on glassfish-javaee diff -Nru sisu-guice-3.2.6/debian/control sisu-guice-4.2.0/debian/control --- sisu-guice-3.2.6/debian/control 2017-11-21 08:25:50.000000000 +0000 +++ sisu-guice-4.2.0/debian/control 2018-04-18 14:07:34.000000000 +0000 @@ -2,11 +2,9 @@ Section: java Priority: optional Maintainer: Debian Java Maintainers -Uploaders: - Damien Raude-Morvan , - Eugene Zhukov +Uploaders: Eugene Zhukov Build-Depends: - debhelper (>= 10), + debhelper (>= 11), default-jdk, junit4, libaopalliance-java, @@ -21,7 +19,7 @@ libmunge-maven-plugin-java, libservlet3.1-java, maven-debian-helper (>= 1.4) -Standards-Version: 4.1.1 +Standards-Version: 4.1.4 Vcs-Git: https://anonscm.debian.org/git/pkg-java/sisu-guice.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/sisu-guice.git Homepage: https://github.com/sonatype/sisu-guice diff -Nru sisu-guice-3.2.6/debian/libsisu-guice-java.poms sisu-guice-4.2.0/debian/libsisu-guice-java.poms --- sisu-guice-3.2.6/debian/libsisu-guice-java.poms 2016-10-04 12:28:41.000000000 +0000 +++ sisu-guice-4.2.0/debian/libsisu-guice-java.poms 2018-04-18 14:07:34.000000000 +0000 @@ -38,5 +38,6 @@ extensions/spring/pom.xml --ignore extensions/struts2/pom.xml --ignore extensions/throwingproviders/pom.xml --ignore +extensions/testlib/pom.xml --ignore extensions/dagger-adapter/pom.xml --ignore jdk8-tests/pom.xml --ignore diff -Nru sisu-guice-3.2.6/debian/maven.ignoreRules sisu-guice-4.2.0/debian/maven.ignoreRules --- sisu-guice-3.2.6/debian/maven.ignoreRules 2016-10-04 12:28:41.000000000 +0000 +++ sisu-guice-4.2.0/debian/maven.ignoreRules 2018-04-18 14:07:34.000000000 +0000 @@ -2,6 +2,7 @@ org.sonatype.sisu sisu-guice jar * tests test biz.aQute bnd * * * * com.google.guava guava-testlib * * * * +com.google.truth truth * * * * javax.inject javax.inject-tck * * * * org.apache.felix org.apache.felix.framework * * * * org.apache.maven.plugins maven-remote-resources-plugin * * * * diff -Nru sisu-guice-3.2.6/debian/patches/allow_maven2.diff sisu-guice-4.2.0/debian/patches/allow_maven2.diff --- sisu-guice-3.2.6/debian/patches/allow_maven2.diff 2015-11-19 22:51:28.000000000 +0000 +++ sisu-guice-4.2.0/debian/patches/allow_maven2.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -Description: Allow building with maven 2 - ---- sisu-guice-3.2.5.orig/pom.xml -+++ sisu-guice-3.2.5/pom.xml -@@ -92,9 +92,9 @@ See the Apache License Version 2.0 for t - - - -- -+ - - - + + + maven-jar-plugin + + + + com.google.guice.extensions.jmx + + + + diff -Nru sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java --- sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,14 +26,17 @@ this.binding = binding; } + @Override public String getSource() { return binding.getSource().toString(); } + @Override public String getKey() { return binding.getKey().toString(); } + @Override public String getProvider() { return binding.getProvider().toString(); } diff -Nru sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java --- sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,18 +23,12 @@ */ public interface ManagedBindingMBean { - /** - * Gets the source of this binding. - */ + /** Gets the source of this binding. */ String getSource(); - /** - * Gets the provider to which this binding is bound. - */ + /** Gets the provider to which this binding is bound. */ String getProvider(); - /** - * Gets the binding key. - */ + /** Gets the binding key. */ String getKey(); } diff -Nru sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java --- sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,10 +21,8 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; - import java.lang.annotation.Annotation; import java.lang.management.ManagementFactory; - import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; @@ -37,21 +35,18 @@ public class Manager { /** - * Registers all the bindings of an Injector with the platform MBean server. - * Consider using the name of your root {@link Module} class as the domain. + * Registers all the bindings of an Injector with the platform MBean server. Consider using the + * name of your root {@link Module} class as the domain. */ - public static void manage( - String domain, - Injector injector) { + public static void manage(String domain, Injector injector) { manage(ManagementFactory.getPlatformMBeanServer(), domain, injector); } /** - * Registers all the bindings of an Injector with the given MBean server. - * Consider using the name of your root {@link Module} class as the domain. + * Registers all the bindings of an Injector with the given MBean server. Consider using the name + * of your root {@link Module} class as the domain. */ - public static void manage(MBeanServer server, String domain, - Injector injector) { + public static void manage(MBeanServer server, String domain, Injector injector) { // Register each binding independently. for (Binding binding : injector.getBindings().values()) { // Construct the name manually so we can ensure proper ordering of the @@ -63,23 +58,18 @@ Annotation annotation = key.getAnnotation(); if (annotation != null) { name.append(",annotation=").append(quote(annotation.toString())); - } - else { + } else { Class annotationType = key.getAnnotationType(); if (annotationType != null) { - name.append(",annotation=") - .append(quote("@" + annotationType.getName())); + name.append(",annotation=").append(quote("@" + annotationType.getName())); } } try { - server.registerMBean(new ManagedBinding(binding), - new ObjectName(name.toString())); - } - catch (MalformedObjectNameException e) { + server.registerMBean(new ManagedBinding(binding), new ObjectName(name.toString())); + } catch (MalformedObjectNameException e) { throw new RuntimeException("Bad object name: " + name, e); - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException(e); } } @@ -90,13 +80,13 @@ return ObjectName.quote(value).replace(',', ';'); } - /** - * Run with no arguments for usage instructions. - */ + /** Run with no arguments for usage instructions. */ public static void main(String[] args) throws Exception { if (args.length != 1) { - System.err.println("Usage: java -Dcom.sun.management.jmxremote " - + Manager.class.getName() + " [module class name]"); + System.err.println( + "Usage: java -Dcom.sun.management.jmxremote " + + Manager.class.getName() + + " [module class name]"); System.err.println("Then run 'jconsole' to connect."); System.exit(1); } diff -Nru sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java --- sisu-guice-3.2.6/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,7 +14,5 @@ * limitations under the License. */ -/** - * JMX integration; this extension requires {@code guice-jmx-3.0.jar}. - */ -package com.google.inject.tools.jmx; \ No newline at end of file +/** JMX integration; this extension requires {@code guice-jmx.jar}. */ +package com.google.inject.tools.jmx; diff -Nru sisu-guice-3.2.6/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java sisu-guice-4.2.0/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java --- sisu-guice-3.2.6/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,12 +23,9 @@ import com.google.inject.Key; import com.google.inject.Singleton; import com.google.inject.name.Names; - import java.lang.annotation.Retention; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class JmxTest { interface Foo {} @@ -40,24 +37,24 @@ static class Bar {} - @BindingAnnotation @Retention(RUNTIME) + @BindingAnnotation + @Retention(RUNTIME) @interface Transactional {} public static void main(String[] args) throws Exception { - Manager.main(new String[] { TestModule.class.getName() }); + Manager.main(new String[] {TestModule.class.getName()}); } - + public static class TestModule extends AbstractModule { + @Override protected void configure() { bind(Foo.class).to(FooImpl.class); bind(Bar.class); - bind(Foo.class) - .annotatedWith(Transactional.class) - .to(FooImpl.class); + bind(Foo.class).annotatedWith(Transactional.class).to(FooImpl.class); bindConstant().annotatedWith(Names.named("port")).to(8080); bind(Key.get(Object.class)).to(Key.get(Bar.class)); -// install(new ServletModule()); + // install(new ServletModule()); } } } diff -Nru sisu-guice-3.2.6/extensions/jndi/pom.xml sisu-guice-4.2.0/extensions/jndi/pom.xml --- sisu-guice-3.2.6/extensions/jndi/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jndi/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,11 +6,25 @@ org.sonatype.sisu.inject extensions-parent - 3.2.6 + 4.2.0 guice-jndi Sisu Guice - Extensions - JNDI + + + + maven-jar-plugin + + + + com.google.guice.extensions.jndi + + + + + + diff -Nru sisu-guice-3.2.6/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java sisu-guice-4.2.0/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java --- sisu-guice-3.2.6/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,13 +18,11 @@ import com.google.inject.Inject; import com.google.inject.Provider; - import javax.naming.Context; import javax.naming.NamingException; /** - * Integrates Guice with JNDI. Requires a binding to - * {@link javax.naming.Context}. + * Integrates Guice with JNDI. Requires a binding to {@link javax.naming.Context}. * * @author crazybob@google.com (Bob Lee) */ @@ -33,8 +31,7 @@ private JndiIntegration() {} /** - * Creates a provider which looks up objects in JNDI using the given name. - * Example usage: + * Creates a provider which looks up objects in JNDI using the given name. Example usage: * *
        * bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
    @@ -55,11 +52,11 @@
           this.name = name;
         }
     
    +    @Override
         public T get() {
           try {
             return type.cast(context.lookup(name));
    -      }
    -      catch (NamingException e) {
    +      } catch (NamingException e) {
             throw new RuntimeException(e);
           }
         }
    diff -Nru sisu-guice-3.2.6/extensions/jndi/src/com/google/inject/jndi/package-info.java sisu-guice-4.2.0/extensions/jndi/src/com/google/inject/jndi/package-info.java
    --- sisu-guice-3.2.6/extensions/jndi/src/com/google/inject/jndi/package-info.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/jndi/src/com/google/inject/jndi/package-info.java	2018-04-03 18:18:08.000000000 +0000
    @@ -14,7 +14,5 @@
      * limitations under the License.
      */
     
    -/**
    - * JNDI integration; this extension requires {@code guice-jndi-3.0.jar}.
    - */
    -package com.google.inject.jndi;
    \ No newline at end of file
    +/** JNDI integration; this extension requires {@code guice-jndi.jar}. */
    +package com.google.inject.jndi;
    diff -Nru sisu-guice-3.2.6/extensions/mini/pom.xml sisu-guice-4.2.0/extensions/mini/pom.xml
    --- sisu-guice-3.2.6/extensions/mini/pom.xml	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/mini/pom.xml	2018-04-03 18:18:08.000000000 +0000
    @@ -6,11 +6,25 @@
       
         org.sonatype.sisu.inject
         extensions-parent
    -    4.0-SNAPSHOT
    +    4.1.1-SNAPSHOT
       
     
       guice-mini
     
       Sisu Guice - Extensions - Mini
     
    +  
    +    
    +      
    +        maven-jar-plugin
    +        
    +          
    +            
    +              com.google.guice.extensions.mini
    +            
    +          
    +        
    +      
    +    
    +  
     
    diff -Nru sisu-guice-3.2.6/extensions/mini/src/com/google/inject/mini/MiniGuice.java sisu-guice-4.2.0/extensions/mini/src/com/google/inject/mini/MiniGuice.java
    --- sisu-guice-3.2.6/extensions/mini/src/com/google/inject/mini/MiniGuice.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/mini/src/com/google/inject/mini/MiniGuice.java	2018-04-03 18:18:08.000000000 +0000
    @@ -32,7 +32,6 @@
     import java.util.Map;
     import java.util.Queue;
     import java.util.Set;
    -
     import javax.inject.Provider;
     
     /**
    @@ -43,34 +42,33 @@
      */
     public final class MiniGuice {
       private static final Object UNINITIALIZED = new Object();
    +
       private MiniGuice() {}
     
    -  private final Map> bindings = new HashMap>();
    -  private final Queue requiredKeys = new ArrayDeque();
    -  private final Set singletons = new HashSet();
    +  private final Map> bindings = new HashMap<>();
    +  private final Queue requiredKeys = new ArrayDeque<>();
    +  private final Set singletons = new HashSet<>();
     
       /**
    -   * Creates an injector defined by {@code modules} and immediately uses it to
    -   * create an instance of {@code type}. The modules can be of any type, and
    -   * must contain {@code @Provides} methods.
    +   * Creates an injector defined by {@code modules} and immediately uses it to create an instance of
    +   * {@code type}. The modules can be of any type, and must contain {@code @Provides} methods.
        *
        * 

    The following injection features are supported: + * *

      - *
    • Field injection. A class may have any number of field injections, and - * fields may be of any visibility. Static fields will be injected each - * time an instance is injected. - *
    • Constructor injection. A class may have a single {@code - * @Inject}-annotated constructor. Classes that have fields injected - * may omit the {@link @Inject} annotation if they have a public - * no-arguments constructor. - *
    • Injection of {@code @Provides} method parameters. - *
    • {@code @Provides} methods annotated {@code @Singleton}. - *
    • Constructor-injected classes annotated {@code @Singleton}. - *
    • Injection of {@link Provider}s. - *
    • Binding annotations on injected parameters and fields. - *
    • Guice annotations. - *
    • JSR 330 annotations. - *
    • Eager loading of singletons. + *
    • Field injection. A class may have any number of field injections, and fields may be of any + * visibility. Static fields will be injected each time an instance is injected. + *
    • Constructor injection. A class may have a single {@code @Inject}-annotated constructor. + * Classes that have fields injected may omit the {@link @Inject} annotation if they have a + * public no-arguments constructor. + *
    • Injection of {@code @Provides} method parameters. + *
    • {@code @Provides} methods annotated {@code @Singleton}. + *
    • Constructor-injected classes annotated {@code @Singleton}. + *
    • Injection of {@link Provider}s. + *
    • Binding annotations on injected parameters and fields. + *
    • Guice annotations. + *
    • JSR 330 annotations. + *
    • Eager loading of singletons. *
    * *

    Note that method injection is not supported. @@ -90,17 +88,20 @@ } private void addProviderBindings() { - Map> providerBindings = new HashMap>(); + Map> providerBindings = new HashMap<>(); for (final Map.Entry> binding : bindings.entrySet()) { Key key = binding.getKey(); final Provider value = binding.getValue(); - Provider> providerProvider = new Provider>() { - public Provider get() { - return value; - } - }; - providerBindings.put(new Key(new ProviderType(javax.inject.Provider.class, key.type), - key.annotation), providerProvider); + Provider> providerProvider = + new Provider>() { + @Override + public Provider get() { + return value; + } + }; + providerBindings.put( + new Key(new ProviderType(javax.inject.Provider.class, key.type), key.annotation), + providerProvider); } bindings.putAll(providerBindings); } @@ -108,7 +109,7 @@ private void requireKey(Key key, Object requiredBy) { if (key.type instanceof ParameterizedType && (((ParameterizedType) key.type).getRawType() == Provider.class - || ((ParameterizedType) key.type).getRawType() == javax.inject.Provider.class)) { + || ((ParameterizedType) key.type).getRawType() == javax.inject.Provider.class)) { Type type = ((ParameterizedType) key.type).getActualTypeArguments()[0]; key = new Key(type, key.annotation); } @@ -120,11 +121,14 @@ for (Key key : singletons) { Provider provider = bindings.get(key); final Object onlyInstance = provider.get(); - bindings.put(key, new Provider() { - public Object get() { - return onlyInstance; - } - }); + bindings.put( + key, + new Provider() { + @Override + public Object get() { + return onlyInstance; + } + }); } } @@ -145,21 +149,24 @@ } private void addProviderMethodBinding(Key key, final Object instance, final Method method) { - final Key[] parameterKeys = parametersToKeys( - method, method.getGenericParameterTypes(), method.getParameterAnnotations()); + final Key[] parameterKeys = + parametersToKeys( + method, method.getGenericParameterTypes(), method.getParameterAnnotations()); method.setAccessible(true); - final Provider unscoped = new Provider() { - public Object get() { - Object[] parameters = keysToValues(parameterKeys); - try { - return method.invoke(instance, parameters); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e.getCause()); - } - } - }; + final Provider unscoped = + new Provider() { + @Override + public Object get() { + Object[] parameters = keysToValues(parameterKeys); + try { + return method.invoke(instance, parameters); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause()); + } + } + }; boolean singleton = method.isAnnotationPresent(javax.inject.Singleton.class); putBinding(key, unscoped, singleton); @@ -185,8 +192,8 @@ /* * Lookup the injectable fields and their corresponding keys. */ - final List injectedFields = new ArrayList(); - List fieldKeysList = new ArrayList(); + final List injectedFields = new ArrayList<>(); + List fieldKeysList = new ArrayList<>(); for (Class c = type; c != Object.class; c = c.getSuperclass()) { for (Field field : c.getDeclaredFields()) { if (!field.isAnnotationPresent(javax.inject.Inject.class)) { @@ -218,14 +225,14 @@ } if (injectedConstructor == null) { if (fieldKeys.length == 0) { - throw new IllegalArgumentException("No injectable constructor on " - + type + " required by " + requiredBy); + throw new IllegalArgumentException( + "No injectable constructor on " + type + " required by " + requiredBy); } try { injectedConstructor = type.getConstructor(); } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("No injectable constructor on " - + type + " required by " + requiredBy); + throw new IllegalArgumentException( + "No injectable constructor on " + type + " required by " + requiredBy); } } @@ -233,27 +240,32 @@ * Create a provider that invokes the constructor and sets its fields. */ final Constructor constructor = injectedConstructor; - final Key[] parameterKeys = parametersToKeys( - constructor, constructor.getGenericParameterTypes(), constructor.getParameterAnnotations()); - final Provider unscoped = new Provider() { - public Object get() { - Object[] constructorParameters = keysToValues(parameterKeys); - try { - Object result = constructor.newInstance(constructorParameters); - Object[] fieldValues = keysToValues(fieldKeys); - for (int i = 0; i < fieldValues.length; i++) { - injectedFields.get(i).set(result, fieldValues[i]); + final Key[] parameterKeys = + parametersToKeys( + constructor, + constructor.getGenericParameterTypes(), + constructor.getParameterAnnotations()); + final Provider unscoped = + new Provider() { + @Override + public Object get() { + Object[] constructorParameters = keysToValues(parameterKeys); + try { + Object result = constructor.newInstance(constructorParameters); + Object[] fieldValues = keysToValues(fieldKeys); + for (int i = 0; i < fieldValues.length; i++) { + injectedFields.get(i).set(result, fieldValues[i]); + } + return result; + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getCause()); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause()); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } } - return result; - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getCause()); - } catch (InvocationTargetException e) { - throw new RuntimeException(e.getCause()); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } - } - }; + }; boolean singleton = type.isAnnotationPresent(javax.inject.Singleton.class); putBinding(new Key(type, null), unscoped, singleton); @@ -263,15 +275,18 @@ if (singleton) { singletons.add(key); final Provider unscoped = provider; - provider = new Provider() { - private Object onlyInstance = UNINITIALIZED; - public Object get() { - if (onlyInstance == UNINITIALIZED) { - onlyInstance = unscoped.get(); - } - return onlyInstance; - } - }; + provider = + new Provider() { + private Object onlyInstance = UNINITIALIZED; + + @Override + public Object get() { + if (onlyInstance == UNINITIALIZED) { + onlyInstance = unscoped.get(); + } + return onlyInstance; + } + }; } if (bindings.put(key, provider) != null) { @@ -324,13 +339,15 @@ this.annotation = annotation; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { return o instanceof Key && ((Key) o).type.equals(type) && equal(annotation, ((Key) o).annotation); } - @Override public int hashCode() { + @Override + public int hashCode() { int result = type.hashCode(); if (annotation != null) { result += (37 * annotation.hashCode()); @@ -338,12 +355,13 @@ return result; } - @Override public String toString() { + @Override + public String toString() { return "key[type=" + type + ",annotation=" + annotation + "]"; } } - private class RequiredKey { + private static class RequiredKey { private final Key key; private final Object requiredBy; @@ -362,19 +380,23 @@ this.typeArgument = typeArgument; } + @Override public Type getRawType() { return rawType; } + @Override public Type[] getActualTypeArguments() { - return new Type[] { typeArgument }; + return new Type[] {typeArgument}; } + @Override public Type getOwnerType() { return null; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (o instanceof ParameterizedType) { ParameterizedType that = (ParameterizedType) o; return Arrays.equals(getActualTypeArguments(), that.getActualTypeArguments()) @@ -383,7 +405,8 @@ return false; } - @Override public int hashCode() { + @Override + public int hashCode() { return Arrays.hashCode(getActualTypeArguments()) ^ rawType.hashCode(); } } diff -Nru sisu-guice-3.2.6/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java sisu-guice-4.2.0/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java --- sisu-guice-3.2.6/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -16,28 +16,32 @@ package com.google.inject.mini; import com.google.inject.Provides; - -import junit.framework.TestCase; - import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; - import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; +import junit.framework.TestCase; +@SuppressWarnings("ProvidesMethodOutsideOfModule") public final class MiniGuiceTest extends TestCase { public void testBasicInjection() { - G g = MiniGuice.inject(G.class, new Object() { - @Provides E provideE(F f) { - return new E(f); - } - @Provides F provideF() { - return new F(); - } - }); + G g = + MiniGuice.inject( + G.class, + new Object() { + @Provides + E provideE(F f) { + return new E(f); + } + + @Provides + F provideF() { + return new F(); + } + }); assertNotNull(g.a); assertNotNull(g.b); @@ -48,25 +52,30 @@ } static class A { - @Inject A() {} + @Inject + A() {} } static class B { - @Inject B() {} + @Inject + B() {} } @Singleton static class C { - @Inject C() {} + @Inject + C() {} } @Singleton static class D { - @Inject D() {} + @Inject + D() {} } static class E { F f; + E(F f) { this.f = f; } @@ -80,12 +89,14 @@ C c; D d; @Inject E e; - @Inject G(C c, D d) { + + @Inject + G(C c, D d) { this.c = c; this.d = d; } } - + public void testProviderInjection() { H h = MiniGuice.inject(H.class); assertNotNull(h.aProvider.get()); @@ -95,42 +106,60 @@ static class H { @Inject Provider aProvider; - @Inject H() {} + + @Inject + H() {} } - + public void testSingletons() { - J j = MiniGuice.inject(J.class, new Object() { - @Provides @Singleton F provideK() { - return new F(); - } - }); + J j = + MiniGuice.inject( + J.class, + new Object() { + @Provides + @Singleton + F provideK() { + return new F(); + } + }); assertSame(j.fProvider.get(), j.fProvider.get()); assertSame(j.iProvider.get(), j.iProvider.get()); } @Singleton static class I { - @Inject I() {} + @Inject + I() {} } static class J { @Inject Provider fProvider; @Inject Provider iProvider; - @Inject J() {} + + @Inject + J() {} } public void testBindingAnnotations() { final A one = new A(); final A two = new A(); - K k = MiniGuice.inject(K.class, new Object() { - @Provides @Named("one") A getOne() { - return one; - } - @Provides @Named("two") A getTwo() { - return two; - } - }); + K k = + MiniGuice.inject( + K.class, + new Object() { + @Provides + @Named("one") + A getOne() { + return one; + } + + @Provides + @Named("two") + A getTwo() { + return two; + } + }); assertNotNull(k.a); assertSame(one, k.aOne); @@ -139,21 +168,33 @@ public static class K { @Inject A a; - @Inject @Named("one") A aOne; - @Inject @Named("two") A aTwo; + + @Inject + @Named("one") + A aOne; + + @Inject + @Named("two") + A aTwo; } - + public void testSingletonBindingAnnotationAndProvider() { - final AtomicReference a1 = new AtomicReference(); - final AtomicReference a2 = new AtomicReference(); + final AtomicReference a1 = new AtomicReference<>(); + final AtomicReference a2 = new AtomicReference<>(); - L l = MiniGuice.inject(L.class, new Object() { - @Provides @Singleton @Named("one") F provideF(Provider aProvider) { - a1.set(aProvider.get()); - a2.set(aProvider.get()); - return new F(); - } - }); + L l = + MiniGuice.inject( + L.class, + new Object() { + @Provides + @Singleton + @Named("one") + F provideF(Provider aProvider) { + a1.set(aProvider.get()); + a2.set(aProvider.get()); + return new F(); + } + }); assertNotNull(a1.get()); assertNotNull(a2.get()); @@ -163,16 +204,24 @@ @Singleton public static class L { - @Inject @Named("one") F f; + @Inject + @Named("one") + F f; + @Inject Provider lProvider; } public void testSingletonInGraph() { - M m = MiniGuice.inject(M.class, new Object() { - @Provides @Singleton F provideF() { - return new F(); - } - }); + M m = + MiniGuice.inject( + M.class, + new Object() { + @Provides + @Singleton + F provideF() { + return new F(); + } + }); assertSame(m.f1, m.f2); assertSame(m.f1, m.n1.f1); @@ -205,41 +254,53 @@ } public static class O { - @Inject @Named("a") A a; + @Inject + @Named("a") + A a; } public void testSubclasses() { - Q q = MiniGuice.inject(Q.class, new Object() { - @Provides F provideF() { - return new F(); - } - }); + Q q = + MiniGuice.inject( + Q.class, + new Object() { + @Provides + F provideF() { + return new F(); + } + }); assertNotNull(q.f); } - + public static class P { @Inject F f; } public static class Q extends P { - @Inject Q() {} + @Inject + Q() {} } - + public void testSingletonsAreEager() { final AtomicBoolean sInjected = new AtomicBoolean(); R.injected = false; - MiniGuice.inject(A.class, new Object() { - @Provides F provideF(R r) { - return new F(); - } - - @Provides @Singleton S provideS() { - sInjected.set(true); - return new S(); - } - }); + MiniGuice.inject( + A.class, + new Object() { + @Provides + F provideF(R r) { + return new F(); + } + + @Provides + @Singleton + S provideS() { + sInjected.set(true); + return new S(); + } + }); assertTrue(R.injected); assertTrue(sInjected.get()); @@ -248,7 +309,9 @@ @Singleton static class R { static boolean injected = false; - @Inject R() { + + @Inject + R() { injected = true; } } diff -Nru sisu-guice-3.2.6/extensions/multibindings/build.properties sisu-guice-4.2.0/extensions/multibindings/build.properties --- sisu-guice-3.2.6/extensions/multibindings/build.properties 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/build.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -lib.dir=../../lib -src.dir=src -test.dir=test -build.dir=build -test.class=com.google.inject.multibindings.AllTests -module=com.google.inject.multibindings -fragment=true diff -Nru sisu-guice-3.2.6/extensions/multibindings/build.xml sisu-guice-4.2.0/extensions/multibindings/build.xml --- sisu-guice-3.2.6/extensions/multibindings/build.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/build.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff -Nru sisu-guice-3.2.6/extensions/multibindings/.gitignore sisu-guice-4.2.0/extensions/multibindings/.gitignore --- sisu-guice-3.2.6/extensions/multibindings/.gitignore 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -/build/ diff -Nru sisu-guice-3.2.6/extensions/multibindings/pom.xml sisu-guice-4.2.0/extensions/multibindings/pom.xml --- sisu-guice-3.2.6/extensions/multibindings/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,11 +6,50 @@ org.sonatype.sisu.inject extensions-parent - 3.2.6 + 4.2.0 guice-multibindings Sisu Guice - Extensions - MultiBindings + + + + maven-jar-plugin + + + + com.google.guice.extensions.multibindings + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + reattach-sources-as-javadoc + package + + attach-artifact + + + + + ${project.build.directory}/${project.build.finalName}-sources.jar + javadoc + + + + + + + + diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Allows {@literal @}{@link ProvidesIntoMap} to specify a class map key. - * - * @since 4.0 - */ -@MapKey(unwrapValue = true) -@Documented -@Target(METHOD) -@Retention(RUNTIME) -public @interface ClassMapKey { - Class value(); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/Element.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/Element.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/Element.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/Element.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.google.inject.multibindings; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.BindingAnnotation; - -import java.lang.annotation.Retention; - -/** - * An internal binding annotation applied to each element in a multibinding. - * All elements are assigned a globally-unique id to allow different modules - * to contribute multibindings independently. - * - * @author jessewilson@google.com (Jesse Wilson) - */ -@Retention(RUNTIME) @BindingAnnotation -@interface Element { - - enum Type { - MAPBINDER, - MULTIBINDER, - OPTIONALBINDER; - } - - String setName(); - int uniqueId(); - Type type(); - String keyType(); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,169 +0,0 @@ -/** - * Copyright (C) 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.common.base.Objects; -import com.google.inject.Binding; -import com.google.inject.Injector; -import com.google.inject.Scope; -import com.google.inject.Scopes; -import com.google.inject.TypeLiteral; -import com.google.inject.spi.BindingScopingVisitor; -import com.google.inject.spi.ConstructorBinding; -import com.google.inject.spi.ConvertedConstantBinding; -import com.google.inject.spi.DefaultBindingTargetVisitor; -import com.google.inject.spi.ExposedBinding; -import com.google.inject.spi.InstanceBinding; -import com.google.inject.spi.LinkedKeyBinding; -import com.google.inject.spi.ProviderBinding; -import com.google.inject.spi.ProviderInstanceBinding; -import com.google.inject.spi.ProviderKeyBinding; -import com.google.inject.spi.UntargettedBinding; - -import java.lang.annotation.Annotation; - -/** - * Visits bindings to return a {@code IndexedBinding} that can be used to emulate the binding - * deduplication that Guice internally performs. - */ -class Indexer extends DefaultBindingTargetVisitor - implements BindingScopingVisitor { - enum BindingType { - INSTANCE, - PROVIDER_INSTANCE, - PROVIDER_KEY, - LINKED_KEY, - UNTARGETTED, - CONSTRUCTOR, - CONSTANT, - EXPOSED, - PROVIDED_BY, - } - - static class IndexedBinding { - final String annotationName; - final Element.Type annotationType; - final TypeLiteral typeLiteral; - final Object scope; - final BindingType type; - final Object extraEquality; - - IndexedBinding(Binding binding, BindingType type, Object scope, Object extraEquality) { - this.scope = scope; - this.type = type; - this.extraEquality = extraEquality; - this.typeLiteral = binding.getKey().getTypeLiteral(); - Element annotation = (Element) binding.getKey().getAnnotation(); - this.annotationName = annotation.setName(); - this.annotationType = annotation.type(); - } - - @Override public boolean equals(Object obj) { - if (!(obj instanceof IndexedBinding)) { - return false; - } - IndexedBinding o = (IndexedBinding) obj; - return type == o.type - && Objects.equal(scope, o.scope) - && typeLiteral.equals(o.typeLiteral) - && annotationType == o.annotationType - && annotationName.equals(o.annotationName) - && Objects.equal(extraEquality, o.extraEquality); - } - - @Override public int hashCode() { - return Objects.hashCode(type, scope, typeLiteral, annotationType, annotationName, - extraEquality); - } - } - - final Injector injector; - - Indexer(Injector injector) { - this.injector = injector; - } - - boolean isIndexable(Binding binding) { - return binding.getKey().getAnnotation() instanceof Element; - } - - private Object scope(Binding binding) { - return binding.acceptScopingVisitor(this); - } - - @Override public Indexer.IndexedBinding visit(ConstructorBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.CONSTRUCTOR, scope(binding), - binding.getConstructor()); - } - - @Override public Indexer.IndexedBinding visit( - ConvertedConstantBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.CONSTANT, scope(binding), - binding.getValue()); - } - - @Override public Indexer.IndexedBinding visit(ExposedBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.EXPOSED, scope(binding), binding); - } - - @Override public Indexer.IndexedBinding visit(InstanceBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.INSTANCE, scope(binding), - binding.getInstance()); - } - - @Override public Indexer.IndexedBinding visit(LinkedKeyBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.LINKED_KEY, scope(binding), - binding.getLinkedKey()); - } - - @Override public Indexer.IndexedBinding visit(ProviderBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.PROVIDED_BY, scope(binding), - injector.getBinding(binding.getProvidedKey())); - } - - @Override public Indexer.IndexedBinding visit(ProviderInstanceBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.PROVIDER_INSTANCE, scope(binding), - binding.getUserSuppliedProvider()); - } - - @Override public Indexer.IndexedBinding visit(ProviderKeyBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.PROVIDER_KEY, scope(binding), - binding.getProviderKey()); - } - - @Override public Indexer.IndexedBinding visit(UntargettedBinding binding) { - return new Indexer.IndexedBinding(binding, BindingType.UNTARGETTED, scope(binding), null); - } - - private static final Object EAGER_SINGLETON = new Object(); - - @Override public Object visitEagerSingleton() { - return EAGER_SINGLETON; - } - - @Override public Object visitNoScoping() { - return Scopes.NO_SCOPE; - } - - @Override public Object visitScope(Scope scope) { - return scope; - } - - @Override public Object visitScopeAnnotation(Class scopeAnnotation) { - return scopeAnnotation; - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -/** - * Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.Binding; -import com.google.inject.Key; -import com.google.inject.TypeLiteral; -import com.google.inject.spi.Element; -import com.google.inject.spi.Elements; - -import java.util.List; -import java.util.Map; - -/** - * A binding for a MapBinder. - *

    - * Although MapBinders may be injected through a variety of generic types (Map<K, V>, Map - * <K, Provider<V>>, Map<K, Set<V>>, Map>, and even Set<Map.Entry<K, Provider<V>>), a - * MapBinderBinding exists only on the Binding associated with the Map<K, V> key. Other - * bindings can be validated to be derived from this MapBinderBinding using - * {@link #containsElement(Element)}. - * - * @param The fully qualified type of the map, including Map. For example: - * MapBinderBinding<Map<String, Snack>> - * - * @since 3.0 - * @author sameb@google.com (Sam Berlin) - */ -public interface MapBinderBinding { - - /** Returns the {@link Key} for the map. */ - Key getMapKey(); - - /** - * Returns the TypeLiteral describing the keys of the map. - *

    - * The TypeLiteral will always match the type Map's generic type. For example, if getMapKey - * returns a key of Map<String, Snack>, then this will always return a - * TypeLiteral<String>. - */ - TypeLiteral getKeyTypeLiteral(); - - /** - * Returns the TypeLiteral describing the values of the map. - *

    - * The TypeLiteral will always match the type Map's generic type. For example, if getMapKey - * returns a key of Map<String, Snack>, then this will always return a - * TypeLiteral<Snack>. - */ - TypeLiteral getValueTypeLiteral(); - - /** - * Returns all entries in the Map. The returned list of Map.Entries contains the key and a binding - * to the value. Duplicate keys or values will exist as separate Map.Entries in the returned list. - * This is only supported on bindings returned from an injector. This will throw - * {@link UnsupportedOperationException} if it is called on an element retrieved from - * {@link Elements#getElements}. - *

    - * The elements will always match the type Map's generic type. For example, if getMapKey returns a - * key of Map<String, Snack>, then this will always return a list of type - * List<Map.Entry<String, Binding<Snack>>>. - */ - List>> getEntries(); - - /** - * Returns true if the MapBinder permits duplicates. This is only supported on bindings returned - * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a - * MapBinderBinding retrieved from {@link Elements#getElements}. - */ - boolean permitsDuplicates(); - - /** - * Returns true if this MapBinder contains the given Element in order to build the map or uses the - * given Element in order to support building and injecting the map. This will work for - * MapBinderBindings retrieved from an injector and {@link Elements#getElements}. Usually this is - * only necessary if you are working with elements retrieved from modules (without an Injector), - * otherwise {@link #getEntries} and {@link #permitsDuplicates} are better options. - *

    - * If you need to introspect the details of the map, such as the keys, values or if it permits - * duplicates, it is necessary to pass the elements through an Injector and use - * {@link #getEntries()} and {@link #permitsDuplicates()}. - */ - boolean containsElement(Element element); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,854 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.inject.multibindings.Element.Type.MAPBINDER; -import static com.google.inject.multibindings.Multibinder.checkConfiguration; -import static com.google.inject.multibindings.Multibinder.checkNotNull; -import static com.google.inject.multibindings.Multibinder.setOf; -import static com.google.inject.util.Types.newParameterizedType; -import static com.google.inject.util.Types.newParameterizedTypeWithOwner; - -import com.google.common.base.Joiner; -import com.google.common.base.Objects; -import com.google.common.base.Supplier; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; -import com.google.common.collect.Sets; -import com.google.inject.Binder; -import com.google.inject.Binding; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.TypeLiteral; -import com.google.inject.binder.LinkedBindingBuilder; -import com.google.inject.internal.Errors; -import com.google.inject.multibindings.Indexer.IndexedBinding; -import com.google.inject.multibindings.Multibinder.RealMultibinder; -import com.google.inject.spi.BindingTargetVisitor; -import com.google.inject.spi.Dependency; -import com.google.inject.spi.Element; -import com.google.inject.spi.HasDependencies; -import com.google.inject.spi.ProviderInstanceBinding; -import com.google.inject.spi.ProviderLookup; -import com.google.inject.spi.ProviderWithDependencies; -import com.google.inject.spi.ProviderWithExtensionVisitor; -import com.google.inject.spi.Toolable; -import com.google.inject.util.Types; - -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * An API to bind multiple map entries separately, only to later inject them as - * a complete map. MapBinder is intended for use in your application's module: - *

    
    - * public class SnacksModule extends AbstractModule {
    - *   protected void configure() {
    - *     MapBinder<String, Snack> mapbinder
    - *         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
    - *     mapbinder.addBinding("twix").toInstance(new Twix());
    - *     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
    - *     mapbinder.addBinding("skittles").to(Skittles.class);
    - *   }
    - * }
    - * - *

    With this binding, a {@link Map}{@code } can now be - * injected: - *

    
    - * class SnackMachine {
    - *   {@literal @}Inject
    - *   public SnackMachine(Map<String, Snack> snacks) { ... }
    - * }
    - * - *

    In addition to binding {@code Map}, a mapbinder will also bind - * {@code Map>} for lazy value provision: - *

    
    - * class SnackMachine {
    - *   {@literal @}Inject
    - *   public SnackMachine(Map<String, Provider<Snack>> snackProviders) { ... }
    - * }
    - * - *

    Contributing mapbindings from different modules is supported. For example, - * it is okay to have both {@code CandyModule} and {@code ChipsModule} both - * create their own {@code MapBinder}, and to each contribute - * bindings to the snacks map. When that map is injected, it will contain - * entries from both modules. - * - *

    The map's iteration order is consistent with the binding order. This is - * convenient when multiple elements are contributed by the same module because - * that module can order its bindings appropriately. Avoid relying on the - * iteration order of elements contributed by different modules, since there is - * no equivalent mechanism to order modules. - * - *

    The map is unmodifiable. Elements can only be added to the map by - * configuring the MapBinder. Elements can never be removed from the map. - * - *

    Values are resolved at map injection time. If a value is bound to a - * provider, that provider's get method will be called each time the map is - * injected (unless the binding is also scoped, or a map of providers is injected). - * - *

    Annotations are used to create different maps of the same key/value - * type. Each distinct annotation gets its own independent map. - * - *

    Keys must be distinct. If the same key is bound more than - * once, map injection will fail. However, use {@link #permitDuplicates()} in - * order to allow duplicate keys; extra bindings to {@code Map>} and - * {@code Map>} will be added. - * - *

    Keys must be non-null. {@code addBinding(null)} will - * throw an unchecked exception. - * - *

    Values must be non-null to use map injection. If any - * value is null, map injection will fail (although injecting a map of providers - * will not). - * - * @author dpb@google.com (David P. Baker) - */ -public abstract class MapBinder { - private MapBinder() {} - - /** - * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a - * {@link Map} that is itself bound with no binding annotation. - */ - public static MapBinder newMapBinder(Binder binder, - TypeLiteral keyType, TypeLiteral valueType) { - binder = binder.skipSources(MapBinder.class, RealMapBinder.class); - return newRealMapBinder(binder, keyType, valueType, Key.get(mapOf(keyType, valueType)), - Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType))); - } - - /** - * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a - * {@link Map} that is itself bound with no binding annotation. - */ - public static MapBinder newMapBinder(Binder binder, - Class keyType, Class valueType) { - return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType)); - } - - /** - * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a - * {@link Map} that is itself bound with {@code annotation}. - */ - public static MapBinder newMapBinder(Binder binder, - TypeLiteral keyType, TypeLiteral valueType, Annotation annotation) { - binder = binder.skipSources(MapBinder.class, RealMapBinder.class); - return newRealMapBinder(binder, keyType, valueType, - Key.get(mapOf(keyType, valueType), annotation), - Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotation)); - } - - /** - * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a - * {@link Map} that is itself bound with {@code annotation}. - */ - public static MapBinder newMapBinder(Binder binder, - Class keyType, Class valueType, Annotation annotation) { - return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotation); - } - - /** - * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a - * {@link Map} that is itself bound with {@code annotationType}. - */ - public static MapBinder newMapBinder(Binder binder, TypeLiteral keyType, - TypeLiteral valueType, Class annotationType) { - binder = binder.skipSources(MapBinder.class, RealMapBinder.class); - return newRealMapBinder(binder, keyType, valueType, - Key.get(mapOf(keyType, valueType), annotationType), - Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotationType)); - } - - /** - * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a - * {@link Map} that is itself bound with {@code annotationType}. - */ - public static MapBinder newMapBinder(Binder binder, Class keyType, - Class valueType, Class annotationType) { - return newMapBinder( - binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotationType); - } - - @SuppressWarnings("unchecked") // a map of is safely a Map - static TypeLiteral> mapOf( - TypeLiteral keyType, TypeLiteral valueType) { - return (TypeLiteral>) TypeLiteral.get( - Types.mapOf(keyType.getType(), valueType.getType())); - } - - @SuppressWarnings("unchecked") // a provider map is safely a Map> - static TypeLiteral>> mapOfProviderOf( - TypeLiteral keyType, TypeLiteral valueType) { - return (TypeLiteral>>) TypeLiteral.get( - Types.mapOf(keyType.getType(), Types.providerOf(valueType.getType()))); - } - - // provider map is safely a Map>> - @SuppressWarnings("unchecked") - static TypeLiteral>> mapOfJavaxProviderOf( - TypeLiteral keyType, TypeLiteral valueType) { - return (TypeLiteral>>) TypeLiteral.get( - Types.mapOf(keyType.getType(), - newParameterizedType(javax.inject.Provider.class, valueType.getType()))); - } - - @SuppressWarnings("unchecked") // a provider map > is safely a Map>> - static TypeLiteral>>> mapOfSetOfProviderOf( - TypeLiteral keyType, TypeLiteral valueType) { - return (TypeLiteral>>>) TypeLiteral.get( - Types.mapOf(keyType.getType(), Types.setOf(Types.providerOf(valueType.getType())))); - } - - @SuppressWarnings("unchecked") // a provider entry is safely a Map.Entry> - static TypeLiteral>> entryOfProviderOf( - TypeLiteral keyType, TypeLiteral valueType) { - return (TypeLiteral>>) TypeLiteral.get(newParameterizedTypeWithOwner( - Map.class, Entry.class, keyType.getType(), Types.providerOf(valueType.getType()))); - } - - // Note: We use valueTypeAndAnnotation effectively as a Pair - // since it's an easy way to group a type and an optional annotation type or instance. - static RealMapBinder newRealMapBinder(Binder binder, TypeLiteral keyType, - Key valueTypeAndAnnotation) { - binder = binder.skipSources(MapBinder.class, RealMapBinder.class); - TypeLiteral valueType = valueTypeAndAnnotation.getTypeLiteral(); - return newRealMapBinder(binder, keyType, valueType, - valueTypeAndAnnotation.ofType(mapOf(keyType, valueType)), - Multibinder.newSetBinder(binder, - valueTypeAndAnnotation.ofType(entryOfProviderOf(keyType, valueType)))); - } - - private static RealMapBinder newRealMapBinder(Binder binder, - TypeLiteral keyType, TypeLiteral valueType, Key> mapKey, - Multibinder>> entrySetBinder) { - RealMapBinder mapBinder = - new RealMapBinder(binder, keyType, valueType, mapKey, entrySetBinder); - binder.install(mapBinder); - return mapBinder; - } - - /** - * Configures the {@code MapBinder} to handle duplicate entries. - *

    When multiple equal keys are bound, the value that gets included in the map is - * arbitrary. - *

    In addition to the {@code Map} and {@code Map>} - * maps that are normally bound, a {@code Map>} and - * {@code Map>>} are also bound, which contain - * all values bound to each key. - *

    - * When multiple modules contribute elements to the map, this configuration - * option impacts all of them. - * - * @return this map binder - * @since 3.0 - */ - public abstract MapBinder permitDuplicates(); - - /** - * Returns a binding builder used to add a new entry in the map. Each - * key must be distinct (and non-null). Bound providers will be evaluated each - * time the map is injected. - * - *

    It is an error to call this method without also calling one of the - * {@code to} methods on the returned binding builder. - * - *

    Scoping elements independently is supported. Use the {@code in} method - * to specify a binding scope. - */ - public abstract LinkedBindingBuilder addBinding(K key); - - /** - * The actual mapbinder plays several roles: - * - *

    As a MapBinder, it acts as a factory for LinkedBindingBuilders for - * each of the map's values. It delegates to a {@link Multibinder} of - * entries (keys to value providers). - * - *

    As a Module, it installs the binding to the map itself, as well as to - * a corresponding map whose values are providers. It uses the entry set - * multibinder to construct the map and the provider map. - * - *

    As a module, this implements equals() and hashcode() in order to trick - * Guice into executing its configure() method only once. That makes it so - * that multiple mapbinders can be created for the same target map, but - * only one is bound. Since the list of bindings is retrieved from the - * injector itself (and not the mapbinder), each mapbinder has access to - * all contributions from all equivalent mapbinders. - * - *

    Rather than binding a single Map.Entry<K, V>, the map binder - * binds keys and values independently. This allows the values to be properly - * scoped. - * - *

    We use a subclass to hide 'implements Module' from the public API. - */ - static final class RealMapBinder extends MapBinder implements Module { - private final TypeLiteral keyType; - private final TypeLiteral valueType; - private final Key> mapKey; - private final Key>> javaxProviderMapKey; - private final Key>> providerMapKey; - private final Key>> multimapKey; - private final Key>>> providerMultimapKey; - private final RealMultibinder>> entrySetBinder; - private final Map duplicateKeyErrorMessages; - - /* the target injector's binder. non-null until initialization, null afterwards */ - private Binder binder; - - private boolean permitDuplicates; - private ImmutableList>> mapBindings; - - private RealMapBinder(Binder binder, TypeLiteral keyType, TypeLiteral valueType, - Key> mapKey, Multibinder>> entrySetBinder) { - this.keyType = keyType; - this.valueType = valueType; - this.mapKey = mapKey; - this.providerMapKey = mapKey.ofType(mapOfProviderOf(keyType, valueType)); - this.javaxProviderMapKey = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); - this.multimapKey = mapKey.ofType(mapOf(keyType, setOf(valueType))); - this.providerMultimapKey = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); - this.entrySetBinder = (RealMultibinder>>) entrySetBinder; - this.binder = binder; - this.duplicateKeyErrorMessages = Maps.newHashMap(); - } - - /** Sets the error message to be shown if the key had duplicate non-equal bindings. */ - void updateDuplicateKeyMessage(K k, String errMsg) { - duplicateKeyErrorMessages.put(k, errMsg); - } - - @Override - public MapBinder permitDuplicates() { - entrySetBinder.permitDuplicates(); - binder.install(new MultimapBinder( - multimapKey, providerMultimapKey, entrySetBinder.getSetKey())); - return this; - } - - Key getKeyForNewValue(K key) { - checkNotNull(key, "key"); - checkConfiguration(!isInitialized(), "MapBinder was already initialized"); - - Key valueKey = Key.get(valueType, - new RealElement(entrySetBinder.getSetName(), MAPBINDER, keyType.toString())); - entrySetBinder.addBinding().toProvider(new ProviderMapEntry( - key, binder.getProvider(valueKey), valueKey)); - return valueKey; - } - - /** - * This creates two bindings. One for the {@code Map.Entry>} - * and another for {@code V}. - */ - @Override public LinkedBindingBuilder addBinding(K key) { - return binder.bind(getKeyForNewValue(key)); - } - - @Override public void configure(Binder binder) { - checkConfiguration(!isInitialized(), "MapBinder was already initialized"); - - ImmutableSet> dependencies - = ImmutableSet.>of(Dependency.get(entrySetBinder.getSetKey())); - - // Binds a Map> from a collection of Set>. - Provider>>> entrySetProvider = binder - .getProvider(entrySetBinder.getSetKey()); - - binder.bind(providerMapKey).toProvider( - new RealProviderMapProvider(dependencies, entrySetProvider)); - - // The map this exposes is internally an ImmutableMap, so it's OK to massage - // the guice Provider to javax Provider in the value (since Guice provider - // implements javax Provider). - @SuppressWarnings("unchecked") - Key massagedProviderMapKey = (Key)providerMapKey; - binder.bind(javaxProviderMapKey).to(massagedProviderMapKey); - - Provider>> mapProvider = binder.getProvider(providerMapKey); - binder.bind(mapKey).toProvider(new RealMapProvider(dependencies, mapProvider)); - } - - boolean containsElement(Element element) { - if (entrySetBinder.containsElement(element)) { - return true; - } else { - Key key; - if (element instanceof Binding) { - key = ((Binding)element).getKey(); - } else if (element instanceof ProviderLookup) { - key = ((ProviderLookup)element).getKey(); - } else { - return false; // cannot match; - } - - return key.equals(mapKey) - || key.equals(providerMapKey) - || key.equals(javaxProviderMapKey) - || key.equals(multimapKey) - || key.equals(providerMultimapKey) - || key.equals(entrySetBinder.getSetKey()) - || matchesValueKey(key); - } - } - - /** Returns true if the key indicates this is a value in the map. */ - private boolean matchesValueKey(Key key) { - return key.getAnnotation() instanceof RealElement - && ((RealElement) key.getAnnotation()).setName().equals(entrySetBinder.getSetName()) - && ((RealElement) key.getAnnotation()).type() == MAPBINDER - && ((RealElement) key.getAnnotation()).keyType().equals(keyType.toString()) - && key.getTypeLiteral().equals(valueType); - } - - private boolean isInitialized() { - return binder == null; - } - - @Override public boolean equals(Object o) { - return o instanceof RealMapBinder - && ((RealMapBinder) o).mapKey.equals(mapKey); - } - - @Override public int hashCode() { - return mapKey.hashCode(); - } - - final class RealProviderMapProvider - extends RealMapBinderProviderWithDependencies>> { - private final ImmutableSet> dependencies; - private final Provider>>> entrySetProvider; - private Map> providerMap; - - private RealProviderMapProvider( - ImmutableSet> dependencies, - Provider>>> entrySetProvider) { - super(mapKey); - this.dependencies = dependencies; - this.entrySetProvider = entrySetProvider; - } - - @Toolable @Inject void initialize(Injector injector) { - RealMapBinder.this.binder = null; - permitDuplicates = entrySetBinder.permitsDuplicates(injector); - - Map> providerMapMutable = new LinkedHashMap>(); - List>> bindingsMutable = Lists.newArrayList(); - Indexer indexer = new Indexer(injector); - Multimap index = HashMultimap.create(); - Set duplicateKeys = null; - for (Entry> entry : entrySetProvider.get()) { - ProviderMapEntry providerEntry = (ProviderMapEntry) entry; - Key valueKey = providerEntry.getValueKey(); - Binding valueBinding = injector.getBinding(valueKey); - // If this isn't a dup due to an exact same binding, add it. - if (index.put(providerEntry.getKey(), valueBinding.acceptTargetVisitor(indexer))) { - Provider previous = providerMapMutable.put(providerEntry.getKey(), - new ValueProvider(providerEntry.getValue(), valueBinding)); - if (previous != null && !permitDuplicates) { - if (duplicateKeys == null) { - duplicateKeys = Sets.newHashSet(); - } - duplicateKeys.add(providerEntry.getKey()); - } - bindingsMutable.add(Maps.immutableEntry(providerEntry.getKey(), valueBinding)); - } - } - if (duplicateKeys != null) { - // Must use a ListMultimap in case more than one binding has the same source - // and is listed multiple times. - Multimap dups = newLinkedKeyArrayValueMultimap(); - for (Map.Entry> entry : bindingsMutable) { - if (duplicateKeys.contains(entry.getKey())) { - dups.put(entry.getKey(), "\t at " + Errors.convert(entry.getValue().getSource())); - } - } - StringBuilder sb = new StringBuilder("Map injection failed due to duplicated key "); - boolean first = true; - for (K key : dups.keySet()) { - if (first) { - first = false; - if (duplicateKeyErrorMessages.containsKey(key)) { - sb.setLength(0); - sb.append(duplicateKeyErrorMessages.get(key)); - } else { - sb.append("\"" + key + "\", from bindings:\n"); - } - } else { - if (duplicateKeyErrorMessages.containsKey(key)) { - sb.append("\n and " + duplicateKeyErrorMessages.get(key)); - } else { - sb.append("\n and key: \"" + key + "\", from bindings:\n"); - } - } - Joiner.on('\n').appendTo(sb, dups.get(key)).append("\n"); - } - checkConfiguration(false, sb.toString()); - } - - providerMap = ImmutableMap.copyOf(providerMapMutable); - mapBindings = ImmutableList.copyOf(bindingsMutable); - } - - @Override public Map> get() { - return providerMap; - } - - @Override public Set> getDependencies() { - return dependencies; - } - } - - final class RealMapProvider extends RealMapWithExtensionProvider> { - private final ImmutableSet> dependencies; - private final Provider>> mapProvider; - - private RealMapProvider( - ImmutableSet> dependencies, - Provider>> mapProvider) { - super(mapKey); - this.dependencies = dependencies; - this.mapProvider = mapProvider; - } - - @Override public Map get() { - // We can initialize the internal table efficiently this way and then swap the values - // one by one. - Map map = new LinkedHashMap(mapProvider.get()); - for (Entry entry : map.entrySet()) { - @SuppressWarnings("unchecked") // we initialized the entries with providers - ValueProvider provider = (ValueProvider)entry.getValue(); - V value = provider.get(); - checkConfiguration(value != null, - "Map injection failed due to null value for key \"%s\", bound at: %s", - entry.getKey(), - provider.getValueBinding().getSource()); - entry.setValue(value); - } - @SuppressWarnings("unchecked") // if we exited the loop then we replaced all Providers - Map typedMap = (Map) map; - return Collections.unmodifiableMap(typedMap); - } - - @Override public Set> getDependencies() { - return dependencies; - } - - @SuppressWarnings("unchecked") - @Override - public R acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - if (visitor instanceof MultibindingsTargetVisitor) { - return ((MultibindingsTargetVisitor, R>)visitor).visit(this); - } else { - return visitor.visit(binding); - } - } - - @Override public Key> getMapKey() { - return mapKey; - } - - @Override public TypeLiteral getKeyTypeLiteral() { - return keyType; - } - - @Override public TypeLiteral getValueTypeLiteral() { - return valueType; - } - - @SuppressWarnings("unchecked") - @Override - public List>> getEntries() { - if (isInitialized()) { - return (List)mapBindings; // safe because mapBindings is immutable - } else { - throw new UnsupportedOperationException( - "getElements() not supported for module bindings"); - } - } - - @Override public boolean permitsDuplicates() { - if (isInitialized()) { - return permitDuplicates; - } else { - throw new UnsupportedOperationException( - "permitsDuplicates() not supported for module bindings"); - } - } - - @Override public boolean containsElement(Element element) { - return RealMapBinder.this.containsElement(element); - } - } - - /** - * Binds {@code Map>} and {{@code Map>>}. - */ - static final class MultimapBinder implements Module { - - private final Key>> multimapKey; - private final Key>>> providerMultimapKey; - private final Key>>> entrySetKey; - - public MultimapBinder( - Key>> multimapKey, - Key>>> providerMultimapKey, - Key>>> entrySetKey) { - this.multimapKey = multimapKey; - this.providerMultimapKey = providerMultimapKey; - this.entrySetKey = entrySetKey; - } - - @Override public void configure(Binder binder) { - ImmutableSet> dependencies - = ImmutableSet.>of(Dependency.get(entrySetKey)); - - Provider>>> entrySetProvider = - binder.getProvider(entrySetKey); - // Binds a Map>> from a collection of Map> if - // permitDuplicates was called. - binder.bind(providerMultimapKey).toProvider( - new RealProviderMultimapProvider(dependencies, entrySetProvider)); - - Provider>>> multimapProvider = - binder.getProvider(providerMultimapKey); - binder.bind(multimapKey).toProvider( - new RealMultimapProvider(dependencies, multimapProvider)); - } - - @Override public int hashCode() { - return multimapKey.hashCode(); - } - - @Override public boolean equals(Object o) { - return o instanceof MultimapBinder - && ((MultimapBinder) o).multimapKey.equals(multimapKey); - } - - final class RealProviderMultimapProvider - extends RealMapBinderProviderWithDependencies>>> { - private final ImmutableSet> dependencies; - private final Provider>>> entrySetProvider; - private Map>> providerMultimap; - - private RealProviderMultimapProvider(ImmutableSet> dependencies, - Provider>>> entrySetProvider) { - super(multimapKey); - this.dependencies = dependencies; - this.entrySetProvider = entrySetProvider; - } - - @SuppressWarnings("unused") - @Inject void initialize(Injector injector) { - Map>> providerMultimapMutable = - new LinkedHashMap>>(); - for (Entry> entry : entrySetProvider.get()) { - if (!providerMultimapMutable.containsKey(entry.getKey())) { - providerMultimapMutable.put( - entry.getKey(), ImmutableSet.>builder()); - } - providerMultimapMutable.get(entry.getKey()).add(entry.getValue()); - } - - ImmutableMap.Builder>> providerMultimapBuilder = - ImmutableMap.builder(); - for (Entry>> entry - : providerMultimapMutable.entrySet()) { - providerMultimapBuilder.put(entry.getKey(), entry.getValue().build()); - } - providerMultimap = providerMultimapBuilder.build(); - } - - @Override public Map>> get() { - return providerMultimap; - } - - @Override public Set> getDependencies() { - return dependencies; - } - } - - final class RealMultimapProvider - extends RealMapBinderProviderWithDependencies>> { - private final ImmutableSet> dependencies; - private final Provider>>> multimapProvider; - - RealMultimapProvider( - ImmutableSet> dependencies, - Provider>>> multimapProvider) { - super(multimapKey); - this.dependencies = dependencies; - this.multimapProvider = multimapProvider; - } - - @Override public Map> get() { - ImmutableMap.Builder> multimapBuilder = ImmutableMap.builder(); - for (Entry>> entry : multimapProvider.get().entrySet()) { - K key = entry.getKey(); - ImmutableSet.Builder valuesBuilder = ImmutableSet.builder(); - for (Provider valueProvider : entry.getValue()) { - V value = valueProvider.get(); - checkConfiguration(value != null, - "Multimap injection failed due to null value for key \"%s\"", key); - valuesBuilder.add(value); - } - multimapBuilder.put(key, valuesBuilder.build()); - } - return multimapBuilder.build(); - } - - @Override public Set> getDependencies() { - return dependencies; - } - } - } - - static final class ValueProvider implements Provider { - private final Provider delegate; - private final Binding binding; - - ValueProvider(Provider delegate, Binding binding) { - this.delegate = delegate; - this.binding = binding; - } - - @Override public V get() { - return delegate.get(); - } - - public Binding getValueBinding() { - return binding; - } - } - - /** - * A Provider that Map.Entry that is also a Provider. The key is the entry in the - * map this corresponds to and the value is the provider of the user's binding. - * This returns itself as the Provider.get value. - */ - static final class ProviderMapEntry implements - ProviderWithDependencies>>, Map.Entry> { - private final K key; - private final Provider provider; - private final Key valueKey; - - private ProviderMapEntry(K key, Provider provider, Key valueKey) { - this.key = key; - this.provider = provider; - this.valueKey = valueKey; - } - - @Override public Entry> get() { - return this; - } - - @Override public Set> getDependencies() { - return ((HasDependencies) provider).getDependencies(); - } - - public Key getValueKey() { - return valueKey; - } - - @Override public K getKey() { - return key; - } - - @Override public Provider getValue() { - return provider; - } - - @Override public Provider setValue(Provider value) { - throw new UnsupportedOperationException(); - } - - @Override public boolean equals(Object obj) { - if (obj instanceof Map.Entry) { - Map.Entry o = (Map.Entry)obj; - return Objects.equal(key, o.getKey()) - && Objects.equal(provider, o.getValue()); - } - return false; - } - - @Override public int hashCode() { - return key.hashCode() ^ provider.hashCode(); - } - - @Override public String toString() { - return "ProviderMapEntry(" + key + ", " + provider + ")"; - } - } - - private static abstract class RealMapWithExtensionProvider - extends RealMapBinderProviderWithDependencies - implements ProviderWithExtensionVisitor, MapBinderBinding { - public RealMapWithExtensionProvider(Object equality) { - super(equality); - } - } - - /** - * A base class for ProviderWithDependencies that need equality - * based on a specific object. - */ - private static abstract class RealMapBinderProviderWithDependencies implements ProviderWithDependencies { - private final Object equality; - - public RealMapBinderProviderWithDependencies(Object equality) { - this.equality = equality; - } - - @Override - public boolean equals(Object obj) { - return this.getClass() == obj.getClass() && - equality.equals(((RealMapBinderProviderWithDependencies)obj).equality); - } - - @Override - public int hashCode() { - return equality.hashCode(); - } - } - - private Multimap newLinkedKeyArrayValueMultimap() { - return Multimaps.newListMultimap( - new LinkedHashMap>(), - new Supplier>() { - @Override public List get() { - return Lists.newArrayList(); - } - }); - } - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Allows users define customized key type annotations for map bindings by annotating an annotation - * of a {@code Map}'s key type. The custom key annotation can be applied to methods also annotated - * with {@literal @}{@link ProvidesIntoMap}. - * - *

    A {@link StringMapKey} and {@link ClassMapKey} are provided for convenience with maps whose - * keys are strings or classes. For maps with enums or primitive types as keys, you must provide - * your own MapKey annotation, such as this one for an enum: - * - *

    - * {@literal @}MapKey(unwrapValue = true)
    - * {@literal @}Retention(RUNTIME)
    - * public {@literal @}interface MyCustomEnumKey {
    - *   MyCustomEnum value();
    - * }
    - * 
    - * - * You can also use the whole annotation as the key, if {@code unwrapValue=false}. - * When unwrapValue is false, the annotation type will be the key type for the injected map and - * the annotation instances will be the key values. If {@code unwrapValue=true}, the value() type - * will be the key type for injected map and the value() instances will be the keys values. - * - * @since 4.0 - */ -@Documented -@Target(ANNOTATION_TYPE) -@Retention(RUNTIME) -public @interface MapKey { - /** - * if {@code unwrapValue} is false, then the whole annotation will be the type and annotation - * instances will be the keys. If {@code unwrapValue} is true, the value() type of key type - * annotation will be the key type for injected map and the value instances will be the keys. - */ - boolean unwrapValue() default true; -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/** - * Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.Binding; -import com.google.inject.Key; -import com.google.inject.TypeLiteral; -import com.google.inject.spi.Element; -import com.google.inject.spi.Elements; - -import java.util.List; - -/** - * A binding for a Multibinder. - * - * @param The fully qualified type of the set, including Set. For example: - * MultibinderBinding<Set<Boolean>> - * - * @since 3.0 - * @author sameb@google.com (Sam Berlin) - */ -public interface MultibinderBinding { - - /** Returns the key for the set. */ - Key getSetKey(); - - /** - * Returns the TypeLiteral that describes the type of elements in the set. - *

    - * The elements will always match the type Set's generic type. For example, if getSetKey returns a - * key of Set<String>, then this will always return a - * TypeLiteral<String>. - */ - TypeLiteral getElementTypeLiteral(); - - /** - * Returns all bindings that make up the set. This is only supported on bindings returned from an - * injector. This will throw {@link UnsupportedOperationException} if it is called on an element - * retrieved from {@link Elements#getElements}. - *

    - * The elements will always match the type Set's generic type. For example, if getSetKey returns a - * key of Set<String>, then this will always return a list of type - * List<Binding<String>>. - */ - List> getElements(); - - /** - * Returns true if the multibinder permits duplicates. This is only supported on bindings returned - * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a - * MultibinderBinding retrieved from {@link Elements#getElements}. - */ - boolean permitsDuplicates(); - - /** - * Returns true if this Multibinder uses the given Element. This will be true for bindings that - * derive the elements of the set and other bindings that Multibinder uses internally. This will - * work for MultibinderBindings retrieved from an injector and {@link Elements#getElements}. - * Usually this is only necessary if you are working with elements retrieved from modules (without - * an Injector), otherwise {@link #getElements} and {@link #permitsDuplicates} are better options. - *

    - * If you need to introspect the details of the set, such as the values or if it permits - * duplicates, it is necessary to pass the elements through an Injector and use - * {@link #getElements()} and {@link #permitsDuplicates()}. - */ - boolean containsElement(Element element); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,575 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.common.base.Predicates.equalTo; -import static com.google.common.primitives.Ints.MAX_POWER_OF_TWO; -import static com.google.common.collect.Iterables.filter; -import static com.google.common.collect.Iterables.getOnlyElement; -import static com.google.inject.multibindings.Element.Type.MULTIBINDER; -import static com.google.inject.name.Names.named; - -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.inject.AbstractModule; -import com.google.inject.Binder; -import com.google.inject.Binding; -import com.google.inject.ConfigurationException; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.TypeLiteral; -import com.google.inject.binder.LinkedBindingBuilder; -import com.google.inject.internal.Errors; -import com.google.inject.spi.BindingTargetVisitor; -import com.google.inject.spi.Dependency; -import com.google.inject.spi.HasDependencies; -import com.google.inject.spi.Message; -import com.google.inject.spi.ProviderInstanceBinding; -import com.google.inject.spi.ProviderWithDependencies; -import com.google.inject.spi.ProviderWithExtensionVisitor; -import com.google.inject.spi.Toolable; -import com.google.inject.util.Types; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * An API to bind multiple values separately, only to later inject them as a - * complete collection. Multibinder is intended for use in your application's - * module: - *

    
    - * public class SnacksModule extends AbstractModule {
    - *   protected void configure() {
    - *     Multibinder<Snack> multibinder
    - *         = Multibinder.newSetBinder(binder(), Snack.class);
    - *     multibinder.addBinding().toInstance(new Twix());
    - *     multibinder.addBinding().toProvider(SnickersProvider.class);
    - *     multibinder.addBinding().to(Skittles.class);
    - *   }
    - * }
    - * - *

    With this binding, a {@link Set}{@code } can now be injected: - *

    
    - * class SnackMachine {
    - *   {@literal @}Inject
    - *   public SnackMachine(Set<Snack> snacks) { ... }
    - * }
    - * - * If desired, {@link Collection}{@code >} can also be injected. - * - *

    Contributing multibindings from different modules is supported. For - * example, it is okay for both {@code CandyModule} and {@code ChipsModule} - * to create their own {@code Multibinder}, and to each contribute - * bindings to the set of snacks. When that set is injected, it will contain - * elements from both modules. - * - *

    The set's iteration order is consistent with the binding order. This is - * convenient when multiple elements are contributed by the same module because - * that module can order its bindings appropriately. Avoid relying on the - * iteration order of elements contributed by different modules, since there is - * no equivalent mechanism to order modules. - * - *

    The set is unmodifiable. Elements can only be added to the set by - * configuring the multibinder. Elements can never be removed from the set. - * - *

    Elements are resolved at set injection time. If an element is bound to a - * provider, that provider's get method will be called each time the set is - * injected (unless the binding is also scoped). - * - *

    Annotations are be used to create different sets of the same element - * type. Each distinct annotation gets its own independent collection of - * elements. - * - *

    Elements must be distinct. If multiple bound elements - * have the same value, set injection will fail. - * - *

    Elements must be non-null. If any set element is null, - * set injection will fail. - * - * @author jessewilson@google.com (Jesse Wilson) - */ -public abstract class Multibinder { - private Multibinder() {} - - /** - * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is - * itself bound with no binding annotation. - */ - public static Multibinder newSetBinder(Binder binder, TypeLiteral type) { - return newRealSetBinder(binder, Key.get(type)); - } - - /** - * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is - * itself bound with no binding annotation. - */ - public static Multibinder newSetBinder(Binder binder, Class type) { - return newRealSetBinder(binder, Key.get(type)); - } - - /** - * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is - * itself bound with {@code annotation}. - */ - public static Multibinder newSetBinder( - Binder binder, TypeLiteral type, Annotation annotation) { - return newRealSetBinder(binder, Key.get(type, annotation)); - } - - /** - * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is - * itself bound with {@code annotation}. - */ - public static Multibinder newSetBinder( - Binder binder, Class type, Annotation annotation) { - return newRealSetBinder(binder, Key.get(type, annotation)); - } - - /** - * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is - * itself bound with {@code annotationType}. - */ - public static Multibinder newSetBinder(Binder binder, TypeLiteral type, - Class annotationType) { - return newRealSetBinder(binder, Key.get(type, annotationType)); - } - - /** - * Returns a new multibinder that collects instances of the key's type in a {@link Set} that is - * itself bound with the annotation (if any) of the key. - * @since 4.0 - */ - public static Multibinder newSetBinder(Binder binder, Key key) { - return newRealSetBinder(binder, key); - } - - /** - * Implementation of newSetBinder. - */ - static RealMultibinder newRealSetBinder(Binder binder, Key key) { - binder = binder.skipSources(RealMultibinder.class, Multibinder.class); - RealMultibinder result = new RealMultibinder(binder, key.getTypeLiteral(), - key.ofType(setOf(key.getTypeLiteral()))); - binder.install(result); - return result; - } - - /** - * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is - * itself bound with {@code annotationType}. - */ - public static Multibinder newSetBinder(Binder binder, Class type, - Class annotationType) { - return newSetBinder(binder, Key.get(type, annotationType)); - } - - @SuppressWarnings("unchecked") // wrapping a T in a Set safely returns a Set - static TypeLiteral> setOf(TypeLiteral elementType) { - Type type = Types.setOf(elementType.getType()); - return (TypeLiteral>) TypeLiteral.get(type); - } - - @SuppressWarnings("unchecked") - static TypeLiteral>> collectionOfProvidersOf( - TypeLiteral elementType) { - Type providerType = Types.providerOf(elementType.getType()); - Type type = Types.newParameterizedType(Collection.class, providerType); - return (TypeLiteral>>) TypeLiteral.get(type); - } - - @SuppressWarnings("unchecked") - static TypeLiteral>> collectionOfJavaxProvidersOf( - TypeLiteral elementType) { - Type providerType = - Types.newParameterizedType(javax.inject.Provider.class, elementType.getType()); - Type type = Types.newParameterizedType(Collection.class, providerType); - return (TypeLiteral>>) TypeLiteral.get(type); - } - - /** - * Configures the bound set to silently discard duplicate elements. When multiple equal values are - * bound, the one that gets included is arbitrary. When multiple modules contribute elements to - * the set, this configuration option impacts all of them. - * - * @return this multibinder - * @since 3.0 - */ - public abstract Multibinder permitDuplicates(); - - /** - * Returns a binding builder used to add a new element in the set. Each - * bound element must have a distinct value. Bound providers will be - * evaluated each time the set is injected. - * - *

    It is an error to call this method without also calling one of the - * {@code to} methods on the returned binding builder. - * - *

    Scoping elements independently is supported. Use the {@code in} method - * to specify a binding scope. - */ - public abstract LinkedBindingBuilder addBinding(); - - /** - * The actual multibinder plays several roles: - * - *

    As a Multibinder, it acts as a factory for LinkedBindingBuilders for - * each of the set's elements. Each binding is given an annotation that - * identifies it as a part of this set. - * - *

    As a Module, it installs the binding to the set itself. As a module, - * this implements equals() and hashcode() in order to trick Guice into - * executing its configure() method only once. That makes it so that - * multiple multibinders can be created for the same target collection, but - * only one is bound. Since the list of bindings is retrieved from the - * injector itself (and not the multibinder), each multibinder has access to - * all contributions from all multibinders. - * - *

    As a Provider, this constructs the set instances. - * - *

    We use a subclass to hide 'implements Module, Provider' from the public - * API. - */ - static final class RealMultibinder extends Multibinder - implements Module, ProviderWithExtensionVisitor>, HasDependencies, - MultibinderBinding> { - - private final TypeLiteral elementType; - private final String setName; - private final Key> setKey; - private final Key>> collectionOfProvidersKey; - private final Key>> collectionOfJavaxProvidersKey; - private final Key permitDuplicatesKey; - - /* the target injector's binder. non-null until initialization, null afterwards */ - private Binder binder; - - /* a binding for each element in the set. null until initialization, non-null afterwards */ - private ImmutableList> bindings; - private Set> dependencies; - - /** whether duplicates are allowed. Possibly configured by a different instance */ - private boolean permitDuplicates; - - private RealMultibinder(Binder binder, TypeLiteral elementType, Key> setKey) { - this.binder = checkNotNull(binder, "binder"); - this.elementType = checkNotNull(elementType, "elementType"); - this.setKey = checkNotNull(setKey, "setKey"); - this.collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); - this.collectionOfJavaxProvidersKey = setKey.ofType(collectionOfJavaxProvidersOf(elementType)); - this.setName = RealElement.nameOf(setKey); - this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates")); - } - - public void configure(Binder binder) { - checkConfiguration(!isInitialized(), "Multibinder was already initialized"); - - binder.bind(setKey).toProvider(this); - binder.bind(collectionOfProvidersKey).toProvider( - new RealMultibinderCollectionOfProvidersProvider()); - - // The collection this exposes is internally an ImmutableList, so it's OK to massage - // the guice Provider to javax Provider in the value (since the guice Provider implements - // javax Provider). - @SuppressWarnings("unchecked") - Key key = (Key) collectionOfProvidersKey; - binder.bind(collectionOfJavaxProvidersKey).to(key); - } - - @Override public Multibinder permitDuplicates() { - binder.install(new PermitDuplicatesModule(permitDuplicatesKey)); - return this; - } - - Key getKeyForNewItem() { - checkConfiguration(!isInitialized(), "Multibinder was already initialized"); - return Key.get(elementType, new RealElement(setName, MULTIBINDER, "")); - } - - @Override public LinkedBindingBuilder addBinding() { - return binder.bind(getKeyForNewItem()); - } - - /** - * Invoked by Guice at Injector-creation time to prepare providers for each - * element in this set. At this time the set's size is known, but its - * contents are only evaluated when get() is invoked. - */ - @Toolable @Inject void initialize(Injector injector) { - List> bindings = Lists.newArrayList(); - Set index = Sets.newHashSet(); - Indexer indexer = new Indexer(injector); - List> dependencies = Lists.newArrayList(); - for (Binding entry : injector.findBindingsByType(elementType)) { - if (keyMatches(entry.getKey())) { - @SuppressWarnings("unchecked") // protected by findBindingsByType() - Binding binding = (Binding) entry; - if (index.add(binding.acceptTargetVisitor(indexer))) { - bindings.add(binding); - dependencies.add(Dependency.get(binding.getKey())); - } - } - } - - this.bindings = ImmutableList.copyOf(bindings); - this.dependencies = ImmutableSet.copyOf(dependencies); - this.permitDuplicates = permitsDuplicates(injector); - this.binder = null; - } - - // This is forked from com.google.common.collect.Maps.capacity - private static int mapCapacity(int numBindings) { - if (numBindings < 3) { - return numBindings + 1; - } else if (numBindings < MAX_POWER_OF_TWO) { - return (int) (numBindings / 0.75F + 1.0F); - } - return Integer.MAX_VALUE; - } - - boolean permitsDuplicates(Injector injector) { - return injector.getBindings().containsKey(permitDuplicatesKey); - } - - private boolean keyMatches(Key key) { - return key.getTypeLiteral().equals(elementType) - && key.getAnnotation() instanceof Element - && ((Element) key.getAnnotation()).setName().equals(setName) - && ((Element) key.getAnnotation()).type() == MULTIBINDER; - } - - private boolean isInitialized() { - return binder == null; - } - - public Set get() { - checkConfiguration(isInitialized(), "Multibinder is not initialized"); - - Map> result = new LinkedHashMap>(mapCapacity(bindings.size())); - for (Binding binding : bindings) { - final T newValue = binding.getProvider().get(); - checkConfiguration(newValue != null, - "Set injection failed due to null element bound at: %s", - binding.getSource()); - Binding duplicateBinding = result.put(newValue, binding); - if (!permitDuplicates && duplicateBinding != null) { - throw newDuplicateValuesException(result, binding, newValue, duplicateBinding); - } - } - return ImmutableSet.copyOf(result.keySet()); - } - - @SuppressWarnings("unchecked") - public V acceptExtensionVisitor( - BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - if (visitor instanceof MultibindingsTargetVisitor) { - return ((MultibindingsTargetVisitor, V>) visitor).visit(this); - } else { - return visitor.visit(binding); - } - } - - String getSetName() { - return setName; - } - - public TypeLiteral getElementTypeLiteral() { - return elementType; - } - - public Key> getSetKey() { - return setKey; - } - - @SuppressWarnings("unchecked") - public List> getElements() { - if (isInitialized()) { - return (List>) (List) bindings; // safe because bindings is immutable. - } else { - throw new UnsupportedOperationException("getElements() not supported for module bindings"); - } - } - - public boolean permitsDuplicates() { - if (isInitialized()) { - return permitDuplicates; - } else { - throw new UnsupportedOperationException( - "permitsDuplicates() not supported for module bindings"); - } - } - - public boolean containsElement(com.google.inject.spi.Element element) { - if (element instanceof Binding) { - Binding binding = (Binding) element; - return keyMatches(binding.getKey()) - || binding.getKey().equals(permitDuplicatesKey) - || binding.getKey().equals(setKey) - || binding.getKey().equals(collectionOfProvidersKey) - || binding.getKey().equals(collectionOfJavaxProvidersKey); - } else { - return false; - } - } - - public Set> getDependencies() { - if (!isInitialized()) { - return ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); - } else { - return dependencies; - } - } - - @Override public boolean equals(Object o) { - return o instanceof RealMultibinder - && ((RealMultibinder) o).setKey.equals(setKey); - } - - @Override public int hashCode() { - return setKey.hashCode(); - } - - @Override public String toString() { - return (setName.isEmpty() ? "" : setName + " ") + "Multibinder<" + elementType + ">"; - } - - final class RealMultibinderCollectionOfProvidersProvider - implements ProviderWithDependencies>> { - @Override public Collection> get() { - checkConfiguration(isInitialized(), "Multibinder is not initialized"); - int size = bindings.size(); - @SuppressWarnings("unchecked") // safe because we only put Provider into it. - Provider[] providers = new Provider[size]; - for (int i = 0; i < size; i++) { - providers[i] = bindings.get(i).getProvider(); - } - return ImmutableList.copyOf(providers); - } - - @Override public Set> getDependencies() { - if (!isInitialized()) { - return ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); - } - ImmutableSet.Builder> setBuilder = ImmutableSet.builder(); - for (Dependency dependency : dependencies) { - Key key = dependency.getKey(); - setBuilder.add( - Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType())))); - } - return setBuilder.build(); - } - - Key getCollectionKey() { - return RealMultibinder.this.collectionOfProvidersKey; - } - - @Override public boolean equals(Object o) { - return o instanceof Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider - && ((Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider) o) - .getCollectionKey().equals(getCollectionKey()); - } - - @Override public int hashCode() { - return getCollectionKey().hashCode(); - } - } - } - - /** - * We install the permit duplicates configuration as its own binding, all by itself. This way, - * if only one of a multibinder's users remember to call permitDuplicates(), they're still - * permitted. - */ - private static class PermitDuplicatesModule extends AbstractModule { - private final Key key; - - PermitDuplicatesModule(Key key) { - this.key = key; - } - - @Override protected void configure() { - bind(key).toInstance(true); - } - - @Override public boolean equals(Object o) { - return o instanceof PermitDuplicatesModule - && ((PermitDuplicatesModule) o).key.equals(key); - } - - @Override public int hashCode() { - return getClass().hashCode() ^ key.hashCode(); - } - } - - static void checkConfiguration(boolean condition, String format, Object... args) { - if (condition) { - return; - } - - throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args)))); - } - - private static ConfigurationException newDuplicateValuesException( - Map> existingBindings, - Binding binding, - final T newValue, - Binding duplicateBinding) { - T oldValue = getOnlyElement(filter(existingBindings.keySet(), equalTo(newValue))); - String oldString = oldValue.toString(); - String newString = newValue.toString(); - if (Objects.equal(oldString, newString)) { - // When the value strings match, just show the source of the bindings - return new ConfigurationException(ImmutableSet.of(new Message(Errors.format( - "Set injection failed due to duplicated element \"%s\"" - + "\n Bound at %s\n Bound at %s", - newValue, - duplicateBinding.getSource(), - binding.getSource())))); - } else { - // When the value strings don't match, include them both as they may be useful for debugging - return new ConfigurationException(ImmutableSet.of(new Message(Errors.format( - "Set injection failed due to multiple elements comparing equal:" - + "\n \"%s\"\n bound at %s" - + "\n \"%s\"\n bound at %s", - oldValue, - duplicateBinding.getSource(), - newValue, - binding.getSource())))); - } - } - - static T checkNotNull(T reference, String name) { - if (reference != null) { - return reference; - } - - NullPointerException npe = new NullPointerException(name); - throw new ConfigurationException(ImmutableSet.of( - new Message(npe.toString(), npe))); - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.common.collect.ImmutableSet; -import com.google.inject.AbstractModule; -import com.google.inject.Binder; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.TypeLiteral; -import com.google.inject.spi.InjectionPoint; -import com.google.inject.spi.ModuleAnnotatedMethodScanner; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Set; - -/** - * Scans a module for annotations that signal multibindings, mapbindings, and optional bindings. - * - * @since 4.0 - */ -public class MultibindingsScanner { - - private MultibindingsScanner() {} - - /** - * Returns a module that, when installed, will scan all modules for methods with the annotations - * {@literal @}{@link ProvidesIntoMap}, {@literal @}{@link ProvidesIntoSet}, and - * {@literal @}{@link ProvidesIntoOptional}. - * - *

    This is a convenience method, equivalent to doing - * {@code binder().scanModulesForAnnotatedMethods(MultibindingsScanner.scanner())}. - */ - public static Module asModule() { - return new AbstractModule() { - @Override protected void configure() { - binder().scanModulesForAnnotatedMethods(Scanner.INSTANCE); - } - }; - } - - /** - * Returns a {@link ModuleAnnotatedMethodScanner} that, when bound, will scan all modules for - * methods with the annotations {@literal @}{@link ProvidesIntoMap}, - * {@literal @}{@link ProvidesIntoSet}, and {@literal @}{@link ProvidesIntoOptional}. - */ - public static ModuleAnnotatedMethodScanner scanner() { - return Scanner.INSTANCE; - } - - private static class Scanner extends ModuleAnnotatedMethodScanner { - private static final Scanner INSTANCE = new Scanner(); - - @Override - public Set> annotationClasses() { - return ImmutableSet.of( - ProvidesIntoSet.class, ProvidesIntoMap.class, ProvidesIntoOptional.class); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) // mapKey doesn't know its key type - @Override - public Key prepareMethod(Binder binder, Annotation annotation, Key key, - InjectionPoint injectionPoint) { - Method method = (Method) injectionPoint.getMember(); - AnnotationOrError mapKey = findMapKeyAnnotation(binder, method); - if (annotation instanceof ProvidesIntoSet) { - if (mapKey.annotation != null) { - binder.addError("Found a MapKey annotation on non map binding at %s.", method); - } - return Multibinder.newRealSetBinder(binder, key).getKeyForNewItem(); - } else if (annotation instanceof ProvidesIntoMap) { - if (mapKey.error) { - // Already failed on the MapKey, don't bother doing more work. - return key; - } - if (mapKey.annotation == null) { - // If no MapKey, make an error and abort. - binder.addError("No MapKey found for map binding at %s.", method); - return key; - } - TypeAndValue typeAndValue = typeAndValueOfMapKey(mapKey.annotation); - return MapBinder.newRealMapBinder(binder, typeAndValue.type, key) - .getKeyForNewValue(typeAndValue.value); - } else if (annotation instanceof ProvidesIntoOptional) { - if (mapKey.annotation != null) { - binder.addError("Found a MapKey annotation on non map binding at %s.", method); - } - switch (((ProvidesIntoOptional)annotation).value()) { - case DEFAULT: - return OptionalBinder.newRealOptionalBinder(binder, key).getKeyForDefaultBinding(); - case ACTUAL: - return OptionalBinder.newRealOptionalBinder(binder, key).getKeyForActualBinding(); - } - } - throw new IllegalStateException("Invalid annotation: " + annotation); - } - } - - private static class AnnotationOrError { - final Annotation annotation; - final boolean error; - AnnotationOrError(Annotation annotation, boolean error) { - this.annotation = annotation; - this.error = error; - } - - static AnnotationOrError forPossiblyNullAnnotation(Annotation annotation) { - return new AnnotationOrError(annotation, false); - } - - static AnnotationOrError forError() { - return new AnnotationOrError(null, true); - } - } - - private static AnnotationOrError findMapKeyAnnotation(Binder binder, Method method) { - Annotation foundAnnotation = null; - for (Annotation annotation : method.getAnnotations()) { - MapKey mapKey = annotation.annotationType().getAnnotation(MapKey.class); - if (mapKey != null) { - if (foundAnnotation != null) { - binder.addError("Found more than one MapKey annotations on %s.", method); - return AnnotationOrError.forError(); - } - if (mapKey.unwrapValue()) { - try { - // validate there's a declared method called "value" - Method valueMethod = annotation.annotationType().getDeclaredMethod("value"); - if (valueMethod.getReturnType().isArray()) { - binder.addError("Array types are not allowed in a MapKey with unwrapValue=true: %s", - annotation.annotationType()); - return AnnotationOrError.forError(); - } - } catch (NoSuchMethodException invalid) { - binder.addError("No 'value' method in MapKey with unwrapValue=true: %s", - annotation.annotationType()); - return AnnotationOrError.forError(); - } - } - foundAnnotation = annotation; - } - } - return AnnotationOrError.forPossiblyNullAnnotation(foundAnnotation); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - static TypeAndValue typeAndValueOfMapKey(Annotation mapKeyAnnotation) { - if (!mapKeyAnnotation.annotationType().getAnnotation(MapKey.class).unwrapValue()) { - return new TypeAndValue(TypeLiteral.get(mapKeyAnnotation.annotationType()), mapKeyAnnotation); - } else { - try { - Method valueMethod = mapKeyAnnotation.annotationType().getDeclaredMethod("value"); - valueMethod.setAccessible(true); - TypeLiteral returnType = - TypeLiteral.get(mapKeyAnnotation.annotationType()).getReturnType(valueMethod); - return new TypeAndValue(returnType, valueMethod.invoke(mapKeyAnnotation)); - } catch (NoSuchMethodException e) { - throw new IllegalStateException(e); - } catch (SecurityException e) { - throw new IllegalStateException(e); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); - } catch (InvocationTargetException e) { - throw new IllegalStateException(e); - } - } - } - - private static class TypeAndValue { - final TypeLiteral type; - final T value; - - TypeAndValue(TypeLiteral type, T value) { - this.type = type; - this.value = value; - } - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/** - * Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.spi.BindingTargetVisitor; - -/** - * A visitor for the multibinder extension. - *

    - * If your {@link BindingTargetVisitor} implements this interface, bindings created by using - * {@link Multibinder}, {@link MapBinder} or {@link OptionalBinderBinding} will be visited through - * this interface. - * - * @since 3.0 - * @author sameb@google.com (Sam Berlin) - */ -public interface MultibindingsTargetVisitor extends BindingTargetVisitor { - - /** - * Visits a binding created through {@link Multibinder}. - */ - V visit(MultibinderBinding multibinding); - - /** - * Visits a binding created through {@link MapBinder}. - */ - V visit(MapBinderBinding mapbinding); - - /** - * Visits a binding created through {@link OptionalBinder}. - * - * @since 4.0 - */ - V visit(OptionalBinderBinding optionalbinding); - -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/** - * Copyright (C) 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.Binding; -import com.google.inject.Key; -import com.google.inject.spi.Element; -import com.google.inject.spi.Elements; - -/** - * A binding for a OptionalBinder. - * - *

    Although OptionalBinders may be injected through a variety of types - * {@code T}, {@code Optional}, {@code Optional>}, etc..), an - * OptionalBinderBinding exists only on the Binding associated with the - * {@code Optional} key. Other bindings can be validated to be derived from this - * OptionalBinderBinding using {@link #containsElement}. - * - * @param The fully qualified type of the optional binding, including Optional. - * For example: {@code Optional}. - * - * @since 4.0 - * @author sameb@google.com (Sam Berlin) - */ -public interface OptionalBinderBinding { - - /** Returns the {@link Key} for this binding. */ - Key getKey(); - - /** - * Returns the default binding (set by {@link OptionalBinder#setDefault}) if one exists or null - * if no default binding is set. This will throw {@link UnsupportedOperationException} if it is - * called on an element retrieved from {@link Elements#getElements}. - *

    - * The Binding's type will always match the type Optional's generic type. For example, if getKey - * returns a key of Optional<String>, then this will always return a - * Binding<String>. - */ - Binding getDefaultBinding(); - - /** - * Returns the actual binding (set by {@link OptionalBinder#setBinding}) or null if not set. - * This will throw {@link UnsupportedOperationException} if it is called on an element retrieved - * from {@link Elements#getElements}. - *

    - * The Binding's type will always match the type Optional's generic type. For example, if getKey - * returns a key of Optional<String>, then this will always return a - * Binding<String>. - */ - Binding getActualBinding(); - - /** - * Returns true if this OptionalBinder contains the given Element in order to build the optional - * binding or uses the given Element in order to support building and injecting its data. This - * will work for OptionalBinderBinding retrieved from an injector and - * {@link Elements#getElements}. Usually this is only necessary if you are working with elements - * retrieved from modules (without an Injector), otherwise {@link #getDefaultBinding} and - * {@link #getActualBinding} are better options. - */ - boolean containsElement(Element element); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,754 +0,0 @@ -/** - * Copyright (C) 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static com.google.inject.multibindings.Multibinder.checkConfiguration; -import static com.google.inject.util.Types.newParameterizedType; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.common.base.Optional; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableSet; -import com.google.inject.Binder; -import com.google.inject.Binding; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.TypeLiteral; -import com.google.inject.binder.LinkedBindingBuilder; -import com.google.inject.spi.BindingTargetVisitor; -import com.google.inject.spi.Dependency; -import com.google.inject.spi.Element; -import com.google.inject.spi.ProviderInstanceBinding; -import com.google.inject.spi.ProviderLookup; -import com.google.inject.spi.ProviderWithDependencies; -import com.google.inject.spi.ProviderWithExtensionVisitor; -import com.google.inject.spi.Toolable; -import com.google.inject.util.Types; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.annotation.Retention; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.Set; - -import javax.inject.Qualifier; - - -/** - * An API to bind optional values, optionally with a default value. - * OptionalBinder fulfills two roles:

      - *
    1. It allows a framework to define an injection point that may or - * may not be bound by users. - *
    2. It allows a framework to supply a default value that can be changed - * by users. - *
    - * - *

    When an OptionalBinder is added, it will always supply the bindings: - * {@code Optional} and {@code Optional>}. If - * {@link #setBinding} or {@link #setDefault} are called, it will also - * bind {@code T}. - * - *

    {@code setDefault} is intended for use by frameworks that need a default - * value. User code can call {@code setBinding} to override the default. - * Warning: Even if setBinding is called, the default binding - * will still exist in the object graph. If it is a singleton, it will be - * instantiated in {@code Stage.PRODUCTION}. - * - *

    If setDefault or setBinding are linked to Providers, the Provider may return - * {@code null}. If it does, the Optional bindings will be absent. Binding - * setBinding to a Provider that returns null will not cause OptionalBinder - * to fall back to the setDefault binding. - * - *

    If neither setDefault nor setBinding are called, it will try to link to a - * user-supplied binding of the same type. If no binding exists, the optionals - * will be absent. Otherwise, if a user-supplied binding of that type exists, - * or if setBinding or setDefault are called, the optionals will return present - * if they are bound to a non-null value. - * - *

    Values are resolved at injection time. If a value is bound to a - * provider, that provider's get method will be called each time the optional - * is injected (unless the binding is also scoped, or an optional of provider is - * injected). - * - *

    Annotations are used to create different optionals of the same key/value - * type. Each distinct annotation gets its own independent binding. - * - *

    
    - * public class FrameworkModule extends AbstractModule {
    - *   protected void configure() {
    - *     OptionalBinder.newOptionalBinder(binder(), Renamer.class);
    - *   }
    - * }
    - * - *

    With this module, an {@link Optional}{@code } can now be - * injected. With no other bindings, the optional will be absent. - * Users can specify bindings in one of two ways: - * - *

    Option 1: - *

    
    - * public class UserRenamerModule extends AbstractModule {
    - *   protected void configure() {
    - *     bind(Renamer.class).to(ReplacingRenamer.class);
    - *   }
    - * }
    - * - *

    or Option 2: - *

    
    - * public class UserRenamerModule extends AbstractModule {
    - *   protected void configure() {
    - *     OptionalBinder.newOptionalBinder(binder(), Renamer.class)
    - *         .setBinding().to(ReplacingRenamer.class);
    - *   }
    - * }
    - * With both options, the {@code Optional} will be present and supply the - * ReplacingRenamer. - * - *

    Default values can be supplied using: - *

    
    - * public class FrameworkModule extends AbstractModule {
    - *   protected void configure() {
    - *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
    - *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
    - *   }
    - * }
    - * With the above module, code can inject an {@code @LookupUrl String} and it - * will supply the DEFAULT_LOOKUP_URL. A user can change this value by binding - *
    
    - * public class UserLookupModule extends AbstractModule {
    - *   protected void configure() {
    - *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
    - *         .setBinding().toInstance(CUSTOM_LOOKUP_URL);
    - *   }
    - * }
    - * ... which will override the default value. - * - *

    If one module uses setDefault the only way to override the default is to use setBinding. - * It is an error for a user to specify the binding without using OptionalBinder if - * setDefault or setBinding are called. For example, - *

    
    - * public class FrameworkModule extends AbstractModule {
    - *   protected void configure() {
    - *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
    - *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
    - *   }
    - * }
    - * public class UserLookupModule extends AbstractModule {
    - *   protected void configure() {
    - *     bind(Key.get(String.class, LookupUrl.class)).toInstance(CUSTOM_LOOKUP_URL);
    - *   } 
    - * }
    - * ... would generate an error, because both the framework and the user are trying to bind - * {@code @LookupUrl String}. - * - * @author sameb@google.com (Sam Berlin) - * @since 4.0 - */ -public abstract class OptionalBinder { - - /* Reflectively capture java 8's Optional types so we can bind them if we're running in java8. */ - private static final Class JAVA_OPTIONAL_CLASS; - private static final Method JAVA_EMPTY_METHOD; - private static final Method JAVA_OF_NULLABLE_METHOD; - static { - Class optional = null; - Method empty = null; - Method ofNullable = null; - boolean useJavaOptional = false; - try { - optional = Class.forName("java.util.Optional"); - empty = optional.getDeclaredMethod("empty"); - ofNullable = optional.getDeclaredMethod("ofNullable", Object.class); - useJavaOptional = true; - } catch (ClassNotFoundException ignored) { - } catch (NoSuchMethodException ignored) { - } catch (SecurityException ignored) { - } - JAVA_OPTIONAL_CLASS = useJavaOptional ? optional : null; - JAVA_EMPTY_METHOD = useJavaOptional ? empty : null; - JAVA_OF_NULLABLE_METHOD = useJavaOptional ? ofNullable : null; - } - - private OptionalBinder() {} - - public static OptionalBinder newOptionalBinder(Binder binder, Class type) { - return newRealOptionalBinder(binder, Key.get(type)); - } - - public static OptionalBinder newOptionalBinder(Binder binder, TypeLiteral type) { - return newRealOptionalBinder(binder, Key.get(type)); - } - - public static OptionalBinder newOptionalBinder(Binder binder, Key type) { - return newRealOptionalBinder(binder, type); - } - - static RealOptionalBinder newRealOptionalBinder(Binder binder, Key type) { - binder = binder.skipSources(OptionalBinder.class, RealOptionalBinder.class); - RealOptionalBinder optionalBinder = new RealOptionalBinder(binder, type); - binder.install(optionalBinder); - return optionalBinder; - } - - @SuppressWarnings("unchecked") - static TypeLiteral> optionalOf( - TypeLiteral type) { - return (TypeLiteral>) TypeLiteral.get( - Types.newParameterizedType(Optional.class, type.getType())); - } - - static TypeLiteral javaOptionalOf( - TypeLiteral type) { - checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); - return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, type.getType())); - } - - @SuppressWarnings("unchecked") - static TypeLiteral>> optionalOfJavaxProvider( - TypeLiteral type) { - return (TypeLiteral>>) TypeLiteral.get( - Types.newParameterizedType(Optional.class, - newParameterizedType(javax.inject.Provider.class, type.getType()))); - } - - static TypeLiteral javaOptionalOfJavaxProvider( - TypeLiteral type) { - checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); - return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, - newParameterizedType(javax.inject.Provider.class, type.getType()))); - } - - @SuppressWarnings("unchecked") - static TypeLiteral>> optionalOfProvider(TypeLiteral type) { - return (TypeLiteral>>) TypeLiteral.get(Types.newParameterizedType( - Optional.class, newParameterizedType(Provider.class, type.getType()))); - } - - static TypeLiteral javaOptionalOfProvider(TypeLiteral type) { - checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); - return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, - newParameterizedType(Provider.class, type.getType()))); - } - - @SuppressWarnings("unchecked") - static Key> providerOf(Key key) { - Type providerT = Types.providerOf(key.getTypeLiteral().getType()); - return (Key>) key.ofType(providerT); - } - - /** - * Returns a binding builder used to set the default value that will be injected. - * The binding set by this method will be ignored if {@link #setBinding} is called. - * - *

    It is an error to call this method without also calling one of the {@code to} - * methods on the returned binding builder. - */ - public abstract LinkedBindingBuilder setDefault(); - - - /** - * Returns a binding builder used to set the actual value that will be injected. - * This overrides any binding set by {@link #setDefault}. - * - *

    It is an error to call this method without also calling one of the {@code to} - * methods on the returned binding builder. - */ - public abstract LinkedBindingBuilder setBinding(); - - enum Source { DEFAULT, ACTUAL } - - @Retention(RUNTIME) - @Qualifier - @interface Default { - String value(); - } - - @Retention(RUNTIME) - @Qualifier - @interface Actual { - String value(); - } - - /** - * The actual OptionalBinder plays several roles. It implements Module to hide that - * fact from the public API, and installs the various bindings that are exposed to the user. - */ - static final class RealOptionalBinder extends OptionalBinder implements Module { - private final Key typeKey; - private final Key> optionalKey; - private final Key>> optionalJavaxProviderKey; - private final Key>> optionalProviderKey; - private final Provider>> optionalProviderT; - private final Key defaultKey; - private final Key actualKey; - - private final Key javaOptionalKey; - private final Key javaOptionalJavaxProviderKey; - private final Key javaOptionalProviderKey; - - /** the target injector's binder. non-null until initialization, null afterwards */ - private Binder binder; - /** the default binding, for the SPI. */ - private Binding defaultBinding; - /** the actual binding, for the SPI */ - private Binding actualBinding; - - /** the dependencies -- initialized with defaults & overridden when tooled. */ - private Set> dependencies; - /** the dependencies -- initialized with defaults & overridden when tooled. */ - private Set> providerDependencies; - - private RealOptionalBinder(Binder binder, Key typeKey) { - this.binder = binder; - this.typeKey = checkNotNull(typeKey); - TypeLiteral literal = typeKey.getTypeLiteral(); - this.optionalKey = typeKey.ofType(optionalOf(literal)); - this.optionalJavaxProviderKey = typeKey.ofType(optionalOfJavaxProvider(literal)); - this.optionalProviderKey = typeKey.ofType(optionalOfProvider(literal)); - this.optionalProviderT = binder.getProvider(optionalProviderKey); - String name = RealElement.nameOf(typeKey); - this.defaultKey = Key.get(typeKey.getTypeLiteral(), new DefaultImpl(name)); - this.actualKey = Key.get(typeKey.getTypeLiteral(), new ActualImpl(name)); - // Until the injector initializes us, we don't know what our dependencies are, - // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly). - this.dependencies = ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); - this.providerDependencies = - ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); - - if (JAVA_OPTIONAL_CLASS != null) { - this.javaOptionalKey = typeKey.ofType(javaOptionalOf(literal)); - this.javaOptionalJavaxProviderKey = typeKey.ofType(javaOptionalOfJavaxProvider(literal)); - this.javaOptionalProviderKey = typeKey.ofType(javaOptionalOfProvider(literal)); - } else { - this.javaOptionalKey = null; - this.javaOptionalJavaxProviderKey = null; - this.javaOptionalProviderKey = null; - } - } - - /** - * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate - * bindings. - */ - private void addDirectTypeBinding(Binder binder) { - binder.bind(typeKey).toProvider(new RealDirectTypeProvider()); - } - - Key getKeyForDefaultBinding() { - checkConfiguration(!isInitialized(), "already initialized"); - addDirectTypeBinding(binder); - return defaultKey; - } - - @Override public LinkedBindingBuilder setDefault() { - return binder.bind(getKeyForDefaultBinding()); - } - - Key getKeyForActualBinding() { - checkConfiguration(!isInitialized(), "already initialized"); - addDirectTypeBinding(binder); - return actualKey; - } - - @Override public LinkedBindingBuilder setBinding() { - return binder.bind(getKeyForActualBinding()); - } - - @Override public void configure(Binder binder) { - checkConfiguration(!isInitialized(), "OptionalBinder was already initialized"); - - binder.bind(optionalProviderKey).toProvider(new RealOptionalProviderProvider()); - - // Optional is immutable, so it's safe to expose Optional> as - // Optional> (since Guice provider implements javax Provider). - @SuppressWarnings({"unchecked", "cast"}) - Key massagedOptionalProviderKey = (Key) optionalProviderKey; - binder.bind(optionalJavaxProviderKey).to(massagedOptionalProviderKey); - - binder.bind(optionalKey).toProvider(new RealOptionalKeyProvider()); - - // Bind the java-8 types if we know them. - bindJava8Optional(binder); - } - - @SuppressWarnings("unchecked") - private void bindJava8Optional(Binder binder) { - if (JAVA_OPTIONAL_CLASS != null) { - binder.bind(javaOptionalKey).toProvider(new JavaOptionalProvider()); - binder.bind(javaOptionalProviderKey).toProvider(new JavaOptionalProviderProvider()); - // for the javax version we reuse the guice version since they're type-compatible. - binder.bind(javaOptionalJavaxProviderKey).to(javaOptionalProviderKey); - } - } - - @SuppressWarnings("rawtypes") - final class JavaOptionalProvider extends RealOptionalBinderProviderWithDependencies - implements ProviderWithExtensionVisitor, OptionalBinderBinding { - private JavaOptionalProvider() { - super(typeKey); - } - - @Override public Object get() { - Optional> optional = optionalProviderT.get(); - try { - if (optional.isPresent()) { - return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get().get()); - } else { - return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS); - } - } catch (IllegalAccessException e) { - throw new SecurityException(e); - } catch (IllegalArgumentException e) { - throw new IllegalStateException(e); - } catch (InvocationTargetException e) { - throw Throwables.propagate(e.getCause()); - } - } - - @Override public Set> getDependencies() { - return dependencies; - } - - @SuppressWarnings("unchecked") - @Override public Object acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - if (visitor instanceof MultibindingsTargetVisitor) { - return ((MultibindingsTargetVisitor) visitor).visit(this); - } else { - return visitor.visit(binding); - } - } - - @Override public boolean containsElement(Element element) { - return RealOptionalBinder.this.containsElement(element); - } - - @Override public Binding getActualBinding() { - return RealOptionalBinder.this.getActualBinding(); - } - - @Override public Binding getDefaultBinding() { - return RealOptionalBinder.this.getDefaultBinding(); - } - - @Override public Key getKey() { - return javaOptionalKey; - } - } - - @SuppressWarnings("rawtypes") - final class JavaOptionalProviderProvider extends RealOptionalBinderProviderWithDependencies { - private JavaOptionalProviderProvider() { - super(typeKey); - } - - @Override public Object get() { - Optional> optional = optionalProviderT.get(); - try { - if (optional.isPresent()) { - return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get()); - } else { - return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS); - } - } catch (IllegalAccessException e) { - throw new SecurityException(e); - } catch (IllegalArgumentException e) { - throw new IllegalStateException(e); - } catch (InvocationTargetException e) { - throw Throwables.propagate(e.getCause()); - } - } - - @Override public Set> getDependencies() { - return providerDependencies; - } - } - - final class RealDirectTypeProvider extends RealOptionalBinderProviderWithDependencies { - private RealDirectTypeProvider() { - super(typeKey); - } - - @Override public T get() { - Optional> optional = optionalProviderT.get(); - if (optional.isPresent()) { - return optional.get().get(); - } - // Let Guice handle blowing up if the injection point doesn't have @Nullable - // (If it does have @Nullable, that's fine. This would only happen if - // setBinding/setDefault themselves were bound to 'null'). - return null; - } - - @Override public Set> getDependencies() { - return dependencies; - } - } - - final class RealOptionalProviderProvider - extends RealOptionalBinderProviderWithDependencies>> { - private Optional> optional; - - private RealOptionalProviderProvider() { - super(typeKey); - } - - @Toolable @Inject void initialize(Injector injector) { - RealOptionalBinder.this.binder = null; - actualBinding = injector.getExistingBinding(actualKey); - defaultBinding = injector.getExistingBinding(defaultKey); - Binding userBinding = injector.getExistingBinding(typeKey); - Binding binding = null; - if (actualBinding != null) { - // TODO(sameb): Consider exposing an option that will allow - // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null. - // Right now, an ACTUAL binding can convert from present -> absent - // if it's bound to a provider that returns null. - binding = actualBinding; - } else if (defaultBinding != null) { - binding = defaultBinding; - } else if (userBinding != null) { - // If neither the actual or default is set, then we fallback - // to the value bound to the type itself and consider that the - // "actual binding" for the SPI. - binding = userBinding; - actualBinding = userBinding; - } - - if (binding != null) { - optional = Optional.of(binding.getProvider()); - RealOptionalBinder.this.dependencies = - ImmutableSet.>of(Dependency.get(binding.getKey())); - RealOptionalBinder.this.providerDependencies = - ImmutableSet.>of(Dependency.get(providerOf(binding.getKey()))); - } else { - optional = Optional.absent(); - RealOptionalBinder.this.dependencies = ImmutableSet.of(); - RealOptionalBinder.this.providerDependencies = ImmutableSet.of(); - } - } - - @Override public Optional> get() { - return optional; - } - - @Override public Set> getDependencies() { - return providerDependencies; - } - } - - final class RealOptionalKeyProvider - extends RealOptionalBinderProviderWithDependencies> - implements ProviderWithExtensionVisitor>, - OptionalBinderBinding>, - Provider> { - private RealOptionalKeyProvider() { - super(typeKey); - } - - @Override public Optional get() { - Optional> optional = optionalProviderT.get(); - if (optional.isPresent()) { - return Optional.fromNullable(optional.get().get()); - } else { - return Optional.absent(); - } - } - - @Override public Set> getDependencies() { - return dependencies; - } - - @SuppressWarnings("unchecked") - @Override - public R acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - if (visitor instanceof MultibindingsTargetVisitor) { - return ((MultibindingsTargetVisitor, R>) visitor).visit(this); - } else { - return visitor.visit(binding); - } - } - - @Override public Key> getKey() { - return optionalKey; - } - - @Override public Binding getActualBinding() { - return RealOptionalBinder.this.getActualBinding(); - } - - @Override public Binding getDefaultBinding() { - return RealOptionalBinder.this.getDefaultBinding(); - } - - @Override public boolean containsElement(Element element) { - return RealOptionalBinder.this.containsElement(element); - } - } - - private Binding getActualBinding() { - if (isInitialized()) { - return actualBinding; - } else { - throw new UnsupportedOperationException( - "getActualBinding() not supported from Elements.getElements, requires an Injector."); - } - } - - private Binding getDefaultBinding() { - if (isInitialized()) { - return defaultBinding; - } else { - throw new UnsupportedOperationException( - "getDefaultBinding() not supported from Elements.getElements, requires an Injector."); - } - } - - private boolean containsElement(Element element) { - Key elementKey; - if (element instanceof Binding) { - elementKey = ((Binding) element).getKey(); - } else if (element instanceof ProviderLookup) { - elementKey = ((ProviderLookup) element).getKey(); - } else { - return false; // cannot match; - } - - return elementKey.equals(optionalKey) - || elementKey.equals(optionalProviderKey) - || elementKey.equals(optionalJavaxProviderKey) - || elementKey.equals(defaultKey) - || elementKey.equals(actualKey) - || matchesJ8Keys(elementKey) - || matchesTypeKey(element, elementKey); - } - - private boolean matchesJ8Keys(Key elementKey) { - if (JAVA_OPTIONAL_CLASS != null) { - return elementKey.equals(javaOptionalKey) - || elementKey.equals(javaOptionalProviderKey) - || elementKey.equals(javaOptionalJavaxProviderKey); - } - return false; - } - - /** Returns true if the key & element indicate they were bound by this OptionalBinder. */ - private boolean matchesTypeKey(Element element, Key elementKey) { - // Just doing .equals(typeKey) isn't enough, because the user can bind that themselves. - return elementKey.equals(typeKey) - && element instanceof ProviderInstanceBinding - && (((ProviderInstanceBinding) element) - .getUserSuppliedProvider() instanceof RealOptionalBinderProviderWithDependencies); - } - - private boolean isInitialized() { - return binder == null; - } - - @Override public boolean equals(Object o) { - return o instanceof RealOptionalBinder - && ((RealOptionalBinder) o).typeKey.equals(typeKey); - } - - @Override public int hashCode() { - return typeKey.hashCode(); - } - - /** - * A base class for ProviderWithDependencies that need equality based on a specific object. - */ - private abstract static class RealOptionalBinderProviderWithDependencies implements - ProviderWithDependencies { - private final Object equality; - - public RealOptionalBinderProviderWithDependencies(Object equality) { - this.equality = equality; - } - - @Override public boolean equals(Object obj) { - return this.getClass() == obj.getClass() - && equality.equals(((RealOptionalBinderProviderWithDependencies) obj).equality); - } - - @Override public int hashCode() { - return equality.hashCode(); - } - } - } - - static class DefaultImpl extends BaseAnnotation implements Default { - public DefaultImpl(String value) { - super(Default.class, value); - } - } - - static class ActualImpl extends BaseAnnotation implements Actual { - public ActualImpl(String value) { - super(Actual.class, value); - } - } - - abstract static class BaseAnnotation implements Serializable, Annotation { - - private final String value; - private final Class clazz; - - BaseAnnotation(Class clazz, String value) { - this.clazz = checkNotNull(clazz, "clazz"); - this.value = checkNotNull(value, "value"); - } - - public String value() { - return this.value; - } - - @Override public int hashCode() { - // This is specified in java.lang.Annotation. - return (127 * "value".hashCode()) ^ value.hashCode(); - } - - @Override public boolean equals(Object o) { - // We check against each annotation type instead of BaseAnnotation - // so that we can compare against generated annotation implementations. - if (o instanceof Actual && clazz == Actual.class) { - Actual other = (Actual) o; - return value.equals(other.value()); - } else if (o instanceof Default && clazz == Default.class) { - Default other = (Default) o; - return value.equals(other.value()); - } - return false; - } - - @Override public String toString() { - return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")"); - } - - @Override public Class annotationType() { - return clazz; - } - - private static final long serialVersionUID = 0; - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/package-info.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/package-info.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/package-info.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Extension for binding multiple instances in a collection; this extension requires {@code - * guice-multibindings-3.0.jar}. - */ -package com.google.inject.multibindings; \ No newline at end of file diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.Module; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Annotates methods of a {@link Module} to add items to a {@link MapBinder}. - * The method's return type, binding annotation and additional key annotation determines - * what Map this will contribute to. For example, - * - *

    - * {@literal @}ProvidesIntoMap
    - * {@literal @}StringMapKey("Foo")
    - * {@literal @}Named("plugins")
    - * Plugin provideFooUrl(FooManager fm) { returm fm.getPlugin(); }
    - *
    - * {@literal @}ProvidesIntoMap
    - * {@literal @}StringMapKey("Bar")
    - * {@literal @}Named("urls")
    - * Plugin provideBarUrl(BarManager bm) { return bm.getPlugin(); }
    - * 
    - * - * will add two items to the {@code @Named("urls") Map} map. The key 'Foo' - * will map to the provideFooUrl method, and the key 'Bar' will map to the provideBarUrl method. - * The values are bound as providers and will be evaluated at injection time. - * - *

    Because the key is specified as an annotation, only Strings, Classes, enums, primitive - * types and annotation instances are supported as keys. - * - * @author sameb@google.com (Sam Berlin) - * @since 4.0 - */ -@Documented -@Target(METHOD) -@Retention(RUNTIME) -public @interface ProvidesIntoMap { -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.Module; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Annotates methods of a {@link Module} to add items to a {@link Multibinder}. - * The method's return type and binding annotation determines what Optional this will - * contribute to. For example, - * - *

    - * {@literal @}ProvidesIntoOptional(DEFAULT)
    - * {@literal @}Named("url")
    - * String provideFooUrl(FooManager fm) { returm fm.getUrl(); }
    - *
    - * {@literal @}ProvidesIntoOptional(ACTUAL)
    - * {@literal @}Named("url")
    - * String provideBarUrl(BarManager bm) { return bm.getUrl(); }
    - * 
    - * - * will set the default value of {@code @Named("url") Optional} to foo's URL, - * and then override it to bar's URL. - * - * @author sameb@google.com (Sam Berlin) - * @since 4.0 - */ -@Documented -@Target(METHOD) -@Retention(RUNTIME) -public @interface ProvidesIntoOptional { - /** - * @since 4.0 - */ - enum Type { - /** Corresponds to {@link OptionalBinder#setBinding}. */ - ACTUAL, - - /** Corresponds to {@link OptionalBinder#setDefault}. */ - DEFAULT - } - - /** Specifies if the binding is for the actual or default value. */ - Type value(); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.inject.Module; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Annotates methods of a {@link Module} to add items to a {@link Multibinder}. - * The method's return type and binding annotation determines what Set this will - * contribute to. For example, - * - *
    - * {@literal @}ProvidesIntoSet
    - * {@literal @}Named("urls")
    - * String provideFooUrl(FooManager fm) { returm fm.getUrl(); }
    - *
    - * {@literal @}ProvidesIntoSet
    - * {@literal @}Named("urls")
    - * String provideBarUrl(BarManager bm) { return bm.getUrl(); }
    - * 
    - * - * will add two items to the {@code @Named("urls") Set} set. The items are bound as - * providers and will be evaluated at injection time. - * - * @author sameb@google.com (Sam Berlin) - * @since 4.0 - */ -@Documented -@Target(METHOD) -@Retention(RUNTIME) -public @interface ProvidesIntoSet { -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.Key; -import com.google.inject.internal.Annotations; - -import java.lang.annotation.Annotation; -import java.util.concurrent.atomic.AtomicInteger; - -/** An implementation of Element. */ -// TODO(cgruber): Use AutoAnnotation when available, here & wherever else is makes sense. -class RealElement implements Element { - private static final AtomicInteger nextUniqueId = new AtomicInteger(1); - - private final int uniqueId; - private final String setName; - private final Element.Type type; - private final String keyType; - - RealElement(String setName, Element.Type type, String keyType) { - this(setName, type, keyType, nextUniqueId.incrementAndGet()); - } - - RealElement(String setName, Element.Type type, String keyType, int uniqueId) { - this.uniqueId = uniqueId; - this.setName = setName; - this.type = type; - this.keyType = keyType; - } - - @Override public String setName() { - return setName; - } - - @Override public int uniqueId() { - return uniqueId; - } - - @Override public Element.Type type() { - return type; - } - - @Override public String keyType() { - return keyType; - } - - @Override public Class annotationType() { - return Element.class; - } - - @Override public String toString() { - return "@" + Element.class.getName() + "(setName=" + setName - + ",uniqueId=" + uniqueId + ", type=" + type + ", keyType=" + keyType + ")"; - } - - @Override public boolean equals(Object o) { - return o instanceof Element - && ((Element) o).setName().equals(setName()) - && ((Element) o).uniqueId() == uniqueId() - && ((Element) o).type() == type() - && ((Element) o).keyType().equals(keyType()); - } - - @Override public int hashCode() { - return ((127 * "setName".hashCode()) ^ setName.hashCode()) - + ((127 * "uniqueId".hashCode()) ^ uniqueId) - + ((127 * "type".hashCode()) ^ type.hashCode()) - + ((127 * "keyType".hashCode()) ^ keyType.hashCode()); - } - - /** - * Returns the name the binding should use. This is based on the annotation. - * If the annotation has an instance and is not a marker annotation, - * we ask the annotation for its toString. If it was a marker annotation - * or just an annotation type, we use the annotation's name. Otherwise, - * the name is the empty string. - */ - static String nameOf(Key key) { - Annotation annotation = key.getAnnotation(); - Class annotationType = key.getAnnotationType(); - if (annotation != null && !Annotations.isMarker(annotationType)) { - return key.getAnnotation().toString(); - } else if (key.getAnnotationType() != null) { - return "@" + key.getAnnotationType().getName(); - } else { - return ""; - } - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java --- sisu-guice-3.2.6/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Allows {@literal @}{@link ProvidesIntoMap} to specify a string map key. - * @since 4.0 - */ -@MapKey(unwrapValue = true) -@Documented -@Target(METHOD) -@Retention(RUNTIME) -public @interface StringMapKey { - String value(); -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/src/README sisu-guice-4.2.0/extensions/multibindings/src/README --- sisu-guice-3.2.6/extensions/multibindings/src/README 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/src/README 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,4 @@ +This extension intentionally has no files in it. The multibindings functionality +is now part of Guice core. This extension still exists in order to ease the +transition. A future release will delete this extension. You can remove your +dependency on multibindings to avoid problems after the extension is deleted. \ No newline at end of file diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import junit.framework.Test; -import junit.framework.TestSuite; - -/** - * @author jessewilson@google.com (Jesse Wilson) - */ -public class AllTests { - - public static Test suite() { - TestSuite suite = new TestSuite(); - suite.addTestSuite(MapBinderTest.class); - suite.addTestSuite(MultibinderTest.class); - suite.addTestSuite(OptionalBinderTest.class); - suite.addTestSuite(RealElementTest.class); - suite.addTestSuite(ProvidesIntoTest.class); - return suite; - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/Collector.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/Collector.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/Collector.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/Collector.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/** - * Copyright (C) 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.spi.DefaultBindingTargetVisitor; - -class Collector extends DefaultBindingTargetVisitor implements - MultibindingsTargetVisitor { - MapBinderBinding mapbinding; - MultibinderBinding setbinding; - OptionalBinderBinding optionalbinding; - - @Override - public Object visit(MapBinderBinding mapbinding) { - this.mapbinding = mapbinding; - return null; - } - - @Override - public Object visit(MultibinderBinding multibinding) { - this.setbinding = multibinding; - return null; - } - - @Override - public Object visit(OptionalBinderBinding optionalbinding) { - this.optionalbinding = optionalbinding; - return null; - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1032 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.inject.Asserts.asModuleChain; -import static com.google.inject.Asserts.assertContains; -import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; -import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; -import static com.google.inject.multibindings.SpiUtils.assertMapVisitor; -import static com.google.inject.multibindings.SpiUtils.instance; -import static com.google.inject.multibindings.SpiUtils.providerInstance; -import static com.google.inject.name.Names.named; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.common.base.Function; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.inject.AbstractModule; -import com.google.inject.Asserts; -import com.google.inject.Binding; -import com.google.inject.BindingAnnotation; -import com.google.inject.ConfigurationException; -import com.google.inject.CreationException; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.Provides; -import com.google.inject.ProvisionException; -import com.google.inject.Stage; -import com.google.inject.TypeLiteral; -import com.google.inject.internal.WeakKeySetUtils; -import com.google.inject.name.Names; -import com.google.inject.spi.Dependency; -import com.google.inject.spi.HasDependencies; -import com.google.inject.spi.InstanceBinding; -import com.google.inject.util.Modules; -import com.google.inject.util.Providers; -import com.google.inject.util.Types; - -import junit.framework.TestCase; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; - -/** - * @author dpb@google.com (David P. Baker) - */ -public class MapBinderTest extends TestCase { - - private static final Set> FRAMEWORK_KEYS = ImmutableSet.of( - Key.get(java.util.logging.Logger.class), - Key.get(Stage.class), - Key.get(Injector.class) - ); - - final TypeLiteral>> mapOfStringJavaxProvider = - new TypeLiteral>>() {}; - final TypeLiteral>> mapOfStringProvider = - new TypeLiteral>>() {}; - final TypeLiteral> mapOfString = new TypeLiteral>() {}; - final TypeLiteral> mapOfIntString = - new TypeLiteral>() {}; - final TypeLiteral> mapOfInteger = new TypeLiteral>() {}; - final TypeLiteral>> mapOfSetOfString = - new TypeLiteral>>() {}; - - private final TypeLiteral stringType = TypeLiteral.get(String.class); - private final TypeLiteral intType = TypeLiteral.get(Integer.class); - - private Type javaxProviderOf(Type type) { - return Types.newParameterizedType(javax.inject.Provider.class, type); - } - - private Type mapEntryOf(Type keyType, Type valueType) { - return Types.newParameterizedTypeWithOwner(Map.class, Map.Entry.class, keyType, valueType); - } - - private Type collectionOf(Type type) { - return Types.newParameterizedType(Collection.class, type); - } - - public void testAllBindings() { - Module module = new AbstractModule() { - @Override - protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class).permitDuplicates(); - } - }; - - Injector injector = Guice.createInjector(module); - - Map, Binding> bindings = injector.getBindings(); - - ImmutableSet> expectedBindings = ImmutableSet.>builder() - .add( - // Map - Key.get(Types.mapOf(String.class, String.class)), - // Map> - Key.get(Types.mapOf(String.class, Types.providerOf(String.class))), - // Map> - Key.get(Types.mapOf(String.class, javaxProviderOf(String.class))), - // Map> - Key.get(Types.mapOf(String.class, Types.setOf(String.class))), - // Map> - Key.get(Types.mapOf(String.class, Types.setOf(Types.providerOf(String.class)))), - // Set>> - Key.get(Types.setOf(mapEntryOf(String.class, Types.providerOf(String.class)))), - // Collection>>> - Key.get(collectionOf(Types.providerOf( - mapEntryOf(String.class, Types.providerOf(String.class))))), - // Collection>>> - Key.get(collectionOf(javaxProviderOf( - mapEntryOf(String.class, Types.providerOf(String.class))))), - // @Named(...) Boolean - Key.get(Boolean.class, - named("Multibinder>> permits duplicates")) - ) - .addAll(FRAMEWORK_KEYS).build(); - - Set> missingBindings = Sets.difference(expectedBindings, bindings.keySet()); - Set> extraBindings = Sets.difference(bindings.keySet(), expectedBindings); - - assertTrue("There should be no missing bindings. Missing: " + missingBindings, - missingBindings.isEmpty()); - assertTrue("There should be no extra bindings. Extra: " + extraBindings, - extraBindings.isEmpty()); - } - - public void testMapBinderAggregatesMultipleModules() { - Module abc = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - multibinder.addBinding("c").toInstance("C"); - } - }; - Module de = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("d").toInstance("D"); - multibinder.addBinding("e").toInstance("E"); - } - }; - - Injector injector = Guice.createInjector(abc, de); - Map abcde = injector.getInstance(Key.get(mapOfString)); - - assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E"), abcde); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abc, de), BOTH, false, 0, - instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance("e", "E")); - - // just make sure these succeed - injector.getInstance(Key.get(mapOfStringProvider)); - injector.getInstance(Key.get(mapOfStringJavaxProvider)); - } - - public void testMapBinderAggregationForAnnotationInstance() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Names.named("abc")); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - - multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Names.named("abc")); - multibinder.addBinding("c").toInstance("C"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> key = Key.get(mapOfString, Names.named("abc")); - Map abc = injector.getInstance(key); - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); - assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0, - instance("a", "A"), instance("b", "B"), instance("c", "C")); - - // just make sure these succeed - injector.getInstance(Key.get(mapOfStringProvider, Names.named("abc"))); - injector.getInstance(Key.get(mapOfStringJavaxProvider, Names.named("abc"))); - } - - public void testMapBinderAggregationForAnnotationType() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Abc.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - - multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Abc.class); - multibinder.addBinding("c").toInstance("C"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> key = Key.get(mapOfString, Abc.class); - Map abc = injector.getInstance(key); - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); - assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0, - instance("a", "A"), instance("b", "B"), instance("c", "C")); - - // just make sure these succeed - injector.getInstance(Key.get(mapOfStringProvider, Abc.class)); - injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class)); - } - - public void testMapBinderWithMultipleAnnotationValueSets() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder abcMapBinder = MapBinder.newMapBinder( - binder(), String.class, String.class, named("abc")); - abcMapBinder.addBinding("a").toInstance("A"); - abcMapBinder.addBinding("b").toInstance("B"); - abcMapBinder.addBinding("c").toInstance("C"); - - MapBinder deMapBinder = MapBinder.newMapBinder( - binder(), String.class, String.class, named("de")); - deMapBinder.addBinding("d").toInstance("D"); - deMapBinder.addBinding("e").toInstance("E"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> abcKey = Key.get(mapOfString, named("abc")); - Map abc = injector.getInstance(abcKey); - Key> deKey = Key.get(mapOfString, named("de")); - Map de = injector.getInstance(deKey); - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); - assertEquals(mapOf("d", "D", "e", "E"), de); - assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1, - instance("a", "A"), instance("b", "B"), instance("c", "C")); - assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1, - instance("d", "D"), instance("e", "E")); - - // just make sure these succeed - injector.getInstance(Key.get(mapOfStringProvider, named("abc"))); - injector.getInstance(Key.get(mapOfStringJavaxProvider, named("abc"))); - injector.getInstance(Key.get(mapOfStringProvider, named("de"))); - injector.getInstance(Key.get(mapOfStringJavaxProvider, named("de"))); - } - - public void testMapBinderWithMultipleAnnotationTypeSets() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder abcMapBinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Abc.class); - abcMapBinder.addBinding("a").toInstance("A"); - abcMapBinder.addBinding("b").toInstance("B"); - abcMapBinder.addBinding("c").toInstance("C"); - - MapBinder deMapBinder = MapBinder.newMapBinder( - binder(), String.class, String.class, De.class); - deMapBinder.addBinding("d").toInstance("D"); - deMapBinder.addBinding("e").toInstance("E"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> abcKey = Key.get(mapOfString, Abc.class); - Map abc = injector.getInstance(abcKey); - Key> deKey = Key.get(mapOfString, De.class); - Map de = injector.getInstance(deKey); - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); - assertEquals(mapOf("d", "D", "e", "E"), de); - assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1, - instance("a", "A"), instance("b", "B"), instance("c", "C")); - assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1, - instance("d", "D"), instance("e", "E")); - - // just make sure these succeed - injector.getInstance(Key.get(mapOfStringProvider, Abc.class)); - injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class)); - injector.getInstance(Key.get(mapOfStringProvider, De.class)); - injector.getInstance(Key.get(mapOfStringJavaxProvider, De.class)); - } - - public void testMapBinderWithMultipleTypes() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("a").toInstance("A"); - MapBinder.newMapBinder(binder(), String.class, Integer.class) - .addBinding("1").toInstance(1); - } - }; - Injector injector = Guice.createInjector(module); - - assertEquals(mapOf("a", "A"), injector.getInstance(Key.get(mapOfString))); - assertEquals(mapOf("1", 1), injector.getInstance(Key.get(mapOfInteger))); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 1, - instance("a", "A")); - assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 1, - instance("1", 1)); - } - - public void testMapBinderWithEmptyMap() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class); - } - }; - Injector injector = Guice.createInjector(module); - - Map map = injector.getInstance(Key.get(mapOfString)); - assertEquals(Collections.emptyMap(), map); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0); - } - - public void testMapBinderMapIsUnmodifiable() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("a").toInstance("A"); - } - }); - - Map map = injector.getInstance(Key.get(mapOfString)); - try { - map.clear(); - fail(); - } catch(UnsupportedOperationException expected) { - } - } - - public void testMapBinderMapIsLazy() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, Integer.class) - .addBinding("num").toProvider(new Provider() { - int nextValue = 1; - @Override public Integer get() { - return nextValue++; - } - }); - } - }; - Injector injector = Guice.createInjector(module); - - assertEquals(mapOf("num", 1), injector.getInstance(Key.get(mapOfInteger))); - assertEquals(mapOf("num", 2), injector.getInstance(Key.get(mapOfInteger))); - assertEquals(mapOf("num", 3), injector.getInstance(Key.get(mapOfInteger))); - assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 0, - providerInstance("num", 1)); - } - - public void testMapBinderMapForbidsDuplicateKeys() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("a").toInstance("B"); - } - }; - try { - Guice.createInjector(module); - fail(); - } catch(CreationException expected) { - assertContains(expected.getMessage(), - "Map injection failed due to duplicated key \"a\""); - } - - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), MODULE, false, 0, - instance("a", "A"), instance("a", "B")); - } - - public void testExhaustiveDuplicateErrorMessage() throws Exception { - class Module1 extends AbstractModule { - @Override protected void configure() { - MapBinder mapbinder = - MapBinder.newMapBinder(binder(), String.class, Object.class); - mapbinder.addBinding("a").to(String.class); - } - } - class Module2 extends AbstractModule { - @Override protected void configure() { - MapBinder mapbinder = - MapBinder.newMapBinder(binder(), String.class, Object.class); - mapbinder.addBinding("a").to(Integer.class); - mapbinder.addBinding("b").to(String.class); - } - } - class Module3 extends AbstractModule { - @Override protected void configure() { - MapBinder mapbinder = - MapBinder.newMapBinder(binder(), String.class, Object.class); - mapbinder.addBinding("b").to(Integer.class); - } - } - class Main extends AbstractModule { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, Object.class); - install(new Module1()); - install(new Module2()); - install(new Module3()); - } - @Provides String provideString() { return "foo"; } - @Provides Integer provideInt() { return 42; } - } - try { - Guice.createInjector(new Main()); - fail(); - } catch(CreationException ce) { - assertContains(ce.getMessage(), - "Map injection failed due to duplicated key \"a\", from bindings:", - asModuleChain(Main.class, Module1.class), - asModuleChain(Main.class, Module2.class), - "and key: \"b\", from bindings:", - asModuleChain(Main.class, Module2.class), - asModuleChain(Main.class, Module3.class), - "at " + Main.class.getName() + ".configure(", - asModuleChain(Main.class, MapBinder.RealMapBinder.class)); - assertEquals(1, ce.getErrorMessages().size()); - } - } - - public void testMapBinderMapPermitDuplicateElements() { - Module ab = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - multibinder.permitDuplicates(); - } - }; - Module bc = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("b").toInstance("B"); - multibinder.addBinding("c").toInstance("C"); - multibinder.permitDuplicates(); - } - }; - Injector injector = Guice.createInjector(ab, bc); - - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injector.getInstance(Key.get(mapOfString))); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab, bc), BOTH, true, 0, - instance("a", "A"), instance("b", "B"), instance("c", "C")); - } - - public void testMapBinderMapDoesNotDedupeDuplicateValues() { - class ValueType { - int keyPart; - int dataPart; - private ValueType(int keyPart, int dataPart) { - this.keyPart = keyPart; - this.dataPart = dataPart; - } - @Override - public boolean equals(Object obj) { - return (obj instanceof ValueType) && (keyPart == ((ValueType) obj).keyPart); - } - @Override - public int hashCode() { - return keyPart; - } - } - Module m1 = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, ValueType.class); - multibinder.addBinding("a").toInstance(new ValueType(1, 2)); - } - }; - Module m2 = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, ValueType.class); - multibinder.addBinding("b").toInstance(new ValueType(1, 3)); - } - }; - - Injector injector = Guice.createInjector(m1, m2); - Map map = injector.getInstance(new Key>() {}); - assertEquals(2, map.get("a").dataPart); - assertEquals(3, map.get("b").dataPart); - } - - public void testMapBinderMultimap() { - AbstractModule ab1c = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B1"); - multibinder.addBinding("c").toInstance("C"); - } - }; - AbstractModule b2c = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - multibinder.addBinding("b").toInstance("B2"); - multibinder.addBinding("c").toInstance("C"); - multibinder.permitDuplicates(); - } - }; - Injector injector = Guice.createInjector(ab1c, b2c); - - assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")), - injector.getInstance(Key.get(mapOfSetOfString))); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab1c, b2c), BOTH, true, 0, - instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C")); - } - - public void testMapBinderMultimapWithAnotation() { - AbstractModule ab1 = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Abc.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B1"); - } - }; - AbstractModule b2c = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder( - binder(), String.class, String.class, Abc.class); - multibinder.addBinding("b").toInstance("B2"); - multibinder.addBinding("c").toInstance("C"); - multibinder.permitDuplicates(); - } - }; - Injector injector = Guice.createInjector(ab1, b2c); - - assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")), - injector.getInstance(Key.get(mapOfSetOfString, Abc.class))); - try { - injector.getInstance(Key.get(mapOfSetOfString)); - fail(); - } catch (ConfigurationException expected) {} - - assertMapVisitor(Key.get(mapOfString, Abc.class), stringType, stringType, setOf(ab1, b2c), BOTH, true, 0, - instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C")); - } - - public void testMapBinderMultimapIsUnmodifiable() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder mapBinder = MapBinder.newMapBinder( - binder(), String.class, String.class); - mapBinder.addBinding("a").toInstance("A"); - mapBinder.permitDuplicates(); - } - }); - - Map> map = injector.getInstance(Key.get(mapOfSetOfString)); - try { - map.clear(); - fail(); - } catch(UnsupportedOperationException expected) { - } - try { - map.get("a").clear(); - fail(); - } catch(UnsupportedOperationException expected) { - } - } - - public void testMapBinderMapForbidsNullKeys() { - try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class).addBinding(null); - } - }); - fail(); - } catch (CreationException expected) {} - } - - public void testMapBinderMapForbidsNullValues() { - Module m = new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("null").toProvider(Providers.of(null)); - } - }; - Injector injector = Guice.createInjector(m); - - try { - injector.getInstance(Key.get(mapOfString)); - fail(); - } catch(ProvisionException expected) { - assertContains(expected.getMessage(), - "1) Map injection failed due to null value for key \"null\", bound at: " - + m.getClass().getName() + ".configure("); - } - } - - public void testMapBinderProviderIsScoped() { - final Provider counter = new Provider() { - int next = 1; - @Override public Integer get() { - return next++; - } - }; - - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, Integer.class) - .addBinding("one").toProvider(counter).asEagerSingleton(); - } - }); - - assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one")); - assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one")); - } - - public void testSourceLinesInMapBindings() { - try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, Integer.class) - .addBinding("one"); - } - }); - fail(); - } catch (CreationException expected) { - assertContains(expected.getMessage(), - "1) No implementation for java.lang.Integer", - "at " + getClass().getName()); - } - } - - /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */ - public void testMultibinderDependencies() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder mapBinder - = MapBinder.newMapBinder(binder(), Integer.class, String.class); - mapBinder.addBinding(1).toInstance("A"); - mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b"))); - - bindConstant().annotatedWith(Names.named("b")).to("B"); - } - }); - - Binding> binding = injector.getBinding(new Key>() {}); - HasDependencies withDependencies = (HasDependencies) binding; - Key setKey = new Key>>>() {}; - assertEquals(ImmutableSet.>of(Dependency.get(setKey)), - withDependencies.getDependencies()); - Set elements = Sets.newHashSet(); - elements.addAll(recurseForDependencies(injector, withDependencies)); - assertEquals(ImmutableSet.of("A", "B"), elements); - } - - private Set recurseForDependencies(Injector injector, HasDependencies hasDependencies) { - Set elements = Sets.newHashSet(); - for (Dependency dependency : hasDependencies.getDependencies()) { - Binding binding = injector.getBinding(dependency.getKey()); - HasDependencies deps = (HasDependencies) binding; - if (binding instanceof InstanceBinding) { - elements.add((String) ((InstanceBinding) binding).getInstance()); - } else { - elements.addAll(recurseForDependencies(injector, deps)); - } - } - return elements; - } - - /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */ - public void testMultibinderDependenciesInToolStage() { - Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() { - @Override protected void configure() { - MapBinder mapBinder - = MapBinder.newMapBinder(binder(), Integer.class, String.class); - mapBinder.addBinding(1).toInstance("A"); - mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b"))); - - bindConstant().annotatedWith(Names.named("b")).to("B"); - }}); - - Binding> binding = injector.getBinding(new Key>() {}); - HasDependencies withDependencies = (HasDependencies) binding; - Key setKey = new Key>>>() {}; - assertEquals(ImmutableSet.>of(Dependency.get(setKey)), - withDependencies.getDependencies()); - } - - - /** - * Our implementation maintains order, but doesn't guarantee it in the API spec. - * TODO: specify the iteration order? - */ - public void testBindOrderEqualsIterationOrder() { - Injector injector = Guice.createInjector( - new AbstractModule() { - @Override protected void configure() { - MapBinder mapBinder - = MapBinder.newMapBinder(binder(), String.class, String.class); - mapBinder.addBinding("leonardo").toInstance("blue"); - mapBinder.addBinding("donatello").toInstance("purple"); - install(new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("michaelangelo").toInstance("orange"); - } - }); - } - }, - new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("raphael").toInstance("red"); - } - }); - - Map map = injector.getInstance(new Key>() {}); - Iterator> iterator = map.entrySet().iterator(); - assertEquals(Maps.immutableEntry("leonardo", "blue"), iterator.next()); - assertEquals(Maps.immutableEntry("donatello", "purple"), iterator.next()); - assertEquals(Maps.immutableEntry("michaelangelo", "orange"), iterator.next()); - assertEquals(Maps.immutableEntry("raphael", "red"), iterator.next()); - } - - /** - * With overrides, we should get the union of all map bindings. - */ - public void testModuleOverrideAndMapBindings() { - Module ab = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - } - }; - Module cd = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("c").toInstance("C"); - multibinder.addBinding("d").toInstance("D"); - } - }; - Module ef = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("e").toInstance("E"); - multibinder.addBinding("f").toInstance("F"); - } - }; - - Module abcd = Modules.override(ab).with(cd); - Injector injector = Guice.createInjector(abcd, ef); - assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"), - injector.getInstance(Key.get(mapOfString))); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, false, 0, - instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance( - "e", "E"), instance("f", "F")); - } - - public void testDeduplicateMapBindings() { - Module module = new AbstractModule() { - @Override protected void configure() { - MapBinder mapbinder = - MapBinder.newMapBinder(binder(), String.class, String.class); - mapbinder.addBinding("a").toInstance("A"); - mapbinder.addBinding("a").toInstance("A"); - mapbinder.addBinding("b").toInstance("B"); - mapbinder.addBinding("b").toInstance("B"); - - } - }; - Injector injector = Guice.createInjector(module); - assertEquals(mapOf("a", "A", "b", "B"), - injector.getInstance(Key.get(mapOfString))); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0, - instance("a", "A"), instance("b", "B")); - } - - /** - * With overrides, we should get the union of all map bindings. - */ - public void testModuleOverrideAndMapBindingsWithPermitDuplicates() { - Module abc = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - multibinder.addBinding("c").toInstance("C"); - multibinder.permitDuplicates(); - } - }; - Module cd = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("c").toInstance("C"); - multibinder.addBinding("d").toInstance("D"); - multibinder.permitDuplicates(); - } - }; - Module ef = new AbstractModule() { - @Override protected void configure() { - MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("e").toInstance("E"); - multibinder.addBinding("f").toInstance("F"); - multibinder.permitDuplicates(); - } - }; - - Module abcd = Modules.override(abc).with(cd); - Injector injector = Guice.createInjector(abcd, ef); - assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"), - injector.getInstance(Key.get(mapOfString))); - assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, true, 0, - instance("a", "A"), instance("b", "B"), instance("c", "C"), instance( - "d", "D"), instance("e", "E"), instance("f", "F")); - - } - - /** Ensure there are no initialization race conditions in basic map injection. */ - public void testBasicMapDependencyInjection() { - final AtomicReference> injectedMap = - new AtomicReference>(); - final Object anObject = new Object() { - @Inject void initialize(Map map) { - injectedMap.set(map); - } - }; - Module abc = new AbstractModule() { - @Override protected void configure() { - requestInjection(anObject); - MapBinder multibinder = - MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - multibinder.addBinding("c").toInstance("C"); - } - }; - Guice.createInjector(abc); - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injectedMap.get()); - } - - /** Ensure there are no initialization race conditions in provider multimap injection. */ - public void testProviderMultimapDependencyInjection() { - final AtomicReference>>> injectedMultimap = - new AtomicReference>>>(); - final Object anObject = new Object() { - @Inject void initialize(Map>> multimap) { - injectedMultimap.set(multimap); - } - }; - Module abc = new AbstractModule() { - @Override protected void configure() { - requestInjection(anObject); - MapBinder multibinder = - MapBinder.newMapBinder(binder(), String.class, String.class); - multibinder.permitDuplicates(); - multibinder.addBinding("a").toInstance("A"); - multibinder.addBinding("b").toInstance("B"); - multibinder.addBinding("c").toInstance("C"); - } - }; - Guice.createInjector(abc); - Map map = Maps.transformValues(injectedMultimap.get(), - new Function>, String>() { - @Override public String apply(Set> stringProvidersSet) { - return Iterables.getOnlyElement(stringProvidersSet).get(); - } - }); - assertEquals(mapOf("a", "A", "b", "B", "c", "C"), map); - } - - @Retention(RUNTIME) @BindingAnnotation - @interface Abc {} - - @Retention(RUNTIME) @BindingAnnotation - @interface De {} - - @SuppressWarnings("unchecked") - private Map mapOf(Object... elements) { - Map result = new HashMap(); - for (int i = 0; i < elements.length; i += 2) { - result.put((K)elements[i], (V)elements[i+1]); - } - return result; - } - - @SuppressWarnings("unchecked") - private Set setOf(V... elements) { - return new HashSet(Arrays.asList(elements)); - } - - @BindingAnnotation - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) - private static @interface Marker {} - - @Marker - public void testMapBinderMatching() throws Exception { - Method m = MapBinderTest.class.getDeclaredMethod("testMapBinderMatching"); - assertNotNull(m); - final Annotation marker = m.getAnnotation(Marker.class); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override public void configure() { - MapBinder mb1 = - MapBinder.newMapBinder(binder(), Integer.class, Integer.class, Marker.class); - MapBinder mb2 = - MapBinder.newMapBinder(binder(), Integer.class, Integer.class, marker); - mb1.addBinding(1).toInstance(1); - mb2.addBinding(2).toInstance(2); - - // This assures us that the two binders are equivalent, so we expect the instance added to - // each to have been added to one set. - assertEquals(mb1, mb2); - } - }); - TypeLiteral> t = new TypeLiteral>() {}; - Map s1 = injector.getInstance(Key.get(t, Marker.class)); - Map s2 = injector.getInstance(Key.get(t, marker)); - - // This assures us that the two sets are in fact equal. They may not be same set (as in Java - // object identical), but we shouldn't expect that, since probably Guice creates the set each - // time in case the elements are dependent on scope. - assertEquals(s1, s2); - - // This ensures that MultiBinder is internally using the correct set name -- - // making sure that instances of marker annotations have the same set name as - // MarkerAnnotation.class. - Map expected = new HashMap(); - expected.put(1, 1); - expected.put(2, 2); - assertEquals(expected, s1); - } - - public void testTwoMapBindersAreDistinct() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("A").toInstance("a"); - - MapBinder.newMapBinder(binder(), Integer.class, String.class) - .addBinding(1).toInstance("b"); - } - }); - Collector collector = new Collector(); - Binding> map1 = injector.getBinding(Key.get(mapOfString)); - map1.acceptTargetVisitor(collector); - assertNotNull(collector.mapbinding); - MapBinderBinding map1Binding = collector.mapbinding; - - Binding> map2 = injector.getBinding(Key.get(mapOfIntString)); - map2.acceptTargetVisitor(collector); - assertNotNull(collector.mapbinding); - MapBinderBinding map2Binding = collector.mapbinding; - - List> bindings = injector.findBindingsByType(stringType); - assertEquals("should have two elements: " + bindings, 2, bindings.size()); - Binding a = bindings.get(0); - Binding b = bindings.get(1); - assertEquals("a", ((InstanceBinding) a).getInstance()); - assertEquals("b", ((InstanceBinding) b).getInstance()); - - // Make sure the correct elements belong to their own sets. - assertTrue(map1Binding.containsElement(a)); - assertFalse(map1Binding.containsElement(b)); - - assertFalse(map2Binding.containsElement(a)); - assertTrue(map2Binding.containsElement(b)); - } - - // Tests for com.google.inject.internal.WeakKeySet not leaking memory. - public void testWeakKeySet_integration_mapbinder() { - Key> mapKey = Key.get(new TypeLiteral>() {}); - - Injector parentInjector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("hi"); - } - }); - WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey); - - Injector childInjector = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - MapBinder binder = - MapBinder.newMapBinder(binder(), String.class, String.class); - binder.addBinding("bar").toInstance("foo"); - } - }); - WeakReference weakRef = new WeakReference(childInjector); - WeakKeySetUtils.assertBlacklisted(parentInjector, mapKey); - - // Clear the ref, GC, and ensure that we are no longer blacklisting. - childInjector = null; - - Asserts.awaitClear(weakRef); - WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey); - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1221 +0,0 @@ -/** - * Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.inject.Asserts.assertContains; -import static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf; -import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; -import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; -import static com.google.inject.multibindings.SpiUtils.assertSetVisitor; -import static com.google.inject.multibindings.SpiUtils.instance; -import static com.google.inject.multibindings.SpiUtils.providerInstance; -import static com.google.inject.name.Names.named; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.common.base.Optional; -import com.google.common.base.Predicates; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.inject.AbstractModule; -import com.google.inject.Binding; -import com.google.inject.BindingAnnotation; -import com.google.inject.CreationException; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.Provides; -import com.google.inject.ProvisionException; -import com.google.inject.Scopes; -import com.google.inject.Stage; -import com.google.inject.TypeLiteral; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import com.google.inject.spi.Dependency; -import com.google.inject.spi.Element; -import com.google.inject.spi.Elements; -import com.google.inject.spi.HasDependencies; -import com.google.inject.spi.InstanceBinding; -import com.google.inject.spi.LinkedKeyBinding; -import com.google.inject.util.Modules; -import com.google.inject.util.Providers; -import com.google.inject.util.Types; - -import junit.framework.TestCase; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * @author jessewilson@google.com (Jesse Wilson) - */ -public class MultibinderTest extends TestCase { - - final TypeLiteral> optionalOfString = - new TypeLiteral>() {}; - final TypeLiteral> mapOfStringString = - new TypeLiteral>() {}; - final TypeLiteral> setOfString = new TypeLiteral>() {}; - final TypeLiteral> setOfInteger = new TypeLiteral>() {}; - final TypeLiteral stringType = TypeLiteral.get(String.class); - final TypeLiteral intType = TypeLiteral.get(Integer.class); - final TypeLiteral> listOfStrings = new TypeLiteral>() {}; - final TypeLiteral>> setOfListOfStrings = new TypeLiteral>>() {}; - final TypeLiteral>> collectionOfProvidersOfStrings = - new TypeLiteral>>() {}; - - public void testMultibinderAggregatesMultipleModules() { - Module abc = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - multibinder.addBinding().toInstance("C"); - } - }; - Module de = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("D"); - multibinder.addBinding().toInstance("E"); - } - }; - - Injector injector = Guice.createInjector(abc, de); - Key> setKey = Key.get(setOfString); - Set abcde = injector.getInstance(setKey); - Set results = setOf("A", "B", "C", "D", "E"); - - assertEquals(results, abcde); - assertSetVisitor(setKey, stringType, setOf(abc, de), BOTH, false, 0, - instance("A"), instance("B"), instance("C"), instance("D"), instance("E")); - } - - public void testMultibinderAggregationForAnnotationInstance() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder - = Multibinder.newSetBinder(binder(), String.class, Names.named("abc")); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - - multibinder = Multibinder.newSetBinder(binder(), String.class, Names.named("abc")); - multibinder.addBinding().toInstance("C"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> setKey = Key.get(setOfString, Names.named("abc")); - Set abc = injector.getInstance(setKey); - Set results = setOf("A", "B", "C"); - assertEquals(results, abc); - assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0, - instance("A"), instance("B"), instance("C")); - } - - public void testMultibinderAggregationForAnnotationType() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder - = Multibinder.newSetBinder(binder(), String.class, Abc.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - - multibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class); - multibinder.addBinding().toInstance("C"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> setKey = Key.get(setOfString, Abc.class); - Set abcde = injector.getInstance(setKey); - Set results = setOf("A", "B", "C"); - assertEquals(results, abcde); - assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0, - instance("A"), instance("B"), instance("C")); - } - - public void testMultibinderWithMultipleAnnotationValueSets() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder abcMultibinder - = Multibinder.newSetBinder(binder(), String.class, named("abc")); - abcMultibinder.addBinding().toInstance("A"); - abcMultibinder.addBinding().toInstance("B"); - abcMultibinder.addBinding().toInstance("C"); - - Multibinder deMultibinder - = Multibinder.newSetBinder(binder(), String.class, named("de")); - deMultibinder.addBinding().toInstance("D"); - deMultibinder.addBinding().toInstance("E"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> abcSetKey = Key.get(setOfString, named("abc")); - Set abc = injector.getInstance(abcSetKey); - Key> deSetKey = Key.get(setOfString, named("de")); - Set de = injector.getInstance(deSetKey); - Set abcResults = setOf("A", "B", "C"); - assertEquals(abcResults, abc); - Set deResults = setOf("D", "E"); - assertEquals(deResults, de); - assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1, - instance("A"), instance("B"), instance("C")); - assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1, - instance("D"), instance("E")); - } - - public void testMultibinderWithMultipleAnnotationTypeSets() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder abcMultibinder - = Multibinder.newSetBinder(binder(), String.class, Abc.class); - abcMultibinder.addBinding().toInstance("A"); - abcMultibinder.addBinding().toInstance("B"); - abcMultibinder.addBinding().toInstance("C"); - - Multibinder deMultibinder - = Multibinder.newSetBinder(binder(), String.class, De.class); - deMultibinder.addBinding().toInstance("D"); - deMultibinder.addBinding().toInstance("E"); - } - }; - Injector injector = Guice.createInjector(module); - - Key> abcSetKey = Key.get(setOfString, Abc.class); - Set abc = injector.getInstance(abcSetKey); - Key> deSetKey = Key.get(setOfString, De.class); - Set de = injector.getInstance(deSetKey); - Set abcResults = setOf("A", "B", "C"); - assertEquals(abcResults, abc); - Set deResults = setOf("D", "E"); - assertEquals(deResults, de); - assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1, - instance("A"), instance("B"), instance("C")); - assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1, - instance("D"), instance("E")); - } - - public void testMultibinderWithMultipleSetTypes() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toInstance("A"); - Multibinder.newSetBinder(binder(), Integer.class) - .addBinding().toInstance(1); - } - }; - Injector injector = Guice.createInjector(module); - - assertEquals(setOf("A"), injector.getInstance(Key.get(setOfString))); - assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger))); - assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 1, - instance("A")); - assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 1, - instance(1)); - } - - public void testMultibinderWithEmptySet() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class); - } - }; - Injector injector = Guice.createInjector(module); - - Set set = injector.getInstance(Key.get(setOfString)); - assertEquals(Collections.emptySet(), set); - assertSetVisitor(Key.get(setOfString), stringType, - setOf(module), BOTH, false, 0); - } - - public void testMultibinderSetIsUnmodifiable() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toInstance("A"); - } - }); - - Set set = injector.getInstance(Key.get(setOfString)); - try { - set.clear(); - fail(); - } catch(UnsupportedOperationException expected) { - } - } - - public void testMultibinderSetIsSerializable() throws IOException, ClassNotFoundException { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toInstance("A"); - } - }); - - Set set = injector.getInstance(Key.get(setOfString)); - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream); - try { - objectOutputStream.writeObject(set); - } finally { - objectOutputStream.close(); - } - ObjectInputStream objectInputStream = new ObjectInputStream( - new ByteArrayInputStream(byteStream.toByteArray())); - try { - Object setCopy = objectInputStream.readObject(); - assertEquals(set, setCopy); - } finally { - objectInputStream.close(); - } - } - - public void testMultibinderSetIsLazy() { - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), Integer.class) - .addBinding().toProvider(new Provider() { - int nextValue = 1; - public Integer get() { - return nextValue++; - } - }); - } - }; - Injector injector = Guice.createInjector(module); - - assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger))); - assertEquals(setOf(2), injector.getInstance(Key.get(setOfInteger))); - assertEquals(setOf(3), injector.getInstance(Key.get(setOfInteger))); - assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 0, - providerInstance(1)); - } - - public void testMultibinderSetForbidsDuplicateElements() { - Module module1 = new AbstractModule() { - @Override protected void configure() { - final Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toProvider(Providers.of("A")); - } - }; - Module module2 = new AbstractModule() { - @Override protected void configure() { - final Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - } - }; - Injector injector = Guice.createInjector(module1, module2); - - try { - injector.getInstance(Key.get(setOfString)); - fail(); - } catch (ProvisionException expected) { - assertContains(expected.getMessage(), - "1) Set injection failed due to duplicated element \"A\"", - "Bound at " + module1.getClass().getName(), - "Bound at " + module2.getClass().getName()); - } - - // But we can still visit the module! - assertSetVisitor(Key.get(setOfString), stringType, setOf(module1, module2), MODULE, false, 0, - instance("A"), instance("A")); - } - - public void testMultibinderSetShowsBothElementsIfToStringDifferent() { - // A simple example of a type whose toString returns more information than its equals method - // considers. - class ValueType { - int a; - int b; - ValueType(int a, int b) { - this.a = a; - this.b = b; - } - @Override - public boolean equals(Object obj) { - return (obj instanceof ValueType) && (((ValueType) obj).a == a); - } - @Override - public int hashCode() { - return a; - } - @Override - public String toString() { - return String.format("ValueType(%d,%d)", a, b); - } - } - - Module module1 = new AbstractModule() { - @Override protected void configure() { - final Multibinder multibinder = - Multibinder.newSetBinder(binder(), ValueType.class); - multibinder.addBinding().toProvider(Providers.of(new ValueType(1, 2))); - } - }; - Module module2 = new AbstractModule() { - @Override protected void configure() { - final Multibinder multibinder = - Multibinder.newSetBinder(binder(), ValueType.class); - multibinder.addBinding().toInstance(new ValueType(1, 3)); - } - }; - Injector injector = Guice.createInjector(module1, module2); - - TypeLiteral valueType = TypeLiteral.get(ValueType.class); - TypeLiteral> setOfValueType = new TypeLiteral>() {}; - try { - injector.getInstance(Key.get(setOfValueType)); - fail(); - } catch (ProvisionException expected) { - assertContains(expected.getMessage(), - "1) Set injection failed due to multiple elements comparing equal:", - "\"ValueType(1,2)\"", - "bound at " + module1.getClass().getName(), - "\"ValueType(1,3)\"", - "bound at " + module2.getClass().getName()); - } - - // But we can still visit the module! - assertSetVisitor(Key.get(setOfValueType), valueType, setOf(module1, module2), MODULE, false, 0, - instance(new ValueType(1, 2)), instance(new ValueType(1, 3))); - } - - public void testMultibinderSetPermitDuplicateElements() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - } - }; - Module bc = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.permitDuplicates(); - multibinder.addBinding().toInstance("B"); - multibinder.addBinding().toInstance("C"); - } - }; - Injector injector = Guice.createInjector(ab, bc); - - assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString))); - assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0, - instance("A"), instance("B"), instance("C")); - } - - public void testMultibinderSetPermitDuplicateCallsToPermitDuplicates() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.permitDuplicates(); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - } - }; - Module bc = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.permitDuplicates(); - multibinder.addBinding().toInstance("B"); - multibinder.addBinding().toInstance("C"); - } - }; - Injector injector = Guice.createInjector(ab, bc); - - assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString))); - assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0, - instance("A"), instance("B"), instance("C")); - } - - public void testMultibinderSetForbidsNullElements() { - Module m = new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toProvider(Providers.of(null)); - } - }; - Injector injector = Guice.createInjector(m); - - try { - injector.getInstance(Key.get(setOfString)); - fail(); - } catch(ProvisionException expected) { - assertContains(expected.getMessage(), - "1) Set injection failed due to null element bound at: " - + m.getClass().getName() + ".configure("); - } - } - - public void testSourceLinesInMultibindings() { - try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), Integer.class).addBinding(); - } - }); - fail(); - } catch (CreationException expected) { - assertContains(expected.getMessage(), "No implementation for java.lang.Integer", - "at " + getClass().getName()); - } - } - - /** - * We just want to make sure that multibinder's binding depends on each of its values. We don't - * really care about the underlying structure of those bindings, which are implementation details. - */ - public void testMultibinderDependencies() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().to(Key.get(String.class, Names.named("b"))); - - bindConstant().annotatedWith(Names.named("b")).to("B"); - } - }); - - Binding> binding = injector.getBinding(new Key>() {}); - HasDependencies withDependencies = (HasDependencies) binding; - Set elements = Sets.newHashSet(); - for (Dependency dependency : withDependencies.getDependencies()) { - elements.add((String) injector.getInstance(dependency.getKey())); - } - assertEquals(ImmutableSet.of("A", "B"), elements); - } - - /** - * We just want to make sure that multibinder's binding depends on each of its values. We don't - * really care about the underlying structure of those bindings, which are implementation details. - */ - public void testMultibinderDependenciesInToolStage() { - Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().to(Key.get(String.class, Names.named("b"))); - - bindConstant().annotatedWith(Names.named("b")).to("B"); - } - }); - - Binding> binding = injector.getBinding(new Key>() {}); - HasDependencies withDependencies = (HasDependencies) binding; - InstanceBinding instanceBinding = null; - LinkedKeyBinding linkedBinding = null; - // The non-tool stage test can test this by calling injector.getInstance to ensure - // the right values are returned -- in tool stage we can't do that. It's also a - // little difficult to validate the dependencies & bindings, because they're - // bindings created internally within Multibinder. - // To workaround this, we just validate that the dependencies lookup to a single - // InstanceBinding whose value is "A" and another LinkedBinding whose target is - // the Key of @Named("b") String=B - for (Dependency dependency : withDependencies.getDependencies()) { - Binding b = injector.getBinding(dependency.getKey()); - if(b instanceof InstanceBinding) { - if(instanceBinding != null) { - fail("Already have an instance binding of: " + instanceBinding + ", and now want to add: " + b); - } else { - instanceBinding = (InstanceBinding)b; - } - } else if(b instanceof LinkedKeyBinding) { - if(linkedBinding != null) { - fail("Already have a linked binding of: " + linkedBinding + ", and now want to add: " + b); - } else { - linkedBinding = (LinkedKeyBinding)b; - } - } else { - fail("Unexpected dependency of: " + dependency); - } - } - - assertNotNull(instanceBinding); - assertNotNull(linkedBinding); - - assertEquals("A", instanceBinding.getInstance()); - assertEquals(Key.get(String.class, Names.named("b")), linkedBinding.getLinkedKey()); - } - - /** - * Our implementation maintains order, but doesn't guarantee it in the API spec. - * TODO: specify the iteration order? - */ - public void testBindOrderEqualsIterationOrder() { - Injector injector = Guice.createInjector( - new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("leonardo"); - multibinder.addBinding().toInstance("donatello"); - install(new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toInstance("michaelangelo"); - } - }); - } - }, - new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("raphael"); - } - }); - - List inOrder = ImmutableList.copyOf(injector.getInstance(Key.get(setOfString))); - assertEquals(ImmutableList.of("leonardo", "donatello", "michaelangelo", "raphael"), inOrder); - } - - @Retention(RUNTIME) @BindingAnnotation - @interface Abc {} - - @Retention(RUNTIME) @BindingAnnotation - @interface De {} - - private Set setOf(T... elements) { - Set result = Sets.newHashSet(); - Collections.addAll(result, elements); - return result; - } - - /** - * With overrides, we should get the union of all multibindings. - */ - public void testModuleOverrideAndMultibindings() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - } - }; - Module cd = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("C"); - multibinder.addBinding().toInstance("D"); - } - }; - Module ef = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("E"); - multibinder.addBinding().toInstance("F"); - } - }; - - Module abcd = Modules.override(ab).with(cd); - Injector injector = Guice.createInjector(abcd, ef); - assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"), - injector.getInstance(Key.get(setOfString))); - - assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, false, 0, - instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F")); - } - - /** - * With overrides, we should get the union of all multibindings. - */ - public void testModuleOverrideAndMultibindingsWithPermitDuplicates() { - Module abc = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - multibinder.addBinding().toInstance("C"); - multibinder.permitDuplicates(); - } - }; - Module cd = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("C"); - multibinder.addBinding().toInstance("D"); - multibinder.permitDuplicates(); - } - }; - Module ef = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("E"); - multibinder.addBinding().toInstance("F"); - multibinder.permitDuplicates(); - } - }; - - Module abcd = Modules.override(abc).with(cd); - Injector injector = Guice.createInjector(abcd, ef); - assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"), - injector.getInstance(Key.get(setOfString))); - - assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, true, 0, - instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F")); - } - - /** - * Doubly-installed modules should not conflict, even when one is overridden. - */ - public void testModuleOverrideRepeatedInstallsAndMultibindings_toInstance() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toInstance("A"); - multibinder.addBinding().toInstance("B"); - } - }; - - // Guice guarantees this assertion, as the same module cannot be installed twice. - assertEquals(ImmutableSet.of("A", "B"), - Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); - - // Guice will only guarantee this assertion if Multibinder ensures the bindings match. - Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); - assertEquals(ImmutableSet.of("A", "B"), - injector.getInstance(Key.get(setOfString))); - } - - public void testModuleOverrideRepeatedInstallsAndMultibindings_toKey() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Key aKey = Key.get(String.class, Names.named("A_string")); - Key bKey = Key.get(String.class, Names.named("B_string")); - bind(aKey).toInstance("A"); - bind(bKey).toInstance("B"); - - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().to(aKey); - multibinder.addBinding().to(bKey); - } - }; - - // Guice guarantees this assertion, as the same module cannot be installed twice. - assertEquals(ImmutableSet.of("A", "B"), - Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); - - // Guice will only guarantee this assertion if Multibinder ensures the bindings match. - Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); - assertEquals(ImmutableSet.of("A", "B"), - injector.getInstance(Key.get(setOfString))); - } - - public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderInstance() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toProvider(Providers.of("A")); - multibinder.addBinding().toProvider(Providers.of("B")); - } - }; - - // Guice guarantees this assertion, as the same module cannot be installed twice. - assertEquals(ImmutableSet.of("A", "B"), - Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); - - // Guice will only guarantee this assertion if Multibinder ensures the bindings match. - Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); - assertEquals(ImmutableSet.of("A", "B"), - injector.getInstance(Key.get(setOfString))); - } - - private static class AStringProvider implements Provider { - public String get() { - return "A"; - } - } - - private static class BStringProvider implements Provider { - public String get() { - return "B"; - } - } - - public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderKey() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toProvider(Key.get(AStringProvider.class)); - multibinder.addBinding().toProvider(Key.get(BStringProvider.class)); - } - }; - - // Guice guarantees this assertion, as the same module cannot be installed twice. - assertEquals(ImmutableSet.of("A", "B"), - Guice.createInjector(ab, ab).getInstance(Key.get(setOfString))); - - // Guice will only guarantee this assertion if Multibinder ensures the bindings match. - Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); - assertEquals(ImmutableSet.of("A", "B"), - injector.getInstance(Key.get(setOfString))); - } - - private static class StringGrabber { - private final String string; - - @SuppressWarnings("unused") // Found by reflection - public StringGrabber(@Named("A_string") String string) { - this.string = string; - } - - @SuppressWarnings("unused") // Found by reflection - public StringGrabber(@Named("B_string") String string, int unused) { - this.string = string; - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string); - } - - @Override - public String toString() { - return "StringGrabber(" + string + ")"; - } - - static Set values(Iterable grabbers) { - Set result = new HashSet(); - for (StringGrabber grabber : grabbers) { - result.add(grabber.string); - } - return result; - } - } - - public void testModuleOverrideRepeatedInstallsAndMultibindings_toConstructor() { - TypeLiteral> setOfStringGrabber = new TypeLiteral>() {}; - Module ab = new AbstractModule() { - @Override protected void configure() { - Key aKey = Key.get(String.class, Names.named("A_string")); - Key bKey = Key.get(String.class, Names.named("B_string")); - bind(aKey).toInstance("A"); - bind(bKey).toInstance("B"); - bind(Integer.class).toInstance(0); // used to disambiguate constructors - - Multibinder multibinder = - Multibinder.newSetBinder(binder(), StringGrabber.class); - try { - multibinder.addBinding().toConstructor( - StringGrabber.class.getConstructor(String.class)); - multibinder.addBinding().toConstructor( - StringGrabber.class.getConstructor(String.class, int.class)); - } catch (NoSuchMethodException e) { - fail("No such method: " + e.getMessage()); - } - } - }; - - // Guice guarantees this assertion, as the same module cannot be installed twice. - assertEquals(ImmutableSet.of("A", "B"), - StringGrabber.values( - Guice.createInjector(ab, ab).getInstance(Key.get(setOfStringGrabber)))); - - // Guice will only guarantee this assertion if Multibinder ensures the bindings match. - Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab)); - assertEquals(ImmutableSet.of("A", "B"), - StringGrabber.values(injector.getInstance(Key.get(setOfStringGrabber)))); - } - - /** - * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or - * explicitly bound in {@link Scopes#NO_SCOPE}. - */ - public void testDuplicateUnscopedBindings() { - Module singleBinding = new AbstractModule() { - @Override protected void configure() { - bind(Integer.class).to(Key.get(Integer.class, named("A"))); - bind(Integer.class).to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE); - } - - @Provides @Named("A") - int provideInteger() { - return 5; - } - }; - Module multibinding = new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), Integer.class); - multibinder.addBinding().to(Key.get(Integer.class, named("A"))); - multibinder.addBinding().to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE); - } - }; - - assertEquals(5, - (int) Guice.createInjector(singleBinding).getInstance(Integer.class)); - assertEquals(ImmutableSet.of(5), - Guice.createInjector(singleBinding, multibinding).getInstance(Key.get(setOfInteger))); - } - - /** - * Ensure key hash codes are fixed at injection time, not binding time. - */ - public void testKeyHashCodesFixedAtInjectionTime() { - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder> multibinder = Multibinder.newSetBinder(binder(), listOfStrings); - List list = Lists.newArrayList(); - multibinder.addBinding().toInstance(list); - list.add("A"); - list.add("B"); - } - }; - - Injector injector = Guice.createInjector(ab); - for (Entry, Binding> entry : injector.getAllBindings().entrySet()) { - Key bindingKey = entry.getKey(); - Key clonedKey; - if (bindingKey.getAnnotation() != null) { - clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation()); - } else if (bindingKey.getAnnotationType() != null) { - clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType()); - } else { - clonedKey = Key.get(bindingKey.getTypeLiteral()); - } - assertEquals(bindingKey, clonedKey); - assertEquals("Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(), - bindingKey.hashCode(), clonedKey.hashCode()); - } - } - - /** - * Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}. - */ - public void testBindingKeysFixedOnReturnFromGetElements() { - final List list = Lists.newArrayList(); - Module ab = new AbstractModule() { - @Override protected void configure() { - Multibinder> multibinder = Multibinder.newSetBinder(binder(), listOfStrings); - multibinder.addBinding().toInstance(list); - list.add("A"); - list.add("B"); - } - }; - - InstanceBinding binding = Iterables.getOnlyElement( - Iterables.filter(Elements.getElements(ab), InstanceBinding.class)); - Key keyBefore = binding.getKey(); - assertEquals(listOfStrings, keyBefore.getTypeLiteral()); - - list.add("C"); - Key keyAfter = binding.getKey(); - assertSame(keyBefore, keyAfter); - } - - /* - * Verify through gratuitous mutation that key hashCode snapshots and whatnot happens at the right - * times, by binding two lists that are different at injector creation, but compare equal when the - * module is configured *and* when the set is instantiated. - */ - public void testConcurrentMutation_bindingsDiffentAtInjectorCreation() { - // We initially bind two equal lists - final List list1 = Lists.newArrayList(); - final List list2 = Lists.newArrayList(); - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder> multibinder = Multibinder.newSetBinder(binder(), listOfStrings); - multibinder.addBinding().toInstance(list1); - multibinder.addBinding().toInstance(list2); - } - }; - List elements = Elements.getElements(module); - - // Now we change the lists so they no longer match, and create the injector. - list1.add("A"); - list2.add("B"); - Injector injector = Guice.createInjector(Elements.getModule(elements)); - - // Now we change the lists so they compare equal again, and create the set. - list1.add(1, "B"); - list2.add(0, "A"); - try { - injector.getInstance(Key.get(setOfListOfStrings)); - fail(); - } catch (ProvisionException e) { - assertEquals(1, e.getErrorMessages().size()); - assertContains( - Iterables.getOnlyElement(e.getErrorMessages()).getMessage().toString(), - "Set injection failed due to duplicated element \"[A, B]\""); - } - - // Finally, we change the lists again so they are once more different, and ensure the set - // contains both. - list1.remove("A"); - list2.remove("B"); - Set> set = injector.getInstance(Key.get(setOfListOfStrings)); - assertEquals(ImmutableSet.of(ImmutableList.of("A"), ImmutableList.of("B")), set); - } - - /* - * Verify through gratuitous mutation that key hashCode snapshots and whatnot happen at the right - * times, by binding two lists that compare equal at injector creation, but are different when the - * module is configured *and* when the set is instantiated. - */ - public void testConcurrentMutation_bindingsSameAtInjectorCreation() { - // We initially bind two distinct lists - final List list1 = Lists.newArrayList("A"); - final List list2 = Lists.newArrayList("B"); - Module module = new AbstractModule() { - @Override protected void configure() { - Multibinder> multibinder = Multibinder.newSetBinder(binder(), listOfStrings); - multibinder.addBinding().toInstance(list1); - multibinder.addBinding().toInstance(list2); - } - }; - List elements = Elements.getElements(module); - - // Now we change the lists so they compare equal, and create the injector. - list1.add(1, "B"); - list2.add(0, "A"); - Injector injector = Guice.createInjector(Elements.getModule(elements)); - - // Now we change the lists again so they are once more different, and create the set. - list1.remove("A"); - list2.remove("B"); - Set> set = injector.getInstance(Key.get(setOfListOfStrings)); - - // The set will contain just one of the two lists. - // (In fact, it will be the first one we bound, but we don't promise that, so we won't test it.) - assertTrue(ImmutableSet.of(ImmutableList.of("A")).equals(set) - || ImmutableSet.of(ImmutableList.of("B")).equals(set)); - } - - @BindingAnnotation - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) - private static @interface Marker {} - - @Marker - public void testMultibinderMatching() throws Exception { - Method m = MultibinderTest.class.getDeclaredMethod("testMultibinderMatching"); - assertNotNull(m); - final Annotation marker = m.getAnnotation(Marker.class); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override public void configure() { - Multibinder mb1 = Multibinder.newSetBinder(binder(), Integer.class, Marker.class); - Multibinder mb2 = Multibinder.newSetBinder(binder(), Integer.class, marker); - mb1.addBinding().toInstance(1); - mb2.addBinding().toInstance(2); - - // This assures us that the two binders are equivalent, so we expect the instance added to - // each to have been added to one set. - assertEquals(mb1, mb2); - } - }); - TypeLiteral> t = new TypeLiteral>() {}; - Set s1 = injector.getInstance(Key.get(t, Marker.class)); - Set s2 = injector.getInstance(Key.get(t, marker)); - - // This assures us that the two sets are in fact equal. They may not be same set (as in Java - // object identical), but we shouldn't expect that, since probably Guice creates the set each - // time in case the elements are dependent on scope. - assertEquals(s1, s2); - - // This ensures that MultiBinder is internally using the correct set name -- - // making sure that instances of marker annotations have the same set name as - // MarkerAnnotation.class. - Set expected = new HashSet(); - expected.add(1); - expected.add(2); - assertEquals(expected, s1); - } - - // See issue 670 - public void testSetAndMapValueAreDistinct() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toInstance("A"); - - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("B").toInstance("b"); - - OptionalBinder.newOptionalBinder(binder(), String.class) - .setDefault().toInstance("C"); - OptionalBinder.newOptionalBinder(binder(), String.class) - .setBinding().toInstance("D"); - } - }); - - assertEquals(ImmutableSet.of("A"), injector.getInstance(Key.get(setOfString))); - assertEquals(ImmutableMap.of("B", "b"), injector.getInstance(Key.get(mapOfStringString))); - assertEquals(Optional.of("D"), injector.getInstance(Key.get(optionalOfString))); - } - - // See issue 670 - public void testSetAndMapValueAreDistinctInSpi() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder.newSetBinder(binder(), String.class) - .addBinding().toInstance("A"); - - MapBinder.newMapBinder(binder(), String.class, String.class) - .addBinding("B").toInstance("b"); - - OptionalBinder.newOptionalBinder(binder(), String.class) - .setDefault().toInstance("C"); - } - }); - Collector collector = new Collector(); - Binding> mapbinding = injector.getBinding(Key.get(mapOfStringString)); - mapbinding.acceptTargetVisitor(collector); - assertNotNull(collector.mapbinding); - - Binding> setbinding = injector.getBinding(Key.get(setOfString)); - setbinding.acceptTargetVisitor(collector); - assertNotNull(collector.setbinding); - - Binding> optionalbinding = injector.getBinding(Key.get(optionalOfString)); - optionalbinding.acceptTargetVisitor(collector); - assertNotNull(collector.optionalbinding); - - // There should only be three instance bindings for string types - // (but because of the OptionalBinder, there's 2 ProviderInstanceBindings also). - // We also know the InstanceBindings will be in the order: A, b, C because that's - // how we bound them, and binding order is preserved. - List> bindings = FluentIterable.from(injector.findBindingsByType(stringType)) - .filter(Predicates.instanceOf(InstanceBinding.class)) - .toList(); - assertEquals(bindings.toString(), 3, bindings.size()); - Binding a = bindings.get(0); - Binding b = bindings.get(1); - Binding c = bindings.get(2); - assertEquals("A", ((InstanceBinding) a).getInstance()); - assertEquals("b", ((InstanceBinding) b).getInstance()); - assertEquals("C", ((InstanceBinding) c).getInstance()); - - // Make sure the correct elements belong to their own sets. - assertFalse(collector.mapbinding.containsElement(a)); - assertTrue(collector.mapbinding.containsElement(b)); - assertFalse(collector.mapbinding.containsElement(c)); - - assertTrue(collector.setbinding.containsElement(a)); - assertFalse(collector.setbinding.containsElement(b)); - assertFalse(collector.setbinding.containsElement(c)); - - assertFalse(collector.optionalbinding.containsElement(a)); - assertFalse(collector.optionalbinding.containsElement(b)); - assertTrue(collector.optionalbinding.containsElement(c)); - } - - public void testMultibinderCanInjectCollectionOfProviders() { - Module module = new AbstractModule() { - @Override protected void configure() { - final Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); - multibinder.addBinding().toProvider(Providers.of("A")); - multibinder.addBinding().toProvider(Providers.of("B")); - multibinder.addBinding().toInstance("C"); - } - }; - Collection expectedValues = ImmutableList.of("A", "B", "C"); - - Injector injector = Guice.createInjector(module); - - Collection> providers = - injector.getInstance(Key.get(collectionOfProvidersOfStrings)); - assertEquals(expectedValues, collectValues(providers)); - - Collection> javaxProviders = - injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType))); - assertEquals(expectedValues, collectValues(javaxProviders)); - } - - public void testMultibinderCanInjectCollectionOfProvidersWithAnnotation() { - final Annotation ann = Names.named("foo"); - Module module = new AbstractModule() { - @Override protected void configure() { - final Multibinder multibinder = - Multibinder.newSetBinder(binder(), String.class, ann); - multibinder.addBinding().toProvider(Providers.of("A")); - multibinder.addBinding().toProvider(Providers.of("B")); - multibinder.addBinding().toInstance("C"); - } - }; - Collection expectedValues = ImmutableList.of("A", "B", "C"); - - Injector injector = Guice.createInjector(module); - - Collection> providers = - injector.getInstance(Key.get(collectionOfProvidersOfStrings, ann)); - Collection values = collectValues(providers); - assertEquals(expectedValues, values); - - Collection> javaxProviders = - injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType), ann)); - assertEquals(expectedValues, collectValues(javaxProviders)); - } - - public void testMultibindingProviderDependencies() { - final Annotation setAnn = Names.named("foo"); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - Multibinder multibinder = - Multibinder.newSetBinder(binder(), String.class, setAnn); - multibinder.addBinding().toInstance("a"); - multibinder.addBinding().toInstance("b"); - } - }); - HasDependencies providerBinding = - (HasDependencies) injector.getBinding(new Key>>(setAnn) {}); - HasDependencies setBinding = - (HasDependencies) injector.getBinding(new Key>(setAnn) {}); - // sanity check the size - assertEquals(setBinding.getDependencies().toString(), 2, setBinding.getDependencies().size()); - Set> expected = Sets.newHashSet(); - for (Dependency dep : setBinding.getDependencies()) { - Key key = dep.getKey(); - Dependency providerDependency = - Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType()))); - expected.add(providerDependency); - } - assertEquals(expected, providerBinding.getDependencies()); - } - - private Collection collectValues( - Collection> providers) { - Collection values = Lists.newArrayList(); - for (javax.inject.Provider provider : providers) { - values.add(provider.get()); - } - return values; - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1241 +0,0 @@ -/** - * Copyright (C) 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.inject.Asserts.assertContains; -import static com.google.inject.multibindings.SpiUtils.assertOptionalVisitor; -import static com.google.inject.multibindings.SpiUtils.instance; -import static com.google.inject.multibindings.SpiUtils.linked; -import static com.google.inject.multibindings.SpiUtils.providerInstance; -import static com.google.inject.multibindings.SpiUtils.providerKey; -import static com.google.inject.name.Names.named; - -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.inject.AbstractModule; -import com.google.inject.Asserts; -import com.google.inject.Binding; -import com.google.inject.BindingAnnotation; -import com.google.inject.CreationException; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.Provides; -import com.google.inject.Scopes; -import com.google.inject.TypeLiteral; -import com.google.inject.internal.WeakKeySetUtils; -import com.google.inject.multibindings.OptionalBinder.Actual; -import com.google.inject.multibindings.OptionalBinder.Default; -import com.google.inject.multibindings.SpiUtils.VisitType; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import com.google.inject.spi.Dependency; -import com.google.inject.spi.Elements; -import com.google.inject.spi.HasDependencies; -import com.google.inject.spi.InstanceBinding; -import com.google.inject.util.Modules; -import com.google.inject.util.Providers; - -import junit.framework.TestCase; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; - -/** - * @author sameb@google.com (Sam Berlin) - */ -public class OptionalBinderTest extends TestCase { - - private static final boolean HAS_JAVA_OPTIONAL; - private static final Class JAVA_OPTIONAL_CLASS; - private static final Method JAVA_OPTIONAL_OR_ELSE; - static { - Class optional = null; - Method orElse = null; - try { - optional = Class.forName("java.util.Optional"); - orElse = optional.getDeclaredMethod("orElse", Object.class); - } catch (ClassNotFoundException ignored) { - } catch (NoSuchMethodException ignored) { - } catch (SecurityException ignored) { - } - HAS_JAVA_OPTIONAL = optional != null; - JAVA_OPTIONAL_CLASS = optional; - JAVA_OPTIONAL_OR_ELSE = orElse; - } - - final Key stringKey = Key.get(String.class); - final TypeLiteral> optionalOfString = new TypeLiteral>() {}; - final TypeLiteral javaOptionalOfString = HAS_JAVA_OPTIONAL ? - OptionalBinder.javaOptionalOf(stringKey.getTypeLiteral()) : null; - final TypeLiteral>> optionalOfProviderString = - new TypeLiteral>>() {}; - final TypeLiteral javaOptionalOfProviderString = HAS_JAVA_OPTIONAL ? - OptionalBinder.javaOptionalOfProvider(stringKey.getTypeLiteral()) : null; - final TypeLiteral>> optionalOfJavaxProviderString = - new TypeLiteral>>() {}; - final TypeLiteral javaOptionalOfJavaxProviderString = HAS_JAVA_OPTIONAL ? - OptionalBinder.javaOptionalOfJavaxProvider(stringKey.getTypeLiteral()) : null; - - final Key intKey = Key.get(Integer.class); - final TypeLiteral> optionalOfInteger = new TypeLiteral>() {}; - final TypeLiteral javaOptionalOfInteger = HAS_JAVA_OPTIONAL ? - OptionalBinder.javaOptionalOf(intKey.getTypeLiteral()) : null; - final TypeLiteral>> optionalOfProviderInteger = - new TypeLiteral>>() {}; - final TypeLiteral javaOptionalOfProviderInteger = HAS_JAVA_OPTIONAL ? - OptionalBinder.javaOptionalOfProvider(intKey.getTypeLiteral()) : null; - final TypeLiteral>> optionalOfJavaxProviderInteger = - new TypeLiteral>>() {}; - final TypeLiteral javaOptionalOfJavaxProviderInteger = HAS_JAVA_OPTIONAL ? - OptionalBinder.javaOptionalOfJavaxProvider(intKey.getTypeLiteral()) : null; - - final TypeLiteral> listOfStrings = new TypeLiteral>() {}; - - public void testTypeNotBoundByDefault() { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class); - requireBinding(new Key>() {}); // the above specifies this. - requireBinding(String.class); // but it doesn't specify this. - binder().requireExplicitBindings(); // need to do this, otherwise String will JIT - - if (HAS_JAVA_OPTIONAL) { - requireBinding(Key.get(javaOptionalOfString)); - } - } - }; - - try { - Guice.createInjector(module); - fail(); - } catch (CreationException ce) { - assertContains(ce.getMessage(), - "1) Explicit bindings are required and java.lang.String is not explicitly bound."); - assertEquals(1, ce.getErrorMessages().size()); - } - } - - public void testOptionalIsAbsentByDefault() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class); - } - }; - - Injector injector = Guice.createInjector(module); - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertFalse(optional.isPresent()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertFalse(optionalP.isPresent()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertFalse(optionalJxP.isPresent()); - - assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, null, null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertFalse(optional.isPresent()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertFalse(optionalP.isPresent()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertFalse(optionalJxP.isPresent()); - } - } - - public void testUsesUserBoundValue() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class); - } - @Provides String provideString() { return "foo"; } - }; - - Injector injector = Guice.createInjector(module); - assertEquals("foo", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertEquals("foo", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertEquals("foo", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertEquals("foo", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, - setOf(module), - VisitType.BOTH, - 0, - null, - null, - providerInstance("foo")); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertEquals("foo", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertEquals("foo", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertEquals("foo", optionalJxP.get().get()); - } - } - - public void testSetDefault() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); - } - }; - Injector injector = Guice.createInjector(module); - assertEquals("a", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - } - } - - public void testSetBinding() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a"); - } - }; - Injector injector = Guice.createInjector(module); - assertEquals("a", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - } - } - - public void testSetBindingOverridesDefault() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder optionalBinder = - OptionalBinder.newOptionalBinder(binder(), String.class); - optionalBinder.setDefault().toInstance("a"); - optionalBinder.setBinding().toInstance("b"); - } - }; - Injector injector = Guice.createInjector(module); - assertEquals("b", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertTrue(optional.isPresent()); - assertEquals("b", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertEquals("b", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertEquals("b", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, - setOf(module), - VisitType.BOTH, - 0, - instance("a"), - instance("b"), - null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertTrue(optional.isPresent()); - assertEquals("b", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertEquals("b", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertEquals("b", optionalJxP.get().get()); - } - } - - public void testSpreadAcrossModules() throws Exception { - Module module1 = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class); - } - }; - Module module2 = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); - } - }; - Module module3 = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); - } - }; - - Injector injector = Guice.createInjector(module1, module2, module3); - assertEquals("b", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertTrue(optional.isPresent()); - assertEquals("b", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertEquals("b", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertEquals("b", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, - setOf(module1, module2, module3), - VisitType.BOTH, - 0, - instance("a"), - instance("b"), - null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertTrue(optional.isPresent()); - assertEquals("b", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertEquals("b", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertEquals("b", optionalJxP.get().get()); - } - } - - public void testExactSameBindingCollapses_defaults() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault() - .toInstance(new String("a")); // using new String to ensure .equals is checked. - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault() - .toInstance(new String("a")); - } - }; - Injector injector = Guice.createInjector(module); - assertEquals("a", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - } - } - - public void testExactSameBindingCollapses_actual() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding() - .toInstance(new String("a")); // using new String to ensure .equals is checked. - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding() - .toInstance(new String("a")); - } - }; - Injector injector = Guice.createInjector(module); - assertEquals("a", injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertTrue(optional.isPresent()); - assertEquals("a", optional.get()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertEquals("a", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertEquals("a", optionalJxP.get().get()); - } - } - - public void testDifferentBindingsFail_defaults() { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b"); - } - }; - try { - Guice.createInjector(module); - fail(); - } catch (CreationException ce) { - assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), - "1) A binding to java.lang.String annotated with @" - + Default.class.getName() + " was already configured at " - + module.getClass().getName() + ".configure(", - "at " + module.getClass().getName() + ".configure("); - } - } - - public void testDifferentBindingsFail_actual() { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a"); - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); - } - }; - try { - Guice.createInjector(module); - fail(); - } catch (CreationException ce) { - assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), - "1) A binding to java.lang.String annotated with @" - + Actual.class.getName() + " was already configured at " - + module.getClass().getName() + ".configure(", - "at " + module.getClass().getName() + ".configure("); - } - } - - public void testDifferentBindingsFail_both() { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b"); - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); - OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("c"); - } - }; - try { - Guice.createInjector(module); - fail(); - } catch (CreationException ce) { - assertEquals(ce.getMessage(), 2, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), - "1) A binding to java.lang.String annotated with @" - + Default.class.getName() + " was already configured at " - + module.getClass().getName() + ".configure(", - "at " + module.getClass().getName() + ".configure(", - "2) A binding to java.lang.String annotated with @" - + Actual.class.getName() + " was already configured at " - + module.getClass().getName() + ".configure(", - "at " + module.getClass().getName() + ".configure("); - } - } - - public void testQualifiedAggregatesTogether() throws Exception { - Module module1 = new AbstractModule() { - @Override - protected void configure() { - OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))); - } - }; - Module module2 = new AbstractModule() { - @Override - protected void configure() { - OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))) - .setDefault().toInstance("a"); - } - }; - Module module3 = new AbstractModule() { - @Override - protected void configure() { - OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))) - .setBinding().toInstance("b"); - } - }; - - Injector injector = Guice.createInjector(module1, module2, module3); - assertEquals("b", injector.getInstance(Key.get(String.class, Names.named("foo")))); - - Optional optional = injector.getInstance(Key.get(optionalOfString, Names.named("foo"))); - assertTrue(optional.isPresent()); - assertEquals("b", optional.get()); - - Optional> optionalP = - injector.getInstance(Key.get(optionalOfProviderString, Names.named("foo"))); - assertTrue(optionalP.isPresent()); - assertEquals("b", optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString, Names.named("foo"))); - assertTrue(optionalJxP.isPresent()); - assertEquals("b", optionalJxP.get().get()); - - assertOptionalVisitor(Key.get(String.class, Names.named("foo")), - setOf(module1, module2, module3), - VisitType.BOTH, - 0, - instance("a"), - instance("b"), - null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString, Names.named("foo")))); - assertTrue(optional.isPresent()); - assertEquals("b", optional.get()); - - optionalP = toOptional(injector.getInstance - (Key.get(javaOptionalOfProviderString, Names.named("foo")))); - assertTrue(optionalP.isPresent()); - assertEquals("b", optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance( - Key.get(javaOptionalOfJavaxProviderString, Names.named("foo")))); - assertTrue(optionalJxP.isPresent()); - assertEquals("b", optionalJxP.get().get()); - } - } - - public void testMultipleDifferentOptionals() { - final Key bKey = Key.get(String.class, named("b")); - final Key cKey = Key.get(String.class, named("c")); - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); - OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(1); - - OptionalBinder.newOptionalBinder(binder(), bKey).setDefault().toInstance("b"); - OptionalBinder.newOptionalBinder(binder(), cKey).setDefault().toInstance("c"); - } - }; - Injector injector = Guice.createInjector(module); - assertEquals("a", injector.getInstance(String.class)); - assertEquals(1, injector.getInstance(Integer.class).intValue()); - assertEquals("b", injector.getInstance(bKey)); - assertEquals("c", injector.getInstance(cKey)); - - assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 3, instance("a"), null, null); - assertOptionalVisitor(intKey, setOf(module), VisitType.BOTH, 3, instance(1), null, null); - assertOptionalVisitor(bKey, setOf(module), VisitType.BOTH, 3, instance("b"), null, null); - assertOptionalVisitor(cKey, setOf(module), VisitType.BOTH, 3, instance("c"), null, null); - } - - public void testOptionalIsAppropriatelyLazy() throws Exception { - Module module = new AbstractModule() { - int nextValue = 1; - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), Integer.class) - .setDefault().to(Key.get(Integer.class, Names.named("foo"))); - } - @Provides @Named("foo") int provideInt() { - return nextValue++; - } - }; - Injector injector = Guice.createInjector(module); - - Optional> optionalP = - injector.getInstance(Key.get(optionalOfProviderInteger)); - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderInteger)); - - assertEquals(1, injector.getInstance(Integer.class).intValue()); - assertEquals(2, injector.getInstance(Integer.class).intValue()); - - // Calling .get() on an Optional multiple times will keep giving the same thing - Optional optional = injector.getInstance(Key.get(optionalOfInteger)); - assertEquals(3, optional.get().intValue()); - assertEquals(3, optional.get().intValue()); - // But getting another Optional will give a new one. - assertEquals(4, injector.getInstance(Key.get(optionalOfInteger)).get().intValue()); - - // And the Optional will return a provider that gives a new value each time. - assertEquals(5, optionalP.get().get().intValue()); - assertEquals(6, optionalP.get().get().intValue()); - - assertEquals(7, optionalJxP.get().get().intValue()); - assertEquals(8, optionalJxP.get().get().intValue()); - - // and same rules with java.util.Optional - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger))); - assertEquals(9, optional.get().intValue()); - assertEquals(9, optional.get().intValue()); - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger))); - assertEquals(10, optional.get().intValue()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderInteger))); - assertEquals(11, optionalP.get().get().intValue()); - assertEquals(12, optionalP.get().get().intValue()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderInteger))); - assertEquals(13, optionalJxP.get().get().intValue()); - assertEquals(14, optionalJxP.get().get().intValue()); - } - } - - public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_default() - throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class) - .setDefault().toProvider(Providers.of(null)); - } - }; - Injector injector = Guice.createInjector(module); - assertNull(injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertFalse(optional.isPresent()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertNull(optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertNull(optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, - setOf(module), - VisitType.BOTH, - 0, - SpiUtils.providerInstance(null), - null, - null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertFalse(optional.isPresent()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertNull(optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertNull(optionalJxP.get().get()); - } - } - - public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_actual() - throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class) - .setBinding().toProvider(Providers.of(null)); - } - }; - Injector injector = Guice.createInjector(module); - assertNull(injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertFalse(optional.isPresent()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertNull(optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertNull(optionalJxP.get().get()); - - assertOptionalVisitor(stringKey, - setOf(module), - VisitType.BOTH, - 0, - null, - SpiUtils.providerInstance(null), - null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertFalse(optional.isPresent()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertNull(optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertNull(optionalJxP.get().get()); - } - } - - // TODO(sameb): Maybe change this? - public void testLinkedToNullActualDoesntFallbackToDefault() throws Exception { - Module module = new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); - OptionalBinder.newOptionalBinder(binder(), String.class) - .setBinding().toProvider(Providers.of(null)); - } - }; - Injector injector = Guice.createInjector(module); - assertNull(injector.getInstance(String.class)); - - Optional optional = injector.getInstance(Key.get(optionalOfString)); - assertFalse(optional.isPresent()); - - Optional> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); - assertTrue(optionalP.isPresent()); - assertNull(optionalP.get().get()); - - Optional> optionalJxP = - injector.getInstance(Key.get(optionalOfJavaxProviderString)); - assertTrue(optionalJxP.isPresent()); - assertNull(optionalP.get().get()); - - assertOptionalVisitor(stringKey, - setOf(module), - VisitType.BOTH, - 0, - instance("a"), - SpiUtils.providerInstance(null), - null); - - if (HAS_JAVA_OPTIONAL) { - optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); - assertFalse(optional.isPresent()); - - optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); - assertTrue(optionalP.isPresent()); - assertNull(optionalP.get().get()); - - optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); - assertTrue(optionalJxP.isPresent()); - assertNull(optionalJxP.get().get()); - } - } - - public void testSourceLinesInException() { - try { - Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault(); - } - }); - fail(); - } catch (CreationException expected) { - assertContains(expected.getMessage(), "No implementation for java.lang.Integer", - "at " + getClass().getName()); - } - } - - public void testDependencies_both() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - OptionalBinder optionalbinder = - OptionalBinder.newOptionalBinder(binder(), String.class); - optionalbinder.setDefault().toInstance("A"); - optionalbinder.setBinding().to(Key.get(String.class, Names.named("b"))); - bindConstant().annotatedWith(Names.named("b")).to("B"); - } - }); - - Binding binding = injector.getBinding(Key.get(String.class)); - HasDependencies withDependencies = (HasDependencies) binding; - Set elements = Sets.newHashSet(); - elements.addAll(recurseForDependencies(injector, withDependencies)); - assertEquals(ImmutableSet.of("B"), elements); - } - - public void testDependencies_actual() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - OptionalBinder optionalbinder = - OptionalBinder.newOptionalBinder(binder(), String.class); - optionalbinder.setBinding().to(Key.get(String.class, Names.named("b"))); - bindConstant().annotatedWith(Names.named("b")).to("B"); - } - }); - - Binding binding = injector.getBinding(Key.get(String.class)); - HasDependencies withDependencies = (HasDependencies) binding; - Set elements = Sets.newHashSet(); - elements.addAll(recurseForDependencies(injector, withDependencies)); - assertEquals(ImmutableSet.of("B"), elements); - } - - public void testDependencies_default() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - OptionalBinder optionalbinder = - OptionalBinder.newOptionalBinder(binder(), String.class); - optionalbinder.setDefault().toInstance("A"); - } - }); - - Binding binding = injector.getBinding(Key.get(String.class)); - HasDependencies withDependencies = (HasDependencies) binding; - Set elements = Sets.newHashSet(); - elements.addAll(recurseForDependencies(injector, withDependencies)); - assertEquals(ImmutableSet.of("A"), elements); - } - - @SuppressWarnings("rawtypes") - private Set recurseForDependencies(Injector injector, HasDependencies hasDependencies) { - Set elements = Sets.newHashSet(); - for (Dependency dependency : hasDependencies.getDependencies()) { - Binding binding = injector.getBinding(dependency.getKey()); - HasDependencies deps = (HasDependencies) binding; - if (binding instanceof InstanceBinding) { - elements.add((String) ((InstanceBinding) binding).getInstance()); - } else { - elements.addAll(recurseForDependencies(injector, deps)); - } - } - return elements; - } - - /** - * Doubly-installed modules should not conflict, even when one is overridden. - */ - public void testModuleOverrideRepeatedInstalls_toInstance() { - Module m = new AbstractModule() { - @Override protected void configure() { - OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); - b.setDefault().toInstance("A"); - b.setBinding().toInstance("B"); - } - }; - - assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); - - Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); - assertEquals("B", injector.getInstance(Key.get(String.class))); - - assertOptionalVisitor(stringKey, - setOf(m, Modules.override(m).with(m)), - VisitType.BOTH, - 0, - instance("A"), - instance("B"), - null); - } - - public void testModuleOverrideRepeatedInstalls_toKey() { - final Key aKey = Key.get(String.class, Names.named("A_string")); - final Key bKey = Key.get(String.class, Names.named("B_string")); - Module m = new AbstractModule() { - @Override protected void configure() { - bind(aKey).toInstance("A"); - bind(bKey).toInstance("B"); - - OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); - b.setDefault().to(aKey); - b.setBinding().to(bKey); - } - }; - - assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); - - Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); - assertEquals("B", injector.getInstance(Key.get(String.class))); - - assertOptionalVisitor(stringKey, - setOf(m, Modules.override(m).with(m)), - VisitType.BOTH, - 0, - linked(aKey), - linked(bKey), - null); - } - - public void testModuleOverrideRepeatedInstalls_toProviderInstance() { - // Providers#of() does not redefine equals/hashCode, so use the same one both times. - final Provider aProvider = Providers.of("A"); - final Provider bProvider = Providers.of("B"); - Module m = new AbstractModule() { - @Override protected void configure() { - OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); - b.setDefault().toProvider(aProvider); - b.setBinding().toProvider(bProvider); - } - }; - - assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); - - Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); - assertEquals("B", injector.getInstance(Key.get(String.class))); - - assertOptionalVisitor(stringKey, - setOf(m, Modules.override(m).with(m)), - VisitType.BOTH, - 0, - providerInstance("A"), - providerInstance("B"), - null); - } - - private static class AStringProvider implements Provider { - public String get() { - return "A"; - } - } - - private static class BStringProvider implements Provider { - public String get() { - return "B"; - } - } - - public void testModuleOverrideRepeatedInstalls_toProviderKey() { - Module m = new AbstractModule() { - @Override protected void configure() { - OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), String.class); - b.setDefault().toProvider(Key.get(AStringProvider.class)); - b.setBinding().toProvider(Key.get(BStringProvider.class)); - } - }; - - assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); - - Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); - assertEquals("B", injector.getInstance(Key.get(String.class))); - - assertOptionalVisitor(stringKey, - setOf(m, Modules.override(m).with(m)), - VisitType.BOTH, - 0, - providerKey(Key.get(AStringProvider.class)), - providerKey(Key.get(BStringProvider.class)), - null); - } - - private static class StringGrabber { - private final String string; - - @SuppressWarnings("unused") // Found by reflection - public StringGrabber(@Named("A_string") String string) { - this.string = string; - } - - @SuppressWarnings("unused") // Found by reflection - public StringGrabber(@Named("B_string") String string, int unused) { - this.string = string; - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string); - } - - @Override - public String toString() { - return "StringGrabber(" + string + ")"; - } - } - - public void testModuleOverrideRepeatedInstalls_toConstructor() { - Module m = new AbstractModule() { - @Override protected void configure() { - Key aKey = Key.get(String.class, Names.named("A_string")); - Key bKey = Key.get(String.class, Names.named("B_string")); - bind(aKey).toInstance("A"); - bind(bKey).toInstance("B"); - bind(Integer.class).toInstance(0); // used to disambiguate constructors - - - OptionalBinder b = - OptionalBinder.newOptionalBinder(binder(), StringGrabber.class); - try { - b.setDefault().toConstructor( - StringGrabber.class.getConstructor(String.class)); - b.setBinding().toConstructor( - StringGrabber.class.getConstructor(String.class, int.class)); - } catch (NoSuchMethodException e) { - fail("No such method: " + e.getMessage()); - } - } - }; - - assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(StringGrabber.class)).string); - - Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); - assertEquals("B", injector.getInstance(Key.get(StringGrabber.class)).string); - } - - /** - * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or - * explicitly bound in {@link Scopes#NO_SCOPE}. - */ - public void testDuplicateUnscopedBindings() { - Module m = new AbstractModule() { - @Override protected void configure() { - OptionalBinder b = OptionalBinder.newOptionalBinder(binder(), Integer.class); - b.setDefault().to(Key.get(Integer.class, named("foo"))); - b.setDefault().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE); - b.setBinding().to(Key.get(Integer.class, named("foo"))); - b.setBinding().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE); - } - @Provides @Named("foo") int provideInt() { return 5; } - }; - assertEquals(5, Guice.createInjector(m).getInstance(Integer.class).intValue()); - } - - /** - * Ensure key hash codes are fixed at injection time, not binding time. - */ - public void testKeyHashCodesFixedAtInjectionTime() { - Module m = new AbstractModule() { - @Override protected void configure() { - OptionalBinder> b = OptionalBinder.newOptionalBinder(binder(), listOfStrings); - List list = Lists.newArrayList(); - b.setDefault().toInstance(list); - b.setBinding().toInstance(list); - list.add("A"); - list.add("B"); - } - }; - - Injector injector = Guice.createInjector(m); - for (Entry, Binding> entry : injector.getAllBindings().entrySet()) { - Key bindingKey = entry.getKey(); - Key clonedKey; - if (bindingKey.getAnnotation() != null) { - clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation()); - } else if (bindingKey.getAnnotationType() != null) { - clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType()); - } else { - clonedKey = Key.get(bindingKey.getTypeLiteral()); - } - assertEquals(bindingKey, clonedKey); - assertEquals("Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(), - bindingKey.hashCode(), clonedKey.hashCode()); - } - } - - /** - * Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}. - */ - public void testBindingKeysFixedOnReturnFromGetElements() { - final List list = Lists.newArrayList(); - Module m = new AbstractModule() { - @Override protected void configure() { - OptionalBinder> b = OptionalBinder.newOptionalBinder(binder(), listOfStrings); - b.setDefault().toInstance(list); - list.add("A"); - list.add("B"); - } - }; - - InstanceBinding binding = Iterables.getOnlyElement( - Iterables.filter(Elements.getElements(m), InstanceBinding.class)); - Key keyBefore = binding.getKey(); - assertEquals(listOfStrings, keyBefore.getTypeLiteral()); - - list.add("C"); - Key keyAfter = binding.getKey(); - assertSame(keyBefore, keyAfter); - } - - @BindingAnnotation - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) - private static @interface Marker {} - - @Marker - public void testMatchingMarkerAnnotations() throws Exception { - Method m = OptionalBinderTest.class.getDeclaredMethod("testMatchingMarkerAnnotations"); - assertNotNull(m); - final Annotation marker = m.getAnnotation(Marker.class); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override public void configure() { - OptionalBinder mb1 = - OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, Marker.class)); - OptionalBinder mb2 = - OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, marker)); - mb1.setDefault().toInstance(1); - mb2.setBinding().toInstance(2); - - // This assures us that the two binders are equivalent, so we expect the instance added to - // each to have been added to one set. - assertEquals(mb1, mb2); - } - }); - Integer i1 = injector.getInstance(Key.get(Integer.class, Marker.class)); - Integer i2 = injector.getInstance(Key.get(Integer.class, marker)); - - // These must be identical, because the marker annotations collapsed to the same thing. - assertSame(i1, i2); - assertEquals(2, i2.intValue()); - } - - // Tests for com.google.inject.internal.WeakKeySet not leaking memory. - public void testWeakKeySet_integration() { - Injector parentInjector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bind(String.class).toInstance("hi"); - } - }); - WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class)); - - Injector childInjector = parentInjector.createChildInjector(new AbstractModule() { - @Override protected void configure() { - OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(4); - } - }); - WeakReference weakRef = new WeakReference(childInjector); - WeakKeySetUtils.assertBlacklisted(parentInjector, Key.get(Integer.class)); - - // Clear the ref, GC, and ensure that we are no longer blacklisting. - childInjector = null; - - Asserts.awaitClear(weakRef); - WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class)); - } - - public void testCompareEqualsAgainstOtherAnnotation() { - OptionalBinder.Actual impl1 = new OptionalBinder.ActualImpl("foo"); - OptionalBinder.Actual other1 = Dummy.class.getAnnotation(OptionalBinder.Actual.class); - assertEquals(impl1, other1); - - OptionalBinder.Default impl2 = new OptionalBinder.DefaultImpl("foo"); - OptionalBinder.Default other2 = Dummy.class.getAnnotation(OptionalBinder.Default.class); - assertEquals(impl2, other2); - - assertFalse(impl1.equals(impl2)); - assertFalse(impl1.equals(other2)); - assertFalse(impl2.equals(other1)); - assertFalse(other1.equals(other2)); - } - - @OptionalBinder.Actual("foo") - @OptionalBinder.Default("foo") - static class Dummy {} - - @SuppressWarnings("unchecked") - private Set setOf(V... elements) { - return ImmutableSet.copyOf(elements); - } - - @SuppressWarnings("unchecked") - private Optional toOptional(Object object) throws Exception { - assertTrue("not a java.util.Optional: " + object.getClass(), - JAVA_OPTIONAL_CLASS.isInstance(object)); - return Optional.fromNullable((T) JAVA_OPTIONAL_OR_ELSE.invoke(object, (Void) null)); - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,373 +0,0 @@ -/** - * Copyright (C) 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.inject.Asserts.assertContains; -import static com.google.inject.name.Names.named; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.inject.AbstractModule; -import com.google.inject.CreationException; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.multibindings.ProvidesIntoOptional.Type; -import com.google.inject.name.Named; - -import junit.framework.TestCase; - -import java.lang.annotation.Retention; -import java.lang.reflect.Field; -import java.util.Map; -import java.util.Set; - -/** - * Tests the various @ProvidesInto annotations. - * - * @author sameb@google.com (Sam Berlin) - */ -public class ProvidesIntoTest extends TestCase { - - public void testAnnotation() throws Exception { - Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), new AbstractModule() { - @Override protected void configure() {} - - @ProvidesIntoSet - @Named("foo") - String setFoo() { return "foo"; } - - @ProvidesIntoSet - @Named("foo") - String setFoo2() { return "foo2"; } - - @ProvidesIntoSet - @Named("bar") - String setBar() { return "bar"; } - - @ProvidesIntoSet - @Named("bar") - String setBar2() { return "bar2"; } - - @ProvidesIntoSet - String setNoAnnotation() { return "na"; } - - @ProvidesIntoSet - String setNoAnnotation2() { return "na2"; } - - @ProvidesIntoMap - @StringMapKey("fooKey") - @Named("foo") - String mapFoo() { return "foo"; } - - @ProvidesIntoMap - @StringMapKey("foo2Key") - @Named("foo") - String mapFoo2() { return "foo2"; } - - @ProvidesIntoMap - @ClassMapKey(String.class) - @Named("bar") - String mapBar() { return "bar"; } - - @ProvidesIntoMap - @ClassMapKey(Number.class) - @Named("bar") - String mapBar2() { return "bar2"; } - - @ProvidesIntoMap - @TestEnumKey(TestEnum.A) - String mapNoAnnotation() { return "na"; } - - @ProvidesIntoMap - @TestEnumKey(TestEnum.B) - String mapNoAnnotation2() { return "na2"; } - - @ProvidesIntoMap - @WrappedKey(number = 1) - Number wrapped1() { return 11; } - - @ProvidesIntoMap - @WrappedKey(number = 2) - Number wrapped2() { return 22; } - - @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT) - @Named("foo") - String optionalDefaultFoo() { return "foo"; } - - @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL) - @Named("foo") - String optionalActualFoo() { return "foo2"; } - - @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT) - @Named("bar") - String optionalDefaultBar() { return "bar"; } - - @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL) - String optionalActualBar() { return "na2"; } - }); - - Set fooSet = injector.getInstance(new Key>(named("foo")) {}); - assertEquals(ImmutableSet.of("foo", "foo2"), fooSet); - - Set barSet = injector.getInstance(new Key>(named("bar")) {}); - assertEquals(ImmutableSet.of("bar", "bar2"), barSet); - - Set noAnnotationSet = injector.getInstance(new Key>() {}); - assertEquals(ImmutableSet.of("na", "na2"), noAnnotationSet); - - Map fooMap = - injector.getInstance(new Key>(named("foo")) {}); - assertEquals(ImmutableMap.of("fooKey", "foo", "foo2Key", "foo2"), fooMap); - - Map, String> barMap = - injector.getInstance(new Key, String>>(named("bar")) {}); - assertEquals(ImmutableMap.of(String.class, "bar", Number.class, "bar2"), barMap); - - Map noAnnotationMap = - injector.getInstance(new Key>() {}); - assertEquals(ImmutableMap.of(TestEnum.A, "na", TestEnum.B, "na2"), noAnnotationMap); - - Map wrappedMap = - injector.getInstance(new Key>() {}); - assertEquals(ImmutableMap.of(wrappedKeyFor(1), 11, wrappedKeyFor(2), 22), wrappedMap); - - Optional fooOptional = - injector.getInstance(new Key>(named("foo")) {}); - assertEquals("foo2", fooOptional.get()); - - Optional barOptional = - injector.getInstance(new Key>(named("bar")) {}); - assertEquals("bar", barOptional.get()); - - Optional noAnnotationOptional = - injector.getInstance(new Key>() {}); - assertEquals("na2", noAnnotationOptional.get()); - } - - enum TestEnum { - A, B - } - - @MapKey(unwrapValue = true) - @Retention(RUNTIME) - @interface TestEnumKey { - TestEnum value(); - } - - @MapKey(unwrapValue = false) - @Retention(RUNTIME) - @interface WrappedKey { - int number(); - } - - @SuppressWarnings("unused") @WrappedKey(number=1) private static Object wrappedKey1Holder; - @SuppressWarnings("unused") @WrappedKey(number=2) private static Object wrappedKey2Holder; - WrappedKey wrappedKeyFor(int number) throws Exception { - Field field; - switch (number) { - case 1: - field = ProvidesIntoTest.class.getDeclaredField("wrappedKey1Holder"); - break; - case 2: - field = ProvidesIntoTest.class.getDeclaredField("wrappedKey2Holder"); - break; - default: - throw new IllegalArgumentException("only 1 or 2 supported"); - } - return field.getAnnotation(WrappedKey.class); - } - - public void testDoubleScannerIsIgnored() { - Injector injector = Guice.createInjector( - MultibindingsScanner.asModule(), - MultibindingsScanner.asModule(), - new AbstractModule() { - @Override protected void configure() {} - @ProvidesIntoSet String provideFoo() { return "foo"; } - } - ); - assertEquals(ImmutableSet.of("foo"), injector.getInstance(new Key>() {})); - } - - @MapKey(unwrapValue = true) - @Retention(RUNTIME) - @interface ArrayUnwrappedKey { - int[] value(); - } - - public void testArrayKeys_unwrapValuesTrue() { - Module m = new AbstractModule() { - @Override protected void configure() {} - @ProvidesIntoMap @ArrayUnwrappedKey({1, 2}) String provideFoo() { return "foo"; } - }; - try { - Guice.createInjector(MultibindingsScanner.asModule(), m); - fail(); - } catch (CreationException ce) { - assertEquals(1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), - "Array types are not allowed in a MapKey with unwrapValue=true: " - + ArrayUnwrappedKey.class.getName(), - "at " + m.getClass().getName() + ".provideFoo("); - } - } - - @MapKey(unwrapValue = false) - @Retention(RUNTIME) - @interface ArrayWrappedKey { - int[] number(); - } - - @SuppressWarnings("unused") @ArrayWrappedKey(number={1, 2}) private static Object arrayWrappedKeyHolder12; - @SuppressWarnings("unused") @ArrayWrappedKey(number={3, 4}) private static Object arrayWrappedKeyHolder34; - ArrayWrappedKey arrayWrappedKeyFor(int number) throws Exception { - Field field; - switch (number) { - case 12: - field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder12"); - break; - case 34: - field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder34"); - break; - default: - throw new IllegalArgumentException("only 1 or 2 supported"); - } - return field.getAnnotation(ArrayWrappedKey.class); - } - - public void testArrayKeys_unwrapValuesFalse() throws Exception { - Module m = new AbstractModule() { - @Override protected void configure() {} - @ProvidesIntoMap @ArrayWrappedKey(number = {1, 2}) String provideFoo() { return "foo"; } - @ProvidesIntoMap @ArrayWrappedKey(number = {3, 4}) String provideBar() { return "bar"; } - }; - Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), m); - Map map = - injector.getInstance(new Key>() {}); - ArrayWrappedKey key12 = arrayWrappedKeyFor(12); - ArrayWrappedKey key34 = arrayWrappedKeyFor(34); - assertEquals("foo", map.get(key12)); - assertEquals("bar", map.get(key34)); - assertEquals(2, map.size()); - } - - public void testProvidesIntoSetWithMapKey() { - Module m = new AbstractModule() { - @Override protected void configure() {} - @ProvidesIntoSet @TestEnumKey(TestEnum.A) String provideFoo() { return "foo"; } - }; - try { - Guice.createInjector(MultibindingsScanner.asModule(), m); - fail(); - } catch (CreationException ce) { - assertEquals(1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), "Found a MapKey annotation on non map binding at " - + m.getClass().getName() + ".provideFoo"); - } - } - - public void testProvidesIntoOptionalWithMapKey() { - Module m = new AbstractModule() { - @Override protected void configure() {} - - @ProvidesIntoOptional(Type.ACTUAL) - @TestEnumKey(TestEnum.A) - String provideFoo() { - return "foo"; - } - }; - try { - Guice.createInjector(MultibindingsScanner.asModule(), m); - fail(); - } catch (CreationException ce) { - assertEquals(1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), "Found a MapKey annotation on non map binding at " - + m.getClass().getName() + ".provideFoo"); - } - } - - public void testProvidesIntoMapWithoutMapKey() { - Module m = new AbstractModule() { - @Override protected void configure() {} - @ProvidesIntoMap String provideFoo() { return "foo"; } - }; - try { - Guice.createInjector(MultibindingsScanner.asModule(), m); - fail(); - } catch (CreationException ce) { - assertEquals(1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), "No MapKey found for map binding at " - + m.getClass().getName() + ".provideFoo"); - } - } - - @MapKey(unwrapValue = true) - @Retention(RUNTIME) - @interface TestEnumKey2 { - TestEnum value(); - } - - public void testMoreThanOneMapKeyAnnotation() { - Module m = new AbstractModule() { - @Override protected void configure() {} - - @ProvidesIntoMap - @TestEnumKey(TestEnum.A) - @TestEnumKey2(TestEnum.B) - String provideFoo() { - return "foo"; - } - }; - try { - Guice.createInjector(MultibindingsScanner.asModule(), m); - fail(); - } catch (CreationException ce) { - assertEquals(1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), "Found more than one MapKey annotations on " - + m.getClass().getName() + ".provideFoo"); - } - } - - @MapKey(unwrapValue = true) - @Retention(RUNTIME) - @interface MissingValueMethod { - } - - public void testMapKeyMissingValueMethod() { - Module m = new AbstractModule() { - @Override protected void configure() {} - - @ProvidesIntoMap - @MissingValueMethod - String provideFoo() { - return "foo"; - } - }; - try { - Guice.createInjector(MultibindingsScanner.asModule(), m); - fail(); - } catch (CreationException ce) { - assertEquals(1, ce.getErrorMessages().size()); - assertContains(ce.getMessage(), "No 'value' method in MapKey with unwrapValue=true: " - + MissingValueMethod.class.getName()); - } - } -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -/** - * Copyright (C) 2014 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import com.google.inject.multibindings.Element.Type; - -import junit.framework.TestCase; - -/** - * Tests for {@link RealElement}. - */ -public class RealElementTest extends TestCase { - - private Element systemElement; - private RealElement realElement; - - @Override protected void setUp() throws Exception { - this.systemElement = Holder.class.getAnnotation(Element.class); - this.realElement = new RealElement("b", Type.MULTIBINDER, "a", 1); - } - - public void testEquals() { - assertEquals(systemElement, realElement); - assertEquals(realElement, systemElement); - } - - public void testHashCode() { - assertEquals(systemElement.hashCode(), realElement.hashCode()); - } - - public void testProperties() { - assertEquals("a", realElement.keyType()); - assertEquals("b", realElement.setName()); - assertEquals(Type.MULTIBINDER, realElement.type()); - assertEquals(1, realElement.uniqueId()); - } - - - @Element(keyType = "a", setName = "b", type = Type.MULTIBINDER, uniqueId = 1) - static class Holder {} - -} diff -Nru sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java --- sisu-guice-3.2.6/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1117 +0,0 @@ -/** - * Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.inject.multibindings; - -import static com.google.inject.multibindings.MapBinder.entryOfProviderOf; -import static com.google.inject.multibindings.MapBinder.mapOf; -import static com.google.inject.multibindings.MapBinder.mapOfJavaxProviderOf; -import static com.google.inject.multibindings.MapBinder.mapOfProviderOf; -import static com.google.inject.multibindings.MapBinder.mapOfSetOfProviderOf; -import static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf; -import static com.google.inject.multibindings.Multibinder.collectionOfProvidersOf; -import static com.google.inject.multibindings.Multibinder.setOf; -import static com.google.inject.multibindings.OptionalBinder.javaOptionalOfJavaxProvider; -import static com.google.inject.multibindings.OptionalBinder.javaOptionalOfProvider; -import static com.google.inject.multibindings.OptionalBinder.optionalOfJavaxProvider; -import static com.google.inject.multibindings.OptionalBinder.optionalOfProvider; -import static com.google.inject.multibindings.SpiUtils.BindType.INSTANCE; -import static com.google.inject.multibindings.SpiUtils.BindType.LINKED; -import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_INSTANCE; -import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_KEY; -import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; -import static com.google.inject.multibindings.SpiUtils.VisitType.INJECTOR; -import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.fail; - -import com.google.common.base.Objects; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.common.collect.Sets; -import com.google.inject.Binding; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.TypeLiteral; -import com.google.inject.multibindings.Indexer.IndexedBinding; -import com.google.inject.multibindings.MapBinder.RealMapBinder.ProviderMapEntry; -import com.google.inject.multibindings.OptionalBinder.Source; -import com.google.inject.spi.DefaultBindingTargetVisitor; -import com.google.inject.spi.Element; -import com.google.inject.spi.Elements; -import com.google.inject.spi.InstanceBinding; -import com.google.inject.spi.LinkedKeyBinding; -import com.google.inject.spi.ProviderInstanceBinding; -import com.google.inject.spi.ProviderKeyBinding; -import com.google.inject.spi.ProviderLookup; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Utilities for testing the Multibinder & MapBinder extension SPI. - * - * @author sameb@google.com (Sam Berlin) - */ -public class SpiUtils { - - private static final boolean HAS_JAVA_OPTIONAL; - static { - Class optional = null; - try { - optional = Class.forName("java.util.Optional"); - } catch (ClassNotFoundException ignored) {} - HAS_JAVA_OPTIONAL = optional != null; - } - - /** The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. */ - enum VisitType { INJECTOR, MODULE, BOTH } - - /** - * Asserts that MapBinderBinding visitors for work correctly. - * - * @param The type of the binding - * @param mapKey The key the map belongs to. - * @param keyType the TypeLiteral of the key of the map - * @param valueType the TypeLiteral of the value of the map - * @param modules The modules that define the mapbindings - * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. - * @param allowDuplicates If duplicates are allowed. - * @param expectedMapBindings The number of other mapbinders we expect to see. - * @param results The kind of bindings contained in the mapbinder. - */ - static void assertMapVisitor(Key mapKey, TypeLiteral keyType, TypeLiteral valueType, - Iterable modules, VisitType visitType, boolean allowDuplicates, - int expectedMapBindings, MapResult... results) { - if(visitType == null) { - fail("must test something"); - } - - if (visitType == BOTH || visitType == INJECTOR) { - mapInjectorTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, - results); - } - - if (visitType == BOTH || visitType == MODULE) { - mapModuleTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, - results); - } - } - - @SuppressWarnings("unchecked") - private static void mapInjectorTest(Key mapKey, TypeLiteral keyType, - TypeLiteral valueType, Iterable modules, boolean allowDuplicates, - int expectedMapBindings, MapResult... results) { - Injector injector = Guice.createInjector(modules); - Visitor visitor = new Visitor(); - Binding mapBinding = injector.getBinding(mapKey); - MapBinderBinding mapbinder = (MapBinderBinding)mapBinding.acceptTargetVisitor(visitor); - assertNotNull(mapbinder); - assertEquals(keyType, mapbinder.getKeyTypeLiteral()); - assertEquals(valueType, mapbinder.getValueTypeLiteral()); - assertEquals(allowDuplicates, mapbinder.permitsDuplicates()); - List>> entries = Lists.newArrayList(mapbinder.getEntries()); - List mapResults = Lists.newArrayList(results); - assertEquals("wrong entries, expected: " + mapResults + ", but was: " + entries, - mapResults.size(), entries.size()); - - for(MapResult result : mapResults) { - Map.Entry> found = null; - for(Map.Entry> entry : entries) { - Object key = entry.getKey(); - Binding value = entry.getValue(); - if(key.equals(result.k) && matches(value, result.v)) { - found = entry; - break; - } - } - if(found == null) { - fail("Could not find entry: " + result + " in remaining entries: " + entries); - } else { - assertTrue("mapBinder doesn't contain: " + found.getValue(), - mapbinder.containsElement(found.getValue())); - entries.remove(found); - } - } - - if(!entries.isEmpty()) { - fail("Found all entries of: " + mapResults + ", but more were left over: " + entries); - } - - Key mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); - Key mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType)); - Key mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); - Key mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType))); - Key setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType))); - Key collectionOfProvidersOfEntryOfProvider = - mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType))); - Key collectionOfJavaxProvidersOfEntryOfProvider = - mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType))); - boolean entrySetMatch = false; - boolean mapJavaxProviderMatch = false; - boolean mapProviderMatch = false; - boolean mapSetMatch = false; - boolean mapSetProviderMatch = false; - boolean collectionOfProvidersOfEntryOfProviderMatch = false; - boolean collectionOfJavaxProvidersOfEntryOfProviderMatch = false; - List otherMapBindings = Lists.newArrayList(); - List otherMatches = Lists.newArrayList(); - Multimap indexedEntries = - MultimapBuilder.hashKeys().hashSetValues().build(); - Indexer indexer = new Indexer(injector); - int duplicates = 0; - for(Binding b : injector.getAllBindings().values()) { - boolean contains = mapbinder.containsElement(b); - Object visited = b.acceptTargetVisitor(visitor); - if(visited instanceof MapBinderBinding) { - if(visited.equals(mapbinder)) { - assertTrue(contains); - } else { - otherMapBindings.add(visited); - } - } else if(b.getKey().equals(mapOfProvider)) { - assertTrue(contains); - mapProviderMatch = true; - } else if (b.getKey().equals(mapOfJavaxProvider)) { - assertTrue(contains); - mapJavaxProviderMatch = true; - } else if(b.getKey().equals(mapOfSet)) { - assertTrue(contains); - mapSetMatch = true; - } else if(b.getKey().equals(mapOfSetOfProvider)) { - assertTrue(contains); - mapSetProviderMatch = true; - } else if(b.getKey().equals(setOfEntry)) { - assertTrue(contains); - entrySetMatch = true; - // Validate that this binding is also a MultibinderBinding. - assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); - } else if(b.getKey().equals(collectionOfProvidersOfEntryOfProvider)) { - assertTrue(contains); - collectionOfProvidersOfEntryOfProviderMatch = true; - } else if(b.getKey().equals(collectionOfJavaxProvidersOfEntryOfProvider)) { - assertTrue(contains); - collectionOfJavaxProvidersOfEntryOfProviderMatch = true; - } else if (contains) { - if (b instanceof ProviderInstanceBinding) { - ProviderInstanceBinding pib = (ProviderInstanceBinding)b; - if (pib.getUserSuppliedProvider() instanceof ProviderMapEntry) { - // weird casting required to workaround compilation issues with jdk6 - ProviderMapEntry pme = - (ProviderMapEntry) (Provider) pib.getUserSuppliedProvider(); - Binding valueBinding = injector.getBinding(pme.getValueKey()); - if (indexer.isIndexable(valueBinding) - && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) { - duplicates++; - } - } - } - otherMatches.add(b); - } - } - - int sizeOfOther = otherMatches.size(); - if(allowDuplicates) { - sizeOfOther--; // account for 1 duplicate binding - } - // Multiply by two because each has a value and Map.Entry. - int expectedSize = 2 * (mapResults.size() + duplicates); - assertEquals("Incorrect other matches: " + otherMatches, expectedSize, sizeOfOther); - assertTrue(entrySetMatch); - assertTrue(mapProviderMatch); - assertTrue(mapJavaxProviderMatch); - assertTrue(collectionOfProvidersOfEntryOfProviderMatch); - assertTrue(collectionOfJavaxProvidersOfEntryOfProviderMatch); - assertEquals(allowDuplicates, mapSetMatch); - assertEquals(allowDuplicates, mapSetProviderMatch); - assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings, - otherMapBindings.size()); - } - - @SuppressWarnings("unchecked") - private static void mapModuleTest(Key mapKey, TypeLiteral keyType, - TypeLiteral valueType, Iterable modules, boolean allowDuplicates, - int expectedMapBindings, MapResult... results) { - Set elements = ImmutableSet.copyOf(Elements.getElements(modules)); - Visitor visitor = new Visitor(); - MapBinderBinding mapbinder = null; - Map, Binding> keyMap = Maps.newHashMap(); - for(Element element : elements) { - if(element instanceof Binding) { - Binding binding = (Binding)element; - keyMap.put(binding.getKey(), binding); - if (binding.getKey().equals(mapKey)) { - mapbinder = (MapBinderBinding)((Binding)binding).acceptTargetVisitor(visitor); - } - } - } - assertNotNull(mapbinder); - - assertEquals(keyType, mapbinder.getKeyTypeLiteral()); - assertEquals(valueType, mapbinder.getValueTypeLiteral()); - List mapResults = Lists.newArrayList(results); - - Key mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType)); - Key mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); - Key mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); - Key mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType))); - Key setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType))); - Key collectionOfProvidersOfEntry = - mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType))); - Key collectionOfJavaxProvidersOfEntry = - mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType))); - boolean entrySetMatch = false; - boolean mapProviderMatch = false; - boolean mapJavaxProviderMatch = false; - boolean mapSetMatch = false; - boolean mapSetProviderMatch = false; - boolean collectionOfProvidersOfEntryMatch = false; - boolean collectionOfJavaxProvidersOfEntryMatch = false; - List otherMapBindings = Lists.newArrayList(); - List otherMatches = Lists.newArrayList(); - List otherElements = Lists.newArrayList(); - Indexer indexer = new Indexer(null); - Multimap indexedEntries = - MultimapBuilder.hashKeys().hashSetValues().build(); - int duplicates = 0; - for(Element element : elements) { - boolean contains = mapbinder.containsElement(element); - if(!contains) { - otherElements.add(element); - } - boolean matched = false; - Key key = null; - Binding b = null; - if(element instanceof Binding) { - b = (Binding)element; - if (b instanceof ProviderInstanceBinding) { - ProviderInstanceBinding pb = (ProviderInstanceBinding) b; - if (pb.getUserSuppliedProvider() instanceof ProviderMapEntry) { - // weird casting required to workaround jdk6 compilation problems - ProviderMapEntry pme = - (ProviderMapEntry) (Provider) pb.getUserSuppliedProvider(); - Binding valueBinding = keyMap.get(pme.getValueKey()); - if (indexer.isIndexable(valueBinding) - && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) { - duplicates++; - } - } - } - - key = b.getKey(); - Object visited = b.acceptTargetVisitor(visitor); - if(visited instanceof MapBinderBinding) { - matched = true; - if(visited.equals(mapbinder)) { - assertTrue(contains); - } else { - otherMapBindings.add(visited); - } - } - } else if(element instanceof ProviderLookup) { - key = ((ProviderLookup)element).getKey(); - } - - if(!matched && key != null) { - if(key.equals(mapOfProvider)) { - matched = true; - assertTrue(contains); - mapProviderMatch = true; - } else if(key.equals(mapOfJavaxProvider)) { - matched = true; - assertTrue(contains); - mapJavaxProviderMatch = true; - } else if(key.equals(mapOfSet)) { - matched = true; - assertTrue(contains); - mapSetMatch = true; - } else if(key.equals(mapOfSetOfProvider)) { - matched = true; - assertTrue(contains); - mapSetProviderMatch = true; - } else if(key.equals(setOfEntry)) { - matched = true; - assertTrue(contains); - entrySetMatch = true; - // Validate that this binding is also a MultibinderBinding. - if(b != null) { - assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); - } - } else if(key.equals(collectionOfProvidersOfEntry)) { - matched = true; - assertTrue(contains); - collectionOfProvidersOfEntryMatch = true; - } else if(key.equals(collectionOfJavaxProvidersOfEntry)) { - matched = true; - assertTrue(contains); - collectionOfJavaxProvidersOfEntryMatch = true; - } - } - - if (!matched && contains) { - otherMatches.add(element); - } - } - - int otherMatchesSize = otherMatches.size(); - if (allowDuplicates) { - otherMatchesSize--; // allow for 1 duplicate binding - } - // Multiply by 3 because each has a value, ProviderLookup, and Map.Entry - int expectedSize = (mapResults.size() + duplicates) * 3; - assertEquals("incorrect number of contains, leftover matches: " + otherMatches, - expectedSize, otherMatchesSize); - - assertTrue(entrySetMatch); - assertTrue(mapProviderMatch); - assertTrue(mapJavaxProviderMatch); - assertTrue(collectionOfProvidersOfEntryMatch); - assertTrue(collectionOfJavaxProvidersOfEntryMatch); - assertEquals(allowDuplicates, mapSetMatch); - assertEquals(allowDuplicates, mapSetProviderMatch); - assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings, - otherMapBindings.size()); - - // Validate that we can construct an injector out of the remaining bindings. - Guice.createInjector(Elements.getModule(otherElements)); - } - - /** - * Asserts that MultibinderBinding visitors work correctly. - * - * @param The type of the binding - * @param setKey The key the set belongs to. - * @param elementType the TypeLiteral of the element - * @param modules The modules that define the multibindings - * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. - * @param allowDuplicates If duplicates are allowed. - * @param expectedMultibindings The number of other multibinders we expect to see. - * @param results The kind of bindings contained in the multibinder. - */ - static void assertSetVisitor(Key> setKey, TypeLiteral elementType, - Iterable modules, VisitType visitType, boolean allowDuplicates, - int expectedMultibindings, BindResult... results) { - if(visitType == null) { - fail("must test something"); - } - - if(visitType == BOTH || visitType == INJECTOR) { - setInjectorTest(setKey, elementType, modules, allowDuplicates, - expectedMultibindings, results); - } - - if(visitType == BOTH || visitType == MODULE) { - setModuleTest(setKey, elementType, modules, allowDuplicates, - expectedMultibindings, results); - } - } - - @SuppressWarnings("unchecked") - private static void setInjectorTest(Key> setKey, TypeLiteral elementType, - Iterable modules, boolean allowDuplicates, int otherMultibindings, - BindResult... results) { - Key collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); - Key collectionOfJavaxProvidersKey = - setKey.ofType(collectionOfJavaxProvidersOf(elementType)); - Injector injector = Guice.createInjector(modules); - Visitor> visitor = new Visitor>(); - Binding> binding = injector.getBinding(setKey); - MultibinderBinding> multibinder = - (MultibinderBinding>)binding.acceptTargetVisitor(visitor); - assertNotNull(multibinder); - assertEquals(elementType, multibinder.getElementTypeLiteral()); - assertEquals(allowDuplicates, multibinder.permitsDuplicates()); - List> elements = Lists.newArrayList(multibinder.getElements()); - List bindResults = Lists.newArrayList(results); - assertEquals("wrong bind elements, expected: " + bindResults - + ", but was: " + multibinder.getElements(), - bindResults.size(), elements.size()); - - for(BindResult result : bindResults) { - Binding found = null; - for(Binding item : elements) { - if (matches(item, result)) { - found = item; - break; - } - } - if(found == null) { - fail("Could not find element: " + result + " in remaining elements: " + elements); - } else { - elements.remove(found); - } - } - - if(!elements.isEmpty()) { - fail("Found all elements of: " + bindResults + ", but more were left over: " + elements); - } - - Set setOfElements = new HashSet(multibinder.getElements()); - Set setOfIndexed = Sets.newHashSet(); - Indexer indexer = new Indexer(injector); - for (Binding oneBinding : setOfElements) { - setOfIndexed.add(oneBinding.acceptTargetVisitor(indexer)); - } - - List otherMultibinders = Lists.newArrayList(); - List otherContains = Lists.newArrayList(); - boolean collectionOfProvidersMatch = false; - boolean collectionOfJavaxProvidersMatch = false; - for(Binding b : injector.getAllBindings().values()) { - boolean contains = multibinder.containsElement(b); - Key key = b.getKey(); - Object visited = b.acceptTargetVisitor(visitor); - if(visited != null) { - if(visited.equals(multibinder)) { - assertTrue(contains); - } else { - otherMultibinders.add(visited); - } - } else if(setOfElements.contains(b)) { - assertTrue(contains); - } else if (key.equals(collectionOfProvidersKey)) { - assertTrue(contains); - collectionOfProvidersMatch = true; - } else if (key.equals(collectionOfJavaxProvidersKey)) { - assertTrue(contains); - collectionOfJavaxProvidersMatch = true; - } else if (contains) { - if (!indexer.isIndexable(b) || !setOfIndexed.contains(b.acceptTargetVisitor(indexer))) { - otherContains.add(b); - } - } - } - - assertTrue(collectionOfProvidersMatch); - assertTrue(collectionOfJavaxProvidersMatch); - - if(allowDuplicates) { - assertEquals("contained more than it should: " + otherContains, 1, otherContains.size()); - } else { - assertTrue("contained more than it should: " + otherContains, otherContains.isEmpty()); - } - assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings, - otherMultibinders.size()); - - } - - @SuppressWarnings("unchecked") - private static void setModuleTest(Key> setKey, TypeLiteral elementType, - Iterable modules, boolean allowDuplicates, int otherMultibindings, - BindResult... results) { - Key collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); - Key collectionOfJavaxProvidersKey = - setKey.ofType(collectionOfJavaxProvidersOf(elementType)); - List bindResults = Lists.newArrayList(results); - List elements = Elements.getElements(modules); - Visitor visitor = new Visitor(); - MultibinderBinding> multibinder = null; - for(Element element : elements) { - if(element instanceof Binding && ((Binding)element).getKey().equals(setKey)) { - multibinder = (MultibinderBinding>)((Binding)element).acceptTargetVisitor(visitor); - break; - } - } - assertNotNull(multibinder); - - assertEquals(elementType, multibinder.getElementTypeLiteral()); - List otherMultibinders = Lists.newArrayList(); - Set otherContains = new HashSet(); - List otherElements = Lists.newArrayList(); - int duplicates = 0; - Set setOfIndexed = Sets.newHashSet(); - Indexer indexer = new Indexer(null); - boolean collectionOfProvidersMatch = false; - boolean collectionOfJavaxProvidersMatch = false; - for(Element element : elements) { - boolean contains = multibinder.containsElement(element); - if(!contains) { - otherElements.add(element); - } - boolean matched = false; - Key key = null; - if(element instanceof Binding) { - Binding binding = (Binding)element; - if (indexer.isIndexable(binding) - && !setOfIndexed.add((IndexedBinding) binding.acceptTargetVisitor(indexer))) { - duplicates++; - } - key = binding.getKey(); - Object visited = binding.acceptTargetVisitor(visitor); - if(visited != null) { - matched = true; - if(visited.equals(multibinder)) { - assertTrue(contains); - } else { - otherMultibinders.add(visited); - } - } - } - - if (collectionOfProvidersKey.equals(key)) { - assertTrue(contains); - assertFalse(matched); - collectionOfProvidersMatch = true; - } else if (collectionOfJavaxProvidersKey.equals(key)) { - assertTrue(contains); - assertFalse(matched); - collectionOfJavaxProvidersMatch = true; - } else if (!matched && contains) { - otherContains.add(element); - } - } - - if(allowDuplicates) { - assertEquals("wrong contained elements: " + otherContains, - bindResults.size() + 1 + duplicates, otherContains.size()); - } else { - assertEquals("wrong contained elements: " + otherContains, - bindResults.size() + duplicates, otherContains.size()); - } - - assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings, - otherMultibinders.size()); - assertTrue(collectionOfProvidersMatch); - assertTrue(collectionOfJavaxProvidersMatch); - - // Validate that we can construct an injector out of the remaining bindings. - Guice.createInjector(Elements.getModule(otherElements)); - } - - /** - * Asserts that OptionalBinderBinding visitors for work correctly. - * - * @param The type of the binding - * @param keyType The key OptionalBinder is binding - * @param modules The modules that define the bindings - * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) - * test, or both. - * @param expectedOtherOptionalBindings the # of other optional bindings we expect to see. - * @param expectedDefault the expected default binding, or null if none - * @param expectedActual the expected actual binding, or null if none - * @param expectedUserLinkedActual the user binding that is the actual binding, used if - * neither the default nor actual are set and a user binding existed for the type. - */ - static void assertOptionalVisitor(Key keyType, - Iterable modules, - VisitType visitType, - int expectedOtherOptionalBindings, - BindResult expectedDefault, - BindResult expectedActual, - BindResult expectedUserLinkedActual) { - if (visitType == null) { - fail("must test something"); - } - - // if java.util.Optional is bound, there'll be twice as many as we expect. - if (HAS_JAVA_OPTIONAL) { - expectedOtherOptionalBindings *= 2; - } - - if (visitType == BOTH || visitType == INJECTOR) { - optionalInjectorTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault, - expectedActual, expectedUserLinkedActual); - } - - if (visitType == BOTH || visitType == MODULE) { - optionalModuleTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault, - expectedActual, expectedUserLinkedActual); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static void optionalInjectorTest(Key keyType, - Iterable modules, - int expectedOtherOptionalBindings, - BindResult expectedDefault, - BindResult expectedActual, - BindResult expectedUserLinkedActual) { - if (expectedUserLinkedActual != null) { - assertNull("cannot have actual if expecting user binding", expectedActual); - assertNull("cannot have default if expecting user binding", expectedDefault); - } - - Key> optionalKey = - keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral())); - Key javaOptionalKey = HAS_JAVA_OPTIONAL ? - keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null; - Injector injector = Guice.createInjector(modules); - Binding> optionalBinding = injector.getBinding(optionalKey); - Visitor visitor = new Visitor(); - OptionalBinderBinding> optionalBinder = - (OptionalBinderBinding>) optionalBinding.acceptTargetVisitor(visitor); - assertNotNull(optionalBinder); - assertEquals(optionalKey, optionalBinder.getKey()); - - Binding javaOptionalBinding = null; - OptionalBinderBinding javaOptionalBinder = null; - if (HAS_JAVA_OPTIONAL) { - javaOptionalBinding = injector.getBinding(javaOptionalKey); - javaOptionalBinder = (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor); - assertNotNull(javaOptionalBinder); - assertEquals(javaOptionalKey, javaOptionalBinder.getKey()); - } - - if (expectedDefault == null) { - assertNull("did not expect a default binding", optionalBinder.getDefaultBinding()); - if (HAS_JAVA_OPTIONAL) { - assertNull("did not expect a default binding", javaOptionalBinder.getDefaultBinding()); - } - } else { - assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: " - + optionalBinder.getDefaultBinding(), - matches(optionalBinder.getDefaultBinding(), expectedDefault)); - if (HAS_JAVA_OPTIONAL) { - assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: " - + javaOptionalBinder.getDefaultBinding(), - matches(javaOptionalBinder.getDefaultBinding(), expectedDefault)); - } - } - - if (expectedActual == null && expectedUserLinkedActual == null) { - assertNull(optionalBinder.getActualBinding()); - if (HAS_JAVA_OPTIONAL) { - assertNull(javaOptionalBinder.getActualBinding()); - } - } else if (expectedActual != null) { - assertTrue("expectedActual: " + expectedActual + ", actualActual: " - + optionalBinder.getActualBinding(), - matches(optionalBinder.getActualBinding(), expectedActual)); - if (HAS_JAVA_OPTIONAL) { - assertTrue("expectedActual: " + expectedActual + ", actualActual: " - + javaOptionalBinder.getActualBinding(), - matches(javaOptionalBinder.getActualBinding(), expectedActual)); - } - } else if (expectedUserLinkedActual != null) { - assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: " - + optionalBinder.getActualBinding(), - matches(optionalBinder.getActualBinding(), expectedUserLinkedActual)); - if (HAS_JAVA_OPTIONAL) { - assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: " - + javaOptionalBinder.getActualBinding(), - matches(javaOptionalBinder.getActualBinding(), expectedUserLinkedActual)); - } - } - - - Key>> optionalJavaxProviderKey = - keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral())); - Key javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ? - keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null; - Key>> optionalProviderKey = - keyType.ofType(optionalOfProvider(keyType.getTypeLiteral())); - Key javaOptionalProviderKey = HAS_JAVA_OPTIONAL ? - keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null; - - boolean keyMatch = false; - boolean optionalKeyMatch = false; - boolean javaOptionalKeyMatch = false; - boolean optionalJavaxProviderKeyMatch = false; - boolean javaOptionalJavaxProviderKeyMatch = false; - boolean optionalProviderKeyMatch = false; - boolean javaOptionalProviderKeyMatch = false; - boolean defaultMatch = false; - boolean actualMatch = false; - List otherOptionalBindings = Lists.newArrayList(); - List otherMatches = Lists.newArrayList(); - for (Binding b : injector.getAllBindings().values()) { - boolean contains = optionalBinder.containsElement(b); - if (HAS_JAVA_OPTIONAL) { - assertEquals(contains, javaOptionalBinder.containsElement(b)); - } - Object visited = b.acceptTargetVisitor(visitor); - if (visited instanceof OptionalBinderBinding) { - if (visited.equals(optionalBinder)) { - assertTrue(contains); - } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) { - assertTrue(contains); - } else { - otherOptionalBindings.add(visited); - } - } - if (b.getKey().equals(keyType)) { - // keyType might match because a user bound it - // (which is possible in a purely absent OptionalBinder) - assertEquals(expectedDefault != null || expectedActual != null, contains); - if (contains) { - keyMatch = true; - } - } else if (b.getKey().equals(optionalKey)) { - assertTrue(contains); - optionalKeyMatch = true; - } else if (b.getKey().equals(javaOptionalKey)) { - assertTrue(contains); - javaOptionalKeyMatch = true; - } else if (b.getKey().equals(optionalJavaxProviderKey)) { - assertTrue(contains); - optionalJavaxProviderKeyMatch = true; - } else if (b.getKey().equals(javaOptionalJavaxProviderKey)) { - assertTrue(contains); - javaOptionalJavaxProviderKeyMatch = true; - } else if (b.getKey().equals(optionalProviderKey)) { - assertTrue(contains); - optionalProviderKeyMatch = true; - } else if (b.getKey().equals(javaOptionalProviderKey)) { - assertTrue(contains); - javaOptionalProviderKeyMatch = true; - } else if (expectedDefault != null && matches(b, expectedDefault)) { - assertTrue(contains); - defaultMatch = true; - } else if (expectedActual != null && matches(b, expectedActual)) { - assertTrue(contains); - actualMatch = true; - } else if (contains) { - otherMatches.add(b); - } - } - - assertEquals(otherMatches.toString(), 0, otherMatches.size()); - // only expect a keymatch if either default or actual are set - assertEquals(expectedDefault != null || expectedActual != null, keyMatch); - assertTrue(optionalKeyMatch); - assertTrue(optionalJavaxProviderKeyMatch); - assertTrue(optionalProviderKeyMatch); - assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch); - assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch); - assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch); - assertEquals(expectedDefault != null, defaultMatch); - assertEquals(expectedActual != null, actualMatch); - assertEquals("other OptionalBindings found: " + otherOptionalBindings, - expectedOtherOptionalBindings, otherOptionalBindings.size()); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static void optionalModuleTest(Key keyType, - Iterable modules, - int expectedOtherOptionalBindings, - BindResult expectedDefault, - BindResult expectedActual, - BindResult expectedUserLinkedActual) { - if (expectedUserLinkedActual != null) { - assertNull("cannot have actual if expecting user binding", expectedActual); - assertNull("cannot have default if expecting user binding", expectedDefault); - } - Set elements = ImmutableSet.copyOf(Elements.getElements(modules)); - Map, Binding> indexed = index(elements); - Key> optionalKey = - keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral())); - Key javaOptionalKey = HAS_JAVA_OPTIONAL ? - keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null; - Visitor visitor = new Visitor(); - OptionalBinderBinding> optionalBinder = null; - OptionalBinderBinding javaOptionalBinder = null; - Key defaultKey = null; - Key actualKey = null; - - Binding optionalBinding = indexed.get(optionalKey); - optionalBinder = - (OptionalBinderBinding>) optionalBinding.acceptTargetVisitor(visitor); - - if (HAS_JAVA_OPTIONAL) { - Binding javaOptionalBinding = indexed.get(javaOptionalKey); - javaOptionalBinder = (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor); - } - - // Locate the defaultKey & actualKey - for (Element element : elements) { - if (optionalBinder.containsElement(element) && element instanceof Binding) { - Binding binding = (Binding) element; - if (isSourceEntry(binding, Source.DEFAULT)) { - defaultKey = binding.getKey(); - } else if (isSourceEntry(binding, Source.ACTUAL)) { - actualKey = binding.getKey(); - } - } - } - assertNotNull(optionalBinder); - if (HAS_JAVA_OPTIONAL) { - assertNotNull(javaOptionalBinder); - } - assertEquals(expectedDefault == null, defaultKey == null); - assertEquals(expectedActual == null, actualKey == null); - - Key>> optionalJavaxProviderKey = - keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral())); - Key javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ? - keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null; - Key>> optionalProviderKey = - keyType.ofType(optionalOfProvider(keyType.getTypeLiteral())); - Key javaOptionalProviderKey = HAS_JAVA_OPTIONAL ? - keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null; - boolean keyMatch = false; - boolean optionalKeyMatch = false; - boolean javaOptionalKeyMatch = false; - boolean optionalJavaxProviderKeyMatch = false; - boolean javaOptionalJavaxProviderKeyMatch = false; - boolean optionalProviderKeyMatch = false; - boolean javaOptionalProviderKeyMatch = false; - boolean defaultMatch = false; - boolean actualMatch = false; - List otherOptionalElements = Lists.newArrayList(); - List otherContains = Lists.newArrayList(); - List nonContainedElements = Lists.newArrayList(); - for (Element element : elements) { - boolean contains = optionalBinder.containsElement(element); - if (HAS_JAVA_OPTIONAL) { - assertEquals(contains, javaOptionalBinder.containsElement(element)); - } - if (!contains) { - nonContainedElements.add(element); - } - Key key = null; - Binding b = null; - if (element instanceof Binding) { - b = (Binding) element; - key = b.getKey(); - Object visited = b.acceptTargetVisitor(visitor); - if (visited instanceof OptionalBinderBinding) { - if (visited.equals(optionalBinder)) { - assertTrue(contains); - } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) { - assertTrue(contains); - } else { - otherOptionalElements.add(visited); - } - } - } else if (element instanceof ProviderLookup) { - key = ((ProviderLookup) element).getKey(); - } - - if (key != null && key.equals(keyType)) { - // keyType might match because a user bound it - // (which is possible in a purely absent OptionalBinder) - assertEquals(expectedDefault != null || expectedActual != null, contains); - if (contains) { - keyMatch = true; - } - } else if (key != null && key.equals(optionalKey)) { - assertTrue(contains); - optionalKeyMatch = true; - } else if (key != null && key.equals(javaOptionalKey)) { - assertTrue(contains); - javaOptionalKeyMatch = true; - } else if (key != null && key.equals(optionalJavaxProviderKey)) { - assertTrue(contains); - optionalJavaxProviderKeyMatch = true; - } else if (key != null && key.equals(javaOptionalJavaxProviderKey)) { - assertTrue(contains); - javaOptionalJavaxProviderKeyMatch = true; - } else if (key != null && key.equals(optionalProviderKey)) { - assertTrue(contains); - optionalProviderKeyMatch = true; - } else if (key != null && key.equals(javaOptionalProviderKey)) { - assertTrue(contains); - javaOptionalProviderKeyMatch = true; - } else if (key != null && key.equals(defaultKey)) { - assertTrue(contains); - if (b != null) { // otherwise it might just be a ProviderLookup into it - assertTrue("expected: " + expectedDefault + ", but was: " + b, - matches(b, expectedDefault)); - defaultMatch = true; - } - } else if (key != null && key.equals(actualKey)) { - assertTrue(contains); - if (b != null) { // otherwise it might just be a ProviderLookup into it - assertTrue("expected: " + expectedActual + ", but was: " + b, matches(b, expectedActual)); - actualMatch = true; - } - } else if (contains) { - otherContains.add(element); - } - } - - // only expect a keymatch if either default or actual are set - assertEquals(expectedDefault != null || expectedActual != null, keyMatch); - assertTrue(optionalKeyMatch); - assertTrue(optionalJavaxProviderKeyMatch); - assertTrue(optionalProviderKeyMatch); - assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch); - assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch); - assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch); - assertEquals(expectedDefault != null, defaultMatch); - assertEquals(expectedActual != null, actualMatch); - assertEquals(otherContains.toString(), 0, otherContains.size()); - assertEquals("other OptionalBindings found: " + otherOptionalElements, - expectedOtherOptionalBindings, otherOptionalElements.size()); - - // Validate that we can construct an injector out of the remaining bindings. - Guice.createInjector(Elements.getModule(nonContainedElements)); - } - - private static boolean isSourceEntry(Binding b, Source type) { - switch(type) { - case ACTUAL: - return b.getKey().getAnnotation() instanceof OptionalBinder.Actual; - case DEFAULT: - return b.getKey().getAnnotation() instanceof OptionalBinder.Default; - default: - throw new IllegalStateException("invalid type: " + type); - } - } - - /** Returns the subset of elements that have keys, indexed by them. */ - private static Map, Binding> index(Iterable elements) { - ImmutableMap.Builder, Binding> builder = ImmutableMap.builder(); - for (Element element : elements) { - if (element instanceof Binding) { - builder.put(((Binding) element).getKey(), (Binding) element); - } - } - return builder.build(); - } - - static MapResult instance(K k, V v) { - return new MapResult(k, new BindResult(INSTANCE, v, null)); - } - - static MapResult linked(K k, Class clazz) { - return new MapResult(k, new BindResult(LINKED, null, Key.get(clazz))); - } - - static MapResult linked(K k, Key key) { - return new MapResult(k, new BindResult(LINKED, null, key)); - } - - static MapResult providerInstance(K k, V v) { - return new MapResult(k, new BindResult(PROVIDER_INSTANCE, v, null)); - } - - static class MapResult { - private final K k; - private final BindResult v; - - MapResult(K k, BindResult v) { - this.k = k; - this.v = v; - } - - @Override - public String toString() { - return "entry[key[" + k + "],value[" + v + "]]"; - } - } - - private static boolean matches(Binding item, BindResult result) { - switch (result.type) { - case INSTANCE: - if (item instanceof InstanceBinding - && ((InstanceBinding) item).getInstance().equals(result.instance)) { - return true; - } - break; - case LINKED: - if (item instanceof LinkedKeyBinding - && ((LinkedKeyBinding) item).getLinkedKey().equals(result.key)) { - return true; - } - break; - case PROVIDER_INSTANCE: - if (item instanceof ProviderInstanceBinding - && Objects.equal(((ProviderInstanceBinding) item).getUserSuppliedProvider().get(), - result.instance)) { - return true; - } - break; - case PROVIDER_KEY: - if (item instanceof ProviderKeyBinding - && ((ProviderKeyBinding) item).getProviderKey().equals(result.key)) { - return true; - } - break; - } - return false; - } - - static BindResult instance(T t) { - return new BindResult(INSTANCE, t, null); - } - - static BindResult linked(Class clazz) { - return new BindResult(LINKED, null, Key.get(clazz)); - } - - static BindResult linked(Key key) { - return new BindResult(LINKED, null, key); - } - - static BindResult providerInstance(T t) { - return new BindResult(PROVIDER_INSTANCE, t, null); - } - - static BindResult providerKey(Key key) { - return new BindResult(PROVIDER_KEY, null, key); - } - - /** The kind of binding. */ - static enum BindType { INSTANCE, LINKED, PROVIDER_INSTANCE, PROVIDER_KEY } - /** The result of the binding. */ - static class BindResult { - private final BindType type; - private final Key key; - private final T instance; - - private BindResult(BindType type, T instance, Key key) { - this.type = type; - this.instance = instance; - this.key = key; - } - - @Override - public String toString() { - switch(type) { - case INSTANCE: - return "instance[" + instance + "]"; - case LINKED: - return "linkedKey[" + key + "]"; - case PROVIDER_INSTANCE: - return "providerInstance[" + instance + "]"; - case PROVIDER_KEY: - return "providerKey[" + key + "]"; - } - return null; - } - } - - private static class Visitor extends - DefaultBindingTargetVisitor implements MultibindingsTargetVisitor { - - public Object visit(MultibinderBinding multibinding) { - return multibinding; - } - - public Object visit(MapBinderBinding mapbinding) { - return mapbinding; - } - - public Object visit(OptionalBinderBinding optionalbinding) { - return optionalbinding; - } - } -} diff -Nru sisu-guice-3.2.6/extensions/persist/pom.xml sisu-guice-4.2.0/extensions/persist/pom.xml --- sisu-guice-3.2.6/extensions/persist/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject extensions-parent - 3.2.6 + 4.2.0 guice-persist @@ -63,4 +63,19 @@ test + + + + + maven-jar-plugin + + + + com.google.guice.extensions.persist + + + + + + diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/Finder.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/Finder.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/Finder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/Finder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,20 +32,18 @@ @Retention(RetentionPolicy.RUNTIME) public @interface Finder { /** - * Returns the configured named query's name. Specify a named query's name - * here. This name is typically specified in your JPA configuration. + * Returns the configured named query's name. Specify a named query's name here. This name is + * typically specified in your JPA configuration. */ String namedQuery() default ""; - /** - * Returns the configured query string. Directly specify a JPAQL query here. - */ + /** Returns the configured query string. Directly specify a JPAQL query here. */ String query() default ""; /** - * Returns the configured autoboxing collection class. - * Use this clause to specify a collection impl to autobox result lists into. The impl must - * have a default no-arg constructor and be a subclass of {@code java.util.Collection}. + * Returns the configured autoboxing collection class. Use this clause to specify a collection + * impl to autobox result lists into. The impl must have a default no-arg constructor and be a + * subclass of {@code java.util.Collection}. */ Class returnAs() default Collection.class; -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,13 +22,12 @@ import java.lang.annotation.Target; /** - * Annotate any dynamic finder method's integer argument with this to pass in - * the index of the first result in the result set you are interested in. - * Useful for paging result sets. Complemented by {@link MaxResults}. + * Annotate any dynamic finder method's integer argument with this to pass in the index of the first + * result in the result set you are interested in. Useful for paging result sets. Complemented by + * {@link MaxResults}. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface FirstResult { -} +public @interface FirstResult {} diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,13 +22,11 @@ import java.lang.annotation.Target; /** - * Annotate any dynamic finder method's integer argument with this to pass in - * the maximum size of returned result window. Usefule for paging result sets. - * Complement of {@link FirstResult}. + * Annotate any dynamic finder method's integer argument with this to pass in the maximum size of + * returned result window. Usefule for paging result sets. Complement of {@link FirstResult}. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface MaxResults { -} +public @interface MaxResults {} diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/package-info.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/package-info.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/finder/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/finder/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,5 @@ * limitations under the License. */ -/** - * Dynamic Finder API for Guice Persist. - */ +/** Dynamic Finder API for Guice Persist. */ package com.google.inject.persist.finder; diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,10 +24,6 @@ import com.google.inject.persist.finder.Finder; import com.google.inject.persist.finder.FirstResult; import com.google.inject.persist.finder.MaxResults; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -35,9 +31,10 @@ import java.util.Collection; import java.util.List; import java.util.Map; - import javax.persistence.EntityManager; import javax.persistence.Query; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; /** * TODO(dhanji): Make this work!! @@ -54,6 +51,7 @@ this.emProvider = emProvider; } + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { EntityManager em = emProvider.get(); @@ -82,31 +80,33 @@ return result; } - private Object getAsCollection(JpaFinderProxy.FinderDescriptor finderDescriptor, - List results) { + private Object getAsCollection(JpaFinderProxy.FinderDescriptor finderDescriptor, List results) { Collection collection; try { collection = (Collection) finderDescriptor.returnCollectionTypeConstructor.newInstance(); } catch (InstantiationException e) { throw new RuntimeException( "Specified collection class of Finder's returnAs could not be instantated: " - + finderDescriptor.returnCollectionType, e); + + finderDescriptor.returnCollectionType, + e); } catch (IllegalAccessException e) { throw new RuntimeException( "Specified collection class of Finder's returnAs could not be instantated (do not have access privileges): " - + finderDescriptor.returnCollectionType, e); + + finderDescriptor.returnCollectionType, + e); } catch (InvocationTargetException e) { throw new RuntimeException( "Specified collection class of Finder's returnAs could not be instantated (it threw an exception): " - + finderDescriptor.returnCollectionType, e); + + finderDescriptor.returnCollectionType, + e); } collection.addAll(results); return collection; } - private void bindQueryNamedParameters(Query jpaQuery, - JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) { + private void bindQueryNamedParameters( + Query jpaQuery, JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) { for (int i = 0; i < arguments.length; i++) { Object argument = arguments[i]; Object annotation = descriptor.parameterAnnotations[i]; @@ -114,7 +114,7 @@ if (null == annotation) //noinspection UnnecessaryContinue { - continue; //skip param as it's not bindable + continue; //skip param as it's not bindable } else if (annotation instanceof Named) { Named named = (Named) annotation; jpaQuery.setParameter(named.value(), argument); @@ -129,8 +129,8 @@ } } - private void bindQueryRawParameters(Query jpaQuery, - JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) { + private void bindQueryRawParameters( + Query jpaQuery, JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) { for (int i = 0, index = 1; i < arguments.length; i++) { Object argument = arguments[i]; Object annotation = descriptor.parameterAnnotations[i]; @@ -189,7 +189,7 @@ } else if (MaxResults.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; - } //leave as null for no binding + } //leave as null for no binding } } @@ -201,13 +201,14 @@ && finderDescriptor.returnClass != Collection.class) { finderDescriptor.returnCollectionType = finder.returnAs(); try { - finderDescriptor.returnCollectionTypeConstructor = finderDescriptor.returnCollectionType - .getConstructor(); - finderDescriptor.returnCollectionTypeConstructor.setAccessible(true); //UGH! + finderDescriptor.returnCollectionTypeConstructor = + finderDescriptor.returnCollectionType.getConstructor(); + finderDescriptor.returnCollectionTypeConstructor.setAccessible(true); //UGH! } catch (NoSuchMethodException e) { throw new RuntimeException( "Finder's collection return type specified has no default constructor! returnAs: " - + finderDescriptor.returnCollectionType, e); + + finderDescriptor.returnCollectionType, + e); } } @@ -238,19 +239,17 @@ return JpaFinderProxy.ReturnType.PLAIN; } - /** - * A wrapper data class that caches information about a finder method. - */ + /** A wrapper data class that caches information about a finder method. */ private static class FinderDescriptor { private volatile boolean isKeyedQuery = false; volatile boolean isBindAsRawParameters = true; - //should we treat the query as having ? instead of :named params + //should we treat the query as having ? instead of :named params volatile JpaFinderProxy.ReturnType returnType; volatile Class returnClass; volatile Class returnCollectionType; volatile Constructor returnCollectionTypeConstructor; volatile Object[] parameterAnnotations; - //contract is: null = no bind, @Named = param, @FirstResult/@MaxResults for paging + //contract is: null = no bind, @Named = param, @FirstResult/@MaxResults for paging private String query; private String name; @@ -274,6 +273,8 @@ } private static enum ReturnType { - PLAIN, COLLECTION, ARRAY + PLAIN, + COLLECTION, + ARRAY } } diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.persist.jpa; import com.google.inject.BindingAnnotation; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -27,4 +26,5 @@ * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Retention(RetentionPolicy.RUNTIME) -@BindingAnnotation @interface Jpa {} +@BindingAnnotation +@interface Jpa {} diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,33 +19,27 @@ import com.google.inject.Inject; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - import java.lang.reflect.Method; - import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ class JpaLocalTxnInterceptor implements MethodInterceptor { // TODO(gak): Move these args to the cxtor & make these final. - @Inject - private JpaPersistService emProvider = null; + @Inject private JpaPersistService emProvider = null; - @Inject - private UnitOfWork unitOfWork = null; + @Inject private UnitOfWork unitOfWork = null; @Transactional private static class Internal {} // Tracks if the unit of work was begun implicitly by this transaction. - private final ThreadLocal didWeStartWork = new ThreadLocal(); + private final ThreadLocal didWeStartWork = new ThreadLocal<>(); + @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { // Should we start a unit of work? @@ -91,7 +85,7 @@ txn.commit(); } finally { //close the em if necessary - if (null != didWeStartWork.get() ) { + if (null != didWeStartWork.get()) { didWeStartWork.remove(); unitOfWork.end(); } @@ -127,8 +121,8 @@ * @param e The exception to test for rollback * @param txn A JPA Transaction to issue rollbacks on */ - private boolean rollbackIfNecessary(Transactional transactional, Exception e, - EntityTransaction txn) { + private boolean rollbackIfNecessary( + Transactional transactional, Exception e, EntityTransaction txn) { boolean commit = true; //check rollback clauses diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,26 +21,21 @@ import com.google.inject.Inject; import com.google.inject.Provides; import com.google.inject.Singleton; -import com.google.inject.TypeLiteral; import com.google.inject.persist.PersistModule; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; import com.google.inject.persist.finder.DynamicFinder; import com.google.inject.persist.finder.Finder; -import com.google.inject.util.Providers; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - import java.lang.reflect.AccessibleObject; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import java.util.Map; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; /** * JPA provider for guice persist. @@ -51,15 +46,16 @@ private final String jpaUnit; public JpaPersistModule(String jpaUnit) { - Preconditions.checkArgument(null != jpaUnit && jpaUnit.length() > 0, - "JPA unit name must be a non-empty string."); + Preconditions.checkArgument( + null != jpaUnit && jpaUnit.length() > 0, "JPA unit name must be a non-empty string."); this.jpaUnit = jpaUnit; } - private Map properties; + private Map properties; private MethodInterceptor transactionInterceptor; - @Override protected void configurePersistence() { + @Override + protected void configurePersistence() { bindConstant().annotatedWith(Jpa.class).to(jpaUnit); bind(JpaPersistService.class).in(Singleton.class); @@ -79,21 +75,25 @@ } } - @Override protected MethodInterceptor getTransactionInterceptor() { + @Override + protected MethodInterceptor getTransactionInterceptor() { return transactionInterceptor; } - @Provides @Jpa Map provideProperties() { + @Provides + @Jpa + Map provideProperties() { return properties; } /** * Configures the JPA persistence provider with a set of properties. - * - * @param properties A set of name value pairs that configure a JPA persistence - * provider as per the specification. + * + * @param properties A set of name value pairs that configure a JPA persistence provider as per + * the specification. + * @since 4.0 (since 3.0 with a parameter type of {@code java.util.Properties}) */ - public JpaPersistModule properties(Map properties) { + public JpaPersistModule properties(Map properties) { this.properties = properties; return this; } @@ -115,48 +115,60 @@ return; } - InvocationHandler finderInvoker = new InvocationHandler() { - @Inject JpaFinderProxy finderProxy; - - public Object invoke(final Object thisObject, final Method method, final Object[] args) - throws Throwable { - - // Don't intercept non-finder methods like equals and hashcode. - if (!method.isAnnotationPresent(Finder.class)) { - // NOTE(dhanji): This is not ideal, we are using the invocation handler's equals - // and hashcode as a proxy (!) for the proxy's equals and hashcode. - return method.invoke(this, args); - } - - return finderProxy.invoke(new MethodInvocation() { - public Method getMethod() { - return method; - } - - public Object[] getArguments() { - return null == args ? new Object[0] : args; - } - - public Object proceed() throws Throwable { - return method.invoke(thisObject, args); + InvocationHandler finderInvoker = + new InvocationHandler() { + @Inject JpaFinderProxy finderProxy; + + @Override + public Object invoke(final Object thisObject, final Method method, final Object[] args) + throws Throwable { + + // Don't intercept non-finder methods like equals and hashcode. + if (!method.isAnnotationPresent(Finder.class)) { + // NOTE(dhanji): This is not ideal, we are using the invocation handler's equals + // and hashcode as a proxy (!) for the proxy's equals and hashcode. + return method.invoke(this, args); + } + + return finderProxy.invoke( + new MethodInvocation() { + @Override + public Method getMethod() { + return method; + } + + @Override + public Object[] getArguments() { + return null == args ? new Object[0] : args; + } + + @Override + public Object proceed() throws Throwable { + return method.invoke(thisObject, args); + } + + @Override + public Object getThis() { + throw new UnsupportedOperationException( + "Bottomless proxies don't expose a this."); + } + + @Override + public AccessibleObject getStaticPart() { + throw new UnsupportedOperationException(); + } + }); } - - public Object getThis() { - throw new UnsupportedOperationException("Bottomless proxies don't expose a this."); - } - - public AccessibleObject getStaticPart() { - throw new UnsupportedOperationException(); - } - }); - } - }; + }; requestInjection(finderInvoker); @SuppressWarnings("unchecked") // Proxy must produce instance of type given. - T proxy = (T) Proxy - .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { iface }, - finderInvoker); + T proxy = + (T) + Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + new Class[] {iface}, + finderInvoker); bind(iface).toInstance(proxy); } @@ -171,8 +183,12 @@ for (Method method : iface.getMethods()) { DynamicFinder finder = DynamicFinder.from(method); if (null == finder) { - addError("Dynamic Finder methods must be annotated with @Finder, but " + iface - + "." + method.getName() + " was not"); + addError( + "Dynamic Finder methods must be annotated with @Finder, but " + + iface + + "." + + method.getName() + + " was not"); valid = false; } } diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,44 +23,43 @@ import com.google.inject.Singleton; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; - import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Map; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Singleton class JpaPersistService implements Provider, UnitOfWork, PersistService { - private final ThreadLocal entityManager = new ThreadLocal(); + private final ThreadLocal entityManager = new ThreadLocal<>(); private final String persistenceUnitName; - private final Map persistenceProperties; + private final Map persistenceProperties; @Inject - public JpaPersistService(@Jpa String persistenceUnitName, - @Nullable @Jpa Map persistenceProperties) { + public JpaPersistService( + @Jpa String persistenceUnitName, @Nullable @Jpa Map persistenceProperties) { this.persistenceUnitName = persistenceUnitName; this.persistenceProperties = persistenceProperties; } + @Override public EntityManager get() { if (!isWorking()) { begin(); } EntityManager em = entityManager.get(); - Preconditions.checkState(null != em, "Requested EntityManager outside work unit. " - + "Try calling UnitOfWork.begin() first, or use a PersistFilter if you " - + "are inside a servlet environment."); + Preconditions.checkState( + null != em, + "Requested EntityManager outside work unit. " + + "Try calling UnitOfWork.begin() first, or use a PersistFilter if you " + + "are inside a servlet environment."); return em; } @@ -69,14 +68,17 @@ return entityManager.get() != null; } + @Override public void begin() { - Preconditions.checkState(null == entityManager.get(), + Preconditions.checkState( + null == entityManager.get(), "Work already begun on this thread. Looks like you have called UnitOfWork.begin() twice" - + " without a balancing call to end() in between."); + + " without a balancing call to end() in between."); entityManager.set(emFactory.createEntityManager()); } + @Override public void end() { EntityManager em = entityManager.get(); @@ -87,8 +89,7 @@ try { em.close(); - } - finally { + } finally { entityManager.remove(); } } @@ -100,17 +101,19 @@ this.emFactory = emFactory; } + @Override public synchronized void start() { Preconditions.checkState(null == emFactory, "Persistence service was already initialized."); if (null != persistenceProperties) { - this.emFactory = Persistence - .createEntityManagerFactory(persistenceUnitName, persistenceProperties); + this.emFactory = + Persistence.createEntityManagerFactory(persistenceUnitName, persistenceProperties); } else { this.emFactory = Persistence.createEntityManagerFactory(persistenceUnitName); } } + @Override public synchronized void stop() { Preconditions.checkState(emFactory.isOpen(), "Persistence service was already shut down."); emFactory.close(); @@ -125,15 +128,15 @@ this.emProvider = emProvider; } + @Override public EntityManagerFactory get() { assert null != emProvider.emFactory; return emProvider.emFactory; } } - + @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) - private @interface Nullable { } - + private @interface Nullable {} } diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/package-info.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/package-info.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/jpa/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/jpa/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,5 @@ * limitations under the License. */ -/** - * guice-persist's Java Persistence API (JPA) support. - */ +/** guice-persist's Java Persistence API (JPA) support. */ package com.google.inject.persist.jpa; diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/package-info.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/package-info.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -16,6 +16,6 @@ /** * Guice Persist: a lightweight persistence library for Guice; this extension requires {@code - * guice-persist-3.0.jar}. + * guice-persist.jar}. */ -package com.google.inject.persist; \ No newline at end of file +package com.google.inject.persist; diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/PersistFilter.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/PersistFilter.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/PersistFilter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/PersistFilter.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +18,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -29,38 +27,37 @@ import javax.servlet.ServletResponse; /** - * Apply this filter to enable the HTTP Request unit of work and to have - * guice-persist manage the lifecycle of active units of work. - * The filter automatically starts and stops the relevant {@link PersistService} - * upon {@link javax.servlet.Filter#init(javax.servlet.FilterConfig)} and - * {@link javax.servlet.Filter#destroy()} respectively. - * - *

    To be able to use the open session-in-view pattern (i.e. work per request), - * register this filter once in your Guice {@code ServletModule}. It is - * important that you register this filter before any other filter. - * - * For multiple providers, you should register this filter once per provider, inside - * a private module for each persist module installed (this must be the same private - * module where the specific persist module is itself installed). + * Apply this filter to enable the HTTP Request unit of work and to have guice-persist manage the + * lifecycle of active units of work. The filter automatically starts and stops the relevant {@link + * PersistService} upon {@link javax.servlet.Filter#init(javax.servlet.FilterConfig)} and {@link + * javax.servlet.Filter#destroy()} respectively. + * + *

    To be able to use the open session-in-view pattern (i.e. work per request), register this + * filter once in your Guice {@code ServletModule}. It is important that you register this + * filter before any other filter. + * + *

    For multiple providers, you should register this filter once per provider, inside a private + * module for each persist module installed (this must be the same private module where the specific + * persist module is itself installed). + * + *

    Example configuration: * - *

    - * Example configuration: *

    {@code
    - *  public class MyModule extends ServletModule {
    - *    public void configureServlets() {
    - *      filter("/*").through(PersistFilter.class);
    - *
    - *      serve("/index.html").with(MyHtmlServlet.class);
    - *      // Etc.
    - *    }
    - *  }
    + * public class MyModule extends ServletModule {
    + *   public void configureServlets() {
    + *     filter("/*").through(PersistFilter.class);
    + *
    + *     serve("/index.html").with(MyHtmlServlet.class);
    + *     // Etc.
    + *   }
    + * }
      * }
    - *

    - * This filter is thread safe and allows you to create injectors concurrently - * and deploy multiple guice-persist modules within the same injector, or even - * multiple injectors with persist modules withing the same JVM or web app. - *

    - * This filter requires the Guice Servlet extension. + * + *

    This filter is thread safe and allows you to create injectors concurrently and deploy multiple + * guice-persist modules within the same injector, or even multiple injectors with persist modules + * withing the same JVM or web app. + * + *

    This filter requires the Guice Servlet extension. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @@ -75,16 +72,22 @@ this.persistService = persistService; } + @Override public void init(FilterConfig filterConfig) throws ServletException { persistService.start(); } + @Override public void destroy() { persistService.stop(); } - public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, - final FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + final ServletRequest servletRequest, + final ServletResponse servletResponse, + final FilterChain filterChain) + throws IOException, ServletException { unitOfWork.begin(); try { diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/PersistModule.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/PersistModule.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/PersistModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/PersistModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,12 +20,10 @@ import static com.google.inject.matcher.Matchers.any; import com.google.inject.AbstractModule; - import org.aopalliance.intercept.MethodInterceptor; /** - * Install this module to add guice-persist library support for JPA persistence - * providers. + * Install this module to add guice-persist library support for JPA persistence providers. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @@ -39,7 +37,7 @@ requireBinding(UnitOfWork.class); /*if[AOP]*/ // wrapping in an if[AOP] just to allow this to compile in NO_AOP -- it won't be used - + // class-level @Transacational bindInterceptor(annotatedWith(Transactional.class), any(), getTransactionInterceptor()); // method-level @Transacational diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/PersistService.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/PersistService.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/PersistService.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/PersistService.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,29 +16,27 @@ package com.google.inject.persist; /** - * Persistence provider service. Use this to manage the overall - * startup and stop of the persistence module(s). + * Persistence provider service. Use this to manage the overall startup and stop of the persistence + * module(s). * - * TODO(dhanji): Integrate with Service API when appropriate. + *

    TODO(dhanji): Integrate with Service API when appropriate. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public interface PersistService { /** - * Starts the underlying persistence engine and makes guice-persist ready for - * use. For instance, with JPA, it creates an EntityManagerFactory and may - * open connection pools. This method must be called by your code prior to - * using any guice-persist or JPA artifacts. If already started, - * calling this method does nothing, if already stopped, it also does - * nothing. + * Starts the underlying persistence engine and makes guice-persist ready for use. For instance, + * with JPA, it creates an EntityManagerFactory and may open connection pools. This method must be + * called by your code prior to using any guice-persist or JPA artifacts. If already started, + * calling this method does nothing, if already stopped, it also does nothing. */ void start(); /** - * Stops the underlying persistence engine. For instance, with JPA, it - * closes the {@code EntityManagerFactory}. If already stopped, calling this - * method does nothing. If not yet started, it also does nothing. + * Stops the underlying persistence engine. For instance, with JPA, it closes the {@code + * EntityManagerFactory}. If already stopped, calling this method does nothing. If not yet + * started, it also does nothing. */ void stop(); } diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/Transactional.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/Transactional.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/Transactional.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/Transactional.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,40 +23,36 @@ import java.lang.annotation.Target; /** - *

    Any method or class marked with this annotation will be considered for transactionality. - * Consult the documentation on https://github.com/google/guice/wiki/GuicePersist for detailed - * semantics. - * Marking a method {@code @Transactional} will start a new transaction before the method - * executes and commit it after the method returns. - *

    - * If the method throws an exception, the transaction will be rolled back unless - * you have specifically requested not to in the {@link #ignore()} clause. - *

    - * Similarly, the set of exceptions that will trigger a rollback can be defined in - * the {@link #rollbackOn()} clause. By default, only unchecked exceptions trigger a - * rollback. + * Any method or class marked with this annotation will be considered for transactionality. Consult + * the documentation on https://github.com/google/guice/wiki/GuicePersist for detailed semantics. + * Marking a method {@code @Transactional} will start a new transaction before the method executes + * and commit it after the method returns. + * + *

    If the method throws an exception, the transaction will be rolled back unless you + * have specifically requested not to in the {@link #ignore()} clause. + * + *

    Similarly, the set of exceptions that will trigger a rollback can be defined in the {@link + * #rollbackOn()} clause. By default, only unchecked exceptions trigger a rollback. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ -@Target({ ElementType.METHOD, ElementType.TYPE }) +@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Transactional { /** - * A list of exceptions to rollback on, if thrown by the transactional method. - * These exceptions are propagated correctly after a rollback. + * A list of exceptions to rollback on, if thrown by the transactional method. These exceptions + * are propagated correctly after a rollback. */ Class[] rollbackOn() default RuntimeException.class; /** - * A list of exceptions to not rollback on. A caveat to the rollbackOn clause. - * The disjunction of rollbackOn and ignore represents the list of exceptions - * that will trigger a rollback. - * The complement of rollbackOn and the universal set plus any exceptions in the - * ignore set represents the list of exceptions that will trigger a commit. - * Note that ignore exceptions take precedence over rollbackOn, but with subtype - * granularity. + * A list of exceptions to not rollback on. A caveat to the rollbackOn clause. The + * disjunction of rollbackOn and ignore represents the list of exceptions that will trigger a + * rollback. The complement of rollbackOn and the universal set plus any exceptions in the ignore + * set represents the list of exceptions that will trigger a commit. Note that ignore exceptions + * take precedence over rollbackOn, but with subtype granularity. */ - Class[] ignore() default { }; + Class[] ignore() default {}; } diff -Nru sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/UnitOfWork.java sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/UnitOfWork.java --- sisu-guice-3.2.6/extensions/persist/src/com/google/inject/persist/UnitOfWork.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/src/com/google/inject/persist/UnitOfWork.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,32 +17,32 @@ package com.google.inject.persist; /** - * This interface is used to gain manual control over the unit of work. This is mostly to do - * work in non-request, non-transactional threads. Or where more fine-grained control over the unit - * of work is required. Starting and ending a unit of work directly corresponds to opening and - * closing a {@code Session}, {@code EntityManager} or {@code ObjectContainer} respectively. - *

    The - * Unit of Work referred to by UnitOfWork will always be local to the calling thread. Be careful to - * end() in a finally block. Neither JPA, nor Hibernate supports threadsafe sessions (reasoning - * behind thread-locality of Unit of Work semantics). + * This interface is used to gain manual control over the unit of work. This is mostly to do work in + * non-request, non-transactional threads. Or where more fine-grained control over the unit of work + * is required. Starting and ending a unit of work directly corresponds to opening and closing a + * {@code Session}, {@code EntityManager} or {@code ObjectContainer} respectively. + * + *

    The Unit of Work referred to by UnitOfWork will always be local to the calling thread. Be + * careful to end() in a finally block. Neither JPA, nor Hibernate supports threadsafe sessions + * (reasoning behind thread-locality of Unit of Work semantics). * *

      - *
    • Using UnitOfWork with the PersistFilter inside a request is not recommended.
    • - *
    • Using UnitOfWork with session-per-txn strategy is not terribly clever either.
    • - *
    • Using UnitOfWork with session-per-request strategy but *outside* a request (i.e. in a - * background or bootstrap thread) is probably a good use case.
    • - *
    + *
  • Using UnitOfWork with the PersistFilter inside a request is not recommended. + *
  • Using UnitOfWork with session-per-txn strategy is not terribly clever either. + *
  • Using UnitOfWork with session-per-request strategy but *outside* a request (i.e. in a + * background or bootstrap thread) is probably a good use case. + * * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public interface UnitOfWork { /** - * Starts a Unit Of Work. Underneath, causes a session to the data layer to be opened. If there - * is already one open, the invocation will do nothing. In this way, you can define arbitrary + * Starts a Unit Of Work. Underneath, causes a session to the data layer to be opened. If there is + * already one open, the invocation will do nothing. In this way, you can define arbitrary * units-of-work that nest within one another safely. * - * Transaction semantics are not affected. + *

    Transaction semantics are not affected. */ void begin(); @@ -50,8 +50,8 @@ * Declares an end to the current Unit of Work. Underneath, causes any open session to the data * layer to close. If there is no Unit of work open, then the call returns silently. You can * safely invoke end() repeatedly. - *

    - * Transaction semantics are not affected. + * + *

    Transaction semantics are not affected. */ void end(); } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/AllTests.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/AllTests.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/AllTests.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/AllTests.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,13 +27,10 @@ import com.google.inject.persist.jpa.ManagedLocalTransactionsTest; import com.google.inject.persist.jpa.ManualLocalTransactionsTest; import com.google.inject.persist.jpa.ManualLocalTransactionsWithCustomMatcherTest; - import junit.framework.Test; import junit.framework.TestSuite; -/** - * @author dhanji@gmail.com (Dhanji R. Prasanna) - */ +/** @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class AllTests { public static Test suite() { @@ -54,4 +51,4 @@ return suite; } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/EdslTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/EdslTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/EdslTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/EdslTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -7,20 +7,20 @@ import java.util.logging.Logger; import junit.framework.TestCase; -/** - * @author dhanji@google.com (Dhanji R. Prasanna) - */ +/** @author dhanji@google.com (Dhanji R. Prasanna) */ public class EdslTest extends TestCase { public void testModuleConfigUsingJpa() throws Exception { Logger.getLogger(getClass().getName()).info("Starting EDSL test."); - Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { - @Override - protected void configure() { - install(new JpaPersistModule("myunit")); - binder().requireExplicitBindings(); - } - }); + Guice.createInjector( + Stage.PRODUCTION, + new AbstractModule() { + @Override + protected void configure() { + install(new JpaPersistModule("myunit")); + binder().requireExplicitBindings(); + } + }); Logger.getLogger(getClass().getName()).info("Completed EDSL test."); } } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,21 +21,18 @@ import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; - -import junit.framework.TestCase; - import java.io.FileNotFoundException; import java.io.IOException; import java.util.Date; import java.util.List; - import javax.persistence.EntityManager; +import junit.framework.TestCase; /** * This test asserts class level @Transactional annotation behavior. * - * Class-level @Transactional is a shortcut if all non-private methods in the class are meant to be - * transactional. + *

    Class-level @Transactional is a shortcut if all non-private methods in the class are meant to + * be transactional. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @@ -44,9 +41,10 @@ private Injector injector; private static final String UNIQUE_TEXT = "JPAsome unique text88888" + new Date(); private static final String UNIQUE_TEXT_2 = "JPAsome asda unique teasdalsdplasdxt" + new Date(); - private static final String TRANSIENT_UNIQUE_TEXT = "JPAsome other unique texaksoksojadasdt" - + new Date(); + private static final String TRANSIENT_UNIQUE_TEXT = + "JPAsome other unique texaksoksojadasdt" + new Date(); + @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); @@ -54,6 +52,7 @@ injector.getInstance(PersistService.class).start(); } + @Override public void tearDown() { injector.getInstance(PersistService.class).stop(); injector = null; @@ -63,20 +62,26 @@ injector.getInstance(TransactionalObject.class).runOperationInTxn(); EntityManager session = injector.getInstance(EntityManager.class); - assertFalse("EntityManager was not closed by transactional service", + assertFalse( + "EntityManager was not closed by transactional service", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); - Object result = session.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT).getSingleResult(); + Object result = + session + .createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT) + .getSingleResult(); session.getTransaction().commit(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", - UNIQUE_TEXT, (((JpaTestEntity) result).getText())); + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT, + (((JpaTestEntity) result).getText())); } public void testSimpleTransactionRollbackOnChecked() { @@ -87,13 +92,17 @@ } EntityManager session = injector.getInstance(EntityManager.class); - assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "EntityManager was not closed by transactional service (rollback didnt happen?)", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); - List result = session.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList(); + List result = + session + .createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getResultList(); session.getTransaction().commit(); @@ -110,18 +119,21 @@ } EntityManager session = injector.getInstance(EntityManager.class); - assertFalse("Txn was not closed by transactional service (commit didnt happen?)", + assertFalse( + "Txn was not closed by transactional service (commit didnt happen?)", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); - Object result = session.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT_2).getSingleResult(); + Object result = + session + .createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT_2) + .getSingleResult(); session.getTransaction().commit(); - assertNotNull("a result was not returned! rollback happened anyway (ignore failed)!!!", - result); + assertNotNull("a result was not returned! rollback happened anyway (ignore failed)!!!", result); } public void testSimpleTransactionRollbackOnUnchecked() { @@ -132,18 +144,21 @@ } EntityManager session = injector.getInstance(EntityManager.class); - assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "EntityManager was not closed by transactional service (rollback didnt happen?)", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); - List result = session.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList(); + List result = + session + .createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getResultList(); session.getTransaction().commit(); - assertTrue("a result was returned! rollback sure didnt happen!!!", - result.isEmpty()); + assertTrue("a result was returned! rollback sure didnt happen!!!", result.isEmpty()); } @Transactional @@ -156,7 +171,6 @@ entity.setText(UNIQUE_TEXT); session.persist(entity); } - } @Transactional diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,17 +20,12 @@ import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import java.util.Properties; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import junit.framework.TestCase; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class CustomPropsEntityManagerFactoryProvisionTest extends TestCase { private Injector injector; @@ -51,7 +46,8 @@ public void testSessionCreateOnInjection() { - assertEquals("SINGLETON VIOLATION " + UnitOfWork.class.getName(), + assertEquals( + "SINGLETON VIOLATION " + UnitOfWork.class.getName(), injector.getInstance(UnitOfWork.class), injector.getInstance(UnitOfWork.class)); diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,15 +23,12 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.finder.Finder; - -import junit.framework.TestCase; - import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.UUID; - import javax.persistence.EntityManager; +import junit.framework.TestCase; /** * A test around providing sessions (starting, closing etc.) @@ -42,6 +39,7 @@ public class DynamicFinderTest extends TestCase { private Injector injector; + @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit").addFinder(JpaFinder.class)); @@ -49,6 +47,7 @@ injector.getInstance(PersistService.class).start(); } + @Override public final void tearDown() { injector.getInstance(PersistService.class).stop(); } @@ -64,7 +63,8 @@ dao.persist(te); //im not sure this hack works... - assertFalse("Duplicate entity managers crossing-scope", + assertFalse( + "Duplicate entity managers crossing-scope", dao.lastEm.equals(injector.getInstance(EntityManager.class))); List list = injector.getInstance(JpaFinder.class).listAll(); @@ -85,7 +85,7 @@ @Inject public JpaDao(Provider em) { - this.em = em; + this.em = em; } @Transactional diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -49,7 +49,7 @@ @Override protected void configure() { - Map p = new HashMap(); + Map p = new HashMap<>(); p.put(Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName()); if (passDataSource) { diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,23 +20,21 @@ import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import junit.framework.TestCase; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class EntityManagerFactoryProvisionTest extends TestCase { private Injector injector; + @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); } + @Override public final void tearDown() { injector.getInstance(UnitOfWork.class).end(); injector.getInstance(EntityManagerFactory.class).close(); @@ -44,8 +42,10 @@ public void testSessionCreateOnInjection() { - assertEquals("SINGLETON VIOLATION " + UnitOfWork.class.getName(), - injector.getInstance(UnitOfWork.class), injector.getInstance(UnitOfWork.class)); + assertEquals( + "SINGLETON VIOLATION " + UnitOfWork.class.getName(), + injector.getInstance(UnitOfWork.class), + injector.getInstance(UnitOfWork.class)); //startup persistence injector.getInstance(PersistService.class).start(); diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +22,9 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import junit.framework.TestCase; /** * A test around providing sessions (starting, closing etc.) @@ -63,14 +61,18 @@ dao.persist(te); //im not sure this hack works... - assertEquals("Entity managers closed inside same thread-scope", - injector.getInstance(EntityManager.class), JpaDao.em); + assertEquals( + "Entity managers closed inside same thread-scope", + injector.getInstance(EntityManager.class), + JpaDao.em); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); - assertTrue("EntityManager was closed and reopened around txn" - + " (persistent object does not persist)", dao.contains(te)); + assertTrue( + "EntityManager was closed and reopened around txn" + + " (persistent object does not persist)", + dao.contains(te)); } public void testEntityManagerLifecyclePerTxn2() { @@ -83,16 +85,21 @@ dao.persist(te); //im not sure this hack works... - assertEquals("Duplicate entity managers crossing-scope", - injector.getInstance(EntityManager.class), JpaDao.em); - assertEquals("Duplicate entity managers crossing-scope", - injector.getInstance(EntityManager.class), JpaDao.em); + assertEquals( + "Duplicate entity managers crossing-scope", + injector.getInstance(EntityManager.class), + JpaDao.em); + assertEquals( + "Duplicate entity managers crossing-scope", + injector.getInstance(EntityManager.class), + JpaDao.em); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); - assertTrue("EntityManager was closed and reopened around txn" - + " (persistent object doesnt persist)", dao.contains(te)); + assertTrue( + "EntityManager was closed and reopened around txn" + " (persistent object doesnt persist)", + dao.contains(te)); } public static class JpaDao { diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +22,9 @@ import com.google.inject.Provider; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; - -import junit.framework.TestCase; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import junit.framework.TestCase; /** * A test around providing sessions (starting, closing etc.) @@ -37,6 +35,7 @@ public class EntityManagerProvisionTest extends TestCase { private Injector injector; + @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); @@ -44,6 +43,7 @@ injector.getInstance(PersistService.class).start(); } + @Override public final void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } @@ -58,14 +58,17 @@ dao.persist(te); //im not sure this hack works... - assertFalse("Duplicate entity managers crossing-scope", + assertFalse( + "Duplicate entity managers crossing-scope", dao.lastEm.equals(injector.getInstance(EntityManager.class))); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); - assertFalse("EntityManager wasnt closed and reopened properly around txn" - + " (persistent object persists)", dao.contains(te)); + assertFalse( + "EntityManager wasnt closed and reopened properly around txn" + + " (persistent object persists)", + dao.contains(te)); } public void testEntityManagerLifecyclePerTxn2() { @@ -78,14 +81,17 @@ dao.persist(te); //im not sure this hack works... - assertFalse("Duplicate entity managers crossing-scope", + assertFalse( + "Duplicate entity managers crossing-scope", dao.lastEm.equals(injector.getInstance(EntityManager.class))); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); - assertFalse("EntityManager wasnt closed and reopened properly around txn" - + " (persistent object persists)", dao.contains(te)); + assertFalse( + "EntityManager wasnt closed and reopened properly around txn" + + " (persistent object persists)", + dao.contains(te)); } public static class JpaDao { @@ -94,7 +100,7 @@ @Inject public JpaDao(Provider em) { - this.em = em; + this.em = em; } @Transactional diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,26 +22,21 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; +import junit.framework.TestCase; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class JoiningLocalTransactionsTest extends TestCase { private Injector injector; - private static final String UNIQUE_TEXT = JoiningLocalTransactionsTest.class + "some unique text" - + new Date(); - private static final String TRANSIENT_UNIQUE_TEXT = JoiningLocalTransactionsTest.class - + "some other unique text" + new Date(); + private static final String UNIQUE_TEXT = + JoiningLocalTransactionsTest.class + "some unique text" + new Date(); + private static final String TRANSIENT_UNIQUE_TEXT = + JoiningLocalTransactionsTest.class + "some other unique text" + new Date(); @Override public void setUp() { @@ -59,27 +54,32 @@ } public void testSimpleTransaction() { - injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) + injector + .getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) .runOperationInTxn(); EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("txn was not closed by transactional service", - em.getTransaction().isActive()); + assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); //test that the data has been stored - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT, + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT, ((JpaTestEntity) result).getText()); } public void testSimpleTransactionRollbackOnChecked() { try { - injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) + injector + .getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) .runOperationInTxnThrowingChecked(); } catch (IOException e) { //ignore @@ -88,21 +88,26 @@ EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("EM was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "EM was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); //test that the data has been stored try { - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); - } catch (NoResultException e) { } + } catch (NoResultException e) { + } } public void testSimpleTransactionRollbackOnUnchecked() { try { - injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) + injector + .getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) .runOperationInTxnThrowingUnchecked(); } catch (RuntimeException re) { //ignore @@ -110,15 +115,19 @@ } EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("Session was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "Session was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); try { - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); - } catch (NoResultException e) {} + } catch (NoResultException e) { + } } public static class TransactionalObject { diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,40 +18,38 @@ import java.util.ArrayList; import java.util.List; - import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; /** - * Created with IntelliJ IDEA. - * On: 2/06/2007 + * Created with IntelliJ IDEA. On: 2/06/2007 * * @author Dhanji R. Prasanna (dhanji@gmail.com) * @since 1.0 */ @Entity public class JpaParentTestEntity { - private Long id; - private List children = new ArrayList(); + private Long id; + private List children = new ArrayList<>(); - @Id - @GeneratedValue - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @OneToMany - public List getChildren() { - return children; - } - - public void setChildren(List children) { - this.children = children; - } + @Id + @GeneratedValue + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @OneToMany + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ package com.google.inject.persist.jpa; -import junit.framework.TestCase; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.doThrow; @@ -24,24 +23,26 @@ import static org.mockito.Mockito.when; import java.util.Properties; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.spi.PersistenceProvider; +import junit.framework.TestCase; public class JpaPersistServiceTest extends TestCase { private static final String PERSISTENCE_UNIT_NAME = "test_persistence_unit_name"; private static final Properties PERSISTENCE_PROPERTIES = new Properties(); - private final JpaPersistService sut = new JpaPersistService(PERSISTENCE_UNIT_NAME, PERSISTENCE_PROPERTIES); + private final JpaPersistService sut = + new JpaPersistService(PERSISTENCE_UNIT_NAME, PERSISTENCE_PROPERTIES); private final PersistenceProvider provider = mock(PersistenceProvider.class); private final EntityManagerFactory factory = mock(EntityManagerFactory.class); private final EntityManager entityManager = mock(EntityManager.class); @Override public void setUp() throws Exception { - when(provider.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, PERSISTENCE_PROPERTIES)).thenReturn(factory); + when(provider.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, PERSISTENCE_PROPERTIES)) + .thenReturn(factory); when(factory.createEntityManager()).thenReturn(entityManager); } @@ -54,12 +55,10 @@ try { sut.end(); fail("Exception expected"); - } - catch (SimulatedException expected) { + } catch (SimulatedException expected) { assertThat(sut.isWorking(), is(false)); } } - private class SimulatedException extends RuntimeException { - } + private static class SimulatedException extends RuntimeException {} } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,8 @@ private Long id; private String text; - @Id @GeneratedValue + @Id + @GeneratedValue public Long getId() { return id; } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,24 +22,21 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; -import org.hibernate.HibernateException; - import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Query; +import junit.framework.TestCase; +import org.hibernate.HibernateException; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class JpaWorkManagerTest extends TestCase { private Injector injector; - private static final String UNIQUE_TEXT_3 = JpaWorkManagerTest.class.getSimpleName() - + "CONSTRAINT_VIOLATING some other unique text" + new Date(); + private static final String UNIQUE_TEXT_3 = + JpaWorkManagerTest.class.getSimpleName() + + "CONSTRAINT_VIOLATING some other unique text" + + new Date(); @Override public void setUp() { @@ -53,8 +50,8 @@ public void tearDown() { try { injector.getInstance(EntityManagerFactory.class).close(); - } catch(HibernateException ex) { - // Expected if the persist service has already been stopped. + } catch (HibernateException ex) { + // Expected if the persist service has already been stopped. } } @@ -64,14 +61,15 @@ injector.getInstance(TransactionalObject.class).runOperationInTxn(); } finally { injector.getInstance(UnitOfWork.class).end(); - } injector.getInstance(UnitOfWork.class).begin(); injector.getInstance(EntityManager.class).getTransaction().begin(); try { - final Query query = injector.getInstance(EntityManager.class) - .createQuery("select e from JpaTestEntity as e where text = :text"); + final Query query = + injector + .getInstance(EntityManager.class) + .createQuery("select e from JpaTestEntity as e where text = :text"); query.setParameter("text", UNIQUE_TEXT_3); final Object o = query.getSingleResult(); @@ -80,8 +78,10 @@ assertTrue("Unknown type returned " + o.getClass(), o instanceof JpaTestEntity); JpaTestEntity ent = (JpaTestEntity) o; - assertEquals("Incorrect result returned or not persisted properly" + ent.getText(), - UNIQUE_TEXT_3, ent.getText()); + assertEquals( + "Incorrect result returned or not persisted properly" + ent.getText(), + UNIQUE_TEXT_3, + ent.getText()); } finally { injector.getInstance(EntityManager.class).getTransaction().commit(); diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,26 +24,21 @@ import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import com.google.inject.persist.finder.Finder; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; +import junit.framework.TestCase; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManagedLocalTransactionsAcrossRequestTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = "some unique text" + new Date(); private static final String UNIQUE_TEXT_MERGE = "meRG_Esome unique text" + new Date(); - private static final String UNIQUE_TEXT_MERGE_FORDF = "aSdoaksdoaksdmeRG_Esome unique text" - + new Date(); + private static final String UNIQUE_TEXT_MERGE_FORDF = + "aSdoaksdoaksdmeRG_Esome unique text" + new Date(); private static final String TRANSIENT_UNIQUE_TEXT = "some other unique text" + new Date(); @Override @@ -66,22 +61,25 @@ assertFalse(em.getTransaction().isActive()); //test that the data has been stored - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", - UNIQUE_TEXT, ((JpaTestEntity) result).getText()); + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT, + ((JpaTestEntity) result).getText()); injector.getInstance(UnitOfWork.class).end(); - } public void testSimpleTransactionWithMerge() { EntityManager emOrig = injector.getInstance(EntityManager.class); - JpaTestEntity entity = injector.getInstance(TransactionalObject.class) - .runOperationInTxnWithMerge(); + JpaTestEntity entity = + injector.getInstance(TransactionalObject.class).runOperationInTxnWithMerge(); assertNotNull("Entity was not given an id (was not persisted correctly?)", entity.getId()); @@ -93,22 +91,25 @@ assertEquals("Em was not kept open across txns", emOrig, em); assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity)); - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT_MERGE).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT_MERGE) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue(result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", - UNIQUE_TEXT_MERGE, ((JpaTestEntity) result).getText()); + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT_MERGE, + ((JpaTestEntity) result).getText()); injector.getInstance(UnitOfWork.class).end(); - } public void disabled_testSimpleTransactionWithMergeAndDF() { EntityManager emOrig = injector.getInstance(EntityManager.class); - JpaTestEntity entity = injector.getInstance(TransactionalObject.class) - .runOperationInTxnWithMergeForDf(); + JpaTestEntity entity = + injector.getInstance(TransactionalObject.class).runOperationInTxnWithMergeForDf(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); @@ -124,10 +125,11 @@ assertNotNull(result); assertTrue(result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", - UNIQUE_TEXT_MERGE_FORDF, ((JpaTestEntity) result).getText()); + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT_MERGE_FORDF, + ((JpaTestEntity) result).getText()); injector.getInstance(UnitOfWork.class).end(); - } public void testSimpleTransactionRollbackOnChecked() { @@ -140,16 +142,20 @@ EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("Previous EM was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "Previous EM was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); //test that the data has been stored try { - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail(); - } catch (NoResultException e) {} + } catch (NoResultException e) { + } injector.getInstance(UnitOfWork.class).end(); } @@ -163,15 +169,19 @@ } EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("Session was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "Session was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); try { - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail(); - } catch (NoResultException e) {} + } catch (NoResultException e) { + } injector.getInstance(UnitOfWork.class).end(); } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,19 +22,14 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; +import junit.framework.TestCase; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManagedLocalTransactionsTest extends TestCase { private Injector injector; @@ -63,19 +58,23 @@ assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); //test that the data has been stored - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", - UNIQUE_TEXT, ((JpaTestEntity) result).getText()); + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT, + ((JpaTestEntity) result).getText()); } public void testSimpleTransactionWithMerge() { - JpaTestEntity entity = injector.getInstance(TransactionalObject.class) - .runOperationInTxnWithMerge(); + JpaTestEntity entity = + injector.getInstance(TransactionalObject.class).runOperationInTxnWithMerge(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); @@ -83,14 +82,18 @@ //test that the data has been stored assertTrue("Em was closed after txn!", em.isOpen()); - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT_MERGE).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT_MERGE) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue(result instanceof JpaTestEntity); - assertEquals("queried entity did not match--did automatic txn fail?", - UNIQUE_TEXT_MERGE, ((JpaTestEntity) result).getText()); + assertEquals( + "queried entity did not match--did automatic txn fail?", + UNIQUE_TEXT_MERGE, + ((JpaTestEntity) result).getText()); } public void testSimpleTransactionRollbackOnChecked() { @@ -103,16 +106,20 @@ EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("Previous EM was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "Previous EM was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); //test that the data has been stored try { - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); - } catch (NoResultException e) {} + } catch (NoResultException e) { + } } public void testSimpleTransactionRollbackOnUnchecked() { @@ -124,15 +131,19 @@ } EntityManager em = injector.getInstance(EntityManager.class); - assertFalse("Session was not closed by transactional service (rollback didnt happen?)", + assertFalse( + "Session was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); try { - Object result = em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); - } catch (NoResultException e) {} + } catch (NoResultException e) { + } } public static class TransactionalObject { diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,23 +21,19 @@ import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; - -import junit.framework.TestCase; - import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.PersistenceException; +import junit.framework.TestCase; -/** - * @author Dhanji R. Prasanna (dhanji@gmail.com) - */ +/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManualLocalTransactionsConfidenceTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT_3 = ManualLocalTransactionsConfidenceTest.class.getSimpleName() - + "CONSTRAINT_VIOLATING some other unique text" + new Date(); + + "CONSTRAINT_VIOLATING some other unique text" + + new Date(); @Override public void setUp() { @@ -69,7 +65,8 @@ } assertNotNull("No exception was thrown!", e); - assertTrue("Exception thrown was not what was expected (i.e. commit-time)", + assertTrue( + "Exception thrown was not what was expected (i.e. commit-time)", e instanceof PersistenceException); } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,13 +22,10 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import junit.framework.TestCase; /** * For instance, a session-per-request strategy will control the opening and closing of the EM at @@ -42,6 +39,7 @@ private static final String UNIQUE_TEXT = "some unique text" + new Date(); private static final String UNIQUE_TEXT_2 = "some other unique text" + new Date(); + @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); @@ -49,6 +47,7 @@ injector.getInstance(PersistService.class).start(); } + @Override public void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } @@ -63,7 +62,8 @@ injector.getInstance(TransactionalObject.class).runOperationInTxn2(); //persisted entity should remain in the same em (which should still be open) - assertTrue("EntityManager appears to have been closed across txns!", + assertTrue( + "EntityManager appears to have been closed across txns!", injector.getInstance(EntityManager.class).contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.isOpen()); @@ -73,10 +73,14 @@ //try to query them back out em = injector.getInstance(EntityManager.class); - assertNotNull(em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT).getSingleResult()); - assertNotNull(em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT_2).getSingleResult()); + assertNotNull( + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT) + .getSingleResult()); + assertNotNull( + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT_2) + .getSingleResult()); em.close(); assertFalse(em.isOpen()); @@ -100,6 +104,5 @@ entity.setText(UNIQUE_TEXT_2); em.persist(entity); } - } } diff -Nru sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java --- sisu-guice-3.2.6/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,18 +22,15 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; - -import junit.framework.TestCase; - import java.util.Date; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import junit.framework.TestCase; /** * Created with IntelliJ IDEA. On: 2/06/2007 * - * For instance, a session-per-request strategy will control the opening and closing of the EM at + *

    For instance, a session-per-request strategy will control the opening and closing of the EM at * its own (manual) discretion. As opposed to a transactional unit of work. * * @author Dhanji R. Prasanna (dhanji@gmail.com) @@ -62,14 +59,17 @@ //pretend that the request was started here EntityManager em = injector.getInstance(EntityManager.class); - JpaTestEntity entity = injector + JpaTestEntity entity = + injector + .getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class) + .runOperationInTxn(); + injector .getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class) - .runOperationInTxn(); - injector.getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class) .runOperationInTxn2(); //persisted entity should remain in the same em (which should still be open) - assertTrue("EntityManager appears to have been closed across txns!", + assertTrue( + "EntityManager appears to have been closed across txns!", injector.getInstance(EntityManager.class).contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.isOpen()); @@ -78,10 +78,14 @@ //try to query them back out em = injector.getInstance(EntityManager.class); - assertNotNull(em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT).getSingleResult()); - assertNotNull(em.createQuery("from JpaTestEntity where text = :text") - .setParameter("text", UNIQUE_TEXT_2).getSingleResult()); + assertNotNull( + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT) + .getSingleResult()); + assertNotNull( + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", UNIQUE_TEXT_2) + .getSingleResult()); em.close(); } @@ -103,6 +107,5 @@ entity.setText(UNIQUE_TEXT_2); em.persist(entity); } - } } diff -Nru sisu-guice-3.2.6/extensions/pom.xml sisu-guice-4.2.0/extensions/pom.xml --- sisu-guice-3.2.6/extensions/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject guice-parent - 3.2.6 + 4.2.0 pom @@ -17,7 +17,6 @@ assistedinject - dagger-adapter grapher jmx @@ -91,7 +90,7 @@ maven-remote-resources-plugin org.codehaus.mojo diff -Nru sisu-guice-3.2.6/extensions/service/pom.xml sisu-guice-4.2.0/extensions/service/pom.xml --- sisu-guice-3.2.6/extensions/service/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/service/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,11 +6,25 @@ org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT guice-service Sisu Guice - Extensions - Service + + + + maven-jar-plugin + + + + com.google.guice.extensions.service + + + + + + diff -Nru sisu-guice-3.2.6/extensions/service/src/com/google/inject/service/AsyncService.java sisu-guice-4.2.0/extensions/service/src/com/google/inject/service/AsyncService.java --- sisu-guice-3.2.6/extensions/service/src/com/google/inject/service/AsyncService.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/service/src/com/google/inject/service/AsyncService.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,22 +17,23 @@ package com.google.inject.service; import com.google.common.base.Preconditions; - import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; /** - * An asynchronous implementation of {@link com.google.inject.service.Service} - * that provides convenience callbacks to create your own services. + * An asynchronous implementation of {@link com.google.inject.service.Service} that provides + * convenience callbacks to create your own services. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public abstract class AsyncService implements Service { - private static final Runnable DO_NOTHING = new Runnable() { - @Override public void run() {} - }; + private static final Runnable DO_NOTHING = + new Runnable() { + @Override + public void run() {} + }; private final ExecutorService executor; @@ -42,33 +43,35 @@ this.executor = executor; } - public synchronized final Future start() { - Preconditions.checkState(state != State.STOPPED, - "Cannot restart a service that has been stopped"); + @Override + public final synchronized Future start() { + Preconditions.checkState( + state != State.STOPPED, "Cannot restart a service that has been stopped"); // Starts are idempotent. if (state == State.STARTED) { return new FutureTask(DO_NOTHING, State.STARTED); } - return executor.submit(new Callable() { - public State call() { - onStart(); - return state = State.STARTED; - } - }); + return executor.submit( + new Callable() { + @Override + public State call() { + onStart(); + return state = State.STARTED; + } + }); } /** - * Called back when this service must do its start work. Typically occurs - * in a background thread. The result of this method is returned to the - * original caller of {@link Service#start()} and can thus be used to - * return a status message after start completes (or fails as the case - * may be). + * Called back when this service must do its start work. Typically occurs in a background thread. + * The result of this method is returned to the original caller of {@link Service#start()} and can + * thus be used to return a status message after start completes (or fails as the case may be). */ protected abstract void onStart(); - public synchronized final Future stop() { + @Override + public final synchronized Future stop() { Preconditions.checkState(state != null, "Must start this service before you stop it!"); // Likewise, stops are idempotent. @@ -76,23 +79,24 @@ return new FutureTask(DO_NOTHING, State.STOPPED); } - return executor.submit(new Callable() { - public State call() { - onStop(); - return state = State.STOPPED; - } - }); + return executor.submit( + new Callable() { + @Override + public State call() { + onStop(); + return state = State.STOPPED; + } + }); } /** - * Called back when this service must shutdown. Typically occurs - * in a background thread. The result of this method is returned to the - * original caller of {@link Service#stop()} and can thus be used to - * return a status message after stop completes (or fails as the case - * may be). + * Called back when this service must shutdown. Typically occurs in a background thread. The + * result of this method is returned to the original caller of {@link Service#stop()} and can thus + * be used to return a status message after stop completes (or fails as the case may be). */ protected abstract void onStop(); + @Override public final State state() { return state; } diff -Nru sisu-guice-3.2.6/extensions/service/src/com/google/inject/service/CompositeService.java sisu-guice-4.2.0/extensions/service/src/com/google/inject/service/CompositeService.java --- sisu-guice-3.2.6/extensions/service/src/com/google/inject/service/CompositeService.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/service/src/com/google/inject/service/CompositeService.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; - import java.util.List; import java.util.Set; import java.util.concurrent.Callable; @@ -41,12 +40,12 @@ private final Set> services = Sets.newLinkedHashSet(); /** - * Represents the state of this composite service. Will equal FAILED - * even if only one component service fails to start or stop. In other - * words, all component services must start successfully for this - * service to be considered started and similarly for stopped. + * Represents the state of this composite service. Will equal FAILED even if only one component + * service fails to start or stop. In other words, all component services must start successfully + * for this service to be considered started and similarly for stopped. */ private volatile Service.State compositeState; + private boolean composed; @Inject @@ -59,7 +58,8 @@ } public CompositeService add(Key service) { - Preconditions.checkState(!composed, + Preconditions.checkState( + !composed, "Cannot reuse a CompositeService after it has been compose()d. Please create a new one."); // Verify that the binding exists. Throws an exception if not. injector.getBinding(service); @@ -69,7 +69,8 @@ } public Service compose() { - Preconditions.checkState(!composed, + Preconditions.checkState( + !composed, "Cannot reuse a CompositeService after it has been compose()d. Please create a new one."); composed = true; @@ -77,6 +78,7 @@ final List> services = ImmutableList.copyOf(this.services); return new Service() { + @Override public Future start() { final List> tasks = Lists.newArrayList(); for (Key service : services) { @@ -86,6 +88,7 @@ return futureGet(tasks, State.STARTED); } + @Override public Future stop() { final List> tasks = Lists.newArrayList(); for (Key service : services) { @@ -95,29 +98,32 @@ return futureGet(tasks, State.STOPPED); } + @Override public State state() { return compositeState; } }; } - private FutureTask futureGet(final List> tasks, - final Service.State state) { - return new FutureTask(new Callable() { - public Service.State call() { - boolean ok = true; - for (Future task : tasks) { - try { - ok = state == task.get(); - } catch (InterruptedException e) { - return compositeState = Service.State.FAILED; - } catch (ExecutionException e) { - return compositeState = Service.State.FAILED; - } - } + private FutureTask futureGet( + final List> tasks, final Service.State state) { + return new FutureTask( + new Callable() { + @Override + public Service.State call() { + boolean ok = true; + for (Future task : tasks) { + try { + ok = state == task.get(); + } catch (InterruptedException e) { + return compositeState = Service.State.FAILED; + } catch (ExecutionException e) { + return compositeState = Service.State.FAILED; + } + } - return compositeState = ok ? state : Service.State.FAILED; - } - }); + return compositeState = ok ? state : Service.State.FAILED; + } + }); } } diff -Nru sisu-guice-3.2.6/extensions/service/src/com/google/inject/service/Service.java sisu-guice-4.2.0/extensions/service/src/com/google/inject/service/Service.java --- sisu-guice-3.2.6/extensions/service/src/com/google/inject/service/Service.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/service/src/com/google/inject/service/Service.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,48 +20,46 @@ import java.util.concurrent.Future; /** - * An object with an operational state, asynchronous {@link #start()} and - * {@link #stop()} lifecycle methods to transition in and out of this state. - * Example services include http servers, RPC systems and timer tasks. + * An object with an operational state, asynchronous {@link #start()} and {@link #stop()} lifecycle + * methods to transition in and out of this state. Example services include http servers, RPC + * systems and timer tasks. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public interface Service { /** - * If the service has already been started, this method returns - * immediately without taking action. A stopped service may not be restarted. + * If the service has already been started, this method returns immediately without taking action. + * A stopped service may not be restarted. * - * @return a future for the startup result, regardless of whether this call - * initiated startup. Calling {@link Future#get} will block until the - * service has finished starting, and returns the resultant state. If - * the service fails to start, {@link Future#get} will throw an {@link - * ExecutionException}. If it has already finished starting, - * {@link Future#get} returns immediately. + * @return a future for the startup result, regardless of whether this call initiated startup. + * Calling {@link Future#get} will block until the service has finished starting, and returns + * the resultant state. If the service fails to start, {@link Future#get} will throw an {@link + * ExecutionException}. If it has already finished starting, {@link Future#get} returns + * immediately. */ Future start(); /** - * If the service is {@link State#STARTED} initiates service shutdown and - * returns immediately. If the service has already been stopped, this - * method returns immediately without taking action. + * If the service is {@link State#STARTED} initiates service shutdown and returns immediately. If + * the service has already been stopped, this method returns immediately without taking action. * - * @return a future for the shutdown result, regardless of whether this call - * initiated shutdown. Calling {@link Future#get} will block until the - * service has finished shutting down, and either returns {@link - * State#STOPPED} or throws an {@link ExecutionException}. If it has + * @return a future for the shutdown result, regardless of whether this call initiated shutdown. + * Calling {@link Future#get} will block until the service has finished shutting down, and + * either returns {@link State#STOPPED} or throws an {@link ExecutionException}. If it has * already finished stopping, {@link Future#get} returns immediately. */ Future stop(); /** - * Returns the current state of this service. One of {@link State} possible - * values, or null if this is a brand new object, i.e., has not been put into - * any state yet. + * Returns the current state of this service. One of {@link State} possible values, or null if + * this is a brand new object, i.e., has not been put into any state yet. */ State state(); - /** - * The lifecycle states of a service. - */ - enum State { STARTED, STOPPED, FAILED } + /** The lifecycle states of a service. */ + enum State { + STARTED, + STOPPED, + FAILED + } } diff -Nru sisu-guice-3.2.6/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java sisu-guice-4.2.0/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java --- sisu-guice-3.2.6/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,8 +1,5 @@ package com.google.inject.service; - -import junit.framework.TestCase; - import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -11,10 +8,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import junit.framework.TestCase; -/** - * Tests using Async Service. - */ +/** Tests using Async Service. */ public class SingleServiceIntegrationTest extends TestCase { @@ -23,21 +19,24 @@ final CountDownLatch startLatch = new CountDownLatch(1); final CountDownLatch stopLatch = new CountDownLatch(1); - AsyncService service = new AsyncService(executor) { - @Override protected void onStart() { - assertEquals(1, startLatch.getCount()); - assertEquals(1, stopLatch.getCount()); - - startLatch.countDown(); - } - - @Override protected void onStop() { - assertEquals(0, startLatch.getCount()); - assertEquals(1, stopLatch.getCount()); - - stopLatch.countDown(); - } - }; + AsyncService service = + new AsyncService(executor) { + @Override + protected void onStart() { + assertEquals(1, startLatch.getCount()); + assertEquals(1, stopLatch.getCount()); + + startLatch.countDown(); + } + + @Override + protected void onStop() { + assertEquals(0, startLatch.getCount()); + assertEquals(1, stopLatch.getCount()); + + stopLatch.countDown(); + } + }; Future future = service.start(); // This should not pass! TODO(sameb): Why? Looks like it should to me @@ -61,15 +60,18 @@ ExecutorService executor = Executors.newSingleThreadExecutor(); final AtomicInteger integer = new AtomicInteger(2); - AsyncService service = new AsyncService(executor) { - @Override protected void onStart() { - assertEquals(2, integer.getAndDecrement()); - } - - @Override protected void onStop() { - assertEquals(1, integer.getAndDecrement()); - } - }; + AsyncService service = + new AsyncService(executor) { + @Override + protected void onStart() { + assertEquals(2, integer.getAndDecrement()); + } + + @Override + protected void onStop() { + assertEquals(1, integer.getAndDecrement()); + } + }; service.start().get(2, TimeUnit.SECONDS); service.stop().get(2, TimeUnit.SECONDS); diff -Nru sisu-guice-3.2.6/extensions/servlet/pom.xml sisu-guice-4.2.0/extensions/servlet/pom.xml --- sisu-guice-3.2.6/extensions/servlet/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject extensions-parent - 3.2.6 + 4.2.0 guice-servlet @@ -28,4 +28,18 @@ + + + + maven-jar-plugin + + + + com.google.guice.extensions.servlet + + + + + + diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,8 @@ import com.google.common.collect.Sets; import com.google.inject.Injector; import com.google.inject.Provider; - import java.io.IOException; import java.util.Set; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.RequestDispatcher; @@ -49,7 +47,9 @@ //Guards a DCL, so needs to be volatile private volatile boolean initialized = false; - protected AbstractFilterPipeline(Injector injector, AbstractServletPipeline servletPipeline, + protected AbstractFilterPipeline( + Injector injector, + AbstractServletPipeline servletPipeline, Provider servletContext) { this.injector = injector; this.servletPipeline = servletPipeline; @@ -66,12 +66,11 @@ */ protected abstract FilterDefinition[] filterDefinitions(); - public synchronized void initPipeline(ServletContext servletContext) - throws ServletException { + @Override + public synchronized void initPipeline(ServletContext servletContext) throws ServletException { //double-checked lock, prevents duplicate initialization - if (initialized) - return; + if (initialized) return; // Used to prevent duplicate initialization. Set initializedSoFar = Sets.newIdentityHashSet(); @@ -87,8 +86,10 @@ initialized = true; } - public void dispatch(ServletRequest request, ServletResponse response, - FilterChain proceedingFilterChain) throws IOException, ServletException { + @Override + public void dispatch( + ServletRequest request, ServletResponse response, FilterChain proceedingFilterChain) + throws IOException, ServletException { //lazy init of filter pipeline (OK by the servlet specification). This is needed //in order for us not to force users to create a GuiceServletContextListener subclass. @@ -99,23 +100,22 @@ //obtain the servlet pipeline to dispatch against new FilterChainInvocation(filterDefinitions(), servletPipeline, proceedingFilterChain) .doFilter(withDispatcher(request, servletPipeline), response); - } /** * Used to create an proxy that dispatches either to the guice-servlet pipeline or the regular * pipeline based on uri-path match. This proxy also provides minimal forwarding support. * - * We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline + *

    We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline * is not called again). However, we can wrap requests with our own dispatcher to forward the * *other* way. web.xml Servlets/JSPs can forward to themselves as per normal. * - * This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, + *

    This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, * incrementally, but not the other way around (which, we should actively discourage). */ - @SuppressWarnings({ "JavaDoc", "deprecation" }) - private ServletRequest withDispatcher(ServletRequest servletRequest, - final AbstractServletPipeline servletPipeline) { + @SuppressWarnings({"JavaDoc", "deprecation"}) + private ServletRequest withDispatcher( + ServletRequest servletRequest, final AbstractServletPipeline servletPipeline) { // don't wrap the request if there are no servlets mapped. This prevents us from inserting our // wrapper unless it's actually going to be used. This is necessary for compatibility for apps @@ -137,6 +137,7 @@ }; } + @Override public void destroyPipeline() { //destroy servlets first servletPipeline.destroy(); diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,42 +20,43 @@ /** * Abstract implementation for all servlet module bindings - * + * * @author sameb@google.com (Sam Berlin) */ class AbstractServletModuleBinding implements ServletModuleBinding { - + private final Map initParams; - private final String pattern; private final T target; private final UriPatternMatcher patternMatcher; - AbstractServletModuleBinding(Map initParams, String pattern, T target, - UriPatternMatcher patternMatcher) { + AbstractServletModuleBinding( + Map initParams, T target, UriPatternMatcher patternMatcher) { this.initParams = initParams; - this.pattern = pattern; this.target = target; this.patternMatcher = patternMatcher; } + @Override public Map getInitParams() { return initParams; } + @Override public String getPattern() { - return pattern; + return patternMatcher.getOriginalPattern(); } protected T getTarget() { return target; } + @Override public UriPatternType getUriPatternType() { return patternMatcher.getPatternType(); } - + + @Override public boolean matchesUri(String uri) { return patternMatcher.matches(uri); } - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,8 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import com.google.inject.Injector; - import java.io.IOException; import java.util.Set; - import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -79,8 +77,8 @@ } /** - * @return Returns a request dispatcher wrapped with a servlet mapped to - * the given path or null if no mapping was found. + * @return Returns a request dispatcher wrapped with a servlet mapped to the given path or null if + * no mapping was found. */ RequestDispatcher getRequestDispatcher(String path) { final String newRequestUri = path; @@ -91,18 +89,20 @@ for (final ServletDefinition servletDefinition : servletDefinitions()) { if (servletDefinition.shouldServe(path)) { return new RequestDispatcher() { + @Override public void forward(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { - Preconditions.checkState(!servletResponse.isCommitted(), + Preconditions.checkState( + !servletResponse.isCommitted(), "Response has been committed--you can only call forward before" - + " committing the response (hint: don't flush buffers)"); + + " committing the response (hint: don't flush buffers)"); // clear buffer before forwarding servletResponse.resetBuffer(); ServletRequest requestToProcess; if (servletRequest instanceof HttpServletRequest) { - requestToProcess = wrapRequest((HttpServletRequest)servletRequest, newRequestUri); + requestToProcess = wrapRequest((HttpServletRequest) servletRequest, newRequestUri); } else { // This should never happen, but instead of throwing an exception // we will allow a happy case pass thru for maximum tolerance to @@ -114,14 +114,18 @@ doServiceImpl(servletDefinition, requestToProcess, servletResponse); } + @Override public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { // route to the target servlet doServiceImpl(servletDefinition, servletRequest, servletResponse); } - private void doServiceImpl(ServletDefinition servletDefinition, ServletRequest servletRequest, - ServletResponse servletResponse) throws ServletException, IOException { + private void doServiceImpl( + ServletDefinition servletDefinition, + ServletRequest servletRequest, + ServletResponse servletResponse) + throws ServletException, IOException { servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE); try { @@ -145,15 +149,16 @@ /** * A Marker constant attribute that when present in the request indicates to Guice servlet that - * this request has been generated by a request dispatcher rather than the servlet pipeline. - * In accordance with section 8.4.2 of the Servlet 2.4 specification. + * this request has been generated by a request dispatcher rather than the servlet pipeline. In + * accordance with section 8.4.2 of the Servlet 2.4 specification. */ static final String REQUEST_DISPATCHER_REQUEST = "javax.servlet.forward.servlet_path"; private static class RequestDispatcherRequestWrapper extends HttpServletRequestWrapper { private final String newRequestUri; - RequestDispatcherRequestWrapper(HttpServletRequest servletRequest, String newRequestUri) { + RequestDispatcherRequestWrapper( + HttpServletRequest servletRequest, String newRequestUri) { super(servletRequest); this.newRequestUri = newRequestUri; } @@ -173,9 +178,9 @@ url.append("://"); url.append(getServerName()); // port might be -1 in some cases (see java.net.URL.getPort) - if (port > 0 && - (("http".equals(scheme) && (port != 80)) || - ("https".equals(scheme) && (port != 443)))) { + if (port > 0 + && (("http".equals(scheme) && (port != 80)) + || ("https".equals(scheme) && (port != 443)))) { url.append(':'); url.append(port); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,8 @@ import com.google.common.collect.Maps; import com.google.inject.OutOfScopeException; - import java.io.IOException; import java.util.Map; - import javax.servlet.ServletInputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -29,8 +27,7 @@ import javax.servlet.http.HttpSession; /** - * A wrapper for requests that makes requests immutable, taking a snapshot - * of the original request. + * A wrapper for requests that makes requests immutable, taking a snapshot of the original request. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @@ -63,31 +60,38 @@ } } - @Override public HttpSession getSession() { + @Override + public HttpSession getSession() { throw new OutOfScopeException("Cannot access the session in a continued request"); } - @Override public HttpSession getSession(boolean create) { + @Override + public HttpSession getSession(boolean create) { throw new UnsupportedOperationException("Cannot access the session in a continued request"); } - @Override public ServletInputStream getInputStream() throws IOException { + @Override + public ServletInputStream getInputStream() throws IOException { throw new UnsupportedOperationException("Cannot access raw request on a continued request"); } - @Override public void setAttribute(String name, Object o) { + @Override + public void setAttribute(String name, Object o) { attributes.put(name, o); } - @Override public void removeAttribute(String name) { + @Override + public void removeAttribute(String name) { attributes.remove(name); } - @Override public Object getAttribute(String name) { + @Override + public Object getAttribute(String name) { return attributes.get(name); } - @Override public Cookie[] getCookies() { + @Override + public Cookie[] getCookies() { // NOTE(dhanji): Cookies themselves are mutable. However a ContinuingHttpServletRequest // snapshots the original set of cookies it received and imprisons them in immutable // form. Unfortunately, the cookie array itself is mutable and there is no way for us @@ -112,31 +116,38 @@ } } - @Override public void setComment(String purpose) { + @Override + public void setComment(String purpose) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } - @Override public void setDomain(String pattern) { + @Override + public void setDomain(String pattern) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } - @Override public void setMaxAge(int expiry) { + @Override + public void setMaxAge(int expiry) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } - @Override public void setPath(String uri) { + @Override + public void setPath(String uri) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } - @Override public void setSecure(boolean flag) { + @Override + public void setSecure(boolean flag) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } - @Override public void setValue(String newValue) { + @Override + public void setValue(String newValue) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } - @Override public void setVersion(int v) { + @Override + public void setVersion(int v) { throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); } } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ package com.google.inject.servlet; import java.io.IOException; - import javax.inject.Inject; import javax.servlet.FilterChain; import javax.servlet.ServletContext; @@ -31,17 +30,19 @@ * @see com.google.inject.servlet.ManagedFilterPipeline See Also ManagedFilterPipeline. */ class DefaultFilterPipeline implements FilterPipeline { - @Inject DefaultFilterPipeline() { - } + @Inject + DefaultFilterPipeline() {} - public void initPipeline(ServletContext context) { - } + @Override + public void initPipeline(ServletContext context) {} - public void destroyPipeline() { - } + @Override + public void destroyPipeline() {} - public void dispatch(ServletRequest request, ServletResponse response, - FilterChain proceedingFilterChain) throws IOException, ServletException { + @Override + public void dispatch( + ServletRequest request, ServletResponse response, FilterChain proceedingFilterChain) + throws IOException, ServletException { proceedingFilterChain.doFilter(request, response); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,8 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; - import java.io.IOException; import java.util.List; -import java.util.Set; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; @@ -35,19 +32,19 @@ * A Filter chain impl which basically passes itself to the "current" filter and iterates the chain * on {@code doFilter()}. Modeled on something similar in Apache Tomcat. * - * Following this, it attempts to dispatch to guice-servlet's registered servlets using the + *

    Following this, it attempts to dispatch to guice-servlet's registered servlets using the * ManagedServletPipeline. * - * And the end, it proceeds to the web.xml (default) servlet filter chain, if needed. + *

    And the end, it proceeds to the web.xml (default) servlet filter chain, if needed. * * @author Dhanji R. Prasanna * @since 1.0 */ class FilterChainInvocation implements FilterChain { - - private static final Set SERVLET_INTERNAL_METHODS = ImmutableSet.of( - FilterChainInvocation.class.getName() + ".doFilter"); - + + private static final ImmutableSet SERVLET_INTERNAL_METHODS = + ImmutableSet.of(FilterChainInvocation.class.getName() + ".doFilter"); + private final FilterDefinition[] filterDefinitions; private final FilterChain proceedingChain; private final AbstractServletPipeline servletPipeline; @@ -57,21 +54,24 @@ // whether or not we've caught an exception & cleaned up stack traces private boolean cleanedStacks = false; - public FilterChainInvocation(FilterDefinition[] filterDefinitions, - AbstractServletPipeline servletPipeline, FilterChain proceedingChain) { + public FilterChainInvocation( + FilterDefinition[] filterDefinitions, + AbstractServletPipeline servletPipeline, + FilterChain proceedingChain) { this.filterDefinitions = filterDefinitions; this.servletPipeline = servletPipeline; this.proceedingChain = proceedingChain; } + @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { GuiceFilter.Context previous = GuiceFilter.localContext.get(); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; - HttpServletRequest originalRequest - = (previous != null) ? previous.getOriginalRequest() : request; + HttpServletRequest originalRequest = + (previous != null) ? previous.getOriginalRequest() : request; GuiceFilter.localContext.set(new GuiceFilter.Context(originalRequest, request, response)); try { Filter filter = findNextFilter(request); @@ -106,8 +106,8 @@ } /** - * Iterates over the remaining filter definitions. - * Returns the first applicable filter, or null if none apply. + * Iterates over the remaining filter definitions. Returns the first applicable filter, or null if + * none apply. */ private Filter findNextFilter(HttpServletRequest request) { while (++index < filterDefinitions.length) { @@ -118,10 +118,10 @@ } return null; } - + /** - * Removes stacktrace elements related to AOP internal mechanics from the - * throwable's stack trace and any causes it may have. + * Removes stacktrace elements related to AOP internal mechanics from the throwable's stack trace + * and any causes it may have. */ private void pruneStacktrace(Throwable throwable) { for (Throwable t = throwable; t != null; t = t.getCause()) { diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; - import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -32,7 +31,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; - import javax.servlet.Filter; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; @@ -47,7 +45,6 @@ public class FilterDefinition implements ProviderWithExtensionVisitor { private static final Logger logger = Logger.getLogger(FilterDefinition.class.getName()); - private final String pattern; private final Key filterKey; private final UriPatternMatcher patternMatcher; private final Map initParams; @@ -55,36 +52,34 @@ private final Filter filterInstance; // always set after init is called. - private final AtomicReference filter = new AtomicReference(); + private final AtomicReference filter = new AtomicReference<>(); - public FilterDefinition(String pattern, Key filterKey, - UriPatternMatcher patternMatcher, Map initParams, Filter filterInstance) { - this.pattern = pattern; + public FilterDefinition( + Key filterKey, + UriPatternMatcher patternMatcher, + Map initParams, + Filter filterInstance) { this.filterKey = filterKey; this.patternMatcher = patternMatcher; this.initParams = Collections.unmodifiableMap(new HashMap(initParams)); this.filterInstance = filterInstance; } + @Override public FilterDefinition get() { return this; } - public V acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - if(visitor instanceof ServletModuleTargetVisitor) { - if(filterInstance != null) { - return ((ServletModuleTargetVisitor)visitor).visit( - new InstanceFilterBindingImpl(initParams, - pattern, - filterInstance, - patternMatcher)); + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { + if (visitor instanceof ServletModuleTargetVisitor) { + if (filterInstance != null) { + return ((ServletModuleTargetVisitor) visitor) + .visit(new InstanceFilterBindingImpl(initParams, filterInstance, patternMatcher)); } else { - return ((ServletModuleTargetVisitor)visitor).visit( - new LinkedFilterBindingImpl(initParams, - pattern, - filterKey, - patternMatcher)); + return ((ServletModuleTargetVisitor) visitor) + .visit(new LinkedFilterBindingImpl(initParams, filterKey, patternMatcher)); } } else { return visitor.visit(binding); @@ -95,13 +90,16 @@ return uri != null && patternMatcher.matches(uri); } - void init(final ServletContext servletContext, Injector injector, - Set initializedSoFar) throws ServletException { + void init( + final ServletContext servletContext, Injector injector, Set initializedSoFar) + throws ServletException { // This absolutely must be a singleton, and so is only initialized once. if (!Scopes.isSingleton(injector.getBinding(filterKey))) { - throw new ServletException("Filters must be bound as singletons. " - + filterKey + " was not bound in singleton scope."); + throw new ServletException( + "Filters must be bound as singletons. " + + filterKey + + " was not bound in singleton scope."); } Filter filter = injector.getInstance(filterKey); @@ -114,23 +112,28 @@ } //initialize our filter with the configured context params and servlet context - filter.init(new FilterConfig() { - public String getFilterName() { - return filterKey.toString(); - } - - public ServletContext getServletContext() { - return servletContext; - } - - public String getInitParameter(String s) { - return initParams.get(s); - } - - public Enumeration getInitParameterNames() { - return Iterators.asEnumeration(initParams.keySet().iterator()); - } - }); + filter.init( + new FilterConfig() { + @Override + public String getFilterName() { + return filterKey.toString(); + } + + @Override + public ServletContext getServletContext() { + return servletContext; + } + + @Override + public String getInitParameter(String s) { + return initParams.get(s); + } + + @Override + public Enumeration getInitParameterNames() { + return Iterators.asEnumeration(initParams.keySet().iterator()); + } + }); initializedSoFar.add(filter); } @@ -176,7 +179,7 @@ public String toPaddedString(int padding) { Filter reference = filter.get(); - return Strings.padEnd(pattern, padding, ' ') + ' ' + return Strings.padEnd(patternMatcher.getOriginalPattern(), padding, ' ') + ' ' + (reference != null ? reference : filterKey); } } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +16,7 @@ package com.google.inject.servlet; import com.google.inject.ImplementedBy; - import java.io.IOException; - import javax.servlet.FilterChain; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -26,15 +24,13 @@ import javax.servlet.ServletResponse; /** - * A dispatcher abstraction for guice-servlet registered servlets and filters. - * By default, we assume a Guice 1.0 style servlet module is in play. In other - * words, we dispatch directly to the web.xml pipeline after setting up scopes. + * A dispatcher abstraction for guice-servlet registered servlets and filters. By default, we assume a + * Guice 1.0 style servlet module is in play. In other words, we dispatch directly to the web.xml + * pipeline after setting up scopes. * - *

    - * If on the other hand, {@link ServletModule} is used to register managed - * servlets and/or filters, then a different pipeline is bound instead. Which, - * after dispatching to Guice-injected filters and servlets continues to the web.xml - * pipeline (if necessary). + *

    If on the other hand, {@link ServletModule} is used to register managed servlets and/or + * filters, then a different pipeline is bound instead. Which, after dispatching to Guice-injected + * filters and servlets continues to the web.xml pipeline (if necessary). * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @@ -60,6 +56,6 @@ * @param response to populate * @param defaultFilterChain for last resort filtering */ - void dispatch(ServletRequest request, ServletResponse response, - FilterChain defaultFilterChain) throws IOException, ServletException; + void dispatch(ServletRequest request, ServletResponse response, FilterChain defaultFilterChain) + throws IOException, ServletException; } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,82 +18,99 @@ import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.internal.UniqueAnnotations; - +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.servlet.Filter; /** - * Builds the guice module that binds configured filters, with their - * wrapper FilterDefinitions. Is part of the binding EDSL. All Filters - * and Servlets are always bound as singletons. + * Builds the guice module that binds configured filters, with their wrapper FilterDefinitions. Is + * part of the binding EDSL. All Filters and Servlets are always bound as singletons. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ class FiltersModuleBuilder { - + private final Binder binder; - + public FiltersModuleBuilder(Binder binder) { this.binder = binder; } public ServletModule.FilterKeyBindingBuilder filter(List patterns) { - return new FilterKeyBindingBuilderImpl(patterns, UriPatternType.SERVLET); + return new FilterKeyBindingBuilderImpl(parsePatterns(UriPatternType.SERVLET, patterns)); } public ServletModule.FilterKeyBindingBuilder filterRegex(List regexes) { - return new FilterKeyBindingBuilderImpl(regexes, UriPatternType.REGEX); + return new FilterKeyBindingBuilderImpl(parsePatterns(UriPatternType.REGEX, regexes)); + } + + private List parsePatterns(UriPatternType type, List patterns) { + List patternMatchers = new ArrayList<>(); + for (String pattern : patterns) { + UriPatternMatcher matcher = null; + try { + matcher = UriPatternType.get(type, pattern); + } catch (IllegalArgumentException iae) { + binder + .skipSources(ServletModule.class, FiltersModuleBuilder.class) + .addError("%s", iae.getMessage()); + } + if (matcher != null) { + patternMatchers.add(matcher); + } + } + return patternMatchers; } //non-static inner class so it can access state of enclosing module class class FilterKeyBindingBuilderImpl implements ServletModule.FilterKeyBindingBuilder { - private final List uriPatterns; - private final UriPatternType uriPatternType; + private final List uriPatterns; - private FilterKeyBindingBuilderImpl(List uriPatterns, UriPatternType uriPatternType) { + private FilterKeyBindingBuilderImpl(List uriPatterns) { this.uriPatterns = uriPatterns; - this.uriPatternType = uriPatternType; } + @Override public void through(Class filterKey) { through(Key.get(filterKey)); } + @Override public void through(Key filterKey) { through(filterKey, new HashMap()); } + @Override public void through(Filter filter) { through(filter, new HashMap()); } - public void through(Class filterKey, - Map initParams) { - + @Override + public void through(Class filterKey, Map initParams) { + // Careful you don't accidentally make this method recursive, thank you IntelliJ IDEA! through(Key.get(filterKey), initParams); } - public void through(Key filterKey, - Map initParams) { + @Override + public void through(Key filterKey, Map initParams) { through(filterKey, initParams, null); } - - private void through(Key filterKey, - Map initParams, - Filter filterInstance) { - for (String pattern : uriPatterns) { - binder.bind(FilterDefinition.class).annotatedWith(UniqueAnnotations.create()).toProvider( - new FilterDefinition(pattern, filterKey, UriPatternType.get(uriPatternType, pattern), - initParams, filterInstance)); + + private void through( + Key filterKey, Map initParams, Filter filterInstance) { + for (UriPatternMatcher pattern : uriPatterns) { + binder + .bind(FilterDefinition.class) + .annotatedWith(UniqueAnnotations.create()) + .toProvider(new FilterDefinition(filterKey, pattern, initParams, filterInstance)); } } - public void through(Filter filter, - Map initParams) { + @Override + public void through(Filter filter, Map initParams) { Key filterKey = Key.get(Filter.class, UniqueAnnotations.create()); binder.bind(filterKey).toInstance(filter); through(filterKey, initParams, filter); diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,12 +21,11 @@ import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.internal.Errors; - import java.io.IOException; import java.lang.ref.WeakReference; -import java.util.concurrent.Callable; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -38,11 +37,11 @@ import javax.servlet.http.HttpServletResponse; /** - *

    * Apply this filter in web.xml above all other filters (typically), to all requests where you plan - * to use servlet scopes. This is also needed in order to dispatch requests to injectable filters - * and servlets: - *

    + * to use servlet scopes. This is also needed in order to dispatch requests to injectable filters
    + * and servlets:
    + *
    + * 
      *  <filter>
      *    <filter-name>guiceFilter</filter-name>
      *    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
    @@ -54,20 +53,18 @@
      *  </filter-mapping>
      *  
    * - * This filter must appear before every filter that makes use of Guice injection or servlet - * scopes functionality. Typically, you will only register this filter in web.xml and register - * any other filters (and servlets) using a {@link ServletModule}. + * This filter must appear before every filter that makes use of Guice injection or servlet scopes + * functionality. Typically, you will only register this filter in web.xml and register any other + * filters (and servlets) using a {@link ServletModule}. * * @author crazybob@google.com (Bob Lee) * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class GuiceFilter implements Filter { - static final ThreadLocal localContext = new ThreadLocal(); + static final ThreadLocal localContext = new ThreadLocal<>(); static volatile FilterPipeline pipeline = new DefaultFilterPipeline(); - /** - * We allow both the static and dynamic versions of the pipeline to exist. - */ + /** We allow both the static and dynamic versions of the pipeline to exist. */ private final FilterPipeline injectedPipeline; /** Used to inject the servlets configured via {@link ServletModule} */ @@ -76,12 +73,13 @@ private static final String MULTIPLE_INJECTORS_WARNING = "Multiple Servlet injectors detected. This is a warning " - + "indicating that you have more than one " - + GuiceFilter.class.getSimpleName() + " running " - + "in your web application. If this is deliberate, you may safely " - + "ignore this message. If this is NOT deliberate however, " - + "your application may not work as expected."; - + + "indicating that you have more than one " + + GuiceFilter.class.getSimpleName() + + " running " + + "in your web application. If this is deliberate, you may safely " + + "ignore this message. If this is NOT deliberate however, " + + "your application may not work as expected."; + private static final Logger LOGGER = Logger.getLogger(GuiceFilter.class.getName()); public GuiceFilter() { @@ -89,7 +87,8 @@ this(null); } - @Inject protected GuiceFilter(FilterPipeline filterPipeline) { + @Inject + protected GuiceFilter(FilterPipeline filterPipeline) { injectedPipeline = filterPipeline; } @@ -113,6 +112,7 @@ localContext.remove(); } + @Override public void doFilter( final ServletRequest servletRequest, final ServletResponse servletResponse, @@ -124,16 +124,16 @@ Context previous = GuiceFilter.localContext.get(); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; - HttpServletRequest originalRequest - = (previous != null) ? previous.getOriginalRequest() : request; + HttpServletRequest originalRequest = + (previous != null) ? previous.getOriginalRequest() : request; try { - new Context(originalRequest, request, response).call(new Callable() { - @Override public Void call() throws Exception { - //dispatch across the servlet pipeline, ensuring web.xml's filterchain is honored - filterPipeline.dispatch(servletRequest, servletResponse, filterChain); - return null; - } - }); + RequestScoper.CloseableScope scope = new Context(originalRequest, request, response).open(); + try { + //dispatch across the servlet pipeline, ensuring web.xml's filterchain is honored + filterPipeline.dispatch(servletRequest, servletResponse, filterChain); + } finally { + scope.close(); + } } catch (IOException e) { throw e; } catch (ServletException e) { @@ -162,20 +162,29 @@ private static Context getContext(Key key) { Context context = localContext.get(); if (context == null) { - throw new OutOfScopeException("Cannot access scoped [" + Errors.convert(key) - + "]. Either we are not currently inside an HTTP Servlet request, or you may" - + " have forgotten to apply " + GuiceFilter.class.getName() - + " as a servlet filter for this request."); + throw new OutOfScopeException( + "Cannot access scoped [" + + Errors.convert(key) + + "]. Either we are not currently inside an HTTP Servlet request, or you may" + + " have forgotten to apply " + + GuiceFilter.class.getName() + + " as a servlet filter for this request."); } return context; } - static class Context { + static class Context implements RequestScoper { final HttpServletRequest originalRequest; final HttpServletRequest request; final HttpServletResponse response; - Context(HttpServletRequest originalRequest, HttpServletRequest request, + // Synchronized to prevent two threads from using the same request + // scope concurrently. + final Lock lock = new ReentrantLock(); + + Context( + HttpServletRequest originalRequest, + HttpServletRequest request, HttpServletResponse response) { this.originalRequest = originalRequest; this.request = request; @@ -194,24 +203,27 @@ return response; } - // Synchronized to prevent two threads from using the same request - // scope concurrently. - synchronized T call(Callable callable) throws Exception { - Context previous = localContext.get(); + @Override + public CloseableScope open() { + lock.lock(); + final Context previous = localContext.get(); localContext.set(this); - try { - return callable.call(); - } finally { - localContext.set(previous); - } + return new CloseableScope() { + @Override + public void close() { + localContext.set(previous); + lock.unlock(); + } + }; } } + @Override public void init(FilterConfig filterConfig) throws ServletException { final ServletContext servletContext = filterConfig.getServletContext(); // Store servlet context in a weakreference, for injection - GuiceFilter.servletContext = new WeakReference(servletContext); + GuiceFilter.servletContext = new WeakReference<>(servletContext); // In the default pipeline, this is a noop. However, if replaced // by a managed pipeline, a lazy init will be triggered the first time @@ -220,6 +232,7 @@ filterPipeline.initPipeline(servletContext); } + @Override public void destroy() { try { diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,47 +17,44 @@ package com.google.inject.servlet; import com.google.inject.Injector; - import java.lang.ref.WeakReference; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** - * As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener} - * class as a logical place to create and configure your injector. This will ensure the injector - * is created when the web application is deployed. - * + * As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener} class + * as a logical place to create and configure your injector. This will ensure the injector is + * created when the web application is deployed. + * * @author Kevin Bourrillion (kevinb@google.com) * @since 2.0 */ -public abstract class GuiceServletContextListener - implements ServletContextListener { +public abstract class GuiceServletContextListener implements ServletContextListener { static final String INJECTOR_NAME = Injector.class.getName(); + @Override public void contextInitialized(ServletContextEvent servletContextEvent) { final ServletContext servletContext = servletContextEvent.getServletContext(); // Set the Servletcontext early for those people who are using this class. // NOTE(dhanji): This use of the servletContext is deprecated. - GuiceFilter.servletContext = new WeakReference(servletContext); + GuiceFilter.servletContext = new WeakReference<>(servletContext); Injector injector = getInjector(); - injector.getInstance(InternalServletModule.BackwardsCompatibleServletContextProvider.class) + injector + .getInstance(InternalServletModule.BackwardsCompatibleServletContextProvider.class) .set(servletContext); servletContext.setAttribute(INJECTOR_NAME, injector); } + @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { ServletContext servletContext = servletContextEvent.getServletContext(); servletContext.removeAttribute(INJECTOR_NAME); } - /** - * Override this method to create (or otherwise obtain a reference to) your - * injector. - */ + /** Override this method to create (or otherwise obtain a reference to) your injector. */ protected abstract Injector getInjector(); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,35 +16,35 @@ package com.google.inject.servlet; -import com.google.common.base.Objects; - +import com.google.common.base.MoreObjects; import java.util.Map; - import javax.servlet.Filter; /** * Default implementation of InstanceFilterBinding. - * + * * @author sameb@google.com (Sam Berlin) */ -class InstanceFilterBindingImpl extends AbstractServletModuleBinding implements - InstanceFilterBinding { +class InstanceFilterBindingImpl extends AbstractServletModuleBinding + implements InstanceFilterBinding { - InstanceFilterBindingImpl(Map initParams, String pattern, - Filter target, UriPatternMatcher patternMatcher) { - super(initParams, pattern, target, patternMatcher); + InstanceFilterBindingImpl( + Map initParams, Filter target, UriPatternMatcher patternMatcher) { + super(initParams, target, patternMatcher); } + @Override public Filter getFilterInstance() { return getTarget(); } - - @Override public String toString() { - return Objects.toStringHelper(InstanceFilterBinding.class) - .add("pattern", getPattern()) - .add("initParams", getInitParams()) - .add("uriPatternType", getUriPatternType()) - .add("filterInstance", getFilterInstance()) - .toString(); + + @Override + public String toString() { + return MoreObjects.toStringHelper(InstanceFilterBinding.class) + .add("pattern", getPattern()) + .add("initParams", getInitParams()) + .add("uriPatternType", getUriPatternType()) + .add("filterInstance", getFilterInstance()) + .toString(); } } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,7 @@ import javax.servlet.Filter; /** - * A binding to a single instance of a filter. + * A binding to a single instance of a filter. * * @author sameb@google.com * @since 3.0 @@ -28,5 +28,4 @@ /** Returns the filter instance that will be used. */ Filter getFilterInstance(); - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,36 +16,35 @@ package com.google.inject.servlet; -import com.google.common.base.Objects; - +import com.google.common.base.MoreObjects; import java.util.Map; - import javax.servlet.http.HttpServlet; /** * Default implementation of InstanceServletBinding. - * + * * @author sameb@google.com (Sam Berlin) */ -class InstanceServletBindingImpl extends AbstractServletModuleBinding implements - InstanceServletBinding { +class InstanceServletBindingImpl extends AbstractServletModuleBinding + implements InstanceServletBinding { - InstanceServletBindingImpl(Map initParams, String pattern, - HttpServlet target, UriPatternMatcher patternMatcher) { - super(initParams, pattern, target, patternMatcher); + InstanceServletBindingImpl( + Map initParams, HttpServlet target, UriPatternMatcher patternMatcher) { + super(initParams, target, patternMatcher); } + @Override public HttpServlet getServletInstance() { return getTarget(); } - @Override public String toString() { - return Objects.toStringHelper(InstanceServletBinding.class) - .add("pattern", getPattern()) - .add("initParams", getInitParams()) - .add("uriPatternType", getUriPatternType()) - .add("servletInstance", getServletInstance()) - .toString(); + @Override + public String toString() { + return MoreObjects.toStringHelper(InstanceServletBinding.class) + .add("pattern", getPattern()) + .add("initParams", getInitParams()) + .add("uriPatternType", getUriPatternType()) + .add("servletInstance", getServletInstance()) + .toString(); } - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,7 @@ import javax.servlet.http.HttpServlet; /** - * A binding to a single instance of a servlet. + * A binding to a single instance of a servlet. * * @author sameb@google.com * @since 3.0 @@ -28,5 +28,4 @@ /** Returns the servlet instance that will be used. */ HttpServlet getServletInstance(); - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,10 +24,8 @@ import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.Singleton; - import java.util.Map; import java.util.logging.Logger; - import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -36,44 +34,47 @@ import javax.servlet.http.HttpSession; /** - * This is a left-factoring of all ServletModules installed in the system. - * In other words, this module contains the bindings common to all ServletModules, - * and is bound exactly once per injector. + * This is a left-factoring of all ServletModules installed in the system. In other words, this + * module contains the bindings common to all ServletModules, and is bound exactly once per + * injector. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ final class InternalServletModule extends AbstractModule { /** - * Special Provider that tries to obtain an injected servlet context, specific - * to the current injector, failing which, it falls back to the static singleton - * instance that is available in the legacy Guice Servlet. + * Special Provider that tries to obtain an injected servlet context, specific to the current + * injector, failing which, it falls back to the static singleton instance that is available in + * the legacy Guice Servlet. */ @Singleton static class BackwardsCompatibleServletContextProvider implements Provider { private ServletContext injectedServletContext; - @Inject BackwardsCompatibleServletContextProvider() {} + @Inject + BackwardsCompatibleServletContextProvider() {} // This setter is called by the GuiceServletContextListener void set(ServletContext injectedServletContext) { this.injectedServletContext = injectedServletContext; } + @Override public ServletContext get() { if (null != injectedServletContext) { return injectedServletContext; } Logger.getLogger(InternalServletModule.class.getName()) - .warning("You are attempting to use a deprecated API (specifically," - + " attempting to @Inject ServletContext inside an eagerly created" - + " singleton. While we allow this for backwards compatibility, be" - + " warned that this MAY have unexpected behavior if you have more" - + " than one injector (with ServletModule) running in the same JVM." - + " Please consult the Guice documentation at" - + " https://github.com/google/guice/wiki/Servlets for more" - + " information."); + .warning( + "You are attempting to use a deprecated API (specifically," + + " attempting to @Inject ServletContext inside an eagerly created" + + " singleton. While we allow this for backwards compatibility, be" + + " warned that this MAY have unexpected behavior if you have more" + + " than one injector (with ServletModule) running in the same JVM." + + " Please consult the Guice documentation at" + + " https://github.com/google/guice/wiki/Servlets for more" + + " information."); return GuiceFilter.getServletContext(); } } @@ -98,25 +99,35 @@ bind(BackwardsCompatibleServletContextProvider.class); } - @Provides @Singleton @ScopingOnly GuiceFilter provideScopingOnlyGuiceFilter() { + @Provides + @Singleton + @ScopingOnly + GuiceFilter provideScopingOnlyGuiceFilter() { return new GuiceFilter(new DefaultFilterPipeline()); } - @Provides @RequestScoped HttpServletRequest provideHttpServletRequest() { + @Provides + @RequestScoped + HttpServletRequest provideHttpServletRequest() { return GuiceFilter.getRequest(Key.get(HttpServletRequest.class)); } - @Provides @RequestScoped HttpServletResponse provideHttpServletResponse() { + @Provides + @RequestScoped + HttpServletResponse provideHttpServletResponse() { return GuiceFilter.getResponse(Key.get(HttpServletResponse.class)); } - @Provides HttpSession provideHttpSession() { + @Provides + HttpSession provideHttpSession() { return GuiceFilter.getRequest(Key.get(HttpSession.class)).getSession(); } @SuppressWarnings("unchecked") // defined by getParameterMap() - @Provides @RequestScoped @RequestParameters Map provideRequestParameters( - ServletRequest req) { + @Provides + @RequestScoped + @RequestParameters + Map provideRequestParameters(ServletRequest req) { return req.getParameterMap(); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,37 +16,38 @@ package com.google.inject.servlet; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.inject.Key; - import java.util.Map; - import javax.servlet.Filter; /** * Default implementation of LinkedFilterBinding. - * + * * @author sameb@google.com (Sam Berlin) */ class LinkedFilterBindingImpl extends AbstractServletModuleBinding> implements LinkedFilterBinding { - LinkedFilterBindingImpl(Map initParams, String pattern, - Key target, UriPatternMatcher patternMatcher) { - super(initParams, pattern, target, patternMatcher); + LinkedFilterBindingImpl( + Map initParams, + Key target, + UriPatternMatcher patternMatcher) { + super(initParams, target, patternMatcher); } + @Override public Key getLinkedKey() { return getTarget(); } - - @Override public String toString() { - return Objects.toStringHelper(LinkedFilterBinding.class) - .add("pattern", getPattern()) - .add("initParams", getInitParams()) - .add("uriPatternType", getUriPatternType()) - .add("linkedFilterKey", getLinkedKey()) - .toString(); + + @Override + public String toString() { + return MoreObjects.toStringHelper(LinkedFilterBinding.class) + .add("pattern", getPattern()) + .add("initParams", getInitParams()) + .add("uriPatternType", getUriPatternType()) + .add("linkedFilterKey", getLinkedKey()) + .toString(); } - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,10 @@ package com.google.inject.servlet; import com.google.inject.Key; - import javax.servlet.Filter; /** - * A linked binding to a filter. + * A linked binding to a filter. * * @author sameb@google.com * @since 3.0 @@ -30,5 +29,4 @@ /** Returns the key used to lookup the filter instance. */ Key getLinkedKey(); - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,37 +16,38 @@ package com.google.inject.servlet; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.inject.Key; - import java.util.Map; - import javax.servlet.http.HttpServlet; /** * Default implementation of LinkedServletBinding. - * + * * @author sameb@google.com (Sam Berlin) */ class LinkedServletBindingImpl extends AbstractServletModuleBinding> implements LinkedServletBinding { - LinkedServletBindingImpl(Map initParams, String pattern, - Key target, UriPatternMatcher patternMatcher) { - super(initParams, pattern, target, patternMatcher); + LinkedServletBindingImpl( + Map initParams, + Key target, + UriPatternMatcher patternMatcher) { + super(initParams, target, patternMatcher); } + @Override public Key getLinkedKey() { return getTarget(); } - @Override public String toString() { - return Objects.toStringHelper(LinkedServletBinding.class) - .add("pattern", getPattern()) - .add("initParams", getInitParams()) - .add("uriPatternType", getUriPatternType()) - .add("linkedServletKey", getLinkedKey()) - .toString(); + @Override + public String toString() { + return MoreObjects.toStringHelper(LinkedServletBinding.class) + .add("pattern", getPattern()) + .add("initParams", getInitParams()) + .add("uriPatternType", getUriPatternType()) + .add("linkedServletKey", getLinkedKey()) + .toString(); } - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,10 @@ package com.google.inject.servlet; import com.google.inject.Key; - import javax.servlet.http.HttpServlet; /** - * A linked binding to a servlet. + * A linked binding to a servlet. * * @author sameb@google.com * @since 3.0 @@ -30,5 +29,4 @@ /** Returns the key used to lookup the servlet instance. */ Key getLinkedKey(); - } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,9 +22,7 @@ import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; - import java.util.List; - import javax.servlet.ServletContext; /** @@ -41,7 +39,9 @@ TypeLiteral.get(FilterDefinition.class); @Inject - public ManagedFilterPipeline(Injector injector, ManagedServletPipeline servletPipeline, + public ManagedFilterPipeline( + Injector injector, + ManagedServletPipeline servletPipeline, Provider servletContext) { super(injector, servletPipeline, servletContext); @@ -61,16 +61,16 @@ /** * Introspects the injector and collects all instances of bound {@code List} * into a master list. - * - * We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map - * that preserves insertion order in entry-set iterators. + * + *

    We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map that + * preserves insertion order in entry-set iterators. */ private FilterDefinition[] collectFilterDefinitions(Injector injector) { List filterDefinitions = Lists.newArrayList(); for (Binding entry : injector.findBindingsByType(FILTER_DEFS)) { filterDefinitions.add(entry.getProvider().get()); } - + // Copy to a fixed-size array for speed of iteration. return filterDefinitions.toArray(new FilterDefinition[filterDefinitions.size()]); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; - import java.util.List; /** @@ -55,13 +54,13 @@ * Introspects the injector and collects all instances of bound {@code List} * into a master list. * - * We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map - * that preserves insertion order in entry-set iterators. + *

    We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map that + * preserves insertion order in entry-set iterators. */ private ServletDefinition[] collectServletDefinitions(Injector injector) { List servletDefinitions = Lists.newArrayList(); for (Binding entry : injector.findBindingsByType(SERVLET_DEFS)) { - servletDefinitions.add(entry.getProvider().get()); + servletDefinitions.add(entry.getProvider().get()); } // Copy to a fixed size array for speed. diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/package-info.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/package-info.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,11 +15,10 @@ */ /** - * Servlet API scopes, bindings and registration; this extension requires {@code - * guice-servlet-3.0.jar}. + * Servlet API scopes, bindings and registration; this extension requires {@code guice-servlet.jar}. * *

    Apply {@link com.google.inject.servlet.GuiceFilter} to any servlets which will use the servlet * scopes. Install {@link com.google.inject.servlet.ServletModule} into your {@link * com.google.inject.Injector} to install everything at once. */ -package com.google.inject.servlet; \ No newline at end of file +package com.google.inject.servlet; diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,18 +19,17 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.BindingAnnotation; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** - * Apply this to field or parameters of type {@code Map} - * when you want the HTTP request parameter map to be injected. + * Apply this to field or parameters of type {@code Map} when you want the HTTP + * request parameter map to be injected. * * @author crazybob@google.com (Bob Lee) */ @Retention(RUNTIME) -@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @BindingAnnotation public @interface RequestParameters {} diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.servlet; import com.google.inject.ScopeAnnotation; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -28,7 +27,7 @@ * * @author crazybob@google.com (Bob Lee) */ -@Target({ ElementType.TYPE, ElementType.METHOD }) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @ScopeAnnotation public @interface RequestScoped {} diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/RequestScoper.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/RequestScoper.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/RequestScoper.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/RequestScoper.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,20 @@ +package com.google.inject.servlet; + +import java.io.Closeable; + +/** Object that can be used to apply a request scope to a block of code. */ +public interface RequestScoper { + /** + * Opens up the request scope until the returned object is closed. Implementations should ensure + * (e.g. by blocking) that multiple threads cannot open the same request scope concurrently. It is + * allowable to open the same request scope on the same thread, as long as open/close calls are + * correctly nested. + */ + CloseableScope open(); + + /** Closeable subclass that does not throw any exceptions from close. */ + public interface CloseableScope extends Closeable { + @Override + void close(); + } +} diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ScopingException.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ScopingException.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ScopingException.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ScopingException.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,19 +19,18 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.BindingAnnotation; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** - * Annotates a {@link GuiceFilter} that provides scope functionality, but - * doesn't dispatch to {@link ServletModule} bound servlets or filters. + * Annotates a {@link GuiceFilter} that provides scope functionality, but doesn't dispatch to {@link + * ServletModule} bound servlets or filters. * * @author iqshum@google.com (Isaac Shum) * @since 4.0 */ @Retention(RUNTIME) -@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @BindingAnnotation public @interface ScopingOnly {} diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +25,6 @@ import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; - import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -37,7 +36,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; - import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -56,7 +54,6 @@ public class ServletDefinition implements ProviderWithExtensionVisitor { private static final Logger logger = Logger.getLogger(ServletDefinition.class.getName()); - private final String pattern; private final Key servletKey; private final UriPatternMatcher patternMatcher; private final Map initParams; @@ -64,36 +61,34 @@ private final HttpServlet servletInstance; //always set in init, our servlet is always presumed to be a singleton - private final AtomicReference httpServlet = new AtomicReference(); + private final AtomicReference httpServlet = new AtomicReference<>(); - public ServletDefinition(String pattern, Key servletKey, - UriPatternMatcher patternMatcher, Map initParams, HttpServlet servletInstance) { - this.pattern = pattern; + public ServletDefinition( + Key servletKey, + UriPatternMatcher patternMatcher, + Map initParams, + HttpServlet servletInstance) { this.servletKey = servletKey; this.patternMatcher = patternMatcher; this.initParams = Collections.unmodifiableMap(new HashMap(initParams)); this.servletInstance = servletInstance; } + @Override public ServletDefinition get() { return this; } - public V acceptExtensionVisitor(BindingTargetVisitor visitor, - ProviderInstanceBinding binding) { - if(visitor instanceof ServletModuleTargetVisitor) { - if(servletInstance != null) { - return ((ServletModuleTargetVisitor)visitor).visit( - new InstanceServletBindingImpl(initParams, - pattern, - servletInstance, - patternMatcher)); + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, ProviderInstanceBinding binding) { + if (visitor instanceof ServletModuleTargetVisitor) { + if (servletInstance != null) { + return ((ServletModuleTargetVisitor) visitor) + .visit(new InstanceServletBindingImpl(initParams, servletInstance, patternMatcher)); } else { - return ((ServletModuleTargetVisitor)visitor).visit( - new LinkedServletBindingImpl(initParams, - pattern, - servletKey, - patternMatcher)); + return ((ServletModuleTargetVisitor) visitor) + .visit(new LinkedServletBindingImpl(initParams, servletKey, patternMatcher)); } } else { return visitor.visit(binding); @@ -104,13 +99,16 @@ return uri != null && patternMatcher.matches(uri); } - void init(final ServletContext servletContext, Injector injector, - Set initializedSoFar) throws ServletException { + void init( + final ServletContext servletContext, Injector injector, Set initializedSoFar) + throws ServletException { // This absolutely must be a singleton, and so is only initialized once. if (!Scopes.isSingleton(injector.getBinding(servletKey))) { - throw new ServletException("Servlets must be bound as singletons. " - + servletKey + " was not bound in singleton scope."); + throw new ServletException( + "Servlets must be bound as singletons. " + + servletKey + + " was not bound in singleton scope."); } HttpServlet httpServlet = injector.getInstance(servletKey); @@ -122,23 +120,28 @@ } //initialize our servlet with the configured context params and servlet context - httpServlet.init(new ServletConfig() { - public String getServletName() { - return servletKey.toString(); - } + httpServlet.init( + new ServletConfig() { + @Override + public String getServletName() { + return servletKey.toString(); + } - public ServletContext getServletContext() { - return servletContext; - } + @Override + public ServletContext getServletContext() { + return servletContext; + } - public String getInitParameter(String s) { - return initParams.get(s); - } + @Override + public String getInitParameter(String s) { + return initParams.get(s); + } - public Enumeration getInitParameterNames() { - return Iterators.asEnumeration(initParams.keySet().iterator()); - } - }); + @Override + public Enumeration getInitParameterNames() { + return Iterators.asEnumeration(initParams.keySet().iterator()); + } + }); // Mark as initialized. initializedSoFar.add(httpServlet); @@ -167,14 +170,13 @@ * Wrapper around the service chain to ensure a servlet is servicing what it must and provides it * with a wrapped request. * - * @return Returns true if this servlet triggered for the given request. Or false if - * guice-servlet should continue dispatching down the servlet pipeline. - * + * @return Returns true if this servlet triggered for the given request. Or false if guice-servlet + * should continue dispatching down the servlet pipeline. * @throws IOException If thrown by underlying servlet * @throws ServletException If thrown by underlying servlet */ - boolean service(ServletRequest servletRequest, - ServletResponse servletResponse) throws IOException, ServletException { + boolean service(ServletRequest servletRequest, ServletResponse servletResponse) + throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final String path = ServletUtils.getContextRelativePath(request); @@ -194,89 +196,90 @@ * Utility that delegates to the actual service method of the servlet wrapped with a contextual * request (i.e. with correctly computed path info). * - * We need to suppress deprecation coz we use HttpServletRequestWrapper, which implements + *

    We need to suppress deprecation coz we use HttpServletRequestWrapper, which implements * deprecated API for backwards compatibility. */ void doService(final ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { - HttpServletRequest request = new HttpServletRequestWrapper( - (HttpServletRequest) servletRequest) { - private boolean pathComputed; - private String path; - - private boolean pathInfoComputed; - private String pathInfo; - - @Override - public String getPathInfo() { - if (!isPathInfoComputed()) { - String servletPath = getServletPath(); - int servletPathLength = servletPath.length(); - String requestUri = getRequestURI(); - pathInfo = requestUri.substring(getContextPath().length()).replaceAll("[/]{2,}", "/"); - // See: https://github.com/google/guice/issues/372 - if (pathInfo.startsWith(servletPath)) { - pathInfo = pathInfo.substring(servletPathLength); - // Corner case: when servlet path & request path match exactly (without trailing '/'), - // then pathinfo is null. - if (pathInfo.isEmpty() && servletPathLength > 0) { - pathInfo = null; - } else { - try { - pathInfo = new URI(pathInfo).getPath(); - } catch (URISyntaxException e) { - // ugh, just leave it alone then + HttpServletRequest request = + new HttpServletRequestWrapper((HttpServletRequest) servletRequest) { + private boolean pathComputed; + private String path; + + private boolean pathInfoComputed; + private String pathInfo; + + @Override + public String getPathInfo() { + if (!isPathInfoComputed()) { + String servletPath = getServletPath(); + int servletPathLength = servletPath.length(); + String requestUri = getRequestURI(); + pathInfo = requestUri.substring(getContextPath().length()).replaceAll("[/]{2,}", "/"); + // See: https://github.com/google/guice/issues/372 + if (pathInfo.startsWith(servletPath)) { + pathInfo = pathInfo.substring(servletPathLength); + // Corner case: when servlet path & request path match exactly (without trailing '/'), + // then pathinfo is null. + if (pathInfo.isEmpty() && servletPathLength > 0) { + pathInfo = null; + } else { + try { + pathInfo = new URI(pathInfo).getPath(); + } catch (URISyntaxException e) { + // ugh, just leave it alone then + } + } + } else { + pathInfo = null; // we know nothing additional about the URI. } + pathInfoComputed = true; } - } else { - pathInfo = null; // we know nothing additional about the URI. + + return pathInfo; } - pathInfoComputed = true; - } - return pathInfo; - } + // NOTE(dhanji): These two are a bit of a hack to help ensure that request dispatcher-sent + // requests don't use the same path info that was memoized for the original request. + // NOTE(iqshum): I don't think this is possible, since the dispatcher-sent request would + // perform its own wrapping. + private boolean isPathInfoComputed() { + return pathInfoComputed + && servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST) == null; + } - // NOTE(dhanji): These two are a bit of a hack to help ensure that request dispatcher-sent - // requests don't use the same path info that was memoized for the original request. - // NOTE(iqshum): I don't think this is possible, since the dispatcher-sent request would - // perform its own wrapping. - private boolean isPathInfoComputed() { - return pathInfoComputed && servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST) == null; - } + private boolean isPathComputed() { + return pathComputed && servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST) == null; + } - private boolean isPathComputed() { - return pathComputed && servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST) == null; - } + @Override + public String getServletPath() { + return computePath(); + } - @Override - public String getServletPath() { - return computePath(); - } + @Override + public String getPathTranslated() { + final String info = getPathInfo(); - @Override - public String getPathTranslated() { - final String info = getPathInfo(); + return (null == info) ? null : getRealPath(info); + } - return (null == info) ? null : getRealPath(info); - } + // Memoizer pattern. + private String computePath() { + if (!isPathComputed()) { + String servletPath = super.getServletPath(); + path = patternMatcher.extractPath(servletPath); + pathComputed = true; - // Memoizer pattern. - private String computePath() { - if (!isPathComputed()) { - String servletPath = super.getServletPath(); - path = patternMatcher.extractPath(servletPath); - pathComputed = true; + if (null == path) { + path = servletPath; + } + } - if (null == path) { - path = servletPath; + return path; } - } - - return path; - } - }; + }; doServiceImpl(request, (HttpServletResponse) servletResponse); } @@ -284,8 +287,8 @@ private void doServiceImpl(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { GuiceFilter.Context previous = GuiceFilter.localContext.get(); - HttpServletRequest originalRequest - = (previous != null) ? previous.getOriginalRequest() : request; + HttpServletRequest originalRequest = + (previous != null) ? previous.getOriginalRequest() : request; GuiceFilter.localContext.set(new GuiceFilter.Context(originalRequest, request, response)); try { HttpServlet reference = httpServlet.get(); @@ -305,13 +308,9 @@ return servletKey.toString(); } - String getPattern() { - return pattern; - } - public String toPaddedString(int padding) { HttpServlet reference = httpServlet.get(); - return Strings.padEnd(pattern, padding, ' ') + ' ' + return Strings.padEnd(patternMatcher.getOriginalPattern(), padding, ' ') + ' ' + (reference != null ? reference : servletKey); } } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ /** * A binding created by {@link ServletModule}. - * + * * @author sameb@google.com (Sam Berlin) * @since 3.0 */ @@ -34,7 +34,7 @@ /** Returns any context params supplied when creating the binding. */ Map getInitParams(); - + /** Returns true if the given URI will match this binding. */ boolean matchesUri(String uri); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletModule.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletModule.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,20 +21,17 @@ import com.google.common.collect.ImmutableList; import com.google.inject.AbstractModule; import com.google.inject.Key; - import java.util.Map; - import javax.servlet.Filter; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; /** - * Configures the servlet scopes and creates bindings for the servlet API - * objects so you can inject the request, response, session, etc. + * Configures the servlet scopes and creates bindings for the servlet API objects so you can inject + * the request, response, session, etc. * - *

    - * You should subclass this module to register servlets and - * filters in the {@link #configureServlets()} method. + *

    You should subclass this module to register servlets and filters in the {@link + * #configureServlets()} method. * * @author crazybob@google.com (Bob Lee) * @author dhanji@gmail.com (Dhanji R. Prasanna) @@ -50,7 +47,7 @@ try { // Install common bindings (skipped if already installed). install(new InternalServletModule()); - + // Install local filter and servlet bindings. configureServlets(); } finally { @@ -60,12 +57,14 @@ } /** + * + * *

    Servlet Mapping EDSL

    * - *

    Part of the EDSL builder language for configuring servlets - * and filters with guice-servlet. Think of this as an in-code replacement for web.xml. - * Filters and servlets are configured here using simple java method calls. Here is a typical - * example of registering a filter when creating your Guice injector: + *

    Part of the EDSL builder language for configuring servlets and filters with guice-servlet. + * Think of this as an in-code replacement for web.xml. Filters and servlets are configured here + * using simple java method calls. Here is a typical example of registering a filter when creating + * your Guice injector: * *

        *   Guice.createInjector(..., new ServletModule() {
    @@ -86,13 +85,15 @@
        * 
    * * Every servlet (or filter) is required to be a singleton. If you cannot annotate the class - * directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in - * your module. Mapping a servlet that is bound under any other scope is an error. + * directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in your + * module. Mapping a servlet that is bound under any other scope is an error. * *

    + * *

    Dispatch Order

    - * You are free to register as many servlets and filters as you like this way. They will - * be compared and dispatched in the order in which the filter methods are called: + * + * You are free to register as many servlets and filters as you like this way. They will be + * compared and dispatched in the order in which the filter methods are called: * *
        *
    @@ -112,51 +113,56 @@
        *      }
        *    }
        * 
    - * This will traverse down the list of rules in lexical order. For example, a url - * "{@code /my/file.js}" (after it runs through the matching filters) will first - * be compared against the servlet mapping: - * + * + * This will traverse down the list of rules in lexical order. For example, a url "{@code + * /my/file.js}" (after it runs through the matching filters) will first be compared against the + * servlet mapping: + * *
        *       serve("*.html").with(MyServlet.class);
        * 
    + * * And failing that, it will descend to the next servlet mapping: * *
        *       serve("/my/*").with(MyServlet.class);
        * 
    * - * Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These - * two mapping rules can also be written in more compact form using varargs syntax: + * Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These two mapping + * rules can also be written in more compact form using varargs syntax: * *
        *       serve("*.html", "/my/*").with(MyServlet.class);
        * 
    - * - * This way you can map several URI patterns to the same servlet. A similar syntax is - * also available for filter mappings. + * + * This way you can map several URI patterns to the same servlet. A similar syntax is also + * available for filter mappings. * *

    + * *

    Regular Expressions

    + * * You can also map servlets (or filters) to URIs using regular expressions: + * *
        *    serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)
        * 
    * * This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as: + * *
      - *
    • http://www.google.com/ajax.html
    • - *
    • http://www.google.com/content/ajax/index
    • - *
    • http://www.google.com/it/is_totally_ajaxian
    • + *
    • http://www.google.com/ajax.html + *
    • http://www.google.com/content/ajax/index + *
    • http://www.google.com/it/is_totally_ajaxian *
    * - * *

    Initialization Parameters

    * - * Servlets (and filters) allow you to pass in init params - * using the {@code } tag in web.xml. You can similarly pass in parameters to - * Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter - * name/value pairs. For example, to initialize {@code MyServlet} with two parameters - * ({@code name="Dhanji", site="google.com"}) you could write: + * Servlets (and filters) allow you to pass in init params using the {@code } tag in + * web.xml. You can similarly pass in parameters to Servlets and filters registered in + * Guice-servlet using a {@link java.util.Map} of parameter name/value pairs. For example, to + * initialize {@code MyServlet} with two parameters ({@code name="Dhanji", site="google.com"}) you + * could write: * *
        *  Map<String, String> params = new HashMap<String, String>();
    @@ -168,11 +174,11 @@
        * 
    * *

    + * *

    Binding Keys

    * - * You can also bind keys rather than classes. This lets you hide - * implementations with package-local visbility and expose them using - * only a Guice module and an annotation: + * You can also bind keys rather than classes. This lets you hide implementations with + * package-local visbility and expose them using only a Guice module and an annotation: * *
        *  ...
    @@ -180,8 +186,8 @@
        * 
    * * Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a - * custom binding annotation. Elsewhere (in one of your own modules) you can bind this - * filter's implementation: + * custom binding annotation. Elsewhere (in one of your own modules) you can bind this filter's + * implementation: * *
        *   bind(Filter.class).annotatedWith(Fave.class).to(MyFilterImpl.class);
    @@ -190,32 +196,33 @@
        * See {@link com.google.inject.Binder} for more information on binding syntax.
        *
        * 

    + * *

    Multiple Modules

    * - * It is sometimes useful to capture servlet and filter mappings from multiple different - * modules. This is essential if you want to package and offer drop-in Guice plugins that - * provide servlet functionality. + * It is sometimes useful to capture servlet and filter mappings from multiple different modules. + * This is essential if you want to package and offer drop-in Guice plugins that provide servlet + * functionality. + * + *

    Guice Servlet allows you to register several instances of {@code ServletModule} to your + * injector. The order in which these modules are installed determines the dispatch order of + * filters and the precedence order of servlets. For example, if you had two servlet modules, + * {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped to + * the same URI pattern, {@code "/*"}: * - *

    - * Guice Servlet allows you to register several instances of {@code ServletModule} to your - * injector. The order in which these modules are installed determines the dispatch order - * of filters and the precedence order of servlets. For example, if you had two servlet modules, - * {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped - * to the same URI pattern, {@code "/*"}: + *

    In {@code RpcModule}: * - *

    - * In {@code RpcModule}: *

        *     filter("/*").through(RpcFilter.class);
        * 
    * * In {@code WebServiceModule}: + * *
        *     filter("/*").through(WebServiceFilter.class);
        * 
    * - * Then the order in which these filters are dispatched is determined by the order in which - * the modules are installed: + * Then the order in which these filters are dispatched is determined by the order in which the + * modules are installed: * *
        *   install(new WebServiceModule());
    @@ -223,25 +230,23 @@
        * 
    * * In the case shown above {@code WebServiceFilter} will run first. - * + * * @since 2.0 */ - protected void configureServlets() { - } - + protected void configureServlets() {} private FiltersModuleBuilder filtersModuleBuilder; private ServletsModuleBuilder servletsModuleBuilder; private FiltersModuleBuilder getFiltersModuleBuilder() { - checkState(filtersModuleBuilder != null, - "This method can only be used inside configureServlets()"); + checkState( + filtersModuleBuilder != null, "This method can only be used inside configureServlets()"); return filtersModuleBuilder; } private ServletsModuleBuilder getServletModuleBuilder() { - checkState(servletsModuleBuilder != null, - "This method can only be used inside configureServlets()"); + checkState( + servletsModuleBuilder != null, "This method can only be used inside configureServlets()"); return servletsModuleBuilder; } @@ -255,6 +260,14 @@ } /** + * @param urlPatterns Any Servlet-style patterns. examples: /*, /html/*, *.html, etc. + * @since 4.1 + */ + protected final FilterKeyBindingBuilder filter(Iterable urlPatterns) { + return getFiltersModuleBuilder().filter(ImmutableList.copyOf(urlPatterns)); + } + + /** * @param regex Any Java-style regular expression. * @since 2.0 */ @@ -264,6 +277,14 @@ } /** + * @param regexes Any Java-style regular expressions. + * @since 4.1 + */ + protected final FilterKeyBindingBuilder filterRegex(Iterable regexes) { + return getFiltersModuleBuilder().filterRegex(ImmutableList.copyOf(regexes)); + } + + /** * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc. * @since 2.0 */ @@ -273,6 +294,14 @@ } /** + * @param urlPatterns Any Servlet-style patterns. examples: /*, /html/*, *.html, etc. + * @since 4.1 + */ + protected final ServletKeyBindingBuilder serve(Iterable urlPatterns) { + return getServletModuleBuilder().serve(ImmutableList.copyOf(urlPatterns)); + } + + /** * @param regex Any Java-style regular expression. * @since 2.0 */ @@ -282,8 +311,17 @@ } /** - * This method only works if you are using the {@linkplain GuiceServletContextListener} to - * create your injector. Otherwise, it returns null. + * @param regexes Any Java-style regular expressions. + * @since 4.1 + */ + protected final ServletKeyBindingBuilder serveRegex(Iterable regexes) { + return getServletModuleBuilder().serveRegex(ImmutableList.copyOf(regexes)); + } + + /** + * This method only works if you are using the {@linkplain GuiceServletContextListener} to create + * your injector. Otherwise, it returns null. + * * @return The current servlet context. * @since 3.0 */ @@ -298,10 +336,13 @@ */ public static interface FilterKeyBindingBuilder { void through(Class filterKey); + void through(Key filterKey); /** @since 3.0 */ void through(Filter filter); + void through(Class filterKey, Map initParams); + void through(Key filterKey, Map initParams); /** @since 3.0 */ void through(Filter filter, Map initParams); @@ -314,10 +355,13 @@ */ public static interface ServletKeyBindingBuilder { void with(Class servletKey); + void with(Key servletKey); /** @since 3.0 */ void with(HttpServlet servlet); + void with(Class servletKey, Map initParams); + void with(Key servletKey, Map initParams); /** @since 3.0 */ void with(HttpServlet servlet, Map initParams); diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,11 +1,11 @@ -/** +/* * Copyright (C) 2010 Google Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under @@ -17,50 +17,49 @@ import com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder; import com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder; import com.google.inject.spi.BindingTargetVisitor; - import javax.servlet.Filter; import javax.servlet.http.HttpServlet; /** * A visitor for the servlet extension. - * - * If your {@link BindingTargetVisitor} implements this interface, bindings created by using + * + *

    If your {@link BindingTargetVisitor} implements this interface, bindings created by using * {@link ServletModule} will be visited through this interface. - * + * * @since 3.0 * @author sameb@google.com (Sam Berlin) */ public interface ServletModuleTargetVisitor extends BindingTargetVisitor { /** - * Visits a filter binding created by {@link ServletModule#filter}, where - * {@link FilterKeyBindingBuilder#through} is called with a Class or Key. - * - * If multiple patterns were specified, this will be called multiple times. + * Visits a filter binding created by {@link ServletModule#filter}, where {@link + * FilterKeyBindingBuilder#through} is called with a Class or Key. + * + *

    If multiple patterns were specified, this will be called multiple times. */ V visit(LinkedFilterBinding binding); /** - * Visits a filter binding created by {@link ServletModule#filter} where - * {@link FilterKeyBindingBuilder#through} is called with a {@link Filter}. - * - * If multiple patterns were specified, this will be called multiple times. + * Visits a filter binding created by {@link ServletModule#filter} where {@link + * FilterKeyBindingBuilder#through} is called with a {@link Filter}. + * + *

    If multiple patterns were specified, this will be called multiple times. */ V visit(InstanceFilterBinding binding); /** - * Visits a servlet binding created by {@link ServletModule#serve} where - * {@link ServletKeyBindingBuilder#with}, is called with a Class or Key. - * - * If multiple patterns were specified, this will be called multiple times. + * Visits a servlet binding created by {@link ServletModule#serve} where {@link + * ServletKeyBindingBuilder#with}, is called with a Class or Key. + * + *

    If multiple patterns were specified, this will be called multiple times. */ V visit(LinkedServletBinding binding); /** - * Visits a servlet binding created by {@link ServletModule#serve} where - * {@link ServletKeyBindingBuilder#with}, is called with an {@link HttpServlet}. - * - * If multiple patterns were specified, this will be called multiple times. + * Visits a servlet binding created by {@link ServletModule#serve} where {@link + * ServletKeyBindingBuilder#with}, is called with an {@link HttpServlet}. + * + *

    If multiple patterns were specified, this will be called multiple times. */ V visit(InstanceServletBinding binding); -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,10 +27,10 @@ import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Scopes; - import java.util.Map; import java.util.concurrent.Callable; - +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -45,29 +45,33 @@ private ServletScopes() {} /** - * A threadlocal scope map for non-http request scopes. The {@link #REQUEST} - * scope falls back to this scope map if no http request is available, and - * requires {@link #scopeRequest} to be called as an alternative. + * A threadlocal scope map for non-http request scopes. The {@link #REQUEST} scope falls back to + * this scope map if no http request is available, and requires {@link #scopeRequest} to be called + * as an alternative. */ - private static final ThreadLocal requestScopeContext - = new ThreadLocal(); + private static final ThreadLocal requestScopeContext = new ThreadLocal<>(); /** A sentinel attribute value representing null. */ - enum NullObject { INSTANCE } + enum NullObject { + INSTANCE + } - /** - * HTTP servlet request scope. - */ - public static final Scope REQUEST = new Scope() { + /** HTTP servlet request scope. */ + public static final Scope REQUEST = new RequestScope(); + + private static final class RequestScope implements Scope { + @Override public Provider scope(final Key key, final Provider creator) { return new Provider() { /** Keys bound in request-scope which are handled directly by GuiceFilter. */ - private final ImmutableSet> REQUEST_CONTEXT_KEYS = ImmutableSet.of( + private final ImmutableSet> REQUEST_CONTEXT_KEYS = + ImmutableSet.of( Key.get(HttpServletRequest.class), Key.get(HttpServletResponse.class), new Key>(RequestParameters.class) {}); + @Override public T get() { // Check if the alternate request scope should be used, if no HTTP // request is in progress. @@ -96,7 +100,7 @@ return t; } // else: fall into normal HTTP request scope and out of scope - // exception is thrown. + // exception is thrown. } // Always synchronize and get/set attributes on the underlying request @@ -139,15 +143,17 @@ public String toString() { return "ServletScopes.REQUEST"; } - }; + } - /** - * HTTP session scope. - */ - public static final Scope SESSION = new Scope() { + /** HTTP session scope. */ + public static final Scope SESSION = new SessionScope(); + + private static final class SessionScope implements Scope { + @Override public Provider scope(final Key key, final Provider creator) { final String name = key.toString(); return new Provider() { + @Override public T get() { HttpSession session = GuiceFilter.getRequest(key).getSession(); synchronized (session) { @@ -166,6 +172,7 @@ return t; } } + @Override public String toString() { return String.format("%s[%s]", creator, SESSION); @@ -177,122 +184,135 @@ public String toString() { return "ServletScopes.SESSION"; } - }; + } /** - * Wraps the given callable in a contextual callable that "continues" the - * HTTP request in another thread. This acts as a way of transporting - * request context data from the request processing thread to to worker - * threads. - *

    - * There are some limitations: + * Wraps the given callable in a contextual callable that "continues" the HTTP request in another + * thread. This acts as a way of transporting request context data from the request processing + * thread to to worker threads. + * + *

    There are some limitations: + * *

      - *
    • Derived objects (i.e. anything marked @RequestScoped will not be - * transported.
    • - *
    • State changes to the HttpServletRequest after this method is called - * will not be seen in the continued thread.
    • - *
    • Only the HttpServletRequest, ServletContext and request parameter - * map are available in the continued thread. The response and session - * are not available.
    • + *
    • Derived objects (i.e. anything marked @RequestScoped will not be transported. + *
    • State changes to the HttpServletRequest after this method is called will not be seen in the + * continued thread. + *
    • Only the HttpServletRequest, ServletContext and request parameter map are available in the + * continued thread. The response and session are not available. *
    * - *

    The returned callable will throw a {@link ScopingException} when called - * if the HTTP request scope is still active on the current thread. + *

    The returned callable will throw a {@link ScopingException} when called if the HTTP request + * scope is still active on the current thread. * - * @param callable code to be executed in another thread, which depends on - * the request scope. - * @param seedMap the initial set of scoped instances for Guice to seed the - * request scope with. To seed a key with null, use {@code null} as - * the value. - * @return a callable that will invoke the given callable, making the request - * context available to it. - * @throws OutOfScopeException if this method is called from a non-request - * thread, or if the request has completed. - * + * @param callable code to be executed in another thread, which depends on the request scope. + * @param seedMap the initial set of scoped instances for Guice to seed the request scope with. To + * seed a key with null, use {@code null} as the value. + * @return a callable that will invoke the given callable, making the request context available to + * it. + * @throws OutOfScopeException if this method is called from a non-request thread, or if the + * request has completed. * @since 3.0 + * @deprecated You probably want to use {@code transferRequest} instead */ - public static Callable continueRequest(final Callable callable, - final Map, Object> seedMap) { - Preconditions.checkArgument(null != seedMap, - "Seed map cannot be null, try passing in Collections.emptyMap() instead."); + @Deprecated + public static Callable continueRequest(Callable callable, Map, Object> seedMap) { + return wrap(callable, continueRequest(seedMap)); + } + + private static RequestScoper continueRequest(Map, Object> seedMap) { + Preconditions.checkArgument( + null != seedMap, "Seed map cannot be null, try passing in Collections.emptyMap() instead."); // Snapshot the seed map and add all the instances to our continuing HTTP request. final ContinuingHttpServletRequest continuingRequest = - new ContinuingHttpServletRequest( - GuiceFilter.getRequest(Key.get(HttpServletRequest.class))); + new ContinuingHttpServletRequest(GuiceFilter.getRequest(Key.get(HttpServletRequest.class))); for (Map.Entry, Object> entry : seedMap.entrySet()) { Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue()); continuingRequest.setAttribute(entry.getKey().toString(), value); } - return new Callable() { - public T call() throws Exception { - checkScopingState(null == GuiceFilter.localContext.get(), + return new RequestScoper() { + @Override + public CloseableScope open() { + checkScopingState( + null == GuiceFilter.localContext.get(), "Cannot continue request in the same thread as a HTTP request!"); - return new GuiceFilter.Context(continuingRequest, continuingRequest, null) - .call(callable); + return new GuiceFilter.Context(continuingRequest, continuingRequest, null).open(); } }; } /** - * Wraps the given callable in a contextual callable that "transfers" the - * request to another thread. This acts as a way of transporting - * request context data from the current thread to a future thread. - * - *

    As opposed to {@link #continueRequest}, this method propagates all - * existing scoped objects. The primary use case is in server implementations - * where you can detach the request processing thread while waiting for data, - * and reattach to a different thread to finish processing at a later time. - * - *

    Because request-scoped objects are not typically thread-safe, the - * callable returned by this method must not be run on a different thread - * until the current request scope has terminated. The returned callable will - * block until the current thread has released the request scope. - * - * @param callable code to be executed in another thread, which depends on - * the request scope. - * @return a callable that will invoke the given callable, making the request - * context available to it. - * @throws OutOfScopeException if this method is called from a non-request - * thread, or if the request has completed. + * Wraps the given callable in a contextual callable that "transfers" the request to another + * thread. This acts as a way of transporting request context data from the current thread to a + * future thread. + * + *

    As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. + * The primary use case is in server implementations where you can detach the request processing + * thread while waiting for data, and reattach to a different thread to finish processing at a + * later time. + * + *

    Because request-scoped objects are not typically thread-safe, the callable returned by this + * method must not be run on a different thread until the current request scope has terminated. + * The returned callable will block until the current thread has released the request scope. + * + * @param callable code to be executed in another thread, which depends on the request scope. + * @return a callable that will invoke the given callable, making the request context available to + * it. + * @throws OutOfScopeException if this method is called from a non-request thread, or if the + * request has completed. * @since 4.0 */ public static Callable transferRequest(Callable callable) { + return wrap(callable, transferRequest()); + } + + /** + * Returns an object that "transfers" the request to another thread. This acts as a way of + * transporting request context data from the current thread to a future thread. The transferred + * scope is the one active for the thread that calls this method. A later call to {@code open()} + * activates the transferred the scope, including propagating any objects scoped at that time. + * + *

    As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. + * The primary use case is in server implementations where you can detach the request processing + * thread while waiting for data, and reattach to a different thread to finish processing at a + * later time. + * + *

    Because request-scoped objects are not typically thread-safe, it is important to avoid + * applying the same request scope concurrently. The returned Scoper will block on open until the + * current thread has released the request scope. + * + * @return an object that when opened will initiate the request scope + * @throws OutOfScopeException if this method is called from a non-request thread, or if the + * request has completed. + * @since 4.1 + */ + public static RequestScoper transferRequest() { return (GuiceFilter.localContext.get() != null) - ? transferHttpRequest(callable) - : transferNonHttpRequest(callable); + ? transferHttpRequest() + : transferNonHttpRequest(); } - private static Callable transferHttpRequest(final Callable callable) { + private static RequestScoper transferHttpRequest() { final GuiceFilter.Context context = GuiceFilter.localContext.get(); if (context == null) { throw new OutOfScopeException("Not in a request scope"); } - return new Callable() { - public T call() throws Exception { - return context.call(callable); - } - }; + return context; } - private static Callable transferNonHttpRequest(final Callable callable) { + private static RequestScoper transferNonHttpRequest() { final Context context = requestScopeContext.get(); if (context == null) { throw new OutOfScopeException("Not in a request scope"); } - return new Callable() { - public T call() throws Exception { - return context.call(callable); - } - }; + return context; } /** - * Returns true if {@code binding} is request-scoped. If the binding is a - * {@link com.google.inject.spi.LinkedKeyBinding linked key binding} and - * belongs to an injector (i. e. it was retrieved via - * {@link Injector#getBinding Injector.getBinding()}), then this method will + * Returns true if {@code binding} is request-scoped. If the binding is a {@link + * com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (i. e. it + * was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will * also return true if the target binding is request-scoped. * * @since 4.0 @@ -302,53 +322,73 @@ } /** - * Scopes the given callable inside a request scope. This is not the same - * as the HTTP request scope, but is used if no HTTP request scope is in - * progress. In this way, keys can be scoped as @RequestScoped and exist - * in non-HTTP requests (for example: RPC requests) as well as in HTTP + * Scopes the given callable inside a request scope. This is not the same as the HTTP request + * scope, but is used if no HTTP request scope is in progress. In this way, keys can be scoped + * as @RequestScoped and exist in non-HTTP requests (for example: RPC requests) as well as in HTTP * request threads. * - *

    The returned callable will throw a {@link ScopingException} when called - * if there is a request scope already active on the current thread. + *

    The returned callable will throw a {@link ScopingException} when called if there is a + * request scope already active on the current thread. * - * @param callable code to be executed which depends on the request scope. - * Typically in another thread, but not necessarily so. - * @param seedMap the initial set of scoped instances for Guice to seed the - * request scope with. To seed a key with null, use {@code null} as - * the value. - * @return a callable that when called will run inside the a request scope - * that exposes the instances in the {@code seedMap} as scoped keys. + * @param callable code to be executed which depends on the request scope. Typically in another + * thread, but not necessarily so. + * @param seedMap the initial set of scoped instances for Guice to seed the request scope with. To + * seed a key with null, use {@code null} as the value. + * @return a callable that when called will run inside the a request scope that exposes the + * instances in the {@code seedMap} as scoped keys. * @since 3.0 */ - public static Callable scopeRequest(final Callable callable, - Map, Object> seedMap) { - Preconditions.checkArgument(null != seedMap, - "Seed map cannot be null, try passing in Collections.emptyMap() instead."); + public static Callable scopeRequest(Callable callable, Map, Object> seedMap) { + return wrap(callable, scopeRequest(seedMap)); + } + + /** + * Returns an object that will apply request scope to a block of code. This is not the same as the + * HTTP request scope, but is used if no HTTP request scope is in progress. In this way, keys can + * be scoped as @RequestScoped and exist in non-HTTP requests (for example: RPC requests) as well + * as in HTTP request threads. + * + *

    The returned object will throw a {@link ScopingException} when opened if there is a request + * scope already active on the current thread. + * + * @param seedMap the initial set of scoped instances for Guice to seed the request scope with. To + * seed a key with null, use {@code null} as the value. + * @return an object that when opened will initiate the request scope + * @since 4.1 + */ + public static RequestScoper scopeRequest(Map, Object> seedMap) { + Preconditions.checkArgument( + null != seedMap, "Seed map cannot be null, try passing in Collections.emptyMap() instead."); // Copy the seed values into our local scope map. final Context context = new Context(); Map, Object> validatedAndCanonicalizedMap = - Maps.transformEntries(seedMap, new EntryTransformer, Object, Object>() { - @Override public Object transformEntry(Key key, Object value) { - return validateAndCanonicalizeValue(key, value); - } - }); + Maps.transformEntries( + seedMap, + new EntryTransformer, Object, Object>() { + @Override + public Object transformEntry(Key key, Object value) { + return validateAndCanonicalizeValue(key, value); + } + }); context.map.putAll(validatedAndCanonicalizedMap); - - return new Callable() { - public T call() throws Exception { - checkScopingState(null == GuiceFilter.localContext.get(), + return new RequestScoper() { + @Override + public CloseableScope open() { + checkScopingState( + null == GuiceFilter.localContext.get(), "An HTTP request is already in progress, cannot scope a new request in this thread."); - checkScopingState(null == requestScopeContext.get(), + checkScopingState( + null == requestScopeContext.get(), "A request scope is already in progress, cannot scope a new request in this thread."); - return context.call(callable); + return context.open(); } }; } /** - * Validates the key and object, ensuring the value matches the key type, and - * canonicalizing null objects to the null sentinel. + * Validates the key and object, ensuring the value matches the key type, and canonicalizing null + * objects to the null sentinel. */ private static Object validateAndCanonicalizeValue(Key key, Object object) { if (object == null || object == NullObject.INSTANCE) { @@ -356,26 +396,38 @@ } if (!key.getTypeLiteral().getRawType().isInstance(object)) { - throw new IllegalArgumentException("Value[" + object + "] of type[" - + object.getClass().getName() + "] is not compatible with key[" + key + "]"); + throw new IllegalArgumentException( + "Value[" + + object + + "] of type[" + + object.getClass().getName() + + "] is not compatible with key[" + + key + + "]"); } return object; } - private static class Context { + private static class Context implements RequestScoper { final Map map = Maps.newHashMap(); // Synchronized to prevent two threads from using the same request // scope concurrently. - synchronized T call(Callable callable) throws Exception { - Context previous = requestScopeContext.get(); + final Lock lock = new ReentrantLock(); + + @Override + public CloseableScope open() { + lock.lock(); + final Context previous = requestScopeContext.get(); requestScopeContext.set(this); - try { - return callable.call(); - } finally { - requestScopeContext.set(previous); - } + return new CloseableScope() { + @Override + public void close() { + requestScopeContext.set(previous); + lock.unlock(); + } + }; } } @@ -384,4 +436,19 @@ throw new ScopingException(msg); } } + + private static final Callable wrap( + final Callable delegate, final RequestScoper requestScoper) { + return new Callable() { + @Override + public T call() throws Exception { + RequestScoper.CloseableScope scope = requestScoper.open(); + try { + return delegate.call(); + } finally { + scope.close(); + } + } + }; + } } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,87 +19,107 @@ import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.internal.UniqueAnnotations; - +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; - import javax.servlet.http.HttpServlet; /** - * Builds the guice module that binds configured servlets, with their - * wrapper ServletDefinitions. Is part of the binding EDSL. Very similar to - * {@link com.google.inject.servlet.FiltersModuleBuilder}. + * Builds the guice module that binds configured servlets, with their wrapper ServletDefinitions. Is + * part of the binding EDSL. Very similar to {@link com.google.inject.servlet.FiltersModuleBuilder}. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ class ServletsModuleBuilder { - + private final Set servletUris = Sets.newHashSet(); private final Binder binder; - + public ServletsModuleBuilder(Binder binder) { this.binder = binder; } //the first level of the EDSL-- public ServletModule.ServletKeyBindingBuilder serve(List urlPatterns) { - return new ServletKeyBindingBuilderImpl(urlPatterns, UriPatternType.SERVLET); + return new ServletKeyBindingBuilderImpl(parsePatterns(UriPatternType.SERVLET, urlPatterns)); } public ServletModule.ServletKeyBindingBuilder serveRegex(List regexes) { - return new ServletKeyBindingBuilderImpl(regexes, UriPatternType.REGEX); + return new ServletKeyBindingBuilderImpl(parsePatterns(UriPatternType.REGEX, regexes)); + } + + private List parsePatterns(UriPatternType type, List patterns) { + List patternMatchers = new ArrayList<>(); + for (String pattern : patterns) { + if (!servletUris.add(pattern)) { + binder + .skipSources(ServletModule.class, ServletsModuleBuilder.class) + .addError("More than one servlet was mapped to the same URI pattern: " + pattern); + } else { + UriPatternMatcher matcher = null; + try { + matcher = UriPatternType.get(type, pattern); + } catch (IllegalArgumentException iae) { + binder + .skipSources(ServletModule.class, ServletsModuleBuilder.class) + .addError("%s", iae.getMessage()); + } + if (matcher != null) { + patternMatchers.add(matcher); + } + } + } + return patternMatchers; } //non-static inner class so it can access state of enclosing module class class ServletKeyBindingBuilderImpl implements ServletModule.ServletKeyBindingBuilder { - private final List uriPatterns; - private final UriPatternType uriPatternType; + private final List uriPatterns; - private ServletKeyBindingBuilderImpl(List uriPatterns, UriPatternType uriPatternType) { + private ServletKeyBindingBuilderImpl(List uriPatterns) { this.uriPatterns = uriPatterns; - this.uriPatternType = uriPatternType; } + @Override public void with(Class servletKey) { with(Key.get(servletKey)); } + @Override public void with(Key servletKey) { with(servletKey, new HashMap()); } + @Override public void with(HttpServlet servlet) { with(servlet, new HashMap()); } - public void with(Class servletKey, - Map initParams) { + @Override + public void with(Class servletKey, Map initParams) { with(Key.get(servletKey), initParams); } - public void with(Key servletKey, - Map initParams) { + @Override + public void with(Key servletKey, Map initParams) { with(servletKey, initParams, null); } - private void with(Key servletKey, Map initParams, + private void with( + Key servletKey, + Map initParams, HttpServlet servletInstance) { - for (String pattern : uriPatterns) { - // Ensure two servlets aren't bound to the same pattern. - if (!servletUris.add(pattern)) { - binder.addError("More than one servlet was mapped to the same URI pattern: " + pattern); - } else { - binder.bind(Key.get(ServletDefinition.class, UniqueAnnotations.create())).toProvider( - new ServletDefinition(pattern, servletKey, UriPatternType - .get(uriPatternType, pattern), initParams, servletInstance)); - } + for (UriPatternMatcher pattern : uriPatterns) { + binder + .bind(Key.get(ServletDefinition.class, UniqueAnnotations.create())) + .toProvider(new ServletDefinition(servletKey, pattern, initParams, servletInstance)); } } - public void with(HttpServlet servlet, - Map initParams) { + @Override + public void with(HttpServlet servlet, Map initParams) { Key servletKey = Key.get(HttpServlet.class, UniqueAnnotations.create()); binder.bind(servletKey).toInstance(servlet); with(servletKey, initParams, servlet); diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,16 @@ package com.google.inject.servlet; +import static com.google.common.base.Charsets.UTF_8; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.net.UrlEscapers; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import javax.servlet.http.HttpServletRequest; /** @@ -24,29 +34,193 @@ * @author ntang@google.com (Michael Tang) */ final class ServletUtils { + private static final Splitter SLASH_SPLITTER = Splitter.on('/'); + private static final Joiner SLASH_JOINER = Joiner.on('/'); + private ServletUtils() { // private to prevent instantiation. } /** - * Gets the context path relative path of the URI. Returns the path of the - * resource relative to the context path for a request's URI, or null if no - * path can be extracted. + * Gets the context path relative path of the URI. Returns the path of the resource relative to + * the context path for a request's URI, or null if no path can be extracted. + * + *

    Also performs url decoding and normalization of the path. */ // @Nullable - public static String getContextRelativePath( + static String getContextRelativePath( // @Nullable final HttpServletRequest request) { if (request != null) { String contextPath = request.getContextPath(); String requestURI = request.getRequestURI(); if (contextPath.length() < requestURI.length()) { - return requestURI.substring(contextPath.length()); - } else if (requestURI != null && requestURI.trim().length() > 0 && - contextPath.length() == requestURI.length()) { + String suffix = requestURI.substring(contextPath.length()); + return normalizePath(suffix); + } else if (requestURI.trim().length() > 0 && contextPath.length() == requestURI.length()) { return "/"; } } return null; } + + /** Normalizes a path by unescaping all safe, percent encoded characters. */ + static String normalizePath(String path) { + StringBuilder sb = new StringBuilder(path.length()); + int queryStart = path.indexOf('?'); + String query = null; + if (queryStart != -1) { + query = path.substring(queryStart); + path = path.substring(0, queryStart); + } + // Normalize the path. we need to decode path segments, normalize and rejoin in order to + // 1. decode and normalize safe percent escaped characters. e.g. %70 -> 'p' + // 2. decode and interpret dangerous character sequences. e.g. /%2E/ -> '/./' -> '/' + // 3. preserve dangerous encoded characters. e.g. '/%2F/' -> '///' -> '/%2F' + List segments = new ArrayList<>(); + for (String segment : SLASH_SPLITTER.split(path)) { + // This decodes all non-special characters from the path segment. so if someone passes + // /%2E/foo we will normalize it to /./foo and then /foo + String normalized = + UrlEscapers.urlPathSegmentEscaper().escape(lenientDecode(segment, UTF_8, false)); + if (".".equals(normalized)) { + // skip + } else if ("..".equals(normalized)) { + if (segments.size() > 1) { + segments.remove(segments.size() - 1); + } + } else { + segments.add(normalized); + } + } + SLASH_JOINER.appendTo(sb, segments); + if (query != null) { + sb.append(query); + } + return sb.toString(); + } + + + /** + * Percent-decodes a US-ASCII string into a Unicode string. The specified encoding is used to + * determine what characters are represented by any consecutive sequences of the form + * "%XX". This is the lenient kind of decoding that will simply ignore and copy as-is any + * "%XX" sequence that is invalid (for example, "%HH"). + * + * @param string a percent-encoded US-ASCII string + * @param encoding a character encoding + * @param decodePlus boolean to indicate whether to decode '+' as ' ' + * @return a Unicode string + */ + private static String lenientDecode(String string, Charset encoding, boolean decodePlus) { + + checkNotNull(string); + checkNotNull(encoding); + + if (decodePlus) { + string = string.replace('+', ' '); + } + + int firstPercentPos = string.indexOf('%'); + + if (firstPercentPos < 0) { + return string; + } + + ByteAccumulator accumulator = new ByteAccumulator(string.length(), encoding); + StringBuilder builder = new StringBuilder(string.length()); + + if (firstPercentPos > 0) { + builder.append(string, 0, firstPercentPos); + } + + for (int srcPos = firstPercentPos; srcPos < string.length(); srcPos++) { + + char c = string.charAt(srcPos); + + if (c < 0x80) { // ASCII + boolean processed = false; + + if (c == '%' && string.length() >= srcPos + 3) { + String hex = string.substring(srcPos + 1, srcPos + 3); + + try { + int encoded = Integer.parseInt(hex, 16); + + if (encoded >= 0) { + accumulator.append((byte) encoded); + srcPos += 2; + processed = true; + } + } catch (NumberFormatException ignore) { + // Expected case (badly formatted % group) + } + } + + if (!processed) { + if (accumulator.isEmpty()) { + // We're not accumulating elements of a multibyte encoded + // char, so just toss it right into the result string. + + builder.append(c); + } else { + accumulator.append((byte) c); + } + } + } else { // Non-ASCII + // A non-ASCII char marks the end of a multi-char encoding sequence, + // if one is in progress. + + accumulator.dumpTo(builder); + builder.append(c); + } + } + + accumulator.dumpTo(builder); + + return builder.toString(); + } + + /** Accumulates byte sequences while decoding strings, and encodes them into a StringBuilder. */ + private static class ByteAccumulator { + private byte[] bytes; + private int length; + private final Charset encoding; + + ByteAccumulator(int capacity, Charset encoding) { + this.bytes = new byte[Math.min(16, capacity)]; + this.encoding = encoding; + } + + void append(byte b) { + ensureCapacity(length + 1); + bytes[length++] = b; + } + + void dumpTo(StringBuilder dest) { + if (length != 0) { + dest.append(new String(bytes, 0, length, encoding)); + length = 0; + } + } + + boolean isEmpty() { + return length == 0; + } + + private void ensureCapacity(int minCapacity) { + int cap = bytes.length; + if (cap >= minCapacity) { + return; + } + int newCapacity = cap + (cap >> 1); // *1.5 + if (newCapacity < minCapacity) { + // we are close to overflowing, grow by smaller steps + newCapacity = minCapacity; + } + // in other cases, we will naturally throw an OOM from here + bytes = Arrays.copyOf(bytes, newCapacity); + } + } + } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.servlet; import com.google.inject.ScopeAnnotation; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -29,7 +28,7 @@ * @see com.google.inject.Scopes#SINGLETON * @author crazybob@google.com (Bob Lee) */ -@Target({ ElementType.TYPE, ElementType.METHOD }) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @ScopeAnnotation public @interface SessionScoped {} diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,7 @@ */ public interface UriPatternMatcher { /** - * @param uri A "contextual" (i.e. relative) Request URI, *not* a complete one. + * @param uri A "contextual" (i.e. relative) and "normalized" Request URI, *not* a complete one. * @return Returns true if the uri matches the pattern. */ boolean matches(String uri); @@ -32,13 +32,15 @@ /** * @param pattern The Path that this service pattern can match against. * @return Returns a canonical servlet path from this pattern. For instance, if the pattern is - * {@code /home/*} then the path extracted will be {@code /home}. Each pattern matcher - * implementation must decide and publish what a canonical path represents. - * - * NOTE(dhanji): This method returns null for the regex pattern matcher. + * {@code /home/*} then the path extracted will be {@code /home}. Each pattern matcher + * implementation must decide and publish what a canonical path represents. + *

    NOTE(dhanji): This method returns null for the regex pattern matcher. */ String extractPath(String pattern); - + /** Returns the type of pattern this is. */ UriPatternType getPatternType(); + + /** Returns the original pattern that was registered. */ + String getOriginalPattern(); } diff -Nru sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java --- sisu-guice-3.2.6/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,14 +17,16 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; /** * An enumeration of the available URI-pattern matching styles - * + * * @since 3.0 */ public enum UriPatternType { - SERVLET, REGEX; + SERVLET, + REGEX; /** * Returns the appropriate {@link UriPatternMatcher} for {@code pattern}. @@ -59,24 +61,45 @@ * @author dhanji@gmail.com (Dhanji R. Prasanna) */ private static class ServletStyleUriPatternMatcher implements UriPatternMatcher { - private final String pattern; + private final String literal; + private final String originalPattern; private final Kind patternKind; - private static enum Kind { PREFIX, SUFFIX, LITERAL, } + private static enum Kind { + PREFIX, + SUFFIX, + LITERAL, + } public ServletStyleUriPatternMatcher(String pattern) { + this.originalPattern = pattern; if (pattern.startsWith("*")) { - this.pattern = pattern.substring(1); + this.literal = pattern.substring(1); this.patternKind = Kind.PREFIX; } else if (pattern.endsWith("*")) { - this.pattern = pattern.substring(0, pattern.length() - 1); + this.literal = pattern.substring(0, pattern.length() - 1); this.patternKind = Kind.SUFFIX; } else { - this.pattern = pattern; + this.literal = pattern; this.patternKind = Kind.LITERAL; } + String normalized = ServletUtils.normalizePath(literal); + if (patternKind == Kind.PREFIX) { + normalized = "*" + normalized; + } else if (patternKind == Kind.SUFFIX) { + normalized = normalized + "*"; + } + if (!pattern.equals(normalized)) { + throw new IllegalArgumentException( + "Servlet patterns cannot contain escape patterns. Registered pattern: '" + + pattern + + "' normalizes to: '" + + normalized + + "'"); + } } + @Override public boolean matches(String uri) { if (null == uri) { return false; @@ -84,20 +107,21 @@ uri = getUri(uri); if (patternKind == Kind.PREFIX) { - return uri.endsWith(pattern); + return uri.endsWith(literal); } else if (patternKind == Kind.SUFFIX) { - return uri.startsWith(pattern); + return uri.startsWith(literal); } - //else treat as a literal - return pattern.equals(uri); + //else we need a complete match + return literal.equals(uri); } + @Override public String extractPath(String path) { if (patternKind == Kind.PREFIX) { return null; } else if (patternKind == Kind.SUFFIX) { - String extract = pattern; + String extract = literal; //trim the trailing '/' if (extract.endsWith("/")) { @@ -110,10 +134,16 @@ //else treat as literal return path; } - + + @Override public UriPatternType getPatternType() { return UriPatternType.SERVLET; } + + @Override + public String getOriginalPattern() { + return originalPattern; + } } /** @@ -123,15 +153,23 @@ */ private static class RegexUriPatternMatcher implements UriPatternMatcher { private final Pattern pattern; + private final String originalPattern; public RegexUriPatternMatcher(String pattern) { - this.pattern = Pattern.compile(pattern); + this.originalPattern = pattern; + try { + this.pattern = Pattern.compile(pattern); + } catch (PatternSyntaxException pse) { + throw new IllegalArgumentException("Invalid regex pattern: " + pse.getMessage()); + } } + @Override public boolean matches(String uri) { return null != uri && this.pattern.matcher(getUri(uri)).matches(); } + @Override public String extractPath(String path) { Matcher matcher = pattern.matcher(path); if (matcher.matches() && matcher.groupCount() >= 1) { @@ -147,9 +185,15 @@ } return null; } - + + @Override public UriPatternType getPatternType() { return UriPatternType.REGEX; } + + @Override + public String getOriginalPattern() { + return originalPattern; + } } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/AllTests.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/AllTests.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/AllTests.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/AllTests.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,9 +19,7 @@ import junit.framework.Test; import junit.framework.TestSuite; -/** - * @author dhanji@gmail.com (Dhanji R. Prasanna) - */ +/** @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class AllTests { public static Test suite() { diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,13 +26,7 @@ import com.google.inject.Scopes; import com.google.inject.name.Named; import com.google.inject.name.Names; - -import junit.framework.TestCase; - -import org.easymock.IMocksControl; - import java.io.IOException; - import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; @@ -42,14 +36,18 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; +import org.easymock.IMocksControl; /** Tests to make sure that servlets with a context path are handled right. */ public class ContextPathTest extends TestCase { - @Inject @Named("foo") + @Inject + @Named("foo") private TestServlet fooServlet; - @Inject @Named("bar") + @Inject + @Named("bar") private TestServlet barServlet; private IMocksControl globalControl; @@ -60,18 +58,24 @@ @Override public final void setUp() throws Exception { - injector = Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - bind(TestServlet.class).annotatedWith(Names.named("foo")) - .to(TestServlet.class).in(Scopes.SINGLETON); - bind(TestServlet.class).annotatedWith(Names.named("bar")) - .to(TestServlet.class).in(Scopes.SINGLETON); - serve("/foo/*").with(Key.get(TestServlet.class, Names.named("foo"))); - serve("/bar/*").with(Key.get(TestServlet.class, Names.named("bar"))); - // TODO: add a filter(..) call and validate it is correct - } - }); + injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + bind(TestServlet.class) + .annotatedWith(Names.named("foo")) + .to(TestServlet.class) + .in(Scopes.SINGLETON); + bind(TestServlet.class) + .annotatedWith(Names.named("bar")) + .to(TestServlet.class) + .in(Scopes.SINGLETON); + serve("/foo/*").with(Key.get(TestServlet.class, Names.named("foo"))); + serve("/bar/*").with(Key.get(TestServlet.class, Names.named("bar"))); + // TODO: add a filter(..) call and validate it is correct + } + }); injector.injectMembers(this); assertNotNull(fooServlet); @@ -83,7 +87,8 @@ filterConfig = globalControl.createMock(FilterConfig.class); expect(servletContext.getAttribute(GuiceServletContextListener.INJECTOR_NAME)) - .andReturn(injector).anyTimes(); + .andReturn(injector) + .anyTimes(); expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes(); globalControl.replay(); @@ -229,8 +234,13 @@ runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false); } - private void runTest(final String requestURI, final String servletPath, final String contextPath, - final boolean filterResult, final boolean fooResult, final boolean barResult) + private void runTest( + final String requestURI, + final String servletPath, + final String contextPath, + final boolean filterResult, + final boolean fooResult, + final boolean barResult) throws Exception { IMocksControl testControl = createControl(); @@ -277,8 +287,9 @@ public static class TestFilterChain implements FilterChain { private boolean triggered = false; - public void doFilter(ServletRequest request, ServletResponse response) throws IOException, - ServletException { + @Override + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { triggered = true; } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,16 +15,15 @@ */ package com.google.inject.servlet; -import junit.framework.AssertionFailedError; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; -import junit.framework.TestCase; - import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; public class ContinuingHttpServletRequestTest extends TestCase { @@ -42,19 +41,16 @@ verify(delegate); } - + public void testReturnDelegateCookies() { - Cookie[] cookies = new Cookie[]{ - new Cookie("testName1", TEST_VALUE_1), - new Cookie("testName2", "testValue2") - }; + Cookie[] cookies = + new Cookie[] {new Cookie("testName1", TEST_VALUE_1), new Cookie("testName2", "testValue2")}; HttpServletRequest delegate = createMock(HttpServletRequest.class); expect(delegate.getCookies()).andStubReturn(cookies); replay(delegate); - ContinuingHttpServletRequest continuingRequest = new ContinuingHttpServletRequest( - delegate); + ContinuingHttpServletRequest continuingRequest = new ContinuingHttpServletRequest(delegate); assertCookieArraysEqual(cookies, continuingRequest.getCookies()); @@ -65,7 +61,7 @@ try { assertCookieArraysEqual(cookies, continuingRequest.getCookies()); - fail(); + throw new Error(); } catch (AssertionFailedError e) { // Expected. } @@ -76,8 +72,8 @@ assertEquals(DEFAULT_MAX_AGE, continuingRequest.getCookies()[1].getMaxAge()); // Perform a snapshot of the snapshot. - ContinuingHttpServletRequest furtherContinuingRequest = new ContinuingHttpServletRequest( - continuingRequest); + ContinuingHttpServletRequest furtherContinuingRequest = + new ContinuingHttpServletRequest(continuingRequest); // The cookies should be fixed. assertCookieArraysEqual(continuingRequest.getCookies(), furtherContinuingRequest.getCookies()); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ package com.google.inject.servlet; -import javax.servlet.http.Cookie; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; @@ -30,9 +29,6 @@ import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.List; import java.util.concurrent.AbstractExecutorService; @@ -42,66 +38,73 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; - import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; -/** - * Tests continuation of requests - */ +/** Tests continuation of requests */ public class ContinuingRequestIntegrationTest extends TestCase { private static final String PARAM_VALUE = "there"; private static final String PARAM_NAME = "hi"; private final AtomicBoolean failed = new AtomicBoolean(false); - private final AbstractExecutorService sameThreadExecutor = new AbstractExecutorService() { - public void shutdown() { - } - - public List shutdownNow() { - return ImmutableList.of(); - } - - public boolean isShutdown() { - return true; - } - - public boolean isTerminated() { - return true; - } - - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - return true; - } - - public void execute(Runnable command) { - command.run(); - } - - @Override public Future submit(Callable task) { - try { - task.call(); - fail(); - } catch (Exception e) { - // Expected. - assertTrue(e instanceof IllegalStateException); - failed.set(true); - } - - return null; - } - }; + private final AbstractExecutorService sameThreadExecutor = + new AbstractExecutorService() { + @Override + public void shutdown() {} + + @Override + public List shutdownNow() { + return ImmutableList.of(); + } + + @Override + public boolean isShutdown() { + return true; + } + + @Override + public boolean isTerminated() { + return true; + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return true; + } + + @Override + public void execute(Runnable command) { + command.run(); + } + + @Override + public Future submit(Callable task) { + try { + task.call(); + fail(); + } catch (Exception e) { + // Expected. + assertTrue(e instanceof IllegalStateException); + failed.set(true); + } + + return null; + } + }; private ExecutorService executor; private Injector injector; - @Override protected void tearDown() throws Exception { + @Override + protected void tearDown() throws Exception { injector.getInstance(GuiceFilter.class).destroy(); } @@ -109,13 +112,16 @@ throws ServletException, IOException, InterruptedException { executor = Executors.newSingleThreadExecutor(); - injector = Guice.createInjector(new ServletModule() { - @Override protected void configureServlets() { - serve("/*").with(ContinuingServlet.class); - - bind(ExecutorService.class).toInstance(executor); - } - }); + injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + serve("/*").with(ContinuingServlet.class); + + bind(ExecutorService.class).toInstance(executor); + } + }); FilterConfig filterConfig = createMock(FilterConfig.class); expect(filterConfig.getServletContext()).andReturn(createMock(ServletContext.class)); @@ -125,9 +131,7 @@ HttpServletRequest request = createMock(HttpServletRequest.class); expect(request.getRequestURI()).andReturn("/"); - expect(request.getContextPath()) - .andReturn("") - .anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); expect(request.getMethod()).andReturn("GET"); expect(request.getCookies()).andReturn(new Cookie[0]); @@ -150,15 +154,18 @@ public final void testRequestContinuationDiesInHttpRequestThread() throws ServletException, IOException, InterruptedException { executor = sameThreadExecutor; - injector = Guice.createInjector(new ServletModule() { - @Override protected void configureServlets() { - serve("/*").with(ContinuingServlet.class); - - bind(ExecutorService.class).toInstance(executor); - - bind(SomeObject.class); - } - }); + injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + serve("/*").with(ContinuingServlet.class); + + bind(ExecutorService.class).toInstance(executor); + + bind(SomeObject.class); + } + }); FilterConfig filterConfig = createMock(FilterConfig.class); expect(filterConfig.getServletContext()).andReturn(createMock(ServletContext.class)); @@ -168,9 +175,7 @@ HttpServletRequest request = createMock(HttpServletRequest.class); expect(request.getRequestURI()).andReturn("/"); - expect(request.getContextPath()) - .andReturn("") - .anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); expect(request.getMethod()).andReturn("GET"); expect(request.getCookies()).andReturn(new Cookie[0]); @@ -192,8 +197,7 @@ } @RequestScoped - public static class SomeObject { - } + public static class SomeObject {} @Singleton public static class ContinuingServlet extends HttpServlet { @@ -202,14 +206,16 @@ private SomeObject someObject; - @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { assertNull(someObject); // Seed with someobject. someObject = new SomeObject(); - Callable task = ServletScopes.continueRequest(callable, - ImmutableMap., Object>of(Key.get(SomeObject.class), someObject)); + Callable task = + ServletScopes.continueRequest( + callable, ImmutableMap., Object>of(Key.get(SomeObject.class), someObject)); executorService.submit(task); } @@ -223,6 +229,7 @@ public String value; + @Override public String call() throws Exception { assertNull(response.get()); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package com.google.inject.servlet; import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -33,20 +32,20 @@ public class DummyFilterImpl implements Filter { int num; - public DummyFilterImpl() { - } + public DummyFilterImpl() {} public DummyFilterImpl(int num) { this.num = num; } - public void init(FilterConfig filterConfig) throws ServletException { - } + @Override + public void init(FilterConfig filterConfig) throws ServletException {} - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { - } + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException {} - public void destroy() { - } + @Override + public void destroy() {} } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ package com.google.inject.servlet; import com.google.inject.Singleton; - import javax.servlet.http.HttpServlet; /** @@ -25,6 +24,4 @@ * @author Dhanji R. Prasanna (dhanji@gmail com) */ @Singleton -public class DummyServlet extends HttpServlet { - -} +public class DummyServlet extends HttpServlet {} diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/EdslTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/EdslTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/EdslTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/EdslTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,10 +22,8 @@ import com.google.inject.Module; import com.google.inject.Singleton; import com.google.inject.Stage; - -import junit.framework.TestCase; - import java.util.HashMap; +import junit.framework.TestCase; /** * Sanity checks the EDSL and resultant bound module(s). @@ -35,18 +33,21 @@ public class EdslTest extends TestCase { public final void testExplicitBindingsWorksWithGuiceServlet() { - Injector injector = Guice.createInjector( - new AbstractModule() { - @Override - protected void configure() { - binder().requireExplicitBindings(); - } - }, new ServletModule() { - @Override protected void configureServlets() { - bind(DummyServlet.class).in(Singleton.class); - serve("/*").with(DummyServlet.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + binder().requireExplicitBindings(); + } + }, + new ServletModule() { + @Override + protected void configureServlets() { + bind(DummyServlet.class).in(Singleton.class); + serve("/*").with(DummyServlet.class); + } + }); assertNotNull(injector.getInstance(DummyServlet.class)); } @@ -54,53 +55,49 @@ public final void testConfigureServlets() { //the various possible config calls-- - Module webModule = new ServletModule() { + Module webModule = + new ServletModule() { - @Override - protected void configureServlets() { - filter("/*").through(DummyFilterImpl.class); - filter("*.html").through(DummyFilterImpl.class); - filter("/*").through(Key.get(DummyFilterImpl.class)); - filter("/*").through(new DummyFilterImpl()); - - filter("*.html").through(DummyFilterImpl.class, - new HashMap()); - - filterRegex("/person/[0-9]*").through(DummyFilterImpl.class); - filterRegex("/person/[0-9]*").through(DummyFilterImpl.class, - new HashMap()); - - filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class)); - filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class), - new HashMap()); - - filterRegex("/person/[0-9]*").through(new DummyFilterImpl()); - filterRegex("/person/[0-9]*").through(new DummyFilterImpl(), - new HashMap()); - - - serve("/1/*").with(DummyServlet.class); - serve("/2/*").with(Key.get(DummyServlet.class)); - serve("/3/*").with(new DummyServlet()); - serve("/4/*").with(DummyServlet.class, new HashMap()); - - serve("*.htm").with(Key.get(DummyServlet.class)); - serve("*.html").with(Key.get(DummyServlet.class), - new HashMap()); - - serveRegex("/person/[0-8]*").with(DummyServlet.class); - serveRegex("/person/[0-9]*").with(DummyServlet.class, - new HashMap()); - - serveRegex("/person/[0-6]*").with(Key.get(DummyServlet.class)); - serveRegex("/person/[0-9]/2/*").with(Key.get(DummyServlet.class), - new HashMap()); - - serveRegex("/person/[0-5]*").with(new DummyServlet()); - serveRegex("/person/[0-9]/3/*").with(new DummyServlet(), - new HashMap()); - } - }; + @Override + protected void configureServlets() { + filter("/*").through(DummyFilterImpl.class); + filter("*.html").through(DummyFilterImpl.class); + filter("/*").through(Key.get(DummyFilterImpl.class)); + filter("/*").through(new DummyFilterImpl()); + + filter("*.html").through(DummyFilterImpl.class, new HashMap()); + + filterRegex("/person/[0-9]*").through(DummyFilterImpl.class); + filterRegex("/person/[0-9]*") + .through(DummyFilterImpl.class, new HashMap()); + + filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class)); + filterRegex("/person/[0-9]*") + .through(Key.get(DummyFilterImpl.class), new HashMap()); + + filterRegex("/person/[0-9]*").through(new DummyFilterImpl()); + filterRegex("/person/[0-9]*") + .through(new DummyFilterImpl(), new HashMap()); + + serve("/1/*").with(DummyServlet.class); + serve("/2/*").with(Key.get(DummyServlet.class)); + serve("/3/*").with(new DummyServlet()); + serve("/4/*").with(DummyServlet.class, new HashMap()); + + serve("*.htm").with(Key.get(DummyServlet.class)); + serve("*.html").with(Key.get(DummyServlet.class), new HashMap()); + + serveRegex("/person/[0-8]*").with(DummyServlet.class); + serveRegex("/person/[0-9]*").with(DummyServlet.class, new HashMap()); + + serveRegex("/person/[0-6]*").with(Key.get(DummyServlet.class)); + serveRegex("/person/[0-9]/2/*") + .with(Key.get(DummyServlet.class), new HashMap()); + + serveRegex("/person/[0-5]*").with(new DummyServlet()); + serveRegex("/person/[0-9]/3/*").with(new DummyServlet(), new HashMap()); + } + }; //verify that it doesn't blow up! Guice.createInjector(Stage.TOOL, webModule); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,11 +29,9 @@ import com.google.inject.servlet.ServletSpiVisitor.Params; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; - -import junit.framework.TestCase; - import java.util.Iterator; import java.util.List; +import junit.framework.TestCase; /** * A very basic test that servletmodule works with bindings. @@ -55,9 +53,9 @@ public final void testSpiOnElements() { ServletSpiVisitor visitor = new ServletSpiVisitor(false); int count = 0; - for(Element element : Elements.getElements(new Module())) { - if(element instanceof Binding) { - assertEquals(count++, ((Binding)element).acceptTargetVisitor(visitor)); + for (Element element : Elements.getElements(new Module())) { + if (element instanceof Binding) { + assertEquals(count++, ((Binding) element).acceptTargetVisitor(visitor)); } } validateVisitor(visitor); @@ -67,7 +65,7 @@ ServletSpiVisitor visitor = new ServletSpiVisitor(true); int count = 0; Injector injector = Guice.createInjector(new Module()); - for(Binding binding : injector.getBindings().values()) { + for (Binding binding : injector.getBindings().values()) { assertEquals(count++, binding.acceptTargetVisitor(visitor)); } validateVisitor(visitor); @@ -77,64 +75,168 @@ assertEquals(48, visitor.currentCount - visitor.otherCount); // This is the expected param list, in order.. - List expected = ImmutableList.of( - new Params("/class", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET), - new Params("/class/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET), - new Params("/key", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), SERVLET), - new Params("/key/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), SERVLET), - new Params("/instance", dummyFilter1, ImmutableMap.of(), SERVLET), - new Params("/instance/2", dummyFilter1, ImmutableMap.of(), SERVLET), - new Params("/class/keyvalues", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), SERVLET), - new Params("/class/keyvalues/2", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), SERVLET), - new Params("/key/keyvalues", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), - new Params("/key/keyvalues/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), - new Params("/instance/keyvalues", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET), - new Params("/instance/keyvalues/2", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET), - - new Params("/class[0-9]", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX), - new Params("/class[0-9]/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX), - new Params("/key[0-9]", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), REGEX), - new Params("/key[0-9]/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), REGEX), - new Params("/instance[0-9]", dummyFilter3, ImmutableMap.of(), REGEX), - new Params("/instance[0-9]/2", dummyFilter3, ImmutableMap.of(), REGEX), - new Params("/class[0-9]/keyvalues", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), REGEX), - new Params("/class[0-9]/keyvalues/2", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), REGEX), - new Params("/key[0-9]/keyvalues", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), - new Params("/key[0-9]/keyvalues/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), - new Params("/instance[0-9]/keyvalues", dummyFilter4, ImmutableMap.of("key", "value"), REGEX), - new Params("/instance[0-9]/keyvalues/2", dummyFilter4, ImmutableMap.of("key", "value"), REGEX), - - new Params("/class", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET), - new Params("/class/2", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET), - new Params("/key", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), SERVLET), - new Params("/key/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), SERVLET), - new Params("/instance", dummyServlet1, ImmutableMap.of(), SERVLET), - new Params("/instance/2", dummyServlet1, ImmutableMap.of(), SERVLET), - new Params("/class/keyvalues", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), SERVLET), - new Params("/class/keyvalues/2", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), SERVLET), - new Params("/key/keyvalues", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), - new Params("/key/keyvalues/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), - new Params("/instance/keyvalues", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET), - new Params("/instance/keyvalues/2", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET), - - new Params("/class[0-9]", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX), - new Params("/class[0-9]/2", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX), - new Params("/key[0-9]", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), REGEX), - new Params("/key[0-9]/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), REGEX), - new Params("/instance[0-9]", dummyServlet3, ImmutableMap.of(), REGEX), - new Params("/instance[0-9]/2", dummyServlet3, ImmutableMap.of(), REGEX), - new Params("/class[0-9]/keyvalues", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), REGEX), - new Params("/class[0-9]/keyvalues/2", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), REGEX), - new Params("/key[0-9]/keyvalues", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), - new Params("/key[0-9]/keyvalues/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), - new Params("/instance[0-9]/keyvalues", dummyServlet4, ImmutableMap.of("key", "value"), REGEX), - new Params("/instance[0-9]/keyvalues/2", dummyServlet4, ImmutableMap.of("key", "value"), REGEX) - ); + List expected = + ImmutableList.of( + new Params("/class", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET), + new Params("/class/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET), + new Params( + "/key", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of(), + SERVLET), + new Params( + "/key/2", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of(), + SERVLET), + new Params("/instance", dummyFilter1, ImmutableMap.of(), SERVLET), + new Params("/instance/2", dummyFilter1, ImmutableMap.of(), SERVLET), + new Params( + "/class/keyvalues", + Key.get(DummyFilterImpl.class), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/class/keyvalues/2", + Key.get(DummyFilterImpl.class), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/key/keyvalues", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/key/keyvalues/2", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/instance/keyvalues", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET), + new Params( + "/instance/keyvalues/2", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET), + new Params("/class[0-9]", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX), + new Params("/class[0-9]/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX), + new Params( + "/key[0-9]", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of(), + REGEX), + new Params( + "/key[0-9]/2", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of(), + REGEX), + new Params("/instance[0-9]", dummyFilter3, ImmutableMap.of(), REGEX), + new Params("/instance[0-9]/2", dummyFilter3, ImmutableMap.of(), REGEX), + new Params( + "/class[0-9]/keyvalues", + Key.get(DummyFilterImpl.class), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/class[0-9]/keyvalues/2", + Key.get(DummyFilterImpl.class), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/key[0-9]/keyvalues", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/key[0-9]/keyvalues/2", + Key.get(DummyFilterImpl.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/instance[0-9]/keyvalues", dummyFilter4, ImmutableMap.of("key", "value"), REGEX), + new Params( + "/instance[0-9]/keyvalues/2", dummyFilter4, ImmutableMap.of("key", "value"), REGEX), + new Params("/class", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET), + new Params("/class/2", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET), + new Params( + "/key", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of(), + SERVLET), + new Params( + "/key/2", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of(), + SERVLET), + new Params("/instance", dummyServlet1, ImmutableMap.of(), SERVLET), + new Params("/instance/2", dummyServlet1, ImmutableMap.of(), SERVLET), + new Params( + "/class/keyvalues", + Key.get(DummyServlet.class), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/class/keyvalues/2", + Key.get(DummyServlet.class), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/key/keyvalues", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/key/keyvalues/2", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + SERVLET), + new Params( + "/instance/keyvalues", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET), + new Params( + "/instance/keyvalues/2", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET), + new Params("/class[0-9]", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX), + new Params("/class[0-9]/2", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX), + new Params( + "/key[0-9]", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of(), + REGEX), + new Params( + "/key[0-9]/2", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of(), + REGEX), + new Params("/instance[0-9]", dummyServlet3, ImmutableMap.of(), REGEX), + new Params("/instance[0-9]/2", dummyServlet3, ImmutableMap.of(), REGEX), + new Params( + "/class[0-9]/keyvalues", + Key.get(DummyServlet.class), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/class[0-9]/keyvalues/2", + Key.get(DummyServlet.class), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/key[0-9]/keyvalues", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/key[0-9]/keyvalues/2", + Key.get(DummyServlet.class, Names.named("foo")), + ImmutableMap.of("key", "value"), + REGEX), + new Params( + "/instance[0-9]/keyvalues", dummyServlet4, ImmutableMap.of("key", "value"), REGEX), + new Params( + "/instance[0-9]/keyvalues/2", + dummyServlet4, + ImmutableMap.of("key", "value"), + REGEX)); assertEquals(expected.size(), visitor.actual.size()); Iterator actualIterator = visitor.actual.iterator(); int i = 0; - for(Params param : expected) { + for (Params param : expected) { assertEquals("wrong " + i++ + "th param", param, actualIterator.next()); } } @@ -145,48 +247,47 @@ binder().requireExplicitBindings(); filter("/class", "/class/2").through(DummyFilterImpl.class); - filter("/key", "/key/2").through( - Key.get(DummyFilterImpl.class, Names.named("foo"))); + filter("/key", "/key/2").through(Key.get(DummyFilterImpl.class, Names.named("foo"))); filter("/instance", "/instance/2").through(dummyFilter1); - filter("/class/keyvalues", "/class/keyvalues/2").through( - DummyFilterImpl.class, ImmutableMap.of("key", "value")); - filter("/key/keyvalues", "/key/keyvalues/2").through( - Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value")); - filter("/instance/keyvalues", "/instance/keyvalues/2").through( - dummyFilter2, ImmutableMap.of("key", "value")); + filter("/class/keyvalues", "/class/keyvalues/2") + .through(DummyFilterImpl.class, ImmutableMap.of("key", "value")); + filter("/key/keyvalues", "/key/keyvalues/2") + .through( + Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value")); + filter("/instance/keyvalues", "/instance/keyvalues/2") + .through(dummyFilter2, ImmutableMap.of("key", "value")); filterRegex("/class[0-9]", "/class[0-9]/2").through(DummyFilterImpl.class); - filterRegex("/key[0-9]", "/key[0-9]/2").through( - Key.get(DummyFilterImpl.class, Names.named("foo"))); + filterRegex("/key[0-9]", "/key[0-9]/2") + .through(Key.get(DummyFilterImpl.class, Names.named("foo"))); filterRegex("/instance[0-9]", "/instance[0-9]/2").through(dummyFilter3); - filterRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2").through( - DummyFilterImpl.class, ImmutableMap.of("key", "value")); - filterRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2").through( - Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value")); - filterRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2").through( - dummyFilter4, ImmutableMap.of("key", "value")); + filterRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2") + .through(DummyFilterImpl.class, ImmutableMap.of("key", "value")); + filterRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2") + .through( + Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value")); + filterRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2") + .through(dummyFilter4, ImmutableMap.of("key", "value")); serve("/class", "/class/2").with(DummyServlet.class); - serve("/key", "/key/2").with( - Key.get(DummyServlet.class, Names.named("foo"))); + serve("/key", "/key/2").with(Key.get(DummyServlet.class, Names.named("foo"))); serve("/instance", "/instance/2").with(dummyServlet1); - serve("/class/keyvalues", "/class/keyvalues/2").with( - DummyServlet.class, ImmutableMap.of("key", "value")); - serve("/key/keyvalues", "/key/keyvalues/2").with( - Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value")); - serve("/instance/keyvalues", "/instance/keyvalues/2").with( - dummyServlet2, ImmutableMap.of("key", "value")); + serve("/class/keyvalues", "/class/keyvalues/2") + .with(DummyServlet.class, ImmutableMap.of("key", "value")); + serve("/key/keyvalues", "/key/keyvalues/2") + .with(Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value")); + serve("/instance/keyvalues", "/instance/keyvalues/2") + .with(dummyServlet2, ImmutableMap.of("key", "value")); serveRegex("/class[0-9]", "/class[0-9]/2").with(DummyServlet.class); - serveRegex("/key[0-9]", "/key[0-9]/2").with( - Key.get(DummyServlet.class, Names.named("foo"))); + serveRegex("/key[0-9]", "/key[0-9]/2").with(Key.get(DummyServlet.class, Names.named("foo"))); serveRegex("/instance[0-9]", "/instance[0-9]/2").with(dummyServlet3); - serveRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2").with( - DummyServlet.class, ImmutableMap.of("key", "value")); - serveRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2").with( - Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value")); - serveRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2").with( - dummyServlet4, ImmutableMap.of("key", "value")); + serveRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2") + .with(DummyServlet.class, ImmutableMap.of("key", "value")); + serveRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2") + .with(Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value")); + serveRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2") + .with(dummyServlet4, ImmutableMap.of("key", "value")); } } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -12,14 +12,10 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.spi.BindingScopingVisitor; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -28,6 +24,7 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** * Tests the lifecycle of the encapsulated {@link FilterDefinition} class. @@ -43,22 +40,20 @@ final MockFilter mockFilter = new MockFilter(); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(Filter.class))) - .andReturn(binding); - - expect(injector.getInstance(Key.get(Filter.class))) - .andReturn(mockFilter) - .anyTimes(); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(Filter.class))).andReturn(binding); + + expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes(); replay(binding, injector); //some init params //noinspection SSBasedInspection - final Map initParams = new ImmutableMap.Builder() - .put("ahsd", "asdas24dok") - .put("ahssd", "asdasd124ok").build(); + final Map initParams = + new ImmutableMap.Builder() + .put("ahsd", "asdas24dok") + .put("ahssd", "asdasd124ok") + .build(); ServletContext servletContext = createMock(ServletContext.class); final String contextName = "thing__!@@44"; @@ -67,14 +62,18 @@ replay(servletContext); String pattern = "/*"; - final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), - UriPatternType.get(UriPatternType.SERVLET, pattern), initParams, null); + final FilterDefinition filterDef = + new FilterDefinition( + Key.get(Filter.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + initParams, + null); filterDef.init(servletContext, injector, Sets.newIdentityHashSet()); assertTrue(filterDef.getFilter() instanceof MockFilter); final FilterConfig filterConfig = mockFilter.getConfig(); assertTrue(null != filterConfig); - assertEquals(filterConfig.getServletContext().getServletContextName(), contextName); + assertEquals(contextName, filterConfig.getServletContext().getServletContextName()); assertEquals(filterConfig.getFilterName(), Key.get(Filter.class).toString()); final Enumeration names = filterConfig.getInitParameterNames(); @@ -95,26 +94,23 @@ final MockFilter mockFilter = new MockFilter(); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(Filter.class))) - .andReturn(binding); - - expect(injector.getInstance(Key.get(Filter.class))) - .andReturn(mockFilter) - .anyTimes(); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(Filter.class))).andReturn(binding); + + expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes(); expect(request.getRequestURI()).andReturn("/index.html"); - expect(request.getContextPath()) - .andReturn("") - .anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); replay(injector, binding, request); String pattern = "/*"; - final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), - UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final FilterDefinition filterDef = + new FilterDefinition( + Key.get(Filter.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); //should fire on mockfilter now filterDef.init(createMock(ServletContext.class), injector, Sets.newIdentityHashSet()); assertTrue(filterDef.getFilter() instanceof MockFilter); @@ -125,12 +121,15 @@ assertSame(mockFilter, matchingFilter); final boolean proceed[] = new boolean[1]; - matchingFilter.doFilter(request, null, new FilterChainInvocation(null, null, null) { - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { - proceed[0] = true; - } - }); + matchingFilter.doFilter( + request, + null, + new FilterChainInvocation(null, null, null) { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + proceed[0] = true; + } + }); assertTrue("Filter did not proceed down chain", proceed[0]); @@ -138,7 +137,6 @@ assertTrue("Destroy did not fire", mockFilter.isDestroy()); verify(injector, request); - } public final void testFilterCreateDispatchDestroySupressChain() @@ -148,51 +146,53 @@ Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); - final MockFilter mockFilter = new MockFilter() { - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) { - //suppress rest of chain... - } - }; - - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(Filter.class))) - .andReturn(binding); - - expect(injector.getInstance(Key.get(Filter.class))) - .andReturn(mockFilter) - .anyTimes(); + final MockFilter mockFilter = + new MockFilter() { + @Override + public void doFilter( + ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) { + //suppress rest of chain... + } + }; + + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(Filter.class))).andReturn(binding); + + expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes(); expect(request.getRequestURI()).andReturn("/index.html"); - expect(request.getContextPath()) - .andReturn("") - .anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); replay(injector, binding, request); String pattern = "/*"; - final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), - UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final FilterDefinition filterDef = + new FilterDefinition( + Key.get(Filter.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); //should fire on mockfilter now filterDef.init(createMock(ServletContext.class), injector, Sets.newIdentityHashSet()); assertTrue(filterDef.getFilter() instanceof MockFilter); - assertTrue("init did not fire", mockFilter.isInit()); Filter matchingFilter = filterDef.getFilterIfMatching(request); assertSame(mockFilter, matchingFilter); final boolean proceed[] = new boolean[1]; - matchingFilter.doFilter(request, null, new FilterChainInvocation(null, null, null) { - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { - proceed[0] = true; - } - }); + matchingFilter.doFilter( + request, + null, + new FilterChainInvocation(null, null, null) { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + proceed[0] = true; + } + }); assertFalse("filter did not suppress chain", proceed[0]); @@ -200,33 +200,34 @@ assertTrue("destroy did not fire", mockFilter.isDestroy()); verify(injector, request); - } public void testGetFilterIfMatching() throws ServletException { String pattern = "/*"; - final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), - UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final FilterDefinition filterDef = + new FilterDefinition( + Key.get(Filter.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); HttpServletRequest servletRequest = createMock(HttpServletRequest.class); ServletContext servletContext = createMock(ServletContext.class); Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); - final MockFilter mockFilter = new MockFilter() { - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) { - //suppress rest of chain... - } - }; - expect(injector.getBinding(Key.get(Filter.class))) - .andReturn(binding); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getInstance(Key.get(Filter.class))) - .andReturn(mockFilter) - .anyTimes(); + final MockFilter mockFilter = + new MockFilter() { + @Override + public void doFilter( + ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) { + //suppress rest of chain... + } + }; + expect(injector.getBinding(Key.get(Filter.class))).andReturn(binding); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes(); expect(servletRequest.getContextPath()).andReturn("/a_context_path"); expect(servletRequest.getRequestURI()).andReturn("/a_context_path/test.html"); @@ -240,28 +241,30 @@ public void testGetFilterIfMatchingNotMatching() throws ServletException { String pattern = "/*"; - final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), - UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final FilterDefinition filterDef = + new FilterDefinition( + Key.get(Filter.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); HttpServletRequest servletRequest = createMock(HttpServletRequest.class); ServletContext servletContext = createMock(ServletContext.class); Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); - final MockFilter mockFilter = new MockFilter() { - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) { - //suppress rest of chain... - } - }; - expect(injector.getBinding(Key.get(Filter.class))) - .andReturn(binding); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getInstance(Key.get(Filter.class))) - .andReturn(mockFilter) - .anyTimes(); + final MockFilter mockFilter = + new MockFilter() { + @Override + public void doFilter( + ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) { + //suppress rest of chain... + } + }; + expect(injector.getBinding(Key.get(Filter.class))).andReturn(binding); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes(); expect(servletRequest.getContextPath()).andReturn("/a_context_path"); expect(servletRequest.getRequestURI()).andReturn("/test.html"); @@ -278,18 +281,22 @@ private boolean destroy; private FilterConfig config; + @Override public void init(FilterConfig filterConfig) { init = true; this.config = filterConfig; } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { //proceed filterChain.doFilter(servletRequest, servletResponse); } + @Override public void destroy() { destroy = true; } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,17 +26,10 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - -import org.easymock.EasyMock; -import org.easymock.IMocksControl; - import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -46,18 +39,19 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; /** + * This tests that filter stage of the pipeline dispatches correctly to guice-managed filters. * - * This tests that filter stage of the pipeline dispatches - * correctly to guice-managed filters. - * - * WARNING(dhanji): Non-parallelizable test =( + *

    WARNING(dhanji): Non-parallelizable test =( * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class FilterDispatchIntegrationTest extends TestCase { - private static int inits, doFilters, destroys; + private static int inits, doFilters, destroys; private IMocksControl control; @@ -70,24 +64,25 @@ GuiceFilter.reset(); } - public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/*").through(TestFilter.class); - filter("*.html").through(TestFilter.class); - filter("/*").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(TestFilter.class)); - filter("*.jsp").through(Key.get(TestFilter.class)); - - // Bind a servlet - serve("*.html").with(TestServlet.class); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/*").through(TestFilter.class); + filter("*.html").through(TestFilter.class); + filter("/*").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(TestFilter.class)); + filter("*.jsp").through(Key.get(TestFilter.class)); + + // Bind a servlet + serve("*.html").with(TestServlet.class); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -95,20 +90,14 @@ // create ourselves a mock request with test URI HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); HttpServletResponse responseMock = control.createMock(HttpServletResponse.class); - expect(responseMock.isCommitted()) - .andReturn(false) - .anyTimes(); + expect(responseMock.isCommitted()).andReturn(false).anyTimes(); responseMock.resetBuffer(); expectLastCall().anyTimes(); @@ -125,25 +114,33 @@ assertTrue(servlet.processedUris.contains("/index.html")); assertTrue(servlet.processedUris.contains(TestServlet.FORWARD_TO)); - assertTrue("lifecycle states did not" - + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, inits == 1 && doFilters == 3 && destroys == 1); + assertTrue( + "lifecycle states did not" + + " fire correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, + inits == 1 && doFilters == 3 && destroys == 1); } public final void testDispatchThatNoFiltersFire() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/public/*").through(TestFilter.class); - filter("*.html").through(TestFilter.class); - filter("*.xml").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(TestFilter.class)); - filter("*.jsp").through(Key.get(TestFilter.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/public/*").through(TestFilter.class); + filter("*.html").through(TestFilter.class); + filter("*.xml").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(TestFilter.class)); + filter("*.jsp").through(Key.get(TestFilter.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -151,12 +148,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.xhtml") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.xhtml").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request FilterChain filterChain = control.createMock(FilterChain.class); @@ -166,25 +159,32 @@ pipeline.destroyPipeline(); control.verify(); - assertTrue("lifecycle states did not " - + "fire correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not " + + "fire correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, inits == 1 && doFilters == 0 && destroys == 1); } - public final void testDispatchFilterPipelineWithRegexMatching() throws ServletException, - IOException { + public final void testDispatchFilterPipelineWithRegexMatching() + throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filterRegex("/[A-Za-z]*").through(TestFilter.class); - filterRegex("/index").through(TestFilter.class); - //these filters should never fire - filterRegex("\\w").through(Key.get(TestFilter.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filterRegex("/[A-Za-z]*").through(TestFilter.class); + filterRegex("/index").through(TestFilter.class); + //these filters should never fire + filterRegex("\\w").through(Key.get(TestFilter.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -192,12 +192,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); // dispatch request FilterChain filterChain = control.createMock(FilterChain.class); @@ -207,44 +203,101 @@ pipeline.destroyPipeline(); control.verify(); - assertTrue("lifecycle states did not fire " - + "correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not fire " + + "correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, inits == 1 && doFilters == 2 && destroys == 1); } @Singleton public static class TestFilter implements Filter { + @Override public void init(FilterConfig filterConfig) { inits++; } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } + @Override public void destroy() { destroys++; } } + public final void testFilterBypass() throws ServletException, IOException { + + final Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/protected/*").through(TestFilter.class); + } + }); + + final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); + pipeline.initPipeline(null); + assertEquals(1, inits); + + runRequestForPath(pipeline, "/./protected/resource", true); + runRequestForPath(pipeline, "/protected/../resource", false); + runRequestForPath(pipeline, "/protected/../protected/resource", true); + + assertEquals(0, destroys); + pipeline.destroyPipeline(); + assertEquals(1, destroys); + } + + private void runRequestForPath(FilterPipeline pipeline, String value, boolean matches) + throws IOException, ServletException { + assertEquals(0, doFilters); + //create ourselves a mock request with test URI + HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); + expect(requestMock.getRequestURI()).andReturn(value).anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); + // dispatch request + FilterChain filterChain = control.createMock(FilterChain.class); + filterChain.doFilter(requestMock, null); + control.replay(); + pipeline.dispatch(requestMock, null, filterChain); + control.verify(); + control.reset(); + if (matches) { + assertEquals("filter was not run", 1, doFilters); + doFilters = 0; + } else { + assertEquals("filter was run", 0, doFilters); + } + } + @Singleton public static class TestServlet extends HttpServlet { public static final String FORWARD_FROM = "/index.html"; public static final String FORWARD_TO = "/forwarded.html"; - public List processedUris = new ArrayList(); + public List processedUris = new ArrayList<>(); @Override - protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + protected void service( + HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { String requestUri = httpServletRequest.getRequestURI(); processedUris.add(requestUri); // If the client is requesting /index.html then we forward to /forwarded.html if (FORWARD_FROM.equals(requestUri)) { - httpServletRequest.getRequestDispatcher(FORWARD_TO) + httpServletRequest + .getRequestDispatcher(FORWARD_TO) .forward(httpServletRequest, httpServletResponse); } } @@ -255,33 +308,36 @@ service((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); } } - + public void testFilterOrder() throws Exception { AtomicInteger counter = new AtomicInteger(); final CountFilter f1 = new CountFilter(counter); final CountFilter f2 = new CountFilter(counter); - - Injector injector = Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - filter("/").through(f1); - install(new ServletModule() { - @Override - protected void configureServlets() { - filter("/").through(f2); - } - }); - } - }); - - HttpServletRequest request = newFakeHttpServletRequest(); + + Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/").through(f1); + install( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/").through(f2); + } + }); + } + }); + + HttpServletRequest request = newFakeHttpServletRequest(); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); - pipeline.initPipeline(null); + pipeline.initPipeline(null); pipeline.dispatch(request, null, newNoOpFilterChain()); assertEquals(0, f1.calledAt); assertEquals(1, f2.calledAt); } - + /** A filter that keeps count of when it was called by increment a counter. */ private static class CountFilter implements Filter { private final AtomicInteger counter; @@ -290,10 +346,11 @@ public CountFilter(AtomicInteger counter) { this.counter = counter; } - - public void destroy() { - } - + + @Override + public void destroy() {} + + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { if (calledAt != -1) { @@ -302,62 +359,69 @@ calledAt = counter.getAndIncrement(); chain.doFilter(request, response); } - + + @Override public void init(FilterConfig filterConfig) {} } - + public final void testFilterExceptionPrunesStack() throws Exception { - Injector injector = Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - filter("/").through(TestFilter.class); - filter("/nothing").through(TestFilter.class); - filter("/").through(ThrowingFilter.class); - } - }); + Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/").through(TestFilter.class); + filter("/nothing").through(TestFilter.class); + filter("/").through(ThrowingFilter.class); + } + }); - HttpServletRequest request = newFakeHttpServletRequest(); + HttpServletRequest request = newFakeHttpServletRequest(); FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); - pipeline.initPipeline(null); + pipeline.initPipeline(null); try { pipeline.dispatch(request, null, null); fail("expected exception"); - } catch(ServletException ex) { + } catch (ServletException ex) { for (StackTraceElement element : ex.getStackTrace()) { String className = element.getClassName(); - assertTrue("was: " + element, + assertTrue( + "was: " + element, !className.equals(FilterChainInvocation.class.getName()) - && !className.equals(FilterDefinition.class.getName())); + && !className.equals(FilterDefinition.class.getName())); } } } - + public final void testServletExceptionPrunesStack() throws Exception { - Injector injector = Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - filter("/").through(TestFilter.class); - filter("/nothing").through(TestFilter.class); - serve("/").with(ThrowingServlet.class); - } - }); + Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/").through(TestFilter.class); + filter("/nothing").through(TestFilter.class); + serve("/").with(ThrowingServlet.class); + } + }); - HttpServletRequest request = newFakeHttpServletRequest(); + HttpServletRequest request = newFakeHttpServletRequest(); FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); - pipeline.initPipeline(null); + pipeline.initPipeline(null); try { pipeline.dispatch(request, null, null); fail("expected exception"); - } catch(ServletException ex) { + } catch (ServletException ex) { for (StackTraceElement element : ex.getStackTrace()) { String className = element.getClassName(); - assertTrue("was: " + element, + assertTrue( + "was: " + element, !className.equals(FilterChainInvocation.class.getName()) - && !className.equals(FilterDefinition.class.getName())); + && !className.equals(FilterDefinition.class.getName())); } } } - + @Singleton private static class ThrowingServlet extends HttpServlet { @@ -366,26 +430,20 @@ throws ServletException { throw new ServletException("failure!"); } - } - @Singleton private static class ThrowingFilter implements Filter { @Override - public void destroy() { - } - + public void destroy() {} + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException { throw new ServletException("we failed!"); } - - @Override - public void init(FilterConfig filterConfig) { - } - + @Override + public void init(FilterConfig filterConfig) {} } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -11,11 +11,7 @@ import com.google.inject.Guice; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -24,11 +20,12 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** - * This is a basic whitebox test that verifies the glue between - * GuiceFilter and ManagedFilterPipeline is working. - * + * This is a basic whitebox test that verifies the glue between GuiceFilter and + * ManagedFilterPipeline is working. + * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class FilterPipelineTest extends TestCase { @@ -36,21 +33,22 @@ @Override public final void setUp() { GuiceFilter.reset(); - - Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - filter("/*").through(TestFilter.class); - filter("*.html").through(TestFilter.class); - filter("/*").through(Key.get(TestFilter.class)); - filter("*.jsp").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(NeverFilter.class)); - filter("/public/login/*").through(Key.get(NeverFilter.class)); - } - }); + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/*").through(TestFilter.class); + filter("*.html").through(TestFilter.class); + filter("/*").through(Key.get(TestFilter.class)); + filter("*.jsp").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(NeverFilter.class)); + filter("/public/login/*").through(Key.get(NeverFilter.class)); + } + }); } @Override @@ -68,16 +66,10 @@ //begin mock script *** - expect(filterConfig.getServletContext()) - .andReturn(servletContext) - .once(); - - expect(request.getRequestURI()) - .andReturn("/public/login.jsp") - .anyTimes(); - expect(request.getContextPath()) - .andReturn("") - .anyTimes(); + expect(filterConfig.getServletContext()).andReturn(servletContext).once(); + + expect(request.getRequestURI()).andReturn("/public/login.jsp").anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); //at the end, proceed down webapp's normal filter chain proceedingFilterChain.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull()); @@ -98,29 +90,32 @@ @Singleton public static class TestFilter implements Filter { - public void init(FilterConfig filterConfig) { - } + @Override + public void init(FilterConfig filterConfig) {} - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } - public void destroy() { - } + @Override + public void destroy() {} } @Singleton public static class NeverFilter implements Filter { - public void init(FilterConfig filterConfig) { - } + @Override + public void init(FilterConfig filterConfig) {} - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) { fail("This filter should never have fired"); } - public void destroy() { - } + @Override + public void destroy() {} } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -13,11 +13,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -26,10 +22,11 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** - * Exactly the same as {@linkplain com.google.inject.servlet.FilterPipelineTest} except - * that we test that the static pipeline is not used. + * Exactly the same as {@linkplain com.google.inject.servlet.FilterPipelineTest} except that we test + * that the static pipeline is not used. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @@ -39,40 +36,43 @@ @Override public final void setUp() { - injector1 = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/*").through(TestFilter.class); - filter("*.html").through(TestFilter.class); - filter("/*").through(Key.get(TestFilter.class)); - filter("*.jsp").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(NeverFilter.class)); - filter("/public/login/*").through(Key.get(NeverFilter.class)); - } - }); + injector1 = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/*").through(TestFilter.class); + filter("*.html").through(TestFilter.class); + filter("/*").through(Key.get(TestFilter.class)); + filter("*.jsp").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(NeverFilter.class)); + filter("/public/login/*").through(Key.get(NeverFilter.class)); + } + }); // Test second injector with exactly opposite pipeline config - injector2 = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - // These filters should never fire - filter("*.html").through(NeverFilter.class); - filter("/non-jsp/*").through(Key.get(NeverFilter.class)); - - // only these filters fire. - filter("/index/*").through(Key.get(TestFilter.class)); - filter("/public/login/*").through(Key.get(TestFilter.class)); - } - }); + injector2 = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + // These filters should never fire + filter("*.html").through(NeverFilter.class); + filter("/non-jsp/*").through(Key.get(NeverFilter.class)); + + // only these filters fire. + filter("/index/*").through(Key.get(TestFilter.class)); + filter("/public/login/*").through(Key.get(TestFilter.class)); + } + }); } @Override - public final void tearDown() { - } + public final void tearDown() {} public final void testDispatchThruInjectedGuiceFilter() throws ServletException, IOException { @@ -84,16 +84,12 @@ //begin mock script *** - expect(filterConfig.getServletContext()) - .andReturn(servletContext) - .once(); + expect(filterConfig.getServletContext()).andReturn(servletContext).once(); expect(request.getRequestURI()) .andReturn("/non-jsp/login.html") // use a path that will fail in injector2 .anyTimes(); - expect(request.getContextPath()) - .andReturn("") - .anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); //at the end, proceed down webapp's normal filter chain proceedingFilterChain.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull()); @@ -111,11 +107,6 @@ //assert expectations verify(filterConfig, servletContext, request, proceedingFilterChain); - - - - - // reset mocks and run them against the other injector reset(filterConfig, servletContext, request, proceedingFilterChain); @@ -124,15 +115,11 @@ //begin mock script *** - expect(filterConfig.getServletContext()) - .andReturn(servletContext) - .once(); + expect(filterConfig.getServletContext()).andReturn(servletContext).once(); expect(request.getRequestURI()) - .andReturn("/public/login/login.jsp") // use a path that will fail in injector1 - .anyTimes(); - expect(request.getContextPath()) - .andReturn("") + .andReturn("/public/login/login.jsp") // use a path that will fail in injector1 .anyTimes(); + expect(request.getContextPath()).andReturn("").anyTimes(); //at the end, proceed down webapp's normal filter chain proceedingFilterChain2.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull()); @@ -153,29 +140,33 @@ @Singleton public static class TestFilter implements Filter { - public void init(FilterConfig filterConfig) throws ServletException { - } + @Override + public void init(FilterConfig filterConfig) throws ServletException {} - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } - public void destroy() { - } + @Override + public void destroy() {} } @Singleton public static class NeverFilter implements Filter { - public void init(FilterConfig filterConfig) throws ServletException { - } + @Override + public void init(FilterConfig filterConfig) throws ServletException {} - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { fail("This filter should never have fired"); } - public void destroy() { - } + @Override + public void destroy() {} } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -5,16 +5,14 @@ import com.google.inject.Guice; import com.google.inject.Scopes; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; +import junit.framework.TestCase; /** - * Ensures that an error is thrown if a Servlet or Filter is bound - * under any scope other than singleton, explicitly. + * Ensures that an error is thrown if a Servlet or Filter is bound under any scope other than + * singleton, explicitly. * * @author dhanji@gmail.com */ @@ -25,15 +23,16 @@ GuiceFilter.reset(); } - public final void testServletInNonSingletonScopeThrowsServletException(){ + public final void testServletInNonSingletonScopeThrowsServletException() { GuiceFilter guiceFilter = new GuiceFilter(); - Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - serve("/*").with(MyNonSingletonServlet.class); - } - }); + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + serve("/*").with(MyNonSingletonServlet.class); + } + }); ServletException se = null; try { @@ -45,15 +44,16 @@ } } - public final void testFilterInNonSingletonScopeThrowsServletException(){ + public final void testFilterInNonSingletonScopeThrowsServletException() { GuiceFilter guiceFilter = new GuiceFilter(); - Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - filter("/*").through(MyNonSingletonFilter.class); - } - }); + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/*").through(MyNonSingletonFilter.class); + } + }); ServletException se = null; try { @@ -65,20 +65,21 @@ } } - public final void testHappyCaseFilter(){ + public final void testHappyCaseFilter() { GuiceFilter guiceFilter = new GuiceFilter(); - Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - // Annotated scoping variant. - filter("/*").through(MySingletonFilter.class); - - // Explicit scoping variant. - bind(DummyFilterImpl.class).in(Scopes.SINGLETON); - filter("/*").through(DummyFilterImpl.class); - } - }); + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + // Annotated scoping variant. + filter("/*").through(MySingletonFilter.class); + + // Explicit scoping variant. + bind(DummyFilterImpl.class).in(Scopes.SINGLETON); + filter("/*").through(DummyFilterImpl.class); + } + }); ServletException se = null; try { @@ -91,11 +92,11 @@ } @RequestScoped - public static class MyNonSingletonServlet extends HttpServlet { } + public static class MyNonSingletonServlet extends HttpServlet {} @SessionScoped - public static class MyNonSingletonFilter extends DummyFilterImpl { } + public static class MyNonSingletonFilter extends DummyFilterImpl {} @Singleton - public static class MySingletonFilter extends DummyFilterImpl { } + public static class MySingletonFilter extends DummyFilterImpl {} } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -9,11 +9,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -21,18 +17,18 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** + * This tests that filter stage of the pipeline dispatches correctly to guice-managed filters with + * multiple modules. * - * This tests that filter stage of the pipeline dispatches - * correctly to guice-managed filters with multiple modules. - * - * WARNING(dhanji): Non-parallelizable test =( + *

    WARNING(dhanji): Non-parallelizable test =( * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class MultiModuleDispatchIntegrationTest extends TestCase { - private static int inits, doFilters, destroys; + private static int inits, doFilters, destroys; @Override public final void setUp() { @@ -43,30 +39,30 @@ GuiceFilter.reset(); } - public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/*").through(TestFilter.class); - - // These filters should never fire - filter("*.jsp").through(Key.get(TestFilter.class)); - } - - }, new ServletModule() { - - @Override - protected void configureServlets() { - filter("*.html").through(TestFilter.class); - filter("/*").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(TestFilter.class)); - } - - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/*").through(TestFilter.class); + + // These filters should never fire + filter("*.jsp").through(Key.get(TestFilter.class)); + } + }, + new ServletModule() { + + @Override + protected void configureServlets() { + filter("*.html").through(TestFilter.class); + filter("/*").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(TestFilter.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -74,12 +70,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -88,24 +80,33 @@ verify(requestMock); - assertTrue("lifecycle states did not" - + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not" + + " fire correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, inits == 1 && doFilters == 3 && destroys == 1); } @Singleton public static class TestFilter implements Filter { + @Override public void init(FilterConfig filterConfig) throws ServletException { inits++; } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } + @Override public void destroy() { destroys++; } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,16 +25,13 @@ import com.google.inject.Guice; import com.google.inject.Injector; - -import junit.framework.TestCase; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.http.HttpServlet; +import junit.framework.TestCase; /** - * This gorgeous test asserts that multiple servlet pipelines can - * run in the SAME JVM. booya. + * This gorgeous test asserts that multiple servlet pipelines can run in the SAME JVM. booya. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @@ -61,14 +58,16 @@ @Override protected Injector getInjector() { // Cache this injector in the test for later testing... - return injectorOne = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - // This creates a ManagedFilterPipeline internally... - serve("/*").with(DummyServlet.class); - } - }); + return injectorOne = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + // This creates a ManagedFilterPipeline internally... + serve("/*").with(DummyServlet.class); + } + }); } }.contextInitialized(new ServletContextEvent(fakeContextOne)); @@ -81,16 +80,18 @@ @Override protected Injector getInjector() { - return injectorTwo = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - // This creates a ManagedFilterPipeline internally... - filter("/8").through(DummyFilterImpl.class); - - serve("/*").with(HttpServlet.class); - } - }); + return injectorTwo = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + // This creates a ManagedFilterPipeline internally... + filter("/8").through(DummyFilterImpl.class); + + serve("/*").with(HttpServlet.class); + } + }); } }.contextInitialized(new ServletContextEvent(fakeContextTwo)); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,9 +28,6 @@ import com.google.inject.Singleton; import com.google.inject.name.Named; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Map; import java.util.concurrent.Callable; @@ -38,12 +35,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - import javax.servlet.ServletException; +import junit.framework.TestCase; -/** - * Tests continuation of requests - */ +/** Tests continuation of requests */ public class ScopeRequestIntegrationTest extends TestCase { private static final String A_VALUE = "thereaoskdao"; @@ -57,17 +52,24 @@ // We use servlet module here because we want to test that @RequestScoped // behaves properly with the non-HTTP request scope logic. - Injector injector = Guice.createInjector(new ServletModule() { - @Override protected void configureServlets() { - bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); - bind(SomeObject.class).in(RequestScoped.class); - } - }); + Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); + bind(SomeObject.class).in(RequestScoped.class); + } + }); SomeObject someObject = new SomeObject(A_VALUE); OffRequestCallable offRequestCallable = injector.getInstance(OffRequestCallable.class); - executor.submit(ServletScopes.scopeRequest(offRequestCallable, - ImmutableMap., Object>of(Key.get(SomeObject.class), someObject))).get(); + executor + .submit( + ServletScopes.scopeRequest( + offRequestCallable, + ImmutableMap., Object>of(Key.get(SomeObject.class), someObject))) + .get(); assertSame(injector.getInstance(OffRequestCallable.class), offRequestCallable); @@ -77,8 +79,12 @@ // Now create a new request and assert that the scopes don't cross. someObject = new SomeObject(A_DIFFERENT_VALUE); - executor.submit(ServletScopes.scopeRequest(offRequestCallable, - ImmutableMap., Object>of(Key.get(SomeObject.class), someObject))).get(); + executor + .submit( + ServletScopes.scopeRequest( + offRequestCallable, + ImmutableMap., Object>of(Key.get(SomeObject.class), someObject))) + .get(); assertSame(injector.getInstance(OffRequestCallable.class), offRequestCallable); @@ -90,36 +96,46 @@ } public final void testWrongValueClasses() throws Exception { - Injector injector = Guice.createInjector(new ServletModule() { - @Override protected void configureServlets() { - bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); - bind(SomeObject.class).in(RequestScoped.class); - } - }); + Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); + bind(SomeObject.class).in(RequestScoped.class); + } + }); OffRequestCallable offRequestCallable = injector.getInstance(OffRequestCallable.class); try { - ServletScopes.scopeRequest(offRequestCallable, - ImmutableMap., Object>of(Key.get(SomeObject.class), "Boo!")); + ServletScopes.scopeRequest( + offRequestCallable, ImmutableMap., Object>of(Key.get(SomeObject.class), "Boo!")); fail(); - } catch(IllegalArgumentException iae) { - assertEquals("Value[Boo!] of type[java.lang.String] is not compatible with key[" + Key.get(SomeObject.class) + "]", iae.getMessage()); + } catch (IllegalArgumentException iae) { + assertEquals( + "Value[Boo!] of type[java.lang.String] is not compatible with key[" + + Key.get(SomeObject.class) + + "]", + iae.getMessage()); } } public final void testNullReplacement() throws Exception { - Injector injector = Guice.createInjector(new ServletModule() { - @Override protected void configureServlets() { - bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); - bind(SomeObject.class).in(RequestScoped.class); - } - }); + Injector injector = + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); + bind(SomeObject.class).in(RequestScoped.class); + } + }); Callable callable = injector.getInstance(Caller.class); try { assertNotNull(callable.call()); fail(); - } catch(ProvisionException pe) { + } catch (ProvisionException pe) { assertTrue(pe.getCause() instanceof OutOfScopeException); } @@ -138,6 +154,7 @@ public SomeObject(@Named(INVALID) String value) { this.value = value; } + private final String value; } @@ -147,6 +164,7 @@ public String value; + @Override public String call() throws Exception { // Inside this request, we should always get the same instance. assertSame(someObject.get(), someObject.get()); @@ -161,6 +179,7 @@ private static class Caller implements Callable { @Inject Provider someObject; + @Override public SomeObject call() throws Exception { return someObject.get(); } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,20 +28,16 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.spi.BindingScopingVisitor; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.HashMap; - import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; /** - * Ensures servlet spec compliance for CGI-style variables and general - * path/pattern matching. + * Ensures servlet spec compliance for CGI-style variables and general path/pattern matching. * * @author Dhanji R. Prasanna (dhanji@gmail com) */ @@ -61,86 +57,98 @@ servletPath("/thing/wing/index.html", "/thing/*", "/thing"); } - private void servletPath(final String requestPath, String mapping, - final String expectedServletPath) throws IOException, ServletException { + private void servletPath( + final String requestPath, String mapping, final String expectedServletPath) + throws IOException, ServletException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); final boolean[] run = new boolean[1]; //get an instance of this servlet expect(injector.getInstance(Key.get(HttpServlet.class))) - .andReturn(new HttpServlet() { + .andReturn( + new HttpServlet() { - @Override - protected void service(HttpServletRequest servletRequest, - HttpServletResponse httpServletResponse) throws ServletException, IOException { - - final String path = servletRequest.getServletPath(); - assertEquals(String.format("expected [%s] but was [%s]", expectedServletPath, path), - expectedServletPath, path); - run[0] = true; - } - }); + @Override + protected void service( + HttpServletRequest servletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + + final String path = servletRequest.getServletPath(); + assertEquals( + String.format("expected [%s] but was [%s]", expectedServletPath, path), + expectedServletPath, + path); + run[0] = true; + } + }); - expect(request.getServletPath()) - .andReturn(requestPath); + expect(request.getServletPath()).andReturn(requestPath); replay(injector, binding, request); - ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class), - UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap(), null); + ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, mapping), + new HashMap(), + null); servletDefinition.init(null, injector, Sets.newIdentityHashSet()); servletDefinition.doService(request, response); assertTrue("Servlet did not run!", run[0]); - - verify(injector, binding, request); + verify(injector, binding, request); } // Data-driven test. public final void testPathInfoWithServletStyleMatching() throws IOException, ServletException { pathInfoWithServletStyleMatching("/path/index.html", "/path", "/*", "/index.html", ""); - pathInfoWithServletStyleMatching("/path//hulaboo///index.html", "/path", "/*", - "/hulaboo/index.html", ""); + pathInfoWithServletStyleMatching( + "/path//hulaboo///index.html", "/path", "/*", "/hulaboo/index.html", ""); pathInfoWithServletStyleMatching("/path/", "/path", "/*", "/", ""); pathInfoWithServletStyleMatching("/path////////", "/path", "/*", "/", ""); // a servlet mapping of /thing/* pathInfoWithServletStyleMatching("/path/thing////////", "/path", "/thing/*", "/", "/thing"); pathInfoWithServletStyleMatching("/path/thing/stuff", "/path", "/thing/*", "/stuff", "/thing"); - pathInfoWithServletStyleMatching("/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html", - "/thing"); + pathInfoWithServletStyleMatching( + "/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html", "/thing"); pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*", null, "/thing"); // see external issue 372 - pathInfoWithServletStyleMatching("/path/some/path/of.jsp", "/path", "/thing/*", - null, "/some/path/of.jsp"); + pathInfoWithServletStyleMatching( + "/path/some/path/of.jsp", "/path", "/thing/*", null, "/some/path/of.jsp"); // *.xx style mapping pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing", null, "/thing.thing"); pathInfoWithServletStyleMatching("/path///h.thing", "/path", "*.thing", null, "/h.thing"); - pathInfoWithServletStyleMatching("/path///...//h.thing", "/path", "*.thing", null, - "/.../h.thing"); + pathInfoWithServletStyleMatching( + "/path///...//h.thing", "/path", "*.thing", null, "/.../h.thing"); pathInfoWithServletStyleMatching("/path/my/h.thing", "/path", "*.thing", null, "/my/h.thing"); // Encoded URLs pathInfoWithServletStyleMatching("/path/index%2B.html", "/path", "/*", "/index+.html", ""); - pathInfoWithServletStyleMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/*", "/a file with spaces in name.html", ""); - pathInfoWithServletStyleMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/*", "/Tamás nem más.html", ""); + pathInfoWithServletStyleMatching( + "/path/a%20file%20with%20spaces%20in%20name.html", + "/path", "/*", "/a file with spaces in name.html", ""); + pathInfoWithServletStyleMatching( + "/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/*", "/Tamás nem más.html", ""); } - private void pathInfoWithServletStyleMatching(final String requestUri, final String contextPath, - String mapping, final String expectedPathInfo, final String servletPath) + private void pathInfoWithServletStyleMatching( + final String requestUri, + final String contextPath, + String mapping, + final String expectedPathInfo, + final String servletPath) throws IOException, ServletException { Injector injector = createMock(Injector.class); @@ -148,55 +156,56 @@ HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); final boolean[] run = new boolean[1]; //get an instance of this servlet expect(injector.getInstance(Key.get(HttpServlet.class))) - .andReturn(new HttpServlet() { + .andReturn( + new HttpServlet() { + + @Override + protected void service( + HttpServletRequest servletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + + final String path = servletRequest.getPathInfo(); + + if (null == expectedPathInfo) { + assertNull( + String.format("expected [%s] but was [%s]", expectedPathInfo, path), path); + } else { + assertEquals( + String.format("expected [%s] but was [%s]", expectedPathInfo, path), + expectedPathInfo, + path); + } + + //assert memoizer + //noinspection StringEquality + assertSame("memo field did not work", path, servletRequest.getPathInfo()); + + run[0] = true; + } + }); + + expect(request.getRequestURI()).andReturn(requestUri); - @Override - protected void service(HttpServletRequest servletRequest, - HttpServletResponse httpServletResponse) throws ServletException, IOException { - - final String path = servletRequest.getPathInfo(); - - if (null == expectedPathInfo) { - assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path), - path); - } - else { - assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path), - expectedPathInfo, path); - } - - //assert memoizer - //noinspection StringEquality - assertSame("memo field did not work", path, servletRequest.getPathInfo()); - - run[0] = true; - } - }); - - expect(request.getRequestURI()) - .andReturn(requestUri); - - expect(request.getServletPath()) - .andReturn(servletPath) - .anyTimes(); + expect(request.getServletPath()).andReturn(servletPath).anyTimes(); - expect(request.getContextPath()) - .andReturn(contextPath); + expect(request.getContextPath()).andReturn(contextPath); expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null); replay(injector, binding, request); - ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class), - UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap(), null); + ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, mapping), + new HashMap(), + null); servletDefinition.init(null, injector, Sets.newIdentityHashSet()); servletDefinition.doService(request, response); @@ -210,37 +219,47 @@ public final void testPathInfoWithRegexMatching() throws IOException, ServletException { // first a mapping of /* pathInfoWithRegexMatching("/path/index.html", "/path", "/(.)*", "/index.html", ""); - pathInfoWithRegexMatching("/path//hulaboo///index.html", "/path", "/(.)*", - "/hulaboo/index.html", ""); + pathInfoWithRegexMatching( + "/path//hulaboo///index.html", "/path", "/(.)*", "/hulaboo/index.html", ""); pathInfoWithRegexMatching("/path/", "/path", "/(.)*", "/", ""); pathInfoWithRegexMatching("/path////////", "/path", "/(.)*", "/", ""); // a servlet mapping of /thing/* pathInfoWithRegexMatching("/path/thing////////", "/path", "/thing/(.)*", "/", "/thing"); pathInfoWithRegexMatching("/path/thing/stuff", "/path", "/thing/(.)*", "/stuff", "/thing"); - pathInfoWithRegexMatching("/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html", - "/thing"); + pathInfoWithRegexMatching( + "/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html", "/thing"); pathInfoWithRegexMatching("/path/thing", "/path", "/thing/(.)*", null, "/thing"); // *.xx style mapping pathInfoWithRegexMatching("/path/thing.thing", "/path", ".*\\.thing", null, "/thing.thing"); pathInfoWithRegexMatching("/path///h.thing", "/path", ".*\\.thing", null, "/h.thing"); - pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null, - "/.../h.thing"); + pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null, "/.../h.thing"); pathInfoWithRegexMatching("/path/my/h.thing", "/path", ".*\\.thing", null, "/my/h.thing"); // path - pathInfoWithRegexMatching("/path/test.com/com.test.MyServletModule", "", "/path/[^/]+/(.*)", - "com.test.MyServletModule", "/path/test.com/com.test.MyServletModule"); + pathInfoWithRegexMatching( + "/path/test.com/com.test.MyServletModule", + "", + "/path/[^/]+/(.*)", + "com.test.MyServletModule", + "/path/test.com/com.test.MyServletModule"); // Encoded URLs pathInfoWithRegexMatching("/path/index%2B.html", "/path", "/(.)*", "/index+.html", ""); - pathInfoWithRegexMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/(.)*", "/a file with spaces in name.html", ""); - pathInfoWithRegexMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/(.)*", "/Tamás nem más.html", ""); + pathInfoWithRegexMatching( + "/path/a%20file%20with%20spaces%20in%20name.html", + "/path", "/(.)*", "/a file with spaces in name.html", ""); + pathInfoWithRegexMatching( + "/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/(.)*", "/Tamás nem más.html", ""); } - public final void pathInfoWithRegexMatching(final String requestUri, final String contextPath, - String mapping, final String expectedPathInfo, final String servletPath) + public final void pathInfoWithRegexMatching( + final String requestUri, + final String contextPath, + String mapping, + final String expectedPathInfo, + final String servletPath) throws IOException, ServletException { Injector injector = createMock(Injector.class); @@ -248,61 +267,62 @@ HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); final boolean[] run = new boolean[1]; //get an instance of this servlet expect(injector.getInstance(Key.get(HttpServlet.class))) - .andReturn(new HttpServlet() { + .andReturn( + new HttpServlet() { - @Override - protected void service(HttpServletRequest servletRequest, - HttpServletResponse httpServletResponse) throws ServletException, IOException { - - final String path = servletRequest.getPathInfo(); - - if (null == expectedPathInfo) { - assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path), - path); - } - else { - assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path), - expectedPathInfo, path); - } - - //assert memoizer - //noinspection StringEquality - assertSame("memo field did not work", path, servletRequest.getPathInfo()); - - run[0] = true; - } - }); - - expect(request.getRequestURI()) - .andReturn(requestUri); - - expect(request.getServletPath()) - .andReturn(servletPath) - .anyTimes(); + @Override + protected void service( + HttpServletRequest servletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + + final String path = servletRequest.getPathInfo(); + + if (null == expectedPathInfo) { + assertNull( + String.format("expected [%s] but was [%s]", expectedPathInfo, path), path); + } else { + assertEquals( + String.format("expected [%s] but was [%s]", expectedPathInfo, path), + expectedPathInfo, + path); + } + + //assert memoizer + //noinspection StringEquality + assertSame("memo field did not work", path, servletRequest.getPathInfo()); + + run[0] = true; + } + }); - expect(request.getContextPath()) - .andReturn(contextPath); + expect(request.getRequestURI()).andReturn(requestUri); + + expect(request.getServletPath()).andReturn(servletPath).anyTimes(); + + expect(request.getContextPath()).andReturn(contextPath); expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null); replay(injector, binding, request); - ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class), - UriPatternType.get(UriPatternType.REGEX, mapping), new HashMap(), null); + ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.REGEX, mapping), + new HashMap(), + null); servletDefinition.init(null, injector, Sets.newIdentityHashSet()); servletDefinition.doService(request, response); assertTrue("Servlet did not run!", run[0]); - + verify(injector, binding, request); } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,19 +28,16 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.spi.BindingScopingVisitor; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Enumeration; import java.util.Map; - import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; /** * Basic unit test for lifecycle of a ServletDefinition (wrapper). @@ -53,32 +50,32 @@ Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); - final HttpServlet mockServlet = new HttpServlet() { - }; - expect(injector.getInstance(Key.get(HttpServlet.class))) - .andReturn(mockServlet) - .anyTimes(); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); + final HttpServlet mockServlet = new HttpServlet() {}; + expect(injector.getInstance(Key.get(HttpServlet.class))).andReturn(mockServlet).anyTimes(); replay(injector, binding); //some init params //noinspection SSBasedInspection - final Map initParams = new ImmutableMap.Builder() - .put("ahsd", "asdas24dok") - .put("ahssd", "asdasd124ok").build(); + final Map initParams = + new ImmutableMap.Builder() + .put("ahsd", "asdas24dok") + .put("ahssd", "asdasd124ok") + .build(); String pattern = "/*"; - final ServletDefinition servletDefinition = new ServletDefinition(pattern, - Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), initParams, null); + final ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + initParams, + null); ServletContext servletContext = createMock(ServletContext.class); final String contextName = "thing__!@@44__SRV" + getClass(); - expect(servletContext.getServletContextName()) - .andReturn(contextName); + expect(servletContext.getServletContextName()).andReturn(contextName); replay(servletContext); @@ -100,17 +97,21 @@ verify(injector, binding, servletContext); } - public void testServiceWithContextPath() throws IOException, ServletException { + public void testServiceWithContextPath() throws IOException, ServletException { String pattern = "/*"; //some init params - Map initParams = new ImmutableMap.Builder() - .put("ahsd", "asdas24dok") - .put("ahssd", "asdasd124ok") - .build(); - - final ServletDefinition servletDefinition = new ServletDefinition(pattern, - Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), - initParams, null); + Map initParams = + new ImmutableMap.Builder() + .put("ahsd", "asdas24dok") + .put("ahssd", "asdasd124ok") + .build(); + + final ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + initParams, + null); HttpServletResponse servletResponse = createMock(HttpServletResponse.class); HttpServletRequest servletRequest = createMock(HttpServletRequest.class); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,11 +26,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -41,10 +37,11 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; /** - * Tests the FilterPipeline that dispatches to guice-managed servlets, - * is a full integration test, with a real injector. + * Tests the FilterPipeline that dispatches to guice-managed servlets, is a full integration test, + * with a real injector. * * @author Dhanji R. Prasanna (dhanji gmail com) */ @@ -63,19 +60,21 @@ public final void testDispatchRequestToManagedPipelineServlets() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - serve("/*").with(TestServlet.class); - - // These servets should never fire... (ordering test) - serve("*.html").with(NeverServlet.class); - serve("/test/*").with(Key.get(NeverServlet.class)); - serve("/index/*").with(Key.get(NeverServlet.class)); - serve("*.jsp").with(Key.get(NeverServlet.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + serve("/*").with(TestServlet.class); + + // These servets should never fire... (ordering test) + serve("*.html").with(NeverServlet.class); + serve("/test/*").with(Key.get(NeverServlet.class)); + serve("/index/*").with(Key.get(NeverServlet.class)); + serve("*.jsp").with(Key.get(NeverServlet.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -84,12 +83,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .times(1); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").times(1); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -100,29 +95,35 @@ verify(requestMock); - assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " - + services + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not fire correct number of times-- inits: " + + inits + + "; dos: " + + services + + "; destroys: " + + destroys, inits == 2 && services == 1 && destroys == 2); } public final void testDispatchRequestToManagedPipelineWithFilter() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/*").through(TestFilter.class); - - serve("/*").with(TestServlet.class); - - // These servets should never fire... - serve("*.html").with(NeverServlet.class); - serve("/test/*").with(Key.get(NeverServlet.class)); - serve("/index/*").with(Key.get(NeverServlet.class)); - serve("*.jsp").with(Key.get(NeverServlet.class)); - - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/*").through(TestFilter.class); + + serve("/*").with(TestServlet.class); + + // These servets should never fire... + serve("*.html").with(NeverServlet.class); + serve("/test/*").with(Key.get(NeverServlet.class)); + serve("/index/*").with(Key.get(NeverServlet.class)); + serve("*.jsp").with(Key.get(NeverServlet.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -131,12 +132,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .times(2); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").times(2); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -147,22 +144,32 @@ verify(requestMock); - assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " - + services + "; destroys: " + destroys + "; doFilters: " + doFilters, + assertTrue( + "lifecycle states did not fire correct number of times-- inits: " + + inits + + "; dos: " + + services + + "; destroys: " + + destroys + + "; doFilters: " + + doFilters, inits == 3 && services == 1 && destroys == 3 && doFilters == 1); } @Singleton public static class TestServlet extends HttpServlet { + @Override public void init(ServletConfig filterConfig) throws ServletException { inits++; } + @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { services++; } + @Override public void destroy() { destroys++; } @@ -170,15 +177,18 @@ @Singleton public static class NeverServlet extends HttpServlet { + @Override public void init(ServletConfig filterConfig) throws ServletException { inits++; } + @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { fail("NeverServlet was fired, when it should not have been."); } + @Override public void destroy() { destroys++; } @@ -186,30 +196,33 @@ @Singleton public static class TestFilter implements Filter { + @Override public void init(FilterConfig filterConfig) throws ServletException { inits++; } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } + @Override public void destroy() { destroys++; } } - @Singleton public static class ForwardingServlet extends HttpServlet { + @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; - request.getRequestDispatcher("/blah.jsp") - .forward(servletRequest, servletResponse); + request.getRequestDispatcher("/blah.jsp").forward(servletRequest, servletResponse); } } @@ -222,6 +235,7 @@ forwardedTo = 0; } + @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; @@ -232,22 +246,19 @@ } public void testForwardUsingRequestDispatcher() throws IOException, ServletException { - Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - serve("/").with(ForwardingServlet.class); - serve("/blah.jsp").with(ForwardedServlet.class); - } - }); + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + serve("/").with(ForwardingServlet.class); + serve("/blah.jsp").with(ForwardedServlet.class); + } + }); final HttpServletRequest requestMock = createMock(HttpServletRequest.class); HttpServletResponse responseMock = createMock(HttpServletResponse.class); - expect(requestMock.getRequestURI()) - .andReturn("/") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); expect(requestMock.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(true); @@ -258,24 +269,24 @@ replay(requestMock, responseMock); - new GuiceFilter() - .doFilter(requestMock, responseMock, - createMock(FilterChain.class)); + new GuiceFilter().doFilter(requestMock, responseMock, createMock(FilterChain.class)); assertEquals("Incorrect number of forwards", 1, ForwardedServlet.forwardedTo); verify(requestMock, responseMock); } public final void testQueryInRequestUri_regex() throws Exception { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filterRegex("(.)*\\.html").through(TestFilter.class); - - serveRegex("(.)*\\.html").with(TestServlet.class); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filterRegex("(.)*\\.html").through(TestFilter.class); + + serveRegex("(.)*\\.html").with(TestServlet.class); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -284,12 +295,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html?query=params") - .atLeastOnce(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html?query=params").atLeastOnce(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -305,15 +312,17 @@ } public final void testQueryInRequestUri() throws Exception { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/index.html").through(TestFilter.class); - - serve("/index.html").with(TestServlet.class); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/index.html").through(TestFilter.class); + + serve("/index.html").with(TestServlet.class); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -322,12 +331,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html?query=params") - .atLeastOnce(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html?query=params").atLeastOnce(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,27 +18,28 @@ import com.google.common.collect.Lists; import com.google.inject.Binding; +import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.spi.DefaultBindingTargetVisitor; import com.google.inject.spi.Elements; - -import junit.framework.TestCase; - import java.util.List; +import junit.framework.TestCase; /** * Tests for ServletModule, to ensure it captures bindings correctly. - * + * * @author sameb@google.com (Sam Berlin) */ public class ServletModuleTest extends TestCase { - + public void testServletModuleCallOutsideConfigure() { try { - new ServletModule() {{ - serve("/*").with(DummyServlet.class); - }}; + new ServletModule() { + { + serve("/*").with(DummyServlet.class); + } + }; fail(); } catch (IllegalStateException e) { // Expected. @@ -48,21 +49,38 @@ public void testServletModuleReuse() { Module module = new Module(); Elements.getElements(module); // use the module once (to, say, introspect bindings) - Injector injector = Guice.createInjector(module); // use it again. - - Visitor visitor = new Visitor(); + Injector injector = Guice.createInjector(module); // use it again. + + Visitor visitor = new Visitor(); // Validate only a single servlet binding & a single filter binding exist. - for(Binding binding : injector.getAllBindings().values()) { + for (Binding binding : injector.getAllBindings().values()) { binding.acceptTargetVisitor(visitor); } - assertEquals("wrong linked servlets: " + visitor.linkedServlets, - 0, visitor.linkedServlets.size()); - assertEquals("wrong linked filters: " + visitor.linkedFilters, - 0, visitor.linkedFilters.size()); - assertEquals("wrong instance servlets: " + visitor.instanceServlets, - 1, visitor.instanceServlets.size()); - assertEquals("wrong instance filters: " + visitor.instanceFilters, - 1, visitor.instanceFilters.size()); + assertEquals( + "wrong linked servlets: " + visitor.linkedServlets, 0, visitor.linkedServlets.size()); + assertEquals("wrong linked filters: " + visitor.linkedFilters, 0, visitor.linkedFilters.size()); + assertEquals( + "wrong instance servlets: " + visitor.instanceServlets, 1, visitor.instanceServlets.size()); + assertEquals( + "wrong instance filters: " + visitor.instanceFilters, 1, visitor.instanceFilters.size()); + } + + public void testServletModule_badPattern() { + try { + Guice.createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + serve("/%2E/*").with(new DummyServlet()); + serveRegex("/(foo|bar/").with(new DummyServlet()); + filter("/%2E/*").through(new DummyFilterImpl()); + filterRegex("/(foo|bar/").through(new DummyFilterImpl()); + } + }); + fail(); + } catch (CreationException e) { + assertEquals(4, e.getErrorMessages().size()); + } } private static class Module extends ServletModule { @@ -73,32 +91,35 @@ } } - private static class Visitor extends DefaultBindingTargetVisitor implements - ServletModuleTargetVisitor { + private static class Visitor extends DefaultBindingTargetVisitor + implements ServletModuleTargetVisitor { List linkedFilters = Lists.newArrayList(); List linkedServlets = Lists.newArrayList(); List instanceFilters = Lists.newArrayList(); List instanceServlets = Lists.newArrayList(); - + + @Override public Void visit(LinkedFilterBinding binding) { linkedFilters.add(binding); return null; } + @Override public Void visit(InstanceFilterBinding binding) { instanceFilters.add(binding); return null; } + @Override public Void visit(LinkedServletBinding binding) { linkedServlets.add(binding); return null; } + @Override public Void visit(InstanceServletBinding binding) { instanceServlets.add(binding); return null; } } - } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,88 +34,81 @@ import com.google.inject.TypeLiteral; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.UUID; - import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; /** - * Tests forwarding and inclusion (RequestDispatcher actions from the - * servlet spec). + * Tests forwarding and inclusion (RequestDispatcher actions from the servlet spec). * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public class ServletPipelineRequestDispatcherTest extends TestCase { private static final Key HTTP_SERLVET_KEY = Key.get(HttpServlet.class); private static final String A_KEY = "thinglyDEgintly" + new Date() + UUID.randomUUID(); - private static final String A_VALUE = ServletPipelineRequestDispatcherTest.class.toString() - + new Date() + UUID.randomUUID(); + private static final String A_VALUE = + ServletPipelineRequestDispatcherTest.class.toString() + new Date() + UUID.randomUUID(); public final void testIncludeManagedServlet() throws IOException, ServletException { String pattern = "blah.html"; - final ServletDefinition servletDefinition = new ServletDefinition(pattern, - Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); final Injector injector = createMock(Injector.class); final Binding binding = createMock(Binding.class); final HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getAttribute(A_KEY)) - .andReturn(A_VALUE); - + expect(requestMock.getAttribute(A_KEY)).andReturn(A_VALUE); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); final boolean[] run = new boolean[1]; - final HttpServlet mockServlet = new HttpServlet() { - protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - run[0] = true; - - final Object o = request.getAttribute(A_KEY); - assertEquals("Wrong attrib returned - " + o, A_VALUE, o); - } - }; - - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); - expect(injector.getInstance(HTTP_SERLVET_KEY)) - .andReturn(mockServlet); - + final HttpServlet mockServlet = + new HttpServlet() { + @Override + protected void service( + HttpServletRequest request, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + run[0] = true; + + final Object o = request.getAttribute(A_KEY); + assertEquals("Wrong attrib returned - " + o, A_VALUE, o); + } + }; + + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); + expect(injector.getInstance(HTTP_SERLVET_KEY)).andReturn(mockServlet); - final Key servetDefsKey = Key - .get(TypeLiteral.get(ServletDefinition.class)); + final Key servetDefsKey = Key.get(TypeLiteral.get(ServletDefinition.class)); Binding mockBinding = createMock(Binding.class); expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral()))) .andReturn(ImmutableList.>of(mockBinding)); Provider bindingProvider = Providers.of(servletDefinition); - expect(mockBinding.getProvider()) - .andReturn(bindingProvider); + expect(mockBinding.getProvider()).andReturn(bindingProvider); replay(injector, binding, requestMock, mockBinding); // Have to init the Servlet before we can dispatch to it. servletDefinition.init(null, injector, Sets.newIdentityHashSet()); - final RequestDispatcher dispatcher = new ManagedServletPipeline( - injector) - .getRequestDispatcher(pattern); + final RequestDispatcher dispatcher = + new ManagedServletPipeline(injector).getRequestDispatcher(pattern); assertNotNull(dispatcher); dispatcher.include(requestMock, createMock(HttpServletResponse.class)); @@ -127,64 +120,62 @@ public final void testForwardToManagedServlet() throws IOException, ServletException { String pattern = "blah.html"; - final ServletDefinition servletDefinition = new ServletDefinition(pattern, - Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); final Injector injector = createMock(Injector.class); final Binding binding = createMock(Binding.class); final HttpServletRequest requestMock = createMock(HttpServletRequest.class); final HttpServletResponse mockResponse = createMock(HttpServletResponse.class); - expect(requestMock.getAttribute(A_KEY)) - .andReturn(A_VALUE); - + expect(requestMock.getAttribute(A_KEY)).andReturn(A_VALUE); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); - expect(mockResponse.isCommitted()) - .andReturn(false); + expect(mockResponse.isCommitted()).andReturn(false); mockResponse.resetBuffer(); expectLastCall().once(); - final List paths = new ArrayList(); - final HttpServlet mockServlet = new HttpServlet() { - protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - paths.add(request.getRequestURI()); - - final Object o = request.getAttribute(A_KEY); - assertEquals("Wrong attrib returned - " + o, A_VALUE, o); - } - }; - - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); + final List paths = new ArrayList<>(); + final HttpServlet mockServlet = + new HttpServlet() { + @Override + protected void service( + HttpServletRequest request, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + paths.add(request.getRequestURI()); + + final Object o = request.getAttribute(A_KEY); + assertEquals("Wrong attrib returned - " + o, A_VALUE, o); + } + }; + + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); - expect(injector.getInstance(HTTP_SERLVET_KEY)) - .andReturn(mockServlet); + expect(injector.getInstance(HTTP_SERLVET_KEY)).andReturn(mockServlet); - final Key servetDefsKey = Key - .get(TypeLiteral.get(ServletDefinition.class)); + final Key servetDefsKey = Key.get(TypeLiteral.get(ServletDefinition.class)); Binding mockBinding = createMock(Binding.class); expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral()))) .andReturn(ImmutableList.>of(mockBinding)); Provider bindingProvider = Providers.of(servletDefinition); - expect(mockBinding.getProvider()) - .andReturn(bindingProvider); + expect(mockBinding.getProvider()).andReturn(bindingProvider); replay(injector, binding, requestMock, mockResponse, mockBinding); // Have to init the Servlet before we can dispatch to it. servletDefinition.init(null, injector, Sets.newIdentityHashSet()); - final RequestDispatcher dispatcher = new ManagedServletPipeline(injector) - .getRequestDispatcher(pattern); + final RequestDispatcher dispatcher = + new ManagedServletPipeline(injector).getRequestDispatcher(pattern); assertNotNull(dispatcher); dispatcher.forward(requestMock, mockResponse); @@ -199,8 +190,7 @@ IllegalStateException expected = null; try { forwardToManagedServletFailureOnCommittedBuffer(); - } - catch (IllegalStateException ise) { + } catch (IllegalStateException ise) { expected = ise; } finally { assertNotNull("Expected IllegalStateException was not thrown", expected); @@ -210,60 +200,58 @@ public final void forwardToManagedServletFailureOnCommittedBuffer() throws IOException, ServletException { String pattern = "blah.html"; - final ServletDefinition servletDefinition = new ServletDefinition(pattern, - Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), - new HashMap(), null); + final ServletDefinition servletDefinition = + new ServletDefinition( + Key.get(HttpServlet.class), + UriPatternType.get(UriPatternType.SERVLET, pattern), + new HashMap(), + null); final Injector injector = createMock(Injector.class); final Binding binding = createMock(Binding.class); final HttpServletRequest mockRequest = createMock(HttpServletRequest.class); final HttpServletResponse mockResponse = createMock(HttpServletResponse.class); - expect(mockResponse.isCommitted()) - .andReturn(true); - - final HttpServlet mockServlet = new HttpServlet() { - protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse) - throws ServletException, IOException { + expect(mockResponse.isCommitted()).andReturn(true); - final Object o = request.getAttribute(A_KEY); - assertEquals("Wrong attrib returned - " + o, A_VALUE, o); - } - }; + final HttpServlet mockServlet = + new HttpServlet() { + @Override + protected void service( + HttpServletRequest request, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + + final Object o = request.getAttribute(A_KEY); + assertEquals("Wrong attrib returned - " + o, A_VALUE, o); + } + }; - expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) - .andReturn(true); - expect(injector.getBinding(Key.get(HttpServlet.class))) - .andReturn(binding); + expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())).andReturn(true); + expect(injector.getBinding(Key.get(HttpServlet.class))).andReturn(binding); - expect(injector.getInstance(Key.get(HttpServlet.class))) - .andReturn(mockServlet); + expect(injector.getInstance(Key.get(HttpServlet.class))).andReturn(mockServlet); - - final Key servetDefsKey = Key - .get(TypeLiteral.get(ServletDefinition.class)); + final Key servetDefsKey = Key.get(TypeLiteral.get(ServletDefinition.class)); Binding mockBinding = createMock(Binding.class); expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral()))) .andReturn(ImmutableList.>of(mockBinding)); Provider bindingProvider = Providers.of(servletDefinition); - expect(mockBinding.getProvider()) - .andReturn(bindingProvider); + expect(mockBinding.getProvider()).andReturn(bindingProvider); replay(injector, binding, mockRequest, mockResponse, mockBinding); // Have to init the Servlet before we can dispatch to it. servletDefinition.init(null, injector, Sets.newIdentityHashSet()); - final RequestDispatcher dispatcher = new ManagedServletPipeline(injector) - .getRequestDispatcher(pattern); + final RequestDispatcher dispatcher = + new ManagedServletPipeline(injector).getRequestDispatcher(pattern); assertNotNull(dispatcher); try { dispatcher.forward(mockRequest, mockResponse); - } - finally { + } finally { verify(injector, mockRequest, mockResponse, mockBinding); } } @@ -301,7 +289,6 @@ assertEquals("http://the.server/new-uri", wrappedRequest.getRequestURL().toString()); } - public final void testWrappedRequestUrlDefaultHttpsPort() { final HttpServletRequest mockRequest = createMock(HttpServletRequest.class); expect(mockRequest.getScheme()).andReturn("https"); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,14 +36,12 @@ import com.google.inject.spi.Elements; import com.google.inject.spi.PrivateElements; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.List; import java.util.Map; +import junit.framework.TestCase; /** * Tests for {@link ServletScopes}. @@ -60,30 +58,32 @@ final Key f = Key.get(String.class, named("F")); final Key g = Key.get(String.class, named("G")); - Module requestScopedBindings = new AbstractModule() { - @Override - protected void configure() { - bind(a).to(b); - bind(b).to(c); - bind(c).toProvider(Providers.of("c")).in(ServletScopes.REQUEST); - bind(d).toProvider(Providers.of("d")).in(RequestScoped.class); - bind(e).to(AnnotatedRequestScopedClass.class); - install(new PrivateModule() { + Module requestScopedBindings = + new AbstractModule() { @Override protected void configure() { - bind(f).toProvider(Providers.of("f")).in(RequestScoped.class); - expose(f); + bind(a).to(b); + bind(b).to(c); + bind(c).toProvider(Providers.of("c")).in(ServletScopes.REQUEST); + bind(d).toProvider(Providers.of("d")).in(RequestScoped.class); + bind(e).to(AnnotatedRequestScopedClass.class); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(f).toProvider(Providers.of("f")).in(RequestScoped.class); + expose(f); + } + }); } - }); - } - @Provides - @Named("G") - @RequestScoped - String provideG() { - return "g"; - } - }; + @Provides + @Named("G") + @RequestScoped + String provideG() { + return "g"; + } + }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(requestScopedBindings); @@ -120,34 +120,36 @@ final Key i = Key.get(String.class, named("I")); final Key j = Key.get(String.class, named("J")); - Module requestScopedBindings = new AbstractModule() { - @Override - protected void configure() { - bind(a).to(b); - bind(b).to(c); - bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); - bind(d).toInstance("d"); - bind(e).toProvider(Providers.of("e")).asEagerSingleton(); - bind(f).toProvider(Providers.of("f")).in(Scopes.SINGLETON); - bind(g).toProvider(Providers.of("g")).in(Singleton.class); - bind(h).toProvider(Providers.of("h")).in(CustomScoped.class); - bindScope(CustomScoped.class, Scopes.NO_SCOPE); - install(new PrivateModule() { + Module requestScopedBindings = + new AbstractModule() { @Override protected void configure() { - bind(i).toProvider(Providers.of("i")).in(CustomScoped.class); - expose(i); + bind(a).to(b); + bind(b).to(c); + bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); + bind(d).toInstance("d"); + bind(e).toProvider(Providers.of("e")).asEagerSingleton(); + bind(f).toProvider(Providers.of("f")).in(Scopes.SINGLETON); + bind(g).toProvider(Providers.of("g")).in(Singleton.class); + bind(h).toProvider(Providers.of("h")).in(CustomScoped.class); + bindScope(CustomScoped.class, Scopes.NO_SCOPE); + install( + new PrivateModule() { + @Override + protected void configure() { + bind(i).toProvider(Providers.of("i")).in(CustomScoped.class); + expose(i); + } + }); } - }); - } - @Provides - @Named("J") - @CustomScoped - String provideJ() { - return "j"; - } - }; + @Provides + @Named("J") + @CustomScoped + String provideJ() { + return "j"; + } + }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(requestScopedBindings); @@ -179,7 +181,7 @@ @RequestScoped static class AnnotatedRequestScopedClass {} - @Target({ ElementType.TYPE, ElementType.METHOD }) + @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RUNTIME) @ScopeAnnotation private @interface CustomScoped {} diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ package com.google.inject.servlet; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; @@ -23,14 +24,10 @@ import com.google.inject.Injector; import com.google.inject.Stage; import com.google.inject.spi.DefaultBindingTargetVisitor; - -import junit.framework.AssertionFailedError; - import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; - import javax.servlet.Filter; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; @@ -39,14 +36,14 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import junit.framework.AssertionFailedError; /** * A visitor for testing the servlet SPI extension. * * @author sameb@google.com (Sam Berlin) */ -class ServletSpiVisitor - extends DefaultBindingTargetVisitor +class ServletSpiVisitor extends DefaultBindingTargetVisitor implements ServletModuleTargetVisitor { int otherCount = 0; @@ -59,34 +56,47 @@ ServletSpiVisitor(boolean forInjector) { ImmutableSet.Builder builder = ImmutableSet.builder(); // always ignore these things... - builder.add(ServletRequest.class, - ServletResponse.class, ManagedFilterPipeline.class, ManagedServletPipeline.class, - FilterPipeline.class, ServletContext.class, HttpServletRequest.class, Filter.class, - HttpServletResponse.class, HttpSession.class, Map.class, HttpServlet.class, + builder.add( + ServletRequest.class, + ServletResponse.class, + ManagedFilterPipeline.class, + ManagedServletPipeline.class, + FilterPipeline.class, + ServletContext.class, + HttpServletRequest.class, + Filter.class, + HttpServletResponse.class, + HttpSession.class, + Map.class, + HttpServlet.class, InternalServletModule.BackwardsCompatibleServletContextProvider.class, GuiceFilter.class); - if(forInjector) { + if (forInjector) { // only ignore these if this is for the live injector, any other time it'd be an error! builder.add(Injector.class, Stage.class, Logger.class); } this.allowedClasses = builder.build(); } + @Override public Integer visit(InstanceFilterBinding binding) { actual.add(new Params(binding, binding.getFilterInstance())); return currentCount++; } + @Override public Integer visit(InstanceServletBinding binding) { actual.add(new Params(binding, binding.getServletInstance())); return currentCount++; } + @Override public Integer visit(LinkedFilterBinding binding) { actual.add(new Params(binding, binding.getLinkedKey())); return currentCount++; } + @Override public Integer visit(LinkedServletBinding binding) { actual.add(new Params(binding, binding.getLinkedKey())); return currentCount++; @@ -94,7 +104,7 @@ @Override protected Integer visitOther(Binding binding) { - if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) { + if (!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) { throw new AssertionFailedError("invalid other binding: " + binding); } otherCount++; @@ -123,8 +133,8 @@ @Override public boolean equals(Object obj) { - if(obj instanceof Params) { - Params o = (Params)obj; + if (obj instanceof Params) { + Params o = (Params) obj; return Objects.equal(pattern, o.pattern) && Objects.equal(keyOrInstance, o.keyOrInstance) && Objects.equal(params, o.params) @@ -141,12 +151,12 @@ @Override public String toString() { - return Objects.toStringHelper(Params.class) - .add("pattern", pattern) - .add("keyOrInstance", keyOrInstance) - .add("initParams", params) - .add("patternType", patternType) - .toString(); + return MoreObjects.toStringHelper(Params.class) + .add("pattern", pattern) + .add("keyOrInstance", keyOrInstance) + .add("initParams", params) + .add("patternType", patternType) + .toString(); } } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,15 +43,11 @@ import com.google.inject.name.Names; import com.google.inject.servlet.ServletScopes.NullObject; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.io.IOException; import java.io.Serializable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.Map; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -64,15 +60,14 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpSession; +import junit.framework.TestCase; -/** - * @author crazybob@google.com (Bob Lee) - */ +/** @author crazybob@google.com (Bob Lee) */ public class ServletTest extends TestCase { private static final Key HTTP_REQ_KEY = Key.get(HttpServletRequest.class); private static final Key HTTP_RESP_KEY = Key.get(HttpServletResponse.class); - private static final Key> REQ_PARAMS_KEY - = new Key>(RequestParameters.class) {}; + private static final Key> REQ_PARAMS_KEY = + new Key>(RequestParameters.class) {}; private static final Key IN_REQUEST_NULL_KEY = Key.get(InRequest.class, Null.class); private static final Key IN_SESSION_KEY = Key.get(InSession.class); @@ -83,36 +78,55 @@ //we need to clear the reference to the pipeline every test =( GuiceFilter.reset(); } - + public void testScopeExceptions() throws Exception { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - install(new ServletModule()); - } - @Provides @RequestScoped String provideString() { return "foo"; } - @Provides @SessionScoped Integer provideInteger() { return 1; } - @Provides @RequestScoped @Named("foo") String provideNamedString() { return "foo"; } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(new ServletModule()); + } + + @Provides + @RequestScoped + String provideString() { + return "foo"; + } + + @Provides + @SessionScoped + Integer provideInteger() { + return 1; + } + + @Provides + @RequestScoped + @Named("foo") + String provideNamedString() { + return "foo"; + } + }); + try { injector.getInstance(String.class); fail(); - } catch(ProvisionException oose) { + } catch (ProvisionException oose) { assertContains(oose.getMessage(), "Cannot access scoped [java.lang.String]."); } - + try { injector.getInstance(Integer.class); fail(); - } catch(ProvisionException oose) { + } catch (ProvisionException oose) { assertContains(oose.getMessage(), "Cannot access scoped [java.lang.Integer]."); } - + Key key = Key.get(String.class, Names.named("foo")); try { injector.getInstance(key); fail(); - } catch(ProvisionException oose) { + } catch (ProvisionException oose) { assertContains(oose.getMessage(), "Cannot access scoped [" + Errors.convert(key) + "]"); } } @@ -124,21 +138,22 @@ final boolean[] invoked = new boolean[1]; GuiceFilter filter = new GuiceFilter(); - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - invoked[0] = true; - assertSame(request, servletRequest); - assertSame(request, injector.getInstance(ServletRequest.class)); - assertSame(request, injector.getInstance(HTTP_REQ_KEY)); - - assertSame(response, servletResponse); - assertSame(response, injector.getInstance(ServletResponse.class)); - assertSame(response, injector.getInstance(HTTP_RESP_KEY)); - - assertSame(servletRequest.getParameterMap(), injector.getInstance(REQ_PARAMS_KEY)); - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + invoked[0] = true; + assertSame(request, servletRequest); + assertSame(request, injector.getInstance(ServletRequest.class)); + assertSame(request, injector.getInstance(HTTP_REQ_KEY)); + + assertSame(response, servletResponse); + assertSame(response, injector.getInstance(ServletResponse.class)); + assertSame(response, injector.getInstance(HTTP_RESP_KEY)); + + assertSame(servletRequest.getParameterMap(), injector.getInstance(REQ_PARAMS_KEY)); + } + }; filter.doFilter(request, response, filterChain); assertTrue(invoked[0]); @@ -146,72 +161,85 @@ public void testRequestAndResponseBindings_wrappingFilter() throws Exception { final HttpServletRequest request = newFakeHttpServletRequest(); - final ImmutableMap wrappedParamMap - = ImmutableMap.of("wrap", new String[]{"a", "b"}); - final HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) { - @Override public Map getParameterMap() { - return wrappedParamMap; - } - - @Override public Object getAttribute(String attr) { - // Ensure that attributes are stored on the original request object. - throw new UnsupportedOperationException(); - } - }; + final ImmutableMap wrappedParamMap = + ImmutableMap.of("wrap", new String[] {"a", "b"}); + final HttpServletRequestWrapper requestWrapper = + new HttpServletRequestWrapper(request) { + @Override + public Map getParameterMap() { + return wrappedParamMap; + } + + @Override + public Object getAttribute(String attr) { + // Ensure that attributes are stored on the original request object. + throw new UnsupportedOperationException(); + } + }; final HttpServletResponse response = newFakeHttpServletResponse(); final HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response); final boolean[] filterInvoked = new boolean[1]; - final Injector injector = createInjector(new ServletModule() { - @Override protected void configureServlets() { - filter("/*").through(new Filter() { - @Inject Provider servletReqProvider; - @Inject Provider reqProvider; - @Inject Provider servletRespProvider; - @Inject Provider respProvider; - - public void init(FilterConfig filterConfig) {} + final Injector injector = + createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + filter("/*") + .through( + new Filter() { + @Inject Provider servletReqProvider; + @Inject Provider reqProvider; + @Inject Provider servletRespProvider; + @Inject Provider respProvider; + + @Override + public void init(FilterConfig filterConfig) {} + + @Override + public void doFilter( + ServletRequest req, ServletResponse resp, FilterChain chain) + throws IOException, ServletException { + filterInvoked[0] = true; + assertSame(req, servletReqProvider.get()); + assertSame(req, reqProvider.get()); + + assertSame(resp, servletRespProvider.get()); + assertSame(resp, respProvider.get()); + + chain.doFilter(requestWrapper, responseWrapper); + + assertSame(req, reqProvider.get()); + assertSame(resp, respProvider.get()); + } + + @Override + public void destroy() {} + }); + } + }); - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) - throws IOException, ServletException { - filterInvoked[0] = true; - assertSame(req, servletReqProvider.get()); - assertSame(req, reqProvider.get()); - - assertSame(resp, servletRespProvider.get()); - assertSame(resp, respProvider.get()); + GuiceFilter filter = new GuiceFilter(); + final boolean[] chainInvoked = new boolean[1]; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + chainInvoked[0] = true; + assertSame(requestWrapper, servletRequest); + assertSame(requestWrapper, injector.getInstance(ServletRequest.class)); + assertSame(requestWrapper, injector.getInstance(HTTP_REQ_KEY)); + + assertSame(responseWrapper, servletResponse); + assertSame(responseWrapper, injector.getInstance(ServletResponse.class)); + assertSame(responseWrapper, injector.getInstance(HTTP_RESP_KEY)); - chain.doFilter(requestWrapper, responseWrapper); + assertSame(servletRequest.getParameterMap(), injector.getInstance(REQ_PARAMS_KEY)); - assertSame(req, reqProvider.get()); - assertSame(resp, respProvider.get()); + InRequest inRequest = injector.getInstance(InRequest.class); + assertSame(inRequest, injector.getInstance(InRequest.class)); } - - public void destroy() {} - }); - } - }); - - GuiceFilter filter = new GuiceFilter(); - final boolean[] chainInvoked = new boolean[1]; - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - chainInvoked[0] = true; - assertSame(requestWrapper, servletRequest); - assertSame(requestWrapper, injector.getInstance(ServletRequest.class)); - assertSame(requestWrapper, injector.getInstance(HTTP_REQ_KEY)); - - assertSame(responseWrapper, servletResponse); - assertSame(responseWrapper, injector.getInstance(ServletResponse.class)); - assertSame(responseWrapper, injector.getInstance(HTTP_RESP_KEY)); - - assertSame(servletRequest.getParameterMap(), injector.getInstance(REQ_PARAMS_KEY)); - - InRequest inRequest = injector.getInstance(InRequest.class); - assertSame(inRequest, injector.getInstance(InRequest.class)); - } - }; + }; filter.doFilter(request, response, filterChain); assertTrue(chainInvoked[0]); @@ -221,157 +249,173 @@ public void testRequestAndResponseBindings_matchesPassedParameters() throws Exception { final int[] filterInvoked = new int[1]; final boolean[] servletInvoked = new boolean[1]; - createInjector(new ServletModule() { - @Override protected void configureServlets() { - final HttpServletRequest[] previousReq = new HttpServletRequest[1]; - final HttpServletResponse[] previousResp = new HttpServletResponse[1]; - - final Provider servletReqProvider = getProvider(ServletRequest.class); - final Provider reqProvider = getProvider(HttpServletRequest.class); - final Provider servletRespProvider = getProvider(ServletResponse.class); - final Provider respProvider = getProvider(HttpServletResponse.class); - - Filter filter = new Filter() { - public void init(FilterConfig filterConfig) {} - - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) - throws IOException, ServletException { - filterInvoked[0]++; - assertSame(req, servletReqProvider.get()); - assertSame(req, reqProvider.get()); - if (previousReq[0] != null) { - assertEquals(req, previousReq[0]); - } - - assertSame(resp, servletRespProvider.get()); - assertSame(resp, respProvider.get()); - if (previousResp[0] != null) { - assertEquals(resp, previousResp[0]); - } - - chain.doFilter( - previousReq[0] = new HttpServletRequestWrapper((HttpServletRequest) req), - previousResp[0] = new HttpServletResponseWrapper((HttpServletResponse) resp)); - - assertSame(req, reqProvider.get()); - assertSame(resp, respProvider.get()); - } - - public void destroy() {} - }; - - filter("/*").through(filter); - filter("/*").through(filter); // filter twice to test wrapping in filters - serve("/*").with(new HttpServlet() { - @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) { - servletInvoked[0] = true; - assertSame(req, servletReqProvider.get()); - assertSame(req, reqProvider.get()); - - assertSame(resp, servletRespProvider.get()); - assertSame(resp, respProvider.get()); + createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + final HttpServletRequest[] previousReq = new HttpServletRequest[1]; + final HttpServletResponse[] previousResp = new HttpServletResponse[1]; + + final Provider servletReqProvider = getProvider(ServletRequest.class); + final Provider reqProvider = getProvider(HttpServletRequest.class); + final Provider servletRespProvider = + getProvider(ServletResponse.class); + final Provider respProvider = + getProvider(HttpServletResponse.class); + + Filter filter = + new Filter() { + @Override + public void init(FilterConfig filterConfig) {} + + @Override + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) + throws IOException, ServletException { + filterInvoked[0]++; + assertSame(req, servletReqProvider.get()); + assertSame(req, reqProvider.get()); + if (previousReq[0] != null) { + assertEquals(req, previousReq[0]); + } + + assertSame(resp, servletRespProvider.get()); + assertSame(resp, respProvider.get()); + if (previousResp[0] != null) { + assertEquals(resp, previousResp[0]); + } + + chain.doFilter( + previousReq[0] = new HttpServletRequestWrapper((HttpServletRequest) req), + previousResp[0] = + new HttpServletResponseWrapper((HttpServletResponse) resp)); + + assertSame(req, reqProvider.get()); + assertSame(resp, respProvider.get()); + } + + @Override + public void destroy() {} + }; + + filter("/*").through(filter); + filter("/*").through(filter); // filter twice to test wrapping in filters + serve("/*") + .with( + new HttpServlet() { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + servletInvoked[0] = true; + assertSame(req, servletReqProvider.get()); + assertSame(req, reqProvider.get()); + + assertSame(resp, servletRespProvider.get()); + assertSame(resp, respProvider.get()); + } + }); } }); - } - }); GuiceFilter filter = new GuiceFilter(); - filter.doFilter(newFakeHttpServletRequest(), newFakeHttpServletResponse(), new FilterChain() { - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { - throw new IllegalStateException("Shouldn't get here"); - } - }); + filter.doFilter( + newFakeHttpServletRequest(), + newFakeHttpServletResponse(), + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + throw new IllegalStateException("Shouldn't get here"); + } + }); assertEquals(2, filterInvoked[0]); assertTrue(servletInvoked[0]); } - public void testNewRequestObject() - throws CreationException, IOException, ServletException { + public void testNewRequestObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); final HttpServletRequest request = newFakeHttpServletRequest(); GuiceFilter filter = new GuiceFilter(); final boolean[] invoked = new boolean[1]; - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - invoked[0] = true; - assertNotNull(injector.getInstance(InRequest.class)); - assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + invoked[0] = true; + assertNotNull(injector.getInstance(InRequest.class)); + assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); + } + }; filter.doFilter(request, null, filterChain); assertTrue(invoked[0]); } - public void testExistingRequestObject() - throws CreationException, IOException, ServletException { + public void testExistingRequestObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); final HttpServletRequest request = newFakeHttpServletRequest(); GuiceFilter filter = new GuiceFilter(); final boolean[] invoked = new boolean[1]; - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - invoked[0] = true; - - InRequest inRequest = injector.getInstance(InRequest.class); - assertSame(inRequest, injector.getInstance(InRequest.class)); - - assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); - assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + invoked[0] = true; + + InRequest inRequest = injector.getInstance(InRequest.class); + assertSame(inRequest, injector.getInstance(InRequest.class)); + + assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); + assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); + } + }; filter.doFilter(request, null, filterChain); assertTrue(invoked[0]); } - public void testNewSessionObject() - throws CreationException, IOException, ServletException { + public void testNewSessionObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); final HttpServletRequest request = newFakeHttpServletRequest(); GuiceFilter filter = new GuiceFilter(); final boolean[] invoked = new boolean[1]; - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - invoked[0] = true; - assertNotNull(injector.getInstance(InSession.class)); - assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + invoked[0] = true; + assertNotNull(injector.getInstance(InSession.class)); + assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); + } + }; filter.doFilter(request, null, filterChain); assertTrue(invoked[0]); } - public void testExistingSessionObject() - throws CreationException, IOException, ServletException { + public void testExistingSessionObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); final HttpServletRequest request = newFakeHttpServletRequest(); GuiceFilter filter = new GuiceFilter(); final boolean[] invoked = new boolean[1]; - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - invoked[0] = true; - - InSession inSession = injector.getInstance(InSession.class); - assertSame(inSession, injector.getInstance(InSession.class)); - - assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); - assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + invoked[0] = true; + + InSession inSession = injector.getInstance(InSession.class); + assertSame(inSession, injector.getInstance(InSession.class)); + + assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); + assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); + } + }; filter.doFilter(request, null, filterChain); @@ -385,14 +429,15 @@ GuiceFilter filter = new GuiceFilter(); final boolean[] invoked = new boolean[1]; - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - invoked[0] = true; - assertNotNull(injector.getInstance(InSession.class)); - assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + invoked[0] = true; + assertNotNull(injector.getInstance(InSession.class)); + assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); + } + }; filter.doFilter(request, null, filterChain); @@ -409,22 +454,29 @@ public void testGuiceFilterConstructors() throws Exception { final RuntimeException servletException = new RuntimeException(); final RuntimeException chainException = new RuntimeException(); - final Injector injector = createInjector(new ServletModule() { - @Override protected void configureServlets() { - serve("/*").with(new HttpServlet() { - @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) { - throw servletException; - } - }); - } - }); + final Injector injector = + createInjector( + new ServletModule() { + @Override + protected void configureServlets() { + serve("/*") + .with( + new HttpServlet() { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + throw servletException; + } + }); + } + }); final HttpServletRequest request = newFakeHttpServletRequest(); - FilterChain filterChain = new FilterChain() { - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse) { - throw chainException; - } - }; + FilterChain filterChain = + new FilterChain() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { + throw chainException; + } + }; try { new GuiceFilter().doFilter(request, null, filterChain); @@ -439,7 +491,8 @@ assertSame(servletException, e); } try { - injector.getInstance(Key.get(GuiceFilter.class, ScopingOnly.class)) + injector + .getInstance(Key.get(GuiceFilter.class, ScopingOnly.class)) .doFilter(request, null, filterChain); fail(); } catch (RuntimeException e) { @@ -448,16 +501,23 @@ } private Injector createInjector(Module... modules) throws CreationException { - return Guice.createInjector(Lists.asList(new AbstractModule() { - @Override - protected void configure() { - install(new ServletModule()); - bind(InSession.class); - bind(IN_SESSION_NULL_KEY).toProvider(Providers.of(null)).in(SessionScoped.class); - bind(InRequest.class); - bind(IN_REQUEST_NULL_KEY).toProvider(Providers.of(null)).in(RequestScoped.class); - } - }, modules)); + return Guice.createInjector( + Lists.asList( + new AbstractModule() { + @Override + protected void configure() { + install(new ServletModule()); + bind(InSession.class); + bind(IN_SESSION_NULL_KEY) + .toProvider(Providers.of(null)) + .in(SessionScoped.class); + bind(InRequest.class); + bind(IN_REQUEST_NULL_KEY) + .toProvider(Providers.of(null)) + .in(RequestScoped.class); + } + }, + modules)); } @SessionScoped @@ -466,6 +526,8 @@ @RequestScoped static class InRequest {} - @BindingAnnotation @Retention(RUNTIME) @Target({PARAMETER, METHOD, FIELD}) + @BindingAnnotation + @Retention(RUNTIME) + @Target({PARAMETER, METHOD, FIELD}) @interface Null {} } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java 2018-04-03 18:18:08.000000000 +0000 @@ -4,13 +4,11 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; - import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Map; - import javax.servlet.FilterChain; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -21,84 +19,93 @@ /** * Utilities for servlet tests. - * + * * @author sameb@google.com (Sam Berlin) */ public class ServletTestUtils { - + private ServletTestUtils() {} private static class ThrowingInvocationHandler implements InvocationHandler { + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { throw new UnsupportedOperationException("No methods are supported on this object"); } } - - /** - * Returns a FilterChain that does nothing. - */ + + /** Returns a FilterChain that does nothing. */ public static FilterChain newNoOpFilterChain() { return new FilterChain() { - public void doFilter(ServletRequest request, ServletResponse response) { - } + @Override + public void doFilter(ServletRequest request, ServletResponse response) {} }; } - - /** - * Returns a fake, HttpServletRequest which stores attributes in a HashMap. - */ + + /** Returns a fake, HttpServletRequest which stores attributes in a HashMap. */ public static HttpServletRequest newFakeHttpServletRequest() { - HttpServletRequest delegate = (HttpServletRequest) Proxy.newProxyInstance( - HttpServletRequest.class.getClassLoader(), - new Class[] { HttpServletRequest.class }, new ThrowingInvocationHandler()); - + HttpServletRequest delegate = + (HttpServletRequest) + Proxy.newProxyInstance( + HttpServletRequest.class.getClassLoader(), + new Class[] {HttpServletRequest.class}, + new ThrowingInvocationHandler()); + return new HttpServletRequestWrapper(delegate) { - final Map attributes = Maps.newHashMap(); + final Map attributes = Maps.newHashMap(); final HttpSession session = newFakeHttpSession(); - @Override public String getMethod() { + @Override + public String getMethod() { return "GET"; } - @Override public Object getAttribute(String name) { + @Override + public Object getAttribute(String name) { return attributes.get(name); } - - @Override public void setAttribute(String name, Object value) { + + @Override + public void setAttribute(String name, Object value) { attributes.put(name, value); } - - @Override public Map getParameterMap() { + + @Override + public Map getParameterMap() { return ImmutableMap.of(); } - - @Override public String getRequestURI() { + + @Override + public String getRequestURI() { return "/"; } - - @Override public String getContextPath() { + + @Override + public String getContextPath() { return ""; } - - @Override public HttpSession getSession() { + + @Override + public HttpSession getSession() { return session; } }; } - + /** - * Returns a fake, HttpServletResponse which throws an exception if any of its - * methods are called. + * Returns a fake, HttpServletResponse which throws an exception if any of its methods are called. */ public static HttpServletResponse newFakeHttpServletResponse() { - return (HttpServletResponse) Proxy.newProxyInstance( - HttpServletResponse.class.getClassLoader(), - new Class[] { HttpServletResponse.class }, new ThrowingInvocationHandler()); - } - + return (HttpServletResponse) + Proxy.newProxyInstance( + HttpServletResponse.class.getClassLoader(), + new Class[] {HttpServletResponse.class}, + new ThrowingInvocationHandler()); + } + private static class FakeHttpSessionHandler implements InvocationHandler, Serializable { final Map attributes = Maps.newHashMap(); + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if ("setAttribute".equals(name)) { @@ -112,12 +119,12 @@ } } - /** - * Returns a fake, serializable HttpSession which stores attributes in a HashMap. - */ + /** Returns a fake, serializable HttpSession which stores attributes in a HashMap. */ public static HttpSession newFakeHttpSession() { - return (HttpSession) Proxy.newProxyInstance(HttpSession.class.getClassLoader(), - new Class[] { HttpSession.class }, new FakeHttpSessionHandler()); + return (HttpSession) + Proxy.newProxyInstance( + HttpSession.class.getClassLoader(), + new Class[] {HttpSession.class}, + new FakeHttpSessionHandler()); } - } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,14 +1,14 @@ // Copyright 2012 Google Inc. All Rights Reserved. package com.google.inject.servlet; + import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; -import junit.framework.TestCase; - import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** * Unit test for the servlet utility class. @@ -17,42 +17,45 @@ */ public class ServletUtilsTest extends TestCase { public void testGetContextRelativePath() { - HttpServletRequest servletRequest = createMock(HttpServletRequest.class); - expect(servletRequest.getContextPath()).andReturn("/a_context_path"); - expect(servletRequest.getRequestURI()).andReturn("/a_context_path/test.html"); - replay(servletRequest); - String path = ServletUtils.getContextRelativePath(servletRequest); - assertEquals("/test.html", path); - verify(servletRequest); + assertEquals( + "/test.html", getContextRelativePath("/a_context_path", "/a_context_path/test.html")); + assertEquals("/test.html", getContextRelativePath("", "/test.html")); + assertEquals("/test.html", getContextRelativePath("", "/foo/../test.html")); + assertEquals("/test.html", getContextRelativePath("", "/././foo/../test.html")); + assertEquals("/test.html", getContextRelativePath("", "/foo/../../../../test.html")); + assertEquals("/test.html", getContextRelativePath("", "/foo/%2E%2E/test.html")); + // %2E == '.' + assertEquals("/test.html", getContextRelativePath("", "/foo/%2E%2E/test.html")); + // %2F == '/' + assertEquals("/foo/%2F/test.html", getContextRelativePath("", "/foo/%2F/test.html")); + // %66 == 'f' + assertEquals("/foo.html", getContextRelativePath("", "/%66oo.html")); + } + + public void testGetContextRelativePath_preserveQuery() { + assertEquals("/foo?q=f", getContextRelativePath("", "/foo?q=f")); + assertEquals("/foo?q=%20+%20", getContextRelativePath("", "/foo?q=%20+%20")); } public void testGetContextRelativePathWithWrongPath() { - HttpServletRequest servletRequest = createMock(HttpServletRequest.class); - expect(servletRequest.getContextPath()).andReturn("/a_context_path"); - expect(servletRequest.getRequestURI()).andReturn("/test.html"); - replay(servletRequest); - String path = ServletUtils.getContextRelativePath(servletRequest); - assertNull(path); - verify(servletRequest); + assertNull(getContextRelativePath("/a_context_path", "/test.html")); } public void testGetContextRelativePathWithRootPath() { - HttpServletRequest servletRequest = createMock(HttpServletRequest.class); - expect(servletRequest.getContextPath()).andReturn("/a_context_path"); - expect(servletRequest.getRequestURI()).andReturn("/a_context_path"); - replay(servletRequest); - String path = ServletUtils.getContextRelativePath(servletRequest); - assertEquals("/", path); - verify(servletRequest); + assertEquals("/", getContextRelativePath("/a_context_path", "/a_context_path")); } public void testGetContextRelativePathWithEmptyPath() { - HttpServletRequest servletRequest = createMock(HttpServletRequest.class); - expect(servletRequest.getContextPath()).andReturn(""); - expect(servletRequest.getRequestURI()).andReturn(""); - replay(servletRequest); - String path = ServletUtils.getContextRelativePath(servletRequest); - assertNull(path); - verify(servletRequest); + assertNull(getContextRelativePath("", "")); + } + + private String getContextRelativePath(String contextPath, String requestPath) { + HttpServletRequest mock = createMock(HttpServletRequest.class); + expect(mock.getContextPath()).andReturn(contextPath); + expect(mock.getRequestURI()).andReturn(requestPath); + replay(mock); + String contextRelativePath = ServletUtils.getContextRelativePath(mock); + verify(mock); + return contextRelativePath; } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,63 +23,80 @@ import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.Provides; - -import junit.framework.TestCase; - import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import junit.framework.TestCase; // TODO: Add test for HTTP transferring. -/** - * Tests transferring of entire request scope. - */ +/** Tests transferring of entire request scope. */ public class TransferRequestIntegrationTest extends TestCase { - private final Callable FALSE_CALLABLE = new Callable() { - @Override public Boolean call() { - return false; - } - }; + private final Callable FALSE_CALLABLE = + new Callable() { + @Override + public Boolean call() { + return false; + } + }; public void testTransferHttp_outOfScope() { try { ServletScopes.transferRequest(FALSE_CALLABLE); fail(); - } catch (OutOfScopeException expected) {} + } catch (OutOfScopeException expected) { + } } public void testTransferNonHttp_outOfScope() { try { ServletScopes.transferRequest(FALSE_CALLABLE); fail(); - } catch (OutOfScopeException expected) {} + } catch (OutOfScopeException expected) { + } + } + + public void testTransferNonHttp_outOfScope_closeable() { + try { + ServletScopes.transferRequest(); + fail(); + } catch (OutOfScopeException expected) { + } } public void testTransferNonHttpRequest() throws Exception { - final Injector injector = Guice.createInjector(new AbstractModule() { - @Override protected void configure() { - bindScope(RequestScoped.class, ServletScopes.REQUEST); - } - - @Provides @RequestScoped Object provideObject() { - return new Object(); - } - }); - - Callable> callable = new Callable>() { - @Override public Callable call() { - final Object original = injector.getInstance(Object.class); - return ServletScopes.transferRequest(new Callable() { - @Override public Boolean call() { - return original == injector.getInstance(Object.class); - } - }); - } - }; + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(RequestScoped.class, ServletScopes.REQUEST); + } + + @Provides + @RequestScoped + Object provideObject() { + return new Object(); + } + }); + + Callable> callable = + new Callable>() { + @Override + public Callable call() { + final Object original = injector.getInstance(Object.class); + return ServletScopes.transferRequest( + new Callable() { + @Override + public Boolean call() { + return original == injector.getInstance(Object.class); + } + }); + } + }; ImmutableMap, Object> seedMap = ImmutableMap.of(); Callable transfer = ServletScopes.scopeRequest(callable, seedMap).call(); @@ -89,33 +106,137 @@ executor.shutdownNow(); } + public void testTransferNonHttpRequest_closeable() throws Exception { + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindScope(RequestScoped.class, ServletScopes.REQUEST); + } + + @Provides + @RequestScoped + Object provideObject() { + return new Object(); + } + }); + + class Data { + Object object; + RequestScoper scoper; + } + + Callable callable = + new Callable() { + @Override + public Data call() { + Data data = new Data(); + data.object = injector.getInstance(Object.class); + data.scoper = ServletScopes.transferRequest(); + return data; + } + }; + + ImmutableMap, Object> seedMap = ImmutableMap.of(); + Data data = ServletScopes.scopeRequest(callable, seedMap).call(); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + RequestScoper.CloseableScope scope = data.scoper.open(); + try { + assertSame(data.object, injector.getInstance(Object.class)); + } finally { + scope.close(); + executor.shutdownNow(); + } + } + public void testTransferNonHttpRequest_concurrentUseBlocks() throws Exception { - Callable callable = new Callable() { - @Override public Boolean call() throws Exception { - ExecutorService executor = Executors.newSingleThreadExecutor(); - try { - Future future = executor.submit(ServletScopes.transferRequest(FALSE_CALLABLE)); - try { - return future.get(100, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - return true; + Callable callable = + new Callable() { + @Override + public Boolean call() throws Exception { + ExecutorService executor = Executors.newSingleThreadExecutor(); + try { + Future future = + executor.submit(ServletScopes.transferRequest(FALSE_CALLABLE)); + try { + return future.get(100, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + return true; + } + } finally { + executor.shutdownNow(); + } } - } finally { - executor.shutdownNow(); - } - } - }; + }; + + ImmutableMap, Object> seedMap = ImmutableMap.of(); + assertTrue(ServletScopes.scopeRequest(callable, seedMap).call()); + } + + public void testTransferNonHttpRequest_concurrentUseBlocks_closeable() throws Exception { + Callable callable = + new Callable() { + @Override + public Boolean call() throws Exception { + final RequestScoper scoper = ServletScopes.transferRequest(); + ExecutorService executor = Executors.newSingleThreadExecutor(); + try { + Future future = + executor.submit( + new Callable() { + @Override + public Boolean call() { + RequestScoper.CloseableScope scope = scoper.open(); + try { + return false; + } finally { + scope.close(); + } + } + }); + try { + return future.get(100, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + return true; + } + } finally { + executor.shutdownNow(); + } + } + }; ImmutableMap, Object> seedMap = ImmutableMap.of(); assertTrue(ServletScopes.scopeRequest(callable, seedMap).call()); } public void testTransferNonHttpRequest_concurrentUseSameThreadOk() throws Exception { - Callable callable = new Callable() { - @Override public Boolean call() throws Exception { - return ServletScopes.transferRequest(FALSE_CALLABLE).call(); - } - }; + Callable callable = + new Callable() { + @Override + public Boolean call() throws Exception { + return ServletScopes.transferRequest(FALSE_CALLABLE).call(); + } + }; + + ImmutableMap, Object> seedMap = ImmutableMap.of(); + assertFalse(ServletScopes.scopeRequest(callable, seedMap).call()); + } + + public void testTransferNonHttpRequest_concurrentUseSameThreadOk_closeable() throws Exception { + Callable callable = + new Callable() { + @Override + public Boolean call() throws Exception { + RequestScoper.CloseableScope scope = ServletScopes.transferRequest().open(); + try { + return false; + } finally { + scope.close(); + } + } + }; ImmutableMap, Object> seedMap = ImmutableMap.of(); assertFalse(ServletScopes.scopeRequest(callable, seedMap).call()); diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,10 @@ * limitations under the License. */ - package com.google.inject.servlet; +import static junit.framework.Assert.fail; + import junit.framework.TestCase; public class UriPatternTypeTest extends TestCase { @@ -56,4 +57,13 @@ assertFalse(pattern.matches("/foo")); assertFalse(pattern.matches("/foo?val=1")); } + + public void testPatternWithPercentEncodedChars_servlet() { + try { + UriPatternType.get(UriPatternType.SERVLET, "/foo/%2f/*"); + fail(); + } catch (IllegalArgumentException iae) { + assertTrue(iae.getMessage().contains("Servlet patterns cannot contain escape patterns.")); + } + } } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -9,11 +9,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -21,18 +17,17 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** + * This tests that filter stage of the pipeline dispatches correctly to guice-managed filters. * - * This tests that filter stage of the pipeline dispatches - * correctly to guice-managed filters. - * - * WARNING(dhanji): Non-parallelizable test =( + *

    WARNING(dhanji): Non-parallelizable test =( * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class VarargsFilterDispatchIntegrationTest extends TestCase { - private static int inits, doFilters, destroys; + private static int inits, doFilters, destroys; @Override public final void setUp() { @@ -43,20 +38,21 @@ GuiceFilter.reset(); } - public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - // This is actually a double match for "/*" - filter("/*", "*.html", "/*").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(TestFilter.class)); - filter("*.jsp").through(Key.get(TestFilter.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + // This is actually a double match for "/*" + filter("/*", "*.html", "/*").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(TestFilter.class)); + filter("*.jsp").through(Key.get(TestFilter.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -64,12 +60,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -78,24 +70,31 @@ verify(requestMock); - assertTrue("lifecycle states did not" - + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not" + + " fire correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, inits == 1 && doFilters == 3 && destroys == 1); } public final void testDispatchThatNoFiltersFire() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/public/*", "*.html", "*.xml").through(Key.get(TestFilter.class)); - - // These filters should never fire - filter("/index/*").through(Key.get(TestFilter.class)); - filter("*.jsp").through(Key.get(TestFilter.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/public/*", "*.html", "*.xml").through(Key.get(TestFilter.class)); + + // These filters should never fire + filter("/index/*").through(Key.get(TestFilter.class)); + filter("*.jsp").through(Key.get(TestFilter.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -103,12 +102,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.xhtml") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.xhtml").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -117,25 +112,32 @@ verify(requestMock); - assertTrue("lifecycle states did not " - + "fire correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not " + + "fire correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, inits == 1 && doFilters == 0 && destroys == 1); } - public final void testDispatchFilterPipelineWithRegexMatching() throws ServletException, - IOException { - - final Injector injector = Guice.createInjector(new ServletModule() { + public final void testDispatchFilterPipelineWithRegexMatching() + throws ServletException, IOException { - @Override - protected void configureServlets() { - filterRegex("/[A-Za-z]*", "/index").through(TestFilter.class); - - //these filters should never fire - filterRegex("\\w").through(Key.get(TestFilter.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filterRegex("/[A-Za-z]*", "/index").through(TestFilter.class); + + //these filters should never fire + filterRegex("\\w").through(Key.get(TestFilter.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); @@ -143,12 +145,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index") - .anyTimes(); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index").anyTimes(); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -157,24 +155,33 @@ verify(requestMock); - assertTrue("lifecycle states did not fire " - + "correct number of times-- inits: " + inits + "; dos: " + doFilters - + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not fire " + + "correct number of times-- inits: " + + inits + + "; dos: " + + doFilters + + "; destroys: " + + destroys, inits == 1 && doFilters == 2 && destroys == 1); } @Singleton public static class TestFilter implements Filter { + @Override public void init(FilterConfig filterConfig) throws ServletException { inits++; } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } + @Override public void destroy() { destroys++; } diff -Nru sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java --- sisu-guice-3.2.6/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,11 +25,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; - -import junit.framework.TestCase; - import java.io.IOException; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -39,10 +35,11 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; +import junit.framework.TestCase; /** - * Tests the FilterPipeline that dispatches to guice-managed servlets, - * is a full integration test, with a real injector. + * Tests the FilterPipeline that dispatches to guice-managed servlets, is a full integration test, + * with a real injector. * * @author Dhanji R. Prasanna (dhanji gmail com) */ @@ -61,16 +58,18 @@ public final void testDispatchRequestToManagedPipelineServlets() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - serve("/*", "/index.html").with(TestServlet.class); - - // These servets should never fire... (ordering test) - serve("*.html", "/o/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + serve("/*", "/index.html").with(TestServlet.class); + + // These servets should never fire... (ordering test) + serve("*.html", "/o/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -79,12 +78,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .times(1); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").times(1); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -94,23 +89,30 @@ verify(requestMock); - assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " - + services + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not fire correct number of times-- inits: " + + inits + + "; dos: " + + services + + "; destroys: " + + destroys, inits == 2 && services == 1 && destroys == 2); } public final void testVarargsSkipDispatchRequestToManagedPipelineServlets() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - serve("/notindex", "/&*", "/index.html").with(TestServlet.class); - - // These servets should never fire... (ordering test) - serve("*.html", "/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + serve("/notindex", "/&*", "/index.html").with(TestServlet.class); + + // These servets should never fire... (ordering test) + serve("*.html", "/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -119,12 +121,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .times(3); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").times(3); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -134,26 +132,32 @@ verify(requestMock); - assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " - + services + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not fire correct number of times-- inits: " + + inits + + "; dos: " + + services + + "; destroys: " + + destroys, inits == 2 && services == 1 && destroys == 2); } public final void testDispatchRequestToManagedPipelineWithFilter() throws ServletException, IOException { - final Injector injector = Guice.createInjector(new ServletModule() { - - @Override - protected void configureServlets() { - filter("/*").through(TestFilter.class); - - serve("/*").with(TestServlet.class); - - // These servets should never fire... - serve("*.html", "/y/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); - - } - }); + final Injector injector = + Guice.createInjector( + new ServletModule() { + + @Override + protected void configureServlets() { + filter("/*").through(TestFilter.class); + + serve("/*").with(TestServlet.class); + + // These servets should never fire... + serve("*.html", "/y/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); + } + }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); @@ -162,12 +166,8 @@ //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); - expect(requestMock.getRequestURI()) - .andReturn("/index.html") - .times(2); - expect(requestMock.getContextPath()) - .andReturn("") - .anyTimes(); + expect(requestMock.getRequestURI()).andReturn("/index.html").times(2); + expect(requestMock.getContextPath()).andReturn("").anyTimes(); //dispatch request replay(requestMock); @@ -178,22 +178,30 @@ verify(requestMock); - assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " - + services + "; destroys: " + destroys, + assertTrue( + "lifecycle states did not fire correct number of times-- inits: " + + inits + + "; dos: " + + services + + "; destroys: " + + destroys, inits == 3 && services == 1 && destroys == 3 && doFilters == 1); } @Singleton public static class TestServlet extends HttpServlet { + @Override public void init(ServletConfig filterConfig) throws ServletException { inits++; } + @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { services++; } + @Override public void destroy() { destroys++; } @@ -201,15 +209,18 @@ @Singleton public static class NeverServlet extends HttpServlet { + @Override public void init(ServletConfig filterConfig) throws ServletException { inits++; } + @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { fail("NeverServlet was fired, when it should not have been."); } + @Override public void destroy() { destroys++; } @@ -217,16 +228,20 @@ @Singleton public static class TestFilter implements Filter { + @Override public void init(FilterConfig filterConfig) throws ServletException { inits++; } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } + @Override public void destroy() { destroys++; } diff -Nru sisu-guice-3.2.6/extensions/spring/pom.xml sisu-guice-4.2.0/extensions/spring/pom.xml --- sisu-guice-3.2.6/extensions/spring/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/spring/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject extensions-parent - 3.2.6 + 4.2.0 guice-spring @@ -22,4 +22,18 @@ + + + + maven-jar-plugin + + + + com.google.guice.extensions.spring + + + + + + diff -Nru sisu-guice-3.2.6/extensions/spring/src/com/google/inject/spring/package-info.java sisu-guice-4.2.0/extensions/spring/src/com/google/inject/spring/package-info.java --- sisu-guice-3.2.6/extensions/spring/src/com/google/inject/spring/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/spring/src/com/google/inject/spring/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -14,7 +14,5 @@ * limitations under the License. */ -/** - * Spring integration; this extension requires {@code guice-spring-3.0.jar}. - */ -package com.google.inject.spring; \ No newline at end of file +/** Spring integration; this extension requires {@code guice-spring.jar}. */ +package com.google.inject.spring; diff -Nru sisu-guice-3.2.6/extensions/spring/src/com/google/inject/spring/SpringIntegration.java sisu-guice-4.2.0/extensions/spring/src/com/google/inject/spring/SpringIntegration.java --- sisu-guice-3.2.6/extensions/spring/src/com/google/inject/spring/SpringIntegration.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/spring/src/com/google/inject/spring/SpringIntegration.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.name.Names; - import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; @@ -35,9 +34,8 @@ private SpringIntegration() {} /** - * Creates a provider which looks up objects from Spring using the given name. - * Expects a binding to {@link - * org.springframework.beans.factory.BeanFactory}. Example usage: + * Creates a provider which looks up objects from Spring using the given name. Expects a binding + * to {@link org.springframework.beans.factory.BeanFactory}. Example usage: * *

        * bind(DataSource.class)
    @@ -49,12 +47,11 @@
       }
     
       /**
    -   * Binds all Spring beans from the given factory by name. For a Spring bean
    -   * named "foo", this method creates a binding to the bean's type and
    -   * {@code @Named("foo")}.
    +   * Binds all Spring beans from the given factory by name. For a Spring bean named "foo", this
    +   * method creates a binding to the bean's type and {@code @Named("foo")}.
        *
        * @see com.google.inject.name.Named
    -   * @see com.google.inject.name.Names#named(String) 
    +   * @see com.google.inject.name.Names#named(String)
        */
       public static void bindAll(Binder binder, ListableBeanFactory beanFactory) {
         binder = binder.skipSources(SpringIntegration.class);
    @@ -65,21 +62,17 @@
         }
       }
     
    -  static  void bindBean(Binder binder, ListableBeanFactory beanFactory,
    -      String name, Class type) {
    -    SpringProvider provider
    -        = SpringProvider.newInstance(type, name);
    +  static  void bindBean(
    +      Binder binder, ListableBeanFactory beanFactory, String name, Class type) {
    +    SpringProvider provider = SpringProvider.newInstance(type, name);
         try {
           provider.initialize(beanFactory);
    -    }
    -    catch (Exception e) {
    +    } catch (Exception e) {
           binder.addError(e);
           return;
         }
     
    -    binder.bind(type)
    -        .annotatedWith(Names.named(name))
    -        .toProvider(provider);
    +    binder.bind(type).annotatedWith(Names.named(name)).toProvider(provider);
       }
     
       static class SpringProvider implements Provider {
    @@ -101,12 +94,13 @@
         void initialize(BeanFactory beanFactory) {
           this.beanFactory = beanFactory;
           if (!beanFactory.isTypeMatch(name, type)) {
    -        throw new ClassCastException("Spring bean named '" + name
    -            + "' does not implement " + type.getName() + ".");
    +        throw new ClassCastException(
    +            "Spring bean named '" + name + "' does not implement " + type.getName() + ".");
           }
           singleton = beanFactory.isSingleton(name);
         }
     
    +    @Override
         public T get() {
           return singleton ? getSingleton() : type.cast(beanFactory.getBean(name));
         }
    diff -Nru sisu-guice-3.2.6/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java sisu-guice-4.2.0/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java
    --- sisu-guice-3.2.6/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -24,81 +24,70 @@
     import com.google.inject.Injector;
     import com.google.inject.Key;
     import com.google.inject.name.Names;
    -
     import junit.framework.TestCase;
    -
     import org.springframework.beans.factory.BeanFactory;
     import org.springframework.beans.factory.support.DefaultListableBeanFactory;
     import org.springframework.beans.factory.support.RootBeanDefinition;
     
    -/**
    - * @author crazybob@google.com (Bob Lee)
    - */
    +/** @author crazybob@google.com (Bob Lee) */
     public class SpringIntegrationTest extends TestCase {
     
       public void testBindFromSpring() throws CreationException {
    -    final DefaultListableBeanFactory beanFactory
    -        = new DefaultListableBeanFactory();
    +    final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
     
    -    RootBeanDefinition singleton
    -        = new RootBeanDefinition(Singleton.class);
    +    RootBeanDefinition singleton = new RootBeanDefinition(Singleton.class);
         beanFactory.registerBeanDefinition("singleton", singleton);
     
    -    RootBeanDefinition prototype
    -        = new RootBeanDefinition(Prototype.class, false);
    +    RootBeanDefinition prototype = new RootBeanDefinition(Prototype.class, false);
         beanFactory.registerBeanDefinition("prototype", prototype);
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        bind(BeanFactory.class).toInstance(beanFactory);
    -        bind(Singleton.class)
    -            .toProvider(fromSpring(Singleton.class, "singleton"));
    -        bind(Prototype.class)
    -            .toProvider(fromSpring(Prototype.class, "prototype"));
    -      }
    -    });
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                bind(BeanFactory.class).toInstance(beanFactory);
    +                bind(Singleton.class).toProvider(fromSpring(Singleton.class, "singleton"));
    +                bind(Prototype.class).toProvider(fromSpring(Prototype.class, "prototype"));
    +              }
    +            });
     
         assertNotNull(injector.getInstance(Singleton.class));
    -    assertSame(injector.getInstance(Singleton.class),
    -        injector.getInstance(Singleton.class));
    +    assertSame(injector.getInstance(Singleton.class), injector.getInstance(Singleton.class));
     
         assertNotNull(injector.getInstance(Prototype.class));
    -    assertNotSame(injector.getInstance(Prototype.class),
    -        injector.getInstance(Prototype.class));
    +    assertNotSame(injector.getInstance(Prototype.class), injector.getInstance(Prototype.class));
       }
     
       public void testBindAll() throws CreationException {
    -    final DefaultListableBeanFactory beanFactory
    -        = new DefaultListableBeanFactory();
    +    final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
     
    -    RootBeanDefinition singleton
    -        = new RootBeanDefinition(Singleton.class);
    +    RootBeanDefinition singleton = new RootBeanDefinition(Singleton.class);
         beanFactory.registerBeanDefinition("singleton", singleton);
     
    -    RootBeanDefinition prototype
    -        = new RootBeanDefinition(Prototype.class, false);
    +    RootBeanDefinition prototype = new RootBeanDefinition(Prototype.class, false);
         beanFactory.registerBeanDefinition("prototype", prototype);
     
    -    Injector injector = Guice.createInjector(new AbstractModule() {
    -      protected void configure() {
    -        SpringIntegration.bindAll(binder(), beanFactory);
    -      }
    -    });
    -
    -    Key singletonKey
    -        = Key.get(Singleton.class, Names.named("singleton"));
    -    Key prototypeKey
    -        = Key.get(Prototype.class, Names.named("prototype"));
    +    Injector injector =
    +        Guice.createInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +                SpringIntegration.bindAll(binder(), beanFactory);
    +              }
    +            });
    +
    +    Key singletonKey = Key.get(Singleton.class, Names.named("singleton"));
    +    Key prototypeKey = Key.get(Prototype.class, Names.named("prototype"));
     
         assertNotNull(injector.getInstance(singletonKey));
    -    assertSame(injector.getInstance(singletonKey),
    -        injector.getInstance(singletonKey));
    +    assertSame(injector.getInstance(singletonKey), injector.getInstance(singletonKey));
     
         assertNotNull(injector.getInstance(prototypeKey));
    -    assertNotSame(injector.getInstance(prototypeKey),
    -        injector.getInstance(prototypeKey));
    +    assertNotSame(injector.getInstance(prototypeKey), injector.getInstance(prototypeKey));
       }
     
       static class Singleton {}
    +
       static class Prototype {}
     }
    diff -Nru sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java
    --- sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -18,9 +18,7 @@
     
     import com.google.inject.servlet.SessionScoped;
     
    -/**
    - * Session-scoped counter.
    - */
    +/** Session-scoped counter. */
     @SessionScoped
     public class Counter {
     
    diff -Nru sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java
    --- sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -16,9 +16,10 @@
     
     package com.google.inject.struts2.example;
     
    -import com.google.inject.Inject;
     import static com.opensymphony.xwork2.Action.SUCCESS;
     
    +import com.google.inject.Inject;
    +
     public class Count {
     
       final Counter counter;
    diff -Nru sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java
    --- sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -16,14 +16,13 @@
     
     package com.google.inject.struts2.example;
     
    -import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
    -
     import com.google.inject.Guice;
     import com.google.inject.Injector;
     import com.google.inject.Singleton;
     import com.google.inject.servlet.GuiceServletContextListener;
     import com.google.inject.servlet.ServletModule;
     import com.google.inject.struts2.Struts2GuicePluginModule;
    +import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
     
     /**
      * Example application module.
    @@ -34,18 +33,17 @@
     
       public Injector getInjector() {
         return Guice.createInjector(
    -      new Struts2GuicePluginModule(),
    -      new ServletModule() {
    -        @Override
    -        protected void configureServlets() {      
    -          // Struts 2 setup
    -          bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class);
    -          filter("/*").through(StrutsPrepareAndExecuteFilter.class);
    -
    -          // Our app-specific code
    -          bind(Service.class).to(ServiceImpl.class);
    -      }
    -    });
    +        new Struts2GuicePluginModule(),
    +        new ServletModule() {
    +          @Override
    +          protected void configureServlets() {
    +            // Struts 2 setup
    +            bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class);
    +            filter("/*").through(StrutsPrepareAndExecuteFilter.class);
    +
    +            // Our app-specific code
    +            bind(Service.class).to(ServiceImpl.class);
    +          }
    +        });
       }
    -
     }
    diff -Nru sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java
    --- sisu-guice-3.2.6/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -21,9 +21,7 @@
     import org.mortbay.jetty.nio.SelectChannelConnector;
     import org.mortbay.jetty.webapp.WebAppContext;
     
    -/**
    - * Starts the example web server on port 8080. Run from "./struts2/example".
    - */
    +/** Starts the example web server on port 8080. Run from "./struts2/example". */
     public class Main {
     
       public static void main(String[] args) throws Exception {
    @@ -31,7 +29,7 @@
     
         Connector connector = new SelectChannelConnector();
         connector.setPort(8080);
    -    server.setConnectors(new Connector[] { connector });
    +    server.setConnectors(new Connector[] {connector});
     
         WebAppContext webapp = new WebAppContext("./root", "/example");
         server.addHandler(webapp);
    diff -Nru sisu-guice-3.2.6/extensions/struts2/pom.xml sisu-guice-4.2.0/extensions/struts2/pom.xml
    --- sisu-guice-3.2.6/extensions/struts2/pom.xml	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/pom.xml	2018-04-03 18:18:08.000000000 +0000
    @@ -6,7 +6,7 @@
       
         org.sonatype.sisu.inject
         extensions-parent
    -    3.2.6
    +    4.2.0
       
     
       guice-struts2
    @@ -33,4 +33,18 @@
         
       
     
    +  
    +    
    +      
    +        maven-jar-plugin
    +        
    +          
    +            
    +              com.google.guice.extensions.struts2
    +            
    +          
    +        
    +      
    +    
    +  
     
    diff -Nru sisu-guice-3.2.6/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java sisu-guice-4.2.0/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java
    --- sisu-guice-3.2.6/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2006 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -23,14 +23,12 @@
     import com.google.inject.Module;
     import com.google.inject.internal.Annotations;
     import com.google.inject.servlet.ServletModule;
    -
     import com.opensymphony.xwork2.ActionInvocation;
     import com.opensymphony.xwork2.ObjectFactory;
     import com.opensymphony.xwork2.config.ConfigurationException;
     import com.opensymphony.xwork2.config.entities.InterceptorConfig;
     import com.opensymphony.xwork2.inject.Inject;
     import com.opensymphony.xwork2.interceptor.Interceptor;
    -
     import java.lang.annotation.Annotation;
     import java.util.ArrayList;
     import java.util.HashSet;
    @@ -39,20 +37,16 @@
     import java.util.Set;
     import java.util.logging.Logger;
     
    -/**
    - * @deprecated Use {@link com.google.inject.struts2.Struts2Factory} instead.
    - */
    +/** @deprecated Use {@link com.google.inject.struts2.Struts2Factory} instead. */
     @Deprecated
     public class GuiceObjectFactory extends ObjectFactory {
     
    -  static final Logger logger =
    -      Logger.getLogger(GuiceObjectFactory.class.getName());
    +  static final Logger logger = Logger.getLogger(GuiceObjectFactory.class.getName());
     
       Module module;
       volatile Injector injector;
       boolean developmentMode = false;
    -  List interceptors
    -      = new ArrayList();
    +  List interceptors = new ArrayList<>();
     
       @Override
       public boolean isNoArgConstructorRequired() {
    @@ -66,7 +60,7 @@
           @SuppressWarnings({"unchecked"})
           Class moduleClass =
               (Class) Class.forName(moduleClassName);
    -      this.module = moduleClass.newInstance();
    +      this.module = moduleClass.getConstructor().newInstance();
         } catch (Exception e) {
           throw new RuntimeException(e);
         }
    @@ -77,8 +71,9 @@
         this.developmentMode = developmentMode.trim().equals("true");
       }
     
    -  Set> boundClasses = new HashSet>();
    +  Set> boundClasses = new HashSet<>();
     
    +  @Override
       public Class getClassInstance(String name) throws ClassNotFoundException {
         Class clazz = super.getClassInstance(name);
     
    @@ -106,6 +101,7 @@
         return clazz;
       }
     
    +  @Override
       @SuppressWarnings("unchecked")
       public Object buildBean(Class clazz, Map extraContext) {
         if (injector == null) {
    @@ -122,34 +118,37 @@
       private void createInjector() {
         try {
           logger.info("Creating injector...");
    -      this.injector = Guice.createInjector(new AbstractModule() {
    -        protected void configure() {
    -          // Install default servlet bindings.
    -          install(new ServletModule());
    -
    -          // Install user's module.
    -          if (module != null) {
    -            logger.info("Installing " + module + "...");
    -            install(module);
    -          }
    -          else {
    -            logger.info("No module found. Set 'guice.module' to a Module "
    -                + "class name if you'd like to use one.");
    -          }
    -
    -          // Tell the injector about all the action classes, etc., so it
    -          // can validate them at startup.
    -          for (Class boundClass : boundClasses) {
    -            // TODO: Set source from Struts XML.
    -            bind(boundClass);
    -          }
    -
    -          // Validate the interceptor class.
    -          for (ProvidedInterceptor interceptor : interceptors) {
    -            interceptor.validate(binder());
    -          }
    -        }
    -      });
    +      this.injector =
    +          Guice.createInjector(
    +              new AbstractModule() {
    +                @Override
    +                protected void configure() {
    +                  // Install default servlet bindings.
    +                  install(new ServletModule());
    +
    +                  // Install user's module.
    +                  if (module != null) {
    +                    logger.info("Installing " + module + "...");
    +                    install(module);
    +                  } else {
    +                    logger.info(
    +                        "No module found. Set 'guice.module' to a Module "
    +                            + "class name if you'd like to use one.");
    +                  }
    +
    +                  // Tell the injector about all the action classes, etc., so it
    +                  // can validate them at startup.
    +                  for (Class boundClass : boundClasses) {
    +                    // TODO: Set source from Struts XML.
    +                    bind(boundClass);
    +                  }
    +
    +                  // Validate the interceptor class.
    +                  for (ProvidedInterceptor interceptor : interceptors) {
    +                    interceptor.validate(binder());
    +                  }
    +                }
    +              });
     
           // Inject interceptors.
           for (ProvidedInterceptor interceptor : interceptors) {
    @@ -163,9 +162,10 @@
         logger.info("Injector created successfully.");
       }
     
    +  @Override
       @SuppressWarnings("unchecked")
    -  public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
    -      Map interceptorRefParams) throws ConfigurationException {
    +  public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams)
    +      throws ConfigurationException {
         // Ensure the interceptor class is present.
         Class interceptorClass;
         try {
    @@ -174,14 +174,14 @@
           throw new RuntimeException(e);
         }
     
    -    ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
    -        interceptorConfig, interceptorRefParams, interceptorClass);
    +    ProvidedInterceptor providedInterceptor =
    +        new ProvidedInterceptor(interceptorConfig, interceptorRefParams, interceptorClass);
         interceptors.add(providedInterceptor);
         return providedInterceptor;
       }
     
    -  Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
    -      Map interceptorRefParams) throws ConfigurationException {
    +  Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams)
    +      throws ConfigurationException {
         return super.buildInterceptor(interceptorConfig, interceptorRefParams);
       }
     
    @@ -192,8 +192,8 @@
         final Class interceptorClass;
         Interceptor delegate;
     
    -    ProvidedInterceptor(InterceptorConfig config, Map params,
    -        Class interceptorClass) {
    +    ProvidedInterceptor(
    +        InterceptorConfig config, Map params, Class interceptorClass) {
           this.config = config;
           this.params = params;
           this.interceptorClass = interceptorClass;
    @@ -202,15 +202,17 @@
         void validate(Binder binder) {
           // TODO: Set source from Struts XML.
           if (hasScope(interceptorClass)) {
    -        binder.addError("Scoping interceptors is not currently supported."
    -            + " Please remove the scope annotation from "
    -            + interceptorClass.getName() + ".");
    +        binder.addError(
    +            "Scoping interceptors is not currently supported."
    +                + " Please remove the scope annotation from "
    +                + interceptorClass.getName()
    +                + ".");
           }
     
           // Make sure it implements Interceptor.
           if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
    -        binder.addError(interceptorClass.getName() + " must implement "
    -          + Interceptor.class.getName() + ".");
    +        binder.addError(
    +            interceptorClass.getName() + " must implement " + Interceptor.class.getName() + ".");
           }
         }
     
    @@ -218,24 +220,25 @@
           delegate = superBuildInterceptor(config, params);
         }
     
    +    @Override
         public void destroy() {
           if (null != delegate) {
             delegate.destroy();
           }
         }
     
    +    @Override
         public void init() {
           throw new AssertionError();
         }
     
    +    @Override
         public String intercept(ActionInvocation invocation) throws Exception {
           return delegate.intercept(invocation);
         }
       }
     
    -  /**
    -   * Returns true if the given class has a scope annotation.
    -   */
    +  /** Returns true if the given class has a scope annotation. */
       private static boolean hasScope(Class interceptorClass) {
         for (Annotation annotation : interceptorClass.getAnnotations()) {
           if (Annotations.isScopeAnnotation(annotation.annotationType())) {
    diff -Nru sisu-guice-3.2.6/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java sisu-guice-4.2.0/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java
    --- sisu-guice-3.2.6/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2009 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -20,14 +20,12 @@
     import com.google.inject.Binder;
     import com.google.inject.Injector;
     import com.google.inject.internal.Annotations;
    -
     import com.opensymphony.xwork2.ActionInvocation;
     import com.opensymphony.xwork2.ObjectFactory;
     import com.opensymphony.xwork2.config.ConfigurationException;
     import com.opensymphony.xwork2.config.entities.InterceptorConfig;
     import com.opensymphony.xwork2.inject.Inject;
     import com.opensymphony.xwork2.interceptor.Interceptor;
    -
     import java.lang.annotation.Annotation;
     import java.util.ArrayList;
     import java.util.HashSet;
    @@ -37,8 +35,8 @@
     import java.util.logging.Logger;
     
     /**
    - * Cleanup up version from Bob's GuiceObjectFactory. Now works properly with
    - * GS2 and fixes several bugs.
    + * Cleanup up version from Bob's GuiceObjectFactory. Now works properly with GS2 and fixes several
    + * bugs.
      *
      * @author dhanji@gmail.com
      * @author benmccann.com
    @@ -49,11 +47,11 @@
       private static final Logger logger = Logger.getLogger(Struts2Factory.class.getName());
       private static final String ERROR_NO_INJECTOR =
           "Cannot find a Guice injector.  Are you sure you registered a GuiceServletContextListener "
    -    + "that uses the Struts2GuicePluginModule in your application's web.xml?";
    +          + "that uses the Struts2GuicePluginModule in your application's web.xml?";
     
       private static @com.google.inject.Inject Injector injector;
     
    -  private final List interceptors = new ArrayList();
    +  private final List interceptors = new ArrayList<>();
       private volatile Injector strutsInjector;
     
       @Override
    @@ -63,13 +61,15 @@
     
       @Inject(value = "guice.module", required = false)
       void setModule(String moduleClassName) {
    -    throw new RuntimeException("The struts2 plugin no longer supports"
    -        + " specifying a module via the 'guice.module' property in XML."
    -        + " Please install your module via a GuiceServletContextListener instead.");
    +    throw new RuntimeException(
    +        "The struts2 plugin no longer supports"
    +            + " specifying a module via the 'guice.module' property in XML."
    +            + " Please install your module via a GuiceServletContextListener instead.");
       }
     
    -  Set> boundClasses = new HashSet>();
    +  Set> boundClasses = new HashSet<>();
     
    +  @Override
       public Class getClassInstance(String name) throws ClassNotFoundException {
         Class clazz = super.getClassInstance(name);
     
    @@ -97,7 +97,8 @@
         return clazz;
       }
     
    -  @Override @SuppressWarnings("unchecked")
    +  @Override
    +  @SuppressWarnings("unchecked")
       public Object buildBean(Class clazz, Map extraContext) {
         if (strutsInjector == null) {
           synchronized (this) {
    @@ -119,22 +120,25 @@
           throw new RuntimeException(ERROR_NO_INJECTOR);
         }
     
    -    this.strutsInjector = injector.createChildInjector(new AbstractModule() {
    -      protected void configure() {
    -
    -        // Tell the injector about all the action classes, etc., so it
    -        // can validate them at startup.
    -        for (Class boundClass : boundClasses) {
    -          // TODO: Set source from Struts XML.
    -          bind(boundClass);
    -        }
    -
    -        // Validate the interceptor class.
    -        for (ProvidedInterceptor interceptor : interceptors) {
    -          interceptor.validate(binder());
    -        }
    -      }
    -    });
    +    this.strutsInjector =
    +        injector.createChildInjector(
    +            new AbstractModule() {
    +              @Override
    +              protected void configure() {
    +
    +                // Tell the injector about all the action classes, etc., so it
    +                // can validate them at startup.
    +                for (Class boundClass : boundClasses) {
    +                  // TODO: Set source from Struts XML.
    +                  bind(boundClass);
    +                }
    +
    +                // Validate the interceptor class.
    +                for (ProvidedInterceptor interceptor : interceptors) {
    +                  interceptor.validate(binder());
    +                }
    +              }
    +            });
     
         // Inject interceptors.
         for (ProvidedInterceptor interceptor : interceptors) {
    @@ -144,26 +148,35 @@
         logger.info("Injector created successfully.");
       }
     
    +  @Override
       @SuppressWarnings("unchecked")
    -  public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
    -      Map interceptorRefParams) throws ConfigurationException {
    +  public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams)
    +      throws ConfigurationException {
         // Ensure the interceptor class is present.
         Class interceptorClass;
         try {
    -      interceptorClass = (Class)
    -          getClassInstance(interceptorConfig.getClassName());
    +      interceptorClass =
    +          (Class) getClassInstance(interceptorConfig.getClassName());
         } catch (ClassNotFoundException e) {
           throw new RuntimeException(e);
         }
     
    -    ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
    -        interceptorConfig, interceptorRefParams, interceptorClass);
    +    ProvidedInterceptor providedInterceptor =
    +        new ProvidedInterceptor(interceptorConfig, interceptorRefParams, interceptorClass);
         interceptors.add(providedInterceptor);
    +    if (strutsInjector != null) {
    +      synchronized (this) {
    +        if (strutsInjector != null) {
    +          providedInterceptor.inject();
    +        }
    +      }
    +    }
         return providedInterceptor;
       }
     
    -  private Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
    -      Map interceptorRefParams) throws ConfigurationException {
    +  private Interceptor superBuildInterceptor(
    +      InterceptorConfig interceptorConfig, Map interceptorRefParams)
    +      throws ConfigurationException {
         return super.buildInterceptor(interceptorConfig, interceptorRefParams);
       }
     
    @@ -176,7 +189,9 @@
         private final Class interceptorClass;
         private Interceptor delegate;
     
    -    ProvidedInterceptor(InterceptorConfig config, Map params,
    +    ProvidedInterceptor(
    +        InterceptorConfig config,
    +        Map params,
             Class interceptorClass) {
           this.config = config;
           this.params = params;
    @@ -186,15 +201,17 @@
         void validate(Binder binder) {
           // TODO: Set source from Struts XML.
           if (hasScope(interceptorClass)) {
    -        binder.addError("Scoping interceptors is not currently supported."
    -            + " Please remove the scope annotation from "
    -            + interceptorClass.getName() + ".");
    +        binder.addError(
    +            "Scoping interceptors is not currently supported."
    +                + " Please remove the scope annotation from "
    +                + interceptorClass.getName()
    +                + ".");
           }
     
           // Make sure it implements Interceptor.
           if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
    -        binder.addError(interceptorClass.getName() + " must implement "
    -          + Interceptor.class.getName() + ".");
    +        binder.addError(
    +            interceptorClass.getName() + " must implement " + Interceptor.class.getName() + ".");
           }
         }
     
    @@ -202,24 +219,25 @@
           delegate = superBuildInterceptor(config, params);
         }
     
    +    @Override
         public void destroy() {
           if (null != delegate) {
             delegate.destroy();
           }
         }
     
    +    @Override
         public void init() {
           throw new AssertionError();
         }
     
    +    @Override
         public String intercept(ActionInvocation invocation) throws Exception {
           return delegate.intercept(invocation);
         }
       }
     
    -  /**
    -   * Returns true if the given class has a scope annotation.
    -   */
    +  /** Returns true if the given class has a scope annotation. */
       private static boolean hasScope(Class interceptorClass) {
         for (Annotation annotation : interceptorClass.getAnnotations()) {
           if (Annotations.isScopeAnnotation(annotation.annotationType())) {
    diff -Nru sisu-guice-3.2.6/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java sisu-guice-4.2.0/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java
    --- sisu-guice-3.2.6/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2010 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -19,8 +19,8 @@
     import com.google.inject.AbstractModule;
     
     /**
    - * Initializes the Struts 2 Guice Plugin. Must be added to the injector returned
    - * by {@link com.google.inject.servlet.GuiceServletContextListener#getInjector}.
    + * Initializes the Struts 2 Guice Plugin. Must be added to the injector returned by {@link
    + * com.google.inject.servlet.GuiceServletContextListener#getInjector}.
      *
      * @author benmccann.com
      */
    @@ -30,5 +30,4 @@
       protected void configure() {
         requestStaticInjection(Struts2Factory.class);
       }
    -
     }
    diff -Nru sisu-guice-3.2.6/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java sisu-guice-4.2.0/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java
    --- sisu-guice-3.2.6/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java	2018-04-03 18:18:08.000000000 +0000
    @@ -1,4 +1,4 @@
    -/**
    +/*
      * Copyright (C) 2010 Google Inc.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
    @@ -22,13 +22,10 @@
     import com.google.inject.Injector;
     import com.google.inject.Module;
     import com.google.inject.Provides;
    -import com.google.inject.Singleton;
     import com.google.inject.servlet.GuiceServletContextListener;
     import com.google.inject.servlet.ServletModule;
    -
    -import junit.framework.TestCase;
    -
     import java.util.Date;
    +import junit.framework.TestCase;
     
     /**
      * Test for Struts2Factory
    @@ -55,30 +52,28 @@
                 @Override
                 protected void configureServlets() {
                   // Struts 2 setup
    -              bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class);
    +              bind(StrutsPrepareAndExecuteFilter.class)
    +                  .in(com.google.inject.Singleton.class);
                   filter("/*").through(StrutsPrepareAndExecuteFilter.class);
                 }
               },
    -          module
    -      );
    +          module);
         }
    -
       }
     
       public void testStruts2Factory() {
         Struts2Factory s2Factory = new Struts2Factory();
    -    TestListener testListener = new TestListener(new AbstractModule() {
    -      @Override
    -      protected void configure() {
    -      }
    -
    -      @Provides @SuppressWarnings("unused")
    -      Date provideDate() {
    -        return TODAY;
    -      }
    -    });
    +    TestListener testListener =
    +        new TestListener(
    +            new AbstractModule() {
    +
    +              @Provides
    +              @SuppressWarnings("unused")
    +              Date provideDate() {
    +                return TODAY;
    +              }
    +            });
         assertEquals(TODAY, testListener.getInjector().getInstance(Date.class));
         assertEquals(TODAY, s2Factory.buildBean(Date.class, null));
       }
    -
     }
    diff -Nru sisu-guice-3.2.6/extensions/testlib/build.xml sisu-guice-4.2.0/extensions/testlib/build.xml
    --- sisu-guice-3.2.6/extensions/testlib/build.xml	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/testlib/build.xml	2018-04-03 18:18:08.000000000 +0000
    @@ -4,10 +4,23 @@
     
       
     
    +  
    +    
    +    
    +  
    +
       
         
         
         
    +    
       
     
       
    diff -Nru sisu-guice-3.2.6/extensions/testlib/pom.xml sisu-guice-4.2.0/extensions/testlib/pom.xml
    --- sisu-guice-3.2.6/extensions/testlib/pom.xml	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/testlib/pom.xml	2018-04-03 18:18:08.000000000 +0000
    @@ -6,7 +6,7 @@
       
         org.sonatype.sisu.inject
         extensions-parent
    -    3.2.6
    +    4.2.0
       
     
       guice-testlib
    @@ -23,6 +23,39 @@
               
             
           
    +      
    +        maven-jar-plugin
    +        
    +          
    +            
    +              com.google.guice.extensions.testlib
    +            
    +          
    +        
    +      
         
       
    +
    +  
    +    
    +      org.sonatype.sisu.inject
    +      guice-throwingproviders
    +      ${project.version}
    +    
    +    
    +      com.google.truth
    +      truth
    +      0.36
    +      compile
    +    
    +    
    +      com.google.guava
    +      guava
    +      20.0
    +    
    +    
    +      com.google.code.findbugs
    +      jsr305
    +    
    +  
     
    diff -Nru sisu-guice-3.2.6/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java sisu-guice-4.2.0/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java
    --- sisu-guice-3.2.6/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java	2015-04-25 16:25:40.000000000 +0000
    +++ sisu-guice-4.2.0/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java	2018-04-03 18:18:08.000000000 +0000
    @@ -23,8 +23,12 @@
     import java.lang.annotation.Target;
     
     /**
    - * Annotation used by {@link BoundFieldModule} to indicate that a field should be bound to its
    - * value using Guice.
    + * Annotation used by {@link BoundFieldModule} to indicate that a field should be bound to its value
    + * using Guice.
    + *
    + * 

    Binding to {@code null} is only allowed for fields that are annotated {@code @Nullable}. See + * https://github.com/google/guice/wiki/UseNullable * * @see BoundFieldModule * @author eatnumber1@google.com (Russ Harmon) @@ -39,10 +43,11 @@ Class to() default Bind.class; /** - * If true, {@link BoundFieldModule} will delay retrieving the field's value until injection time - * rather than eagerly fetching it at configure time. - * - *

    This option is not supported with Provider valued fields. + * If true, {@link BoundFieldModule} will delay reading the field until injection time rather than + * eagerly reading it at configure time. + * + *

    When used with Provider valued fields, the provider will be read from the field and {@code + * .get()} will be called for each provision. This may be useful for testing provision failures. */ boolean lazy() default false; } diff -Nru sisu-guice-3.2.6/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java sisu-guice-4.2.0/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java --- sisu-guice-3.2.6/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -26,8 +26,9 @@ import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.LinkedBindingBuilder; import com.google.inject.internal.Annotations; +import com.google.inject.internal.Nullability; import com.google.inject.spi.Message; - +import com.google.inject.util.Providers; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; @@ -42,43 +43,40 @@ *

    The following rules are followed in determining how fields are bound using this module: * *

      - *
    • - * For each {@link Bind} annotated field of an object and its superclasses, this module will bind - * that field's type to that field's value at injector creation time. This includes both instance - * and static fields. - *
    • - *
    • - * If {@link Bind#to} is specified, the field's value will be bound to the class specified by - * {@link Bind#to} instead of the field's actual type. - *
    • - *
    • - * If a {@link BindingAnnotation} or {@link javax.inject.Qualifier} is present on the field, - * that field will be bound using that annotation via {@link AnnotatedBindingBuilder#annotatedWith}. - * For example, {@code bind(Foo.class).annotatedWith(BarAnnotation.class).toInstance(theValue)}. - * It is an error to supply more than one {@link BindingAnnotation} or - * {@link javax.inject.Qualifier}. - *
    • - *
    • - * If the field is of type {@link Provider}, the field's value will be bound as a {@link Provider} - * using {@link LinkedBindingBuilder#toProvider} to the provider's parameterized type. For example, - * {@code Provider} binds to {@link Integer}. Attempting to bind a non-parameterized - * {@link Provider} without a {@link Bind#to} clause is an error. - *
    • + *
    • For each {@link Bind} annotated field of an object and its superclasses, this module will + * bind that field's type to that field's value at injector creation time. This includes both + * instance and static fields. + *
    • If {@link Bind#to} is specified, the field's value will be bound to the class specified by + * {@link Bind#to} instead of the field's actual type. + *
    • If {@link Bind#lazy} is true, this module will delay reading the value from the field until + * injection time, allowing the field's value to be reassigned during the course of a test's + * execution. + *
    • If a {@link BindingAnnotation} or {@link javax.inject.Qualifier} is present on the field, + * that field will be bound using that annotation via {@link + * AnnotatedBindingBuilder#annotatedWith}. For example, {@code + * bind(Foo.class).annotatedWith(BarAnnotation.class).toInstance(theValue)}. It is an error to + * supply more than one {@link BindingAnnotation} or {@link javax.inject.Qualifier}. + *
    • If the field is of type {@link Provider}, the field's value will be bound as a {@link + * Provider} using {@link LinkedBindingBuilder#toProvider} to the provider's parameterized + * type. For example, {@code Provider} binds to {@link Integer}. Attempting to bind a + * non-parameterized {@link Provider} without a {@link Bind#to} clause is an error. *
    * *

    Example use: + * *

    
      * public class TestFoo {
      *   // bind(new TypeLiteral{@code >}() {}).toInstance(listOfObjects);
      *   {@literal @}Bind private List{@code } listOfObjects = Lists.of();
    - *   
    + *
    + *   // private String userName = "string_that_changes_over_time";
      *   // bind(String.class).toProvider(new Provider() { public String get() { return userName; }});
      *   {@literal @}Bind(lazy = true) private String userName;
      *
      *   // bind(SuperClass.class).toInstance(aSubClass);
      *   {@literal @}Bind(to = SuperClass.class) private SubClass aSubClass = new SubClass();
      *
    - *   // bind(Object.class).annotatedWith(MyBindingAnnotation.class).toInstance(object2);
    + *   // bind(String.class).annotatedWith(MyBindingAnnotation.class).toInstance(myString);
      *   {@literal @}Bind
      *   {@literal @}MyBindingAnnotation
      *   private String myString = "hello";
    @@ -131,8 +129,8 @@
         /**
          * The actual type of the field.
          *
    -     * 

    For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be - * {@link Number}. + *

    For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be {@link + * Number}. */ final TypeLiteral type; @@ -142,26 +140,23 @@ /** * The type this field will bind to. * - *

    For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be - * {@link Object} and {@code @Bind Number one = new Integer(1);} will be {@link Number}. + *

    For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be {@link + * Object} and {@code @Bind Number one = new Integer(1);} will be {@link Number}. */ final TypeLiteral boundType; /** * The "natural" type of this field. * - *

    For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be - * {@link Number}, and {@code @Bind(to = Object.class) Provider one = new Integer(1);} - * will be {@link Number}. + *

    For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be {@link + * Number}, and {@code @Bind(to = Object.class) Provider one = new Integer(1);} will be + * {@link Number}. * * @see #getNaturalFieldType */ final Optional> naturalType; - BoundFieldInfo( - Field field, - Bind bindAnnotation, - TypeLiteral fieldType) { + BoundFieldInfo(Field field, Bind bindAnnotation, TypeLiteral fieldType) { this.field = field; this.type = fieldType; this.bindAnnotation = bindAnnotation; @@ -182,7 +177,7 @@ throwBoundFieldException( field, "Non parameterized Provider fields must have an explicit " - + "binding class via @Bind(to = Foo.class)"); + + "binding class via @Bind(to = Foo.class)"); } return this.naturalType.get(); } else { @@ -199,7 +194,7 @@ * is the field's actual type. * * @return the type this field binds to naturally, or {@link Optional#absent()} if this field is - * a non-parameterized {@link Provider}. + * a non-parameterized {@link Provider}. */ private Optional> getNaturalFieldType() { if (isTransparentProvider(type.getRawType())) { @@ -225,6 +220,12 @@ throw new AssertionError(e); } } + + /** Returns whether a binding supports null values. */ + boolean allowsNull() { + return !isTransparentProvider(type.getRawType()) + && Nullability.allowsNull(field.getAnnotations()); + } } private static boolean hasInject(Field field) { @@ -235,31 +236,24 @@ /** * Retrieve a {@link BoundFieldInfo}. * - *

    This returns a {@link BoundFieldInfo} if the field has a {@link Bind} annotation. - * Otherwise it returns {@link Optional#absent()}. + *

    This returns a {@link BoundFieldInfo} if the field has a {@link Bind} annotation. Otherwise + * it returns {@link Optional#absent()}. */ private Optional getBoundFieldInfo( - TypeLiteral containingClassType, - Field field) { + TypeLiteral containingClassType, Field field) { Bind bindAnnotation = field.getAnnotation(Bind.class); if (bindAnnotation == null) { return Optional.absent(); } if (hasInject(field)) { - throwBoundFieldException( - field, - "Fields annotated with both @Bind and @Inject are illegal."); + throwBoundFieldException(field, "Fields annotated with both @Bind and @Inject are illegal."); } return Optional.of( - new BoundFieldInfo( - field, - bindAnnotation, - containingClassType.getFieldType(field))); + new BoundFieldInfo(field, bindAnnotation, containingClassType.getFieldType(field))); } private LinkedBindingBuilder verifyBindingAnnotations( - Field field, - AnnotatedBindingBuilder annotatedBinder) { + Field field, AnnotatedBindingBuilder annotatedBinder) { LinkedBindingBuilder binderRet = annotatedBinder; for (Annotation annotation : field.getAnnotations()) { Class annotationType = annotation.annotationType(); @@ -275,14 +269,17 @@ /** * Determines if {@code clazz} is a "transparent provider". * - *

    A transparent provider is a {@link com.google.inject.Provider} or - * {@link javax.inject.Provider} which binds to it's parameterized type when used as the argument - * to {@link Binder#bind}. + *

    A transparent provider is a {@link com.google.inject.Provider} or {@link + * javax.inject.Provider} which binds to it's parameterized type when used as the argument to + * {@link Binder#bind}. * *

    A {@link Provider} is transparent if the base class of that object is {@link Provider}. In - * other words, subclasses of {@link Provider} are not transparent. As a special case, if a - * {@link Provider} has no parameterized type but is otherwise transparent, then it is considered + * other words, subclasses of {@link Provider} are not transparent. As a special case, if a {@link + * Provider} has no parameterized type but is otherwise transparent, then it is considered * transparent. + * + *

    Subclasses of {@link Provider} are not considered transparent in order to allow users to + * bind those subclasses directly, enabling them to inject the providers themselves. */ private static boolean isTransparentProvider(Class clazz) { return com.google.inject.Provider.class == clazz || javax.inject.Provider.class == clazz; @@ -315,43 +312,72 @@ if (isTransparentProvider(fieldInfo.type.getRawType())) { if (fieldInfo.bindAnnotation.lazy()) { - // We don't support this because it is confusing about when values are captured. - throwBoundFieldException(fieldInfo.field, - "'lazy' is incompatible with Provider valued fields"); + binderUnsafe.toProvider( + new Provider() { + @Override + // @Nullable + public Object get() { + // This is safe because we checked that the field's type is Provider above. + @SuppressWarnings("unchecked") + javax.inject.Provider provider = + (javax.inject.Provider) getFieldValue(fieldInfo); + return provider.get(); + } + }); + } else { + // This is safe because we checked that the field's type is Provider above. + @SuppressWarnings("unchecked") + javax.inject.Provider fieldValueUnsafe = + (javax.inject.Provider) getFieldValue(fieldInfo); + binderUnsafe.toProvider(fieldValueUnsafe); } - // This is safe because we checked that the field's type is Provider above. - @SuppressWarnings("unchecked") - Provider fieldValueUnsafe = (Provider) getFieldValue(fieldInfo); - binderUnsafe.toProvider(fieldValueUnsafe); } else if (fieldInfo.bindAnnotation.lazy()) { - binderUnsafe.toProvider(new Provider() { - @Override public Object get() { - return getFieldValue(fieldInfo); - } - }); + binderUnsafe.toProvider( + new Provider() { + @Override + // @Nullable + public Object get() { + return getFieldValue(fieldInfo); + } + }); } else { - binderUnsafe.toInstance(getFieldValue(fieldInfo)); + Object fieldValue = getFieldValue(fieldInfo); + if (fieldValue == null) { + binderUnsafe.toProvider(Providers.of(null)); + } else { + binderUnsafe.toInstance(fieldValue); + } } } + // @Nullable + /** + * Returns the field value to bind, throwing for non-{@code @Nullable} fields with null values, + * and for null "transparent providers". + */ private Object getFieldValue(final BoundFieldInfo fieldInfo) { Object fieldValue = fieldInfo.getValue(); - if (fieldValue == null) { - throwBoundFieldException( - fieldInfo.field, - "Binding to null values is not allowed. " - + "Use Providers.of(null) if this is your intended behavior.", - fieldInfo.field.getName()); + if (fieldValue == null && !fieldInfo.allowsNull()) { + if (isTransparentProvider(fieldInfo.type.getRawType())) { + throwBoundFieldException( + fieldInfo.field, + "Binding to null is not allowed. Use Providers.of(null) if this is your intended " + + "behavior.", + fieldInfo.field.getName()); + } else { + throwBoundFieldException( + fieldInfo.field, + "Binding to null values is only allowed for fields that are annotated @Nullable.", + fieldInfo.field.getName()); + } } return fieldValue; } private void throwBoundFieldException(Field field, String format, Object... args) { Preconditions.checkNotNull(binder); - String source = String.format( - "%s field %s", - field.getDeclaringClass().getName(), - field.getName()); + String source = + String.format("%s field %s", field.getDeclaringClass().getName(), field.getName()); throw new BoundFieldException(new Message(source, String.format(format, args))); } @@ -364,8 +390,7 @@ while (currentClassType.getRawType() != Object.class) { for (Field field : currentClassType.getRawType().getDeclaredFields()) { try { - Optional fieldInfoOpt = - getBoundFieldInfo(currentClassType, field); + Optional fieldInfoOpt = getBoundFieldInfo(currentClassType, field); if (fieldInfoOpt.isPresent()) { bindField(fieldInfoOpt.get()); } diff -Nru sisu-guice-3.2.6/extensions/testlib/src/com/google/inject/testing/throwingproviders/CheckedProviderSubject.java sisu-guice-4.2.0/extensions/testlib/src/com/google/inject/testing/throwingproviders/CheckedProviderSubject.java --- sisu-guice-3.2.6/extensions/testlib/src/com/google/inject/testing/throwingproviders/CheckedProviderSubject.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/testlib/src/com/google/inject/testing/throwingproviders/CheckedProviderSubject.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,83 @@ +package com.google.inject.testing.throwingproviders; + +import static com.google.common.truth.Truth.assertAbout; + +import com.google.common.truth.FailureMetadata; +import com.google.common.truth.Subject; +import com.google.common.truth.ThrowableSubject; +import com.google.inject.throwingproviders.CheckedProvider; +import javax.annotation.Nullable; + +/** + * Truth {@link Subject} for use with {@link CheckedProvider} classes. + * + * @author eatnumber1@google.com (Russ Harmon) + */ +public final class CheckedProviderSubject> + extends Subject, P> { + + private static final class CheckedProviderSubjectFactory> + implements Subject.Factory, P> { + @Override + public CheckedProviderSubject createSubject( + FailureMetadata failureMetadata, @Nullable P target) { + return new CheckedProviderSubject(failureMetadata, target); + } + } + + public static > + Subject.Factory, P> checkedProviders() { + return new CheckedProviderSubjectFactory<>(); + } + + public static > CheckedProviderSubject assertThat( + @Nullable P provider) { + return assertAbout(CheckedProviderSubject.checkedProviders()).that(provider); + } + + private CheckedProviderSubject(FailureMetadata failureMetadata, @Nullable P subject) { + super(failureMetadata, subject); + } + + /** + * Allows for assertions on the value provided by this provider. + * + *

    The value provided by a checked provider is the object returned by a call to {@link + * CheckedProvider#get} + * + * @return a {@link Subject} for asserting against the return value of {@link CheckedProvider#get} + */ + public Subject providedValue() { + P provider = actual(); + T got; + try { + got = provider.get(); + } catch (Exception e) { + failWithRawMessageAndCause( + String.format("checked provider <%s> threw an exception", provider), e); + return ignoreCheck().that(new Object()); + } + return check().withMessage("value provided by <%s>", provider).that(got); + } + + /** + * Allows for assertions on the exception thrown by this provider. + * + *

    The exception thrown by a checked provider is the {@link Throwable} thrown by a call to + * {@link CheckedProvider#get} + * + * @return a {@link ThrowableSubject} for asserting against the {@link Throwable} thrown by {@link + * CheckedProvider#get} + */ + public ThrowableSubject thrownException() { + P provider = actual(); + T got; + try { + got = provider.get(); + } catch (Throwable e) { + return check().withMessage("exception thrown by <%s>", provider).that(e); + } + failWithBadResults("threw", "an exception", "provided", got); + return ignoreCheck().that(new Throwable()); + } +} diff -Nru sisu-guice-3.2.6/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java sisu-guice-4.2.0/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java --- sisu-guice-3.2.6/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -31,14 +31,11 @@ import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.util.Providers; - -import junit.framework.TestCase; - import java.lang.annotation.Retention; import java.util.Arrays; import java.util.List; - import javax.inject.Qualifier; +import junit.framework.TestCase; /** Unit tests for {@link BoundFieldModule}. */ public class BoundFieldModuleTest extends TestCase { @@ -53,9 +50,10 @@ public void testBindingOnePrivate() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind private Integer anInt = testValue; - }; + Object instance = + new Object() { + @Bind private Integer anInt = testValue; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -65,9 +63,10 @@ public void testBindingOnePublic() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind public Integer anInt = testValue; - }; + Object instance = + new Object() { + @Bind public Integer anInt = testValue; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -101,10 +100,11 @@ public void testBindingTwo() { final Integer testValue = 1024; final String testString = "Hello World!"; - Object instance = new Object() { - @Bind private Integer anInt = testValue; - @Bind private String aString = testString; - }; + Object instance = + new Object() { + @Bind private Integer anInt = testValue; + @Bind private String aString = testString; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -115,9 +115,11 @@ public void testBindingSuperType() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind(to = Number.class) private Integer anInt = testValue; - }; + Object instance = + new Object() { + @Bind(to = Number.class) + private Integer anInt = testValue; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -127,31 +129,36 @@ public void testBindingSuperTypeAccessSubType() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind(to = Number.class) private Integer anInt = testValue; - }; + Object instance = + new Object() { + @Bind(to = Number.class) + private Integer anInt = testValue; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); try { injector.getInstance(Integer.class); + fail(); } catch (ConfigurationException e) { - assertContains( - e.getMessage(), - "Could not find a suitable constructor in java.lang.Integer"); + assertContains(e.getMessage(), "Could not find a suitable constructor in java.lang.Integer"); } } public void testBindingIncorrectTypeProviderFails() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind(to = String.class) private Provider anIntProvider = new Provider() { - @Override public Integer get() { - return testValue; - } - }; - }; + Object instance = + new Object() { + @Bind(to = String.class) + private Provider anIntProvider = + new Provider() { + @Override + public Integer get() { + return testValue; + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); @@ -162,7 +169,7 @@ assertContains( e.getMessage(), "Requested binding type \"java.lang.String\" is not " - + "assignable from field binding type \"java.lang.Integer\""); + + "assignable from field binding type \"java.lang.Integer\""); } } @@ -172,21 +179,19 @@ public void testBindingWithBindingAnnotation() { final Integer testValue1 = 1024, testValue2 = 2048; - Object instance = new Object() { - @Bind private Integer anInt = testValue1; + Object instance = + new Object() { + @Bind private Integer anInt = testValue1; - @Bind - @SomeBindingAnnotation - private Integer anotherInt = testValue2; - }; + @Bind @SomeBindingAnnotation private Integer anotherInt = testValue2; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); assertEquals(testValue1, injector.getInstance(Integer.class)); assertEquals( - testValue2, - injector.getInstance(Key.get(Integer.class, SomeBindingAnnotation.class))); + testValue2, injector.getInstance(Key.get(Integer.class, SomeBindingAnnotation.class))); } @Qualifier @@ -195,74 +200,68 @@ public void testBindingWithQualifier() { final Integer testValue1 = 1024, testValue2 = 2048; - Object instance = new Object() { - @Bind private Integer anInt = testValue1; + Object instance = + new Object() { + @Bind private Integer anInt = testValue1; - @Bind - @SomeQualifier - private Integer anotherInt = testValue2; - }; + @Bind @SomeQualifier private Integer anotherInt = testValue2; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); assertEquals(testValue1, injector.getInstance(Integer.class)); - assertEquals( - testValue2, - injector.getInstance(Key.get(Integer.class, SomeQualifier.class))); + assertEquals(testValue2, injector.getInstance(Key.get(Integer.class, SomeQualifier.class))); } public void testCanReuseBindingAnnotationsWithDifferentValues() { final Integer testValue1 = 1024, testValue2 = 2048; final String name1 = "foo", name2 = "bar"; - Object instance = new Object() { - @Bind - @Named(name1) - private Integer anInt = testValue1; - - @Bind - @Named(name2) - private Integer anotherInt = testValue2; - }; + Object instance = + new Object() { + @Bind + @Named(name1) + private Integer anInt = testValue1; + + @Bind + @Named(name2) + private Integer anotherInt = testValue2; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); - assertEquals( - testValue1, - injector.getInstance(Key.get(Integer.class, Names.named(name1)))); - assertEquals( - testValue2, - injector.getInstance(Key.get(Integer.class, Names.named(name2)))); + assertEquals(testValue1, injector.getInstance(Key.get(Integer.class, Names.named(name1)))); + assertEquals(testValue2, injector.getInstance(Key.get(Integer.class, Names.named(name2)))); } public void testBindingWithValuedBindingAnnotation() { final Integer testValue1 = 1024, testValue2 = 2048; final String name = "foo"; - Object instance = new Object() { - @Bind private Integer anInt = testValue1; - - @Bind - @Named(name) - private Integer anotherInt = testValue2; - }; + Object instance = + new Object() { + @Bind private Integer anInt = testValue1; + + @Bind + @Named(name) + private Integer anotherInt = testValue2; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); assertEquals(testValue1, injector.getInstance(Integer.class)); - assertEquals( - testValue2, - injector.getInstance(Key.get(Integer.class, Names.named(name)))); + assertEquals(testValue2, injector.getInstance(Key.get(Integer.class, Names.named(name)))); } public void testBindingWithGenerics() { final List testIntList = Arrays.asList(new Integer[] {1, 2, 3}); final List testBoolList = Arrays.asList(new Boolean[] {true, true, false}); - Object instance = new Object() { - @Bind private List anIntList = testIntList; - @Bind private List aBoolList = testBoolList; - }; + Object instance = + new Object() { + @Bind private List anIntList = testIntList; + @Bind private List aBoolList = testBoolList; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -285,9 +284,11 @@ public void testIncompatibleBindingType() { final Integer testInt = 1024; - Object instance = new Object() { - @Bind(to = String.class) private Integer anInt = testInt; - }; + Object instance = + new Object() { + @Bind(to = String.class) + private Integer anInt = testInt; + }; BoundFieldModule module = BoundFieldModule.of(instance); @@ -295,25 +296,28 @@ Guice.createInjector(module); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Requested binding type \"java.lang.String\" is not assignable from field binding type " - + "\"java.lang.Integer\""); + + "\"java.lang.Integer\""); } } public void testFailureOnMultipleBindingAnnotations() { final Integer testInt = 1024; - Object instance = new Object() { - @Bind - @Named("a") - @SomeBindingAnnotation - private Integer anInt = testInt; - }; + Object instance = + new Object() { + @Bind + @Named("a") + @SomeBindingAnnotation + private Integer anInt = testInt; + }; BoundFieldModule module = BoundFieldModule.of(instance); try { Guice.createInjector(module); + fail(); } catch (CreationException e) { assertContains(e.getMessage(), "More than one annotation is specified for this binding."); } @@ -321,11 +325,12 @@ public void testBindingSuperTypeAndBindingAnnotation() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind(to = Number.class) - @Named("foo") - private Integer anInt = testValue; - }; + Object instance = + new Object() { + @Bind(to = Number.class) + @Named("foo") + private Integer anInt = testValue; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -335,13 +340,17 @@ public void testBindingProvider() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind private Provider anInt = new Provider() { - @Override public Integer get() { - return testValue; - } - }; - }; + Object instance = + new Object() { + @Bind + private Provider anInt = + new Provider() { + @Override + public Integer get() { + return testValue; + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -349,10 +358,31 @@ assertEquals(testValue, injector.getInstance(Integer.class)); } - public void testBindingNullField() { - Object instance = new Object() { - @Bind private Integer anInt = null; - }; + public void testBindingJavaxProvider() { + final Integer testValue = 1024; + Object instance = + new Object() { + @Bind + private javax.inject.Provider anInt = + new javax.inject.Provider() { + @Override + public Integer get() { + return testValue; + } + }; + }; + + BoundFieldModule module = BoundFieldModule.of(instance); + Injector injector = Guice.createInjector(module); + + assertEquals(testValue, injector.getInstance(Integer.class)); + } + + public void testBindingNonNullableNullField() { + Object instance = + new Object() { + @Bind private Integer anInt = null; + }; BoundFieldModule module = BoundFieldModule.of(instance); @@ -360,16 +390,30 @@ Guice.createInjector(module); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), - "Binding to null values is not allowed. " - + "Use Providers.of(null) if this is your intended behavior."); + assertContains( + e.getMessage(), + "Binding to null values is only allowed for fields that are annotated @Nullable."); } } + @Retention(RUNTIME) + private @interface Nullable {} + + public void testBindingNullableNullField() { + Object instance = + new Object() { + @Bind @Nullable private Integer anInt = null; + }; + + Injector injector = Guice.createInjector(BoundFieldModule.of(instance)); + assertNull(injector.getInstance(Integer.class)); + } + public void testBindingNullProvider() { - Object instance = new Object() { - @Bind private Provider anIntProvider = null; - }; + Object instance = + new Object() { + @Bind private Provider anIntProvider = null; + }; BoundFieldModule module = BoundFieldModule.of(instance); @@ -377,9 +421,29 @@ Guice.createInjector(module); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), - "Binding to null values is not allowed. " - + "Use Providers.of(null) if this is your intended behavior."); + assertContains( + e.getMessage(), + "Binding to null is not allowed. Use Providers.of(null) if this is your intended " + + "behavior."); + } + } + + public void testBindingNullableNullProvider() { + Object instance = + new Object() { + @Bind @Nullable private Provider anIntProvider = null; + }; + + BoundFieldModule module = BoundFieldModule.of(instance); + + try { + Guice.createInjector(module); + fail(); + } catch (CreationException e) { + assertContains( + e.getMessage(), + "Binding to null is not allowed. Use Providers.of(null) if this is your intended " + + "behavior."); } } @@ -390,16 +454,18 @@ this.value = value; } - @Override public Integer get() { + @Override + public Integer get() { return value; } } public void testProviderSubclassesBindToTheProviderItself() { final IntegerProvider integerProvider = new IntegerProvider(1024); - Object instance = new Object() { - @Bind private IntegerProvider anIntProvider = integerProvider; - }; + Object instance = + new Object() { + @Bind private IntegerProvider anIntProvider = integerProvider; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -409,9 +475,10 @@ public void testProviderSubclassesDoNotBindParameterizedType() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind private IntegerProvider anIntProvider = new IntegerProvider(testValue); - }; + Object instance = + new Object() { + @Bind private IntegerProvider anIntProvider = new IntegerProvider(testValue); + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -424,6 +491,18 @@ } } + public void testNullableProviderSubclassesAllowNull() { + Object instance = + new Object() { + @Bind @Nullable private IntegerProvider anIntProvider = null; + }; + + BoundFieldModule module = BoundFieldModule.of(instance); + Injector injector = Guice.createInjector(module); + + assertNull(injector.getInstance(IntegerProvider.class)); + } + private static class ParameterizedObject { ParameterizedObject(T instance) { this.instance = instance; @@ -433,7 +512,7 @@ } public void testBindParameterizedTypeFails() { - ParameterizedObject instance = new ParameterizedObject(0); + ParameterizedObject instance = new ParameterizedObject<>(0); BoundFieldModule module = BoundFieldModule.of(instance); @@ -456,10 +535,11 @@ } public void testBindArray() { - final Integer[] testArray = new Integer[] { 1024, 2048 }; - Object instance = new Object() { - @Bind private Integer[] anIntArray = testArray; - }; + final Integer[] testArray = new Integer[] {1024, 2048}; + Object instance = + new Object() { + @Bind private Integer[] anIntArray = testArray; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -469,13 +549,17 @@ public void testRawProviderCannotBeBound() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind private Provider anIntProvider = new Provider() { - @Override public Object get() { - return testValue; - } - }; - }; + Object instance = + new Object() { + @Bind + private Provider anIntProvider = + new Provider() { + @Override + public Object get() { + return testValue; + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); @@ -483,21 +567,26 @@ Guice.createInjector(module); fail(); } catch (CreationException e) { - assertContains(e.getMessage(), + assertContains( + e.getMessage(), "Non parameterized Provider fields must have an " - + "explicit binding class via @Bind(to = Foo.class)"); + + "explicit binding class via @Bind(to = Foo.class)"); } } public void testExplicitlyBoundRawProviderCanBeBound() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind(to = Integer.class) private Provider anIntProvider = new Provider() { - @Override public Object get() { - return testValue; - } - }; - }; + Object instance = + new Object() { + @Bind(to = Integer.class) + private Provider anIntProvider = + new Provider() { + @Override + public Object get() { + return testValue; + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -507,13 +596,17 @@ public void testRawProviderCanBindToIncorrectType() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind(to = String.class) private Provider anIntProvider = new Provider() { - @Override public Object get() { - return testValue; - } - }; - }; + Object instance = + new Object() { + @Bind(to = String.class) + private Provider anIntProvider = + new Provider() { + @Override + public Object get() { + return testValue; + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -522,14 +615,18 @@ } public void testMultipleErrorsAreAggregated() { - Object instance = new Object() { - @Bind private Provider aProvider; - @Bind(to = String.class) private Integer anInt; - }; + Object instance = + new Object() { + @Bind private Provider aProvider; + + @Bind(to = String.class) + private Integer anInt; + }; BoundFieldModule module = BoundFieldModule.of(instance); try { Guice.createInjector(module); + fail(); } catch (CreationException e) { assertEquals(2, e.getErrorMessages().size()); } @@ -537,9 +634,10 @@ public void testBindingProviderWithProviderSubclassValue() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind private Provider anIntProvider = new IntegerProvider(testValue); - }; + Object instance = + new Object() { + @Bind private Provider anIntProvider = new IntegerProvider(testValue); + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -548,34 +646,36 @@ } public void testBoundFieldsCannotBeInjected() { - Object instance = new Object() { - @Bind - @Inject - Integer anInt = 0; - }; + Object instance = + new Object() { + @Bind @Inject Integer anInt = 0; + }; BoundFieldModule module = BoundFieldModule.of(instance); try { Guice.createInjector(module); + fail(); } catch (CreationException e) { - assertContains( - e.getMessage(), - "Fields annotated with both @Bind and @Inject are illegal."); + assertContains(e.getMessage(), "Fields annotated with both @Bind and @Inject are illegal."); } } public void testIncrementingProvider() { final Integer testBaseValue = 1024; - Object instance = new Object() { - @Bind private Provider anIntProvider = new Provider() { - private int value = testBaseValue; - - @Override public Integer get() { - return value++; - } - }; - }; + Object instance = + new Object() { + @Bind + private Provider anIntProvider = + new Provider() { + private int value = testBaseValue; + + @Override + public Integer get() { + return value++; + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -586,13 +686,17 @@ } public void testProviderDoesNotProvideDuringInjectorConstruction() { - Object instance = new Object() { - @Bind private Provider myIntProvider = new Provider() { - @Override public Integer get() { - throw new UnsupportedOperationException(); - } - }; - }; + Object instance = + new Object() { + @Bind + private Provider myIntProvider = + new Provider() { + @Override + public Integer get() { + throw new UnsupportedOperationException(); + } + }; + }; BoundFieldModule module = BoundFieldModule.of(instance); Guice.createInjector(module); @@ -601,7 +705,8 @@ } private static class InvalidBindableClass { - @Bind(to = String.class) Integer anInt; + @Bind(to = String.class) + Integer anInt; } public void testIncompatibleBindingTypeStackTraceHasUserFrame() { @@ -620,17 +725,19 @@ private static class InjectedNumberProvider implements Provider { @Inject Integer anInt; - @Override public Number get() { + @Override + public Number get() { return anInt; } } public void testBoundProvidersAreInjected() { final Integer testValue = 1024; - Object instance = new Object() { - @Bind private Integer anInt = testValue; - @Bind private Provider aNumberProvider = new InjectedNumberProvider(); - }; + Object instance = + new Object() { + @Bind private Integer anInt = testValue; + @Bind private Provider aNumberProvider = new InjectedNumberProvider(); + }; BoundFieldModule module = BoundFieldModule.of(instance); Injector injector = Guice.createInjector(module); @@ -641,10 +748,11 @@ public void testBoundInstancesAreInjected() { final Integer testValue = 1024; final InjectedNumberProvider testNumberProvider = new InjectedNumberProvider(); - Object instance = new Object() { - @Bind private Integer anInt = testValue; - @Bind private InjectedNumberProvider aNumberProvider = testNumberProvider; - }; + Object instance = + new Object() { + @Bind private Integer anInt = testValue; + @Bind private InjectedNumberProvider aNumberProvider = testNumberProvider; + }; BoundFieldModule module = BoundFieldModule.of(instance); Guice.createInjector(module); @@ -661,11 +769,12 @@ try { Guice.createInjector(module); + fail(); } catch (CreationException e) { assertContains( e.getMessage(), "Requested binding type \"java.lang.String\" is not assignable from field binding type " - + "\"java.lang.Integer\""); + + "\"java.lang.Integer\""); } } @@ -690,7 +799,8 @@ } static final class LazyClass { - @Bind(lazy = true) Integer foo = 1; + @Bind(lazy = true) + Integer foo = 1; } public void testFieldBound_lazy() { @@ -701,7 +811,7 @@ assertEquals(2, injector.getInstance(Integer.class).intValue()); } - public void testFieldBound_lazy_rejectNull() { + public void testNonNullableFieldBound_lazy_rejectNull() { LazyClass asProvider = new LazyClass(); Injector injector = Guice.createInjector(BoundFieldModule.of(asProvider)); assertEquals(1, injector.getInstance(Integer.class).intValue()); @@ -710,23 +820,72 @@ injector.getInstance(Integer.class); fail(); } catch (ProvisionException e) { - assertContains(e.getMessage(), - "Binding to null values is not allowed. " - + "Use Providers.of(null) if this is your intended behavior."); + assertContains( + e.getMessage(), + "Binding to null values is only allowed for fields that are annotated @Nullable."); } } + static final class LazyClassNullable { + @Bind(lazy = true) + @Nullable + Integer foo = 1; + } + + public void testNullableFieldBound_lazy_allowNull() { + LazyClassNullable asProvider = new LazyClassNullable(); + Injector injector = Guice.createInjector(BoundFieldModule.of(asProvider)); + assertEquals(1, injector.getInstance(Integer.class).intValue()); + asProvider.foo = null; + assertNull(injector.getInstance(Integer.class)); + } + static final class LazyProviderClass { - @Bind(lazy = true) Provider foo = Providers.of(null); + @Bind(lazy = true) + Provider foo = Providers.of(null); } - public void testFieldBoundAsProvider_rejectProvider() { + public void testFieldBoundAsProvider_lazy() { LazyProviderClass asProvider = new LazyProviderClass(); + Provider provider = + Guice.createInjector(BoundFieldModule.of(asProvider)).getProvider(Integer.class); + assertNull(provider.get()); + asProvider.foo = Providers.of(1); + assertEquals(1, provider.get().intValue()); + asProvider.foo = + new Provider() { + @Override + public Integer get() { + throw new RuntimeException("boom"); + } + }; try { - Guice.createInjector(BoundFieldModule.of(asProvider)); + provider.get(); fail(); - } catch (CreationException e) { - assertContains(e.getMessage(), "'lazy' is incompatible with Provider valued fields"); + } catch (ProvisionException e) { + assertContains(e.getMessage(), "boom"); + } + } + + private static final class LazyNonTransparentProvider { + @Bind(lazy = true) + @Nullable + private IntegerProvider anIntProvider = null; + } + + public void testFieldBoundAsNonTransparentProvider_lazy() { + LazyNonTransparentProvider instance = new LazyNonTransparentProvider(); + BoundFieldModule module = BoundFieldModule.of(instance); + Injector injector = Guice.createInjector(module); + + assertNull(injector.getInstance(IntegerProvider.class)); + instance.anIntProvider = new IntegerProvider(3); + assertEquals(3, injector.getInstance(IntegerProvider.class).get().intValue()); + try { + injector.getInstance(Integer.class); + fail(); + } catch (ConfigurationException expected) { + // expected because we don't interpret IntegerProvider as a Provider } } } diff -Nru sisu-guice-3.2.6/extensions/testlib/test/com/google/inject/testing/throwingproviders/CheckedProviderSubjectTest.java sisu-guice-4.2.0/extensions/testlib/test/com/google/inject/testing/throwingproviders/CheckedProviderSubjectTest.java --- sisu-guice-3.2.6/extensions/testlib/test/com/google/inject/testing/throwingproviders/CheckedProviderSubjectTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/testlib/test/com/google/inject/testing/throwingproviders/CheckedProviderSubjectTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,120 @@ +package com.google.inject.testing.throwingproviders; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.inject.testing.throwingproviders.CheckedProviderSubject.assertThat; + +import com.google.common.truth.ExpectFailure; +import com.google.common.truth.SimpleSubjectBuilder; +import com.google.inject.throwingproviders.CheckedProvider; +import com.google.inject.throwingproviders.CheckedProviders; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit tests for {@link CheckedProviderSubject}. + * + * @author eatnumber1@google.com (Russ Harmon) + */ +@RunWith(JUnit4.class) +public class CheckedProviderSubjectTest { + public @Rule ExpectFailure expect = new ExpectFailure(); + + private interface StringCheckedProvider extends CheckedProvider {} + + @Test + public void providedValue_gotExpected_expectSuccess() { + String expected = "keep Summer safe"; + CheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, expected); + + assertThat(provider).providedValue().isEqualTo(expected); + } + + @Test + public void providedValue_gotUnexpected_expectFailure() { + String expected = "keep Summer safe"; + String unexpected = "Summer is unsafe"; + CheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, unexpected); + String message = + String.format( + "value provided by <%s>: Not true that <%s> is equal to <%s>", + getReturningProviderName(unexpected), unexpected, expected); + + expectWhenTesting().that(provider).providedValue().isEqualTo(expected); + assertThat(expect.getFailure()).hasMessageThat().isEqualTo(message); + } + + private static final class SummerException extends RuntimeException {} + + @Test + public void providedValue_throws_expectFailure() { + CheckedProvider provider = + CheckedProviders.throwing(StringCheckedProvider.class, SummerException.class); + String message = + String.format( + "checked provider <%s> threw an exception", + getThrowingProviderName(SummerException.class.getName())); + + expectWhenTesting().that(provider).providedValue(); + AssertionError expected = expect.getFailure(); + assertThat(expected).hasCauseThat().isInstanceOf(SummerException.class); + assertThat(expected).hasMessageThat().isEqualTo(message); + } + + @Test + public void thrownException_threwExpected_expectSuccess() { + CheckedProvider provider = + CheckedProviders.throwing(StringCheckedProvider.class, SummerException.class); + + assertThat(provider).thrownException().isInstanceOf(SummerException.class); + } + + @Test + public void thrownException_threwUnexpected_expectFailure() { + Class expected = SummerException.class; + Class unexpected = UnsupportedOperationException.class; + CheckedProvider provider = + CheckedProviders.throwing(StringCheckedProvider.class, unexpected); + String message = + String.format( + "exception thrown by <%s>: Not true that <%s> is an instance of <%s>. " + + "It is an instance of <%s>", + getThrowingProviderName(UnsupportedOperationException.class.getName()), + UnsupportedOperationException.class.getName(), + SummerException.class.getName(), + UnsupportedOperationException.class.getName()); + + expectWhenTesting().that(provider).thrownException().isInstanceOf(expected); + assertThat(expect.getFailure()).hasMessageThat().isEqualTo(message); + } + + @Test + public void thrownException_gets_expectFailure() { + String getValue = "keep WINTER IS COMING safe"; + CheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, getValue); + String message = + String.format( + "Not true that <%s> threw . It provided <%s>", + getReturningProviderName(getValue), getValue); + + expectWhenTesting().that(provider).thrownException(); + assertThat(expect.getFailure()).hasMessageThat().isEqualTo(message); + } + + private SimpleSubjectBuilder< + CheckedProviderSubject>, CheckedProvider> + expectWhenTesting() { + return expect + .whenTesting() + .about(CheckedProviderSubject.>checkedProviders()); + } + + private String getReturningProviderName(String providing) { + return String.format("generated CheckedProvider returning <%s>", providing); + } + + private String getThrowingProviderName(String throwing) { + return String.format("generated CheckedProvider throwing <%s>", throwing); + } +} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/pom.xml sisu-guice-4.2.0/extensions/throwingproviders/pom.xml --- sisu-guice-3.2.6/extensions/throwingproviders/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -6,7 +6,7 @@ org.sonatype.sisu.inject extensions-parent - 3.2.6 + 4.2.0 guice-throwingproviders @@ -23,6 +23,28 @@ + + maven-jar-plugin + + + + com.google.guice.extensions.throwingproviders + + + + + + + + com.google.truth + truth + + + com.google.code.findbugs + jsr305 + true + + diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,21 +17,22 @@ package com.google.inject.throwingproviders; /** - * Alternative to the Guice {@link com.google.inject.Provider} that throws - * a checked Exception. Users may not inject {@code T} directly. + * Alternative to the Guice {@link com.google.inject.Provider} that throws a checked Exception. + * Users may not inject {@code T} directly. + * + *

    This interface must be extended to use application-specific exception types. Such + * subinterfaces may not define new methods, but may narrow the exception type. * - *

    This interface must be extended to use application-specific exception types. - * Such subinterfaces may not define new methods, but may narrow the exception type. *

    - * public interface RemoteProvider<T> extends CheckedProvider<T> { 
    + * public interface RemoteProvider<T> extends CheckedProvider<T> {
      *   T get() throws CustomExceptionOne, CustomExceptionTwo;
      * }
      * 
    * - *

    When this type is bound using {@link ThrowingProviderBinder}, the value returned - * or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get} - * will invoked at most once within each scope. - * + *

    When this type is bound using {@link ThrowingProviderBinder}, the value returned or exception + * thrown by {@link #get} will be scoped. As a consequence, {@link #get} will invoked at most once + * within each scope. + * * @since 3.0 */ public interface CheckedProvider { diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,6 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder; - import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -79,17 +78,16 @@ void configure(Binder binder) { binder = binder.withSource(method); - SecondaryBinder sbinder = - ThrowingProviderBinder.create(binder) - .bind(checkedProvider, key.getTypeLiteral()); - if(key.getAnnotation() != null) { + SecondaryBinder sbinder = + ThrowingProviderBinder.create(binder).bind(checkedProvider, key.getTypeLiteral()); + if (key.getAnnotation() != null) { sbinder = sbinder.annotatedWith(key.getAnnotation()); - } else if(key.getAnnotationType() != null) { + } else if (key.getAnnotationType() != null) { sbinder = sbinder.annotatedWith(key.getAnnotationType()); } sbinder.scopeExceptions(scopeExceptions); ScopedBindingBuilder sbbuilder = sbinder.toProviderMethod(this); - if(scopeAnnotation != null) { + if (scopeAnnotation != null) { sbbuilder.in(scopeAnnotation); } @@ -98,11 +96,12 @@ // misplaced @Exposed, calling this will add an error to the binder's error queue ((PrivateBinder) binder).expose(sbinder.getKey()); } - + CheckedProvideUtils.validateExceptions( binder, exceptionTypes, sbinder.getExceptionTypes(), checkedProvider); } + @Override public T get() throws Exception { Object[] parameters = new Object[parameterProviders.size()]; for (int i = 0; i < parameters.length; i++) { @@ -111,28 +110,30 @@ try { // We know this cast is safe becase T is the method's return type. - @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" }) + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) T result = (T) method.invoke(instance, parameters); return result; } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); - if(t instanceof Exception) { - throw (Exception)t; - } else if(t instanceof Error) { - throw (Error)t; + if (t instanceof Exception) { + throw (Exception) t; + } else if (t instanceof Error) { + throw (Error) t; } else { throw new IllegalStateException(t); } } } + @Override public Set> getDependencies() { return dependencies; } - @Override public String toString() { + @Override + public String toString() { return "@CheckedProvides " + StackTraceElements.forMember(method); } } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,6 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.Message; import com.google.inject.util.Modules; - import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.lang.reflect.Method; @@ -39,9 +38,9 @@ import java.util.logging.Logger; /** - * Creates bindings to methods annotated with {@literal @}{@link CheckedProvides}. Use the scope - * and binding annotations on the provider method to configure the binding. - * + * Creates bindings to methods annotated with {@literal @}{@link CheckedProvides}. Use the scope and + * binding annotations on the provider method to configure the binding. + * * @author sameb@google.com (Sam Berlin) */ final class CheckedProviderMethodsModule implements Module { @@ -55,9 +54,7 @@ this.typeLiteral = TypeLiteral.get(this.delegate.getClass()); } - /** - * Returns a module which creates bindings for provider methods from the given module. - */ + /** Returns a module which creates bindings for provider methods from the given module. */ static Module forModule(Module module) { // avoid infinite recursion, since installing a module always installs itself if (module instanceof CheckedProviderMethodsModule) { @@ -66,7 +63,8 @@ return new CheckedProviderMethodsModule(module); } - + + @Override public synchronized void configure(Binder binder) { for (CheckedProviderMethod throwingProviderMethod : getProviderMethods(binder)) { throwingProviderMethod.configure(binder); @@ -78,7 +76,7 @@ for (Class c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) { for (Method method : c.getDeclaredMethods()) { CheckedProvides checkedProvides = method.getAnnotation(CheckedProvides.class); - if(checkedProvides != null) { + if (checkedProvides != null) { result.add(createProviderMethod(binder, method, checkedProvides)); } } @@ -86,8 +84,8 @@ return result; } - CheckedProviderMethod createProviderMethod(Binder binder, final Method method, - CheckedProvides checkedProvides) { + CheckedProviderMethod createProviderMethod( + Binder binder, final Method method, CheckedProvides checkedProvides) { @SuppressWarnings("rawtypes") Class throwingProvider = checkedProvides.value(); binder = binder.withSource(method); @@ -109,7 +107,7 @@ key = loggerKey; } dependencies.add(Dependency.get(key)); - parameterProviders.add(binder.getProvider(key)); + parameterProviders.add(binder.getProvider(key)); } @SuppressWarnings("unchecked") // Define T as the method's return type. @@ -117,16 +115,23 @@ List> exceptionTypes = typeLiteral.getExceptionTypes(method); Key key = getKey(errors, returnType, method, method.getAnnotations()); - Class scopeAnnotation - = Annotations.findScopeAnnotation(errors, method.getAnnotations()); + Class scopeAnnotation = + Annotations.findScopeAnnotation(errors, method.getAnnotations()); for (Message message : errors.getMessages()) { binder.addError(message); } - return new CheckedProviderMethod(key, method, delegate, ImmutableSet.copyOf(dependencies), - parameterProviders, scopeAnnotation, throwingProvider, exceptionTypes, - checkedProvides.scopeExceptions()); + return new CheckedProviderMethod( + key, + method, + delegate, + ImmutableSet.copyOf(dependencies), + parameterProviders, + scopeAnnotation, + throwingProvider, + exceptionTypes, + checkedProvides.scopeExceptions()); } Key getKey(Errors errors, TypeLiteral type, Member member, Annotation[] annotations) { @@ -134,23 +139,26 @@ return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation); } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { return o instanceof CheckedProviderMethodsModule && ((CheckedProviderMethodsModule) o).delegate == delegate; } - @Override public int hashCode() { + @Override + public int hashCode() { return delegate.hashCode(); } - + /** A provider that returns a logger based on the method name. */ private static final class LogProvider implements Provider { private final String name; - + public LogProvider(Method method) { this.name = method.getDeclaringClass().getName() + "." + method.getName(); } - + + @Override public Logger get() { return Logger.getLogger(name); } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviders.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviders.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviders.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviders.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,238 @@ +package com.google.inject.throwingproviders; + +import static com.google.inject.throwingproviders.ProviderChecker.checkInterface; + +import com.google.common.base.Optional; +import com.google.inject.TypeLiteral; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Nullable; + +/** + * Static utility methods for creating and working with instances of {@link CheckedProvider}. + * + * @author eatnumber1@google.com (Russ Harmon) + * @since 4.2 + */ +public final class CheckedProviders { + private abstract static class CheckedProviderInvocationHandler implements InvocationHandler { + private boolean isGetMethod(Method method) { + // Since Java does not allow multiple methods with the same name and number & type of + // arguments, this is all we need to check to see if it is an overriding method of + // CheckedProvider#get(). + return method.getName().equals("get") && method.getParameterTypes().length == 0; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getDeclaringClass() == Object.class) { + return method.invoke(this, args); + } else if (isGetMethod(method)) { + return invokeGet(proxy, method); + } + throw new UnsupportedOperationException( + String.format( + "Unsupported method <%s> with args <%s> invoked on <%s>", + method, Arrays.toString(args), proxy)); + } + + protected abstract T invokeGet(Object proxy, Method method) throws Throwable; + + @Override + public abstract String toString(); + } + + private static final class ReturningHandler extends CheckedProviderInvocationHandler { + private final T returned; + + ReturningHandler(T returned) { + this.returned = returned; + } + + @Override + protected T invokeGet(Object proxy, Method method) throws Throwable { + return returned; + } + + @Override + public String toString() { + return String.format("generated CheckedProvider returning <%s>", returned); + } + } + + private static final class ThrowingHandler extends CheckedProviderInvocationHandler { + private final Constructor throwableCtor; + private final String typeName; + + private ThrowingHandler(Constructor throwableCtor, String typeName) { + this.throwableCtor = throwableCtor; + this.typeName = typeName; + + this.throwableCtor.setAccessible(true); + } + + static ThrowingHandler forClass(Class throwable) { + try { + return new ThrowingHandler(throwable.getDeclaredConstructor(), throwable.getName()); + } catch (NoSuchMethodException e) { + // This should have been caught by checkThrowable + throw new AssertionError( + String.format( + "Throwable <%s> does not have a no-argument constructor", throwable.getName())); + } + } + + @Override + protected Object invokeGet(Object proxy, Method method) throws Throwable { + throw this.throwableCtor.newInstance(); + } + + @Override + public String toString() { + return String.format("generated CheckedProvider throwing <%s>", this.typeName); + } + } + + private CheckedProviders() {} + + private static > P generateProvider( + Class

    providerType, Optional value, InvocationHandler handler) { + checkInterface(providerType, getClassOptional(value)); + Object proxy = + Proxy.newProxyInstance( + providerType.getClassLoader(), new Class[] {providerType}, handler); + @SuppressWarnings("unchecked") // guaranteed by the newProxyInstance API + P proxyP = (P) proxy; + return proxyP; + } + + private static > P generateProvider( + TypeLiteral

    providerType, Optional value, InvocationHandler handler) { + // TODO(eatnumber1): Understand why TypeLiteral#getRawType returns a Class rather + // than a Class and remove this unsafe cast. + Class

    providerRaw = (Class) providerType.getRawType(); + return generateProvider(providerRaw, value, handler); + } + + private static Optional> getClassOptional(Optional value) { + if (!value.isPresent()) { + return Optional.absent(); + } + return Optional.>of(value.get().getClass()); + } + + /** + * Returns a {@link CheckedProvider} which always provides {@code instance}. + * + *

    The provider type passed as {@code providerType} must be an interface. Calls to methods + * other than {@link CheckedProvider#get} will throw {@link UnsupportedOperationException}. + * + * @param providerType the type of the {@link CheckedProvider} to return + * @param instance the instance that should always be provided + */ + public static > P of( + TypeLiteral

    providerType, @Nullable T instance) { + return generateProvider( + providerType, Optional.fromNullable(instance), new ReturningHandler(instance)); + } + + /** + * Returns a {@link CheckedProvider} which always provides {@code instance}. + * + * @param providerType the type of the {@link CheckedProvider} to return + * @param instance the instance that should always be provided + * @see #of(TypeLiteral, T) + */ + public static > P of( + Class

    providerType, @Nullable T instance) { + return of(TypeLiteral.get(providerType), instance); + } + + /** + * Returns a {@link CheckedProvider} which always throws exceptions. + * + *

    This method uses the nullary (no argument) constructor of {@code throwable} to create a new + * instance of the given {@link Throwable} on each method invocation which is then thrown + * immediately. + * + *

    See {@link #of(TypeLiteral, T)} for more information. + * + * @param providerType the type of the {@link CheckedProvider} to return + * @param throwable the type of the {@link Throwable} to throw + * @see #of(TypeLiteral, T) + */ + public static > P throwing( + TypeLiteral

    providerType, Class throwable) { + // TODO(eatnumber1): Understand why TypeLiteral#getRawType returns a Class rather + // than a Class and remove this unsafe cast. + Class

    providerRaw = (Class) providerType.getRawType(); + checkThrowable(providerRaw, throwable); + return generateProvider( + providerType, Optional.absent(), ThrowingHandler.forClass(throwable)); + } + + /** + * Returns a {@link CheckedProvider} which always throws exceptions. + * + * @param providerType the type of the {@link CheckedProvider} to return + * @param throwable the type of the {@link Throwable} to throw + * @see #throwing(TypeLiteral, Class) + */ + public static > P throwing( + Class

    providerType, Class throwable) { + return throwing(TypeLiteral.get(providerType), throwable); + } + + private static boolean isCheckedException(Class thrownType) { + return Exception.class.isAssignableFrom(thrownType) + && !RuntimeException.class.isAssignableFrom(thrownType); + } + + private static void checkThrowable( + Class> providerType, Class thrownType) { + try { + thrownType.getDeclaredConstructor(); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException( + String.format( + "Thrown exception <%s> must have a no-argument constructor", thrownType.getName()), + e); + } + + if (!isCheckedException(thrownType)) { + return; + } + + Method getMethod; + try { + getMethod = providerType.getMethod("get"); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException( + String.format("Provider class <%s> must have a get() method", providerType.getName()), e); + } + + @SuppressWarnings("unchecked") // guaranteed by getExceptionTypes + List> exceptionTypes = + Arrays.asList((Class[]) getMethod.getExceptionTypes()); + + if (exceptionTypes.size() == 0) { + return; + } + + // Check if the thrown exception is declared to be thrown in the method signature. + for (Class exceptionType : exceptionTypes) { + if (exceptionType.isAssignableFrom(thrownType)) { + return; + } + } + + throw new IllegalArgumentException( + String.format( + "Thrown exception <%s> is not declared to be thrown by <%s>", + thrownType.getName(), getMethod)); + } +} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,11 +20,9 @@ import com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder; /** - * A checked provider with dependencies, so {@link HasDependencies} can be implemented - * when using the {@link SecondaryBinder#using} methods. - * + * A checked provider with dependencies, so {@link HasDependencies} can be implemented when using + * the {@link SecondaryBinder#using} methods. + * * @author sameb@google.com (Sam Berlin) */ -interface CheckedProviderWithDependencies extends CheckedProvider, HasDependencies { - -} +interface CheckedProviderWithDependencies extends CheckedProvider, HasDependencies {} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,28 +24,29 @@ import java.lang.annotation.Target; /** - * Annotates methods of a {@link com.google.inject.Module} to create a - * {@link CheckedProvider} method binding that can throw exceptions. The - * method's return type is bound to a {@link CheckedProvider} that can be - * injected. Guice will pass dependencies to the method as parameters. Install - * {@literal @}CheckedProvides methods by using - * {@link ThrowingProviderBinder#forModule(com.google.inject.Module)} on the - * module where the methods are declared. - * + * Annotates methods of a {@link com.google.inject.Module} to create a {@link CheckedProvider} + * method binding that can throw exceptions. The method's return type is bound to a {@link + * CheckedProvider} that can be injected. Guice will pass dependencies to the method as parameters. + * Install {@literal @}CheckedProvides methods by using {@link + * ThrowingProviderBinder#forModule(com.google.inject.Module)} on the module where the methods are + * declared. + * * @author sameb@google.com (Sam Berlin) * @since 3.0 */ -@Documented @Target(METHOD) @Retention(RUNTIME) +@Documented +@Target(METHOD) +@Retention(RUNTIME) public @interface CheckedProvides { - - /** - * The interface that provides this value, a subinterface of {@link CheckedProvider}. - */ + + /** The interface that provides this value, a subinterface of {@link CheckedProvider}. */ Class value(); /** - * Whether exceptions should be put into the Guice scope. - * Default behavior is that exceptions are scoped. + * Whether exceptions should be put into the Guice scope. Default behavior is that exceptions are + * scoped. + * + * @since 4.0 */ - boolean scopeExceptions() default true; + boolean scopeExceptions() default true; } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,46 +21,48 @@ import com.google.inject.internal.Annotations; import com.google.inject.internal.Errors; import com.google.inject.spi.Message; - import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; /** * Utilities for the throwing provider module. - * + * * @author sameb@google.com (Sam Berlin) */ class CheckedProvideUtils { - + private CheckedProvideUtils() {} - + private static final String CONSTRUCTOR_RULES = "Classes must have either one (and only one) constructor annotated with @ThrowingInject."; - + @SuppressWarnings("unchecked") // safe because it's a constructor of the typeLiteral static Constructor findThrowingConstructor( TypeLiteral typeLiteral, Binder binder) { - + Class rawType = typeLiteral.getRawType(); Errors errors = new Errors(rawType); Constructor cxtor = null; for (Constructor constructor : rawType.getDeclaredConstructors()) { if (constructor.isAnnotationPresent(ThrowingInject.class)) { if (cxtor != null) { - errors.addMessage("%s has more than one constructor annotated with @ThrowingInject. " - + CONSTRUCTOR_RULES, rawType); + errors.addMessage( + "%s has more than one constructor annotated with @ThrowingInject. " + + CONSTRUCTOR_RULES, + rawType); } cxtor = constructor; - Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation( - errors, cxtor, ((AnnotatedElement) cxtor).getAnnotations()); + Annotation misplacedBindingAnnotation = + Annotations.findBindingAnnotation( + errors, cxtor, ((AnnotatedElement) cxtor).getAnnotations()); if (misplacedBindingAnnotation != null) { errors.misplacedBindingAnnotation(cxtor, misplacedBindingAnnotation); } } } - + if (cxtor == null) { errors.addMessage( "Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES, rawType); @@ -71,9 +73,10 @@ } return (Constructor) cxtor; } - + /** Adds errors to the binder if the exceptions aren't valid. */ - static void validateExceptions(Binder binder, + static void validateExceptions( + Binder binder, Iterable> actualExceptionTypes, Iterable> expectedExceptionTypes, Class checkedProvider) { @@ -96,11 +99,10 @@ } if (notAssignable) { binder.addError( - "%s is not compatible with the exceptions (%s) declared in " - + "the CheckedProvider interface (%s)", + "%s is not compatible with the exceptions (%s) declared in " + + "the CheckedProvider interface (%s)", exActual, expectedExceptionTypes, checkedProvider); } } } - } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java 2018-04-03 18:18:08.000000000 +0000 @@ -16,6 +16,6 @@ /** * Extension for injecting objects that may throw at provision time; this extension requires {@code - * guice-throwingproviders-3.0.jar}. + * guice-throwingproviders.jar}. */ -package com.google.inject.throwingproviders; \ No newline at end of file +package com.google.inject.throwingproviders; diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ProviderChecker.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ProviderChecker.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ProviderChecker.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ProviderChecker.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,120 @@ +package com.google.inject.throwingproviders; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.inject.internal.Errors; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.List; + +/** Helper methods to verify the correctness of CheckedProvider interfaces. */ +final class ProviderChecker { + + private ProviderChecker() {} + + static

    > void checkInterface( + Class

    interfaceType, Optional valueType) { + checkArgument(interfaceType.isInterface(), "%s must be an interface", interfaceType.getName()); + checkArgument( + interfaceType.getGenericInterfaces().length == 1, + "%s must extend CheckedProvider (and only CheckedProvider)", + interfaceType); + + boolean tpMode = interfaceType.getInterfaces()[0] == ThrowingProvider.class; + if (!tpMode) { + checkArgument( + interfaceType.getInterfaces()[0] == CheckedProvider.class, + "%s must extend CheckedProvider (and only CheckedProvider)", + interfaceType); + } + + // Ensure that T is parameterized and unconstrained. + ParameterizedType genericThrowingProvider = + (ParameterizedType) interfaceType.getGenericInterfaces()[0]; + if (interfaceType.getTypeParameters().length == 1) { + String returnTypeName = interfaceType.getTypeParameters()[0].getName(); + Type returnType = genericThrowingProvider.getActualTypeArguments()[0]; + checkArgument( + returnType instanceof TypeVariable, + "%s does not properly extend CheckedProvider, the first type parameter of CheckedProvider" + + " (%s) is not a generic type", + interfaceType, + returnType); + checkArgument( + returnTypeName.equals(((TypeVariable) returnType).getName()), + "The generic type (%s) of %s does not match the generic type of CheckedProvider (%s)", + returnTypeName, + interfaceType, + ((TypeVariable) returnType).getName()); + } else { + checkArgument( + interfaceType.getTypeParameters().length == 0, + "%s has more than one generic type parameter: %s", + interfaceType, + Arrays.asList(interfaceType.getTypeParameters())); + if (valueType.isPresent()) { + checkArgument( + genericThrowingProvider.getActualTypeArguments()[0].equals(valueType.get()), + "%s expects the value type to be %s, but it was %s", + interfaceType, + genericThrowingProvider.getActualTypeArguments()[0], + valueType.get()); + } + } + + if (tpMode) { // only validate exception in ThrowingProvider mode. + Type exceptionType = genericThrowingProvider.getActualTypeArguments()[1]; + checkArgument( + exceptionType instanceof Class, + "%s has the wrong Exception generic type (%s) when extending CheckedProvider", + interfaceType, + exceptionType); + } + + // Skip synthetic/bridge methods because java8 generates + // a default method on the interface w/ the superinterface type that + // just delegates directly to the overridden method. + List declaredMethods = + FluentIterable.from(Arrays.asList(interfaceType.getDeclaredMethods())) + .filter(NotSyntheticOrBridgePredicate.INSTANCE) + .toList(); + if (declaredMethods.size() == 1) { + Method method = declaredMethods.get(0); + checkArgument( + method.getName().equals("get"), + "%s may not declare any new methods, but declared %s", + interfaceType, + method); + checkArgument( + method.getParameterTypes().length == 0, + "%s may not declare any new methods, but declared %s", + interfaceType, + method.toGenericString()); + } else { + checkArgument( + declaredMethods.isEmpty(), + "%s may not declare any new methods, but declared %s", + interfaceType, + Arrays.asList(interfaceType.getDeclaredMethods())); + } + } + + private static void checkArgument(boolean condition, String messageFormat, Object... args) { + if (!condition) { + throw new IllegalArgumentException(Errors.format(messageFormat, args)); + } + } + + private static class NotSyntheticOrBridgePredicate implements Predicate { + static final NotSyntheticOrBridgePredicate INSTANCE = new NotSyntheticOrBridgePredicate(); + + @Override + public boolean apply(Method input) { + return !input.isBridge() && !input.isSynthetic(); + } + } +} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,24 +20,24 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.Inject; - import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** - * A version of {@literal @}{@link Inject} designed for ThrowingProviders. Use by: + * A version of {@literal @}{@link Inject} designed for ThrowingProviders. Use by: + * *

    ThrowingProviderBinder.create(binder())
      *    .bind(RemoteProvider.class, Customer.class)
      *    .providing(CustomerImpl.class);
      * 
    + * * where CustomerImpl has a constructor annotated with ThrowingInject. * * @author sameb@google.com (Sam Berlin) * @since 4.0 */ -@Target({ CONSTRUCTOR }) +@Target({CONSTRUCTOR}) @Retention(RUNTIME) @Documented -public @interface ThrowingInject { -} +public @interface ThrowingInject {} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,8 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; @@ -35,7 +34,6 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.ProviderWithDependencies; import com.google.inject.util.Types; - import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; @@ -44,26 +42,27 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.Arrays; import java.util.List; import java.util.Set; /** - *

    Builds a binding for a {@link CheckedProvider}. - * + * Builds a binding for a {@link CheckedProvider}. + * *

    You can use a fluent API and custom providers: + * *

    ThrowingProviderBinder.create(binder())
      *    .bind(RemoteProvider.class, Customer.class)
      *    .to(RemoteCustomerProvider.class)
      *    .in(RequestScope.class);
      * 
    + * * or, you can use throwing provider methods: + * *
    class MyModule extends AbstractModule {
      *   configure() {
    - *     ThrowingProviderBinder.install(this, binder());
    + *     install(ThrowingProviderBinder.forModule(this));
      *   }
    - *   
    + *
      *   {@literal @}CheckedProvides(RemoteProvider.class)
      *   {@literal @}RequestScope
      *   Customer provideCustomer(FlakyCustomerCreator creator) throws RemoteException {
    @@ -71,25 +70,27 @@
      *   }
      * }
      * 
    - * You also can declare that a CheckedProvider construct - * a particular class whose constructor throws an exception: + * + * You also can declare that a CheckedProvider construct a particular class whose constructor throws + * an exception: + * *
    ThrowingProviderBinder.create(binder())
      *    .bind(RemoteProvider.class, Customer.class)
      *    .providing(CustomerImpl.class)
      *    .in(RequestScope.class);
      * 
    - * + * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) * @author sameb@google.com (Sam Berlin) */ public class ThrowingProviderBinder { - private static final TypeLiteral> CHECKED_PROVIDER_TYPE - = new TypeLiteral>() { }; + private static final TypeLiteral> CHECKED_PROVIDER_TYPE = + new TypeLiteral>() {}; - private static final TypeLiteral> CHECKED_PROVIDER_METHOD_TYPE - = new TypeLiteral>() { }; + private static final TypeLiteral> CHECKED_PROVIDER_METHOD_TYPE = + new TypeLiteral>() {}; private final Binder binder; @@ -98,42 +99,36 @@ } public static ThrowingProviderBinder create(Binder binder) { - return new ThrowingProviderBinder(binder.skipSources( - ThrowingProviderBinder.class, - ThrowingProviderBinder.SecondaryBinder.class)); + return new ThrowingProviderBinder( + binder.skipSources( + ThrowingProviderBinder.class, ThrowingProviderBinder.SecondaryBinder.class)); } - + /** * Returns a module that installs {@literal @}{@link CheckedProvides} methods. - * + * * @since 3.0 */ public static Module forModule(Module module) { return CheckedProviderMethodsModule.forModule(module); } - - /** - * @deprecated Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead. - */ + + /** @deprecated Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead. */ @Deprecated - public

    SecondaryBinder - bind(Class

    interfaceType, Type clazz) { + public

    SecondaryBinder bind( + Class

    interfaceType, Type clazz) { return new SecondaryBinder(interfaceType, clazz); } - /** - * @since 4.0 - */ - public

    SecondaryBinder - bind(Class

    interfaceType, Class clazz) { + /** @since 4.0 */ + public

    SecondaryBinder bind( + Class

    interfaceType, Class clazz) { return new SecondaryBinder(interfaceType, clazz); } - - /** - * @since 4.0 - */ - public

    SecondaryBinder - bind(Class

    interfaceType, TypeLiteral typeLiteral) { + + /** @since 4.0 */ + public

    SecondaryBinder bind( + Class

    interfaceType, TypeLiteral typeLiteral) { return new SecondaryBinder(interfaceType, typeLiteral.getType()); } @@ -151,19 +146,19 @@ public SecondaryBinder(Class

    interfaceType, Type valueType) { this.interfaceType = checkNotNull(interfaceType, "interfaceType"); this.valueType = checkNotNull(valueType, "valueType"); - if(checkInterface()) { + if (checkInterface()) { this.exceptionTypes = getExceptionType(interfaceType); valid = true; } else { valid = false; this.exceptionTypes = ImmutableList.of(); - } + } } - + List> getExceptionTypes() { return exceptionTypes; } - + Key

    getKey() { return interfaceKey; } @@ -186,6 +181,7 @@ /** * Determines if exceptions should be scoped. By default exceptions are scoped. + * * @param scopeExceptions whether exceptions should be scoped. * @since 4.0 */ @@ -193,23 +189,25 @@ this.scopeExceptions = scopeExceptions; return this; } - + public ScopedBindingBuilder to(P target) { Key

    targetKey = Key.get(interfaceType, UniqueAnnotations.create()); binder.bind(targetKey).toInstance(target); return to(targetKey); } - + public ScopedBindingBuilder to(Class targetType) { return to(Key.get(targetType)); } - + + /** @since 4.0 */ public ScopedBindingBuilder providing(Class cxtorClass) { return providing(TypeLiteral.get(cxtorClass)); } - + + /** @since 4.0 */ @SuppressWarnings("unchecked") // safe because this is the cxtor of the literal - public ScopedBindingBuilder providing(TypeLiteral cxtorLiteral) { + public ScopedBindingBuilder providing(TypeLiteral cxtorLiteral) { // Find a constructor that has @ThrowingInject. Constructor cxtor = CheckedProvideUtils.findThrowingConstructor(cxtorLiteral, binder); @@ -221,7 +219,7 @@ // Validate the exceptions are consistent with the CheckedProvider interface. CheckedProvideUtils.validateExceptions( binder, cxtorLiteral.getExceptionTypes(cxtor), exceptionTypes, interfaceType); - + typeKey = Key.get(cxtorLiteral, UniqueAnnotations.create()); binder.bind(typeKey).toConstructor((Constructor) cxtor).in(Scopes.NO_SCOPE); typeProvider = binder.getProvider((Key) typeKey); @@ -230,43 +228,44 @@ typeProvider = null; typeKey = null; } - + // Create a CheckedProvider that calls our cxtor - CheckedProvider checkedProvider = new CheckedProviderWithDependencies() { - @Override - public T get() throws Exception { - try { - return typeProvider.get(); - } catch (ProvisionException pe) { - // Rethrow the provision cause as the actual exception - if (pe.getCause() instanceof Exception) { - throw (Exception) pe.getCause(); - } else if (pe.getCause() instanceof Error) { - throw (Error) pe.getCause(); - } else { - // If this failed because of multiple reasons (ie, more than - // one dependency failed due to scoping errors), then - // the ProvisionException won't have a cause, so we need - // to rethrow it as-is. - throw pe; + CheckedProvider checkedProvider = + new CheckedProviderWithDependencies() { + @Override + public T get() throws Exception { + try { + return typeProvider.get(); + } catch (ProvisionException pe) { + // Rethrow the provision cause as the actual exception + if (pe.getCause() instanceof Exception) { + throw (Exception) pe.getCause(); + } else if (pe.getCause() instanceof Error) { + throw (Error) pe.getCause(); + } else { + // If this failed because of multiple reasons (ie, more than + // one dependency failed due to scoping errors), then + // the ProvisionException won't have a cause, so we need + // to rethrow it as-is. + throw pe; + } + } } - } - } - - @Override - public Set> getDependencies() { - return ImmutableSet.>of(Dependency.get(typeKey)); - } - }; - - Key> targetKey = Key.get(CHECKED_PROVIDER_TYPE, - UniqueAnnotations.create()); + + @Override + public Set> getDependencies() { + return ImmutableSet.>of(Dependency.get(typeKey)); + } + }; + + Key> targetKey = + Key.get(CHECKED_PROVIDER_TYPE, UniqueAnnotations.create()); binder.bind(targetKey).toInstance(checkedProvider); return toInternal(targetKey); } - + ScopedBindingBuilder toProviderMethod(CheckedProviderMethod target) { - Key> targetKey = + Key> targetKey = Key.get(CHECKED_PROVIDER_METHOD_TYPE, UniqueAnnotations.create()); binder.bind(targetKey).toInstance(target); @@ -276,9 +275,9 @@ @SuppressWarnings("unchecked") // P only extends the raw type of CheckedProvider public ScopedBindingBuilder to(Key targetKey) { checkNotNull(targetKey, "targetKey"); - return toInternal((Key>)targetKey); + return toInternal((Key>) targetKey); } - + private ScopedBindingBuilder toInternal(final Key> targetKey) { final Key resultKey = Key.get(Result.class, UniqueAnnotations.create()); // Note that this provider will behave like the final provider Guice creates. @@ -288,53 +287,59 @@ interfaceKey = createKey(); // don't bother binding the proxy type if this is in an invalid state. - if(valid) { - binder.bind(interfaceKey).toProvider(new ProviderWithDependencies

    () { - private final P instance = interfaceType.cast(Proxy.newProxyInstance( - interfaceType.getClassLoader(), new Class[] { interfaceType }, - new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - // Allow methods like .equals(..), .hashcode(..), .toString(..) to work. - if (method.getDeclaringClass() == Object.class) { - return method.invoke(this, args); + if (valid) { + binder + .bind(interfaceKey) + .toProvider( + new ProviderWithDependencies

    () { + private final P instance = + interfaceType.cast( + Proxy.newProxyInstance( + interfaceType.getClassLoader(), + new Class[] {interfaceType}, + new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + // Allow methods like .equals(..), .hashcode(..), .toString(..) to work. + if (method.getDeclaringClass() == Object.class) { + return method.invoke(this, args); + } + + if (scopeExceptions) { + return resultProvider.get().getOrThrow(); + } else { + Result result; + try { + result = resultProvider.get(); + } catch (ProvisionException pe) { + Throwable cause = pe.getCause(); + if (cause instanceof ResultException) { + throw ((ResultException) cause).getCause(); + } else { + throw pe; + } + } + return result.getOrThrow(); + } + } + })); + + @Override + public P get() { + return instance; } - - if (scopeExceptions) { - return resultProvider.get().getOrThrow(); - } else { - Result result; - try { - result = resultProvider.get(); - } catch (ProvisionException pe) { - Throwable cause = pe.getCause(); - if (cause instanceof ResultException) { - throw ((ResultException)cause).getCause(); - } else { - throw pe; - } - } - return result.getOrThrow(); + + @Override + public Set> getDependencies() { + return ImmutableSet.>of(Dependency.get(resultKey)); } - } - })); - - @Override - public P get() { - return instance; - } - - @Override - public Set> getDependencies() { - return ImmutableSet.>of(Dependency.get(resultKey)); - } - }); + }); } - // The provider is unscoped, but the user may apply a scope to it through the + // The provider is unscoped, but the user may apply a scope to it through the // ScopedBindingBuilder this returns. - return binder.bind(resultKey).toProvider( - createResultProvider(targetKey, targetProvider)); + return binder.bind(resultKey).toProvider(createResultProvider(targetKey, targetProvider)); } private ProviderWithDependencies createResultProvider( @@ -371,10 +376,9 @@ } }; } - + /** - * Returns the exception type declared to be thrown by the get method of - * {@code interfaceType}. + * Returns the exception type declared to be thrown by the get method of {@code interfaceType}. */ private List> getExceptionType(Class

    interfaceType) { try { @@ -394,100 +398,12 @@ } private boolean checkInterface() { - if(!checkArgument(interfaceType.isInterface(), - "%s must be an interface", interfaceType.getName())) { - return false; - } - if(!checkArgument(interfaceType.getGenericInterfaces().length == 1, - "%s must extend CheckedProvider (and only CheckedProvider)", - interfaceType)) { - return false; - } - - boolean tpMode = interfaceType.getInterfaces()[0] == ThrowingProvider.class; - if(!tpMode) { - if(!checkArgument(interfaceType.getInterfaces()[0] == CheckedProvider.class, - "%s must extend CheckedProvider (and only CheckedProvider)", - interfaceType)) { - return false; - } - } - - // Ensure that T is parameterized and unconstrained. - ParameterizedType genericThrowingProvider - = (ParameterizedType) interfaceType.getGenericInterfaces()[0]; - if (interfaceType.getTypeParameters().length == 1) { - String returnTypeName = interfaceType.getTypeParameters()[0].getName(); - Type returnType = genericThrowingProvider.getActualTypeArguments()[0]; - if(!checkArgument(returnType instanceof TypeVariable, - "%s does not properly extend CheckedProvider, the first type parameter of CheckedProvider (%s) is not a generic type", - interfaceType, returnType)) { - return false; - } - if(!checkArgument(returnTypeName.equals(((TypeVariable) returnType).getName()), - "The generic type (%s) of %s does not match the generic type of CheckedProvider (%s)", - returnTypeName, interfaceType, ((TypeVariable)returnType).getName())) { - return false; - } - } else { - if(!checkArgument(interfaceType.getTypeParameters().length == 0, - "%s has more than one generic type parameter: %s", - interfaceType, Arrays.asList(interfaceType.getTypeParameters()))) { - return false; - } - if(!checkArgument(genericThrowingProvider.getActualTypeArguments()[0].equals(valueType), - "%s expects the value type to be %s, but it was %s", - interfaceType, genericThrowingProvider.getActualTypeArguments()[0], valueType)) { - return false; - } - } - - if(tpMode) { // only validate exception in ThrowingProvider mode. - Type exceptionType = genericThrowingProvider.getActualTypeArguments()[1]; - if(!checkArgument(exceptionType instanceof Class, - "%s has the wrong Exception generic type (%s) when extending CheckedProvider", - interfaceType, exceptionType)) { - return false; - } - } - - // Skip synthetic/bridge methods because java8 generates - // a default method on the interface w/ the superinterface type that - // just delegates directly to the overridden method. - List declaredMethods = FluentIterable - .from(Arrays.asList(interfaceType.getDeclaredMethods())) - .filter(NotSyntheticOrBridgePredicate.INSTANCE) - .toList(); - if (declaredMethods.size() == 1) { - Method method = declaredMethods.get(0); - if(!checkArgument(method.getName().equals("get"), - "%s may not declare any new methods, but declared %s", - interfaceType, method)) { - return false; - } - if(!checkArgument(method.getParameterTypes().length == 0, - "%s may not declare any new methods, but declared %s", - interfaceType, method.toGenericString())) { - return false; - } - } else { - if(!checkArgument(declaredMethods.isEmpty(), - "%s may not declare any new methods, but declared %s", - interfaceType, Arrays.asList(interfaceType.getDeclaredMethods()))) { - return false; - } - } - - return true; - } - - private boolean checkArgument(boolean condition, - String messageFormat, Object... args) { - if (!condition) { - binder.addError(messageFormat, args); - return false; - } else { + try { + ProviderChecker.checkInterface(interfaceType, Optional.of(valueType)); return true; + } catch (IllegalArgumentException e) { + binder.addError(e.getMessage()); + return false; } } @@ -495,8 +411,9 @@ private Key

    createKey() { TypeLiteral

    typeLiteral; if (interfaceType.getTypeParameters().length == 1) { - ParameterizedType type = Types.newParameterizedTypeWithOwner( - interfaceType.getEnclosingClass(), interfaceType, valueType); + ParameterizedType type = + Types.newParameterizedTypeWithOwner( + interfaceType.getEnclosingClass(), interfaceType, valueType); typeLiteral = (TypeLiteral

    ) TypeLiteral.get(type); } else { typeLiteral = TypeLiteral.get(interfaceType); @@ -504,10 +421,10 @@ if (annotation != null) { return Key.get(typeLiteral, annotation); - + } else if (annotationType != null) { return Key.get(typeLiteral, annotationType); - + } else { return Key.get(typeLiteral); } @@ -536,7 +453,7 @@ public static Result forException(Exception e) { return new Result(null, e); } - + public Object getOrThrow() throws Exception { if (exception != null) { throw exception; @@ -547,20 +464,12 @@ } /** - * RuntimeException class to wrap exceptions from the checked provider. - * The regular guice provider can throw it and the checked provider proxy extracts - * the underlying exception and rethrows it. + * RuntimeException class to wrap exceptions from the checked provider. The regular guice provider + * can throw it and the checked provider proxy extracts the underlying exception and rethrows it. */ private static class ResultException extends RuntimeException { ResultException(Exception cause) { super(cause); } } - - private static class NotSyntheticOrBridgePredicate implements Predicate { - static NotSyntheticOrBridgePredicate INSTANCE = new NotSyntheticOrBridgePredicate(); - @Override public boolean apply(Method input) { - return !input.isBridge() && !input.isSynthetic(); - } - } } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java --- sisu-guice-3.2.6/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,24 +17,26 @@ package com.google.inject.throwingproviders; /** - * Alternative to the Guice {@link com.google.inject.Provider} that throws - * a checked Exception. Users may not inject {@code T} directly. + * Alternative to the Guice {@link com.google.inject.Provider} that throws a checked Exception. + * Users may not inject {@code T} directly. + * + *

    This interface must be extended to use application-specific exception types. Such + * subinterfaces may not define new methods: * - *

    This interface must be extended to use application-specific exception types. - * Such subinterfaces may not define new methods: *

      * public interface RemoteProvider<T> extends ThrowingProvider<T, RemoteException> { }
      * 
    * - *

    When this type is bound using {@link ThrowingProviderBinder}, the value returned - * or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get} - * will invoked at most once within each scope. + *

    When this type is bound using {@link ThrowingProviderBinder}, the value returned or exception + * thrown by {@link #get} will be scoped. As a consequence, {@link #get} will invoked at most once + * within each scope. * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) * @deprecated use {@link CheckedProvider} instead. */ @Deprecated -public interface ThrowingProvider extends CheckedProvider { +public interface ThrowingProvider extends CheckedProvider { + @Override T get() throws E; } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java --- sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,40 +27,36 @@ import com.google.inject.TypeLiteral; import com.google.inject.name.Named; import com.google.inject.name.Names; - -import junit.framework.TestCase; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.BindException; import java.rmi.RemoteException; +import junit.framework.TestCase; -/** - * Test methods for {@link CheckedProviderMethodsModule}. - */ +/** Test methods for {@link CheckedProviderMethodsModule}. */ public class CheckedProviderMethodsModuleTest extends TestCase { - private final TypeLiteral> rpcProviderOfString - = new TypeLiteral>() { }; - private final TypeLiteral> rpcProviderOfInteger - = new TypeLiteral>() { }; - private final TypeLiteral> rpcProviderOfLong - = new TypeLiteral>() { }; - private final TypeLiteral> rpcProviderOfFloat - = new TypeLiteral>() { }; - private final TypeLiteral>> rpcProviderOfPair - = new TypeLiteral>>() { }; + private final TypeLiteral> rpcProviderOfString = + new TypeLiteral>() {}; + private final TypeLiteral> rpcProviderOfInteger = + new TypeLiteral>() {}; + private final TypeLiteral> rpcProviderOfLong = + new TypeLiteral>() {}; + private final TypeLiteral> rpcProviderOfFloat = + new TypeLiteral>() {}; + private final TypeLiteral>> rpcProviderOfPair = + new TypeLiteral>>() {}; private final TestScope testScope = new TestScope(); interface RpcProvider extends CheckedProvider { + @Override T get() throws RemoteException, BindException; } @Retention(RetentionPolicy.RUNTIME) @BindingAnnotation - @interface TestAnnotation { - } + @interface TestAnnotation {} class TestModule extends AbstractModule { @@ -78,12 +74,14 @@ return "Works"; } - @CheckedProvides(RpcProvider.class) @TestScope.Scoped + @CheckedProvides(RpcProvider.class) + @TestScope.Scoped int getSomeIntegerFromServer() { return nextIntToReturn; } - @CheckedProvides(RpcProvider.class) @TestAnnotation + @CheckedProvides(RpcProvider.class) + @TestAnnotation long getSomeLongFromServer() { return 0xffL; } @@ -115,55 +113,52 @@ install(ThrowingProviderBinder.forModule(this)); } - @CheckedProvides(RpcProvider.class) @Named("fruit") @Exposed + @CheckedProvides(RpcProvider.class) + @Named("fruit") + @Exposed String provideApples() { return "apple"; } } - public void testNoAnnotationNoScope() throws BindException, RemoteException { Injector injector = Guice.createInjector(new TestModule()); - RpcProvider provider = injector - .getInstance(Key.get(rpcProviderOfString)); + RpcProvider provider = injector.getInstance(Key.get(rpcProviderOfString)); assertEquals("Works", provider.get()); } public void testWithScope() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); - RpcProvider provider = injector - .getInstance(Key.get(rpcProviderOfInteger)); + RpcProvider provider = injector.getInstance(Key.get(rpcProviderOfInteger)); - assertEquals((Integer)100, provider.get()); + assertEquals((Integer) 100, provider.get()); testModule.setNextIntToReturn(120); - assertEquals((Integer)100, provider.get()); + assertEquals((Integer) 100, provider.get()); testScope.beginNewScope(); - assertEquals((Integer)120, provider.get()); + assertEquals((Integer) 120, provider.get()); } public void testWithAnnotation() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); - RpcProvider provider = injector - .getInstance(Key.get(rpcProviderOfLong, TestAnnotation.class)); - assertEquals((Long)0xffL, provider.get()); + RpcProvider provider = + injector.getInstance(Key.get(rpcProviderOfLong, TestAnnotation.class)); + assertEquals((Long) 0xffL, provider.get()); } public void testWithInjectedParameters() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); - RpcProvider> provider = injector - .getInstance(Key.get(rpcProviderOfPair)); + RpcProvider> provider = injector.getInstance(Key.get(rpcProviderOfPair)); Pair pair = provider.get(); - assertEquals(pair.first, 4.0d); + assertEquals(pair.first, 4.0d, 0.0); } public void testWithThrownException() { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); - RpcProvider provider = injector - .getInstance(Key.get(rpcProviderOfFloat)); + RpcProvider provider = injector.getInstance(Key.get(rpcProviderOfFloat)); try { provider.get(); fail(); @@ -177,19 +172,18 @@ public void testExposedMethod() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); - RpcProvider provider = injector - .getInstance(Key.get(rpcProviderOfString, Names.named("fruit"))); + RpcProvider provider = + injector.getInstance(Key.get(rpcProviderOfString, Names.named("fruit"))); assertEquals("apple", provider.get()); - } - + private static class Pair { A first; B second; Pair(A a, B b) { - this.first= a; + this.first = a; this.second = b; } } -} \ No newline at end of file +} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProvidersTest.java sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProvidersTest.java --- sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProvidersTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProvidersTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,161 @@ +package com.google.inject.throwingproviders; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.inject.TypeLiteral; +import java.util.Arrays; +import junit.framework.TestCase; + +/** + * Unit tests for {@link CheckedProviders}. + * + * @author eatnumber1@google.com (Russ Harmon) + */ +public final class CheckedProvidersTest extends TestCase { + private static interface StringCheckedProvider extends CheckedProvider {} + + public void testCheckedProviderClass_get_returnsValidString() throws Exception { + String expected = "rick"; + + StringCheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, expected); + assertThat(provider.get()).isEqualTo(expected); + } + + public void testCheckedProviderTypeLiteral_get_returnsValidString() throws Exception { + String expected = "morty"; + + StringCheckedProvider provider = + CheckedProviders.of(TypeLiteral.get(StringCheckedProvider.class), expected); + assertThat(provider.get()).isEqualTo(expected); + } + + public void testCheckedProviderClassNull_get_returnsNull() throws Exception { + StringCheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, null); + assertThat(provider.get()).isNull(); + } + + public void testCheckedProviderTypeLiteralNull_get_returnsNull() throws Exception { + StringCheckedProvider provider = + CheckedProviders.of(TypeLiteral.get(StringCheckedProvider.class), null); + assertThat(provider.get()).isNull(); + } + + private static final class FooException extends Exception {} + + private interface FooCheckedProvider extends CheckedProvider { + @Override + Object get() throws FooException; + } + + public void testThrowingCheckedProviderClass_get_throwsException() { + FooCheckedProvider provider = + CheckedProviders.throwing(FooCheckedProvider.class, FooException.class); + try { + provider.get(); + fail(); + } catch (FooException expected) { + } + } + + public void testThrowingCheckedProviderTypeLiteral_get_throwsException() { + FooCheckedProvider provider = + CheckedProviders.throwing(TypeLiteral.get(FooCheckedProvider.class), FooException.class); + try { + provider.get(); + fail(); + } catch (FooException expected) { + } + } + + private interface MoreMethodsCheckedProvider extends CheckedProvider { + @Override + T get() throws FooException; + + void otherMethod(); + } + + public void testUnsupportedMethods_otherMethod_throwsIllegalArgumentException() + throws NoSuchMethodException { + String message = + String.format( + "%s may not declare any new methods, but declared %s", + MoreMethodsCheckedProvider.class.getName(), + Arrays.toString(MoreMethodsCheckedProvider.class.getDeclaredMethods())); + + try { + CheckedProviders.of( + new TypeLiteral>() {}, "SHOW ME WHAT YOU GOT"); + fail("Expected an exception to be thrown"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(message); + } + } + + private static final class StringException extends RuntimeException { + StringException(String arg) {} + } + + public void testCheckThrowable_unsupportedThrowableConstructor_throwsIllegalArgumentException() { + String message = + String.format( + "Thrown exception <%s> must have a no-argument constructor", + StringException.class.getName()); + + try { + CheckedProviders.throwing(FooCheckedProvider.class, StringException.class); + fail("Expected an exception to be thrown"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(message); + assertWithMessage(String.format("exception <%s> with cause", e)) + .that(e.getCause()) + .isInstanceOf(NoSuchMethodException.class); + } + } + + private static final class BarException extends Exception {} + + public void testCheckThrowable_checkedExceptionNotDeclared_throwsIllegalArgumentException() + throws Exception { + String message = + String.format( + "Thrown exception <%s> is not declared to be thrown by <%s>", + BarException.class.getName(), FooCheckedProvider.class.getMethod("get")); + + try { + CheckedProviders.throwing(FooCheckedProvider.class, BarException.class); + fail("Expected an exception to be thrown"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(message); + } + } + + private static final class ExpectedRuntimeException extends RuntimeException {} + + public void testCheckThrowable_runtimeExceptionNotDeclared_throwsExpectedRuntimeException() + throws Exception { + FooCheckedProvider provider = + CheckedProviders.throwing(FooCheckedProvider.class, ExpectedRuntimeException.class); + + try { + provider.get(); + fail("Expected an exception to be thrown"); + } catch (ExpectedRuntimeException e) { + // expected + } + } + + private static final class ExpectedError extends Error {} + + public void testCheckThrowable_errorNotDeclared_throwsExpectedError() throws Exception { + FooCheckedProvider provider = + CheckedProviders.throwing(FooCheckedProvider.class, ExpectedError.class); + + try { + provider.get(); + fail("Expected an exception to be thrown"); + } catch (ExpectedError e) { + // expected + } + } +} diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java --- sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import com.google.inject.AbstractModule; import com.google.inject.Asserts; import com.google.inject.BindingAnnotation; @@ -45,9 +44,6 @@ import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; import com.google.inject.throwingproviders.ThrowingProviderBinder.Result; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; @@ -62,6 +58,7 @@ import java.util.List; import java.util.Set; import java.util.TooManyListenersException; +import junit.framework.TestCase; /** * @author jmourits@google.com (Jerome Mourits) @@ -69,108 +66,113 @@ * @author sameb@google.com (Sam Berlin) */ public class CheckedProviderTest extends TestCase { - @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation - @interface NotExceptionScoping { }; - + @Target(METHOD) + @Retention(RUNTIME) + @BindingAnnotation + @interface NotExceptionScoping {}; + private static final Function, Key> DEPENDENCY_TO_KEY = new Function, Key>() { + @Override public Key apply(Dependency from) { return from.getKey(); } }; - private final TypeLiteral> remoteProviderOfFoo - = new TypeLiteral>() { }; - private final MockRemoteProvider mockRemoteProvider = new MockRemoteProvider(); + private final TypeLiteral> remoteProviderOfFoo = + new TypeLiteral>() {}; + private final MockRemoteProvider mockRemoteProvider = new MockRemoteProvider<>(); private final TestScope testScope = new TestScope(); - - private Injector bindInjector; + + private Injector bindInjector; private Injector providesInjector; private Injector cxtorInjector; - + @Override protected void setUp() throws Exception { MockFoo.nextToThrow = null; MockFoo.nextToReturn = null; AnotherMockFoo.nextToThrow = null; AnotherMockFoo.nextToReturn = null; - - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .to(mockRemoteProvider) - .in(testScope); - - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .annotatedWith(NotExceptionScoping.class) - .scopeExceptions(false) - .to(mockRemoteProvider) - .in(testScope); - } - }); - - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - bindScope(TestScope.Scoped.class, testScope); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - @TestScope.Scoped - Foo throwOrGet() throws RemoteException, BindException { - return mockRemoteProvider.get(); - } + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .to(mockRemoteProvider) + .in(testScope); + + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .annotatedWith(NotExceptionScoping.class) + .scopeExceptions(false) + .to(mockRemoteProvider) + .in(testScope); + } + }); - @SuppressWarnings("unused") - @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false) - @NotExceptionScoping - @TestScope.Scoped - Foo notExceptionScopingThrowOrGet() throws RemoteException, BindException { - return mockRemoteProvider.get(); - } - - }); - - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(MockFoo.class) - .in(testScope); - - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .annotatedWith(NotExceptionScoping.class) - .scopeExceptions(false) - .providing(MockFoo.class) - .in(testScope); - - } - }); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + bindScope(TestScope.Scoped.class, testScope); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + @TestScope.Scoped + Foo throwOrGet() throws RemoteException, BindException { + return mockRemoteProvider.get(); + } + + @SuppressWarnings("unused") + @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false) + @NotExceptionScoping + @TestScope.Scoped + Foo notExceptionScopingThrowOrGet() throws RemoteException, BindException { + return mockRemoteProvider.get(); + } + }); + + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(MockFoo.class) + .in(testScope); + + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .annotatedWith(NotExceptionScoping.class) + .scopeExceptions(false) + .providing(MockFoo.class) + .in(testScope); + } + }); } public void testExceptionsThrown_Bind() throws Exception { tExceptionsThrown(bindInjector); } - + public void testExceptionsThrown_Provides() throws Exception { tExceptionsThrown(providesInjector); } - + public void testExceptionsThrown_Cxtor() throws Exception { tExceptionsThrown(cxtorInjector); } - + private void tExceptionsThrown(Injector injector) throws Exception { - RemoteProvider remoteProvider = - injector.getInstance(Key.get(remoteProviderOfFoo)); + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfFoo)); mockRemoteProvider.throwOnNextGet(new BindException("kaboom!")); MockFoo.nextToThrow = new BindException("kaboom!"); @@ -182,29 +184,30 @@ } } - public void testValuesScoped_Bind() throws Exception { + public void testValuesScoped_Bind() throws Exception { tValuesScoped(bindInjector, null); } - - public void testValuesScoped_Provides() throws Exception { + + public void testValuesScoped_Provides() throws Exception { tValuesScoped(providesInjector, null); } - - public void testValuesScopedWhenNotExceptionScoping_Bind() throws Exception { + + public void testValuesScopedWhenNotExceptionScoping_Bind() throws Exception { tValuesScoped(bindInjector, NotExceptionScoping.class); } - - public void testValuesScopedWhenNotExceptionScoping_Provides() throws Exception { + + public void testValuesScopedWhenNotExceptionScoping_Provides() throws Exception { tValuesScoped(providesInjector, NotExceptionScoping.class); } - private void tValuesScoped(Injector injector, - Class annotation) throws Exception { - Key> key = annotation != null ? - Key.get(remoteProviderOfFoo, annotation) : - Key.get(remoteProviderOfFoo); + private void tValuesScoped(Injector injector, Class annotation) + throws Exception { + Key> key = + annotation != null + ? Key.get(remoteProviderOfFoo, annotation) + : Key.get(remoteProviderOfFoo); RemoteProvider remoteProvider = injector.getInstance(key); - + mockRemoteProvider.setNextToReturn(new SimpleFoo("A")); assertEquals("A", remoteProvider.get().s()); @@ -214,14 +217,13 @@ testScope.beginNewScope(); assertEquals("B", remoteProvider.get().s()); } - + public void testValuesScoped_Cxtor() throws Exception { - RemoteProvider remoteProvider = - cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); + RemoteProvider remoteProvider = cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); Foo retrieved = remoteProvider.get(); assertSame(retrieved, remoteProvider.get()); // same, not in new scope. - + testScope.beginNewScope(); assertNotSame(retrieved, remoteProvider.get()); // different, new scope. } @@ -229,18 +231,17 @@ public void testExceptionsScoped_Bind() throws Exception { tExceptionsScoped(bindInjector); } - + public void testExceptionsScoped_Provides() throws Exception { tExceptionsScoped(providesInjector); } - + public void testExceptionScopes_Cxtor() throws Exception { tExceptionsScoped(cxtorInjector); } - + private void tExceptionsScoped(Injector injector) throws Exception { - RemoteProvider remoteProvider = - injector.getInstance(Key.get(remoteProviderOfFoo)); + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfFoo)); mockRemoteProvider.throwOnNextGet(new RemoteException("A")); MockFoo.nextToThrow = new RemoteException("A"); @@ -250,7 +251,7 @@ } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } - + mockRemoteProvider.throwOnNextGet(new RemoteException("B")); MockFoo.nextToThrow = new RemoteException("B"); try { @@ -260,21 +261,21 @@ assertEquals("A", expected.getMessage()); } } - + public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() throws Exception { tExceptionsNotScopedWhenNotExceptionScoping(bindInjector); } - + public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() throws Exception { tExceptionsNotScopedWhenNotExceptionScoping(providesInjector); } - + public void testExceptionNotScopedWhenNotExceptionScoping_Cxtor() throws Exception { tExceptionsNotScopedWhenNotExceptionScoping(cxtorInjector); } - + private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) throws Exception { - RemoteProvider remoteProvider = + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfFoo, NotExceptionScoping.class)); mockRemoteProvider.throwOnNextGet(new RemoteException("A")); @@ -285,7 +286,7 @@ } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } - + mockRemoteProvider.throwOnNextGet(new RemoteException("B")); MockFoo.nextToThrow = new RemoteException("B"); try { @@ -295,100 +296,104 @@ assertEquals("B", expected.getMessage()); } } - + public void testAnnotations_Bind() throws Exception { - final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); - final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .annotatedWith(Names.named("a")) - .to(mockRemoteProviderA); - - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .to(mockRemoteProviderB); - } - }); + final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider<>(); + final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider<>(); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .annotatedWith(Names.named("a")) + .to(mockRemoteProviderA); + + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .to(mockRemoteProviderB); + } + }); tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB); } - + public void testAnnotations_Provides() throws Exception { - final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); - final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - @Named("a") - Foo throwOrGet() throws RemoteException, BindException { - return mockRemoteProviderA.get(); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - Foo throwOrGet2() throws RemoteException, BindException { - return mockRemoteProviderB.get(); - } - }); + final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider<>(); + final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider<>(); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + @Named("a") + Foo throwOrGet() throws RemoteException, BindException { + return mockRemoteProviderA.get(); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + Foo throwOrGet2() throws RemoteException, BindException { + return mockRemoteProviderB.get(); + } + }); tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB); } - - private void tAnnotations(Injector injector, MockRemoteProvider mockA, - MockRemoteProvider mockB) throws Exception { + + private void tAnnotations( + Injector injector, MockRemoteProvider mockA, MockRemoteProvider mockB) + throws Exception { mockA.setNextToReturn(new SimpleFoo("A")); mockB.setNextToReturn(new SimpleFoo("B")); - assertEquals("A", - injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s()); + assertEquals( + "A", injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s()); - assertEquals("B", - injector.getInstance(Key.get(remoteProviderOfFoo)).get().s()); + assertEquals("B", injector.getInstance(Key.get(remoteProviderOfFoo)).get().s()); } - + public void testAnnotations_Cxtor() throws Exception { - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .annotatedWith(Names.named("a")) - .providing(MockFoo.class); - - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(AnotherMockFoo.class); - } - }); + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .annotatedWith(Names.named("a")) + .providing(MockFoo.class); + + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(AnotherMockFoo.class); + } + }); MockFoo.nextToReturn = "A"; AnotherMockFoo.nextToReturn = "B"; - assertEquals("A", - cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s()); + assertEquals( + "A", cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s()); - assertEquals("B", - cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s()); + assertEquals("B", cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s()); } - + public void testUndeclaredExceptions_Bind() throws Exception { tUndeclaredExceptions(bindInjector); } - + public void testUndeclaredExceptions_Provides() throws Exception { tUndeclaredExceptions(providesInjector); } - + public void testUndeclaredExceptions_Cxtor() throws Exception { tUndeclaredExceptions(cxtorInjector); } - private void tUndeclaredExceptions(Injector injector) throws Exception { - RemoteProvider remoteProvider = - injector.getInstance(Key.get(remoteProviderOfFoo)); + private void tUndeclaredExceptions(Injector injector) throws Exception { + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfFoo)); mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A")); MockFoo.nextToThrow = new IndexOutOfBoundsException("A"); try { @@ -413,215 +418,257 @@ final SubMockRemoteProvider aProvider = new SubMockRemoteProvider(); aProvider.setNextToReturn(new SimpleFoo("A")); - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .to(aProvider); - } - }); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .to(aProvider); + } + }); - assertEquals("A", - bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s()); + assertEquals("A", bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s()); } - static class SubMockRemoteProvider extends MockRemoteProvider { } + static class SubMockRemoteProvider extends MockRemoteProvider {} public void testBindingToNonInterfaceType_Bind() throws Exception { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(MockRemoteProvider.class, Foo.class) - .to(mockRemoteProvider); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(MockRemoteProvider.class, Foo.class) + .to(mockRemoteProvider); + } + }); fail(); } catch (CreationException expected) { - assertEquals(MockRemoteProvider.class.getName() + " must be an interface", + assertEquals( + MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testBindingToNonInterfaceType_Provides() throws Exception { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(MockRemoteProvider.class) - Foo foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(MockRemoteProvider.class) + Foo foo() { + return null; + } + }); fail(); } catch (CreationException expected) { - assertEquals(MockRemoteProvider.class.getName() + " must be an interface", + assertEquals( + MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } - } - + } + public void testBindingToSubSubInterface_Bind() throws Exception { try { - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(SubRemoteProvider.class, Foo.class); - } - }); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()).bind(SubRemoteProvider.class, Foo.class); + } + }); fail(); } catch (CreationException expected) { - assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", + assertEquals( + SubRemoteProvider.class.getName() + + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testBindingToSubSubInterface_Provides() throws Exception { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(SubRemoteProvider.class) - Foo foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(SubRemoteProvider.class) + Foo foo() { + return null; + } + }); fail(); } catch (CreationException expected) { - assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", + assertEquals( + SubRemoteProvider.class.getName() + + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } - } + } - interface SubRemoteProvider extends RemoteProvider { } + interface SubRemoteProvider extends RemoteProvider {} public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception { try { - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProviderWithExtraMethod.class, Foo.class); - } - }); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProviderWithExtraMethod.class, Foo.class); + } + }); fail(); } catch (CreationException expected) { - assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " - + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), + assertEquals( + RemoteProviderWithExtraMethod.class.getName() + + " may not declare any new methods, but declared " + + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProviderWithExtraMethod.class) - Foo foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProviderWithExtraMethod.class) + Foo foo() { + return null; + } + }); fail(); } catch (CreationException expected) { - assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " - + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), + assertEquals( + RemoteProviderWithExtraMethod.class.getName() + + " may not declare any new methods, but declared " + + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testDependencies_Bind() { - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toInstance("Foo"); - bind(Integer.class).toInstance(5); - bind(Double.class).toInstance(5d); - bind(Long.class).toInstance(5L); - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .to(DependentRemoteProvider.class); - } - }); - + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("Foo"); + bind(Integer.class).toInstance(5); + bind(Double.class).toInstance(5d); + bind(Long.class).toInstance(5L); + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .to(DependentRemoteProvider.class); + } + }); + HasDependencies hasDependencies = - (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfFoo)); - hasDependencies = - (HasDependencies)bindInjector.getBinding( - Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); + (HasDependencies) bindInjector.getBinding(Key.get(remoteProviderOfFoo)); + hasDependencies = + (HasDependencies) + bindInjector.getBinding( + Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // Make sure that that is dependent on DependentRemoteProvider. - assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), + assertEquals( + Dependency.get(Key.get(DependentRemoteProvider.class)), Iterables.getOnlyElement(hasDependencies.getDependencies())); // And make sure DependentRemoteProvider has the proper dependencies. - hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class); - Set> dependencyKeys = ImmutableSet.copyOf( - Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); - assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), - Key.get(Long.class), Key.get(Double.class)), dependencyKeys); + hasDependencies = (HasDependencies) bindInjector.getBinding(DependentRemoteProvider.class); + Set> dependencyKeys = + ImmutableSet.copyOf( + Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); + assertEquals( + ImmutableSet.>of( + Key.get(String.class), + Key.get(Integer.class), + Key.get(Long.class), + Key.get(Double.class)), + dependencyKeys); } - + public void testDependencies_Provides() { - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toInstance("Foo"); - bind(Integer.class).toInstance(5); - bind(Double.class).toInstance(5d); - bind(Long.class).toInstance(5L); - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - Foo foo(String s, Integer i, Double d, Long l) { - return null; - } - }); - + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("Foo"); + bind(Integer.class).toInstance(5); + bind(Double.class).toInstance(5d); + bind(Long.class).toInstance(5L); + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + Foo foo(String s, Integer i, Double d, Long l) { + return null; + } + }); + HasDependencies hasDependencies = (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfFoo)); // RemoteProvider is dependent on the provider method.. - hasDependencies = (HasDependencies) providesInjector.getBinding( - Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); + hasDependencies = + (HasDependencies) + providesInjector.getBinding( + Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // And the provider method has our real dependencies.. - hasDependencies = (HasDependencies)providesInjector.getBinding( - Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); - Set> dependencyKeys = ImmutableSet.copyOf( - Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); - assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), - Key.get(Long.class), Key.get(Double.class)), dependencyKeys); - } - + hasDependencies = + (HasDependencies) + providesInjector.getBinding( + Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); + Set> dependencyKeys = + ImmutableSet.copyOf( + Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); + assertEquals( + ImmutableSet.>of( + Key.get(String.class), + Key.get(Integer.class), + Key.get(Long.class), + Key.get(Double.class)), + dependencyKeys); + } + public void testDependencies_Cxtor() { - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toInstance("Foo"); - bind(Integer.class).toInstance(5); - bind(Double.class).toInstance(5d); - bind(Long.class).toInstance(5L); - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(DependentMockFoo.class); - } - }); - + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("Foo"); + bind(Integer.class).toInstance(5); + bind(Double.class).toInstance(5d); + bind(Long.class).toInstance(5L); + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(DependentMockFoo.class); + } + }); + Key key = Key.get(remoteProviderOfFoo); - + // RemoteProvider is dependent on Result. HasDependencies hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey(); @@ -631,81 +678,91 @@ hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey(); assertTrue(CheckedProvider.class.isAssignableFrom(key.getTypeLiteral().getRawType())); - + // And the CheckedProvider is dependent on DependentMockFoo... hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey(); assertEquals(DependentMockFoo.class, key.getTypeLiteral().getRawType()); - + // And DependentMockFoo is dependent on the goods. - hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); - Set> dependencyKeys = ImmutableSet.copyOf( - Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); - assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), - Key.get(Long.class), Key.get(Double.class)), dependencyKeys); - } + hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); + Set> dependencyKeys = + ImmutableSet.copyOf( + Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); + assertEquals( + ImmutableSet.>of( + Key.get(String.class), + Key.get(Integer.class), + Key.get(Long.class), + Key.get(Double.class)), + dependencyKeys); + } interface RemoteProviderWithExtraMethod extends CheckedProvider { T get(T defaultValue) throws RemoteException, BindException; } - interface RemoteProvider extends CheckedProvider { + interface RemoteProvider extends CheckedProvider { + @Override public T get() throws RemoteException, BindException; } - + static class DependentMockFoo implements Foo { @Inject double foo; - - @ThrowingInject public DependentMockFoo(String foo, int bar) { - } - - @Inject void initialize(long foo) {} - + + @ThrowingInject + public DependentMockFoo(String foo, int bar) {} + + @Inject + void initialize(long foo) {} + @Override public String s() { return null; } } - + static class DependentRemoteProvider implements RemoteProvider { @Inject double foo; - - @Inject public DependentRemoteProvider(String foo, int bar) { - } - - @Inject void initialize(long foo) {} - + + @Inject + public DependentRemoteProvider(String foo, int bar) {} + + @Inject + void initialize(long foo) {} + + @Override public T get() { return null; } } - + interface Foo { String s(); } - + static class SimpleFoo implements Foo { private String s; - + SimpleFoo(String s) { this.s = s; } - + @Override public String s() { return s; } - + @Override public String toString() { return s; } } - + static class MockFoo implements Foo { - static Exception nextToThrow; + static Exception nextToThrow; static String nextToReturn; - + @ThrowingInject MockFoo() throws RemoteException, BindException { if (nextToThrow instanceof RemoteException) { @@ -720,22 +777,22 @@ throw new AssertionError("nextToThrow must be a runtime or remote exception"); } } - + @Override public String s() { return nextToReturn; } - + @Override public String toString() { return nextToReturn; } } - + static class AnotherMockFoo implements Foo { - static Exception nextToThrow; + static Exception nextToThrow; static String nextToReturn; - + @ThrowingInject AnotherMockFoo() throws RemoteException, BindException { if (nextToThrow instanceof RemoteException) { @@ -750,18 +807,18 @@ throw new AssertionError("nextToThrow must be a runtime or remote exception"); } } - + @Override public String s() { return nextToReturn; } - + @Override public String toString() { return nextToReturn; } } - + static class MockRemoteProvider implements RemoteProvider { Exception nextToThrow; T nextToReturn; @@ -773,7 +830,8 @@ public void setNextToReturn(T nextToReturn) { this.nextToReturn = nextToReturn; } - + + @Override public T get() throws RemoteException, BindException { if (nextToThrow instanceof RemoteException) { throw (RemoteException) nextToThrow; @@ -790,196 +848,225 @@ } public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException { - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(StringRemoteProvider.class, String.class) - .to(new StringRemoteProvider() { - public String get() { - return "A"; + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(StringRemoteProvider.class, String.class) + .to( + new StringRemoteProvider() { + @Override + public String get() { + return "A"; + } + }); } }); - } - }); - + assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get()); } - + public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException { - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(StringRemoteProvider.class) - String foo() throws RemoteException { - return "A"; - } - }); - + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(StringRemoteProvider.class) + String foo() throws RemoteException { + return "A"; + } + }); + assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get()); } interface StringRemoteProvider extends CheckedProvider { - @Override String get() throws RemoteException; + @Override + String get() throws RemoteException; } @SuppressWarnings("deprecation") public void testBindingToInterfaceWithGeneric_Bind() throws Exception { - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, new TypeLiteral>() { }.getType()) - .to(new RemoteProvider>() { - public List get() { - return Arrays.asList("A", "B"); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, new TypeLiteral>() {}.getType()) + .to( + new RemoteProvider>() { + @Override + public List get() { + return Arrays.asList("A", "B"); + } + }); } }); - } - }); - Key>> key - = Key.get(new TypeLiteral>>() { }); + Key>> key = + Key.get(new TypeLiteral>>() {}); assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get()); } - + public void testBindingToInterfaceWithGeneric_BindUsingTypeLiteral() throws Exception { - bindInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, new TypeLiteral>() {}) - .to(new RemoteProvider>() { - public List get() { - return Arrays.asList("A", "B"); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, new TypeLiteral>() {}) + .to( + new RemoteProvider>() { + @Override + public List get() { + return Arrays.asList("A", "B"); + } + }); } }); - } - }); - Key>> key - = Key.get(new TypeLiteral>>() { }); + Key>> key = + Key.get(new TypeLiteral>>() {}); assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get()); } - + public void testBindingToInterfaceWithGeneric_Provides() throws Exception { - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - List foo() throws RemoteException { - return Arrays.asList("A", "B"); - } - }); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } - Key>> key - = Key.get(new TypeLiteral>>() { }); + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + List foo() throws RemoteException { + return Arrays.asList("A", "B"); + } + }); + + Key>> key = + Key.get(new TypeLiteral>>() {}); assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get()); } - + public void testBindingToInterfaceWithGeneric_Cxtor() throws Exception { - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, new TypeLiteral>() {}) - .providing(new TypeLiteral>() {}); - } - }); + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, new TypeLiteral>() {}) + .providing(new TypeLiteral>() {}); + } + }); - Key>> key - = Key.get(new TypeLiteral>>() { }); + Key>> key = + Key.get(new TypeLiteral>>() {}); assertEquals(Arrays.asList(), cxtorInjector.getInstance(key).get()); } - + private static class ThrowingArrayList extends ArrayList { @SuppressWarnings("unused") @ThrowingInject ThrowingArrayList() {} } - + public void testProviderMethodWithWrongException() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws InterruptedException { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() throws InterruptedException { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(InterruptedException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + } catch (CreationException ce) { + assertEquals( + InterruptedException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testCxtorWithWrongException() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(WrongExceptionFoo.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(WrongExceptionFoo.class); + } + }); fail(); } catch (CreationException ce) { - assertEquals(InterruptedException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + assertEquals( + InterruptedException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + static class WrongExceptionFoo implements Foo { @SuppressWarnings("unused") @ThrowingInject - public WrongExceptionFoo() throws InterruptedException { - } - + public WrongExceptionFoo() throws InterruptedException {} + @Override - public String s() { return null; } + public String s() { + return null; + } } - + public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception { - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - Foo foo() throws AccessException { - throw new AccessException("boo!"); - } - }); - - RemoteProvider remoteProvider = - providesInjector.getInstance(Key.get(remoteProviderOfFoo)); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + Foo foo() throws AccessException { + throw new AccessException("boo!"); + } + }); + + RemoteProvider remoteProvider = providesInjector.getInstance(Key.get(remoteProviderOfFoo)); try { remoteProvider.get(); @@ -989,113 +1076,126 @@ assertEquals("boo!", expected.getMessage()); } } - + public void testCxtorWithSubclassOfExceptionIsOk() throws Exception { - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(SubclassExceptionFoo.class); - } - }); - - RemoteProvider remoteProvider = - cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); - - try { - remoteProvider.get(); - fail(); - } catch (RemoteException expected) { - assertTrue(expected instanceof AccessException); - assertEquals("boo!", expected.getMessage()); - } + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(SubclassExceptionFoo.class); + } + }); + + RemoteProvider remoteProvider = cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); + + try { + remoteProvider.get(); + fail(); + } catch (RemoteException expected) { + assertTrue(expected instanceof AccessException); + assertEquals("boo!", expected.getMessage()); + } } - + static class SubclassExceptionFoo implements Foo { @ThrowingInject public SubclassExceptionFoo() throws AccessException { throw new AccessException("boo!"); } - + @Override - public String s() { return null; } + public String s() { + return null; + } } - + public void testProviderMethodWithSuperclassExceptionFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - Foo foo() throws IOException { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + Foo foo() throws IOException { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(IOException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + } catch (CreationException ce) { + assertEquals( + IOException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testCxtorWithSuperclassExceptionFails() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(SuperclassExceptionFoo.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(SuperclassExceptionFoo.class); + } + }); fail(); } catch (CreationException ce) { - assertEquals(IOException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + assertEquals( + IOException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + static class SuperclassExceptionFoo implements Foo { @SuppressWarnings("unused") @ThrowingInject - public SuperclassExceptionFoo() throws IOException { - } - + public SuperclassExceptionFoo() throws IOException {} + @Override - public String s() { return null; } + public String s() { + return null; + } } - + public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception { - providesInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - Foo foo() throws RuntimeException { - throw new RuntimeException("boo!"); - } - }); - - RemoteProvider remoteProvider = - providesInjector.getInstance(Key.get(remoteProviderOfFoo)); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + Foo foo() throws RuntimeException { + throw new RuntimeException("boo!"); + } + }); + + RemoteProvider remoteProvider = providesInjector.getInstance(Key.get(remoteProviderOfFoo)); try { remoteProvider.get(); @@ -1104,19 +1204,20 @@ assertEquals("boo!", expected.getCause().getMessage()); } } - + public void testCxtorWithRuntimeExceptionsIsOk() throws Exception { - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(RuntimeExceptionFoo.class); - } - }); - - RemoteProvider remoteProvider = - cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(RuntimeExceptionFoo.class); + } + }); + + RemoteProvider remoteProvider = cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); try { remoteProvider.get(); @@ -1125,428 +1226,477 @@ assertEquals("boo!", expected.getCause().getMessage()); } } - + static class RuntimeExceptionFoo implements Foo { @ThrowingInject public RuntimeExceptionFoo() throws RuntimeException { throw new RuntimeException("boo!"); } - + @Override - public String s() { return null; } + public String s() { + return null; + } } - + private static class SubBindException extends BindException {} - + public void testProviderMethodWithManyExceptions() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws InterruptedException, RuntimeException, RemoteException, - AccessException, TooManyListenersException, - BindException, SubBindException { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() + throws InterruptedException, RuntimeException, RemoteException, AccessException, + TooManyListenersException, BindException, SubBindException { + return null; + } + }); fail(); - } catch(CreationException ce) { + } catch (CreationException ce) { // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK. List errors = ImmutableList.copyOf(ce.getErrorMessages()); - assertEquals(InterruptedException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + assertEquals( + InterruptedException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", errors.get(0).getMessage()); - assertEquals(TooManyListenersException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + assertEquals( + TooManyListenersException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", errors.get(1).getMessage()); assertEquals(2, errors.size()); } } - + public void testCxtorWithManyExceptions() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(ManyExceptionFoo.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(ManyExceptionFoo.class); + } + }); fail(); } catch (CreationException ce) { // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK. List errors = ImmutableList.copyOf(ce.getErrorMessages()); - assertEquals(InterruptedException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + assertEquals( + InterruptedException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", errors.get(0).getMessage()); - assertEquals(TooManyListenersException.class.getName() - + " is not compatible with the exceptions ([" - + RemoteException.class + ", " + BindException.class - + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() - + ")", + assertEquals( + TooManyListenersException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + ", " + + BindException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", errors.get(1).getMessage()); assertEquals(2, errors.size()); } } - + static class ManyExceptionFoo implements Foo { @SuppressWarnings("unused") @ThrowingInject public ManyExceptionFoo() - throws InterruptedException, - RuntimeException, - RemoteException, - AccessException, - TooManyListenersException, - BindException, - SubBindException { - } - + throws InterruptedException, RuntimeException, RemoteException, AccessException, + TooManyListenersException, BindException, SubBindException {} + @Override - public String s() { return null; } + public String s() { + return null; + } } - + public void testMoreTypeParameters() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(TooManyTypeParameters.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(TooManyTypeParameters.class) + String foo() { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]", + } catch (CreationException ce) { + assertEquals( + TooManyTypeParameters.class.getName() + + " has more than one generic type parameter: [T, P]", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); - } + } } - + public void testWrongThrowingProviderType() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(WrongThrowingProviderType.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(WrongThrowingProviderType.class) + String foo() { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(WrongThrowingProviderType.class.getName() - + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider " - + "(java.lang.String) is not a generic type", + } catch (CreationException ce) { + assertEquals( + WrongThrowingProviderType.class.getName() + + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider " + + "(java.lang.String) is not a generic type", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); - } + } } - + public void testOneMethodThatIsntGet() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(OneNoneGetMethod.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(OneNoneGetMethod.class) + String foo() { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(OneNoneGetMethod.class.getName() - + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]), + } catch (CreationException ce) { + assertEquals( + OneNoneGetMethod.class.getName() + + " may not declare any new methods, but declared " + + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testManyMethods() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(ManyMethods.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(ManyMethods.class) + String foo() { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(ManyMethods.class.getName() - + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()), + } catch (CreationException ce) { + assertEquals( + ManyMethods.class.getName() + + " may not declare any new methods, but declared " + + Arrays.asList(ManyMethods.class.getDeclaredMethods()), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testIncorrectPredefinedType_Bind() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(StringRemoteProvider.class, Integer.class) - .to(new StringRemoteProvider() { - public String get() { - return "A"; - } - }); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(StringRemoteProvider.class, Integer.class) + .to( + new StringRemoteProvider() { + @Override + public String get() { + return "A"; + } + }); + } + }); fail(); - } catch(CreationException ce) { - assertEquals(StringRemoteProvider.class.getName() - + " expects the value type to be java.lang.String, but it was java.lang.Integer", + } catch (CreationException ce) { + assertEquals( + StringRemoteProvider.class.getName() + + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testIncorrectPredefinedType_Provides() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(StringRemoteProvider.class) - Integer foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(StringRemoteProvider.class) + Integer foo() { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(StringRemoteProvider.class.getName() - + " expects the value type to be java.lang.String, but it was java.lang.Integer", + } catch (CreationException ce) { + assertEquals( + StringRemoteProvider.class.getName() + + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - - private static interface TooManyTypeParameters extends CheckedProvider { - } - - private static interface WrongThrowingProviderType extends CheckedProvider { - } - + + private static interface TooManyTypeParameters extends CheckedProvider {} + + private static interface WrongThrowingProviderType extends CheckedProvider {} + private static interface OneNoneGetMethod extends CheckedProvider { T bar(); } - + private static interface ManyMethods extends CheckedProvider { T bar(); + String baz(); } - + public void testResultSerializes() throws Exception { Result result = Result.forValue("foo"); result = Asserts.reserialize(result); assertEquals("foo", result.getOrThrow()); } - + public void testResultExceptionSerializes() throws Exception { Result result = Result.forException(new Exception("boo")); result = Asserts.reserialize(result); try { result.getOrThrow(); fail(); - } catch(Exception ex) { + } catch (Exception ex) { assertEquals("boo", ex.getMessage()); } } - + public void testEarlyBindingError() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(StringRemoteProvider.class, String.class) - .to(FailingProvider.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(StringRemoteProvider.class, String.class) + .to(FailingProvider.class); + } + }); fail(); - } catch(CreationException ce) { - assertEquals("Could not find a suitable constructor in " + FailingProvider.class.getName() - + ". Classes must have either one (and only one) constructor annotated with @Inject" - + " or a zero-argument constructor that is not private.", + } catch (CreationException ce) { + assertEquals( + "Could not find a suitable constructor in " + + FailingProvider.class.getName() + + ". Classes must have either one (and only one) constructor annotated with @Inject" + + " or a zero-argument constructor that is not private.", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + private static class FailingProvider implements StringRemoteProvider { // no @Inject. @SuppressWarnings("unused") FailingProvider(Integer foo) {} - + + @Override public String get() { return null; } } - + public void testNoInjectionPointForUsing() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(InvalidFoo.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(InvalidFoo.class); + } + }); fail(); } catch (CreationException ce) { - assertEquals("Could not find a suitable constructor in " + InvalidFoo.class.getName() - + ". Classes must have either one (and only one) constructor annotated with " - + "@ThrowingInject.", + assertEquals( + "Could not find a suitable constructor in " + + InvalidFoo.class.getName() + + ". Classes must have either one (and only one) constructor annotated with " + + "@ThrowingInject.", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + static class InvalidFoo implements Foo { - public InvalidFoo(String dep) { + public InvalidFoo(String dep) {} + + @Override + public String s() { + return null; } - - @Override public String s() { return null; } } - + public void testNoThrowingInject() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(NormalInjectableFoo.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(NormalInjectableFoo.class); + } + }); fail(); } catch (CreationException ce) { - assertEquals("Could not find a suitable constructor in " + NormalInjectableFoo.class.getName() - + ". Classes must have either one (and only one) constructor annotated with " - + "@ThrowingInject.", + assertEquals( + "Could not find a suitable constructor in " + + NormalInjectableFoo.class.getName() + + ". Classes must have either one (and only one) constructor annotated with " + + "@ThrowingInject.", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + static class NormalInjectableFoo implements Foo { @Inject - public NormalInjectableFoo() { + public NormalInjectableFoo() {} + + @Override + public String s() { + return null; } - - @Override public String s() { return null; } } - + public void testProvisionExceptionOnDependenciesOfCxtor() throws Exception { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(ProvisionExceptionFoo.class); - bindScope(BadScope.class, new Scope() { - @Override - public Provider scope(Key key, Provider unscoped) { - return new Provider() { - @Override - public T get() { - throw new OutOfScopeException("failure"); - } - }; - } - }); - } - }); - + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(ProvisionExceptionFoo.class); + bindScope( + BadScope.class, + new Scope() { + @Override + public Provider scope(final Key key, Provider unscoped) { + return new Provider() { + @Override + public T get() { + throw new OutOfScopeException("failure: " + key.toString()); + } + }; + } + }); + } + }); + try { injector.getInstance(Key.get(remoteProviderOfFoo)).get(); fail(); - } catch(ProvisionException pe) { - assertEquals(2, pe.getErrorMessages().size()); - List messages = Lists.newArrayList(pe.getErrorMessages()); - assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure", - messages.get(0).getMessage()); - assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure", - messages.get(1).getMessage()); + } catch (ProvisionException pe) { + Message message = Iterables.getOnlyElement(pe.getErrorMessages()); + assertEquals( + "Error in custom provider, com.google.inject.OutOfScopeException: failure: " + + Key.get(Unscoped1.class), + message.getMessage()); } } - + @ScopeAnnotation @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) - private @interface BadScope { } - - @BadScope private static class Unscoped1 {} - @BadScope private static class Unscoped2 {} - + private @interface BadScope {} + + @BadScope + private static class Unscoped1 {} + + @BadScope + private static class Unscoped2 {} + static class ProvisionExceptionFoo implements Foo { @ThrowingInject - public ProvisionExceptionFoo(Unscoped1 a, Unscoped2 b) { + public ProvisionExceptionFoo(Unscoped1 a, Unscoped2 b) {} + + @Override + public String s() { + return null; } - - @Override public String s() { return null; } } - + public void testUsingDoesntClashWithBindingsOfSameType() throws Exception { - cxtorInjector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, Foo.class) - .providing(MockFoo.class); - bind(Foo.class).to(MockFoo.class); - bind(MockFoo.class).to(SubMockFoo.class); - } - }); - - RemoteProvider remoteProvider = - cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); + cxtorInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, Foo.class) + .providing(MockFoo.class); + bind(Foo.class).to(MockFoo.class); + bind(MockFoo.class).to(SubMockFoo.class); + } + }); + + RemoteProvider remoteProvider = cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)); Foo providerGot = remoteProvider.get(); Foo fooGot = cxtorInjector.getInstance(Foo.class); Foo mockGot = cxtorInjector.getInstance(MockFoo.class); - + assertEquals(MockFoo.class, providerGot.getClass()); assertEquals(SubMockFoo.class, fooGot.getClass()); assertEquals(SubMockFoo.class, mockGot.getClass()); } - + static class SubMockFoo extends MockFoo { - public SubMockFoo() throws RemoteException, BindException { - } - + public SubMockFoo() throws RemoteException, BindException {} } } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java --- sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.ScopeAnnotation; - import java.lang.annotation.Retention; import java.util.HashMap; import java.util.Map; @@ -34,14 +33,16 @@ */ class TestScope implements Scope { - @Retention(RUNTIME) @ScopeAnnotation - public @interface Scoped { } + @Retention(RUNTIME) + @ScopeAnnotation + public @interface Scoped {} - private Map inScopeObjectsMap = new HashMap(); + private Map inScopeObjectsMap = new HashMap<>(); - public Provider scope( - final Key key, final Provider provider) { + @Override + public Provider scope(final Key key, final Provider provider) { return new Provider() { + @Override @SuppressWarnings({"unchecked"}) public T get() { T t = (T) inScopeObjectsMap.get(key); @@ -55,6 +56,6 @@ } public void beginNewScope() { - inScopeObjectsMap = new HashMap(); + inScopeObjectsMap = new HashMap<>(); } } diff -Nru sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java --- sisu-guice-3.2.6/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,9 +37,6 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; - -import junit.framework.TestCase; - import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; @@ -50,6 +47,7 @@ import java.util.List; import java.util.Set; import java.util.TooManyListenersException; +import junit.framework.TestCase; /** * @author jmourits@google.com (Jerome Mourits) @@ -57,61 +55,68 @@ */ @SuppressWarnings("deprecation") public class ThrowingProviderTest extends TestCase { - @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation - @interface NotExceptionScoping { }; - - private final TypeLiteral> remoteProviderOfString - = new TypeLiteral>() { }; - private final MockRemoteProvider mockRemoteProvider = new MockRemoteProvider(); + @Target(METHOD) + @Retention(RUNTIME) + @BindingAnnotation + @interface NotExceptionScoping {}; + + private final TypeLiteral> remoteProviderOfString = + new TypeLiteral>() {}; + private final MockRemoteProvider mockRemoteProvider = new MockRemoteProvider<>(); private final TestScope testScope = new TestScope(); - private Injector bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, String.class) - .to(mockRemoteProvider) - .in(testScope); - - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, String.class) - .annotatedWith(NotExceptionScoping.class) - .scopeExceptions(false) - .to(mockRemoteProvider) - .in(testScope); - } - }); - private Injector providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - bindScope(TestScope.Scoped.class, testScope); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - @TestScope.Scoped - String throwOrGet() throws RemoteException { - return mockRemoteProvider.get(); - } - - @SuppressWarnings("unused") - @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false) - @NotExceptionScoping - @TestScope.Scoped - String notExceptionScopingThrowOrGet() throws RemoteException { - return mockRemoteProvider.get(); - } - }); + private Injector bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, String.class) + .to(mockRemoteProvider) + .in(testScope); + + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, String.class) + .annotatedWith(NotExceptionScoping.class) + .scopeExceptions(false) + .to(mockRemoteProvider) + .in(testScope); + } + }); + private Injector providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + bindScope(TestScope.Scoped.class, testScope); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + @TestScope.Scoped + String throwOrGet() throws RemoteException { + return mockRemoteProvider.get(); + } + + @SuppressWarnings("unused") + @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false) + @NotExceptionScoping + @TestScope.Scoped + String notExceptionScopingThrowOrGet() throws RemoteException { + return mockRemoteProvider.get(); + } + }); public void testExceptionsThrown_Bind() { tExceptionsThrown(bindInjector); } - + public void testExceptionsThrown_Provides() { tExceptionsThrown(providesInjector); } - + private void tExceptionsThrown(Injector injector) { - RemoteProvider remoteProvider = - injector.getInstance(Key.get(remoteProviderOfString)); + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet("kaboom!"); try { @@ -125,24 +130,25 @@ public void testValuesScoped_Bind() throws RemoteException { tValuesScoped(bindInjector, null); } - + public void testValuesScoped_Provides() throws RemoteException { tValuesScoped(providesInjector, null); } - + public void testValuesScopedWhenNotExceptionScoping_Bind() throws RemoteException { tValuesScoped(bindInjector, NotExceptionScoping.class); } - + public void testValuesScopedWhenNotExceptionScoping_Provides() throws RemoteException { tValuesScoped(providesInjector, NotExceptionScoping.class); } - - private void tValuesScoped(Injector injector, Class annotation) + + private void tValuesScoped(Injector injector, Class annotation) throws RemoteException { - Key> key = annotation != null ? - Key.get(remoteProviderOfString, annotation) : - Key.get(remoteProviderOfString); + Key> key = + annotation != null + ? Key.get(remoteProviderOfString, annotation) + : Key.get(remoteProviderOfString); RemoteProvider remoteProvider = injector.getInstance(key); mockRemoteProvider.setNextToReturn("A"); @@ -158,14 +164,13 @@ public void testExceptionsScoped_Bind() { tExceptionsScoped(bindInjector); } - + public void testExceptionsScoped_Provides() { tExceptionsScoped(providesInjector); } - + private void tExceptionsScoped(Injector injector) { - RemoteProvider remoteProvider = - injector.getInstance(Key.get(remoteProviderOfString)); + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet("A"); try { @@ -174,7 +179,7 @@ } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } - + mockRemoteProvider.throwOnNextGet("B"); try { remoteProvider.get(); @@ -187,13 +192,13 @@ public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() { tExceptionsNotScopedWhenNotExceptionScoping(bindInjector); } - + public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() { tExceptionsNotScopedWhenNotExceptionScoping(providesInjector); } - + private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) { - RemoteProvider remoteProvider = + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString, NotExceptionScoping.class)); mockRemoteProvider.throwOnNextGet("A"); @@ -203,7 +208,7 @@ } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } - + mockRemoteProvider.throwOnNextGet("B"); try { remoteProvider.get(); @@ -212,71 +217,76 @@ assertEquals("B", expected.getMessage()); } } - + public void testAnnotations_Bind() throws RemoteException { - final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); - final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, String.class) - .annotatedWith(Names.named("a")) - .to(mockRemoteProviderA); - - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, String.class) - .to(mockRemoteProviderB); - } - }); + final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider<>(); + final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider<>(); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, String.class) + .annotatedWith(Names.named("a")) + .to(mockRemoteProviderA); + + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, String.class) + .to(mockRemoteProviderB); + } + }); tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB); } - + public void testAnnotations_Provides() throws RemoteException { - final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); - final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); - providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - @Named("a") - String throwOrGet() throws RemoteException { - return mockRemoteProviderA.get(); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String throwOrGet2() throws RemoteException { - return mockRemoteProviderB.get(); - } - }); + final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider<>(); + final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider<>(); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + @Named("a") + String throwOrGet() throws RemoteException { + return mockRemoteProviderA.get(); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String throwOrGet2() throws RemoteException { + return mockRemoteProviderB.get(); + } + }); tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB); } - - private void tAnnotations(Injector injector, MockRemoteProvider mockA, - MockRemoteProvider mockB) throws RemoteException { + + private void tAnnotations( + Injector injector, MockRemoteProvider mockA, MockRemoteProvider mockB) + throws RemoteException { mockA.setNextToReturn("A"); mockB.setNextToReturn("B"); - assertEquals("A", - injector.getInstance(Key.get(remoteProviderOfString, Names.named("a"))).get()); + assertEquals( + "A", injector.getInstance(Key.get(remoteProviderOfString, Names.named("a"))).get()); - assertEquals("B", - injector.getInstance(Key.get(remoteProviderOfString)).get()); + assertEquals("B", injector.getInstance(Key.get(remoteProviderOfString)).get()); } - + public void testUndeclaredExceptions_Bind() throws RemoteException { tUndeclaredExceptions(bindInjector); } - + public void testUndeclaredExceptions_Provides() throws RemoteException { tUndeclaredExceptions(providesInjector); } - private void tUndeclaredExceptions(Injector injector) throws RemoteException { - RemoteProvider remoteProvider = - injector.getInstance(Key.get(remoteProviderOfString)); + private void tUndeclaredExceptions(Injector injector) throws RemoteException { + RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A")); try { remoteProvider.get(); @@ -299,224 +309,279 @@ final SubMockRemoteProvider aProvider = new SubMockRemoteProvider(); aProvider.setNextToReturn("A"); - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, String.class) - .to(aProvider); - } - }); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, String.class) + .to(aProvider); + } + }); - assertEquals("A", - bindInjector.getInstance(Key.get(remoteProviderOfString)).get()); + assertEquals("A", bindInjector.getInstance(Key.get(remoteProviderOfString)).get()); } - static class SubMockRemoteProvider extends MockRemoteProvider { } + static class SubMockRemoteProvider extends MockRemoteProvider {} public void testBindingToNonInterfaceType_Bind() throws RemoteException { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(MockRemoteProvider.class, String.class) - .to(mockRemoteProvider); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(MockRemoteProvider.class, String.class) + .to(mockRemoteProvider); + } + }); fail(); } catch (CreationException expected) { - assertEquals(MockRemoteProvider.class.getName() + " must be an interface", + assertEquals( + MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testBindingToNonInterfaceType_Provides() throws RemoteException { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(MockRemoteProvider.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(MockRemoteProvider.class) + String foo() { + return null; + } + }); fail(); } catch (CreationException expected) { - assertEquals(MockRemoteProvider.class.getName() + " must be an interface", + assertEquals( + MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } - } - + } + public void testBindingToSubSubInterface_Bind() throws RemoteException { try { - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(SubRemoteProvider.class, String.class); - } - }); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(SubRemoteProvider.class, String.class); + } + }); fail(); } catch (CreationException expected) { - assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", + assertEquals( + SubRemoteProvider.class.getName() + + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testBindingToSubSubInterface_Provides() throws RemoteException { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(SubRemoteProvider.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(SubRemoteProvider.class) + String foo() { + return null; + } + }); fail(); } catch (CreationException expected) { - assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", + assertEquals( + SubRemoteProvider.class.getName() + + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } - } + } - interface SubRemoteProvider extends RemoteProvider { } + interface SubRemoteProvider extends RemoteProvider {} public void testBindingToInterfaceWithExtraMethod_Bind() throws RemoteException { try { - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProviderWithExtraMethod.class, String.class); - } - }); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProviderWithExtraMethod.class, String.class); + } + }); fail(); } catch (CreationException expected) { - assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " - + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), + assertEquals( + RemoteProviderWithExtraMethod.class.getName() + + " may not declare any new methods, but declared " + + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testBindingToInterfaceWithExtraMethod_Provides() throws RemoteException { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProviderWithExtraMethod.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProviderWithExtraMethod.class) + String foo() { + return null; + } + }); fail(); } catch (CreationException expected) { - assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " - + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), + assertEquals( + RemoteProviderWithExtraMethod.class.getName() + + " may not declare any new methods, but declared " + + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } - + public void testDependencies_Bind() { - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("Foo"); - bind(Integer.class).toInstance(5); - bind(Double.class).toInstance(5d); - bind(Long.class).toInstance(5L); - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, String.class) - .to(DependentRemoteProvider.class); - } - }); - + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("Foo"); + bind(Integer.class).toInstance(5); + bind(Double.class).toInstance(5d); + bind(Long.class).toInstance(5L); + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, String.class) + .to(DependentRemoteProvider.class); + } + }); + HasDependencies hasDependencies = - (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfString)); - hasDependencies = - (HasDependencies)bindInjector.getBinding( - Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); + (HasDependencies) bindInjector.getBinding(Key.get(remoteProviderOfString)); + hasDependencies = + (HasDependencies) + bindInjector.getBinding( + Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // Make sure that that is dependent on DependentRemoteProvider. - assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), + assertEquals( + Dependency.get(Key.get(DependentRemoteProvider.class)), Iterables.getOnlyElement(hasDependencies.getDependencies())); // And make sure DependentRemoteProvider has the proper dependencies. - hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class); - Set> dependencyKeys = ImmutableSet.copyOf( - Iterables.transform(hasDependencies.getDependencies(), - new Function, Key>() { - public Key apply(Dependency from) { - return from.getKey(); - } - })); - assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), - Key.get(Long.class), Key.get(Double.class)), dependencyKeys); + hasDependencies = (HasDependencies) bindInjector.getBinding(DependentRemoteProvider.class); + Set> dependencyKeys = + ImmutableSet.copyOf( + Iterables.transform( + hasDependencies.getDependencies(), + new Function, Key>() { + @Override + public Key apply(Dependency from) { + return from.getKey(); + } + })); + assertEquals( + ImmutableSet.>of( + Key.get(String.class), + Key.get(Integer.class), + Key.get(Long.class), + Key.get(Double.class)), + dependencyKeys); } - + public void testDependencies_Provides() { - providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - bind(String.class).toInstance("Foo"); - bind(Integer.class).toInstance(5); - bind(Double.class).toInstance(5d); - bind(Long.class).toInstance(5L); - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo(String s, Integer i, Double d, Long l) { - return null; - } - }); - + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("Foo"); + bind(Integer.class).toInstance(5); + bind(Double.class).toInstance(5d); + bind(Long.class).toInstance(5L); + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo(String s, Integer i, Double d, Long l) { + return null; + } + }); + HasDependencies hasDependencies = - (HasDependencies)providesInjector.getBinding(Key.get(remoteProviderOfString)); + (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfString)); // RemoteProvider is dependent on the provider method.. - hasDependencies = - (HasDependencies)providesInjector.getBinding( - Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); + hasDependencies = + (HasDependencies) + providesInjector.getBinding( + Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // And the provider method has our real dependencies.. - hasDependencies = (HasDependencies)providesInjector.getBinding( - Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); - Set> dependencyKeys = ImmutableSet.copyOf( - Iterables.transform(hasDependencies.getDependencies(), - new Function, Key>() { - public Key apply(Dependency from) { - return from.getKey(); - } - })); - assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), - Key.get(Long.class), Key.get(Double.class)), dependencyKeys); - } + hasDependencies = + (HasDependencies) + providesInjector.getBinding( + Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); + Set> dependencyKeys = + ImmutableSet.copyOf( + Iterables.transform( + hasDependencies.getDependencies(), + new Function, Key>() { + @Override + public Key apply(Dependency from) { + return from.getKey(); + } + })); + assertEquals( + ImmutableSet.>of( + Key.get(String.class), + Key.get(Integer.class), + Key.get(Long.class), + Key.get(Double.class)), + dependencyKeys); + } interface RemoteProviderWithExtraMethod extends ThrowingProvider { T get(T defaultValue) throws RemoteException; } - interface RemoteProvider extends ThrowingProvider { } - + interface RemoteProvider extends ThrowingProvider {} + static class DependentRemoteProvider implements RemoteProvider { @Inject double foo; - - @Inject public DependentRemoteProvider(String foo, int bar) { - } - - @Inject void initialize(long foo) {} - + + @Inject + public DependentRemoteProvider(String foo, int bar) {} + + @Inject + void initialize(long foo) {} + + @Override public T get() throws RemoteException { return null; } } - + static class MockRemoteProvider implements RemoteProvider { Exception nextToThrow; T nextToReturn; - + public void throwOnNextGet(String message) { throwOnNextGet(new RemoteException(message)); } @@ -528,7 +593,8 @@ public void setNextToReturn(T nextToReturn) { this.nextToReturn = nextToReturn; } - + + @Override public T get() throws RemoteException { if (nextToThrow instanceof RemoteException) { throw (RemoteException) nextToThrow; @@ -543,112 +609,137 @@ } public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException { - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(StringRemoteProvider.class, String.class) - .to(new StringRemoteProvider() { - public String get() throws RemoteException { - return "A"; + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(StringRemoteProvider.class, String.class) + .to( + new StringRemoteProvider() { + @Override + public String get() throws RemoteException { + return "A"; + } + }); } }); - } - }); - + assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get()); } - + public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException { - providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(StringRemoteProvider.class) - String foo() throws RemoteException { - return "A"; - } - }); - + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(StringRemoteProvider.class) + String foo() throws RemoteException { + return "A"; + } + }); + assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get()); } - interface StringRemoteProvider extends ThrowingProvider { } + interface StringRemoteProvider extends ThrowingProvider {} public void testBindingToInterfaceWithGeneric_Bind() throws RemoteException { - bindInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(RemoteProvider.class, new TypeLiteral>() { }.getType()) - .to(new RemoteProvider>() { - public List get() throws RemoteException { - return Arrays.asList("A", "B"); + bindInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(RemoteProvider.class, new TypeLiteral>() {}.getType()) + .to( + new RemoteProvider>() { + @Override + public List get() throws RemoteException { + return Arrays.asList("A", "B"); + } + }); } }); - } - }); - Key>> key - = Key.get(new TypeLiteral>>() { }); + Key>> key = + Key.get(new TypeLiteral>>() {}); assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get()); } - + public void testBindingToInterfaceWithGeneric_Provides() throws RemoteException { - providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - List foo() throws RemoteException { - return Arrays.asList("A", "B"); - } - }); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } - Key>> key - = Key.get(new TypeLiteral>>() { }); + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + List foo() throws RemoteException { + return Arrays.asList("A", "B"); + } + }); + + Key>> key = + Key.get(new TypeLiteral>>() {}); assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get()); } - + public void testProviderMethodWithWrongException() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws InterruptedException { - return null; - } - }); - fail(); - } catch(CreationException ce) { - assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions ([" - + RemoteException.class + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() + ")", + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() throws InterruptedException { + return null; + } + }); + fail(); + } catch (CreationException ce) { + assertEquals( + InterruptedException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testProviderMethodWithSubclassOfExceptionIsOk() { - providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws AccessException { - throw new AccessException("boo!"); - } - }); - - RemoteProvider remoteProvider = - providesInjector.getInstance(Key.get(remoteProviderOfString)); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() throws AccessException { + throw new AccessException("boo!"); + } + }); + + RemoteProvider remoteProvider = + providesInjector.getInstance(Key.get(remoteProviderOfString)); try { remoteProvider.get(); @@ -658,44 +749,53 @@ assertEquals("boo!", expected.getMessage()); } } - + public void testProviderMethodWithSuperclassFails() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws IOException { - return null; - } - }); - fail(); - } catch(CreationException ce) { - assertEquals(IOException.class.getName() + " is not compatible with the exceptions ([" - + RemoteException.class + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() + ")", + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() throws IOException { + return null; + } + }); + fail(); + } catch (CreationException ce) { + assertEquals( + IOException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testProviderMethodWithRuntimeExceptionsIsOk() throws RemoteException { - providesInjector = Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws RuntimeException { - throw new RuntimeException("boo!"); - } - }); - - RemoteProvider remoteProvider = - providesInjector.getInstance(Key.get(remoteProviderOfString)); + providesInjector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() throws RuntimeException { + throw new RuntimeException("boo!"); + } + }); + + RemoteProvider remoteProvider = + providesInjector.getInstance(Key.get(remoteProviderOfString)); try { remoteProvider.get(); @@ -704,175 +804,209 @@ assertEquals("boo!", expected.getCause().getMessage()); } } - + public void testProviderMethodWithManyExceptions() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(RemoteProvider.class) - String foo() throws InterruptedException, RuntimeException, RemoteException, - AccessException, TooManyListenersException { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(RemoteProvider.class) + String foo() + throws InterruptedException, RuntimeException, RemoteException, AccessException, + TooManyListenersException { + return null; + } + }); fail(); - } catch(CreationException ce) { + } catch (CreationException ce) { // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK. List errors = ImmutableList.copyOf(ce.getErrorMessages()); - assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions ([" - + RemoteException.class + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() + ")", + assertEquals( + InterruptedException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", errors.get(0).getMessage()); - assertEquals(TooManyListenersException.class.getName() + " is not compatible with the exceptions ([" - + RemoteException.class + "]) declared in the CheckedProvider interface (" - + RemoteProvider.class.getName() + ")", + assertEquals( + TooManyListenersException.class.getName() + + " is not compatible with the exceptions ([" + + RemoteException.class + + "]) declared in the CheckedProvider interface (" + + RemoteProvider.class.getName() + + ")", errors.get(1).getMessage()); assertEquals(2, errors.size()); } } - + public void testMoreTypeParameters() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(TooManyTypeParameters.class) - String foo() { - return null; - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(TooManyTypeParameters.class) + String foo() { + return null; + } + }); fail(); - } catch(CreationException ce) { - assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]", + } catch (CreationException ce) { + assertEquals( + TooManyTypeParameters.class.getName() + + " has more than one generic type parameter: [T, P]", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); - } + } } - + public void testWrongThrowingProviderType() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(WrongThrowingProviderType.class) - String foo() { - return null; - } - }); - fail(); - } catch(CreationException ce) { - assertEquals(WrongThrowingProviderType.class.getName() - + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider " - + "(java.lang.String) is not a generic type", + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(WrongThrowingProviderType.class) + String foo() { + return null; + } + }); + fail(); + } catch (CreationException ce) { + assertEquals( + WrongThrowingProviderType.class.getName() + + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider " + + "(java.lang.String) is not a generic type", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); - } + } } - + public void testOneMethodThatIsntGet() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(OneNoneGetMethod.class) - String foo() { - return null; - } - }); - fail(); - } catch(CreationException ce) { - assertEquals(OneNoneGetMethod.class.getName() - + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]), + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(OneNoneGetMethod.class) + String foo() { + return null; + } + }); + fail(); + } catch (CreationException ce) { + assertEquals( + OneNoneGetMethod.class.getName() + + " may not declare any new methods, but declared " + + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testManyMethods() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(ManyMethods.class) - String foo() { - return null; - } - }); - fail(); - } catch(CreationException ce) { - assertEquals(ManyMethods.class.getName() - + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()), + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(ManyMethods.class) + String foo() { + return null; + } + }); + fail(); + } catch (CreationException ce) { + assertEquals( + ManyMethods.class.getName() + + " may not declare any new methods, but declared " + + Arrays.asList(ManyMethods.class.getDeclaredMethods()), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testIncorrectPredefinedType_Bind() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - ThrowingProviderBinder.create(binder()) - .bind(StringRemoteProvider.class, Integer.class) - .to(new StringRemoteProvider() { - public String get() throws RemoteException { - return "A"; - } - }); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + ThrowingProviderBinder.create(binder()) + .bind(StringRemoteProvider.class, Integer.class) + .to( + new StringRemoteProvider() { + @Override + public String get() throws RemoteException { + return "A"; + } + }); + } + }); fail(); - } catch(CreationException ce) { - assertEquals(StringRemoteProvider.class.getName() - + " expects the value type to be java.lang.String, but it was java.lang.Integer", + } catch (CreationException ce) { + assertEquals( + StringRemoteProvider.class.getName() + + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - + public void testIncorrectPredefinedType_Provides() { try { - Guice.createInjector(new AbstractModule() { - protected void configure() { - install(ThrowingProviderBinder.forModule(this)); - } - - @SuppressWarnings("unused") - @CheckedProvides(StringRemoteProvider.class) - Integer foo() { - return null; - } - }); - fail(); - } catch(CreationException ce) { - assertEquals(StringRemoteProvider.class.getName() - + " expects the value type to be java.lang.String, but it was java.lang.Integer", + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(ThrowingProviderBinder.forModule(this)); + } + + @SuppressWarnings("unused") + @CheckedProvides(StringRemoteProvider.class) + Integer foo() { + return null; + } + }); + fail(); + } catch (CreationException ce) { + assertEquals( + StringRemoteProvider.class.getName() + + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } - - private static interface TooManyTypeParameters extends ThrowingProvider { - } - - private static interface WrongThrowingProviderType extends ThrowingProvider { - } - + + private static interface TooManyTypeParameters extends ThrowingProvider {} + + private static interface WrongThrowingProviderType + extends ThrowingProvider {} + private static interface OneNoneGetMethod extends ThrowingProvider { T bar(); } - + private static interface ManyMethods extends ThrowingProvider { T bar(); + String baz(); } } diff -Nru sisu-guice-3.2.6/.gitignore sisu-guice-4.2.0/.gitignore --- sisu-guice-3.2.6/.gitignore 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/.gitignore 2018-04-03 18:18:08.000000000 +0000 @@ -10,3 +10,4 @@ .idea/ *.iml *.ipr +extensions/**/build/ \ No newline at end of file diff -Nru sisu-guice-3.2.6/jdk8-tests/pom.xml sisu-guice-4.2.0/jdk8-tests/pom.xml --- sisu-guice-3.2.6/jdk8-tests/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/jdk8-tests/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -13,13 +13,11 @@ See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. --> - + org.sonatype.sisu.inject guice-parent - 4.0-SNAPSHOT + 4.2.0 4.0.0 @@ -34,6 +32,12 @@ ${project.version} test + + org.sonatype.sisu.inject + guice-assistedinject + ${project.version} + test + cglib cglib diff -Nru sisu-guice-3.2.6/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java sisu-guice-4.2.0/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java --- sisu-guice-3.2.6/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,14 +24,11 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.matcher.Matchers; - -import junit.framework.TestCase; - -import org.aopalliance.intercept.MethodInterceptor; - import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.concurrent.atomic.AtomicInteger; +import junit.framework.TestCase; +import org.aopalliance.intercept.MethodInterceptor; /** * Tests for interception of default methods. @@ -44,10 +41,11 @@ private static final AtomicInteger interceptedCallCount = new AtomicInteger(0); // the interceptor's a lambda too - private final MethodInterceptor interceptor = invocation -> { - interceptedCallCount.incrementAndGet(); - return invocation.proceed(); - }; + private final MethodInterceptor interceptor = + invocation -> { + interceptedCallCount.incrementAndGet(); + return invocation.proceed(); + }; @Override protected void setUp() throws Exception { @@ -76,14 +74,16 @@ } public void testInterceptedDefaultMethod() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class), - interceptor); - bind(Foo.class).to(NonOverridingFoo.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.annotatedWith(InterceptMe.class), interceptor); + bind(Foo.class).to(NonOverridingFoo.class); + } + }); Foo foo = injector.getInstance(Foo.class); assertEquals("Foo", foo.defaultMethod()); @@ -92,13 +92,15 @@ } public void testInterceptedDefaultMethod_calledByAnotherMethod() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class), - interceptor); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.annotatedWith(InterceptMe.class), interceptor); + } + }); NonOverridingFoo foo = injector.getInstance(NonOverridingFoo.class); assertEquals("NonOverriding-Foo", foo.methodCallingDefault()); @@ -116,18 +118,19 @@ } /** Foo implementation that should use superclass method rather than default method. */ - public static class InheritingFoo extends BaseClass implements Foo { - } + public static class InheritingFoo extends BaseClass implements Foo {} public void testInterceptedDefaultMethod_whenParentClassDefinesNonInterceptedMethod() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class), - interceptor); - bind(Foo.class).to(InheritingFoo.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.annotatedWith(InterceptMe.class), interceptor); + bind(Foo.class).to(InheritingFoo.class); + } + }); // the concrete implementation that wins is not annotated Foo foo = injector.getInstance(Foo.class); @@ -151,18 +154,19 @@ /** * Foo implementation that should use intercepted superclass method rather than default method. */ - public static class InheritingFoo2 extends BaseClass2 implements Foo { - } + public static class InheritingFoo2 extends BaseClass2 implements Foo {} public void testInterceptedDefaultMethod_whenParentClassDefinesInterceptedMethod() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class), - interceptor); - bind(Foo.class).to(InheritingFoo2.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor( + Matchers.any(), Matchers.annotatedWith(InterceptMe.class), interceptor); + bind(Foo.class).to(InheritingFoo2.class); + } + }); // the concrete implementation that wins is not annotated Foo foo = injector.getInstance(Foo.class); @@ -188,13 +192,15 @@ } public void testInterception_ofAllMethodsOnType() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindInterceptor(Matchers.subclassesOf(Baz.class), Matchers.any(), interceptor); - bind(Baz.class).to(BazImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor(Matchers.subclassesOf(Baz.class), Matchers.any(), interceptor); + bind(Baz.class).to(BazImpl.class); + } + }); Baz baz = injector.getInstance(Baz.class); @@ -205,13 +211,15 @@ } public void testInterception_ofAllMethodsOnType_interceptsInheritedDefaultMethod() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bindInterceptor(Matchers.subclassesOf(BazImpl.class), Matchers.any(), interceptor); - bind(Baz.class).to(BazImpl.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bindInterceptor(Matchers.subclassesOf(BazImpl.class), Matchers.any(), interceptor); + bind(Baz.class).to(BazImpl.class); + } + }); Baz baz = injector.getInstance(Baz.class); diff -Nru sisu-guice-3.2.6/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java sisu-guice-4.2.0/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java --- sisu-guice-3.2.6/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,14 +26,12 @@ import com.google.inject.Provides; import com.google.inject.ProvisionException; import com.google.inject.TypeLiteral; - -import junit.framework.TestCase; - import java.util.Collections; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; +import junit.framework.TestCase; /** * Test bindings to lambdas, method references, etc. @@ -46,12 +44,14 @@ // See https://github.com/google/guice/issues/757 for more on why they exist. public void testBinding_lambdaToInterface() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(new TypeLiteral>() {}).toInstance(o -> o != null); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(new TypeLiteral>() {}).toInstance(o -> o != null); + } + }); Predicate predicate = injector.getInstance(new Key>() {}); assertTrue(predicate.test(new Object())); @@ -59,34 +59,34 @@ } public void testProviderMethod_returningLambda() throws Exception { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() {} - - @Provides - public Callable provideCallable() { - return () -> "foo"; - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + + @Provides + public Callable provideCallable() { + return () -> "foo"; + } + }); Callable callable = injector.getInstance(new Key>() {}); assertEquals("foo", callable.call()); } public void testProviderMethod_containingLambda_throwingException() throws Exception { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() {} - - @Provides - public Callable provideCallable() { - if (Boolean.parseBoolean("false")) { // avoid dead code warnings - return () -> "foo"; - } else { - throw new RuntimeException("foo"); - } - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + + @Provides + public Callable provideCallable() { + if (Boolean.parseBoolean("false")) { // avoid dead code warnings + return () -> "foo"; + } else { + throw new RuntimeException("foo"); + } + } + }); try { injector.getInstance(new Key>() {}); @@ -98,25 +98,28 @@ public void testProvider_usingJdk8Features() { try { - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toProvider(StringProvider.class); - } - }); + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toProvider(StringProvider.class); + } + }); fail(); } catch (CreationException expected) { } UUID uuid = UUID.randomUUID(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(UUID.class).toInstance(uuid); - bind(String.class).toProvider(StringProvider.class); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(UUID.class).toInstance(uuid); + bind(String.class).toProvider(StringProvider.class); + } + }); assertEquals(uuid.toString(), injector.getInstance(String.class)); } @@ -131,32 +134,34 @@ @Override public String get() { - return Collections.singleton(uuid).stream() - .map(UUID::toString) - .findFirst().get(); + return Collections.singleton(uuid).stream().map(UUID::toString).findFirst().get(); } } public void testBinding_toProvider_lambda() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - AtomicInteger i = new AtomicInteger(); - bind(String.class).toProvider(() -> "Hello" + i.incrementAndGet()); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + AtomicInteger i = new AtomicInteger(); + bind(String.class).toProvider(() -> "Hello" + i.incrementAndGet()); + } + }); assertEquals("Hello1", injector.getInstance(String.class)); assertEquals("Hello2", injector.getInstance(String.class)); } public void testBinding_toProvider_methodReference() { - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(String.class).toProvider(Java8LanguageFeatureBindingTest.this::provideString); - } - }); + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toProvider(Java8LanguageFeatureBindingTest.this::provideString); + } + }); Provider provider = injector.getProvider(String.class); assertEquals("Hello", provider.get()); diff -Nru sisu-guice-3.2.6/jdk8-tests/test/com/google/inject/jdk8/StaticInterfaceMethodsTest.java sisu-guice-4.2.0/jdk8-tests/test/com/google/inject/jdk8/StaticInterfaceMethodsTest.java --- sisu-guice-3.2.6/jdk8-tests/test/com/google/inject/jdk8/StaticInterfaceMethodsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/jdk8-tests/test/com/google/inject/jdk8/StaticInterfaceMethodsTest.java 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.jdk8; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.FactoryModuleBuilder; +import junit.framework.TestCase; + +/** + * Test static methods in interfaces. + * + * @author tavianator@tavianator.com (Tavian Barnes) + */ +public class StaticInterfaceMethodsTest extends TestCase { + + private static class Thing { + final int i; + + @Inject + Thing(@Assisted int i) { + this.i = i; + } + } + + private interface Factory { + Thing create(int i); + + static Factory getDefault() { + return Thing::new; + } + } + + public void testAssistedInjection() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + install(new FactoryModuleBuilder().build(Factory.class)); + } + }); + Factory factory = injector.getInstance(Factory.class); + assertEquals(1, factory.create(1).i); + } +} diff -Nru sisu-guice-3.2.6/lib/build/jdiff/Null.java sisu-guice-4.2.0/lib/build/jdiff/Null.java --- sisu-guice-3.2.6/lib/build/jdiff/Null.java 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/lib/build/jdiff/Null.java 2018-04-03 18:18:08.000000000 +0000 @@ -1,9 +1,7 @@ -/** - * This class is used only as a "null" argument for Javadoc when comparing - * two API files. Javadoc has to have a package, .java or .class file as an - * argument, even though JDiff doesn't use it. +/** + * This class is used only as a "null" argument for Javadoc when comparing two API files. Javadoc + * has to have a package, .java or .class file as an argument, even though JDiff doesn't use it. */ public class Null { - public Null() { - } + public Null() {} } diff -Nru sisu-guice-3.2.6/PATCHES/GUICE_1171_remove_java6_references.patch sisu-guice-4.2.0/PATCHES/GUICE_1171_remove_java6_references.patch --- sisu-guice-3.2.6/PATCHES/GUICE_1171_remove_java6_references.patch 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/PATCHES/GUICE_1171_remove_java6_references.patch 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,66 @@ +Description: Remove some lingering references to Java 6 (Guice 4.2+ requires Java 7) +Author: Stuart McCulloch +Bug-Google: https://github.com/google/guice/issues/1171 +Last-Update: 2018-04-03 + +diff --git a/common.xml b/common.xml +index 0f661926..6e4b084c 100644 +--- a/common.xml ++++ b/common.xml +@@ -35,7 +35,7 @@ + + + +- ++ + + + +diff --git a/core/pom.xml b/core/pom.xml +index 2a81de58..03dd0fbc 100644 +--- a/core/pom.xml ++++ b/core/pom.xml +@@ -86,7 +86,7 @@ + maven-remote-resources-plugin + + + + org.codehaus.mojo +diff --git a/extensions/pom.xml b/extensions/pom.xml +index ff8350e7..d1da67c8 100644 +--- a/extensions/pom.xml ++++ b/extensions/pom.xml +@@ -90,7 +90,7 @@ + maven-remote-resources-plugin + + + + org.codehaus.mojo +diff --git a/pom.xml b/pom.xml +index ebb0d028..60b3c958 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -32,7 +32,7 @@ See the Apache License Version 2.0 for the specific language governing permissio + Google Guice + + +- Guice is a lightweight dependency injection framework for Java 6 and above ++ Guice is a lightweight dependency injection framework for Java 7 and above + + + https://github.com/google/guice +@@ -345,7 +345,7 @@ See the Apache License Version 2.0 for the specific language governing permissio + https://github.com/google/guice + ${project.artifactId} + $(module) +- JavaSE-1.6 ++ JavaSE-1.7 + !com.google.inject.*,* + <_exportcontents>!*.internal.*,$(module).*;version=${guice.api.version} + <_versionpolicy>$(version;==;$(@)) diff -Nru sisu-guice-3.2.6/PATCHES/GUICE_1172_mark_jsr305_as_optional.patch sisu-guice-4.2.0/PATCHES/GUICE_1172_mark_jsr305_as_optional.patch --- sisu-guice-3.2.6/PATCHES/GUICE_1172_mark_jsr305_as_optional.patch 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/PATCHES/GUICE_1172_mark_jsr305_as_optional.patch 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,17 @@ +Description: Mark JSR305 dependency as optional for throwingproviders +Author: Stuart McCulloch +Bug-Google: https://github.com/google/guice/issues/1172 +Last-Update: 2018-04-03 + +diff --git a/extensions/throwingproviders/pom.xml b/extensions/throwingproviders/pom.xml +index 2ef89f38..762d5b7c 100644 +--- a/extensions/throwingproviders/pom.xml ++++ b/extensions/throwingproviders/pom.xml +@@ -44,6 +44,7 @@ + + com.google.code.findbugs + jsr305 ++ true + + + diff -Nru sisu-guice-3.2.6/PATCHES/GUICE_1173_fix_osgi_metadata.patch sisu-guice-4.2.0/PATCHES/GUICE_1173_fix_osgi_metadata.patch --- sisu-guice-3.2.6/PATCHES/GUICE_1173_fix_osgi_metadata.patch 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/PATCHES/GUICE_1173_fix_osgi_metadata.patch 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,41 @@ +Description: Fix two minor OSGi metadata issues caused by upgrade to bundleplugin 3.5.0 +Author: Stuart McCulloch +Bug-Google: https://github.com/google/guice/issues/1173 +Last-Update: 2018-04-03 + +diff --git a/core/pom.xml b/core/pom.xml +index 2a81de58..dbdc7c91 100644 +--- a/core/pom.xml ++++ b/core/pom.xml +@@ -118,6 +118,9 @@ + ${project.artifactId}$(if;$(classes;NAMED;*.MethodAspect);; (no_aop)) + !net.sf.cglib.*,!org.objectweb.asm.*,!com.google.inject.*,* + true ++ ++ ++ !Bundle-Name,!Import-Package + + + +diff --git a/pom.xml b/pom.xml +index ebb0d028..36323e08 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -348,14 +348,15 @@ See the Apache License Version 2.0 for the specific language governing permissio + JavaSE-1.6 + !com.google.inject.*,* + <_exportcontents>!*.internal.*,$(module).*;version=${guice.api.version} +- <_versionpolicy>$(version;==;$(@)) ++ <_consumer-policy>$(version;==;$(@)) + <_nouses>true + <_removeheaders> + Embed-Dependency,Embed-Transitive, + Built-By,Tool,Created-By,Build-Jdk, + Originally-Created-By,Archiver-Version, + Include-Resource,Private-Package, +- Ignore-Package,Bnd-LastModified ++ Ignore-Package,Bnd-LastModified, ++ Merge-Headers + + + diff -Nru sisu-guice-3.2.6/PATCHES/GUICE_1174_exclude_ant_dep_from_cglib.patch sisu-guice-4.2.0/PATCHES/GUICE_1174_exclude_ant_dep_from_cglib.patch --- sisu-guice-3.2.6/PATCHES/GUICE_1174_exclude_ant_dep_from_cglib.patch 1970-01-01 00:00:00.000000000 +0000 +++ sisu-guice-4.2.0/PATCHES/GUICE_1174_exclude_ant_dep_from_cglib.patch 2018-04-03 18:18:08.000000000 +0000 @@ -0,0 +1,22 @@ +Description: Exclude transitive ant dependency from cglib because we don't need it +Author: Stuart McCulloch +Bug-Google: https://github.com/google/guice/issues/1174 +Last-Update: 2018-04-03 + +diff --git a/pom.xml b/pom.xml +index ebb0d028..3ee80c56 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -160,6 +160,12 @@ See the Apache License Version 2.0 for the specific language governing permissio + cglib + cglib + 3.2.6 ++ ++ ++ org.apache.ant ++ ant ++ ++ + + + junit diff -Nru sisu-guice-3.2.6/PATCHES/GUICE_492_slf4j_logger_injection.patch sisu-guice-4.2.0/PATCHES/GUICE_492_slf4j_logger_injection.patch --- sisu-guice-3.2.6/PATCHES/GUICE_492_slf4j_logger_injection.patch 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/PATCHES/GUICE_492_slf4j_logger_injection.patch 2018-04-03 18:18:08.000000000 +0000 @@ -1,7 +1,7 @@ Description: Provide built-in injection of SLF4J loggers Author: Stuart McCulloch Bug-Google: http://code.google.com/p/google-guice/issues/detail?id=492 -Last-Update: 2014-11-07 +Last-Update: 2016-09-18 diff --git a/common.xml b/common.xml index a23eb90..2d3d9b3 100644 @@ -60,10 +60,10 @@ index 6100879..56b13b3 100644 --- a/core/src/com/google/inject/internal/InjectorShell.java +++ b/core/src/com/google/inject/internal/InjectorShell.java -@@ -251,6 +251,15 @@ final class InjectorShell { - new ProviderInstanceBindingImpl(injector, key, - SourceProvider.UNKNOWN_SOURCE, loggerFactory, Scoping.UNSCOPED, - loggerFactory, ImmutableSet.of())); +@@ -272,6 +272,15 @@ final class InjectorShell { + Scoping.UNSCOPED, + loggerFactory, + ImmutableSet.of())); + + try { + Key slf4jKey = Key.get(org.slf4j.Logger.class); @@ -76,10 +76,10 @@ } private static class LoggerFactory implements InternalFactory, Provider { -@@ -270,6 +279,44 @@ final class InjectorShell { +@@ -295,6 +295,44 @@ final class InjectorShell { } } - + + private static class SLF4JLoggerFactory implements InternalFactory, Provider { + private final Injector injector; + @@ -101,7 +101,7 @@ + return loggerFactory; + } + -+ public org.slf4j.Logger get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { ++ public org.slf4j.Logger get(InternalContext context, Dependency dependency, boolean linked) { + InjectionPoint injectionPoint = dependency.getInjectionPoint(); + if (injectionPoint != null) { + return loggerFactory().getLogger(injectionPoint.getMember().getDeclaringClass().getName()); @@ -120,7 +120,7 @@ + private static void bindStage(InjectorImpl injector, Stage stage) { Key key = Key.get(Stage.class); - InstanceBindingImpl stageBinding = new InstanceBindingImpl( + InstanceBindingImpl stageBinding = diff --git a/extensions/persist/pom.xml b/extensions/persist/pom.xml index a560f38..e909927 100644 --- a/extensions/persist/pom.xml @@ -142,7 +142,7 @@ index 37305d0..5834d49 100644 --- a/pom.xml +++ b/pom.xml -@@ -283,7 +283,7 @@ See the Apache License Version 2.0 for the specific language governing permissio +@@ -298,7 +298,7 @@ See the Apache License Version 2.0 for the specific language governing permissio maven-surefire-plugin diff -Nru sisu-guice-3.2.6/PATCHES/GUICE_618_extensible_filter_pipeline.patch sisu-guice-4.2.0/PATCHES/GUICE_618_extensible_filter_pipeline.patch --- sisu-guice-3.2.6/PATCHES/GUICE_618_extensible_filter_pipeline.patch 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/PATCHES/GUICE_618_extensible_filter_pipeline.patch 2018-04-03 18:18:08.000000000 +0000 @@ -1,15 +1,15 @@ Description: Let sub-classes of GuiceFilter customize the servlet filter pipeline Author: Stuart McCulloch Bug-Google: http://code.google.com/p/google-guice/issues/detail?id=618 -Last-Update: 2015-01-20 +Last-Update: 2016-09-18 diff --git a/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java new file mode 100644 -index 0000000..ab8f746 +index 0000000..196e428 --- /dev/null +++ b/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java -@@ -0,0 +1,150 @@ -+/** +@@ -0,0 +1,151 @@ ++/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,10 +29,8 @@ +import com.google.common.collect.Sets; +import com.google.inject.Injector; +import com.google.inject.Provider; -+ +import java.io.IOException; +import java.util.Set; -+ +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.RequestDispatcher; @@ -60,7 +58,9 @@ + //Guards a DCL, so needs to be volatile + private volatile boolean initialized = false; + -+ protected AbstractFilterPipeline(Injector injector, AbstractServletPipeline servletPipeline, ++ protected AbstractFilterPipeline( ++ Injector injector, ++ AbstractServletPipeline servletPipeline, + Provider servletContext) { + this.injector = injector; + this.servletPipeline = servletPipeline; @@ -77,12 +77,11 @@ + */ + protected abstract FilterDefinition[] filterDefinitions(); + -+ public synchronized void initPipeline(ServletContext servletContext) -+ throws ServletException { ++ @Override ++ public synchronized void initPipeline(ServletContext servletContext) throws ServletException { + + //double-checked lock, prevents duplicate initialization -+ if (initialized) -+ return; ++ if (initialized) return; + + // Used to prevent duplicate initialization. + Set initializedSoFar = Sets.newIdentityHashSet(); @@ -98,8 +97,10 @@ + initialized = true; + } + -+ public void dispatch(ServletRequest request, ServletResponse response, -+ FilterChain proceedingFilterChain) throws IOException, ServletException { ++ @Override ++ public void dispatch( ++ ServletRequest request, ServletResponse response, FilterChain proceedingFilterChain) ++ throws IOException, ServletException { + + //lazy init of filter pipeline (OK by the servlet specification). This is needed + //in order for us not to force users to create a GuiceServletContextListener subclass. @@ -110,23 +111,22 @@ + //obtain the servlet pipeline to dispatch against + new FilterChainInvocation(filterDefinitions(), servletPipeline, proceedingFilterChain) + .doFilter(withDispatcher(request, servletPipeline), response); -+ + } + + /** + * Used to create an proxy that dispatches either to the guice-servlet pipeline or the regular + * pipeline based on uri-path match. This proxy also provides minimal forwarding support. + * -+ * We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline ++ *

    We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline + * is not called again). However, we can wrap requests with our own dispatcher to forward the + * *other* way. web.xml Servlets/JSPs can forward to themselves as per normal. + * -+ * This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, ++ *

    This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, + * incrementally, but not the other way around (which, we should actively discourage). + */ -+ @SuppressWarnings({ "JavaDoc", "deprecation" }) -+ private ServletRequest withDispatcher(ServletRequest servletRequest, -+ final AbstractServletPipeline servletPipeline) { ++ @SuppressWarnings({"JavaDoc", "deprecation"}) ++ private ServletRequest withDispatcher( ++ ServletRequest servletRequest, final AbstractServletPipeline servletPipeline) { + + // don't wrap the request if there are no servlets mapped. This prevents us from inserting our + // wrapper unless it's actually going to be used. This is necessary for compatibility for apps @@ -148,6 +148,7 @@ + }; + } + ++ @Override + public void destroyPipeline() { + //destroy servlets first + servletPipeline.destroy(); @@ -161,11 +162,11 @@ +} diff --git a/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java b/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java new file mode 100644 -index 0000000..811820a +index 0000000..5dd3640 --- /dev/null +++ b/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java -@@ -0,0 +1,187 @@ -+/** +@@ -0,0 +1,192 @@ ++/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); @@ -185,10 +186,8 @@ +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import com.google.inject.Injector; -+ +import java.io.IOException; +import java.util.Set; -+ +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; @@ -246,8 +245,8 @@ + } + + /** -+ * @return Returns a request dispatcher wrapped with a servlet mapped to -+ * the given path or null if no mapping was found. ++ * @return Returns a request dispatcher wrapped with a servlet mapped to the given path or null if ++ * no mapping was found. + */ + RequestDispatcher getRequestDispatcher(String path) { + final String newRequestUri = path; @@ -258,18 +257,20 @@ + for (final ServletDefinition servletDefinition : servletDefinitions()) { + if (servletDefinition.shouldServe(path)) { + return new RequestDispatcher() { ++ @Override + public void forward(ServletRequest servletRequest, ServletResponse servletResponse) + throws ServletException, IOException { -+ Preconditions.checkState(!servletResponse.isCommitted(), ++ Preconditions.checkState( ++ !servletResponse.isCommitted(), + "Response has been committed--you can only call forward before" -+ + " committing the response (hint: don't flush buffers)"); ++ + " committing the response (hint: don't flush buffers)"); + + // clear buffer before forwarding + servletResponse.resetBuffer(); + + ServletRequest requestToProcess; + if (servletRequest instanceof HttpServletRequest) { -+ requestToProcess = wrapRequest((HttpServletRequest)servletRequest, newRequestUri); ++ requestToProcess = wrapRequest((HttpServletRequest) servletRequest, newRequestUri); + } else { + // This should never happen, but instead of throwing an exception + // we will allow a happy case pass thru for maximum tolerance to @@ -281,14 +282,18 @@ + doServiceImpl(servletDefinition, requestToProcess, servletResponse); + } + ++ @Override + public void include(ServletRequest servletRequest, ServletResponse servletResponse) + throws ServletException, IOException { + // route to the target servlet + doServiceImpl(servletDefinition, servletRequest, servletResponse); + } + -+ private void doServiceImpl(ServletDefinition servletDefinition, ServletRequest servletRequest, -+ ServletResponse servletResponse) throws ServletException, IOException { ++ private void doServiceImpl( ++ ServletDefinition servletDefinition, ++ ServletRequest servletRequest, ++ ServletResponse servletResponse) ++ throws ServletException, IOException { + servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE); + + try { @@ -312,15 +317,16 @@ + + /** + * A Marker constant attribute that when present in the request indicates to Guice servlet that -+ * this request has been generated by a request dispatcher rather than the servlet pipeline. -+ * In accordance with section 8.4.2 of the Servlet 2.4 specification. ++ * this request has been generated by a request dispatcher rather than the servlet pipeline. In ++ * accordance with section 8.4.2 of the Servlet 2.4 specification. + */ + static final String REQUEST_DISPATCHER_REQUEST = "javax.servlet.forward.servlet_path"; + + private static class RequestDispatcherRequestWrapper extends HttpServletRequestWrapper { + private final String newRequestUri; + -+ RequestDispatcherRequestWrapper(HttpServletRequest servletRequest, String newRequestUri) { ++ RequestDispatcherRequestWrapper( ++ HttpServletRequest servletRequest, String newRequestUri) { + super(servletRequest); + this.newRequestUri = newRequestUri; + } @@ -340,9 +346,9 @@ + url.append("://"); + url.append(getServerName()); + // port might be -1 in some cases (see java.net.URL.getPort) -+ if (port > 0 && -+ (("http".equals(scheme) && (port != 80)) || -+ ("https".equals(scheme) && (port != 443)))) { ++ if (port > 0 ++ && (("http".equals(scheme) && (port != 80)) ++ || ("https".equals(scheme) && (port != 443)))) { + url.append(':'); + url.append(port); + } @@ -356,8 +362,8 @@ index b4112cf..bfe5a83 100644 --- a/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java +++ b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java -@@ -50,7 +50,7 @@ class FilterChainInvocation implements FilterChain { - +@@ -48,7 +48,7 @@ class FilterChainInvocation implements FilterChain { + private final FilterDefinition[] filterDefinitions; private final FilterChain proceedingChain; - private final ManagedServletPipeline servletPipeline; @@ -365,20 +371,20 @@ //state variable tracks current link in filterchain private int index = -1; -@@ -58,7 +58,7 @@ class FilterChainInvocation implements FilterChain { - private boolean cleanedStacks = false; +@@ -57,7 +57,7 @@ class FilterChainInvocation implements FilterChain { - public FilterChainInvocation(FilterDefinition[] filterDefinitions, -- ManagedServletPipeline servletPipeline, FilterChain proceedingChain) { -+ AbstractServletPipeline servletPipeline, FilterChain proceedingChain) { + public FilterChainInvocation( + FilterDefinition[] filterDefinitions, +- ManagedServletPipeline servletPipeline, ++ AbstractServletPipeline servletPipeline, + FilterChain proceedingChain) { this.filterDefinitions = filterDefinitions; - this.servletPipeline = servletPipeline; diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java index ff1e5b6..76ece31 100644 --- a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java +++ b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java -@@ -37,11 +37,11 @@ import javax.servlet.ServletException; +@@ -35,11 +35,11 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; /** @@ -389,19 +395,19 @@ */ -class FilterDefinition implements ProviderWithExtensionVisitor { +public class FilterDefinition implements ProviderWithExtensionVisitor { - private final String pattern; private final Key filterKey; private final UriPatternMatcher patternMatcher; -@@ -90,7 +90,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor + private final Map initParams; +@@ -85,7 +85,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor return uri != null && patternMatcher.matches(uri); } -- public void init(final ServletContext servletContext, Injector injector, -+ void init(final ServletContext servletContext, Injector injector, - Set initializedSoFar) throws ServletException { +- public void init( ++ void init( + final ServletContext servletContext, Injector injector, Set initializedSoFar) + throws ServletException { - // This absolutely must be a singleton, and so is only initialized once. -@@ -130,7 +130,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor +@@ -133,7 +133,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor initializedSoFar.add(filter); } @@ -410,7 +416,7 @@ // filters are always singletons Filter reference = filter.get(); -@@ -150,7 +150,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor +@@ -153,7 +153,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor } } @@ -423,16 +429,16 @@ index 985064b..c745d20 100644 --- a/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java +++ b/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java -@@ -26,7 +26,7 @@ import javax.servlet.ServletRequest; +@@ -24,7 +24,7 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** -- * An internal dispatcher for guice-servlet registered servlets and filters. -+ * A dispatcher abstraction for guice-servlet registered servlets and filters. - * By default, we assume a Guice 1.0 style servlet module is in play. In other - * words, we dispatch directly to the web.xml pipeline after setting up scopes. +- * An internal dispatcher for guice-servlet registered servlets and filters. By default, we assume a ++ * A dispatcher abstraction for guice-servlet registered servlets and filters. By default, we assume a + * Guice 1.0 style servlet module is in play. In other words, we dispatch directly to the web.xml + * pipeline after setting up scopes. * -@@ -39,10 +39,27 @@ import javax.servlet.ServletResponse; +@@ -35,11 +35,27 @@ import javax.servlet.ServletResponse; * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @ImplementedBy(DefaultFilterPipeline.class) @@ -445,7 +451,7 @@ + * @param context of the web application + */ void initPipeline(ServletContext context) throws ServletException; -+ + + /** + * Destroys the pipeline, taking it out of service. + */ @@ -458,27 +464,27 @@ + * @param response to populate + * @param defaultFilterChain for last resort filtering + */ - void dispatch(ServletRequest request, ServletResponse response, - FilterChain defaultFilterChain) throws IOException, ServletException; + void dispatch(ServletRequest request, ServletResponse response, FilterChain defaultFilterChain) + throws IOException, ServletException; } diff --git a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java index ba7a5af..0737b38 100644 --- a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java +++ b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java -@@ -89,7 +89,7 @@ public class GuiceFilter implements Filter { - this(null); +@@ -88,7 +88,7 @@ public class GuiceFilter implements Filter { } -- @Inject GuiceFilter(FilterPipeline filterPipeline) { -+ @Inject protected GuiceFilter(FilterPipeline filterPipeline) { + @Inject +- GuiceFilter(FilterPipeline filterPipeline) { ++ protected GuiceFilter(FilterPipeline filterPipeline) { injectedPipeline = filterPipeline; } diff --git a/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java -index 538e10a..76bc269 100644 +index 2317aca..76bc269 100644 --- a/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java +++ b/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java -@@ -16,7 +16,6 @@ +@@ -16,43 +16,25 @@ package com.google.inject.servlet; import com.google.common.collect.Lists; @@ -486,14 +492,12 @@ import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.Injector; -@@ -24,50 +23,41 @@ import com.google.inject.Provider; + import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; - -import java.io.IOException; import java.util.List; -import java.util.Set; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.RequestDispatcher; @@ -513,7 +517,7 @@ * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Singleton --class ManagedFilterPipeline implements FilterPipeline{ +-class ManagedFilterPipeline implements FilterPipeline { +class ManagedFilterPipeline extends AbstractFilterPipeline { private final FilterDefinition[] filterDefinitions; - private final ManagedServletPipeline servletPipeline; @@ -527,8 +531,9 @@ private static final TypeLiteral FILTER_DEFS = TypeLiteral.get(FilterDefinition.class); - @Inject - public ManagedFilterPipeline(Injector injector, ManagedServletPipeline servletPipeline, +@@ -61,13 +43,21 @@ class ManagedFilterPipeline implements FilterPipeline { + Injector injector, + ManagedServletPipeline servletPipeline, Provider servletContext) { - this.injector = injector; - this.servletPipeline = servletPipeline; @@ -551,17 +556,16 @@ /** * Introspects the injector and collects all instances of bound {@code List} * into a master list. -@@ -84,86 +74,4 @@ class ManagedFilterPipeline implements FilterPipeline{ +@@ -84,87 +84,4 @@ class ManagedFilterPipeline implements FilterPipeline{ // Copy to a fixed-size array for speed of iteration. return filterDefinitions.toArray(new FilterDefinition[filterDefinitions.size()]); } - -- public synchronized void initPipeline(ServletContext servletContext) -- throws ServletException { +- @Override +- public synchronized void initPipeline(ServletContext servletContext) throws ServletException { - - //double-checked lock, prevents duplicate initialization -- if (initialized) -- return; +- if (initialized) return; - - // Used to prevent duplicate initialization. - Set initializedSoFar = Sets.newIdentityHashSet(); @@ -577,8 +581,10 @@ - initialized = true; - } - -- public void dispatch(ServletRequest request, ServletResponse response, -- FilterChain proceedingFilterChain) throws IOException, ServletException { +- @Override +- public void dispatch( +- ServletRequest request, ServletResponse response, FilterChain proceedingFilterChain) +- throws IOException, ServletException { - - //lazy init of filter pipeline (OK by the servlet specification). This is needed - //in order for us not to force users to create a GuiceServletContextListener subclass. @@ -589,23 +595,22 @@ - //obtain the servlet pipeline to dispatch against - new FilterChainInvocation(filterDefinitions, servletPipeline, proceedingFilterChain) - .doFilter(withDispatcher(request, servletPipeline), response); -- - } - - /** - * Used to create an proxy that dispatches either to the guice-servlet pipeline or the regular - * pipeline based on uri-path match. This proxy also provides minimal forwarding support. - * -- * We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline +- *

    We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline - * is not called again). However, we can wrap requests with our own dispatcher to forward the - * *other* way. web.xml Servlets/JSPs can forward to themselves as per normal. - * -- * This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, +- *

    This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, - * incrementally, but not the other way around (which, we should actively discourage). - */ -- @SuppressWarnings({ "JavaDoc", "deprecation" }) -- private ServletRequest withDispatcher(ServletRequest servletRequest, -- final ManagedServletPipeline servletPipeline) { +- @SuppressWarnings({"JavaDoc", "deprecation"}) +- private ServletRequest withDispatcher( +- ServletRequest servletRequest, final ManagedServletPipeline servletPipeline) { - - // don't wrap the request if there are no servlets mapped. This prevents us from inserting our - // wrapper unless it's actually going to be used. This is necessary for compatibility for apps @@ -627,6 +632,7 @@ - }; - } - +- @Override - public void destroyPipeline() { - //destroy servlets first - servletPipeline.destroy(); @@ -639,10 +645,10 @@ - } } diff --git a/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java b/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java -index 455551a..ab58a8e 100644 +index ae164c6..ab58a8e 100644 --- a/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java +++ b/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java -@@ -15,27 +15,14 @@ +@@ -15,25 +15,13 @@ */ package com.google.inject.servlet; @@ -654,11 +660,9 @@ import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; - -import java.io.IOException; import java.util.List; -import java.util.Set; -- -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; @@ -670,7 +674,7 @@ /** * A wrapping dispatcher for servlets, in much the same way as {@link ManagedFilterPipeline} is for -@@ -44,7 +31,7 @@ import javax.servlet.http.HttpServletRequestWrapper; +@@ -42,7 +29,7 @@ import javax.servlet.http.HttpServletRequestWrapper; * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Singleton @@ -679,7 +683,7 @@ private final ServletDefinition[] servletDefinitions; private static final TypeLiteral SERVLET_DEFS = TypeLiteral.get(ServletDefinition.class); -@@ -54,10 +41,16 @@ class ManagedServletPipeline { +@@ -52,10 +39,16 @@ class ManagedServletPipeline { this.servletDefinitions = collectServletDefinitions(injector); } @@ -697,7 +701,7 @@ /** * Introspects the injector and collects all instances of bound {@code List} * into a master list. -@@ -74,140 +67,4 @@ class ManagedServletPipeline { +@@ -72,147 +72,4 @@ class ManagedServletPipeline { // Copy to a fixed size array for speed. return servletDefinitions.toArray(new ServletDefinition[servletDefinitions.size()]); } @@ -732,8 +736,8 @@ - } - - /** -- * @return Returns a request dispatcher wrapped with a servlet mapped to -- * the given path or null if no mapping was found. +- * @return Returns a request dispatcher wrapped with a servlet mapped to the given path or null if +- * no mapping was found. - */ - RequestDispatcher getRequestDispatcher(String path) { - final String newRequestUri = path; @@ -744,18 +748,20 @@ - for (final ServletDefinition servletDefinition : servletDefinitions) { - if (servletDefinition.shouldServe(path)) { - return new RequestDispatcher() { +- @Override - public void forward(ServletRequest servletRequest, ServletResponse servletResponse) - throws ServletException, IOException { -- Preconditions.checkState(!servletResponse.isCommitted(), +- Preconditions.checkState( +- !servletResponse.isCommitted(), - "Response has been committed--you can only call forward before" -- + " committing the response (hint: don't flush buffers)"); +- + " committing the response (hint: don't flush buffers)"); - - // clear buffer before forwarding - servletResponse.resetBuffer(); - - ServletRequest requestToProcess; - if (servletRequest instanceof HttpServletRequest) { -- requestToProcess = wrapRequest((HttpServletRequest)servletRequest, newRequestUri); +- requestToProcess = wrapRequest((HttpServletRequest) servletRequest, newRequestUri); - } else { - // This should never happen, but instead of throwing an exception - // we will allow a happy case pass thru for maximum tolerance to @@ -767,14 +773,18 @@ - doServiceImpl(servletDefinition, requestToProcess, servletResponse); - } - +- @Override - public void include(ServletRequest servletRequest, ServletResponse servletResponse) - throws ServletException, IOException { - // route to the target servlet - doServiceImpl(servletDefinition, servletRequest, servletResponse); - } - -- private void doServiceImpl(ServletDefinition servletDefinition, ServletRequest servletRequest, -- ServletResponse servletResponse) throws ServletException, IOException { +- private void doServiceImpl( +- ServletDefinition servletDefinition, +- ServletRequest servletRequest, +- ServletResponse servletResponse) +- throws ServletException, IOException { - servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE); - - try { @@ -798,15 +808,16 @@ - - /** - * A Marker constant attribute that when present in the request indicates to Guice servlet that -- * this request has been generated by a request dispatcher rather than the servlet pipeline. -- * In accordance with section 8.4.2 of the Servlet 2.4 specification. +- * this request has been generated by a request dispatcher rather than the servlet pipeline. In +- * accordance with section 8.4.2 of the Servlet 2.4 specification. - */ - public static final String REQUEST_DISPATCHER_REQUEST = "javax.servlet.forward.servlet_path"; - - private static class RequestDispatcherRequestWrapper extends HttpServletRequestWrapper { - private final String newRequestUri; - -- public RequestDispatcherRequestWrapper(HttpServletRequest servletRequest, String newRequestUri) { +- public RequestDispatcherRequestWrapper( +- HttpServletRequest servletRequest, String newRequestUri) { - super(servletRequest); - this.newRequestUri = newRequestUri; - } @@ -826,9 +837,9 @@ - url.append("://"); - url.append(getServerName()); - // port might be -1 in some cases (see java.net.URL.getPort) -- if (port > 0 && -- (("http".equals(scheme) && (port != 80)) || -- ("https".equals(scheme) && (port != 443)))) { +- if (port > 0 +- && (("http".equals(scheme) && (port != 80)) +- || ("https".equals(scheme) && (port != 443)))) { - url.append(':'); - url.append(port); - } @@ -842,7 +853,7 @@ index 11328ed..285ff31 100644 --- a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java +++ b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java -@@ -46,12 +46,11 @@ import javax.servlet.http.HttpServletRequestWrapper; +@@ -44,12 +44,11 @@ import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; /** @@ -854,19 +865,19 @@ */ -class ServletDefinition implements ProviderWithExtensionVisitor { +public class ServletDefinition implements ProviderWithExtensionVisitor { - private final String pattern; private final Key servletKey; private final UriPatternMatcher patternMatcher; -@@ -100,7 +99,7 @@ class ServletDefinition implements ProviderWithExtensionVisitor initParams; +@@ -95,7 +94,7 @@ class ServletDefinition implements ProviderWithExtensionVisitor initializedSoFar) throws ServletException { +- public void init( ++ void init( + final ServletContext servletContext, Injector injector, Set initializedSoFar) + throws ServletException { - // This absolutely must be a singleton, and so is only initialized once. -@@ -140,7 +139,7 @@ class ServletDefinition implements ProviderWithExtensionVisitor { + private static final Logger logger = Logger.getLogger(FilterDefinition.class.getName()); + - private final String pattern; private final Key filterKey; private final UriPatternMatcher patternMatcher; -@@ -154,7 +159,11 @@ public class FilterDefinition implements ProviderWithExtensionVisitor initParams; +@@ -157,7 +162,11 @@ public class FilterDefinition implements ProviderWithExtensionVisitor { + private static final Logger logger = Logger.getLogger(ServletDefinition.class.getName()); + - private final String pattern; private final Key servletKey; private final UriPatternMatcher patternMatcher; -@@ -283,7 +288,14 @@ public class ServletDefinition implements ProviderWithExtensionVisitor initParams; +@@ -286,7 +291,14 @@ public class ServletDefinition implements ProviderWithExtensionVisitor -Last-Update: 2015-04-23 +Last-Update: 2018-04-03 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1405580..c6eb646 100644 @@ -63,7 +63,7 @@ - 1. Finally, push the commits to your fork and submit a [pull request][]. - -[forking]: https://help.github.com/articles/fork-a-repo --[java style guide]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html +-[java style guide]: https://google.github.io/styleguide/javaguide.html -[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html -[pull request]: https://help.github.com/articles/creating-a-pull-request +This is a patched build of https://github.com/google/guice/ which includes selected contributions that have not yet been merged into the upstream build. @@ -79,14 +79,14 @@ -==== +Patched build of https://github.com/google/guice/ - see PATCHES for the exact differences. --**Now, out in [4.0 Beta5](https://github.com/google/guice/wiki/Guice40)!** +-**Latest release: [4.1](https://github.com/google/guice/wiki/Guice41)** +Compatibility with Google-Guice +------------------------------- --**Documentation:** [User Guide](https://github.com/google/guice/wiki/Motivation), [3.0 javadocs](http://google.github.io/guice/api-docs/3.0/javadoc/packages.html), [Latest javadocs](http://google.github.io/guice/api-docs/latest/javadoc/index.html)
    +-**Documentation:** [User Guide](https://github.com/google/guice/wiki/Motivation), [4.1 javadocs](http://google.github.io/guice/api-docs/4.1/javadoc/index.html), [Latest javadocs](http://google.github.io/guice/api-docs/latest/javadoc/index.html)
    -**Continuous Integration:** [![Build Status](https://api.travis-ci.org/google/guice.png?branch=master)](https://travis-ci.org/google/guice)
    --**Mailing Lists:** [User Mailing List](http://groups.google.com/group/google-guice), [Developer Mailing List](http://groups.google.com/group/google-guice-dev)
    +-**Mailing Lists:** [User Mailing List](http://groups.google.com/group/google-guice)
    -**License:** [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) +The main difference between Sisu-Guice and Google-Guice is that Guava is now exposed as a direct Maven dependency. If you are assembling your application outside of Maven you therefore need to add Guava to the runtime JARs. The build uses Guava 16.0.1 but you can use Maven's `` to select a different version of Guava. @@ -116,9 +116,9 @@ - com.google.inject + org.sonatype.sisu.inject guice-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT -@@ -13,84 +13,84 @@ +@@ -13,79 +13,79 @@ guice-bom @@ -183,12 +183,6 @@ - com.google.inject.extensions + org.sonatype.sisu.inject - guice-multibindings - ${project.version} - - -- com.google.inject.extensions -+ org.sonatype.sisu.inject guice-persist ${project.version} @@ -222,7 +216,7 @@ guice-throwingproviders ${project.version} -@@ -98,12 +98,12 @@ +@@ -93,12 +93,12 @@ | not yet promoted... - - @@ -248,7 +242,7 @@ - com.google.inject + org.sonatype.sisu.inject guice-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT - guice @@ -260,7 +254,7 @@ -@@ -39,11 +40,13 @@ +@@ -33,11 +34,13 @@ org.ow2.asm asm true @@ -274,7 +268,7 @@ @@ -500,7 +489,7 @@ ${project.version} tests test -@@ -105,22 +105,10 @@ +@@ -103,22 +103,10 @@ maven-bundle-plugin @@ -535,7 +524,8 @@ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT +- 4.0-SNAPSHOT ++ 4.1.1-SNAPSHOT guice-service @@ -555,7 +545,7 @@ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT guice-servlet @@ -576,7 +566,7 @@ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT guice-spring @@ -597,7 +587,7 @@ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT guice-struts2 @@ -623,7 +613,7 @@ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT guice-testlib @@ -633,6 +623,31 @@ +@@ -28,7 +28,7 @@ + + + +- com.google.inject.extensions ++ org.sonatype.sisu.inject + guice-throwingproviders + ${project.version} + +@@ -45,9 +45,15 @@ + + com.google.truth + truth ++ 0.36 + compile + + ++ com.google.guava ++ guava ++ 20.0 ++ ++ + com.google.code.findbugs + jsr305 + diff --git a/extensions/throwingproviders/pom.xml b/extensions/throwingproviders/pom.xml index 63a8b78..bb24528 100644 --- a/extensions/throwingproviders/pom.xml @@ -644,7 +659,7 @@ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT guice-throwingproviders @@ -658,14 +673,14 @@ index 763587e..9e88e9a 100644 --- a/jdk8-tests/pom.xml +++ b/jdk8-tests/pom.xml -@@ -17,20 +17,20 @@ See the Apache License Version 2.0 for the specific language governing permissio +@@ -17,25 +17,25 @@ See the Apache License Version 2.0 for the specific language governing permissio xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + org.sonatype.sisu.inject guice-parent - com.google.inject - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT 4.0.0 @@ -683,6 +698,12 @@ ${project.version} test + +- com.google.inject.extensions ++ org.sonatype.sisu.inject + guice-assistedinject + ${project.version} + test diff --git a/pom.xml b/pom.xml index 6931067..b316a9c 100644 --- a/pom.xml @@ -694,9 +715,9 @@ - com.google - google - 5 -+ org.sonatype.forge -+ forge-parent -+ 38 ++ org.sonatype.buildsupport ++ public-parent ++ 12 pom @@ -704,7 +725,7 @@ - com.google.inject + org.sonatype.sisu.inject guice-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT - Google Guice + Sisu Guice @@ -755,7 +776,31 @@ -@@ -329,7 +316,7 @@ See the Apache License Version 2.0 for the specific language governing permissio +@@ -132,12 +132,12 @@ See the Apache License Version 2.0 for the specific language governing permissio + + com.google.guava + guava +- 23.6-android ++ 18.0 + + + com.google.guava + guava-testlib +- 23.6-android ++ 18.0 + + + org.ow2.asm +@@ -158,7 +158,7 @@ See the Apache License Version 2.0 for the specific language governing permissio + + com.google.truth + truth +- 0.36 ++ 0.30 + test + + +@@ -344,7 +331,7 @@ See the Apache License Version 2.0 for the specific language governing permissio Copyright (C) 2006 Google Inc. https://github.com/google/guice ${project.artifactId} @@ -764,18 +809,18 @@ JavaSE-1.6 !com.google.inject.*,* <_exportcontents>!*.internal.*,$(module).*;version=${guice.api.version} -@@ -343,6 +330,10 @@ See the Apache License Version 2.0 for the specific language governing permissio - Ignore-Package,Bnd-LastModified - - -+ -+ guava +@@ -372,6 +372,10 @@ See the Apache License Version 2.0 for the specific language governing permissio + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + false ++ ++ false ++ false ++ + - -@@ -390,45 +381,24 @@ See the Apache License Version 2.0 for the specific language governing permissio +@@ -405,45 +396,24 @@ See the Apache License Version 2.0 for the specific language governing permissio maven-source-plugin 2.1.2 @@ -827,7 +872,7 @@ -@@ -454,6 +424,7 @@ See the Apache License Version 2.0 for the specific language governing permissio +@@ -469,6 +439,7 @@ See the Apache License Version 2.0 for the specific language governing permissio @@ -835,7 +880,7 @@ org.apache.maven.plugins -@@ -463,6 +434,7 @@ See the Apache License Version 2.0 for the specific language governing permissio +@@ -478,6 +449,7 @@ See the Apache License Version 2.0 for the specific language governing permissio @@ -844,36 +889,21 @@ diff --git a/extensions/dagger-adapter/pom.xml b/extensions/dagger-adapter/pom.xml -index 10af044..8566a98 100644 +index d64d36c..0ad5261 100644 --- a/extensions/dagger-adapter/pom.xml +++ b/extensions/dagger-adapter/pom.xml -@@ -2,16 +2,20 @@ - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +@@ -3,12 +3,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 -+ - com.google.inject.extensions + org.sonatype.sisu.inject extensions-parent - 4.0-SNAPSHOT + 4.1.1-SNAPSHOT -+ guice-dagger-adapter - Google Guice - Extensions - Dagger Adapter -+ + Sisu Guice - Extensions - Dagger Adapter -+ -- com.google.inject.extensions -+ org.sonatype.sisu.inject - guice-multibindings - ${project.version} - -@@ -21,4 +25,5 @@ - 2.0 - - -+ - + com.google.dagger diff -Nru sisu-guice-3.2.6/pom.xml sisu-guice-4.2.0/pom.xml --- sisu-guice-3.2.6/pom.xml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/pom.xml 2018-04-03 18:18:08.000000000 +0000 @@ -18,21 +18,21 @@ 4.0.0 - org.sonatype.forge - forge-parent - 38 + org.sonatype.buildsupport + public-parent + 12 pom org.sonatype.sisu.inject guice-parent - 3.2.6 + 4.2.0 Sisu Guice - Patched build of Guice: a lightweight dependency injection framework for Java 6 and above + Patched build of Guice: a lightweight dependency injection framework for Java 7 and above https://github.com/google/guice @@ -64,11 +64,11 @@ scm:git:git@github.com:sonatype/sisu-guice.git scm:git:git@github.com:sonatype/sisu-guice.git http://github.com/sonatype/sisu-guice - sisu-guice-3.2.6 + sisu-guice-4.2.0 - Google Code + Github https://github.com/google/guice/issues/ @@ -132,22 +132,45 @@ com.google.guava guava - 16.0.1 + 18.0 com.google.guava guava-testlib - 16.0.1 + 18.0 org.ow2.asm asm - 5.0.3 + 6.0 cglib cglib - 3.1 + 3.2.6 + + + org.apache.ant + ant + + + + + junit + junit + 4.11 + test + + + com.google.truth + truth + 0.30 + test + + + com.google.code.findbugs + jsr305 + 3.0.1 @@ -156,8 +179,6 @@ junit junit - 4.11 - test @@ -238,30 +259,30 @@ maven-compiler-plugin 2.3.2 - 1.6 - 1.6 + 1.7 + 1.7 org.codehaus.mojo animal-sniffer-maven-plugin - 1.10 + 1.16 org.codehaus.mojo.signature - java16 + java17 1.0 - check-java-1.6-compat + check-java-1.7-compat process-classes check @@ -309,7 +330,7 @@ org.apache.felix maven-bundle-plugin - 2.1.0 + 3.5.0 com.google.inject @@ -318,23 +339,20 @@ https://github.com/google/guice ${project.artifactId} Sonatype, Inc. - JavaSE-1.6 + JavaSE-1.7 !com.google.inject.*,* <_exportcontents>!*.internal.*,$(module).*;version=${guice.api.version} - <_versionpolicy>$(version;==;$(@)) + <_consumer-policy>$(version;==;$(@)) <_nouses>true <_removeheaders> Embed-Dependency,Embed-Transitive, Built-By,Tool,Created-By,Build-Jdk, Originally-Created-By,Archiver-Version, Include-Resource,Private-Package, - Ignore-Package,Bnd-LastModified + Ignore-Package,Bnd-LastModified, + Merge-Headers - - guava @@ -356,6 +374,10 @@ ${project.build.outputDirectory}/META-INF/MANIFEST.MF false + + false + false + @@ -369,7 +391,7 @@ maven-javadoc-plugin - 2.7 + 3.0.0 package @@ -419,7 +441,9 @@ org.apache.maven.plugins maven-javadoc-plugin - -Xdoclint:none + + -Xdoclint:none + @@ -431,7 +455,9 @@ org.apache.maven.plugins maven-javadoc-plugin - -Xdoclint:none + + -Xdoclint:none + diff -Nru sisu-guice-3.2.6/.travis.yml sisu-guice-4.2.0/.travis.yml --- sisu-guice-3.2.6/.travis.yml 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/.travis.yml 2018-04-03 18:18:08.000000000 +0000 @@ -1,10 +1,14 @@ language: java +sudo: false + +cache: + directories: + - $HOME/.m2 jdk: + - oraclejdk9 - oraclejdk8 - - oraclejdk7 - openjdk7 - - openjdk6 env: global: @@ -14,7 +18,7 @@ matrix: - LABEL=ant CMD="ant dist test.dist" INSTALL="/bin/true" - LABEL=ant_no_aop CMD="ant -f build/no_aop/build.xml dist test.dist" INSTALL="ant no_aop" - - LABEL=mvn CMD="mvn -P!standard-with-extra-repos verify --fail-at-end -Dsource.skip=true -Dmaven.javadoc.skip=true" INSTALL="mvn -P!standard-with-extra-repos dependency:go-offline test clean --quiet --fail-never -DskipTests=true" + - LABEL=mvn CMD="mvn -B -P!standard-with-extra-repos verify --fail-at-end -Dsource.skip=true -Dmaven.javadoc.skip=true" INSTALL="mvn -P!standard-with-extra-repos dependency:go-offline test clean --quiet --fail-never -DskipTests=true" install: - ${INSTALL} @@ -22,11 +26,6 @@ script: - ${CMD} -notifications: - email: - recipients: - - google-guice-dev+ci@googlegroups.com - after_success: - util/generate-latest-docs.sh - util/compareBuilds.sh diff -Nru sisu-guice-3.2.6/util/generate-latest-docs.sh sisu-guice-4.2.0/util/generate-latest-docs.sh --- sisu-guice-3.2.6/util/generate-latest-docs.sh 2015-04-25 16:25:40.000000000 +0000 +++ sisu-guice-4.2.0/util/generate-latest-docs.sh 2018-04-03 18:18:08.000000000 +0000 @@ -23,7 +23,7 @@ cp -rf $HOME/api-diffs-latest api-docs/latest/api-diffs cp -rf $HOME/javadoc-latest api-docs/latest/javadoc git add -f . - git commit -m "Lastest javadoc & api-diffs on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" + git commit -m "Latest javadoc & api-diffs on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" git push -fq origin gh-pages > /dev/null echo -e "Published Javadoc & JDiff to gh-pages.\n"