View Javadoc

1   package org.apache.maven.surefire.util;
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.File;
23  import java.util.ArrayList;
24  import java.util.Calendar;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  /**
31   * Scans directories looking for tests.
32   * 
33   * @author Karl M. Davis
34   * @author Kristian Rosenvold
35   */
36  public class DefaultDirectoryScanner
37      implements DirectoryScanner
38  {
39  
40      private static final String FS = System.getProperty( "file.separator" );
41  
42      private static final String[] EMPTY_STRING_ARRAY = new String[0];
43  
44      private static final String JAVA_SOURCE_FILE_EXTENSION = ".java";
45  
46      private static final String JAVA_CLASS_FILE_EXTENSION = ".class";
47  
48      private final File basedir;
49  
50      private final List includes;
51  
52      private final List excludes;
53  
54      private final List classesSkippedByValidation = new ArrayList();
55  
56      private final Comparator sortOrder;
57  
58      private final RunOrder runOrder;
59  
60      public DefaultDirectoryScanner( File basedir, List includes, List excludes, RunOrder runOrder )
61      {
62          this.basedir = basedir;
63          this.includes = includes;
64          this.excludes = excludes;
65          this.runOrder = runOrder;
66          this.sortOrder = getSortOrderComparator();
67      }
68  
69      public TestsToRun locateTestClasses( ClassLoader classLoader, ScannerFilter scannerFilter )
70      {
71          String[] testClassNames = collectTests();
72          List result = new ArrayList();
73  
74          for ( int i = 0; i < testClassNames.length; i++ )
75          {
76              String className = testClassNames[i];
77  
78              Class testClass = loadClass( classLoader, className );
79  
80              if ( scannerFilter == null || scannerFilter.accept( testClass ) )
81              {
82                  result.add( testClass );
83              }
84              else
85              {
86                  classesSkippedByValidation.add( testClass );
87              }
88          }
89          orderTestClasses( result );
90          return new TestsToRun( result );
91      }
92  
93      private static Class loadClass( ClassLoader classLoader, String className )
94      {
95          Class testClass;
96          try
97          {
98              testClass = classLoader.loadClass( className );
99          }
100         catch ( ClassNotFoundException e )
101         {
102             throw new NestedRuntimeException( "Unable to create test class '" + className + "'", e );
103         }
104         return testClass;
105     }
106 
107     String[] collectTests()
108     {
109         String[] tests = EMPTY_STRING_ARRAY;
110         if ( basedir.exists() )
111         {
112             org.codehaus.plexus.util.DirectoryScanner scanner = new org.codehaus.plexus.util.DirectoryScanner();
113 
114             scanner.setBasedir( basedir );
115 
116             if ( includes != null )
117             {
118                 scanner.setIncludes( processIncludesExcludes( includes ) );
119             }
120 
121             if ( excludes != null )
122             {
123                 scanner.setExcludes( processIncludesExcludes( excludes ) );
124             }
125 
126             scanner.scan();
127 
128             tests = scanner.getIncludedFiles();
129             for ( int i = 0; i < tests.length; i++ )
130             {
131                 String test = tests[i];
132                 test = test.substring( 0, test.indexOf( "." ) );
133                 tests[i] = test.replace( FS.charAt( 0 ), '.' );
134             }
135         }
136         return tests;
137     }
138 
139     private static String[] processIncludesExcludes( List list )
140     {
141         List newList = new ArrayList();
142         Iterator iter = list.iterator();
143         while (iter.hasNext())
144         {
145             String include = (String) iter.next();
146             String [] includes = include.split( "," );
147             for ( int i = 0; i < includes.length; ++i )
148             {
149                 newList.add( includes[i] );
150             }
151         }
152 
153         String[] incs = new String[newList.size()];
154 
155         for ( int i = 0; i < incs.length; i++ )
156         {
157             String inc = (String) newList.get( i );
158             if ( inc.endsWith( JAVA_SOURCE_FILE_EXTENSION ) )
159             {
160                 inc =
161                     new StringBuffer( inc.length() - JAVA_SOURCE_FILE_EXTENSION.length()
162                         + JAVA_CLASS_FILE_EXTENSION.length() ).append( inc.substring( 0,
163                                                                                       inc.lastIndexOf( JAVA_SOURCE_FILE_EXTENSION ) ) ).append( JAVA_CLASS_FILE_EXTENSION ).toString();
164             }
165             incs[i] = inc;
166 
167         }
168         return incs;
169     }
170 
171     public List getClassesSkippedByValidation()
172     {
173         return classesSkippedByValidation;
174     }
175 
176     private void orderTestClasses( List testClasses )
177     {
178         if ( RunOrder.RANDOM.equals( runOrder ) )
179         {
180             Collections.shuffle( testClasses );
181         }
182         else if ( sortOrder != null )
183         {
184             Collections.sort( testClasses, sortOrder );
185         }
186     }
187 
188     private Comparator getSortOrderComparator()
189     {
190         if ( RunOrder.ALPHABETICAL.equals( runOrder ) )
191         {
192             return getAlphabeticalComparator();
193         }
194         else if ( RunOrder.REVERSE_ALPHABETICAL.equals( runOrder ) )
195         {
196             return getReverseAlphabeticalComparator();
197         }
198         else if ( RunOrder.HOURLY.equals( runOrder ) )
199         {
200             final int hour = Calendar.getInstance().get( Calendar.HOUR_OF_DAY );
201             return ( ( hour % 2 ) == 0 ) ? getAlphabeticalComparator() : getReverseAlphabeticalComparator();
202         }
203         else
204         {
205             return null;
206         }
207     }
208 
209     private Comparator getReverseAlphabeticalComparator()
210     {
211         return new Comparator()
212         {
213             public int compare( Object o1, Object o2 )
214             {
215                 return ( (Class) o2 ).getName().compareTo( ( (Class) o1 ).getName() );
216             }
217         };
218     }
219 
220     private Comparator getAlphabeticalComparator()
221     {
222         return new Comparator()
223         {
224             public int compare( Object o1, Object o2 )
225             {
226                 return ( (Class) o1 ).getName().compareTo( ( (Class) o2 ).getName() );
227             }
228         };
229     }
230 
231 }