alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (InjectionPointTest.java)

This example Java source code file (InjectionPointTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

dependency, exception, field, inject, injectionpoint, ioexception, method, named, nosuchmethodexception, override, reflection, set, signature, string, typeliteral, util

The InjectionPointTest.java Java example source code

/**
 * 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.spi;

import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.Asserts.assertEqualsBothWays;
import static com.google.inject.Asserts.assertNotSerializable;
import static com.google.inject.name.Names.named;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
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;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * @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) {}
  }

  public void testFieldInjectionPoint() throws NoSuchFieldException, IOException, ErrorsException {
    TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());
    Field fooField = getClass().getField("foo");

    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, fooField, false);
    assertSame(fooField, injectionPoint.getMember());
    assertFalse(injectionPoint.isOptional());
    assertEquals(getClass().getName() + ".foo", injectionPoint.toString());
    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, fooField, false));
    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(fooField, dependency.getInjectionPoint().getMember());
    assertEquals(-1, dependency.getParameterIndex());
    assertEquals(Key.get(String.class, named("a")), dependency.getKey());
    assertFalse(dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency,
        getOnlyElement(new InjectionPoint(typeLiteral, fooField, false).getDependencies()));
  }

  public void testMethodInjectionPoint() throws Exception {
    TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());

    Method barMethod = getClass().getMethod("bar", String.class);
    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, barMethod, false);
    assertSame(barMethod, injectionPoint.getMember());
    assertFalse(injectionPoint.isOptional());
    assertEquals(getClass().getName() + ".bar()", injectionPoint.toString());
    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, barMethod, false));
    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(barMethod, dependency.getInjectionPoint().getMember());
    assertEquals(0, dependency.getParameterIndex());
    assertEquals(Key.get(String.class, named("b")), dependency.getKey());
    assertFalse(dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency,
        getOnlyElement(new InjectionPoint(typeLiteral, barMethod, false).getDependencies()));
  }

  public void testConstructorInjectionPoint() throws NoSuchMethodException, IOException,
      ErrorsException {
    TypeLiteral<?> typeLiteral = TypeLiteral.get(Constructable.class);

    Constructor<?> constructor = Constructable.class.getConstructor(String.class);
    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, constructor);
    assertSame(constructor, injectionPoint.getMember());
    assertFalse(injectionPoint.isOptional());
    assertEquals(Constructable.class.getName() + ".<init>()", injectionPoint.toString());
    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, constructor));
    assertNotSerializable(injectionPoint);

    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=c)]@"
        + Constructable.class.getName() + ".<init>()[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()));
  }

  public void testUnattachedDependency() throws IOException {
    Dependency<String> dependency = Dependency.get(Key.get(String.class, named("d")));
    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=d)]",
        dependency.toString());
    assertNull(dependency.getInjectionPoint());
    assertEquals(-1, dependency.getParameterIndex());
    assertEquals(Key.get(String.class, named("d")), dependency.getKey());
    assertTrue(dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency, Dependency.get(Key.get(String.class, named("d"))));
  }

  public void testForConstructor() throws NoSuchMethodException {
    Constructor<HashSet> constructor = HashSet.class.getConstructor();
    TypeLiteral<HashSet hashSet = new TypeLiteral>() {};

    InjectionPoint injectionPoint = InjectionPoint.forConstructor(constructor, hashSet);
    assertSame(constructor, injectionPoint.getMember());
    assertEquals(ImmutableList.<Dependency>of(), injectionPoint.getDependencies());
    assertFalse(injectionPoint.isOptional());

    try {
      InjectionPoint.forConstructor(constructor, new TypeLiteral<LinkedHashSet() {});
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "java.util.LinkedHashSet<java.lang.String>",
          " does not define java.util.HashSet.<init>()",
          "  while locating java.util.LinkedHashSet<java.lang.String>");
    }

    try {
      InjectionPoint.forConstructor((Constructor) constructor, new TypeLiteral<Set() {});
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "java.util.Set<java.lang.String>",
          " does not define java.util.HashSet.<init>()",
          "  while locating java.util.Set<java.lang.String>");
    }
  }

  public void testForConstructorOf() {
    InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Constructable.class);
    assertEquals(Constructable.class.getName() + ".<init>()", injectionPoint.toString());
  }

  public void testAddForInstanceMethodsAndFields() throws Exception {
    Method instanceMethod = HasInjections.class.getMethod("instanceMethod", String.class);
    Field instanceField = HasInjections.class.getField("instanceField");

    TypeLiteral<HasInjections> type = TypeLiteral.get(HasInjections.class);
    assertEquals(ImmutableSet.of(
        new InjectionPoint(type, instanceMethod, false),
        new InjectionPoint(type, instanceField, false)),
        InjectionPoint.forInstanceMethodsAndFields(HasInjections.class));
  }

  public void testAddForStaticMethodsAndFields() throws Exception {
    Method staticMethod = HasInjections.class.getMethod("staticMethod", String.class);
    Field staticField = HasInjections.class.getField("staticField");

    Set<InjectionPoint> 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);
  }

  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;
  }

  public void testAddForParameterizedInjections() {
    TypeLiteral<?> type = new TypeLiteral>() {};

    InjectionPoint constructor = InjectionPoint.forConstructorOf(type);
    assertEquals(new Key<Map() {},
        getOnlyElement(constructor.getDependencies()).getKey());

    InjectionPoint field = getOnlyElement(InjectionPoint.forInstanceMethodsAndFields(type));
    assertEquals(new Key<Set() {}, getOnlyElement(field.getDependencies()).getKey());
  }

  static class ParameterizedInjections<T> {
    @Inject Set<T> setOfTees;
    @Inject public ParameterizedInjections(Map<T, T> map) {}
  }

  public void testSignature() throws Exception {
    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 barB = new Signature(Bar.class.getDeclaredMethod("b"));

    assertEquals(fooA.hashCode(), barA.hashCode());
    assertEquals(fooB.hashCode(), barB.hashCode());
    assertEquals(fooA, barA);
    assertEquals(fooB, barB);
  }

  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<InjectionPoint> points;

    points = InjectionPoint.forInstanceMethodsAndFields(Super.class);
    assertEquals(points.toString(), 6, points.size());
    assertPoints(points, Super.class, "atInject", "gInject", "privateAtAndPublicG",
        "privateGAndPublicAt", "atFirstThenG", "gFirstThenAt");

    points = InjectionPoint.forInstanceMethodsAndFields(Sub.class);
    assertEquals(points.toString(), 7, points.size());
    // Superclass will always have is private members injected,
    // and 'gInject' was last @Injected in Super, so that remains the owner
    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");
    
    points = InjectionPoint.forInstanceMethodsAndFields(SubSub.class);
    assertEquals(points.toString(), 6, points.size());
    // Superclass still has all the injection points it did before..
    assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject");
    // Subclass is missing the privateGAndPublicAt because it first became public with
    // 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");    
  }
  
  /**
   * 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<InjectionPoint> points;
    
    points = InjectionPoint.forInstanceMethodsAndFields(RestrictedSuper.class);
    assertPointDependencies(points, new TypeLiteral<Provider() {});
    assertEquals(points.toString(), 2, points.size());
    assertPoints(points, RestrictedSuper.class, "jInject", "gInject");
    
    points = InjectionPoint.forInstanceMethodsAndFields(ExposedSub.class);
    assertPointDependencies(points, new TypeLiteral<Provider() {});
    assertEquals(points.toString(), 2, points.size());
    assertPoints(points, RestrictedSuper.class, "jInject", "gInject");
  }
  
  private void assertPoints(Iterable<InjectionPoint> points, Class clazz,
      String... methodNames) {
    Set<String> methods = new HashSet();
    for (InjectionPoint point : points) {
      if (point.getDeclaringType().getRawType() == clazz) {
        methods.add(point.getMember().getName());
      }
    }
    assertEquals(points.toString(), ImmutableSet.copyOf(methodNames), methods);
  }
  
  /** Asserts that each injection point has the specified dependencies, in the given order. */
  private void assertPointDependencies(Iterable<InjectionPoint> points,
      TypeLiteral<?>... literals) {
    for (InjectionPoint point : points) {
      assertEquals(literals.length, point.getDependencies().size());
      for (Dependency<?> dep : point.getDependencies()) {
        assertEquals(literals[dep.getParameterIndex()], dep.getKey().getTypeLiteral());
      }
    }
  }
  
  static class Super {
    @javax.inject.Inject public void atInject() {}
    @com.google.inject.Inject public void gInject() {}

    @javax.inject.Inject private void privateAtAndPublicG() {}
    @com.google.inject.Inject private void privateGAndPublicAt() {}

    @javax.inject.Inject public void atFirstThenG() {}
    @com.google.inject.Inject public void gFirstThenAt() {}
  }
  
  static class Sub extends Super {
    public void atInject() {}
    public void gInject() {}
    
    @com.google.inject.Inject public void privateAtAndPublicG() {}
    @javax.inject.Inject public void privateGAndPublicAt() {}
    
    @com.google.inject.Inject
    @Override 
    public void atFirstThenG() {}
    
    @javax.inject.Inject
    @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() {}
  }
  
  static class RestrictedSuper {
    @com.google.inject.Inject public void gInject(Provider<String> p) {}
    @javax.inject.Inject public void jInject(Provider<String> 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.
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java InjectionPointTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.