View Javadoc
1   package org.apache.maven.surefire.testng.conf;
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.lang.reflect.Method;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.maven.surefire.booter.ProviderParameterNames;
29  import org.apache.maven.surefire.testset.TestSetFailedException;
30  import org.testng.TestNG;
31  import org.testng.xml.XmlSuite;
32  
33  /**
34   * Configurator that relies on reflection to set parameters in TestNG
35   *
36   */
37  public abstract class AbstractDirectConfigurator
38      implements Configurator
39  {
40      final Map<String, Setter> setters;
41  
42      AbstractDirectConfigurator()
43      {
44          Map<String, Setter> options = new HashMap<String, Setter>();
45          // options.put( ProviderParameterNames.TESTNG_GROUPS_PROP, new Setter( "setGroups", String.class ) );
46          // options.put( ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP, new Setter( "setExcludedGroups", String.class
47          // ) );
48          options.put( "junit", new Setter( "setJUnit", Boolean.class ) );
49          options.put( ProviderParameterNames.THREADCOUNT_PROP, new Setter( "setThreadCount", int.class ) );
50          options.put( "usedefaultlisteners", new Setter( "setUseDefaultListeners", boolean.class ) );
51          this.setters = options;
52      }
53  
54      @Override
55      public void configure( TestNG testng, Map<String, String> options )
56          throws TestSetFailedException
57      {
58          System.out.println( "\n\n\n\nCONFIGURING TESTNG\n\n\n\n" );
59          // kind of ugly, but listeners are configured differently
60          final String listeners = options.remove( "listener" );
61          // DGF In 4.7, default listeners dump XML files in the surefire-reports directory,
62          // confusing the report plugin.  This was fixed in later versions.
63          testng.setUseDefaultListeners( false );
64          configureInstance( testng, options );
65          // TODO: we should have the Profile so that we can decide if this is needed or not
66          testng.setListenerClasses( loadListenerClasses( listeners ) );
67      }
68  
69      @Override
70      public void configure( XmlSuite suite, Map<String, String> options )
71          throws TestSetFailedException
72      {
73          Map<String, String> filtered = filterForSuite( options );
74          configureInstance( suite, filtered );
75      }
76  
77      protected Map<String, String> filterForSuite( Map<String, String> options )
78      {
79          Map<String, String> result = new HashMap<String, String>();
80          addPropIfNotNull( options, result, ProviderParameterNames.PARALLEL_PROP );
81          addPropIfNotNull( options, result, ProviderParameterNames.THREADCOUNT_PROP );
82          return result;
83      }
84  
85      private void addPropIfNotNull( Map<String, String> options, Map<String, String> result, String prop )
86      {
87          if ( options.containsKey( prop ) )
88          {
89              result.put( prop, options.get( prop ) );
90          }
91      }
92  
93      private void configureInstance( Object testngInstance, Map<String, String> options )
94      {
95          for ( Map.Entry<String, String> entry : options.entrySet() )
96          {
97              String key = entry.getKey();
98              String val = entry.getValue();
99              Setter setter = setters.get( key );
100             if ( setter != null )
101             {
102                 try
103                 {
104                     setter.invoke( testngInstance, val );
105                 }
106                 catch ( Exception e )
107                 {
108                     throw new RuntimeException( "Cannot set option " + key + " with value " + val, e );
109                 }
110             }
111         }
112     }
113 
114     static List<Class> loadListenerClasses( String listenerClasses )
115         throws TestSetFailedException
116     {
117         if ( listenerClasses == null || listenerClasses.trim().isEmpty() )
118         {
119             return new ArrayList<Class>();
120         }
121 
122         List<Class> classes = new ArrayList<Class>();
123         String[] classNames = listenerClasses.split( "\\s*,\\s*(\\r?\\n)?\\s*" );
124         for ( String className : classNames )
125         {
126             Class<?> clazz = loadClass( className );
127             classes.add( clazz );
128         }
129 
130         return classes;
131     }
132 
133     static Class<?> loadClass( String className )
134         throws TestSetFailedException
135     {
136         try
137         {
138             return Class.forName( className );
139         }
140         catch ( Exception ex )
141         {
142             throw new TestSetFailedException( "Cannot find listener class " + className, ex );
143         }
144     }
145 
146     /**
147      * Describes a property setter by method name and parameter class
148      *
149      */
150     public static final class Setter
151     {
152         private final String setterName;
153 
154         private final Class<?> paramClass;
155 
156         public Setter( String name, Class<?> clazz )
157         {
158             setterName = name;
159             paramClass = clazz;
160         }
161 
162         public void invoke( Object target, String value )
163             throws Exception
164         {
165             Method setter = target.getClass().getMethod( setterName, paramClass );
166             if ( setter != null )
167             {
168                 setter.invoke( target, convertValue( value ) );
169             }
170         }
171 
172         private Object convertValue( String value )
173         {
174             if ( value == null )
175             {
176                 return null;
177             }
178             if ( paramClass.isAssignableFrom( value.getClass() ) )
179             {
180                 return value;
181             }
182 
183             if ( Boolean.class.equals( paramClass ) || boolean.class.equals( paramClass ) )
184             {
185                 return Boolean.valueOf( value );
186             }
187             if ( Integer.class.equals( paramClass ) || int.class.equals( paramClass ) )
188             {
189                 return Integer.valueOf( value );
190             }
191 
192             return value;
193         }
194     }
195 }