PageRenderTime 43ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/geotools-9.2/modules/library/metadata/src/test/java/org/geotools/factory/FactoryRegistryTest.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 337 lines | 165 code | 19 blank | 153 comment | 4 complexity | 68dd50cde6b3d63d80a4f54df77ebf74 MD5 | raw file
  1. /*
  2. * GeoTools - The Open Source Java GIS Toolkit
  3. * http://geotools.org
  4. *
  5. * (C) 2005-2008, Open Source Geospatial Foundation (OSGeo)
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation;
  10. * version 2.1 of the License.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. */
  17. package org.geotools.factory;
  18. import static org.junit.Assert.*;
  19. import java.net.MalformedURLException;
  20. import java.net.URL;
  21. import java.net.URLClassLoader;
  22. import java.util.ArrayList;
  23. import java.util.Collections;
  24. import java.util.HashSet;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Set;
  28. import org.geotools.resources.LazySet;
  29. import org.junit.Before;
  30. import org.junit.Test;
  31. /**
  32. * Tests {@link FactoryRegistry} implementation.
  33. *
  34. *
  35. *
  36. * @source $URL$
  37. * @version $Id$
  38. * @author Martin Desruisseaux
  39. */
  40. public final class FactoryRegistryTest {
  41. /**
  42. * Ensures that class {@link Hints} is loaded before {@link DummyFactory}.
  43. * It is not needed for normal execution, but Maven seems to mess with class loaders.
  44. */
  45. @Before
  46. public void ensureHintsLoaded() {
  47. assertNotNull(Hints.DATUM_FACTORY.toString());
  48. }
  49. /**
  50. * Creates the factory registry to test. The tests performed in this method are more
  51. * J2SE tests than Geotools implementation tests. We basically just ensure that we
  52. * have setup the service registry properly.
  53. * <p>
  54. * Factories are specified in arguments as {@link Factory} objects in order to avoid
  55. * the {@link DummyClass} to be initialized before {@link Hints}. This is not a problem
  56. * for normal execution, but Maven seems to mess with class loaders.
  57. *
  58. * @param creator {@code true} if the registry should be an instance of {@link FactoryCreator}.
  59. */
  60. private FactoryRegistry getRegistry(final boolean creator,
  61. final Factory factory1,
  62. final Factory factory2,
  63. final Factory factory3)
  64. {
  65. @SuppressWarnings("unchecked")
  66. final Set<Class<?>> categories = (Set) Collections.singleton(DummyFactory.class);
  67. // The above line fails without the cast, I don't know why...
  68. final FactoryRegistry registry;
  69. if (creator) {
  70. registry = new FactoryCreator(categories);
  71. } else {
  72. registry = new FactoryRegistry(categories);
  73. }
  74. registry.registerServiceProvider(factory1);
  75. registry.registerServiceProvider(factory2);
  76. registry.registerServiceProvider(factory3);
  77. assertTrue(registry.setOrdering(DummyFactory.class, (DummyFactory)factory1, (DummyFactory)factory2));
  78. assertTrue(registry.setOrdering(DummyFactory.class, (DummyFactory)factory2, (DummyFactory)factory3));
  79. assertTrue(registry.setOrdering(DummyFactory.class, (DummyFactory)factory1, (DummyFactory)factory3));
  80. final List<?> factories = new ArrayList<Object>(new LazySet<Object>(
  81. registry.getServiceProviders(DummyFactory.class, null, null)));
  82. assertTrue(factories.contains(factory1));
  83. assertTrue(factories.contains(factory2));
  84. assertTrue(factories.contains(factory3));
  85. assertTrue(factories.indexOf(factory1) < factories.indexOf(factory2));
  86. assertTrue(factories.indexOf(factory2) < factories.indexOf(factory3));
  87. return registry;
  88. }
  89. /**
  90. * Tests the {@link FactoryRegistry#getProvider} method.
  91. * Note that the tested method do not create any new factory.
  92. * If no registered factory matching the hints is found, an exception is expected.
  93. * <br><br>
  94. * Three factories are initially registered: factory #1, #2 and #3.
  95. *
  96. * Factory #1 has no dependency.
  97. * Factory #2 uses factory #1.
  98. * Factory #3 uses factory #2, which implies an indirect dependency to factory #1.
  99. *
  100. * Additionnaly, factory #1 uses a KEY_INTERPOLATION hint.
  101. */
  102. @Test
  103. public void testGetProvider() {
  104. final Hints.Key key = DummyFactory.DUMMY_FACTORY;
  105. final DummyFactory factory1 = new DummyFactory.Example1();
  106. final DummyFactory factory2 = new DummyFactory.Example2();
  107. final DummyFactory factory3 = new DummyFactory.Example3();
  108. final FactoryRegistry registry = getRegistry(false, factory1, factory2, factory3);
  109. Hints hints;
  110. DummyFactory factory;
  111. // ------------------------------------------------
  112. // PART 1: SIMPLE HINT (not a Factory hint)
  113. // ------------------------------------------------
  114. /*
  115. * No hints. The fist factory should be selected.
  116. */
  117. hints = null;
  118. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  119. assertSame("No preferences; should select the first factory. ", factory1, factory);
  120. /*
  121. * A hint compatible with one of our factories. Factory #1 declares explicitly that it uses
  122. * a bilinear interpolation, which is compatible with user's hints. All other factories are
  123. * indifferent. Since factory #1 is the first one in the list, it should be selected.
  124. */
  125. hints = new Hints(Hints.KEY_INTERPOLATION, Hints.VALUE_INTERPOLATION_BILINEAR);
  126. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  127. assertSame("First factory matches; it should be selected. ", factory1, factory);
  128. /*
  129. * A hint incompatible with all our factories. Factory #1 is the only one to defines
  130. * explicitly a KEY_INTERPOLATION hint, but all other factories depend on factory #1
  131. * either directly (factory #2) or indirectly (factory #3, which depends on #2).
  132. */
  133. hints = new Hints(Hints.KEY_INTERPOLATION, Hints.VALUE_INTERPOLATION_BICUBIC);
  134. try {
  135. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  136. fail("Found factory "+factory+", while the hint should have been rejected.");
  137. } catch (FactoryNotFoundException exception) {
  138. // This is the expected exception. Continue...
  139. }
  140. /*
  141. * Add a new factory implementation, and try again with exactly the same hints
  142. * than the previous test. This time, the new factory should be selected since
  143. * this one doesn't have any dependency toward factory #1.
  144. */
  145. final DummyFactory factory4 = new DummyFactory.Example4();
  146. registry.registerServiceProvider(factory4);
  147. assertTrue(registry.setOrdering(DummyFactory.class, factory1, factory4));
  148. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  149. assertSame("The new factory should be selected. ", factory4, factory);
  150. // ----------------------------
  151. // PART 2: FACTORY HINT
  152. // ----------------------------
  153. /*
  154. * Trivial case: user gives explicitly a factory instance.
  155. */
  156. DummyFactory explicit = new DummyFactory.Example3();
  157. hints = new Hints(DummyFactory.DUMMY_FACTORY, explicit);
  158. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  159. assertSame("The user-specified factory should have been selected. ", explicit, factory);
  160. /*
  161. * User specifies the expected implementation class rather than an instance.
  162. */
  163. hints = new Hints(DummyFactory.DUMMY_FACTORY, DummyFactory.Example2.class);
  164. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  165. assertSame("Factory of class #2 were requested. ", factory2, factory);
  166. /*
  167. * Same as above, but with classes specified in an array.
  168. */
  169. hints = new Hints(DummyFactory.DUMMY_FACTORY, new Class<?>[] {
  170. DummyFactory.Example3.class,
  171. DummyFactory.Example2.class
  172. });
  173. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  174. assertSame("Factory of class #3 were requested. ", factory3, factory);
  175. /*
  176. * The following hint should be ignored by factory #1, since this factory doesn't have
  177. * any dependency to the INTERNAL_FACTORY hint. Since factory #1 is first in the ordering,
  178. * it should be selected.
  179. */
  180. hints = new Hints(DummyFactory.INTERNAL_FACTORY, DummyFactory.Example2.class);
  181. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  182. assertSame("Expected factory #1. ", factory1, factory);
  183. /*
  184. * If the user really wants some factory that do have a dependency to factory #2, he should
  185. * specifies in a DUMMY_FACTORY hint the implementation classes (or a common super-class or
  186. * interface) that do care about the INTERNAL_FACTORY hint. Note that this extra step should
  187. * not be a big deal in most real application, because:
  188. *
  189. * 1) Either all implementations have this dependency (for example it would be
  190. * unusual to see a DatumAuthorityFactory without a DatumFactory dependency);
  191. *
  192. * 2) or the user really know the implementation he wants (for example if he specifies a
  193. * JTS CoordinateSequenceFactory, he probably wants to use the JTS GeometryFactory).
  194. *
  195. * In the particular case of this test suite, this extra step would not be needed
  196. * neither if factory #1 was last in the ordering rather than first.
  197. */
  198. final Hints implementations = new Hints(DummyFactory.DUMMY_FACTORY, new Class[]
  199. {DummyFactory.Example2.class, DummyFactory.Example3.class});
  200. /*
  201. * Now search NOT for factory #1, but rather for a factory using #1 internally.
  202. * This is the case of factory #2.
  203. */
  204. hints = new Hints(DummyFactory.INTERNAL_FACTORY, DummyFactory.Example1.class);
  205. hints.add(implementations);
  206. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  207. assertSame("Expected a factory using #1 internally. ", factory2, factory);
  208. }
  209. /**
  210. * Tests the {@link FactoryCreator#getProvider} method.
  211. * This test tries again the cases that was expected to throws an exception in
  212. * {@link #testGetProvider}. But now, those cases are expected to creates automatically
  213. * new factory instances instead of throwing an exception.
  214. */
  215. @Test
  216. public void testCreateProvider() {
  217. final Hints.Key key = DummyFactory.DUMMY_FACTORY;
  218. final DummyFactory factory1 = new DummyFactory.Example1();
  219. final DummyFactory factory2 = new DummyFactory.Example2();
  220. final DummyFactory factory3 = new DummyFactory.Example3();
  221. final FactoryRegistry registry = getRegistry(true, factory1, factory2, factory3);
  222. Hints hints;
  223. DummyFactory factory;
  224. /*
  225. * Same tests than above (at least some of them).
  226. * See comments in 'testGetProvider()' for explanation.
  227. */
  228. hints = new Hints(Hints.KEY_INTERPOLATION, Hints.VALUE_INTERPOLATION_BILINEAR);
  229. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  230. assertSame("First factory matches; it should be selected. ", factory1, factory);
  231. hints = new Hints(DummyFactory.DUMMY_FACTORY, DummyFactory.Example2.class);
  232. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  233. assertSame("Factory of class #2 were requested. ", factory2, factory);
  234. /*
  235. * The following case was throwing an exception in testGetProvider(). It should fails again
  236. * here, but for a different reason. FactoryCreator is unable to creates automatically a new
  237. * factory instance, since we gave no implementation hint and no registered factory have a
  238. * constructor expecting a Hints argument.
  239. */
  240. hints = new Hints(Hints.KEY_INTERPOLATION, Hints.VALUE_INTERPOLATION_BICUBIC);
  241. try {
  242. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  243. fail("Found or created factory "+factory+", while it should not have been allowed.");
  244. } catch (FactoryNotFoundException exception) {
  245. // This is the expected exception. Continue...
  246. }
  247. /*
  248. * Register a DummyFactory with a constructor expecting a Hints argument, and try again
  249. * with the same hints. Now it should creates a new factory instance, because we are using
  250. * FactoryCreator instead of FactoryRegistry and an appropriate constructor is found.
  251. * Note that an AssertionFailedError should be thrown if the no-argument constructor of
  252. * Example5 is invoked, since the constructor with a Hints argument should have priority.
  253. */
  254. final DummyFactory factory5 = new DummyFactory.Example5(null);
  255. registry.registerServiceProvider(factory5);
  256. assertTrue(registry.setOrdering(DummyFactory.class, factory1, factory5));
  257. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  258. assertSame ("An instance of Factory #5 should have been created.", factory5.getClass(), factory.getClass());
  259. assertNotSame("A NEW instance of Factory #5 should have been created", factory5, factory);
  260. /*
  261. * Tries again with a class explicitly specified as an implementation hint.
  262. * It doesn't matter if this class is registered or not.
  263. */
  264. hints.put(DummyFactory.DUMMY_FACTORY, DummyFactory.Example4.class);
  265. factory = registry.getServiceProvider(DummyFactory.class, null, hints, key);
  266. assertEquals("An instance of Factory #4 should have been created.", DummyFactory.Example4.class, factory.getClass());
  267. }
  268. @Test
  269. public void testLookupWithExtendedClasspath() {
  270. URL url = getClass().getResource("foo.jar");
  271. assertNotNull(url);
  272. FactoryRegistry reg = new FactoryCreator( DummyInterface.class );
  273. Iterator it = reg.getServiceProviders(DummyInterface.class, false);
  274. assertFalse(it.hasNext());
  275. URLClassLoader cl = new URLClassLoader(new URL[]{url});
  276. GeoTools.addClassLoader(cl);
  277. reg.scanForPlugins();
  278. // collect the classes
  279. it = reg.getServiceProviders(DummyInterface.class, false);
  280. Set<String> classes = new HashSet<String>();
  281. while(it.hasNext()) {
  282. classes.add(it.next().getClass().getName());
  283. }
  284. assertEquals(2, classes.size());
  285. assertTrue(classes.contains("pkg.Foo"));
  286. assertTrue(classes.contains("org.geotools.factory.DummyInterfaceImpl"));
  287. }
  288. /**
  289. * Tests for GEOT-2817
  290. * @throws MalformedURLException
  291. * @throws ClassNotFoundException
  292. */
  293. @Test
  294. public void testLookupWithSameFactoryInTwoClassLoaders() throws MalformedURLException, ClassNotFoundException {
  295. // create url to this project's classes
  296. URL projectClasses = getClass().getResource("/");
  297. // create 2 classloaders with parent null to avoid delegation to the system class loader !
  298. // this occurs in reality with split class loader hierarchies (e.g. GWT plugin and
  299. // some application servers)
  300. URLClassLoader cl1 = new URLClassLoader(new URL[] { projectClasses }, null);
  301. URLClassLoader cl2 = new URLClassLoader(new URL[] { projectClasses }, null);
  302. // extend with both class loaders
  303. GeoTools.addClassLoader(cl1);
  304. GeoTools.addClassLoader(cl2);
  305. // code below was throwing ClassCastException (before java 7) prior to adding isAssignableFrom() check (line 862)
  306. for (int i = 0; i < 2; i++) {
  307. ClassLoader loader = (i == 0 ? cl1 : cl2);
  308. Class dummy = loader.loadClass("org.geotools.factory.DummyInterface");
  309. FactoryRegistry reg = new FactoryCreator(dummy);
  310. reg.scanForPlugins();
  311. Iterator it = reg.getServiceProviders(dummy, false);
  312. assertTrue(it.hasNext());
  313. Object next = it.next();
  314. // factory class should have same class loader as interface
  315. assertSame(loader, next.getClass().getClassLoader());
  316. }
  317. }
  318. }