package org.codehaus.mojo.setup;
/*
* 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.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.List;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.shared.filtering.MavenFileFilter;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.codehaus.mojo.setup.SetupExecutionRequest.MergeType;
import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
/**
* @author Robert Scholte
* @since 1.0.0
*/
public abstract class AbstractSetupManager
implements SetupManager, LogEnabled
{
/**
* @plexus.requirement
*/
private MavenFileFilter mavenFileFilter;
private Logger log;
protected final Logger getLog()
{
return log;
}
public void process( SetupExecutionRequest request )
throws SetupExecutionException
{
validateRequest( request );
File targetReadFile = getTargetFile( request.getSession() );
File templateFile = null;
if ( request.getTemplateFile() != null )
{
templateFile = filter( request );
}
Reader targetSettingsFileReader = null;
if ( MergeType.EXPAND.equals( request.getMergeType() ) || MergeType.UPDATE.equals( request.getMergeType() ) )
{
try
{
Reader currentSettingsFileReader = null;
currentSettingsFileReader = new FileReader( targetReadFile );
Reader inputSettingsFileReader = null;
inputSettingsFileReader = new FileReader( templateFile );
if ( MergeType.EXPAND.equals( request.getMergeType() ) )
{
targetSettingsFileReader = merge( currentSettingsFileReader, inputSettingsFileReader );
}
else if ( MergeType.UPDATE.equals( request.getMergeType() ) )
{
targetSettingsFileReader = merge( inputSettingsFileReader, currentSettingsFileReader );
}
}
catch ( FileNotFoundException e )
{
throw new SetupExecutionException( e.getMessage(), e );
}
}
else if ( templateFile != null )
{
try
{
targetSettingsFileReader = new FileReader( templateFile );
}
catch ( FileNotFoundException e )
{
// nop, already checked
}
}
else if ( targetReadFile.exists() )
{
try
{
targetSettingsFileReader = new FileReader( targetReadFile );
}
catch ( FileNotFoundException e )
{
// nop, already checked
}
}
if ( !request.getAdditionalProperties().isEmpty() )
{
targetSettingsFileReader = postMerge( targetSettingsFileReader, request );
}
File targetWriteFile;
if ( request.isDryRun() )
{
String targetFileName = getTargetFile( request.getSession() ).getName();
String targetDirectoryName = getTargetFile( request.getSession() ).getParentFile().getName();
targetWriteFile = new File( targetDirectoryName, targetFileName );
}
else
{
targetWriteFile = getTargetFile( request.getSession() );
}
if ( log.isDebugEnabled() ) {
getLog().debug( "Writing to " + targetWriteFile.getAbsolutePath() );
}
if ( !MergeType.NONE.equals( request.getMergeType() ) )
{
if ( targetWriteFile.exists() )
{
createBackupFile( targetWriteFile );
}
else
{
targetWriteFile.getParentFile().mkdirs();
}
try
{
IOUtil.copy( targetSettingsFileReader, new FileWriter( targetWriteFile ) );
}
catch ( IOException e )
{
throw new SetupExecutionException( e.getMessage(), e );
}
}
}
/**
* check if we have enough data to process the setuprequest
*
* @param request
* @throws SetupExecutionException
*/
private void validateRequest( SetupExecutionRequest request )
throws SetupExecutionException
{
if ( request == null )
{
throw new SetupExecutionException( "request is null" );
}
if ( request.getTemplateFile() == null && request.getAdditionalProperties().isEmpty() )
{
throw new SetupExecutionException( "missing template or additional properties" );
}
if ( request.getTemplateFile() != null && !( request.getTemplateFile().exists()
&& request.getTemplateFile().isFile() ) )
{
throw new SetupExecutionException( request.getTemplateFile() + " doesn't exist or is not a file" );
}
if ( getTargetFile( request.getSession() ).exists() && request.getMergeType() == null )
{
throw new SetupExecutionException( "Targetfile exists, so a mergetype is required" );
}
}
/**
* Give the opportunity to do some extra processing after the merge, based on the request. By default just return
* the incoming reader
*
* @param targetSettingsFileReader
* @param request
* @return
* @throws SetupMergeException
*/
protected Reader postMerge( Reader targetSettingsFileReader, SetupExecutionRequest request )
throws SetupMergeException
{
return targetSettingsFileReader;
}
/**
* @param targetFile existing file
* @throws SetupExecutionException
*/
@SuppressWarnings( "unchecked" )
private void createBackupFile( File targetFile )
throws SetupExecutionException
{
String includes = FileUtils.basename( targetFile.getAbsolutePath() ) + ".*";
try
{
List < String > fileNames = FileUtils.getFileNames( targetFile.getParentFile(), includes, null, true );
int lastBackupIndex = -1;
for ( String fileName : fileNames )
{
String extension = FileUtils.extension( fileName );
if ( "bak".equals( extension ) )
{
lastBackupIndex++;
}
else if ( extension.matches( "bak\\d+" ) )
{
lastBackupIndex = Math.max( lastBackupIndex, Integer.parseInt( extension.substring( 3 ) ) );
}
}
File backupFile =
FileUtils.getFile( targetFile.getAbsolutePath() + ".bak"
+ ( lastBackupIndex == -1 ? "" : ++lastBackupIndex ) );
FileUtils.copyFile( targetFile, backupFile );
}
catch ( IOException e )
{
throw new SetupExecutionException( " Failed to create backupfile" );
}
}
protected abstract String getPrototypeFilename();
/**
* Use Readers to keep most logic in this class
*
* @param dominant
* @param recessive
* @return
* @throws SetupMergeException
*/
protected abstract Reader merge( Reader dominant, Reader recessive )
throws SetupMergeException;
protected abstract File getTargetFile( MavenSession session );
protected void write( Reader reader, MavenSession session )
throws IOException
{
IOUtil.copy( reader, new FileWriter( getTargetFile( session ) ) );
}
/**
* @param from
* @param to
* @param propertiesFilePaths
* @throws IOException
*/
@SuppressWarnings( "unchecked" )
protected File filter( SetupExecutionRequest request )
throws SetupExecutionException
{
File result = FileUtils.createTempFile( request.getTemplateFile().getName(), "-filtered", null );
if ( getLog().isDebugEnabled() )
{
getLog().debug( "Create temporary file: " + result.getAbsolutePath() );
getLog().debug( "Temporary file won't be deleted while debugging" );
}
else
{
result.deleteOnExit();
}
try
{
List < FileUtils.FilterWrapper > filterWrappers =
mavenFileFilter.getDefaultFilterWrappers( null, request.getPropertyFilenames(), true,
request.getSession(), null );
FileUtils.copyFile( request.getTemplateFile(), result, request.getEncoding(),
filterWrappers.toArray( new FileUtils.FilterWrapper[0] ), true );
}
catch ( MavenFilteringException e )
{
throw new SetupExecutionException( e.getMessage() );
}
catch ( IOException e )
{
throw new SetupExecutionException( e.getMessage() );
}
return result;
}
public InputStream getPrototypeInputStream()
throws IOException
{
return this.getClass().getClassLoader().getResource( getPrototypeFilename() ).openStream();
}
public void enableLogging( Logger logger )
{
this.log = logger;
}
}