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.util.Collections;
24  import java.util.Iterator;
25  
26  import org.apache.maven.surefire.util.CloseableIterator;
27  import org.apache.maven.surefire.util.TestsToRun;
28  
29  import static org.apache.maven.surefire.booter.CommandReader.getReader;
30  import static org.apache.maven.surefire.util.ReflectionUtils.loadClass;
31  
32  /**
33   * A variant of TestsToRun that is provided with test class names
34   * from an {@code System.in}.
35   * The method {@link #iterator()} returns an Iterator that blocks on calls to
36   * {@link Iterator#hasNext()} or {@link Iterator#next()} until new classes are available, or no more
37   * classes will be available or the internal stream is closed.
38   * The iterator can be used only in one Thread and it is the thread which executes
39   * {@link org.apache.maven.surefire.providerapi.SurefireProvider provider implementation}.
40   *
41   * @author Andreas Gudian
42   * @author Tibor Digana
43   */
44  final class LazyTestsToRun
45      extends TestsToRun
46  {
47      private final PrintStream originalOutStream;
48  
49      /**
50       * C'tor
51       *
52       * @param originalOutStream the output stream to use when requesting new new tests
53       */
54      LazyTestsToRun( PrintStream originalOutStream )
55      {
56          super( Collections.<Class<?>>emptySet() );
57  
58          this.originalOutStream = originalOutStream;
59      }
60  
61      private final class BlockingIterator
62          implements Iterator<Class<?>>
63      {
64          private final Iterator<String> it = getReader().getIterableClasses( originalOutStream ).iterator();
65  
66          @Override
67          public boolean hasNext()
68          {
69              return it.hasNext();
70          }
71  
72          @Override
73          public Class<?> next()
74          {
75              return findClass( it.next() );
76          }
77  
78          @Override
79          public void remove()
80          {
81              throw new UnsupportedOperationException();
82          }
83      }
84  
85      /**
86       * @return test classes which have been retrieved by {@link LazyTestsToRun#iterator()}.
87       */
88      @Override
89      public Iterator<Class<?>> iterated()
90      {
91          return newWeakIterator();
92      }
93  
94      /**
95       * The iterator can be used only in one Thread.
96       * {@inheritDoc}
97       * @see org.apache.maven.surefire.util.TestsToRun#iterator()
98       * */
99      @Override
100     public Iterator<Class<?>> iterator()
101     {
102         return new BlockingIterator();
103     }
104 
105     /* (non-Javadoc)
106      * {@inheritDoc}
107       * @see org.apache.maven.surefire.util.TestsToRun#toString()
108       */
109     @Override
110     public String toString()
111     {
112         return "LazyTestsToRun";
113     }
114 
115     /* (non-Javadoc)
116      * {@inheritDoc}
117      * @see org.apache.maven.surefire.util.TestsToRun#allowEagerReading()
118      */
119     @Override
120     public boolean allowEagerReading()
121     {
122         return false;
123     }
124 
125     private static Class<?> findClass( String clazz )
126     {
127         return loadClass( Thread.currentThread().getContextClassLoader(), clazz );
128     }
129 
130     /**
131      * @return snapshot of tests upon constructs of {@link CommandReader#iterated() iterator}.
132      * Therefore weakly consistent while {@link LazyTestsToRun#iterator()} is being iterated.
133      */
134     private Iterator<Class<?>> newWeakIterator()
135     {
136         final Iterator<String> it = getReader().iterated();
137         return new CloseableIterator<Class<?>>()
138         {
139             @Override
140             protected boolean isClosed()
141             {
142                 return LazyTestsToRun.this.isFinished();
143             }
144 
145             @Override
146             protected boolean doHasNext()
147             {
148                 return it.hasNext();
149             }
150 
151             @Override
152             protected Class<?> doNext()
153             {
154                 return findClass( it.next() );
155             }
156 
157             @Override
158             protected void doRemove()
159             {
160             }
161 
162             @Override
163             public void remove()
164             {
165                 throw new UnsupportedOperationException( "unsupported remove" );
166             }
167         };
168     }
169 }