1 package org.apache.maven.surefire.providerapi;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import javax.annotation.Nonnull;
23 import java.io.BufferedReader;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.net.URL;
28 import java.util.Enumeration;
29 import java.util.HashSet;
30 import java.util.Set;
31
32 import static java.lang.Character.isJavaIdentifierPart;
33 import static java.lang.Character.isJavaIdentifierStart;
34 import static java.util.Collections.emptySet;
35 import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor;
36
37
38
39
40
41
42
43
44
45 public final class ServiceLoader
46 {
47
48 @Nonnull
49 @SuppressWarnings( "unchecked" )
50 public <T> Set<T> load( Class<T> clazz, ClassLoader classLoader )
51 {
52 try
53 {
54 Set<T> implementations = new HashSet<>();
55 for ( String fullyQualifiedClassName : lookup( clazz, classLoader ) )
56 {
57 Class<?> implClass = classLoader.loadClass( fullyQualifiedClassName );
58 implementations.add( (T) getConstructor( implClass ).newInstance() );
59 }
60 return implementations;
61 }
62 catch ( IOException | ReflectiveOperationException e )
63 {
64 throw new IllegalStateException( e.getLocalizedMessage(), e );
65 }
66 }
67
68 @Nonnull
69 public Set<String> lookup( Class<?> clazz, ClassLoader classLoader )
70 throws IOException
71 {
72 final String resourceName = "META-INF/services/" + clazz.getName();
73
74 if ( classLoader == null )
75 {
76 return emptySet();
77 }
78 final Enumeration<URL> urls = classLoader.getResources( resourceName );
79 return lookupSpiImplementations( urls );
80 }
81
82
83
84
85
86
87
88
89
90 @Nonnull
91 @SuppressWarnings( "checkstyle:innerassignment" )
92 private static Set<String> lookupSpiImplementations( final Enumeration<URL> urlEnumeration )
93 throws IOException
94 {
95 final Set<String> names = new HashSet<>();
96 nextUrl:
97 while ( urlEnumeration.hasMoreElements() )
98 {
99 final URL url = urlEnumeration.nextElement();
100 try ( BufferedReader reader = getReader( url ) )
101 {
102 for ( String line; ( line = reader.readLine() ) != null; )
103 {
104 int ci = line.indexOf( '#' );
105 if ( ci >= 0 )
106 {
107 line = line.substring( 0, ci );
108 }
109 line = line.trim();
110 int n = line.length();
111 if ( n == 0 )
112 {
113 continue;
114 }
115
116 if ( line.indexOf( ' ' ) >= 0 || line.indexOf( '\t' ) >= 0 )
117 {
118 continue nextUrl;
119 }
120 char cp = line.charAt( 0 );
121 if ( !isJavaIdentifierStart( cp ) )
122 {
123 continue nextUrl;
124 }
125 for ( int i = 1; i < n; i++ )
126 {
127 cp = line.charAt( i );
128 if ( !isJavaIdentifierPart( cp ) && cp != '.' )
129 {
130 continue nextUrl;
131 }
132 }
133 if ( !names.contains( line ) )
134 {
135 names.add( line );
136 }
137 }
138 }
139 }
140
141 return names;
142 }
143
144 @Nonnull
145 private static BufferedReader getReader( @Nonnull URL url )
146 throws IOException
147 {
148 final InputStream inputStream = url.openStream();
149 final InputStreamReader inputStreamReader = new InputStreamReader( inputStream );
150 return new BufferedReader( inputStreamReader );
151 }
152 }