View Javadoc

1   package org.apache.maven.surefire.booter;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.PrintStream;
23  import java.lang.reflect.Method;
24  import java.util.Iterator;
25  
26  import org.apache.maven.surefire.providerapi.SurefireProvider;
27  import org.apache.maven.surefire.report.ReporterException;
28  import org.apache.maven.surefire.suite.RunResult;
29  import org.apache.maven.surefire.testset.TestSetFailedException;
30  import org.apache.maven.surefire.util.NestedRuntimeException;
31  import org.apache.maven.surefire.util.ReflectionUtils;
32  
33  
34  /**
35   * Creates the surefire provider.
36   * <p/>
37   *
38   * @author Kristian Rosenvold
39   */
40  public class ProviderFactory
41  {
42      private final StartupConfiguration startupConfiguration;
43  
44      private final ProviderConfiguration providerConfiguration;
45  
46      private final ClassLoader surefireClassLoader;
47  
48      private final ClassLoader testsClassLoader;
49  
50      private final SurefireReflector surefireReflector;
51  
52      private final Object reporterManagerFactory;
53  
54      private static final Class[] invokeParamaters = new Class[]{ Object.class };
55  
56  
57      public ProviderFactory( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
58                              ClassLoader surefireClassLoader, ClassLoader testsClassLoader,
59                              Object reporterManagerFactory )
60      {
61          this.providerConfiguration = providerConfiguration;
62          this.surefireClassLoader = surefireClassLoader;
63          this.startupConfiguration = startupConfiguration;
64          this.surefireReflector = new SurefireReflector( surefireClassLoader );
65          this.testsClassLoader = testsClassLoader;
66          this.reporterManagerFactory = reporterManagerFactory;
67      }
68  
69      public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader,
70                                              ClassLoader surefireClassLoader, Object factory,
71                                              ProviderConfiguration providerConfiguration, boolean insideFork,
72                                              StartupConfiguration startupConfiguration1 )
73      {
74          final PrintStream orgSystemOut = System.out;
75          final PrintStream orgSystemErr = System.err;
76          // Note that System.out/System.err are also read in the "ReporterConfiguration" instatiation
77          // in createProvider below. These are the same values as here.
78  
79          ProviderFactory providerFactory =
80              new ProviderFactory( startupConfiguration1, providerConfiguration, surefireClassLoader, testsClassLoader,
81                                   factory );
82          final SurefireProvider provider = providerFactory.createProvider( insideFork );
83  
84          try
85          {
86              return provider.invoke( testSet );
87          }
88          catch ( TestSetFailedException e )
89          {
90              throw new NestedRuntimeException( e );
91          }
92          catch ( ReporterException e )
93          {
94              throw new NestedRuntimeException( e );
95          }
96          finally
97          {
98              if ( System.getSecurityManager() == null )
99              {
100                 System.setOut( orgSystemOut );
101                 System.setErr( orgSystemErr );
102             }
103         }
104     }
105 
106     public SurefireProvider createProvider( boolean isInsideFork )
107     {
108         ClassLoader context = java.lang.Thread.currentThread().getContextClassLoader();
109         Thread.currentThread().setContextClassLoader( surefireClassLoader );
110 
111         StartupConfiguration starterConfiguration = startupConfiguration;
112 
113         final Object o =
114             surefireReflector.createBooterConfiguration( surefireClassLoader, reporterManagerFactory, isInsideFork );
115         surefireReflector.setTestSuiteDefinitionAware( o, providerConfiguration.getTestSuiteDefinition() );
116         surefireReflector.setProviderPropertiesAware( o, providerConfiguration.getProviderProperties() );
117         surefireReflector.setReporterConfigurationAware( o, providerConfiguration.getReporterConfiguration() );
118         surefireReflector.setTestClassLoaderAware( o, surefireClassLoader, testsClassLoader );
119         surefireReflector.setTestArtifactInfoAware( o, providerConfiguration.getTestArtifact() );
120         surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
121         surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
122 
123         Object provider = surefireReflector.instantiateProvider( starterConfiguration.getProviderClassName(), o );
124         Thread.currentThread().setContextClassLoader( context );
125 
126         return new ProviderProxy( provider, testsClassLoader );
127     }
128 
129 
130     private class ProviderProxy
131         implements SurefireProvider
132     {
133         private final Object providerInOtherClassLoader;
134 
135         private final ClassLoader testsClassLoader;
136 
137 
138         private ProviderProxy( Object providerInOtherClassLoader, ClassLoader testsClassLoader )
139         {
140             this.providerInOtherClassLoader = providerInOtherClassLoader;
141             this.testsClassLoader = testsClassLoader;
142         }
143 
144         public Iterator getSuites()
145         {
146             ClassLoader current = swapClassLoader( testsClassLoader );
147             try
148             {
149                 return (Iterator) ReflectionUtils.invokeGetter( providerInOtherClassLoader, "getSuites" );
150             }
151             finally
152             {
153                 Thread.currentThread().setContextClassLoader( current );
154             }
155         }
156 
157         public RunResult invoke( Object forkTestSet )
158             throws TestSetFailedException, ReporterException
159         {
160             ClassLoader current = swapClassLoader( testsClassLoader );
161             try
162             {
163                 final Method invoke =
164                     ReflectionUtils.getMethod( providerInOtherClassLoader.getClass(), "invoke", invokeParamaters );
165 
166                 final Object result = ReflectionUtils.invokeMethodWithArray( providerInOtherClassLoader, invoke,
167                                                                              new Object[]{ forkTestSet } );
168                 return (RunResult) surefireReflector.convertIfRunResult( result );
169             }
170             finally
171             {
172                 Thread.currentThread().setContextClassLoader( current );
173             }
174 
175         }
176 
177         private ClassLoader swapClassLoader( ClassLoader newClassLoader )
178         {
179             ClassLoader current = Thread.currentThread().getContextClassLoader();
180             Thread.currentThread().setContextClassLoader( newClassLoader );
181             return current;
182         }
183 
184         public void cancel()
185         {
186             final Method invoke =
187                 ReflectionUtils.getMethod( providerInOtherClassLoader.getClass(), "cancel", new Class[]{ } );
188             ReflectionUtils.invokeMethodWithArray( providerInOtherClassLoader, invoke, null );
189         }
190     }
191 }