/*
* Copyright 2006-2014 smartics, Kronseder & Reiner GmbH
*
* Licensed 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.
*/
package com.redhat.rcm.maven.plugin.buildmetadata.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
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.io.PrintWriter;
import java.io.StringReader;
import java.io.Writer;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.Manifest;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import com.redhat.rcm.maven.plugin.buildmetadata.BuildReportMojo;
import com.redhat.rcm.maven.plugin.buildmetadata.common.Constant;
import com.redhat.rcm.maven.plugin.buildmetadata.common.MojoUtils;
import com.redhat.rcm.maven.plugin.buildmetadata.common.SortedProperties;
import com.redhat.rcm.maven.plugin.buildmetadata.util.FilePathNormalizer;
/**
* Helper to handle the build meta data properties file.
*
* @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
* @version $Revision:591 $
*/
public final class BuildPropertiesFileHelper
{
// ********************************* Fields *********************************
// --- constants ------------------------------------------------------------
// --- members --------------------------------------------------------------
/**
* The logger to use.
*/
private final Log log;
/**
* The file to write to.
*/
private final File propertiesOutputFile;
/**
* The normalizer to be applied to file name value to remove the base dir
* prefix.
*/
private final FilePathNormalizer filePathNormalizer;
// ****************************** Initializer *******************************
// ****************************** Constructors ******************************
/**
* Default constructor.
*
* @param log the logger to use.
* @param propertiesOutputFile the file to write to.
* @param filePathNormalizer the normalizer to be applied to file name value
* to remove the base dir prefix.
*/
public BuildPropertiesFileHelper(final Log log,
final File propertiesOutputFile,
final FilePathNormalizer filePathNormalizer)
{
this.log = log;
this.propertiesOutputFile = propertiesOutputFile;
this.filePathNormalizer = filePathNormalizer;
}
// ****************************** Inner Classes *****************************
// ********************************* Methods ********************************
// --- init -----------------------------------------------------------------
// --- get&set --------------------------------------------------------------
// --- business -------------------------------------------------------------
/**
* Writes the build meta data properties to the target file.
*
* @param buildMetaDataProperties the properties to write.
* @return the reference to the written file.
* @throws MojoExecutionException on any problem encountered while writing the
* properties.
*/
public File writePropertiesFile(final Properties buildMetaDataProperties)
throws MojoExecutionException
{
final File buildMetaDataFile =
createBuildMetaDataFile(propertiesOutputFile);
if (log.isInfoEnabled())
{
log.info("Writing properties '" + buildMetaDataFile.getAbsolutePath()
+ "'...");
}
//OutputStream out = null;
PrintWriter out = null;
try
{
out = new PrintWriter (buildMetaDataFile);
final String comments = "# Created by buildmetadata-maven-plugin " + getManifestInformation();
final Properties sortedBuildMetaDataProperties =
SortedProperties.createSorted(buildMetaDataProperties);
normalizeProperties(sortedBuildMetaDataProperties);
// Rather than using the Properties.store directly we write it out
// manually therebye avoiding the Date line in the properties file.
ByteArrayOutputStream bao = new ByteArrayOutputStream();
sortedBuildMetaDataProperties.store(bao, null);
String result = bao.toString("8859_1");
BufferedReader bufReader = new BufferedReader(new StringReader(result));
String line;
while( (line=bufReader.readLine()) != null )
{
if (line.startsWith("#"))
{
out.println(comments);
}
else
{
out.println(line);
}
}
out.flush();
}
catch (final FileNotFoundException e)
{
final String message =
"Cannot find file '" + buildMetaDataFile
+ "' to write properties to.";
throw MojoUtils.createException(log, e, message);
}
catch (final IOException e)
{
final String message =
"Cannot write properties to file '" + buildMetaDataFile + "'.";
throw MojoUtils.createException(log, e, message);
}
finally
{
IOUtil.close(out);
}
return buildMetaDataFile;
}
private void normalizeProperties(final Properties buildMetaDataProperties)
{
final String filters =
buildMetaDataProperties.getProperty(Constant.PROP_NAME_MAVEN_FILTERS);
if (filters != null)
{
final String slashedFilters = filters.trim().replace('\\', '/');
final String slashedBaseDir =
filePathNormalizer.getBaseDir().replace('\\', '/');
final String normBaseDir =
slashedBaseDir.endsWith("/") ? slashedBaseDir : slashedBaseDir + '/';
final String normFilters =
StringUtils.replace(slashedFilters, normBaseDir, "");
buildMetaDataProperties.setProperty(Constant.PROP_NAME_MAVEN_FILTERS,
normFilters);
}
}
/**
* Creates the properties file for the build meta data. If the directory to
* place it in is not present, it will be created.
*
* @return the file to write the build properties to.
* @throws MojoExecutionException if the output directory is not present and
* cannot be created.
*/
private File createBuildMetaDataFile(final File propertiesOutputFile)
throws MojoExecutionException
{
final File outputDirectory = propertiesOutputFile.getParentFile();
if (!outputDirectory.exists())
{
final boolean created = outputDirectory.mkdirs();
if (!created)
{
throw new MojoExecutionException("Cannot create output directory '"
+ outputDirectory + "'.");
}
}
return propertiesOutputFile;
}
/**
* Reads the build properties file from stream. The properties file is passed
* to this instance via the {@link BuildPropertiesFileHelper(Log, File)
* constructor} {@code propertiesOutputFile}.
*
* @param buildMetaDataProperties the properties instance to append the read
* properties to.
* @throws MojoExecutionException if the properties cannot be read.
*/
public void readBuildPropertiesFile(final Properties buildMetaDataProperties)
throws MojoExecutionException
{
InputStream inStream = null;
try
{
inStream =
new BufferedInputStream(new FileInputStream(propertiesOutputFile));
buildMetaDataProperties.load(inStream);
}
catch (final IOException e)
{
throw new MojoExecutionException(
"Cannot read provided properties file: "
+ propertiesOutputFile.getAbsolutePath(), e);
}
finally
{
IOUtil.close(inStream);
}
}
/**
* Fetches the project properties and if <code>null</code> returns a new empty
* properties instance that is associated with the project.
*
* @param project the project whose properties are requested.
* @return the properties of the project.
*/
public Properties getProjectProperties(final MavenProject project)
{
Properties projectProperties = project.getProperties();
if (projectProperties == null)
{
projectProperties = new Properties();
project.getModel().setProperties(projectProperties);
}
return projectProperties;
}
private String getManifestInformation()
throws MojoExecutionException
{
String result = "";
try
{
final Enumeration<URL> resources = BuildReportMojo.class.getClassLoader()
.getResources( "META-INF/MANIFEST.MF" );
while ( resources.hasMoreElements() )
{
final URL jarUrl = resources.nextElement();
log.debug( "Processing jar resource " + jarUrl );
if ( jarUrl.getFile()
.contains( "buildmetadata-maven-plugin" ) )
{
final Manifest manifest = new Manifest( jarUrl.openStream() );
result = manifest.getMainAttributes()
.getValue( "Implementation-Version" );
result += " ( SHA: " + manifest.getMainAttributes()
.getValue( "Scm-Revision" ) + " ) ";
break;
}
}
}
catch ( final IOException e )
{
throw new MojoExecutionException( "Error retrieving information from manifest");
}
return result;
}
}