View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.providerapi;
20  
21  import javax.annotation.Nonnull;
22  import javax.inject.Inject;
23  import javax.inject.Named;
24  import javax.inject.Singleton;
25  
26  import java.io.IOException;
27  import java.util.Collections;
28  import java.util.List;
29  import java.util.Optional;
30  import java.util.Set;
31  
32  import org.apache.maven.surefire.api.provider.SurefireProvider;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import static java.lang.Thread.currentThread;
37  import static java.util.Arrays.stream;
38  import static java.util.Collections.emptyList;
39  import static java.util.stream.Collectors.toList;
40  
41  /**
42   * @author Kristian Rosenvold
43   */
44  @Singleton
45  @Named
46  public final class ProviderDetector {
47      private Logger logger = LoggerFactory.getLogger(getClass());
48  
49      @Inject
50      private ServiceLoader serviceLoader;
51  
52      @Nonnull
53      public List<ProviderInfo> resolve(ConfigurableProviderInfo dynamicProvider, ProviderInfo... wellKnownProviders) {
54          Set<String> manuallyConfiguredProviders = getManuallyConfiguredProviders();
55  
56          List<ProviderInfo> providersToRun = manuallyConfiguredProviders.stream()
57                  .map(name -> findByName(name, wellKnownProviders).orElseGet(() -> dynamicProvider.instantiate(name)))
58                  .collect(toList());
59  
60          providersToRun.forEach(p -> logger.info("Using configured provider " + p.getProviderName()));
61  
62          if (providersToRun.isEmpty()) {
63              return autoDetectOneWellKnownProvider(wellKnownProviders)
64                      .map(Collections::singletonList)
65                      .orElse(emptyList());
66          } else {
67              return Collections.unmodifiableList(providersToRun);
68          }
69      }
70  
71      private Optional<ProviderInfo> autoDetectOneWellKnownProvider(ProviderInfo... wellKnownProviders) {
72          Optional<ProviderInfo> providerInfo =
73                  stream(wellKnownProviders).filter(ProviderInfo::isApplicable).findFirst();
74  
75          providerInfo.ifPresent(p -> logger.info("Using auto detected provider " + p.getProviderName()));
76  
77          return providerInfo;
78      }
79  
80      private Set<String> getManuallyConfiguredProviders() {
81          try {
82              ClassLoader cl = currentThread().getContextClassLoader();
83              return serviceLoader.lookup(SurefireProvider.class, cl);
84          } catch (IOException e) {
85              throw new RuntimeException(e);
86          }
87      }
88  
89      @Nonnull
90      private Optional<ProviderInfo> findByName(String providerClassName, ProviderInfo... wellKnownProviders) {
91          return stream(wellKnownProviders)
92                  .filter(p -> p.getProviderName().equals(providerClassName))
93                  .findFirst();
94      }
95  }