1 package org.eclipse.aether.impl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Modifier;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.LinkedHashSet;
29 import java.util.List;
30 import java.util.Map;
31 import static java.util.Objects.requireNonNull;
32
33 import org.eclipse.aether.RepositorySystem;
34 import org.eclipse.aether.internal.impl.DefaultArtifactResolver;
35 import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
36 import org.eclipse.aether.internal.impl.DefaultDependencyCollector;
37 import org.eclipse.aether.internal.impl.DefaultDeployer;
38 import org.eclipse.aether.internal.impl.DefaultFileProcessor;
39 import org.eclipse.aether.internal.impl.DefaultInstaller;
40 import org.eclipse.aether.internal.impl.DefaultLocalRepositoryProvider;
41 import org.eclipse.aether.internal.impl.DefaultMetadataResolver;
42 import org.eclipse.aether.internal.impl.DefaultOfflineController;
43 import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
44 import org.eclipse.aether.internal.impl.DefaultRepositoryConnectorProvider;
45 import org.eclipse.aether.internal.impl.DefaultRepositoryEventDispatcher;
46 import org.eclipse.aether.internal.impl.DefaultRepositoryLayoutProvider;
47 import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
48 import org.eclipse.aether.internal.impl.DefaultSyncContextFactory;
49 import org.eclipse.aether.internal.impl.DefaultTransporterProvider;
50 import org.eclipse.aether.internal.impl.DefaultUpdateCheckManager;
51 import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
52 import org.eclipse.aether.internal.impl.EnhancedLocalRepositoryManagerFactory;
53 import org.eclipse.aether.internal.impl.Maven2RepositoryLayoutFactory;
54 import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
55 import org.eclipse.aether.internal.impl.slf4j.Slf4jLoggerFactory;
56 import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider;
57 import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory;
58 import org.eclipse.aether.spi.connector.layout.RepositoryLayoutProvider;
59 import org.eclipse.aether.spi.connector.transport.TransporterProvider;
60 import org.eclipse.aether.spi.io.FileProcessor;
61 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
62 import org.eclipse.aether.spi.locator.Service;
63 import org.eclipse.aether.spi.locator.ServiceLocator;
64 import org.eclipse.aether.spi.log.LoggerFactory;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public final class DefaultServiceLocator
80 implements ServiceLocator
81 {
82
83 private class Entry<T>
84 {
85
86 private final Class<T> type;
87
88 private final Collection<Object> providers;
89
90 private List<T> instances;
91
92 Entry( Class<T> type )
93 {
94 this.type = requireNonNull( type, "service type cannot be null" );
95 providers = new LinkedHashSet<Object>( 8 );
96 }
97
98 public synchronized void setServices( T... services )
99 {
100 providers.clear();
101 if ( services != null )
102 {
103 for ( T service : services )
104 {
105 providers.add( requireNonNull( service, "service instance cannot be null" ) );
106 }
107 }
108 instances = null;
109 }
110
111 public synchronized void setService( Class<? extends T> impl )
112 {
113 providers.clear();
114 addService( impl );
115 }
116
117 public synchronized void addService( Class<? extends T> impl )
118 {
119 providers.add( requireNonNull( impl, "implementation class cannot be null" ) );
120 instances = null;
121 }
122
123 public T getInstance()
124 {
125 List<T> instances = getInstances();
126 return instances.isEmpty() ? null : instances.get( 0 );
127 }
128
129 public synchronized List<T> getInstances()
130 {
131 if ( instances == null )
132 {
133 instances = new ArrayList<T>( providers.size() );
134 for ( Object provider : providers )
135 {
136 T instance;
137 if ( provider instanceof Class )
138 {
139 instance = newInstance( (Class<?>) provider );
140 }
141 else
142 {
143 instance = type.cast( provider );
144 }
145 if ( instance != null )
146 {
147 instances.add( instance );
148 }
149 }
150 instances = Collections.unmodifiableList( instances );
151 }
152 return instances;
153 }
154
155 private T newInstance( Class<?> impl )
156 {
157 try
158 {
159 Constructor<?> constr = impl.getDeclaredConstructor();
160 if ( !Modifier.isPublic( constr.getModifiers() ) )
161 {
162 constr.setAccessible( true );
163 }
164 Object obj = constr.newInstance();
165
166 T instance = type.cast( obj );
167 if ( instance instanceof Service )
168 {
169 ( (Service) instance ).initService( DefaultServiceLocator.this );
170 }
171 return instance;
172 }
173 catch ( Exception e )
174 {
175 serviceCreationFailed( type, impl, e );
176 }
177 catch ( LinkageError e )
178 {
179 serviceCreationFailed( type, impl, e );
180 }
181 return null;
182 }
183
184 }
185
186 private final Map<Class<?>, Entry<?>> entries;
187
188 private ErrorHandler errorHandler;
189
190
191
192
193 public DefaultServiceLocator()
194 {
195 entries = new HashMap<Class<?>, Entry<?>>();
196
197 addService( RepositorySystem.class, DefaultRepositorySystem.class );
198 addService( ArtifactResolver.class, DefaultArtifactResolver.class );
199 addService( DependencyCollector.class, DefaultDependencyCollector.class );
200 addService( Deployer.class, DefaultDeployer.class );
201 addService( Installer.class, DefaultInstaller.class );
202 addService( MetadataResolver.class, DefaultMetadataResolver.class );
203 addService( RepositoryLayoutProvider.class, DefaultRepositoryLayoutProvider.class );
204 addService( RepositoryLayoutFactory.class, Maven2RepositoryLayoutFactory.class );
205 addService( TransporterProvider.class, DefaultTransporterProvider.class );
206 addService( ChecksumPolicyProvider.class, DefaultChecksumPolicyProvider.class );
207 addService( RepositoryConnectorProvider.class, DefaultRepositoryConnectorProvider.class );
208 addService( RemoteRepositoryManager.class, DefaultRemoteRepositoryManager.class );
209 addService( UpdateCheckManager.class, DefaultUpdateCheckManager.class );
210 addService( UpdatePolicyAnalyzer.class, DefaultUpdatePolicyAnalyzer.class );
211 addService( FileProcessor.class, DefaultFileProcessor.class );
212 addService( SyncContextFactory.class, DefaultSyncContextFactory.class );
213 addService( RepositoryEventDispatcher.class, DefaultRepositoryEventDispatcher.class );
214 addService( OfflineController.class, DefaultOfflineController.class );
215 addService( LocalRepositoryProvider.class, DefaultLocalRepositoryProvider.class );
216 addService( LocalRepositoryManagerFactory.class, SimpleLocalRepositoryManagerFactory.class );
217 addService( LocalRepositoryManagerFactory.class, EnhancedLocalRepositoryManagerFactory.class );
218 if ( Slf4jLoggerFactory.isSlf4jAvailable() )
219 {
220 addService( LoggerFactory.class, Slf4jLoggerFactory.class );
221 }
222 }
223
224 private <T> Entry<T> getEntry( Class<T> type, boolean create )
225 {
226 @SuppressWarnings( "unchecked" )
227 Entry<T> entry = (Entry<T>) entries.get( requireNonNull( type, "service type cannot be null" ) );
228 if ( entry == null && create )
229 {
230 entry = new Entry<T>( type );
231 entries.put( type, entry );
232 }
233 return entry;
234 }
235
236
237
238
239
240
241
242
243
244
245
246 public <T> DefaultServiceLocator setService( Class<T> type, Class<? extends T> impl )
247 {
248 getEntry( type, true ).setService( impl );
249 return this;
250 }
251
252
253
254
255
256
257
258
259
260
261
262 public <T> DefaultServiceLocator addService( Class<T> type, Class<? extends T> impl )
263 {
264 getEntry( type, true ).addService( impl );
265 return this;
266 }
267
268
269
270
271
272
273
274
275
276 public <T> DefaultServiceLocator setServices( Class<T> type, T... services )
277 {
278 getEntry( type, true ).setServices( services );
279 return this;
280 }
281
282 public <T> T getService( Class<T> type )
283 {
284 Entry<T> entry = getEntry( type, false );
285 return ( entry != null ) ? entry.getInstance() : null;
286 }
287
288 public <T> List<T> getServices( Class<T> type )
289 {
290 Entry<T> entry = getEntry( type, false );
291 return ( entry != null ) ? entry.getInstances() : null;
292 }
293
294 private void serviceCreationFailed( Class<?> type, Class<?> impl, Throwable exception )
295 {
296 if ( errorHandler != null )
297 {
298 errorHandler.serviceCreationFailed( type, impl, exception );
299 }
300 }
301
302
303
304
305
306
307 public void setErrorHandler( ErrorHandler errorHandler )
308 {
309 this.errorHandler = errorHandler;
310 }
311
312
313
314
315 public abstract static class ErrorHandler
316 {
317
318
319
320
321
322
323
324
325
326 public void serviceCreationFailed( Class<?> type, Class<?> impl, Throwable exception )
327 {
328 }
329
330 }
331
332 }