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.InvocationTargetException;
24  import java.lang.reflect.Method;
25  import java.util.Iterator;
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.ReflectionUtils;
31  
32  
33  /**
34   * Creates the surefire provider.
35   * <p/>
36   *
37   * @author Kristian Rosenvold
38   */
39  public class ProviderFactory
40  {
41      private final StartupConfiguration startupConfiguration;
42  
43      private final ProviderConfiguration providerConfiguration;
44  
45      private final ClassLoader surefireClassLoader;
46  
47      private final ClassLoader testsClassLoader;
48  
49      private final SurefireReflector surefireReflector;
50  
51      private final Object reporterManagerFactory;
52  
53      private static final Class[] invokeParamaters = new Class[]{ Object.class };
54  
55  
56      public ProviderFactory( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
57                              ClassLoader surefireClassLoader, ClassLoader testsClassLoader,
58                              Object reporterManagerFactory )
59      {
60          this.providerConfiguration = providerConfiguration;
61          this.surefireClassLoader = surefireClassLoader;
62          this.startupConfiguration = startupConfiguration;
63          this.surefireReflector = new SurefireReflector( surefireClassLoader );
64          this.testsClassLoader = testsClassLoader;
65          this.reporterManagerFactory = reporterManagerFactory;
66      }
67  
68      public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader,
69                                              ClassLoader surefireClassLoader, Object factory,
70                                              ProviderConfiguration providerConfiguration, boolean insideFork,
71                                              StartupConfiguration startupConfiguration1, boolean restoreStreams )
72          throws TestSetFailedException, InvocationTargetException
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          finally
89          {
90              if ( restoreStreams && System.getSecurityManager() == null )
91              {
92                  System.setOut( orgSystemOut );
93                  System.setErr( orgSystemErr );
94              }
95          }
96      }
97  
98      public SurefireProvider createProvider( boolean isInsideFork )
99      {
100         ClassLoader systemClassLoader = java.lang.Thread.currentThread().getContextClassLoader();
101         Thread.currentThread().setContextClassLoader( surefireClassLoader );
102 
103         StartupConfiguration starterConfiguration = startupConfiguration;
104 
105         final Object o =
106             surefireReflector.createBooterConfiguration( surefireClassLoader, reporterManagerFactory, isInsideFork );
107         surefireReflector.setTestSuiteDefinitionAware( o, providerConfiguration.getTestSuiteDefinition() );
108         surefireReflector.setProviderPropertiesAware( o, providerConfiguration.getProviderProperties() );
109         surefireReflector.setReporterConfigurationAware( o, providerConfiguration.getReporterConfiguration() );
110         surefireReflector.setTestClassLoaderAware( o, surefireClassLoader, testsClassLoader );
111         surefireReflector.setTestArtifactInfoAware( o, providerConfiguration.getTestArtifact() );
112         surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
113         surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
114 
115         Object provider = surefireReflector.instantiateProvider( starterConfiguration.getProviderClassName(), o );
116         Thread.currentThread().setContextClassLoader( systemClassLoader );
117 
118         return new ProviderProxy( provider, testsClassLoader );
119     }
120 
121 
122     private class ProviderProxy
123         implements SurefireProvider
124     {
125         private final Object providerInOtherClassLoader;
126 
127         private final ClassLoader testsClassLoader;
128 
129 
130         private ProviderProxy( Object providerInOtherClassLoader, ClassLoader testsClassLoader )
131         {
132             this.providerInOtherClassLoader = providerInOtherClassLoader;
133             this.testsClassLoader = testsClassLoader;
134         }
135 
136         public Iterator getSuites()
137         {
138             ClassLoader current = swapClassLoader( testsClassLoader );
139             try
140             {
141                 return (Iterator) ReflectionUtils.invokeGetter( providerInOtherClassLoader, "getSuites" );
142             }
143             finally
144             {
145                 Thread.currentThread().setContextClassLoader( current );
146             }
147         }
148 
149         public RunResult invoke( Object forkTestSet )
150             throws TestSetFailedException, ReporterException, InvocationTargetException
151         {
152             ClassLoader current = swapClassLoader( testsClassLoader );
153             try
154             {
155                 final Method invoke =
156                     ReflectionUtils.getMethod( providerInOtherClassLoader.getClass(), "invoke", invokeParamaters );
157 
158                 final Object result = ReflectionUtils.invokeMethodWithArray2( providerInOtherClassLoader, invoke,
159                                                                               new Object[]{ forkTestSet } );
160                 return (RunResult) surefireReflector.convertIfRunResult( result );
161             }
162             finally
163             {
164                 if ( System.getSecurityManager() == null )
165                 {
166                     Thread.currentThread().setContextClassLoader( current );
167                 }
168             }
169 
170         }
171 
172         private ClassLoader swapClassLoader( ClassLoader newClassLoader )
173         {
174             ClassLoader current = Thread.currentThread().getContextClassLoader();
175             Thread.currentThread().setContextClassLoader( newClassLoader );
176             return current;
177         }
178 
179         public void cancel()
180         {
181             final Method invoke =
182                 ReflectionUtils.getMethod( providerInOtherClassLoader.getClass(), "cancel", new Class[]{ } );
183             ReflectionUtils.invokeMethodWithArray( providerInOtherClassLoader, invoke, null );
184         }
185     }
186 }