hibernate/hibernate-search — pull request #288 by rhauch (2012-05-05 00:58:50+00:00)
Title: HSEARCH-1115 Changed use of ReflectHelper to specify classloader

Two uses of `ReflectHelper.classForName(String)` were changed to use the `classForName(String,Class)` form instead. In the latter method, if the class cannot be found on the thread's context class loader then the class will be loaded using the classloader of the class specified in the second parameter.

In one of the cases (`DocumentBuilderHelper`), the `DocumentBuilderHelper` class was passed as the second parameter, meaning that the same classloader used to load the Hibernate Search classes will be used.

In the second case (`ConfigContext`), the second parameter is the class of the `SearchConfiguration` implementation that was supplied to the `ConfigContext` constructor. This is better than using the `ConfigContext` class directly, since the `SearchConfiguration` implementation will be provided by the components using the `SearchFactoryBuilder` to build a `SearchFactory`. This means that the components' classloader will be used to load the `Analyzer` implementation class.

There are a few other uses of `ReflectionHelper.classForName(String)` in the Hibernate Search codebase, but I don't think they require the same classloading logic.

When used in a Java SE environment, there is no net difference in classloading behavior. However, in JBoss AS7 (or even OSGi) the different classloaders have a significant effect. Specifically, when used in JBoss AS7, the modules might look like this (where "-->" signifies 'depends on'):

org.foo (uses Hibernate Search, implements SearchConfiguration)
--> org.hibernate.search.engine
--> org.hibernate (specifically the hibernate-commons-annotations JAR)
--> org.apache.lucene
--> others

In this case, the result of the code before this change is that `ConfigContext` would expect to find the Analyzer implementation using the `org.hibernate` module (where the `ReflectHelper` class exists), which does cannot see any of the `Analyzer` implementations in `org.apache.lucene` nor any implementations provided by `org.foo`. After this change, `ConfigContext` uses `org.foo` class loader (since that's where the `SearchConfiguration` implementation class exists), and thus can see any `Analyzer` implementation provide in `org.foo`, `org.hibernate.search.engine`, `org.apache.lucene`, `org.hibernate` (if there were any), or any of the other modules.

All unit tests run by the build pass successfully with these changes.