View Javadoc
1   package org.apache.maven.resolver.internal.ant;
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.BufferedReader;
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.IOException;
26  import java.io.InputStreamReader;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.HashMap;
31  import java.util.HashSet;
32  import java.util.LinkedHashMap;
33  import java.util.List;
34  import java.util.Locale;
35  import java.util.Map;
36  import java.util.Objects;
37  import java.util.Properties;
38  import java.util.concurrent.CopyOnWriteArrayList;
39  
40  import org.apache.maven.model.Model;
41  import org.apache.maven.model.building.DefaultModelBuilderFactory;
42  import org.apache.maven.model.building.DefaultModelBuildingRequest;
43  import org.apache.maven.model.building.FileModelSource;
44  import org.apache.maven.model.building.ModelBuilder;
45  import org.apache.maven.model.building.ModelBuildingException;
46  import org.apache.maven.model.building.ModelBuildingRequest;
47  import org.apache.maven.model.resolution.ModelResolver;
48  import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
49  import org.apache.maven.resolver.internal.ant.types.Artifact;
50  import org.apache.maven.resolver.internal.ant.types.Artifacts;
51  import org.apache.maven.resolver.internal.ant.types.Authentication;
52  import org.apache.maven.resolver.internal.ant.types.Dependencies;
53  import org.apache.maven.resolver.internal.ant.types.Dependency;
54  import org.apache.maven.resolver.internal.ant.types.DependencyContainer;
55  import org.apache.maven.resolver.internal.ant.types.Exclusion;
56  import org.apache.maven.resolver.internal.ant.types.LocalRepository;
57  import org.apache.maven.resolver.internal.ant.types.Mirror;
58  import org.apache.maven.resolver.internal.ant.types.Pom;
59  import org.apache.maven.resolver.internal.ant.types.Proxy;
60  import org.apache.maven.resolver.internal.ant.types.RemoteRepositories;
61  import org.apache.maven.resolver.internal.ant.types.RemoteRepository;
62  import org.apache.maven.resolver.internal.ant.types.RemoteRepository.Policy;
63  import org.apache.maven.settings.Profile;
64  import org.apache.maven.settings.Repository;
65  import org.apache.maven.settings.RepositoryPolicy;
66  import org.apache.maven.settings.Server;
67  import org.apache.maven.settings.Settings;
68  import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
69  import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
70  import org.apache.maven.settings.building.SettingsBuilder;
71  import org.apache.maven.settings.building.SettingsBuildingException;
72  import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
73  import org.apache.maven.settings.crypto.SettingsDecrypter;
74  import org.apache.maven.settings.crypto.SettingsDecryptionResult;
75  import org.apache.tools.ant.BuildException;
76  import org.apache.tools.ant.Project;
77  import org.apache.tools.ant.Task;
78  import org.apache.tools.ant.taskdefs.condition.Os;
79  import org.apache.tools.ant.types.Reference;
80  import org.codehaus.plexus.util.xml.Xpp3Dom;
81  import org.eclipse.aether.ConfigurationProperties;
82  import org.eclipse.aether.DefaultRepositoryCache;
83  import org.eclipse.aether.DefaultRepositorySystemSession;
84  import org.eclipse.aether.RepositorySystem;
85  import org.eclipse.aether.RepositorySystemSession;
86  import org.eclipse.aether.artifact.DefaultArtifact;
87  import org.eclipse.aether.collection.CollectRequest;
88  import org.eclipse.aether.collection.CollectResult;
89  import org.eclipse.aether.collection.DependencyCollectionException;
90  import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
91  import org.eclipse.aether.deployment.DeployRequest;
92  import org.eclipse.aether.deployment.DeploymentException;
93  import org.eclipse.aether.impl.DefaultServiceLocator;
94  import org.eclipse.aether.impl.RemoteRepositoryManager;
95  import org.eclipse.aether.installation.InstallRequest;
96  import org.eclipse.aether.installation.InstallationException;
97  import org.eclipse.aether.repository.AuthenticationSelector;
98  import org.eclipse.aether.repository.LocalRepositoryManager;
99  import org.eclipse.aether.repository.MirrorSelector;
100 import org.eclipse.aether.repository.ProxySelector;
101 import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
102 import org.eclipse.aether.spi.connector.transport.TransporterFactory;
103 import org.eclipse.aether.spi.log.Logger;
104 import org.eclipse.aether.transport.classpath.ClasspathTransporterFactory;
105 import org.eclipse.aether.transport.file.FileTransporterFactory;
106 import org.eclipse.aether.transport.http.HttpTransporterFactory;
107 import org.eclipse.aether.util.repository.AuthenticationBuilder;
108 import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector;
109 import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
110 import org.eclipse.aether.util.repository.DefaultMirrorSelector;
111 import org.eclipse.aether.util.repository.DefaultProxySelector;
112 
113 /**
114  */
115 public class AntRepoSys
116 {
117 
118     private static final boolean OS_WINDOWS = Os.isFamily( "windows" );
119 
120     private static final ModelBuilder MODEL_BUILDER = new DefaultModelBuilderFactory().newInstance();
121 
122     private static final SettingsBuilder SETTINGS_BUILDER = new DefaultSettingsBuilderFactory().newInstance();
123 
124     private static final SettingsDecrypter SETTINGS_DECRYPTER = new AntSettingsDecryptorFactory().newInstance();
125 
126     private final Project project;
127 
128     private final DefaultServiceLocator locator;
129 
130     private RepositorySystem repoSys;
131 
132     private RemoteRepositoryManager remoteRepoMan;
133 
134     private File userSettings;
135 
136     private File globalSettings;
137 
138     private Settings settings;
139 
140     private final List<Mirror> mirrors = new CopyOnWriteArrayList<>();
141 
142     private final List<Proxy> proxies = new CopyOnWriteArrayList<>();
143 
144     private final List<Authentication> authentications = new CopyOnWriteArrayList<>();
145 
146     private LocalRepository localRepository;
147 
148     private Pom defaultPom;
149 
150     private static <T> boolean eq( T o1, T o2 )
151     {
152         return Objects.equals( o1, o2 );
153     }
154 
155     public static synchronized AntRepoSys getInstance( Project project )
156     {
157         Object obj = project.getReference( Names.ID );
158         if ( obj instanceof AntRepoSys )
159         {
160             return (AntRepoSys) obj;
161         }
162         AntRepoSys instance = new AntRepoSys( project );
163         project.addReference( Names.ID, instance );
164         instance.initDefaults();
165         return instance;
166     }
167 
168     private AntRepoSys( Project project )
169     {
170         this.project = project;
171 
172         locator = MavenRepositorySystemUtils.newServiceLocator();
173         locator.setErrorHandler( new AntServiceLocatorErrorHandler( project ) );
174         locator.setServices( Logger.class, new AntLogger( project ) );
175         locator.setServices( ModelBuilder.class, MODEL_BUILDER );
176         locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class );
177         locator.addService( TransporterFactory.class, FileTransporterFactory.class );
178         locator.addService( TransporterFactory.class, HttpTransporterFactory.class );
179         locator.addService( TransporterFactory.class, ClasspathTransporterFactory.class );
180     }
181 
182     private void initDefaults()
183     {
184         RemoteRepository repo = new RemoteRepository();
185         repo.setProject( project );
186         repo.setId( "central" );
187         repo.setUrl( "https://repo1.maven.org/maven2/" );
188         project.addReference( Names.ID_CENTRAL, repo );
189 
190         repo = new RemoteRepository();
191         repo.setProject( project );
192         repo.setRefid( new Reference( project, Names.ID_CENTRAL ) );
193 
194         RemoteRepositories repos = new RemoteRepositories();
195         repos.setProject( project );
196         repos.addRemoterepo( repo );
197         project.addReference( Names.ID_DEFAULT_REPOS, repos );
198     }
199 
200     public synchronized RepositorySystem getSystem()
201     {
202         if ( repoSys == null )
203         {
204             repoSys = locator.getService( RepositorySystem.class );
205             if ( repoSys == null )
206             {
207                 throw new BuildException( "The repository system could not be initialized" );
208             }
209         }
210         return repoSys;
211     }
212 
213     private synchronized RemoteRepositoryManager getRemoteRepoMan()
214     {
215         if ( remoteRepoMan == null )
216         {
217             remoteRepoMan = locator.getService( RemoteRepositoryManager.class );
218             if ( remoteRepoMan == null )
219             {
220                 throw new BuildException( "The repository system could not be initialized" );
221             }
222         }
223         return remoteRepoMan;
224     }
225 
226     public RepositorySystemSession getSession( Task task, LocalRepository localRepo )
227     {
228         DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
229 
230         final Map<Object, Object> configProps = new LinkedHashMap<>();
231         configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() );
232         configProps.putAll( (Map<?, ?>) project.getProperties() );
233         processServerConfiguration( configProps );
234         session.setConfigProperties( configProps );
235 
236         session.setOffline( isOffline() );
237         session.setUserProperties( project.getUserProperties() );
238 
239         session.setProxySelector( getProxySelector() );
240         session.setMirrorSelector( getMirrorSelector() );
241         session.setAuthenticationSelector( getAuthSelector() );
242 
243         session.setCache( new DefaultRepositoryCache() );
244 
245         session.setRepositoryListener( new AntRepositoryListener( task ) );
246         session.setTransferListener( new AntTransferListener( task ) );
247 
248         session.setLocalRepositoryManager( getLocalRepoMan( session, localRepo ) );
249 
250         session.setWorkspaceReader( ProjectWorkspaceReader.getInstance() );
251 
252         return session;
253     }
254 
255     private String getUserAgent()
256     {
257         StringBuilder buffer = new StringBuilder( 128 );
258 
259         buffer.append( "Apache-Ant/" ).append( project.getProperty( "ant.version" ) );
260         buffer.append( " (" );
261         buffer.append( "Java " ).append( System.getProperty( "java.version" ) );
262         buffer.append( "; " );
263         buffer.append( System.getProperty( "os.name" ) ).append( " " ).append( System.getProperty( "os.version" ) );
264         buffer.append( ")" );
265         buffer.append( " Aether" );
266 
267         return buffer.toString();
268     }
269 
270     private boolean isOffline()
271     {
272         String prop = project.getProperty( Names.PROPERTY_OFFLINE );
273         if ( prop != null )
274         {
275             return Boolean.parseBoolean( prop );
276         }
277         return getSettings().isOffline();
278     }
279 
280     private void processServerConfiguration( Map<Object, Object> configProps )
281     {
282         Settings settings = getSettings();
283         for ( Server server : settings.getServers() )
284         {
285             if ( server.getConfiguration() != null )
286             {
287                 Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
288                 for ( int i = dom.getChildCount() - 1; i >= 0; i-- )
289                 {
290                     Xpp3Dom child = dom.getChild( i );
291                     if ( "wagonProvider".equals( child.getName() ) )
292                     {
293                         dom.removeChild( i );
294                     }
295                     else if ( "httpHeaders".equals( child.getName() ) )
296                     {
297                         configProps.put( ConfigurationProperties.HTTP_HEADERS + "." + server.getId(),
298                                          getHttpHeaders( child ) );
299                     }
300                 }
301 
302                 configProps.put( "aether.connector.wagon.config." + server.getId(), dom );
303             }
304 
305             configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() );
306             configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() );
307         }
308     }
309 
310     private Map<String, String> getHttpHeaders( Xpp3Dom dom )
311     {
312         final Map<String, String> headers = new HashMap<>();
313         for ( int i = 0; i < dom.getChildCount(); i++ )
314         {
315             Xpp3Dom child = dom.getChild( i );
316             Xpp3Dom name = child.getChild( "name" );
317             Xpp3Dom value = child.getChild( "value" );
318             if ( name != null && name.getValue() != null )
319             {
320                 headers.put( name.getValue(), ( value != null ) ? value.getValue() : null );
321             }
322         }
323         return Collections.unmodifiableMap( headers );
324     }
325 
326     private File getDefaultLocalRepoDir()
327     {
328         String dir = project.getProperty( "maven.repo.local" );
329         if ( dir != null )
330         {
331             return project.resolveFile( dir );
332         }
333 
334         Settings settings = getSettings();
335         if ( settings.getLocalRepository() != null )
336         {
337             return new File( settings.getLocalRepository() );
338         }
339 
340         return new File( new File( project.getProperty( "user.home" ), ".m2" ), "repository" );
341     }
342 
343     private LocalRepositoryManager getLocalRepoMan( RepositorySystemSession session, LocalRepository localRepo )
344     {
345         if ( localRepo == null )
346         {
347             localRepo = localRepository;
348         }
349 
350         File repoDir;
351         if ( localRepo != null && localRepo.getDir() != null )
352         {
353             repoDir = localRepo.getDir();
354         }
355         else
356         {
357             repoDir = getDefaultLocalRepoDir();
358         }
359 
360         org.eclipse.aether.repository.LocalRepository repo =
361             new org.eclipse.aether.repository.LocalRepository( repoDir );
362 
363         return getSystem().newLocalRepositoryManager( session, repo );
364     }
365 
366     private synchronized Settings getSettings()
367     {
368         if ( settings == null )
369         {
370             DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
371             request.setUserSettingsFile( getUserSettings() );
372             request.setGlobalSettingsFile( getGlobalSettings() );
373             request.setSystemProperties( getSystemProperties() );
374             request.setUserProperties( getUserProperties() );
375 
376             try
377             {
378                 settings = SETTINGS_BUILDER.build( request ).getEffectiveSettings();
379             }
380             catch ( SettingsBuildingException e )
381             {
382                 project.log( "Could not process settings.xml: " + e.getMessage(), e, Project.MSG_WARN );
383             }
384 
385             SettingsDecryptionResult result =
386                 SETTINGS_DECRYPTER.decrypt( new DefaultSettingsDecryptionRequest( settings ) );
387             settings.setServers( result.getServers() );
388             settings.setProxies( result.getProxies() );
389         }
390         return settings;
391     }
392 
393     private ProxySelector getProxySelector()
394     {
395         DefaultProxySelector selector = new DefaultProxySelector();
396 
397         for ( Proxy proxy : proxies )
398         {
399             selector.add( ConverterUtils.toProxy( proxy ), proxy.getNonProxyHosts() );
400         }
401 
402         Settings settings = getSettings();
403         for ( org.apache.maven.settings.Proxy proxy : settings.getProxies() )
404         {
405             AuthenticationBuilder auth = new AuthenticationBuilder();
406             auth.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() );
407             selector.add( new org.eclipse.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(),
408                                                                    proxy.getPort(), auth.build() ),
409                           proxy.getNonProxyHosts() );
410         }
411 
412         return selector;
413     }
414 
415     private MirrorSelector getMirrorSelector()
416     {
417         DefaultMirrorSelector selector = new DefaultMirrorSelector();
418 
419         for ( Mirror mirror : mirrors )
420         {
421             selector.add( mirror.getId(), mirror.getUrl(), mirror.getType(), false, mirror.getMirrorOf(), null );
422         }
423 
424         Settings settings = getSettings();
425         for ( org.apache.maven.settings.Mirror mirror : settings.getMirrors() )
426         {
427             selector.add( String.valueOf( mirror.getId() ), mirror.getUrl(), mirror.getLayout(), false,
428                           mirror.getMirrorOf(), mirror.getMirrorOfLayouts() );
429         }
430 
431         return selector;
432     }
433 
434     private AuthenticationSelector getAuthSelector()
435     {
436         DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector();
437 
438         final Collection<String> ids = new HashSet<>();
439         for ( Authentication auth : authentications )
440         {
441             List<String> servers = auth.getServers();
442             if ( !servers.isEmpty() )
443             {
444                 org.eclipse.aether.repository.Authentication a = ConverterUtils.toAuthentication( auth );
445                 for ( String server : servers )
446                 {
447                     if ( ids.add( server ) )
448                     {
449                         selector.add( server, a );
450                     }
451                 }
452             }
453         }
454 
455         Settings settings = getSettings();
456         for ( Server server : settings.getServers() )
457         {
458             AuthenticationBuilder auth = new AuthenticationBuilder();
459             auth.addUsername( server.getUsername() ).addPassword( server.getPassword() );
460             auth.addPrivateKey( server.getPrivateKey(), server.getPassphrase() );
461             selector.add( server.getId(), auth.build() );
462         }
463 
464         return new ConservativeAuthenticationSelector( selector );
465     }
466 
467     private RemoteRepositories getRemoteRepositories()
468     {
469         RemoteRepositories remoteRepositories = new RemoteRepositories();
470         remoteRepositories.setProject( project );
471 
472         Settings settings = getSettings();
473         List<String> activeProfiles = settings.getActiveProfiles();
474         for ( String profileId : activeProfiles )
475         {
476             Profile profile = settings.getProfilesAsMap().get( profileId );
477             for ( Repository repository : profile.getRepositories() )
478             {
479                 String id = repository.getId();
480                 RemoteRepository repo = new RemoteRepository();
481                 repo.setProject( project );
482                 repo.setId( id );
483                 repo.setUrl( repository.getUrl() );
484                 if ( repository.getReleases() != null )
485                 {
486                     RepositoryPolicy repositoryPolicy = repository.getReleases();
487                     Policy policy = new Policy();
488                     policy.setEnabled( repositoryPolicy.isEnabled() );
489                     if ( repositoryPolicy.getChecksumPolicy() != null )
490                     {
491                         policy.setChecksums( repositoryPolicy.getChecksumPolicy() );
492                     }
493                     if ( repositoryPolicy.getUpdatePolicy() != null )
494                     {
495                         policy.setUpdates( repositoryPolicy.getUpdatePolicy() );
496                     }
497                     repo.addReleases( policy );
498                 }
499                 if ( repository.getSnapshots() != null )
500                 {
501                     RepositoryPolicy repositoryPolicy = repository.getSnapshots();
502                     Policy policy = new Policy();
503                     policy.setEnabled( repositoryPolicy.isEnabled() );
504                     if ( repositoryPolicy.getChecksumPolicy() != null )
505                     {
506                         policy.setChecksums( repositoryPolicy.getChecksumPolicy() );
507                     }
508                     if ( repositoryPolicy.getUpdatePolicy() != null )
509                     {
510                         policy.setUpdates( repositoryPolicy.getUpdatePolicy() );
511                     }
512                     repo.addSnapshots( policy );
513                 }
514                 project.addReference( id, repo );
515 
516                 repo = new RemoteRepository();
517                 repo.setProject( project );
518                 repo.setRefid( new Reference( project, id ) );
519                 remoteRepositories.addRemoterepo( repo );
520             }
521         }
522 
523         return remoteRepositories;
524     }
525 
526     private RemoteRepositories getMergedRepositories()
527     {
528         RemoteRepositories defaultRepositories = AetherUtils.getDefaultRepositories( project );
529         RemoteRepositories settingsRepositories = getRemoteRepositories();
530 
531         RemoteRepositories mergedRepositories = new RemoteRepositories();
532         mergedRepositories.setProject( project );
533         mergedRepositories.addRemoterepos( defaultRepositories );
534         mergedRepositories.addRemoterepos( settingsRepositories );
535 
536         return mergedRepositories;
537     }
538 
539     public synchronized void setUserSettings( File file )
540     {
541         if ( !eq( this.userSettings, file ) )
542         {
543             settings = null;
544         }
545         this.userSettings = file;
546     }
547 
548     /* UT */File getUserSettings()
549     {
550         if ( userSettings == null )
551         {
552             userSettings = AetherUtils.findUserSettings( project );
553         }
554         return userSettings;
555     }
556 
557     public void setGlobalSettings( File file )
558     {
559         if ( !eq( this.globalSettings, file ) )
560         {
561             settings = null;
562         }
563         this.globalSettings = file;
564     }
565 
566     /* UT */File getGlobalSettings()
567     {
568         if ( globalSettings == null )
569         {
570             globalSettings = AetherUtils.findGlobalSettings( project );
571         }
572         return globalSettings;
573     }
574 
575     public void addProxy( Proxy proxy )
576     {
577         proxies.add( proxy );
578     }
579 
580     public void addMirror( Mirror mirror )
581     {
582         mirrors.add( mirror );
583     }
584 
585     public void addAuthentication( Authentication authentication )
586     {
587         authentications.add( authentication );
588     }
589 
590     public void setLocalRepository( LocalRepository localRepository )
591     {
592         this.localRepository = localRepository;
593     }
594 
595     public Model loadModel( Task task, File pomFile, boolean local, RemoteRepositories remoteRepositories )
596     {
597         RepositorySystemSession session = getSession( task, null );
598 
599         remoteRepositories =
600             remoteRepositories == null ? getMergedRepositories() : remoteRepositories;
601 
602         List<org.eclipse.aether.repository.RemoteRepository> repositories =
603             ConverterUtils.toRepositories( task.getProject(), session, remoteRepositories, getRemoteRepoMan() );
604 
605         ModelResolver modelResolver =
606             new AntModelResolver( session, "project", getSystem(), getRemoteRepoMan(), repositories );
607 
608         Settings settings = getSettings();
609 
610         try
611         {
612             DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
613             request.setLocationTracking( true );
614             request.setProcessPlugins( false );
615             if ( local )
616             {
617                 request.setPomFile( pomFile );
618                 request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
619             }
620             else
621             {
622                 request.setModelSource( new FileModelSource( pomFile ) );
623                 request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
624             }
625             request.setSystemProperties( getSystemProperties() );
626             request.setUserProperties( getUserProperties() );
627             request.setProfiles( SettingsUtils.convert( settings.getProfiles() ) );
628             request.setActiveProfileIds( settings.getActiveProfiles() );
629             request.setModelResolver( modelResolver );
630             return MODEL_BUILDER.build( request ).getEffectiveModel();
631         }
632         catch ( ModelBuildingException e )
633         {
634             throw new BuildException( "Could not load POM " + pomFile + ": " + e.getMessage(), e );
635         }
636     }
637 
638     private Properties getSystemProperties()
639     {
640         Properties props = new Properties();
641         getEnvProperties( props );
642         props.putAll( System.getProperties() );
643         ConverterUtils.addProperties( props, project.getProperties() );
644         return props;
645     }
646 
647     private Properties getEnvProperties( Properties props )
648     {
649         if ( props == null )
650         {
651             props = new Properties();
652         }
653         boolean envCaseInsensitive = OS_WINDOWS;
654         for ( Map.Entry<String, String> entry : System.getenv().entrySet() )
655         {
656             String key = entry.getKey();
657             if ( envCaseInsensitive )
658             {
659                 key = key.toUpperCase( Locale.ENGLISH );
660             }
661             key = "env." + key;
662             props.put( key, entry.getValue() );
663         }
664         return props;
665     }
666 
667     private Properties getUserProperties()
668     {
669         return ConverterUtils.addProperties( null, project.getUserProperties() );
670     }
671 
672     /**
673      * Sets the default POM.
674      */
675     public void setDefaultPom( Pom pom )
676     {
677         this.defaultPom = pom;
678     }
679 
680     /**
681      * Returns the current default POM.
682      */
683     public Pom getDefaultPom()
684     {
685         return defaultPom;
686     }
687 
688     public CollectResult collectDependencies( Task task, Dependencies dependencies, LocalRepository localRepository,
689                                               RemoteRepositories remoteRepositories )
690     {
691         RepositorySystemSession session = getSession( task, localRepository );
692 
693         remoteRepositories =
694             remoteRepositories == null ? getMergedRepositories() : remoteRepositories;
695 
696         List<org.eclipse.aether.repository.RemoteRepository> repos =
697             ConverterUtils.toRepositories( project, session, remoteRepositories, getRemoteRepoMan() );
698 
699         CollectRequest collectRequest = new CollectRequest();
700         collectRequest.setRequestContext( "project" );
701 
702         for ( org.eclipse.aether.repository.RemoteRepository repo : repos )
703         {
704             task.getProject().log( "Using remote repository " + repo, Project.MSG_VERBOSE );
705             collectRequest.addRepository( repo );
706         }
707 
708         if ( dependencies != null )
709         {
710             populateCollectRequest( collectRequest, task, session, dependencies, Collections.<Exclusion>emptyList() );
711         }
712 
713         task.getProject().log( "Collecting dependencies", Project.MSG_VERBOSE );
714 
715         CollectResult result;
716         try
717         {
718             result = getSystem().collectDependencies( session, collectRequest );
719         }
720         catch ( DependencyCollectionException e )
721         {
722             throw new BuildException( "Could not collect dependencies: " + e.getMessage(), e );
723         }
724 
725         return result;
726     }
727 
728     private void populateCollectRequest( CollectRequest collectRequest, Task task, RepositorySystemSession session,
729                                          Dependencies dependencies, List<Exclusion> exclusions )
730     {
731         List<Exclusion> globalExclusions = exclusions;
732         if ( !dependencies.getExclusions().isEmpty() )
733         {
734             globalExclusions = new ArrayList<>( exclusions );
735             globalExclusions.addAll( dependencies.getExclusions() );
736         }
737 
738         final Collection<String> ids = new HashSet<>();
739 
740         for ( DependencyContainer container : dependencies.getDependencyContainers() )
741         {
742             if ( container instanceof Dependency )
743             {
744                 Dependency dep = (Dependency) container;
745                 ids.add( dep.getVersionlessKey() );
746                 collectRequest.addDependency( ConverterUtils.toDependency( dep, globalExclusions, session ) );
747             }
748             else
749             {
750                 populateCollectRequest( collectRequest, task, session, (Dependencies) container, globalExclusions );
751             }
752         }
753 
754         if ( dependencies.getPom() != null )
755         {
756             Model model = dependencies.getPom().getModel( task );
757             for ( org.apache.maven.model.Dependency dep : model.getDependencies() )
758             {
759                 Dependency dependency = new Dependency();
760                 dependency.setArtifactId( dep.getArtifactId() );
761                 dependency.setClassifier( dep.getClassifier() );
762                 dependency.setGroupId( dep.getGroupId() );
763                 dependency.setScope( dep.getScope() );
764                 dependency.setType( dep.getType() );
765                 dependency.setVersion( dep.getVersion() );
766                 if ( ids.contains( dependency.getVersionlessKey() ) )
767                 {
768                     project.log( "Ignoring dependency " + dependency.getVersionlessKey() + " from " + model.getId()
769                         + ", already declared locally", Project.MSG_VERBOSE );
770                     continue;
771                 }
772                 if ( dep.getSystemPath() != null && dep.getSystemPath().length() > 0 )
773                 {
774                     dependency.setSystemPath( task.getProject().resolveFile( dep.getSystemPath() ) );
775                 }
776                 for ( org.apache.maven.model.Exclusion exc : dep.getExclusions() )
777                 {
778                     Exclusion exclusion = new Exclusion();
779                     exclusion.setGroupId( exc.getGroupId() );
780                     exclusion.setArtifactId( exc.getArtifactId() );
781                     exclusion.setClassifier( "*" );
782                     exclusion.setExtension( "*" );
783                     dependency.addExclusion( exclusion );
784                 }
785                 collectRequest.addDependency( ConverterUtils.toDependency( dependency, globalExclusions, session ) );
786             }
787         }
788 
789         if ( dependencies.getFile() != null )
790         {
791             List<Dependency> deps = readDependencies( dependencies.getFile() );
792             for ( Dependency dependency : deps )
793             {
794                 if ( ids.contains( dependency.getVersionlessKey() ) )
795                 {
796                     project.log( "Ignoring dependency " + dependency.getVersionlessKey() + " from "
797                                      + dependencies.getFile() + ", already declared locally", Project.MSG_VERBOSE );
798                     continue;
799                 }
800                 collectRequest.addDependency( ConverterUtils.toDependency( dependency, globalExclusions, session ) );
801             }
802         }
803     }
804 
805     private List<Dependency> readDependencies( File file )
806     {
807         final List<Dependency> dependencies = new ArrayList<>();
808         try
809         {
810             try ( BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream( file ), "UTF-8" ) ) )
811             {
812                 for ( String line = reader.readLine(); line != null; line = reader.readLine() )
813                 {
814                     int comment = line.indexOf( '#' );
815                     if ( comment >= 0 )
816                     {
817                         line = line.substring( 0, comment );
818                     }
819                     line = line.trim();
820                     if ( line.length() <= 0 )
821                     {
822                         continue;
823                     }
824                     Dependency dependency = new Dependency();
825                     dependency.setCoords( line );
826                     dependencies.add( dependency );
827                 }
828             }
829         }
830         catch ( IOException e )
831         {
832             throw new BuildException( "Cannot read " + file, e );
833         }
834         return dependencies;
835     }
836 
837     public void install( Task task, Pom pom, Artifacts artifacts )
838     {
839         RepositorySystemSession session = getSession( task, null );
840 
841         InstallRequest request = new InstallRequest();
842         request.setArtifacts( toArtifacts( task, session, pom, artifacts ) );
843 
844         try
845         {
846             getSystem().install( session, request );
847         }
848         catch ( InstallationException e )
849         {
850             throw new BuildException( "Could not install artifacts: " + e.getMessage(), e );
851         }
852     }
853 
854     public void deploy( Task task, Pom pom, Artifacts artifacts, RemoteRepository releaseRepository,
855                         RemoteRepository snapshotRepository )
856     {
857         RepositorySystemSession session = getSession( task, null );
858 
859         DeployRequest request = new DeployRequest();
860         request.setArtifacts( toArtifacts( task, session, pom, artifacts ) );
861         boolean snapshot = request.getArtifacts().iterator().next().isSnapshot();
862         RemoteRepository distRepo = ( snapshot && snapshotRepository != null ) ? snapshotRepository : releaseRepository;
863         request.setRepository( ConverterUtils.toDistRepository( distRepo, session ) );
864 
865         try
866         {
867             getSystem().deploy( session, request );
868         }
869         catch ( DeploymentException e )
870         {
871             throw new BuildException( "Could not deploy artifacts: " + e.getMessage(), e );
872         }
873     }
874 
875     private List<org.eclipse.aether.artifact.Artifact> toArtifacts( Task task, RepositorySystemSession session,
876                                                                     Pom pom, Artifacts artifacts )
877     {
878         Model model = pom.getModel( task );
879         File pomFile = pom.getFile();
880 
881         final List<org.eclipse.aether.artifact.Artifact> results = new ArrayList<>();
882 
883         org.eclipse.aether.artifact.Artifact pomArtifact =
884             new DefaultArtifact( model.getGroupId(), model.getArtifactId(), "pom", model.getVersion() ).setFile( pomFile );
885         results.add( pomArtifact );
886 
887         for ( Artifact artifact : artifacts.getArtifacts() )
888         {
889             org.eclipse.aether.artifact.Artifact buildArtifact =
890                 new DefaultArtifact( model.getGroupId(), model.getArtifactId(), artifact.getClassifier(),
891                                      artifact.getType(), model.getVersion() ).setFile( artifact.getFile() );
892             results.add( buildArtifact );
893         }
894 
895         return results;
896     }
897 
898 }