public static String getUserPackageName ( TypeLiteral < ? > typeLiteral ) { Map < String , Class < ? > > packageNames = new LinkedHashMap < String , Class < ? > > ( ) ; getTypePackageNames ( typeLiteral . getType ( ) , packageNames ) ; if ( packageNames . size ( ) == 0 ) { // All type names are public, so typeLiteral is visible from any package. // Arbitrarily put it in the package declaring the top-level class. return typeLiteral . getRawType ( ) . getPackage ( ) . getName ( ) ; } else if ( packageNames . size ( ) == 1 ) { // The type contains names that are private to exactly one package; it // must be referenced from that package. return packageNames . keySet ( ) . iterator ( ) . next ( ) ; } else { // The type literal contains types that are private to two or more // different packages. This can happen if a class uses a type that is // protected in its parent, and its parent is from another package. For // instance: // // package pkg1: // public class Parent { // protected static class ForSubclasses { // } // } // // Here the type ForSubclasses is accessible to anything in the package // "pkg1", but it can't be used in another package: // // package pkg2: // class Foo<T> { // } // // class Child extends Parent { // @Inject Child(Foo<ForSubclasses>) {} // } // // There's no package in which we can place code that can create // Foo<ForSubclasses>, even though the user was able to write that type, // because we would have to subclass Parent to do so. (theoretically we // could write static helper methods inside a subclass, but that seems // like too much trouble to support this sort of weirdness) StringBuilder packageNamesListBuilder = new StringBuilder ( ) ; for ( Class < ? > entry : packageNames . values ( ) ) { packageNamesListBuilder . append ( entry . getCanonicalName ( ) ) . append ( "\n" ) ; } throw new IllegalArgumentException ( PrettyPrinter . format ( "Unable to inject an instance of %s because it references protected classes" + " from multiple packages:\n%s" , typeLiteral , packageNamesListBuilder ) ) ; } }
Return the name of the package from which the given type can be used .