blob: b4685ef0404a15fb8f5ba80b18af189d756e9ece [file] [log] [blame]
package org.apache.maven.shared.release.config;
/*
* 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 java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.maven.model.Scm;
import org.apache.maven.shared.release.scm.IdentifiedScm;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.IOUtil;
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
import org.sonatype.plexus.components.cipher.PlexusCipherException;
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
/**
* Read and write release configuration and state from a properties file.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @plexus.component role="org.apache.maven.shared.release.config.ReleaseDescriptorStore" role-hint="properties"
*/
public class PropertiesReleaseDescriptorStore
extends AbstractLogEnabled
implements ReleaseDescriptorStore
{
/**
* When this plugin requires Maven 3.0 as minimum, this component can be removed and o.a.m.s.c.SettingsDecrypter be
* used instead.
*
* @plexus.requirement role="org.sonatype.plexus.components.sec.dispatcher.SecDispatcher" role-hint="mng-4384"
*/
private DefaultSecDispatcher secDispatcher;
public ReleaseDescriptor read( ReleaseDescriptor mergeDescriptor )
throws ReleaseDescriptorStoreException
{
return read( mergeDescriptor, getDefaultReleasePropertiesFile( mergeDescriptor ) );
}
public ReleaseDescriptor read( File file )
throws ReleaseDescriptorStoreException
{
return read( null, file );
}
public ReleaseDescriptor read( ReleaseDescriptor mergeDescriptor, File file )
throws ReleaseDescriptorStoreException
{
Properties properties = new Properties();
InputStream inStream = null;
try
{
inStream = new FileInputStream( file );
properties.load( inStream );
}
catch ( FileNotFoundException e )
{
getLogger().debug( file.getName() + " not found - using empty properties" );
}
catch ( IOException e )
{
throw new ReleaseDescriptorStoreException(
"Error reading properties file '" + file.getName() + "': " + e.getMessage(), e );
}
finally
{
IOUtil.close( inStream );
}
ReleaseDescriptor releaseDescriptor = ReleaseUtils.copyPropertiesToReleaseDescriptor( properties );
if ( mergeDescriptor != null )
{
releaseDescriptor = ReleaseUtils.merge( releaseDescriptor, mergeDescriptor );
}
return releaseDescriptor;
}
public void write( ReleaseDescriptor config )
throws ReleaseDescriptorStoreException
{
write( config, getDefaultReleasePropertiesFile( config ) );
}
public void delete( ReleaseDescriptor config )
{
File file = getDefaultReleasePropertiesFile( config );
if ( file.exists() )
{
file.delete();
}
}
public void write( ReleaseDescriptor config, File file )
throws ReleaseDescriptorStoreException
{
Properties properties = new Properties();
properties.setProperty( "completedPhase", config.getCompletedPhase() );
if ( config.isCommitByProject() ) //default is false
{
properties.setProperty( "commitByProject", "true" );
}
properties.setProperty( "scm.url", config.getScmSourceUrl() );
if ( config.getScmId() != null )
{
properties.setProperty( "scm.id", config.getScmId() );
}
if ( config.getScmUsername() != null )
{
properties.setProperty( "scm.username", config.getScmUsername() );
}
if ( config.getScmPassword() != null )
{
String password = config.getScmPassword();
try
{
password = encryptAndDecorate( password );
}
catch ( IllegalStateException e )
{
getLogger().debug( e.getMessage() );
}
catch ( SecDispatcherException e )
{
getLogger().debug( e.getMessage() );
}
catch ( PlexusCipherException e )
{
getLogger().debug( e.getMessage() );
}
properties.setProperty( "scm.password", password );
}
if ( config.getScmPrivateKey() != null )
{
properties.setProperty( "scm.privateKey", config.getScmPrivateKey() );
}
if ( config.getScmPrivateKeyPassPhrase() != null )
{
String passPhrase = config.getScmPrivateKeyPassPhrase();
try
{
passPhrase = encryptAndDecorate( passPhrase );
}
catch ( IllegalStateException e )
{
getLogger().debug( e.getMessage() );
}
catch ( SecDispatcherException e )
{
getLogger().debug( e.getMessage() );
}
catch ( PlexusCipherException e )
{
getLogger().debug( e.getMessage() );
}
properties.setProperty( "scm.passphrase", passPhrase );
}
if ( config.getScmTagBase() != null )
{
properties.setProperty( "scm.tagBase", config.getScmTagBase() );
}
if ( config.getScmBranchBase() != null )
{
properties.setProperty( "scm.branchBase", config.getScmBranchBase() );
}
if ( config.getScmReleaseLabel() != null )
{
properties.setProperty( "scm.tag", config.getScmReleaseLabel() );
}
if ( config.getScmTagNameFormat() != null )
{
properties.setProperty( "scm.tagNameFormat", config.getScmTagNameFormat() );
}
if ( config.getScmCommentPrefix() != null )
{
properties.setProperty( "scm.commentPrefix", config.getScmCommentPrefix() );
}
if ( config.getAdditionalArguments() != null )
{
properties.setProperty( "exec.additionalArguments", config.getAdditionalArguments() );
}
if ( config.getPomFileName() != null )
{
properties.setProperty( "exec.pomFileName", config.getPomFileName() );
}
if ( config.getPreparationGoals() != null )
{
properties.setProperty( "preparationGoals", config.getPreparationGoals() );
}
if ( config.getCompletionGoals() != null )
{
properties.setProperty( "completionGoals", config.getCompletionGoals() );
}
if ( config.getProjectVersionPolicyId() != null )
{
properties.setProperty( "projectVersionPolicyId", config.getProjectVersionPolicyId() );
}
properties.setProperty( "exec.snapshotReleasePluginAllowed",
Boolean.toString( config.isSnapshotReleasePluginAllowed() ) );
properties.setProperty( "remoteTagging", Boolean.toString( config.isRemoteTagging() ) );
properties.setProperty( "pushChanges", Boolean.toString( config.isPushChanges() ) );
// others boolean properties are not written to the properties file because the value from the caller is always
// used
for ( Iterator<?> i = config.getReleaseVersions().entrySet().iterator(); i.hasNext(); )
{
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
properties.setProperty( "project.rel." + entry.getKey(), (String) entry.getValue() );
}
for ( Iterator<?> i = config.getDevelopmentVersions().entrySet().iterator(); i.hasNext(); )
{
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
properties.setProperty( "project.dev." + entry.getKey(), (String) entry.getValue() );
}
for ( Iterator<?> i = config.getOriginalScmInfo().entrySet().iterator(); i.hasNext(); )
{
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
Scm scm = (Scm) entry.getValue();
String prefix = "project.scm." + entry.getKey();
if ( scm != null )
{
if ( scm.getConnection() != null )
{
properties.setProperty( prefix + ".connection", scm.getConnection() );
}
if ( scm.getDeveloperConnection() != null )
{
properties.setProperty( prefix + ".developerConnection", scm.getDeveloperConnection() );
}
if ( scm.getUrl() != null )
{
properties.setProperty( prefix + ".url", scm.getUrl() );
}
if ( scm.getTag() != null )
{
properties.setProperty( prefix + ".tag", scm.getTag() );
}
if ( scm instanceof IdentifiedScm )
{
IdentifiedScm identifiedScm = (IdentifiedScm) scm;
if ( identifiedScm.getId() != null )
{
properties.setProperty( prefix + ".id", identifiedScm.getId() );
}
}
}
else
{
properties.setProperty( prefix + ".empty", "true" );
}
}
if ( ( config.getResolvedSnapshotDependencies() != null )
&& ( config.getResolvedSnapshotDependencies().size() > 0 ) )
{
processResolvedDependencies( properties, config.getResolvedSnapshotDependencies() );
}
OutputStream outStream = null;
//noinspection OverlyBroadCatchBlock
try
{
outStream = new FileOutputStream( file );
properties.store( outStream, "release configuration" );
}
catch ( IOException e )
{
throw new ReleaseDescriptorStoreException(
"Error writing properties file '" + file.getName() + "': " + e.getMessage(), e );
}
finally
{
IOUtil.close( outStream );
}
}
private void processResolvedDependencies( Properties prop, Map<?, ?> resolvedDependencies )
{
Set<?> entries = resolvedDependencies.entrySet();
Iterator<?> iterator = entries.iterator();
Entry<?, ?> currentEntry;
while ( iterator.hasNext() )
{
currentEntry = (Entry<?, ?>) iterator.next();
Map<?, ?> versionMap = (Map<?, ?>) currentEntry.getValue();
prop.setProperty( "dependency." + currentEntry.getKey() + ".release",
(String) versionMap.get( ReleaseDescriptor.RELEASE_KEY ) );
prop.setProperty( "dependency." + currentEntry.getKey() + ".development",
(String) versionMap.get( ReleaseDescriptor.DEVELOPMENT_KEY ) );
}
}
private static File getDefaultReleasePropertiesFile( ReleaseDescriptor mergeDescriptor )
{
return new File( mergeDescriptor.getWorkingDirectory(), "release.properties" );
}
// From org.apache.maven.cli.MavenCli.encryption(CliRequest)
private String encryptAndDecorate( String passwd ) throws IllegalStateException, SecDispatcherException, PlexusCipherException
{
String configurationFile = secDispatcher.getConfigurationFile();
if ( configurationFile.startsWith( "~" ) )
{
configurationFile = System.getProperty( "user.home" ) + configurationFile.substring( 1 );
}
String file = System.getProperty( DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile );
String master = null;
SettingsSecurity sec = SecUtil.read( file, true );
if ( sec != null )
{
master = sec.getMaster();
}
if ( master == null )
{
throw new IllegalStateException( "Master password is not set in the setting security file: " + file );
}
DefaultPlexusCipher cipher = new DefaultPlexusCipher();
String masterPasswd = cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
return cipher.encryptAndDecorate( passwd, masterPasswd );
}
}