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 org.apache.maven.surefire.providerapi.ProviderParameters;
23  import org.apache.maven.surefire.report.ReporterConfiguration;
24  import org.apache.maven.surefire.suite.RunResult;
25  import org.apache.maven.surefire.testset.DirectoryScannerParameters;
26  import org.apache.maven.surefire.testset.TestArtifactInfo;
27  import org.apache.maven.surefire.testset.TestRequest;
28  import org.apache.maven.surefire.util.ReflectionUtils;
29  import org.apache.maven.surefire.util.SurefireReflectionException;
30  
31  import java.io.File;
32  import java.lang.reflect.Constructor;
33  import java.lang.reflect.InvocationHandler;
34  import java.lang.reflect.Method;
35  import java.util.List;
36  import java.util.Properties;
37  
38  /**
39   * Does reflection based invocation of the surefire methods.
40   * <p/>
41   * This is to avoid compilications with linkage issues
42   *
43   * @author Kristian Rosenvold
44   */
45  public class SurefireReflector
46  {
47      private final ClassLoader classLoader;
48  
49      private final Class reporterConfiguration;
50  
51      private final Class testRequest;
52  
53      private final Class testArtifactInfo;
54  
55      private final Class testArtifactInfoAware;
56  
57      private final Class directoryScannerParameters;
58  
59      private final Class directoryScannerParametersAware;
60  
61      private final Class testSuiteDefinitionAware;
62  
63      private final Class testClassLoaderAware;
64  
65      private final Class reporterConfigurationAware;
66  
67      private final Class providerPropertiesAware;
68  
69      private final Class runResult;
70  
71      private final Class booterParameters;
72  
73      public SurefireReflector( ClassLoader surefireClassLoader )
74      {
75          this.classLoader = surefireClassLoader;
76          try
77          {
78              reporterConfiguration = surefireClassLoader.loadClass( ReporterConfiguration.class.getName() );
79              testRequest = surefireClassLoader.loadClass( TestRequest.class.getName() );
80              testArtifactInfo = surefireClassLoader.loadClass( TestArtifactInfo.class.getName() );
81              testArtifactInfoAware = surefireClassLoader.loadClass( TestArtifactInfoAware.class.getName() );
82              directoryScannerParameters = surefireClassLoader.loadClass( DirectoryScannerParameters.class.getName() );
83              directoryScannerParametersAware =
84                  surefireClassLoader.loadClass( DirectoryScannerParametersAware.class.getName() );
85              testSuiteDefinitionAware = surefireClassLoader.loadClass( TestRequestAware.class.getName() );
86              testClassLoaderAware = surefireClassLoader.loadClass( SurefireClassLoadersAware.class.getName() );
87              reporterConfigurationAware = surefireClassLoader.loadClass( ReporterConfigurationAware.class.getName() );
88              providerPropertiesAware = surefireClassLoader.loadClass( ProviderPropertiesAware.class.getName() );
89              runResult = surefireClassLoader.loadClass( RunResult.class.getName() );
90              booterParameters = surefireClassLoader.loadClass( ProviderParameters.class.getName() );
91          }
92          catch ( ClassNotFoundException e )
93          {
94              throw new SurefireReflectionException( e );
95          }
96      }
97  
98      public Object convertIfRunResult( Object result )
99      {
100         if ( result == null || !isRunResult( result ) )
101         {
102             return result;
103         }
104         final Integer getCompletedCount1 = (Integer) ReflectionUtils.invokeGetter( result, "getCompletedCount" );
105         final Integer getErrors = (Integer) ReflectionUtils.invokeGetter( result, "getErrors" );
106         final Integer getSkipped = (Integer) ReflectionUtils.invokeGetter( result, "getSkipped" );
107         final Integer getFailures = (Integer) ReflectionUtils.invokeGetter( result, "getFailures" );
108         return new RunResult( getCompletedCount1.intValue(), getErrors.intValue(), getFailures.intValue(),
109                               getSkipped.intValue() );
110 
111     }
112 
113 
114     /**
115      * @noinspection UnusedDeclaration
116      */
117     class ClassLoaderProxy
118         implements InvocationHandler
119     {
120         private final Object target;
121 
122         /**
123          * @param delegate a target
124          * @noinspection UnusedDeclaration
125          */
126         public ClassLoaderProxy( Object delegate )
127         {
128             this.target = delegate;
129         }
130 
131         public Object invoke( Object proxy, Method method, Object[] args )
132             throws Throwable
133         {
134             Method delegateMethod = target.getClass().getMethod( method.getName(), method.getParameterTypes() );
135             return delegateMethod.invoke( target, args );
136         }
137     }
138 
139 
140     Object createTestRequest( TestRequest suiteDefinition )
141     {
142         if ( suiteDefinition == null )
143         {
144             return null;
145         }
146         Class[] arguments = { List.class, File.class, String.class, String.class };
147         Constructor constructor = ReflectionUtils.getConstructor( this.testRequest, arguments );
148         return ReflectionUtils.newInstance( constructor, new Object[] {
149             suiteDefinition.getSuiteXmlFiles(),
150             suiteDefinition.getTestSourceDirectory(),
151             suiteDefinition.getRequestedTest(),
152             suiteDefinition.getRequestedTestMethod() } );
153     }
154 
155 
156     Object createDirectoryScannerParameters( DirectoryScannerParameters directoryScannerParameters )
157     {
158         if ( directoryScannerParameters == null )
159         {
160             return null;
161         }
162         Class[] arguments = { File.class, List.class, List.class, Boolean.class, String.class };
163         Constructor constructor = ReflectionUtils.getConstructor( this.directoryScannerParameters, arguments );
164         return ReflectionUtils.newInstance( constructor,
165                                             new Object[]{ directoryScannerParameters.getTestClassesDirectory(),
166                                                 directoryScannerParameters.getIncludes(),
167                                                 directoryScannerParameters.getExcludes(),
168                                                 directoryScannerParameters.isFailIfNoTests(),
169                                                 directoryScannerParameters.getRunOrder() } );
170     }
171 
172     Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo )
173     {
174         if ( testArtifactInfo == null )
175         {
176             return null;
177         }
178         Class[] arguments = { String.class, String.class };
179         Constructor constructor = ReflectionUtils.getConstructor( this.testArtifactInfo, arguments );
180         return ReflectionUtils.newInstance( constructor, new Object[]{ testArtifactInfo.getVersion(),
181             testArtifactInfo.getClassifier() } );
182     }
183 
184     Object createReporterConfiguration( ReporterConfiguration reporterConfiguration )
185     {
186         Constructor constructor = ReflectionUtils.getConstructor( this.reporterConfiguration,
187                                                                   new Class[]{ List.class, File.class, Boolean.class,
188                                                                       Integer.class } );
189         return ReflectionUtils.newInstance( constructor, new Object[]{ reporterConfiguration.getReports(),
190             reporterConfiguration.getReportsDirectory(), reporterConfiguration.isTrimStackTrace(),
191             reporterConfiguration.getForkTimeout() } );
192     }
193 
194     public Object createBooterConfiguration()
195     {
196         return ReflectionUtils.instantiate( classLoader, BaseProviderFactory.class.getName() );
197     }
198 
199     public Object instantiateProvider( String providerClassName, Object booterParameters )
200     {
201         return ReflectionUtils.instantiateOneArg( classLoader, providerClassName, this.booterParameters,
202                                                   booterParameters );
203     }
204 
205     public void setIfDirScannerAware( Object o, DirectoryScannerParameters dirScannerParams )
206     {
207         if ( directoryScannerParametersAware.isAssignableFrom( o.getClass() ) )
208         {
209             setDirectoryScannerParameters( o, dirScannerParams );
210         }
211     }
212 
213     public void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams )
214     {
215         final Object param = createDirectoryScannerParameters( dirScannerParams );
216         ReflectionUtils.invokeSetter( o, "setDirectoryScannerParameters", this.directoryScannerParameters, param );
217     }
218 
219     public void setTestSuiteDefinitionAware( Object o, TestRequest testSuiteDefinition2 )
220     {
221         if ( testSuiteDefinitionAware.isAssignableFrom( o.getClass() ) )
222         {
223             setTestSuiteDefinition( o, testSuiteDefinition2 );
224         }
225     }
226 
227     void setTestSuiteDefinition( Object o, TestRequest testSuiteDefinition1 )
228     {
229         final Object param = createTestRequest( testSuiteDefinition1 );
230         ReflectionUtils.invokeSetter( o, "setTestRequest", this.testRequest, param );
231     }
232 
233     public void setProviderPropertiesAware( Object o, Properties properties )
234     {
235         if ( providerPropertiesAware.isAssignableFrom( o.getClass() ) )
236         {
237             setProviderProperties( o, properties );
238         }
239     }
240 
241     void setProviderProperties( Object o, Properties providerProperties )
242     {
243         ReflectionUtils.invokeSetter( o, "setProviderProperties", Properties.class, providerProperties );
244     }
245 
246     public void setReporterConfigurationAware( Object o, ReporterConfiguration reporterConfiguration1 )
247     {
248         if ( reporterConfigurationAware.isAssignableFrom( o.getClass() ) )
249         {
250             setReporterConfiguration( o, reporterConfiguration1 );
251         }
252     }
253 
254 
255     void setReporterConfiguration( Object o, ReporterConfiguration reporterConfiguration )
256     {
257         final Object param = createReporterConfiguration( reporterConfiguration );
258         ReflectionUtils.invokeSetter( o, "setReporterConfiguration", this.reporterConfiguration, param );
259     }
260 
261     public void setTestClassLoaderAware( Object o, ClassLoader surefireClassLoader, ClassLoader testClassLoader )
262     {
263         if ( testClassLoaderAware.isAssignableFrom( o.getClass() ) )
264         {
265             setTestClassLoader( o, surefireClassLoader, testClassLoader );
266         }
267     }
268 
269     void setTestClassLoader( Object o, ClassLoader surefireClassLoader, ClassLoader testClassLoader )
270     {
271         final Method setter =
272             ReflectionUtils.getMethod( o, "setClassLoaders", new Class[]{ ClassLoader.class, ClassLoader.class } );
273         ReflectionUtils.invokeMethodWithArray( o, setter, new Object[]{ surefireClassLoader, testClassLoader } );
274     }
275 
276     public void setTestArtifactInfoAware( Object o, TestArtifactInfo testArtifactInfo1 )
277     {
278         if ( testArtifactInfoAware.isAssignableFrom( o.getClass() ) )
279         {
280             setTestArtifactInfo( o, testArtifactInfo1 );
281         }
282     }
283 
284     void setTestArtifactInfo( Object o, TestArtifactInfo testArtifactInfo )
285     {
286         final Object param = createTestArtifactInfo( testArtifactInfo );
287         ReflectionUtils.invokeSetter( o, "setTestArtifactInfo", this.testArtifactInfo, param );
288     }
289 
290     private boolean isRunResult( Object o )
291     {
292         return runResult.isAssignableFrom( o.getClass() );
293     }
294 }