View Javadoc

1   package org.apache.maven.settings;
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 org.apache.maven.settings.io.xpp3.SettingsXpp3Reader;
23  import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
24  import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
25  import org.codehaus.plexus.logging.AbstractLogEnabled;
26  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
27  import org.codehaus.plexus.util.IOUtil;
28  import org.codehaus.plexus.util.ReaderFactory;
29  import org.codehaus.plexus.util.StringUtils;
30  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
31  
32  import java.io.File;
33  import java.io.IOException;
34  import java.io.Reader;
35  import java.io.StringReader;
36  import java.io.StringWriter;
37  import java.util.Iterator;
38  import java.util.List;
39  
40  /**
41   * @author jdcasey
42   * @version $Id: DefaultMavenSettingsBuilder.java 747683 2009-02-25 06:52:54Z brett $
43   */
44  public class DefaultMavenSettingsBuilder
45      extends AbstractLogEnabled
46      implements MavenSettingsBuilder, Initializable
47  {
48      public static final String userHome = System.getProperty( "user.home" );
49  
50      /**
51       * @configuration
52       */
53      private String userSettingsPath;
54  
55      /**
56       * @configuration
57       */
58      private String globalSettingsPath;
59  
60      private File userSettingsFile;
61  
62      private File globalSettingsFile;
63  
64      private Settings loadedSettings;
65  
66      // ----------------------------------------------------------------------
67      // Component Lifecycle
68      // ----------------------------------------------------------------------
69  
70      public void initialize()
71      {
72          userSettingsFile =
73              getFile( userSettingsPath, "user.home", MavenSettingsBuilder.ALT_USER_SETTINGS_XML_LOCATION );
74  
75          globalSettingsFile =
76              getFile( globalSettingsPath, "maven.home", MavenSettingsBuilder.ALT_GLOBAL_SETTINGS_XML_LOCATION );
77  
78          getLogger().debug(
79              "Building Maven global-level settings from: '" + globalSettingsFile.getAbsolutePath() + "'" );
80          getLogger().debug( "Building Maven user-level settings from: '" + userSettingsFile.getAbsolutePath() + "'" );
81      }
82  
83      // ----------------------------------------------------------------------
84      // MavenProfilesBuilder Implementation
85      // ----------------------------------------------------------------------
86  
87      private Settings readSettings( File settingsFile )
88          throws IOException, XmlPullParserException
89      {
90          Settings settings = null;
91  
92          if ( settingsFile != null && settingsFile.exists() && settingsFile.isFile() )
93          {
94              Reader reader = null;
95              try
96              {
97                  reader = ReaderFactory.newXmlReader( settingsFile );
98                  StringWriter sWriter = new StringWriter();
99  
100                 IOUtil.copy( reader, sWriter );
101 
102                 String rawInput = sWriter.toString();
103 
104                 try
105                 {
106                     RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
107                     interpolator.addValueSource( new EnvarBasedValueSource() );
108 
109                     rawInput = interpolator.interpolate( rawInput, "settings" );
110                 }
111                 catch ( Exception e )
112                 {
113                     getLogger().warn(
114                         "Failed to initialize environment variable resolver. Skipping environment substitution in settings." );
115                     getLogger().debug( "Failed to initialize envar resolver. Skipping resolution.", e );
116                 }
117 
118                 StringReader sReader = new StringReader( rawInput );
119 
120                 SettingsXpp3Reader modelReader = new SettingsXpp3Reader();
121 
122                 settings = modelReader.read( sReader, true );
123 
124                 RuntimeInfo rtInfo = new RuntimeInfo( settings );
125 
126                 rtInfo.setFile( settingsFile );
127 
128                 settings.setRuntimeInfo( rtInfo );
129             }
130             finally
131             {
132                 IOUtil.close( reader );
133             }
134         }
135 
136         return settings;
137     }
138 
139     public Settings buildSettings()
140         throws IOException, XmlPullParserException
141     {
142         return buildSettings( userSettingsFile );
143     }
144 
145     public Settings buildSettings( boolean useCachedSettings )
146         throws IOException, XmlPullParserException
147     {
148         return buildSettings( userSettingsFile, useCachedSettings );
149     }
150 
151     public Settings buildSettings( File userSettingsFile )
152         throws IOException, XmlPullParserException
153     {
154         return buildSettings( userSettingsFile, true );
155     }
156 
157     public Settings buildSettings( File userSettingsFile, boolean useCachedSettings )
158         throws IOException, XmlPullParserException
159     {
160         if ( !useCachedSettings || loadedSettings == null )
161         {
162             Settings globalSettings = readSettings( globalSettingsFile );
163             Settings userSettings = readSettings( userSettingsFile );
164 
165             if ( globalSettings == null )
166             {
167                 globalSettings = new Settings();
168             }
169 
170             if ( userSettings == null )
171             {
172                 userSettings = new Settings();
173                 userSettings.setRuntimeInfo( new RuntimeInfo( userSettings ) );
174             }
175 
176             SettingsUtils.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL );
177 
178             activateDefaultProfiles( userSettings );
179 
180             setLocalRepository( userSettings );
181 
182             loadedSettings = userSettings;
183         }
184 
185         return loadedSettings;
186     }
187 
188     private void activateDefaultProfiles( Settings settings )
189     {
190         List activeProfiles = settings.getActiveProfiles();
191 
192         for ( Iterator profiles = settings.getProfiles().iterator(); profiles.hasNext(); )
193         {
194             Profile profile = (Profile) profiles.next();
195             if ( profile.getActivation() != null && profile.getActivation().isActiveByDefault()
196                 && !activeProfiles.contains( profile.getId() ) )
197             {
198                 settings.addActiveProfile( profile.getId() );
199             }
200         }
201     }
202 
203     private void setLocalRepository( Settings userSettings )
204     {
205         // try using the local repository specified on the command line...
206         String localRepository = System.getProperty( MavenSettingsBuilder.ALT_LOCAL_REPOSITORY_LOCATION );
207 
208         // otherwise, use the one in settings.xml
209         if ( localRepository == null || localRepository.length() < 1 )
210         {
211             localRepository = userSettings.getLocalRepository();
212         }
213 
214         // if all of the above are missing, default to ~/.m2/repository.
215         if ( localRepository == null || localRepository.length() < 1 )
216         {
217             File mavenUserConfigurationDirectory = new File( userHome, ".m2" );
218             if ( !mavenUserConfigurationDirectory.exists() )
219             {
220                 if ( !mavenUserConfigurationDirectory.mkdirs() )
221                 {
222                     //throw a configuration exception
223                 }
224             }
225 
226             localRepository = new File( mavenUserConfigurationDirectory, "repository" ).getAbsolutePath();
227         }
228 
229         // for the special case of a drive-relative Windows path, make sure it's absolute to save plugins from trouble
230         File file = new File( localRepository );
231         if ( !file.isAbsolute() && file.getPath().startsWith( File.separator ) )
232         {
233             localRepository = file.getAbsolutePath();
234         }
235 
236         userSettings.setLocalRepository( localRepository );
237     }
238 
239     private File getFile( String pathPattern, String basedirSysProp, String altLocationSysProp )
240     {
241         // -------------------------------------------------------------------------------------
242         // Alright, here's the justification for all the regexp wizardry below...
243         //
244         // Continuum and other server-like apps may need to locate the user-level and 
245         // global-level settings somewhere other than ${user.home} and ${maven.home},
246         // respectively. Using a simple replacement of these patterns will allow them
247         // to specify the absolute path to these files in a customized components.xml
248         // file. Ideally, we'd do full pattern-evaluation against the sysprops, but this
249         // is a first step. There are several replacements below, in order to normalize
250         // the path character before we operate on the string as a regex input, and 
251         // in order to avoid surprises with the File construction...
252         // -------------------------------------------------------------------------------------
253 
254         String path = System.getProperty( altLocationSysProp );
255 
256         if ( StringUtils.isEmpty( path ) )
257         {
258             // TODO: This replacing shouldn't be necessary as user.home should be in the
259             // context of the container and thus the value would be interpolated by Plexus
260             String basedir = System.getProperty( basedirSysProp );
261             if ( basedir == null )
262             {
263                 basedir = System.getProperty( "user.dir" );
264             }
265 
266             basedir = basedir.replaceAll( "\\\\", "/" );
267             basedir = basedir.replaceAll( "\\$", "\\\\\\$" );
268 
269             path = pathPattern.replaceAll( "\\$\\{" + basedirSysProp + "\\}", basedir );
270             path = path.replaceAll( "\\\\", "/" );
271             // ---------------------------------------------------------------------------------
272             // I'm not sure if this last regexp was really intended to disallow the usage of
273             // network paths as user.home directory. Unfortunately it did. I removed it and 
274             // have not detected any problems yet.
275             // ---------------------------------------------------------------------------------
276             // path = path.replaceAll( "//", "/" );
277 
278             return new File( path ).getAbsoluteFile();
279         }
280         else
281         {
282             return new File( path ).getAbsoluteFile();
283         }
284     }
285 
286 }