PageRenderTime 119ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/sisu-2.2.3/sisu-inject/containers/guice-bean/guice-bean-binders/src/test/java/org/sonatype/guice/bean/binders/BeanImportTest.java

#
Java | 714 lines | 573 code | 130 blank | 11 comment | 0 complexity | bd4fd7fea4f3e85bd82670eef3c19cd0 MD5 | raw file
Possible License(s): Apache-2.0, EPL-1.0
  1. /*******************************************************************************
  2. * Copyright (c) 2010-2011 Sonatype, Inc.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * and Apache License v2.0 which accompanies this distribution.
  6. * The Eclipse Public License is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. * The Apache License v2.0 is available at
  9. * http://www.apache.org/licenses/LICENSE-2.0.html
  10. * You may elect to redistribute this code under either of these licenses.
  11. *******************************************************************************/
  12. package org.sonatype.guice.bean.binders;
  13. import static java.lang.annotation.ElementType.FIELD;
  14. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  15. import java.lang.annotation.Annotation;
  16. import java.lang.annotation.Retention;
  17. import java.lang.annotation.Target;
  18. import java.util.Collections;
  19. import java.util.HashMap;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.Random;
  24. import java.util.Set;
  25. import javax.inject.Inject;
  26. import javax.inject.Named;
  27. import junit.framework.TestCase;
  28. import org.slf4j.Logger;
  29. import org.sonatype.guice.bean.reflect.ClassSpace;
  30. import org.sonatype.guice.bean.reflect.TypeParameters;
  31. import org.sonatype.guice.bean.reflect.URLClassSpace;
  32. import org.sonatype.inject.BeanEntry;
  33. import org.sonatype.inject.Nullable;
  34. import com.google.inject.AbstractModule;
  35. import com.google.inject.BindingAnnotation;
  36. import com.google.inject.CreationException;
  37. import com.google.inject.Guice;
  38. import com.google.inject.ImplementedBy;
  39. import com.google.inject.Injector;
  40. import com.google.inject.Key;
  41. import com.google.inject.ProvidedBy;
  42. import com.google.inject.Provider;
  43. import com.google.inject.ProvisionException;
  44. import com.google.inject.TypeLiteral;
  45. import com.google.inject.matcher.Matchers;
  46. import com.google.inject.name.Names;
  47. public class BeanImportTest
  48. extends TestCase
  49. {
  50. @Target( FIELD )
  51. @Retention( RUNTIME )
  52. @BindingAnnotation
  53. public @interface Fuzzy
  54. {
  55. }
  56. static class FuzzyImpl
  57. implements Fuzzy
  58. {
  59. public Class<? extends Annotation> annotationType()
  60. {
  61. return Fuzzy.class;
  62. }
  63. @Override
  64. public boolean equals( final Object rhs )
  65. {
  66. return rhs instanceof Fuzzy;
  67. }
  68. @Override
  69. public int hashCode()
  70. {
  71. return 0;
  72. }
  73. }
  74. interface X
  75. {
  76. }
  77. interface Y
  78. {
  79. }
  80. interface Z<T>
  81. {
  82. }
  83. @ProvidedBy( XProvider.class )
  84. interface ImplicitX
  85. extends X
  86. {
  87. }
  88. @ImplementedBy( YImpl.class )
  89. interface ImplicitY
  90. extends Y
  91. {
  92. }
  93. static class XProvider
  94. implements Provider<ImplicitX>
  95. {
  96. public ImplicitX get()
  97. {
  98. return new ImplicitX()
  99. {
  100. };
  101. }
  102. }
  103. static abstract class AbstractY
  104. implements Y
  105. {
  106. }
  107. static class YImpl
  108. extends AbstractY
  109. implements ImplicitY
  110. {
  111. }
  112. static class ZImpl<T>
  113. implements Z<T>
  114. {
  115. T element;
  116. }
  117. static abstract class AbstractX
  118. implements X
  119. {
  120. @Inject
  121. Injector injector;
  122. @Inject
  123. Logger logger;
  124. @Inject
  125. ImplicitX implicitX;
  126. @Inject
  127. ImplicitY implicitY;
  128. @Inject
  129. YImpl concreteY;
  130. @Inject
  131. @Nullable
  132. AbstractY abstractY;
  133. @Inject
  134. @Fuzzy
  135. Y fuzzy;
  136. @Inject
  137. @Named( "local" )
  138. Y local;
  139. @Inject
  140. Map<Named, Y> namedMap;
  141. }
  142. static class UnrestrictedInstance
  143. extends AbstractX
  144. {
  145. final Y single;
  146. @Inject
  147. UnrestrictedInstance( @Nullable final Y single, @Named( "local" ) final Y local )
  148. {
  149. this.single = single;
  150. this.local = local;
  151. }
  152. }
  153. static class UnrestrictedList
  154. extends AbstractX
  155. {
  156. @Inject
  157. List<Y> list;
  158. @Inject
  159. Iterable<Y> iterable;
  160. }
  161. static class UnrestrictedSet
  162. extends AbstractX
  163. {
  164. @Inject
  165. Set<Y> set;
  166. }
  167. static class NamedType
  168. extends AbstractX
  169. {
  170. final Y single;
  171. @Inject
  172. NamedType( @Named( "local" ) final Y local, @Nullable @Named final Y single )
  173. {
  174. this.single = single;
  175. this.local = local;
  176. }
  177. }
  178. static class NamedInstance
  179. extends AbstractX
  180. {
  181. final Y single;
  182. @Inject
  183. NamedInstance( @Nullable @Named( "TEST" ) final Y single )
  184. {
  185. this.single = single;
  186. }
  187. @Inject
  188. void setLocal( final @Named( "local" ) Y local )
  189. {
  190. this.local = local;
  191. }
  192. }
  193. static class HintMap
  194. extends AbstractX
  195. {
  196. @Inject
  197. Map<String, Y> map;
  198. }
  199. static class BeanEntries
  200. implements X
  201. {
  202. @Inject
  203. Iterable<BeanEntry<Named, Y>> entries;
  204. }
  205. static class PlaceholderInstance
  206. extends AbstractX
  207. {
  208. @Inject
  209. @Nullable
  210. @Named( "${name}" )
  211. Y single;
  212. }
  213. static class PlaceholderString
  214. extends AbstractX
  215. {
  216. @Inject
  217. @Nullable
  218. @Named( "${text}" )
  219. String config;
  220. @Inject
  221. @Nullable
  222. @Named( "text" )
  223. String plain;
  224. }
  225. static class PlaceholderConfig
  226. extends AbstractX
  227. {
  228. @Inject
  229. @Nullable
  230. @Named( "4${value}2" )
  231. int single;
  232. }
  233. static class BadMap
  234. implements X
  235. {
  236. @Inject
  237. Map<Integer, Integer> map;
  238. }
  239. static class RawList
  240. implements X
  241. {
  242. @Inject
  243. @SuppressWarnings( "rawtypes" )
  244. List list;
  245. }
  246. static class RawMap
  247. implements X
  248. {
  249. @Inject
  250. @SuppressWarnings( "rawtypes" )
  251. Map map;
  252. }
  253. static class MissingList
  254. implements X
  255. {
  256. @Inject
  257. @Named( "missing" )
  258. List<Y> list;
  259. }
  260. static class MissingSet
  261. implements X
  262. {
  263. @Inject
  264. @Named( "missing" )
  265. Set<Y> set;
  266. }
  267. static class MissingMap
  268. implements X
  269. {
  270. @Inject
  271. @Named( "missing" )
  272. Map<Named, Y> map;
  273. }
  274. static class GenericInstance
  275. implements X
  276. {
  277. @Inject
  278. Z<? extends Number> number;
  279. @Inject
  280. Z<String> chars;
  281. @Inject
  282. Z<Random> random;
  283. }
  284. static Map<String, Object> PROPS = new HashMap<String, Object>();
  285. class TestModule
  286. extends AbstractModule
  287. {
  288. @Override
  289. protected void configure()
  290. {
  291. bind( ClassSpace.class ).toInstance( new URLClassSpace( BeanImportTest.class.getClassLoader() ) );
  292. bindInterceptor( Matchers.subclassesOf( X.class ), Matchers.any() );
  293. requestInjection( BeanImportTest.this );
  294. bind( X.class ).annotatedWith( Names.named( "UI" ) ).to( UnrestrictedInstance.class );
  295. bind( X.class ).annotatedWith( Names.named( "UL" ) ).to( UnrestrictedList.class );
  296. bind( X.class ).annotatedWith( Names.named( "US" ) ).to( UnrestrictedSet.class );
  297. bind( X.class ).annotatedWith( Names.named( "NT" ) ).to( NamedType.class );
  298. bind( X.class ).annotatedWith( Names.named( "NI" ) ).to( NamedInstance.class );
  299. bind( X.class ).annotatedWith( Names.named( "HM" ) ).to( HintMap.class );
  300. bind( X.class ).annotatedWith( Names.named( "BE" ) ).to( BeanEntries.class );
  301. bind( X.class ).annotatedWith( Names.named( "PI" ) ).to( PlaceholderInstance.class );
  302. bind( X.class ).annotatedWith( Names.named( "PS" ) ).to( PlaceholderString.class );
  303. bind( X.class ).annotatedWith( Names.named( "PC" ) ).to( PlaceholderConfig.class );
  304. bind( X.class ).annotatedWith( Names.named( "GI" ) ).to( GenericInstance.class );
  305. bind( Y.class ).annotatedWith( Names.named( "local" ) ).toInstance( new YImpl() );
  306. bind( Y.class ).annotatedWith( new FuzzyImpl() ).toInstance( new YImpl() );
  307. bind( Z.class ).annotatedWith( Names.named( "integer" ) ).toInstance( new ZImpl<Integer>()
  308. {
  309. } );
  310. bind( Z.class ).annotatedWith( Names.named( "string" ) ).toInstance( new ZImpl<String>()
  311. {
  312. } );
  313. bind( Z.class ).annotatedWith( Names.named( "raw" ) ).to( ZImpl.class );
  314. bind( ParameterKeys.PROPERTIES ).toInstance( PROPS );
  315. }
  316. }
  317. public void testUnrestrictedImport()
  318. {
  319. final Injector injector = Guice.createInjector( new WireModule( new TestModule() ) );
  320. final UnrestrictedInstance unrestrictedInstance =
  321. (UnrestrictedInstance) injector.getInstance( Key.get( X.class, Names.named( "UI" ) ) );
  322. assertSame( unrestrictedInstance.local, unrestrictedInstance.single );
  323. final UnrestrictedList unrestrictedList =
  324. (UnrestrictedList) injector.getInstance( Key.get( X.class, Names.named( "UL" ) ) );
  325. assertEquals( 2, unrestrictedList.list.size() );
  326. assertSame( unrestrictedInstance.local, unrestrictedList.list.get( 0 ) );
  327. assertSame( unrestrictedList.local, unrestrictedList.list.get( 0 ) );
  328. assertSame( unrestrictedInstance.fuzzy, unrestrictedList.list.get( 1 ) );
  329. assertSame( unrestrictedList.fuzzy, unrestrictedList.list.get( 1 ) );
  330. assertNotSame( unrestrictedList.list.get( 0 ), unrestrictedList.list.get( 1 ) );
  331. final Iterator<?> iterator = unrestrictedList.iterable.iterator();
  332. assertTrue( iterator.hasNext() );
  333. assertSame( unrestrictedList.list.get( 0 ), iterator.next() );
  334. assertSame( unrestrictedList.list.get( 1 ), iterator.next() );
  335. assertFalse( iterator.hasNext() );
  336. final UnrestrictedSet unrestrictedSet =
  337. (UnrestrictedSet) injector.getInstance( Key.get( X.class, Names.named( "US" ) ) );
  338. assertEquals( 2, unrestrictedSet.set.size() );
  339. assertTrue( unrestrictedSet.set.contains( unrestrictedInstance.local ) );
  340. assertTrue( unrestrictedSet.set.contains( unrestrictedList.local ) );
  341. assertTrue( unrestrictedSet.set.contains( unrestrictedInstance.fuzzy ) );
  342. assertTrue( unrestrictedSet.set.contains( unrestrictedList.fuzzy ) );
  343. }
  344. public void testNamedImports()
  345. {
  346. final Injector injector = Guice.createInjector( new WireModule( new TestModule() ) );
  347. final NamedType namedType = (NamedType) injector.getInstance( Key.get( X.class, Names.named( "NT" ) ) );
  348. final NamedInstance namedInstance =
  349. (NamedInstance) injector.getInstance( Key.get( X.class, Names.named( "NI" ) ) );
  350. assertNotNull( namedType.single );
  351. assertSame( namedType.local, namedType.single );
  352. assertNull( namedInstance.single );
  353. final HintMap hintMap = (HintMap) injector.getInstance( Key.get( X.class, Names.named( "HM" ) ) );
  354. assertEquals( Collections.singletonMap( Names.named( "local" ), hintMap.local ), hintMap.namedMap );
  355. assertSame( namedType.local, hintMap.map.get( "local" ) );
  356. assertSame( hintMap.local, hintMap.map.get( "local" ) );
  357. assertEquals( 1, hintMap.map.size() );
  358. }
  359. public void testBeanEntries()
  360. {
  361. final Injector injector = Guice.createInjector( new WireModule( new TestModule() ) );
  362. final BeanEntries beans = (BeanEntries) injector.getInstance( Key.get( X.class, Names.named( "BE" ) ) );
  363. final HintMap hintMap = (HintMap) injector.getInstance( Key.get( X.class, Names.named( "HM" ) ) );
  364. final Iterator<BeanEntry<Named, Y>> i = beans.entries.iterator();
  365. assertTrue( i.hasNext() );
  366. assertSame( hintMap.map.get( "local" ), i.next().getValue() );
  367. assertFalse( i.hasNext() );
  368. }
  369. public void testPlaceholderImports()
  370. {
  371. final Injector injector = Guice.createInjector( new WireModule( new TestModule() ) );
  372. PlaceholderInstance placeholderInstance;
  373. placeholderInstance = (PlaceholderInstance) injector.getInstance( Key.get( X.class, Names.named( "PI" ) ) );
  374. assertNull( placeholderInstance.single );
  375. final Y why = new YImpl();
  376. PROPS.put( "name", why );
  377. placeholderInstance = (PlaceholderInstance) injector.getInstance( Key.get( X.class, Names.named( "PI" ) ) );
  378. assertSame( why, placeholderInstance.single );
  379. PROPS.put( "name", "local" );
  380. placeholderInstance = (PlaceholderInstance) injector.getInstance( Key.get( X.class, Names.named( "PI" ) ) );
  381. assertSame( placeholderInstance.local, placeholderInstance.single );
  382. PlaceholderString placeholderString;
  383. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  384. assertNull( placeholderString.config );
  385. assertNull( placeholderString.plain );
  386. PROPS.put( "text", "Hello, world!" );
  387. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  388. assertEquals( "Hello, world!", placeholderString.config );
  389. assertEquals( "Hello, world!", placeholderString.plain );
  390. PROPS.put( "text", "text" );
  391. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  392. assertEquals( "text", placeholderString.config );
  393. assertEquals( "text", placeholderString.plain );
  394. PROPS.put( "text", "${text}" );
  395. try
  396. {
  397. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  398. fail( "Expected ProvisionException" );
  399. }
  400. catch ( final ProvisionException e )
  401. {
  402. assertTrue( e.getMessage().contains( "${text}" ) );
  403. }
  404. PROPS.put( "text", ">${one}{" );
  405. PROPS.put( "one", "-${two}=" );
  406. PROPS.put( "two", "<${three}}" );
  407. PROPS.put( "three", "|${text}|" );
  408. try
  409. {
  410. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  411. fail( "Expected ProvisionException" );
  412. }
  413. catch ( final ProvisionException e )
  414. {
  415. assertTrue( e.getMessage().contains( ">-<|>-<|${text}|}={|}={" ) );
  416. }
  417. PROPS.put( "text", ">${text" );
  418. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  419. assertEquals( ">${text", placeholderString.config );
  420. assertEquals( ">${text", placeholderString.plain );
  421. PROPS.put( "text", "${key:-default}" );
  422. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  423. assertEquals( "default", placeholderString.config );
  424. assertEquals( "default", placeholderString.plain );
  425. PROPS.put( "key", "configured" );
  426. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  427. assertEquals( "configured", placeholderString.config );
  428. assertEquals( "configured", placeholderString.plain );
  429. PROPS.put( "text", "${:-some:-default:-value:-}" );
  430. placeholderString = (PlaceholderString) injector.getInstance( Key.get( X.class, Names.named( "PS" ) ) );
  431. assertEquals( "some:-default:-value:-", placeholderString.config );
  432. assertEquals( "some:-default:-value:-", placeholderString.plain );
  433. try
  434. {
  435. injector.getInstance( Key.get( X.class, Names.named( "PC" ) ) );
  436. fail( "Expected RuntimeException" );
  437. }
  438. catch ( final RuntimeException e )
  439. {
  440. System.out.println( e );
  441. }
  442. PROPS.put( "value", "53" );
  443. assertEquals( 4532,
  444. ( (PlaceholderConfig) injector.getInstance( Key.get( X.class, Names.named( "PC" ) ) ) ).single );
  445. }
  446. public void testDuplicatesAreIgnored()
  447. {
  448. Guice.createInjector( new WireModule( new TestModule(), new TestModule(), new TestModule() ) );
  449. }
  450. public void testImportSource()
  451. {
  452. final Injector injector = Guice.createInjector( new WireModule( new TestModule() ) );
  453. assertEquals( LocatorWiring.class.getName(), injector.getBinding( Y.class ).getSource().toString() );
  454. }
  455. public void testInvalidTypeParameters()
  456. {
  457. try
  458. {
  459. Guice.createInjector( new WireModule( new AbstractModule()
  460. {
  461. @Override
  462. protected void configure()
  463. {
  464. bind( X.class ).annotatedWith( Names.named( "BM" ) ).to( BadMap.class );
  465. }
  466. } ) );
  467. fail( "Expected CreationException" );
  468. }
  469. catch ( final CreationException e )
  470. {
  471. }
  472. try
  473. {
  474. Guice.createInjector( new WireModule( new AbstractModule()
  475. {
  476. @Override
  477. protected void configure()
  478. {
  479. bind( X.class ).annotatedWith( Names.named( "RL" ) ).to( RawList.class );
  480. }
  481. } ) );
  482. fail( "Expected CreationException" );
  483. }
  484. catch ( final CreationException e )
  485. {
  486. }
  487. try
  488. {
  489. Guice.createInjector( new WireModule( new AbstractModule()
  490. {
  491. @Override
  492. protected void configure()
  493. {
  494. bind( X.class ).annotatedWith( Names.named( "RM" ) ).to( RawMap.class );
  495. }
  496. } ) );
  497. fail( "Expected CreationException" );
  498. }
  499. catch ( final CreationException e )
  500. {
  501. }
  502. try
  503. {
  504. Guice.createInjector( new WireModule( new AbstractModule()
  505. {
  506. @Override
  507. protected void configure()
  508. {
  509. bind( X.class ).annotatedWith( Names.named( "ML" ) ).to( MissingList.class );
  510. }
  511. } ) );
  512. fail( "Expected CreationException" );
  513. }
  514. catch ( final CreationException e )
  515. {
  516. }
  517. try
  518. {
  519. Guice.createInjector( new WireModule( new AbstractModule()
  520. {
  521. @Override
  522. protected void configure()
  523. {
  524. bind( X.class ).annotatedWith( Names.named( "MS" ) ).to( MissingSet.class );
  525. }
  526. } ) );
  527. fail( "Expected CreationException" );
  528. }
  529. catch ( final CreationException e )
  530. {
  531. }
  532. try
  533. {
  534. Guice.createInjector( new WireModule( new AbstractModule()
  535. {
  536. @Override
  537. protected void configure()
  538. {
  539. bind( X.class ).annotatedWith( Names.named( "MM" ) ).to( MissingMap.class );
  540. }
  541. } ) );
  542. fail( "Expected CreationException" );
  543. }
  544. catch ( final CreationException e )
  545. {
  546. }
  547. }
  548. public void testGenericInjection()
  549. {
  550. final Injector injector = Guice.createInjector( new WireModule( new TestModule() ) );
  551. final GenericInstance genericInstance =
  552. (GenericInstance) injector.getInstance( Key.get( X.class, Names.named( "GI" ) ) );
  553. assertEquals( TypeLiteral.get( Integer.class ),
  554. TypeParameters.get( TypeLiteral.get( genericInstance.number.getClass() ).getSupertype( Z.class ),
  555. 0 ) );
  556. assertEquals( TypeLiteral.get( String.class ),
  557. TypeParameters.get( TypeLiteral.get( genericInstance.chars.getClass() ).getSupertype( Z.class ),
  558. 0 ) );
  559. assertEquals( ZImpl.class, genericInstance.random.getClass() );
  560. }
  561. public void testChildWiring()
  562. {
  563. final Y y = new YImpl();
  564. final Injector parent = Guice.createInjector( new AbstractModule()
  565. {
  566. @Override
  567. protected void configure()
  568. {
  569. bind( Y.class ).annotatedWith( Names.named( "local" ) ).toInstance( y );
  570. }
  571. } );
  572. final Injector child = parent.createChildInjector( new AbstractModule()
  573. {
  574. @Override
  575. protected void configure()
  576. {
  577. bind( Y.class ).annotatedWith( new FuzzyImpl() ).toInstance( y );
  578. }
  579. } );
  580. final Injector grandchild = child.createChildInjector( new ChildWireModule( child, new TestModule() ) );
  581. assertSame( y, ( (PlaceholderString) grandchild.getInstance( Key.get( X.class, Names.named( "PS" ) ) ) ).local );
  582. assertSame( y, ( (PlaceholderString) grandchild.getInstance( Key.get( X.class, Names.named( "PS" ) ) ) ).fuzzy );
  583. }
  584. }