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