3
3
import com .google .inject .Injector ;
4
4
import cucumber .runtime .Env ;
5
5
import cucumber .runtime .java .guice .InjectorSource ;
6
+ import org .junit .Assert ;
6
7
import org .junit .Test ;
7
8
9
+ import java .io .ByteArrayOutputStream ;
10
+ import java .io .File ;
11
+ import java .io .FileInputStream ;
12
+ import java .io .FileNotFoundException ;
13
+ import java .net .URL ;
14
+ import java .net .URLClassLoader ;
8
15
import java .util .Properties ;
9
16
10
17
import static org .hamcrest .CoreMatchers .instanceOf ;
@@ -110,4 +117,62 @@ public void failsToInstantiateClassWithNoDefaultConstructor() throws Exception {
110
117
assertThat (exception .getCause (), instanceOf (InstantiationException .class ));
111
118
}
112
119
}
120
+
121
+ /**
122
+ * <p>Simulates enterprise applications which often use a hierarchy of classloaders.
123
+ *
124
+ * <p>MyChildClassLoader is the only classloader with knowledge of c.r.j.guice.impl.LivesInChildClassLoader
125
+ *
126
+ * <p>The bytecode of LivesInChildClassLoader is intentionally renamed to 'LivesInChildClassLoader.class.txt' to prevent
127
+ * this test's ClassLoader from resolving it.
128
+ *
129
+ * <p>If InjectorSourceFactory calls Class#forName without an explicit ClassLoader argument, which is the behavior of
130
+ * 1.2.4 and earlier, Class#forName will default to the test's ClassLoader which has no knowledge
131
+ * of class LivesInChildClassLoader and the test will fail.
132
+ *
133
+ * <p>See <a href="https://github.com/cucumber/cucumber-jvm/issues/1036">https://github.com/cucumber/cucumber-jvm/issues/1036</a>
134
+ * @throws Exception
135
+ */
136
+ @ Test
137
+ public void instantiateClassInChildClassLoader () throws Exception {
138
+ ClassLoader childClassLoader = new MyChildClassLoader (this .getClass ().getClassLoader ());
139
+ Thread .currentThread ().setContextClassLoader ( childClassLoader );
140
+
141
+ Properties properties = new Properties ();
142
+ properties .setProperty (InjectorSourceFactory .GUICE_INJECTOR_SOURCE_KEY , "cucumber.runtime.java.guice.impl.LivesInChildClassLoader" );
143
+ InjectorSourceFactory injectorSourceFactory = createInjectorSourceFactory (properties );
144
+
145
+ assertThat (injectorSourceFactory .create (), is (instanceOf (InjectorSource .class )));
146
+ }
147
+
148
+ private static class MyChildClassLoader extends ClassLoader {
149
+ public MyChildClassLoader ( ClassLoader parent ) {
150
+ super (parent );
151
+ }
152
+
153
+ @ Override
154
+ protected Class <?> loadClass ( String name , boolean resolve ) throws ClassNotFoundException {
155
+ if ( name .equals ( "cucumber.runtime.java.guice.impl.LivesInChildClassLoader" ) ) {
156
+ String filename = getClass ().getClassLoader ().getResource ("cucumber/runtime/java/guice/impl/LivesInChildClassLoader.class.txt" ).getFile ();
157
+ File file = new File ( filename );
158
+ try {
159
+ FileInputStream in = new FileInputStream ( file );
160
+ byte [] bytes = new byte [1024 ];
161
+ ByteArrayOutputStream content = new ByteArrayOutputStream ();
162
+ while ( true ) {
163
+ int iLen = in .read (bytes );
164
+ content .write ( bytes , 0 , iLen );
165
+ if ( iLen < 1024 ) {
166
+ break ;
167
+ }
168
+ }
169
+ byte [] bytecode = content .toByteArray ();
170
+ return defineClass ( name , bytecode , 0 , bytecode .length );
171
+ } catch (Exception e ) {
172
+ throw new RuntimeException ( e );
173
+ }
174
+ }
175
+ return super .loadClass (name , resolve );
176
+ }
177
+ }
113
178
}
0 commit comments