blob: f10643dc19754a49d6c5b687b7ab42e2dada4f7c [file] [log] [blame]
package org.apache.maven.settings;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;
/**
* @author jdcasey
* @version $Id$
*/
public class DefaultMavenSettingsBuilder
extends AbstractLogEnabled
implements MavenSettingsBuilder, Initializable
{
public static final String userHome = System.getProperty( "user.home" );
/**
* @configuration
*/
private String userSettingsPath;
/**
* @configuration
*/
private String globalSettingsPath;
private File userSettingsFile;
private File globalSettingsFile;
private Settings loadedSettings;
// ----------------------------------------------------------------------
// Component Lifecycle
// ----------------------------------------------------------------------
public void initialize()
{
userSettingsFile =
getFile( userSettingsPath, "user.home", MavenSettingsBuilder.ALT_USER_SETTINGS_XML_LOCATION );
globalSettingsFile =
getFile( globalSettingsPath, "maven.home", MavenSettingsBuilder.ALT_GLOBAL_SETTINGS_XML_LOCATION );
getLogger().debug(
"Building Maven global-level settings from: '" + globalSettingsFile.getAbsolutePath() + "'" );
getLogger().debug( "Building Maven user-level settings from: '" + userSettingsFile.getAbsolutePath() + "'" );
}
// ----------------------------------------------------------------------
// MavenProfilesBuilder Implementation
// ----------------------------------------------------------------------
private Settings readSettings( File settingsFile )
throws IOException, XmlPullParserException
{
Settings settings = null;
if ( settingsFile != null && settingsFile.exists() && settingsFile.isFile() )
{
Reader reader = null;
try
{
reader = ReaderFactory.newXmlReader( settingsFile );
StringWriter sWriter = new StringWriter();
IOUtil.copy( reader, sWriter );
String rawInput = sWriter.toString();
try
{
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
interpolator.addValueSource( new EnvarBasedValueSource() );
rawInput = interpolator.interpolate( rawInput, "settings" );
}
catch ( Exception e )
{
getLogger().warn(
"Failed to initialize environment variable resolver. Skipping environment substitution in settings." );
getLogger().debug( "Failed to initialize envar resolver. Skipping resolution.", e );
}
StringReader sReader = new StringReader( rawInput );
SettingsXpp3Reader modelReader = new SettingsXpp3Reader();
settings = modelReader.read( sReader, true );
RuntimeInfo rtInfo = new RuntimeInfo( settings );
rtInfo.setFile( settingsFile );
settings.setRuntimeInfo( rtInfo );
}
finally
{
IOUtil.close( reader );
}
}
return settings;
}
public Settings buildSettings()
throws IOException, XmlPullParserException
{
return buildSettings( userSettingsFile );
}
public Settings buildSettings( boolean useCachedSettings )
throws IOException, XmlPullParserException
{
return buildSettings( userSettingsFile, useCachedSettings );
}
public Settings buildSettings( File userSettingsFile )
throws IOException, XmlPullParserException
{
return buildSettings( userSettingsFile, true );
}
public Settings buildSettings( File userSettingsFile, boolean useCachedSettings )
throws IOException, XmlPullParserException
{
if ( !useCachedSettings || loadedSettings == null )
{
Settings globalSettings = readSettings( globalSettingsFile );
Settings userSettings = readSettings( userSettingsFile );
if ( globalSettings == null )
{
globalSettings = new Settings();
}
if ( userSettings == null )
{
userSettings = new Settings();
userSettings.setRuntimeInfo( new RuntimeInfo( userSettings ) );
}
SettingsUtils.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL );
activateDefaultProfiles( userSettings );
setLocalRepository( userSettings );
loadedSettings = userSettings;
}
return loadedSettings;
}
private void activateDefaultProfiles( Settings settings )
{
List<String> activeProfiles = settings.getActiveProfiles();
for ( Profile profile : settings.getProfiles() )
{
if ( profile.getActivation() != null && profile.getActivation().isActiveByDefault()
&& !activeProfiles.contains( profile.getId() ) )
{
settings.addActiveProfile( profile.getId() );
}
}
}
private void setLocalRepository( Settings userSettings )
{
// try using the local repository specified on the command line...
String localRepository = System.getProperty( MavenSettingsBuilder.ALT_LOCAL_REPOSITORY_LOCATION );
// otherwise, use the one in settings.xml
if ( localRepository == null || localRepository.length() < 1 )
{
localRepository = userSettings.getLocalRepository();
}
// if all of the above are missing, default to ~/.m2/repository.
if ( localRepository == null || localRepository.length() < 1 )
{
File mavenUserConfigurationDirectory = new File( userHome, ".m2" );
if ( !mavenUserConfigurationDirectory.exists() )
{
if ( !mavenUserConfigurationDirectory.mkdirs() )
{
//throw a configuration exception
}
}
localRepository = new File( mavenUserConfigurationDirectory, "repository" ).getAbsolutePath();
}
// for the special case of a drive-relative Windows path, make sure it's absolute to save plugins from trouble
File file = new File( localRepository );
if ( !file.isAbsolute() && file.getPath().startsWith( File.separator ) )
{
localRepository = file.getAbsolutePath();
}
userSettings.setLocalRepository( localRepository );
}
private File getFile( String pathPattern, String basedirSysProp, String altLocationSysProp )
{
// -------------------------------------------------------------------------------------
// Alright, here's the justification for all the regexp wizardry below...
//
// Continuum and other server-like apps may need to locate the user-level and
// global-level settings somewhere other than ${user.home} and ${maven.home},
// respectively. Using a simple replacement of these patterns will allow them
// to specify the absolute path to these files in a customized components.xml
// file. Ideally, we'd do full pattern-evaluation against the sysprops, but this
// is a first step. There are several replacements below, in order to normalize
// the path character before we operate on the string as a regex input, and
// in order to avoid surprises with the File construction...
// -------------------------------------------------------------------------------------
String path = System.getProperty( altLocationSysProp );
if ( StringUtils.isEmpty( path ) )
{
// TODO: This replacing shouldn't be necessary as user.home should be in the
// context of the container and thus the value would be interpolated by Plexus
String basedir = System.getProperty( basedirSysProp );
if ( basedir == null )
{
basedir = System.getProperty( "user.dir" );
}
basedir = basedir.replaceAll( "\\\\", "/" );
basedir = basedir.replaceAll( "\\$", "\\\\\\$" );
path = pathPattern.replaceAll( "\\$\\{" + basedirSysProp + "\\}", basedir );
path = path.replaceAll( "\\\\", "/" );
// ---------------------------------------------------------------------------------
// I'm not sure if this last regexp was really intended to disallow the usage of
// network paths as user.home directory. Unfortunately it did. I removed it and
// have not detected any problems yet.
// ---------------------------------------------------------------------------------
// path = path.replaceAll( "//", "/" );
return new File( path ).getAbsoluteFile();
}
else
{
return new File( path ).getAbsoluteFile();
}
}
}