PageRenderTime 585ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/sisu-2.2.3/sisu-inject/containers/guice-plexus/guice-plexus-binders/src/test/java/org/sonatype/guice/plexus/binders/PlexusRequirementTest.java

#
Java | 560 lines | 453 code | 90 blank | 17 comment | 1 complexity | afed34d3cadcbabf1de8f5b1d9df388e 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. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *******************************************************************************/
  8. package org.sonatype.guice.plexus.binders;
  9. import java.io.File;
  10. import java.net.URL;
  11. import java.net.URLClassLoader;
  12. import java.util.ArrayList;
  13. import java.util.Collections;
  14. import java.util.Iterator;
  15. import java.util.List;
  16. import java.util.Map;
  17. import javax.inject.Inject;
  18. import junit.framework.TestCase;
  19. import org.codehaus.plexus.component.annotations.Component;
  20. import org.codehaus.plexus.component.annotations.Requirement;
  21. import org.sonatype.guice.bean.reflect.ClassSpace;
  22. import org.sonatype.guice.bean.reflect.DeferredClass;
  23. import org.sonatype.guice.bean.reflect.URLClassSpace;
  24. import org.sonatype.guice.plexus.config.Hints;
  25. import org.sonatype.guice.plexus.config.PlexusBeanConverter;
  26. import org.sonatype.guice.plexus.config.PlexusBeanLocator;
  27. import org.sonatype.guice.plexus.config.PlexusBeanModule;
  28. import org.sonatype.guice.plexus.config.PlexusBeanSource;
  29. import org.sonatype.guice.plexus.config.Strategies;
  30. import org.sonatype.guice.plexus.converters.PlexusDateTypeConverter;
  31. import org.sonatype.guice.plexus.converters.PlexusXmlBeanConverter;
  32. import org.sonatype.guice.plexus.locators.DefaultPlexusBeanLocator;
  33. import com.google.inject.AbstractModule;
  34. import com.google.inject.Binder;
  35. import com.google.inject.Guice;
  36. import com.google.inject.ImplementedBy;
  37. import com.google.inject.Injector;
  38. import com.google.inject.ProvisionException;
  39. import com.google.inject.Scopes;
  40. import com.google.inject.name.Names;
  41. public class PlexusRequirementTest
  42. extends TestCase
  43. {
  44. @Inject
  45. Component1 component;
  46. @Inject
  47. Injector injector;
  48. @Override
  49. protected void setUp()
  50. {
  51. Guice.createInjector( new AbstractModule()
  52. {
  53. @Override
  54. @SuppressWarnings( "unchecked" )
  55. protected void configure()
  56. {
  57. final ClassSpace space = new URLClassSpace( TestCase.class.getClassLoader() );
  58. final DeferredClass<A> deferA = (DeferredClass<A>) space.deferLoadClass( BrokenAImpl.class.getName() );
  59. install( new PlexusDateTypeConverter() );
  60. bind( PlexusBeanLocator.class ).to( DefaultPlexusBeanLocator.class );
  61. bind( PlexusBeanConverter.class ).to( PlexusXmlBeanConverter.class );
  62. bind( A.class ).annotatedWith( Names.named( "AA" ) ).to( AAImpl.class );
  63. bind( A.class ).annotatedWith( Names.named( "broken" ) ).toProvider( deferA.asProvider() );
  64. bind( A.class ).annotatedWith( Names.named( "AB" ) ).to( ABImpl.class );
  65. bind( A.class ).to( AImpl.class ).in( Scopes.SINGLETON );
  66. bind( A.class ).annotatedWith( Names.named( "AC" ) ).to( ACImpl.class );
  67. bind( B.class ).annotatedWith( Names.named( "B" ) ).to( BImpl.class );
  68. bind( D.class ).annotatedWith( Names.named( "" ) ).to( DImpl.class );
  69. install( new PlexusBindingModule( null, new PlexusBeanModule()
  70. {
  71. public PlexusBeanSource configure( final Binder binder )
  72. {
  73. binder.bind( Alpha.class ).to( AlphaImpl.class ).in( Scopes.SINGLETON );
  74. binder.bind( Omega.class ).to( OmegaImpl.class ).in( Scopes.SINGLETON );
  75. final DeferredClass<Gamma> gammaProvider =
  76. (DeferredClass<Gamma>) space.deferLoadClass( "some-broken-class" ).asProvider();
  77. binder.bind( Gamma.class ).toProvider( gammaProvider.asProvider() ).in( Scopes.SINGLETON );
  78. return null;
  79. }
  80. }, new PlexusAnnotatedBeanModule( null, null ) ) );
  81. requestInjection( PlexusRequirementTest.this );
  82. }
  83. } );
  84. }
  85. @ImplementedBy( AImpl.class )
  86. interface A
  87. {
  88. }
  89. interface B
  90. {
  91. }
  92. interface C
  93. {
  94. }
  95. interface D
  96. {
  97. }
  98. static class AImpl
  99. implements A
  100. {
  101. }
  102. static class BImpl
  103. implements B
  104. {
  105. }
  106. static class DImpl
  107. implements D
  108. {
  109. }
  110. static class AAImpl
  111. extends AImpl
  112. {
  113. }
  114. static class ABImpl
  115. extends AImpl
  116. {
  117. }
  118. static class ACImpl
  119. extends AImpl
  120. {
  121. }
  122. static class BrokenAImpl
  123. extends AImpl
  124. {
  125. public BrokenAImpl( final MissingClass missing )
  126. {
  127. }
  128. }
  129. static class MissingClass
  130. {
  131. }
  132. @Component( role = Component1.class, instantiationStrategy = Strategies.PER_LOOKUP )
  133. static class Component1
  134. {
  135. @Requirement
  136. A testField;
  137. A testSetter;
  138. @Requirement( hints = { "default" } )
  139. void setValue( final A a )
  140. {
  141. testSetter = a;
  142. }
  143. @Requirement( role = A.class )
  144. Object testRole;
  145. @Requirement( hint = "AB", optional = true )
  146. A testHint;
  147. @Requirement( hint = "MISSING", optional = true )
  148. A testOptional = new ACImpl();
  149. @Requirement( role = A.class )
  150. Map<String, ?> testMap;
  151. @Requirement( hints = { "AC", "AB" } )
  152. Map<String, A> testSubMap;
  153. @Requirement
  154. Map<String, C> testEmptyMap;
  155. @Requirement( role = A.class )
  156. List<?> testList;
  157. @Requirement( hints = { "AC", "AA" } )
  158. List<? extends A> testSubList;
  159. @Requirement
  160. List<C> testEmptyList;
  161. @Requirement
  162. B testWildcard;
  163. @Requirement( optional = true )
  164. C optionalRequirement;
  165. }
  166. @Component( role = Component2.class )
  167. static class Component2
  168. {
  169. @Requirement
  170. void testZeroArgSetter()
  171. {
  172. throw new RuntimeException();
  173. }
  174. }
  175. @Component( role = Component3.class )
  176. static class Component3
  177. {
  178. @Requirement
  179. void testMultiArgSetter( final A a1, final A a2 )
  180. {
  181. throw new RuntimeException();
  182. }
  183. }
  184. @Component( role = Component4.class )
  185. static class Component4
  186. {
  187. @Requirement
  188. C testMissingRequirement;
  189. }
  190. @Component( role = Component5.class )
  191. static class Component5
  192. {
  193. @Requirement( hint = "B!" )
  194. B testNoSuchHint;
  195. }
  196. @Component( role = Component6.class )
  197. static class Component6
  198. {
  199. @Requirement( hints = { "AA", "AZ", "A!" } )
  200. Map<String, B> testNoSuchHint;
  201. }
  202. @Component( role = Component7.class )
  203. static class Component7
  204. {
  205. @Requirement( hints = { "AA", "AZ", "A!" } )
  206. List<C> testNoSuchHint;
  207. }
  208. @Component( role = Component8.class )
  209. static class Component8
  210. {
  211. @Requirement( hints = { "" } )
  212. List<A> testWildcardHint;
  213. }
  214. @Component( role = Component9.class )
  215. static class Component9
  216. {
  217. @Requirement( hint = "default" )
  218. B testNoDefault;
  219. }
  220. public void testRepeatInjection()
  221. {
  222. final Component1 duplicate = injector.getInstance( Component1.class );
  223. assertSame( component.testField, duplicate.testField );
  224. assertSame( component.testSetter, duplicate.testSetter );
  225. assertSame( component.testRole, duplicate.testRole );
  226. }
  227. public void testSingleRequirement()
  228. {
  229. assertEquals( AImpl.class, component.testField.getClass() );
  230. assertEquals( AImpl.class, component.testSetter.getClass() );
  231. assertEquals( AImpl.class, component.testRole.getClass() );
  232. assertEquals( ABImpl.class, component.testHint.getClass() );
  233. assertEquals( ACImpl.class, component.testOptional.getClass() );
  234. assertEquals( BImpl.class, component.testWildcard.getClass() );
  235. }
  236. public void testRequirementMap()
  237. {
  238. assertEquals( 5, component.testMap.size() );
  239. assertEquals( 0, component.testEmptyMap.size() );
  240. // check mapping
  241. assertEquals( AImpl.class, component.testMap.get( "default" ).getClass() );
  242. assertEquals( AAImpl.class, component.testMap.get( "AA" ).getClass() );
  243. assertEquals( ABImpl.class, component.testMap.get( "AB" ).getClass() );
  244. assertEquals( ACImpl.class, component.testMap.get( "AC" ).getClass() );
  245. // check key ordering is same as original map-binder
  246. final Iterator<String> keys = component.testMap.keySet().iterator();
  247. assertEquals( Hints.DEFAULT_HINT, keys.next() );
  248. assertEquals( "AA", keys.next() );
  249. assertEquals( "broken", keys.next() );
  250. assertEquals( "AB", keys.next() );
  251. assertEquals( "AC", keys.next() );
  252. assertFalse( keys.hasNext() );
  253. // check value ordering is same as original map-binder
  254. final Iterator<?> values = component.testMap.values().iterator();
  255. assertEquals( AImpl.class, values.next().getClass() );
  256. assertEquals( AAImpl.class, values.next().getClass() );
  257. try
  258. {
  259. values.next();
  260. fail( "Expected ProvisionException" );
  261. }
  262. catch ( final ProvisionException e )
  263. {
  264. }
  265. assertEquals( ABImpl.class, values.next().getClass() );
  266. assertEquals( ACImpl.class, values.next().getClass() );
  267. assertFalse( values.hasNext() );
  268. }
  269. public void testRequirementSubMap()
  270. {
  271. assertEquals( 2, component.testSubMap.size() );
  272. // check mapping
  273. assertEquals( ABImpl.class, component.testSubMap.get( "AB" ).getClass() );
  274. assertEquals( ACImpl.class, component.testSubMap.get( "AC" ).getClass() );
  275. // check key ordering is same as original map-binder
  276. final Iterator<String> keys = component.testSubMap.keySet().iterator();
  277. assertEquals( "AC", keys.next() );
  278. assertEquals( "AB", keys.next() );
  279. assertFalse( keys.hasNext() );
  280. // check value ordering is same as hints
  281. final Iterator<A> values = component.testSubMap.values().iterator();
  282. assertEquals( ACImpl.class, values.next().getClass() );
  283. assertEquals( ABImpl.class, values.next().getClass() );
  284. assertFalse( values.hasNext() );
  285. }
  286. public void testRequirementList()
  287. {
  288. assertEquals( 5, component.testList.size() );
  289. assertEquals( 0, component.testEmptyList.size() );
  290. // check ordering is same as original map-binder
  291. final Iterator<?> i = component.testList.iterator();
  292. assertEquals( AImpl.class, i.next().getClass() );
  293. assertEquals( AAImpl.class, i.next().getClass() );
  294. try
  295. {
  296. i.next();
  297. fail( "Expected ProvisionException" );
  298. }
  299. catch ( final ProvisionException e )
  300. {
  301. }
  302. assertEquals( ABImpl.class, i.next().getClass() );
  303. assertEquals( ACImpl.class, i.next().getClass() );
  304. assertFalse( i.hasNext() );
  305. }
  306. public void testRequirementSubList()
  307. {
  308. assertEquals( 2, component.testSubList.size() );
  309. // check ordering is same as hints
  310. final Iterator<? extends A> i = component.testSubList.iterator();
  311. assertEquals( ACImpl.class, i.next().getClass() );
  312. assertEquals( AAImpl.class, i.next().getClass() );
  313. assertFalse( i.hasNext() );
  314. }
  315. public void testZeroArgSetterError()
  316. {
  317. injector.getInstance( Component2.class );
  318. }
  319. public void testMultiArgSetterError()
  320. {
  321. injector.getInstance( Component3.class );
  322. }
  323. public void testMissingRequirement()
  324. {
  325. try
  326. {
  327. injector.getInstance( Component4.class );
  328. fail( "Expected error for missing requirement" );
  329. }
  330. catch ( final ProvisionException e )
  331. {
  332. }
  333. }
  334. public void testNoSuchHint()
  335. {
  336. try
  337. {
  338. injector.getInstance( Component5.class );
  339. fail( "Expected error for no such hint" );
  340. }
  341. catch ( final ProvisionException e )
  342. {
  343. }
  344. }
  345. public void testNoSuchMapHint()
  346. {
  347. try
  348. {
  349. injector.getInstance( Component6.class ).testNoSuchHint.toString();
  350. fail( "Expected error for no such hint" );
  351. }
  352. catch ( final ProvisionException e )
  353. {
  354. }
  355. }
  356. public void testNoSuchListHint()
  357. {
  358. try
  359. {
  360. injector.getInstance( Component7.class ).testNoSuchHint.toString();
  361. fail( "Expected error for no such hint" );
  362. }
  363. catch ( final ProvisionException e )
  364. {
  365. }
  366. }
  367. public void testWildcardHint()
  368. {
  369. final List<A> testList = injector.getInstance( Component8.class ).testWildcardHint;
  370. assertEquals( 5, testList.size() );
  371. // check ordering is same as original map-binder
  372. final Iterator<?> i = testList.iterator();
  373. assertEquals( AImpl.class, i.next().getClass() );
  374. assertEquals( AAImpl.class, i.next().getClass() );
  375. try
  376. {
  377. i.next();
  378. fail( "Expected ProvisionException" );
  379. }
  380. catch ( final ProvisionException e )
  381. {
  382. }
  383. assertEquals( ABImpl.class, i.next().getClass() );
  384. assertEquals( ACImpl.class, i.next().getClass() );
  385. assertFalse( i.hasNext() );
  386. }
  387. public void testNoDefault()
  388. {
  389. try
  390. {
  391. injector.getInstance( Component9.class );
  392. fail( "Expected error for missing default requirement" );
  393. }
  394. catch ( final ProvisionException e )
  395. {
  396. }
  397. }
  398. interface Alpha
  399. {
  400. }
  401. interface Omega
  402. {
  403. }
  404. interface Gamma
  405. {
  406. }
  407. @Component( role = Alpha.class )
  408. static class AlphaImpl
  409. implements Alpha
  410. {
  411. @Requirement
  412. Omega omega;
  413. }
  414. @Component( role = Omega.class )
  415. static class OmegaImpl
  416. implements Omega
  417. {
  418. @Requirement
  419. Alpha alpha;
  420. }
  421. @Inject
  422. Alpha alpha;
  423. @Inject
  424. Omega omega;
  425. public void testCircularity()
  426. {
  427. assertNotNull( ( (OmegaImpl) omega ).alpha );
  428. assertNotNull( ( (AlphaImpl) alpha ).omega );
  429. assertSame( alpha, ( (OmegaImpl) omega ).alpha );
  430. assertSame( omega, ( (AlphaImpl) alpha ).omega );
  431. }
  432. public void testBadDeferredRole()
  433. {
  434. try
  435. {
  436. injector.getInstance( Gamma.class );
  437. fail( "Expected ProvisionException" );
  438. }
  439. catch ( final ProvisionException e )
  440. {
  441. }
  442. }
  443. public void testPlexus121Compatibility()
  444. throws Exception
  445. {
  446. final List<URL> urls = new ArrayList<URL>();
  447. urls.add( new File( "target/dependency/plexus-component-annotations-1.2.1.jar" ).toURI().toURL() );
  448. Collections.addAll( urls, ( (URLClassLoader) getClass().getClassLoader() ).getURLs() );
  449. // check binding works with Plexus 1.2.1 annotations: @Requirement does not have optional setting
  450. final ClassLoader legacyLoader = new URLClassLoader( urls.toArray( new URL[urls.size()] ), null )
  451. {
  452. @Override
  453. protected synchronized Class<?> loadClass( final String name, final boolean resolve )
  454. throws ClassNotFoundException
  455. {
  456. if ( name.contains( "cobertura" ) )
  457. {
  458. return PlexusRequirementTest.class.getClassLoader().loadClass( name );
  459. }
  460. return super.loadClass( name, resolve );
  461. }
  462. };
  463. legacyLoader.loadClass( SimpleRequirementExample.class.getName() ).newInstance();
  464. }
  465. @SuppressWarnings( "unchecked" )
  466. static <S, T extends S> DeferredClass<T> defer( final Class<S> clazz )
  467. {
  468. return (DeferredClass<T>) new URLClassSpace( TestCase.class.getClassLoader() ).deferLoadClass( clazz.getName() );
  469. }
  470. }