master moved from 57aad211bb85 to f1abba38c7f5
5 new revisions:
Revision: a5b2b1fc374c
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:17:11 2014 UTC
Log: Suppress compiler errors reported by an error-prone checker ([])
for t...
http://code.google.com/p/google-guice/source/detail?r=a5b2b1fc374c
Revision: c7ae433fc9d5
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:17:37 2014 UTC
Log: Add BoundFieldModule to automatically bind @Bind annotated fields
to t...
http://code.google.com/p/google-guice/source/detail?r=c7ae433fc9d5
Revision: c35ebc2ce88f
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:18:01 2014 UTC
Log: Fix external issue 372 -- only scrub the pathInfo if the
servletPath a...
http://code.google.com/p/google-guice/source/detail?r=c35ebc2ce88f
Revision: 647b24f7f1b5
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:18:26 2014 UTC
Log: Fix external issue 755. Grapher config was wrong....
http://code.google.com/p/google-guice/source/detail?r=647b24f7f1b5
Revision: f1abba38c7f5
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:18:51 2014 UTC
Log: On second thought, according to the javadocs @
http://docs.oracle.com/...
http://code.google.com/p/google-guice/source/detail?r=f1abba38c7f5
==============================================================================
Revision: a5b2b1fc374c
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:17:11 2014 UTC
Log: Suppress compiler errors reported by an error-prone checker ([])
for tests.
I wrote an error-prone checker([]) to check that injected constructors are
not annotated with @Inject(optional=true) or with binding annotations. This
CL annotates the intentional tests for such cases with @SuppressWarnings.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=64575706
http://code.google.com/p/google-guice/source/detail?r=a5b2b1fc374c
Modified:
/core/test/com/google/inject/OptionalBindingTest.java
/core/test/com/google/inject/ProvisionExceptionTest.java
=======================================
--- /core/test/com/google/inject/OptionalBindingTest.java Fri Jul 8
00:34:16 2011 UTC
+++ /core/test/com/google/inject/OptionalBindingTest.java Thu Apr 10
23:17:11 2014 UTC
@@ -255,6 +255,9 @@
}
static class HasOptionalConstructor {
+ // Suppress compiler errors by the error-prone checker
InjectedConstructorAnnotations,
+ // which catches optional injected constructors.
+ @SuppressWarnings("InjectedConstructorAnnotations")
@Inject(optional=true)
HasOptionalConstructor() {}
}
=======================================
--- /core/test/com/google/inject/ProvisionExceptionTest.java Sat Oct 5
21:05:39 2013 UTC
+++ /core/test/com/google/inject/ProvisionExceptionTest.java Thu Apr 10
23:17:11 2014 UTC
@@ -295,6 +295,9 @@
}
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) {}
}
==============================================================================
Revision: c7ae433fc9d5
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:17:37 2014 UTC
Log: Add BoundFieldModule to automatically bind @Bind annotated fields
to their
values, reducing test boilerplate.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=64668801
http://code.google.com/p/google-guice/source/detail?r=c7ae433fc9d5
Added:
/extensions/testlib/build.properties
/extensions/testlib/build.xml
/extensions/testlib/pom.xml
/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java
/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java
/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java
/extensions/testlib/testlib.iml
Modified:
/build.properties
/build.xml
/extensions/pom.xml
=======================================
--- /dev/null
+++ /extensions/testlib/build.properties Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.testing.fieldbinder.FieldBindingModuleTest
+module=com.google.inject.testing
+fragment=true
=======================================
--- /dev/null
+++ /extensions/testlib/build.xml Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-testlib" basedir="." default="jar">
+
+ <import file="../../common.xml"/>
+
+ <path id="compile.classpath">
+ <fileset dir="${lib.dir}" includes="*.jar"/>
+ <fileset dir="${lib.dir}/build" includes="*.jar"/>
+ <pathelement path="../../build/classes"/>
+ </path>
+
+ <target name="jar" depends="compile, manifest" description="Build jar.">
+ <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+ manifest="${build.dir}/META-INF/MANIFEST.MF">
+ <fileset dir="${build.dir}/classes" />
+ </jar>
+ </target>
+
+</project>
=======================================
--- /dev/null
+++ /extensions/testlib/pom.xml Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>extensions-parent</artifactId>
+ <version>4.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>guice-testlib</artifactId>
+
+ <name>Google Guice - Extensions - TestLib</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/TestScope*</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
=======================================
--- /dev/null
+++ /extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java
Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,40 @@
+/*
+ * 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.testing.fieldbinder;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used by {@link BoundFieldModule} to indicate that a field
should be bound to its
+ * value using Guice.
+ *
+ * @see BoundFieldModule
+ * @author [email protected] (Russ Harmon)
+ */
+@Retention(RUNTIME)
+@Target({FIELD})
+public @interface Bind {
+ /**
+ * If specified, {@link BoundFieldModule} will bind the annotated
field's value to this type,
+ * rather than to the field's actual type.
+ */
+ Class<?> to() default Bind.class;
+}
=======================================
--- /dev/null
+++
/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java
Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,363 @@
+/*
+ * 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.testing.fieldbinder;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.inject.Binder;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.internal.Annotations;
+import com.google.inject.spi.Message;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Automatically creates Guice bindings for fields in an object annotated
with {@link Bind}.
+ *
+ * <p>This module is intended for use in tests to reduce the code needed
to bind local fields
+ * (usually mocks) for injection.
+ *
+ * <p>The following rules are followed in determining how fields are bound
using this module:
+ *
+ * <ul>
+ * <li>
+ * 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.
+ * </li>
+ * <li>
+ * 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.
+ * </li>
+ * <li>
+ * If a {@link BindingAnnotation} or {@link 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 Qualifier}.
+ * </li>
+ * <li>
+ * 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<Integer>} binds to {@link Integer}. Attempting to bind
a non-parameterized
+ * {@link Provider} without a {@link Bind#to} clause is an error.
+ * </li>
+ * </ul>
+ *
+ * <p>Example use:
+ * <pre><code>
+ * public class TestFoo {
+ * // bind(new TypeLiteral{@code <List<Object>>}()
{}).toInstance(listOfObjects);
+ * {@literal @}Bind private List{@code <Object>} listOfObjects =
Lists.of();
+ *
+ * // bind(SuperClass.class).toInstance(aSubClass);
+ * {@literal @}Bind(to = SuperClass.class) private SubClass aSubClass =
new SubClass();
+ *
+ * //
bind(Object.class).annotatedWith(MyBindingAnnotation.class).toInstance(object2);
+ * {@literal @}Bind
+ * {@literal @}MyBindingAnnotation
+ * private String myString = "hello";
+ *
+ * // bind(Object.class).toProvider(myProvider);
+ * {@literal @}Bind private Provider{@code <Object>} myProvider =
getProvider();
+ *
+ * {@literal @}Before public void setUp() {
+ * Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
+ * }
+ * }
+ * </code></pre>
+ *
+ * @see Bind
+ * @author [email protected] (Russ Harmon)
+ */
+public final class BoundFieldModule implements Module {
+ private final Object instance;
+
+ // Note that binder is not initialized until configure() is called.
+ private Binder binder;
+
+ private BoundFieldModule(Object instance) {
+ this.instance = instance;
+ }
+
+ /**
+ * Create a BoundFieldModule which binds the {@link Bind} annotated
fields of {@code instance}.
+ *
+ * @param instance the instance whose fields will be bound.
+ * @return a module which will bind the {@link Bind} annotated fields of
{@code instance}.
+ */
+ public static BoundFieldModule of(Object instance) {
+ return new BoundFieldModule(instance);
+ }
+
+ private static class BoundFieldException extends RuntimeException {
+ BoundFieldException(String message) {
+ super(message);
+ }
+ }
+
+ private class BoundFieldInfo {
+ /** The field itself. */
+ final Field field;
+
+ /**
+ * The actual type of the field.
+ *
+ * <p>For example, {@code @Bind(to = Object.class) Number one = new
Integer(1);} will be
+ * {@link Number}.
+ */
+ final TypeLiteral<?> type;
+
+ /** The {@link Bind} annotation which is present on the field. */
+ final Bind bindAnnotation;
+
+ /**
+ * The type this field will bind to.
+ *
+ * <p>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.
+ *
+ * <p>For example, {@code @Bind(to = Object.class) Number one = new
Integer(1);} will be
+ * {@link Number}, and {@code @Bind(to = Object.class)
Provider<Number> one = new Integer(1);}
+ * will be {@link Number}.
+ *
+ * @see getNaturalFieldType
+ */
+ final Optional<TypeLiteral<?>> naturalType;
+
+ BoundFieldInfo(
+ Field field,
+ Bind bindAnnotation,
+ TypeLiteral<?> fieldType) {
+ this.field = field;
+ this.type = fieldType;
+ this.bindAnnotation = bindAnnotation;
+
+ field.setAccessible(true);
+
+ this.naturalType = getNaturalFieldType();
+ this.boundType = getBoundType();
+ }
+
+ private TypeLiteral<?> getBoundType() {
+ Class<?> bindClass = bindAnnotation.to();
+ // Bind#to's default value is Bind.class which is used to represent
that no explicit binding
+ // type is requested.
+ if (bindClass == Bind.class) {
+ Preconditions.checkState(naturalType != null);
+ if (!this.naturalType.isPresent()) {
+ addErrorAndThrow(
+ field,
+ "Non parameterized Provider fields must have an explicit "
+ + "binding class via @Bind(to = Foo.class)");
+ }
+ return this.naturalType.get();
+ } else {
+ return TypeLiteral.get(bindClass);
+ }
+ }
+
+ /**
+ * Retrieves the type this field binds to naturally.
+ *
+ * <p>A field's "natural" type specifically ignores the to() method on
the @Bind annotation, is
+ * the parameterized type if the field's actual type is a
parameterized {@link Provider}, is
+ * {@link Optional#absent()} if this field is a non-parameterized
{@link Provider} and otherwise
+ * 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}.
+ */
+ private Optional<TypeLiteral<?>> getNaturalFieldType() {
+ if (isTransparentProvider(type.getRawType())) {
+ Type providerType = type.getType();
+ if (providerType instanceof Class) {
+ return Optional.absent();
+ }
+ Preconditions.checkState(providerType instanceof
ParameterizedType);
+ Type[] providerTypeArguments = ((ParameterizedType)
providerType).getActualTypeArguments();
+ Preconditions.checkState(providerTypeArguments.length == 1);
+ return
Optional.<TypeLiteral<?>>of(TypeLiteral.get(providerTypeArguments[0]));
+ } else {
+ return Optional.<TypeLiteral<?>>of(type);
+ }
+ }
+
+ Object getValue() {
+ try {
+ return field.get(instance);
+ } catch (IllegalAccessException e) {
+ // Since we called setAccessible(true) on this field in the
constructor, this is a
+ // programming error if it occurs.
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ private static boolean hasInject(Field field) {
+ return field.isAnnotationPresent(javax.inject.Inject.class)
+ || field.isAnnotationPresent(com.google.inject.Inject.class);
+ }
+
+ /**
+ * Retrieve a {@link BoundFieldInfo}.
+ *
+ * <p>This returns a {@link BoundFieldInfo} if the field has a {@link
Bind} annotation.
+ * Otherwise it returns {@link Optional#absent()}.
+ */
+ private Optional<BoundFieldInfo> getBoundFieldInfo(
+ TypeLiteral<?> containingClassType,
+ Field field) {
+ Bind bindAnnotation = field.getAnnotation(Bind.class);
+ if (bindAnnotation == null) {
+ return Optional.absent();
+ }
+ if (hasInject(field)) {
+ addErrorAndThrow(
+ field,
+ "Fields annotated with both @Bind and @Inject are illegal.");
+ }
+ return Optional.of(new BoundFieldInfo(
+ field,
+ bindAnnotation,
+ containingClassType.getFieldType(field)));
+ }
+
+ private LinkedBindingBuilder<?> verifyBindingAnnotations(
+ Field field,
+ AnnotatedBindingBuilder<?> annotatedBinder) {
+ LinkedBindingBuilder<?> binderRet = annotatedBinder;
+ for (Annotation annotation : field.getAnnotations()) {
+ Class<? extends Annotation> annotationType =
annotation.annotationType();
+ if (Annotations.isBindingAnnotation(annotationType)) {
+ // not returning here ensures that annotatedWith will be called
multiple times if this field
+ // has multiple BindingAnnotations, relying on the binder to throw
an error in this case.
+ binderRet = annotatedBinder.annotatedWith(annotation);
+ }
+ }
+ return binderRet;
+ }
+
+ /**
+ * Determines if {@code clazz} is a "transparent provider".
+ *
+ * <p>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}.
+ *
+ * <p>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
+ * transparent.
+ */
+ private static boolean isTransparentProvider(Class<?> clazz) {
+ return com.google.inject.Provider.class == clazz ||
javax.inject.Provider.class == clazz;
+ }
+
+ private void bindField(BoundFieldInfo fieldInfo) {
+ if (fieldInfo.naturalType.isPresent()) {
+ Class<?> naturalRawType = fieldInfo.naturalType.get().getRawType();
+ Class<?> boundRawType = fieldInfo.boundType.getRawType();
+ if (!boundRawType.isAssignableFrom(naturalRawType)) {
+ addErrorAndThrow(
+ fieldInfo.field,
+ "Requested binding type \"%s\" is not assignable from field
binding type \"%s\"",
+ boundRawType.getName(),
+ naturalRawType.getName());
+ }
+ }
+
+ AnnotatedBindingBuilder<?> annotatedBinder =
binder.bind(fieldInfo.boundType);
+ LinkedBindingBuilder<?> binder =
verifyBindingAnnotations(fieldInfo.field, annotatedBinder);
+
+ // It's unfortunate that Field.get() just returns Object rather than
the actual type (although
+ // that would be impossible) because as a result calling
binder.toInstance or binder.toProvider
+ // is impossible to do without an unchecked cast. This is safe if
fieldInfo.naturalType is
+ // present because compatibility is checked explicitly above, but is
_unsafe_ if
+ // fieldInfo.naturalType is absent which occurrs when a
non-parameterized Provider is used with
+ // @Bind(to = ...)
+ @SuppressWarnings("unchecked")
+ AnnotatedBindingBuilder<Object> binderUnsafe =
(AnnotatedBindingBuilder<Object>) binder;
+
+ Object fieldValue = fieldInfo.getValue();
+
+ if (fieldValue == null) {
+ addErrorAndThrow(
+ fieldInfo.field,
+ "Binding to null values is not allowed. "
+ + "Use Providers.of(null) if this is your intended behavior.",
+ fieldInfo.field.getName());
+ }
+
+ if (isTransparentProvider(fieldInfo.type.getRawType())) {
+ // This is safe because we checked that the field's type is Provider
above.
+ @SuppressWarnings("unchecked")
+ Provider<?> fieldValueUnsafe = (Provider<?>) fieldValue;
+
+ binderUnsafe.toProvider(fieldValueUnsafe);
+ } else {
+ binderUnsafe.toInstance(fieldValue);
+ }
+ }
+
+ private void addErrorAndThrow(Field field, String format, Object...
args) {
+ Preconditions.checkNotNull(binder);
+ String source = String.format(
+ "%s field %s",
+ field.getDeclaringClass().getName(),
+ field.getName());
+ Message messageObj = new Message(source, String.format(format, args));
+
+ binder.addError(messageObj);
+ throw new BoundFieldException(messageObj.getMessage());
+ }
+
+ @Override
+ public void configure(Binder binder) {
+ binder = binder.skipSources(BoundFieldModule.class);
+ this.binder = binder;
+
+ TypeLiteral<?> currentClassType = TypeLiteral.get(instance.getClass());
+ while (currentClassType.getRawType() != Object.class) {
+ for (Field field :
currentClassType.getRawType().getDeclaredFields()) {
+ try {
+ Optional<BoundFieldInfo> fieldInfoOpt =
+ getBoundFieldInfo(currentClassType, field);
+ if (fieldInfoOpt.isPresent()) {
+ bindField(fieldInfoOpt.get());
+ }
+ } catch (BoundFieldException e) {
+ // addErrorAndThrow already called addError, so do nothing
+ }
+ }
+ currentClassType = currentClassType.getSupertype(
+ currentClassType.getRawType().getSuperclass());
+ }
+ }
+}
=======================================
--- /dev/null
+++
/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java
Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,671 @@
+/*
+ * 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.testing.fieldbinder;
+
+import static com.google.inject.Asserts.assertContains;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+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.Provider;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.inject.Qualifier;
+
+/** Unit tests for {@link BoundFieldModule}. */
+public class BoundFieldModuleTest extends TestCase {
+ public void testBindingNothing() {
+ Object instance = new Object() {};
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Guice.createInjector(module);
+
+ // If we didn't throw an exception, we succeeded.
+ }
+
+ public void testBindingOnePrivate() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind private Integer anInt = testValue;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ public void testBindingOnePublic() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind public Integer anInt = testValue;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ private static class FieldBindableClass {
+ @Bind Integer anInt;
+
+ FieldBindableClass(Integer anInt) {
+ this.anInt = anInt;
+ }
+ }
+
+ private static class FieldBindableSubclass extends FieldBindableClass {
+ FieldBindableSubclass(Integer anInt) {
+ super(anInt);
+ }
+ }
+
+ public void testSuperTypeBinding() {
+ FieldBindableSubclass instance = new FieldBindableSubclass(1024);
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(instance.anInt, injector.getInstance(Integer.class));
+ }
+
+ 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;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ assertEquals(testString, injector.getInstance(String.class));
+ }
+
+ public void testBindingSuperType() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind(to = Number.class) private Integer anInt = testValue;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Number.class));
+ }
+
+ public void testBindingIncorrectTypeProviderFails() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind(to = String.class) private Provider<Integer> anIntProvider =
new Provider<Integer>() {
+ @Override public Integer get() {
+ return testValue;
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ 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\"");
+ }
+ }
+
+ @BindingAnnotation
+ @Retention(RUNTIME)
+ private static @interface SomeBindingAnnotation {}
+
+ public void testBindingWithBindingAnnotation() {
+ final Integer testValue1 = 1024, testValue2 = 2048;
+ Object instance = new Object() {
+ @Bind private Integer anInt = testValue1;
+
+ @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)));
+ }
+
+ @Qualifier
+ @Retention(RUNTIME)
+ private static @interface SomeQualifier {}
+
+ public void testBindingWithQualifier() {
+ final Integer testValue1 = 1024, testValue2 = 2048;
+ Object instance = new Object() {
+ @Bind private Integer anInt = testValue1;
+
+ @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)));
+ }
+
+ 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;
+ };
+
+ 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))));
+ }
+
+ 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;
+ };
+
+ 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))));
+ }
+
+ public void testBindingWithGenerics() {
+ final List<Integer> testIntList = Arrays.asList(new Integer[] {1, 2,
3});
+ final List<Boolean> testBoolList = Arrays.asList(new Boolean[] {true,
true, false});
+ Object instance = new Object() {
+ @Bind private List<Integer> anIntList = testIntList;
+ @Bind private List<Boolean> aBoolList = testBoolList;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testIntList, injector.getInstance(new
Key<List<Integer>>() {}));
+ assertEquals(testBoolList, injector.getInstance(new
Key<List<Boolean>>() {}));
+ }
+
+ public void testBoundValueDoesntChange() {
+ Integer testValue = 1024;
+ FieldBindableClass instance = new FieldBindableClass(testValue);
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ instance.anInt++;
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ public void testIncompatibleBindingType() {
+ final Integer testInt = 1024;
+ Object instance = new Object() {
+ @Bind(to = String.class) private Integer anInt = testInt;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ 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\"");
+ }
+ }
+
+ public void testFailureOnMultipleBindingAnnotations() {
+ final Integer testInt = 1024;
+ Object instance = new Object() {
+ @Bind
+ @Named("a")
+ @SomeBindingAnnotation
+ private Integer anInt = testInt;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ Guice.createInjector(module);
+ } catch (CreationException e) {
+ assertContains(e.getMessage(), "More than one annotation is
specified for this binding.");
+ }
+ }
+
+ public void testBindingSuperTypeAndBindingAnnotation() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind(to = Number.class)
+ @Named("foo")
+ private Integer anInt = testValue;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Key.get(Number.class,
Names.named("foo"))));
+ }
+
+ public void testBindingProvider() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind private Provider<Integer> anInt = new Provider<Integer>() {
+ @Override public Integer get() {
+ return testValue;
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ public void testBindingNullField() {
+ Object instance = new Object() {
+ @Bind private Integer anInt = null;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ 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.");
+ }
+ }
+
+ public void testBindingNullProvider() {
+ Object instance = new Object() {
+ @Bind private Provider<Integer> anIntProvider = null;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ 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.");
+ }
+ }
+
+ private static class IntegerProvider implements Provider<Integer> {
+ private final Integer value;
+
+ IntegerProvider(Integer value) {
+ this.value = value;
+ }
+
+ @Override public Integer get() {
+ return value;
+ }
+ }
+
+ public void testProviderSubclassesBindToTheProviderItself() {
+ final IntegerProvider integerProvider = new IntegerProvider(1024);
+ Object instance = new Object() {
+ @Bind private IntegerProvider anIntProvider = integerProvider;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(integerProvider,
injector.getInstance(IntegerProvider.class));
+ }
+
+ public void testProviderSubclassesDoNotBindParameterizedType() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind private IntegerProvider anIntProvider = new
IntegerProvider(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.");
+ }
+ }
+
+ private static class ParameterizedObject<T> {
+ ParameterizedObject(T instance) {
+ this.instance = instance;
+ }
+
+ @Bind private T instance;
+ }
+
+ public void testBindParameterizedTypeFails() {
+ ParameterizedObject<Integer> instance = new
ParameterizedObject<Integer>(0);
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ Guice.createInjector(module);
+ fail();
+ } catch (CreationException e) {
+ assertContains(e.getMessage(), "T cannot be used as a key; It is not
fully specified.");
+ }
+ }
+
+ public void testBindSubclassOfParameterizedTypeSucceeds() {
+ final Integer testValue = 1024;
+ ParameterizedObject<Integer> instance = new
ParameterizedObject<Integer>(testValue) {};
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ public void testBindArray() {
+ 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);
+
+ assertEquals(testArray, injector.getInstance(Integer[].class));
+ }
+
+ public void testRawProviderCannotBeBound() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind private Provider anIntProvider = new Provider() {
+ @Override public Object get() {
+ return testValue;
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ Guice.createInjector(module);
+ fail();
+ } catch (CreationException e) {
+ assertContains(e.getMessage(),
+ "Non parameterized Provider fields must have an "
+ + "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;
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ 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;
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(String.class));
+ }
+
+ public void testMultipleErrorsAreAggregated() {
+ Object instance = new Object() {
+ @Bind private Provider aProvider;
+ @Bind(to = String.class) private Integer anInt;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ try {
+ Guice.createInjector(module);
+ } catch (CreationException e) {
+ assertEquals(2, e.getErrorMessages().size());
+ }
+ }
+
+ public void testBindingProviderWithProviderSubclassValue() {
+ final Integer testValue = 1024;
+ Object instance = new Object() {
+ @Bind private Provider<Integer> anIntProvider = new
IntegerProvider(testValue);
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Integer.class));
+ }
+
+ public void testBoundFieldsCannotBeInjected() {
+ Object instance = new Object() {
+ @Bind
+ @Inject
+ Integer anInt = 0;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ Guice.createInjector(module);
+ } catch (CreationException e) {
+ 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<Integer> anIntProvider = new
Provider<Integer>() {
+ private int value = testBaseValue;
+
+ @Override public Integer get() {
+ return value++;
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testBaseValue, injector.getInstance(Integer.class));
+ assertEquals((Integer) (testBaseValue + 1),
injector.getInstance(Integer.class));
+ assertEquals((Integer) (testBaseValue + 2),
injector.getInstance(Integer.class));
+ }
+
+ public void testProviderDoesNotProvideDuringInjectorConstruction() {
+ Object instance = new Object() {
+ @Bind private Provider<Integer> myIntProvider = new
Provider<Integer>() {
+ @Override public Integer get() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Guice.createInjector(module);
+
+ // If we don't throw an exception, we succeeded.
+ }
+
+ private static class InvalidBindableClass {
+ @Bind(to = String.class) Integer anInt;
+ }
+
+ public void testIncompatibleBindingTypeStackTraceHasUserFrame() {
+ Object instance = new InvalidBindableClass();
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ Guice.createInjector(module);
+ fail();
+ } catch (CreationException e) {
+ assertContains(e.getMessage(), "at " +
InvalidBindableClass.class.getName() + " field anInt");
+ }
+ }
+
+ private static class InjectedNumberProvider implements Provider<Number> {
+ @Inject Integer anInt;
+
+ @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<Number> aNumberProvider = new
InjectedNumberProvider();
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, injector.getInstance(Number.class));
+ }
+
+ 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;
+ };
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue, testNumberProvider.anInt);
+ }
+
+ private static class InvalidBindableSubclass extends
InvalidBindableClass {}
+
+ public void testClassIsPrintedInErrorsWhenCauseIsSuperclass() {
+ Object instance = new InvalidBindableSubclass();
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+
+ try {
+ Guice.createInjector(module);
+ } catch (CreationException e) {
+ assertContains(
+ e.getMessage(),
+ "Requested binding type \"java.lang.String\" is not assignable
from field binding type "
+ + "\"java.lang.Integer\"");
+ }
+ }
+
+ private static class FieldBindableSubclass2 extends FieldBindableClass {
+ @Bind Number aNumber;
+
+ FieldBindableSubclass2(Integer anInt, Number aNumber) {
+ super(anInt);
+ this.aNumber = aNumber;
+ }
+ }
+
+ public void testFieldsAreBoundFromFullClassHierarchy() {
+ final Integer testValue1 = 1024, testValue2 = 2048;
+ FieldBindableSubclass2 instance = new
FieldBindableSubclass2(testValue1, testValue2);
+
+ BoundFieldModule module = BoundFieldModule.of(instance);
+ Injector injector = Guice.createInjector(module);
+
+ assertEquals(testValue1, injector.getInstance(Integer.class));
+ assertEquals(testValue2, injector.getInstance(Number.class));
+ }
+}
=======================================
--- /dev/null
+++ /extensions/testlib/testlib.iml Thu Apr 10 23:17:37 2014 UTC
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="guice" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../lib/build/junit.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ </component>
+</module>
+
=======================================
--- /build.properties Thu Feb 13 18:37:24 2014 UTC
+++ /build.properties Thu Apr 10 23:17:37 2014 UTC
@@ -13,6 +13,7 @@
persist.src.dir=extensions/persist/src
struts2.src.dir=extensions/struts2/src
grapher.src.dir=extensions/grapher/src
+testlib.src.dir=extensions/testlib/src
build.dir=build
javadoc.packagenames=com.google.inject,com.google.inject.spi,\
com.google.inject.matcher,\
@@ -29,7 +30,9 @@
com.google.inject.util,\
com.google.inject.persist,\
com.google.inject.persist.finder,\
- com.google.inject.persist.jpa
+ com.google.inject.persist.jpa,\
+ com.google.inject.testing,\
+ com.google.inject.testing.fieldbinder
test.class=com.google.inject.AllTests
module=com.google.inject
imports=!net.sf.cglib.*,!org.objectweb.asm.*
=======================================
--- /build.xml Tue Apr 8 16:26:24 2014 UTC
+++ /build.xml Thu Apr 10 23:17:37 2014 UTC
@@ -28,7 +28,8 @@
<ant antfile="extensions/throwingproviders/build.xml"
target="distjars" inheritAll="false"/>
<ant antfile="extensions/multibindings/build.xml" target="distjars"
inheritAll="false"/>
<ant antfile="extensions/persist/build.xml" target="distjars"
inheritAll="false"/>
- <ant antfile="extensions/grapher/build.xml" target="distjars"
inheritAll="false"/>
+ <ant antfile="extensions/grapher/build.xml" target="distjars"
inheritAll="false"/>
+ <ant antfile="extensions/testlib/build.xml" target="distjars"
inheritAll="false"/>
<copy toDir="${build.dir}/dist">
<fileset dir="extensions/servlet/build" includes="*.jar"/>
@@ -57,9 +58,12 @@
<copy toDir="${build.dir}/dist">
<fileset dir="extensions/persist/build" includes="*.jar"/>
</copy>
- <copy toDir="${build.dir}/dist">
- <fileset dir="extensions/grapher/build" includes="*.jar"/>
- </copy>
+ <copy toDir="${build.dir}/dist">
+ <fileset dir="extensions/grapher/build" includes="*.jar"/>
+ </copy>
+ <copy toDir="${build.dir}/dist">
+ <fileset dir="extensions/testlib/build" includes="*.jar"/>
+ </copy>
<copy toDir="${build.dir}/dist" file="COPYING"/>
<copy toDir="${build.dir}/dist">
@@ -153,6 +157,7 @@
<fileset dir="${persist.src.dir}"/>
<fileset dir="${struts2.src.dir}"/>
<fileset dir="${grapher.src.dir}"/>
+ <fileset dir="${testlib.src.dir}"/>
<doclet name="jdiff.JDiff"
path="${jdiff.home}/jdiff.jar:${jdiff.home}/xerces.jar">
<param name="-apidir" value="${jdiff.tmp}" />
@@ -179,7 +184,7 @@
</doclet>
</javadoc>
</target>
-
+
<target name="javadoc">
<javadoc packagenames="com.google.*"
destdir="build/docs"
@@ -200,6 +205,7 @@
<fileset dir="${multibindings.src.dir}"/>
<fileset dir="${persist.src.dir}"/>
<fileset dir="${grapher.src.dir}"/>
+ <fileset dir="${testlib.src.dir}"/>
<!-- TODO: this breaks Doclava for some reason
<fileset dir="${struts2.src.dir}"/> -->
@@ -280,6 +286,7 @@
<ant dir="extensions/multibindings" antfile="build.xml"
target="clean"/>
<ant dir="extensions/persist" antfile="build.xml" target="clean"/>
<ant dir="extensions/grapher" antfile="build.xml" target="clean"/>
+ <ant dir="extensions/testlib" antfile="build.xml" target="clean"/>
</target>
</project>
=======================================
--- /extensions/pom.xml Tue Apr 8 16:26:24 2014 UTC
+++ /extensions/pom.xml Thu Apr 10 23:17:37 2014 UTC
@@ -26,6 +26,7 @@
<module>servlet</module>
<module>spring</module>
<module>struts2</module>
+ <module>testlib</module>
<module>throwingproviders</module>
<!--
| not yet promoted...
==============================================================================
Revision: c35ebc2ce88f
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:18:01 2014 UTC
Log: Fix external issue 372 -- only scrub the pathInfo if the
servletPath actually
began it (not if it just happens to be longer than the servlet path).
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=64723867
http://code.google.com/p/google-guice/source/detail?r=c35ebc2ce88f
Modified:
/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
=======================================
---
/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
Thu Jun 27 00:43:11 2013 UTC
+++
/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
Thu Apr 10 23:18:01 2014 UTC
@@ -205,18 +205,19 @@
@Override
public String getPathInfo() {
if (!isPathInfoComputed()) {
- int servletPathLength = getServletPath().length();
- pathInfo = getRequestURI().substring(getContextPath().length())
- .replaceAll("[/]{2,}", "/");
- pathInfo = pathInfo.length() > servletPathLength
- ? pathInfo.substring(servletPathLength) : null;
-
- // Corner case: when servlet path and request path match exactly
(without trailing '/'),
- // then pathinfo is null
- if ("".equals(pathInfo) && servletPathLength != 0) {
- pathInfo = null;
+ String servletPath = getServletPath();
+ int servletPathLength = servletPath.length();
+ String requestUri = getRequestURI();
+ pathInfo =
requestUri.substring(getContextPath().length()).replaceAll("[/]{2,}", "/");
+ // See:
http://code.google.com/p/google-guice/issues/detail?id=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;
+ }
}
-
pathInfoComputed = true;
}
=======================================
---
/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
Fri Jul 8 00:34:16 2011 UTC
+++
/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
Thu Apr 10 23:18:01 2014 UTC
@@ -124,6 +124,10 @@
"/thing");
pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*",
null, "/thing");
+ // see external issue 372
+
pathInfoWithServletStyleMatching("/path/some/path/of.jsp", "/path", "/thing/*",
+ "/some/path/of.jsp", "/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");
==============================================================================
Revision: 647b24f7f1b5
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:18:26 2014 UTC
Log: Fix external issue 755. Grapher config was wrong.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=64724255
http://code.google.com/p/google-guice/source/detail?r=647b24f7f1b5
Modified:
/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizGrapher.java
=======================================
---
/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizGrapher.java
Thu May 16 14:56:20 2013 UTC
+++
/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizGrapher.java
Thu Apr 10 23:18:26 2014 UTC
@@ -116,7 +116,7 @@
attrs.put("label", getNodeLabel(node));
// remove most of the margin because the table has internal padding
- attrs.put("margin", "0.02,0");
+ attrs.put("margin", "\"0.02,0\"");
attrs.put("shape", node.getShape().toString());
attrs.put("style", node.getStyle().toString());
==============================================================================
Revision: f1abba38c7f5
Author: Sam Berlin <[email protected]>
Date: Thu Apr 10 23:18:51 2014 UTC
Log: On second thought, according to the javadocs @
http://docs.oracle.com/javaee/5/api/javax/servlet/http/HttpServletRequest.html#getPathInfo() ..
this is probably more correct, and still better than what it was before.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=64726165
http://code.google.com/p/google-guice/source/detail?r=f1abba38c7f5
Modified:
/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
=======================================
---
/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
Thu Apr 10 23:18:01 2014 UTC
+++
/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
Thu Apr 10 23:18:51 2014 UTC
@@ -217,6 +217,8 @@
if (pathInfo.isEmpty() && servletPathLength > 0) {
pathInfo = null;
}
+ } else {
+ pathInfo = null; // we know nothing additional about the URI.
}
pathInfoComputed = true;
}
=======================================
---
/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
Thu Apr 10 23:18:01 2014 UTC
+++
/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
Thu Apr 10 23:18:51 2014 UTC
@@ -126,7 +126,7 @@
// see external issue 372
pathInfoWithServletStyleMatching("/path/some/path/of.jsp", "/path", "/thing/*",
- "/some/path/of.jsp", "/some/path/of.jsp");
+ null, "/some/path/of.jsp");
// *.xx style mapping
pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing",
null, "/thing.thing");
--
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-guice-dev.
For more options, visit https://groups.google.com/d/optout.