![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.statscm.StatScmMojo Maven / Gradle / Ivy
package net.sf.statscm;
/*
* Copyright 2006 Doug Culnane
*
* 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.
*/
import net.sf.statsvn.util.SvnStartupUtils;
import net.sf.statsvn.util.SvnVersionMismatchException;
import net.sf.statcvs.Messages;
import net.sf.statcvs.input.LogSyntaxException;
import net.sf.statcvs.output.CommandLineParser;
import net.sf.statsvn.output.SvnCommandLineParser;
import net.sf.statsvn.output.SvnConfigurationOptions;
import net.sf.statcvs.output.ConfigurationException;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.maven.project.MavenProject;
/**
* Generate a Source Code Management Metrics Report.
*
* @goal stats
* @phase site
*/
public class StatScmMojo extends AbstractMavenReport
{
/**
* Maven Project. This represents the POM where StatSCM gets most of its configuration from. This object is provided
* by Maven.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* Each <include> tag inside here gives one Ant-style wildcard pattern indicating what to include. Example:
* "src / ** / *.java" matches all java files in the src directory or its subdirectories. Note that "*.java "only
* matches java files in the root directory, because '*' does not match subdirectories. (Quotes not needed.)
*
* If not specified, all files will be included.
*
* First we add in all files or all these files and then we subtract all the excluded files.
*
* @parameter
*/
private String[] includes;
/**
* Each <exclude> tag inside here gives one Ant-style wildcard pattern indicating what to exclude. Example:
* "** /test/*.java" matches all java files in with a 'test' folder somewhere in the path. Note that "*.java" only
* matches java files in the root directory, because '*' does not match subdirectories. (Quotes not needed.)
*
* If not specified, no files will be excluded.
*
* First we add in all files or all these files and then we subtract all the excluded files.
*
* @parameter
*/
private String[] excludes;
/**
* Each <nonDeveloperLogin> tag in inside here gives one scm login account name. Each account name given here
* will be excluded from all developer reports. This is useful to reduce noise from administrative and other
* non-developer accounts.
*
* Multiple accounts can be excluded by adding a tag for each such account.
*
* @parameter
*/
private String[] nonDeveloperLogins;
/**
* Specify a cache directory for information retrieved from the Subversion server (e.g. line counts). The data will
* be saved in this directory. The directory will be created if it doesn't exist. By default, the current user
* directory is used. This is only relevant when the SCM is subversion and is ignored if it is CVS.
*
* @parameter
*/
private String cacheDir;
/**
* The contents of the specified file will be included at the top of the report's index page. The file should
* contain a valid block-level HTML fragment, for example:
*
*
* <p>
* These are development statistics for the
* <a href="http://www.statsvn.org">StatSVN</a>
* project, created by StatSVN itself.
* </p>
* <p>
* <strong>Note:</strong>
* This report was generated by an unreleased
* development version of StatSVN. It might
* contain features not yet found in the
* official release.
* </p>
*
*
* @parameter
*/
private String notesFile;
/**
* Set this true to avoid running the stat-scm report in this project. Useful in child projects where the parent pom
* project specifies the stat-scm report.
*
* @parameter expression="false"
*/
private boolean skip;
/**
* Specifies a display title to be used in the reports. The setting in <project><name> is used if no
* title is specified here and the name of the Subversion module will be used as default if no title is otherwise
* specified.
*
* @parameter
*/
private String title;
/**
* Configuration for this instance.
*/
private StatConf statConf = new StatConf();
/**
* For running directly.
* @todo This direct call should generate HTML reports by changing the output from Xdoc to html and the outputDir.
*/
public void execute()
{
getLog().error( "StatSCM can not be run directly!" );
getLog().info( "Configure it to run with the \"mvn site\" command." );
getLog().info( "See: http://sourceforge.net/tracker/index.php?func=detail&aid=1610964&group_id=182522&atid=901553." );
}
/**
* Main mojo execution method called by plugin environment.
*
* @param locale Locale for 118n.
* @throws MavenReportException
* Throws an error if any failure.
*/
public void executeReport( Locale locale ) throws MavenReportException
{
if (skip)
{
getLog().info( getMessage("info.greeting.skip") );
}
else
{
// Start
getLog().info( getMessage("info.greeting.ok") );
// Configure
try
{
getLog().info( "StatSCM Version:" + getStatSCMVersion() );
getLog().info( "Configuring StatXXX" );
statConf.configure( project, locale );
configFromMojoProperties();
getLog().info( "SCM Connection Type :" + statConf.getConnectionType() );
getLog().info( "Output Directory :" + this.getOutputDirectory() );
}
catch ( ConfigurationException e )
{
getLog().error( getMessage( "error.config" ), e );
return;
}
// Get the Log file
SrcManager scm = new SrcManager();
if ( !scm.log( statConf.getBaseDirectory(), getLog(), statConf ) )
{
getLog().error( getMessage( "error.scmlog.file_missing" ) );
return;
}
// Create Output dirs
if ( !createOutputDirectory() )
{
getLog().error( getMessage( "error.ouput.can_not_create_output_folder" ) );
return;
}
// Perform report
try
{
if ( statConf.isStatSVN() || statConf.isStatCVS() )
{
if ( statConf.isStatSVN() )
{
doSvnStats();
}
else if ( statConf.isStatCVS() )
{
doCvsStats();
}
doGenerateReport( getSink() );
copyResourceFiles( getOutputDirectory(), project.getBasedir() + statConf.FILE_SEPARATOR + "target"
+ statConf.FILE_SEPARATOR + "site" + statConf.FILE_SEPARATOR + StatConf.STATSCM_DIR_NAME );
}
else
{
getLog().error( getMessage( "warn.scm.type_xxx" ) );
}
}
catch ( Exception e )
{
getLog().error( getMessage( "error.config" ), e );
}
}
}
/**
* Use StatSVN to generate xDoc output.
*
* @throws MavenReportException if there is an error.
*/
private void doSvnStats() throws MavenReportException
{
Messages.setPrimaryResource( "net.sf.statsvn.statcvs" );
try
{
Messages.setPrimaryResource( "net.sf.statsvn.statcvs" );
new SvnCommandLineParser( new String[] { StatConf.getLogFileName(), "." } ).parse();
SvnStartupUtils.checkSvnVersionSufficient();
SvnStartupUtils.checkRepoRootAvailable();
net.sf.statsvn.Main.generateDefaultHTMLSuite();
}
catch ( LogSyntaxException e )
{
getLog().error( getMessage( "error.scmlog.parsing" ), e );
throw new MavenReportException( e.getMessage() );
}
catch ( IOException e )
{
getLog().error( "Error generating Subversion Stats.", e );
throw new MavenReportException( e.getMessage() );
}
catch ( ConfigurationException e )
{
getLog().error( getMessage( "error.config" ), e );
throw new MavenReportException( e.getMessage() );
}
catch ( SvnVersionMismatchException e )
{
getLog().error( e.getMessage(), e );
throw new MavenReportException( e.getMessage() );
}
catch ( NullPointerException e )
{
getLog().warn("Null Pointer: Sometimes happens when local files are not synced with the repository!");
getLog().error( e.getMessage(), e );
//throw new MavenReportException( e.getMessage() );
}
}
/**
* Use StatCVS to generate xDoc output.
*
* @throws MavenReportException if there is an error.
*/
private void doCvsStats() throws MavenReportException
{
try
{
new CommandLineParser( new String[] { StatConf.getLogFileName(), "." } ).parse();
net.sf.statcvs.Main.generateDefaultHTMLSuite();
}
catch ( LogSyntaxException e )
{
getLog().error( getMessage( "error.scmlog.parsing" ), e );
throw new MavenReportException( e.getMessage() );
}
catch ( IOException e )
{
getLog().error( "Error generating Subversion Stats.", e );
throw new MavenReportException( e.getMessage() );
}
catch ( ConfigurationException e )
{
getLog().error( getMessage( "error.config" ), e );
throw new MavenReportException( e.getMessage() );
}
}
/**
* Create the output directory for generated xdoc output.
*
* @return True if directory there or was sucessfully created.
*/
private boolean createOutputDirectory()
{
File outputDir = new File( getOutputDirectory() );
if ( outputDir.exists() )
{
if ( outputDir.isDirectory() )
{
return true;
}
else
{
getLog().error( getMessage( "error.outputDir.file_in_the_way" )
+ outputDir.getAbsolutePath() );
return false;
}
}
else
{
if ( outputDir.mkdirs() )
{
return true;
}
else
{
getLog().error( "Can not make output directory at: " + outputDir.getAbsolutePath() );
return false;
}
}
}
/**
* Use settings in the POM to configure some more things for STATSCM.
*
* @throws ConfigurationException if any of the POM settings are invalid
*/
private void configFromMojoProperties() throws ConfigurationException
{
configIncludeExclude();
configNonDeveloperLogins();
configCacheSettings();
configNotesFile();
configTitle();
}
/**
* Use POM content to set the title appearing on the window. This takes precedence over the name of the POM project
* name, which is the default title.
*/
private void configTitle()
{
if ( title != null )
{
String projectName = title.trim();
if ( projectName.length() > 0 )
{
statConf.setProjectName( projectName );
}
getLog().info( "Page title: " + statConf.getProjectName() );
}
}
/**
* Use POM settings to configure a 'notes' file holding HTML to appear at the top of pages.
*
* @throws ConfigurationException if the notes file can't be used
*/
private void configNotesFile() throws ConfigurationException
{
if ( notesFile != null )
{
String filename = notesFile.trim();
if ( filename.length() > 0 )
{
try
{
statConf.setNotesFile( filename );
getLog().info( "Notes file: " + filename );
}
catch ( ConfigurationException e )
{
getLog().info( "Notes file: " + filename );
throw e;
// @todo: convert this to use message file
// getLog().error( e.getMessage() );
}
}
}
}
/**
* Use POM setting to configure where the cache file is stored.
*
* @throws ConfigurationException if the cache folder cannot be used
*/
private void configCacheSettings() throws ConfigurationException
{
if ( cacheDir != null )
{
String dir = cacheDir.trim();
if ( dir.length() > 0 )
{
try
{
SvnConfigurationOptions.setCacheDir( dir );
getLog().info( "Cache directory: " + dir );
}
catch ( ConfigurationException e )
{
getLog().info( "Cache directory: " + dir );
throw e;
// getLog().error( getMessage( "error.config.bad_cache_dir" ) + dir );
}
}
}
}
/**
* Use the parameters configured in the POM to set things up for the list of files that will be included or
* excluded.
*/
private void configIncludeExclude()
{
String patternList = buildIncludeExcludeString( includes );
if ( patternList.length() > 0 )
{
statConf.setIncludePattern( patternList );
getLog().info( "Includes: " + patternList );
}
else
{
getLog().info( "Include all" );
}
patternList = buildIncludeExcludeString( excludes );
if ( patternList.length() > 0 )
{
statConf.setExcludePattern( patternList );
getLog().info( "Excludes: " + patternList );
}
else
{
getLog().info( "Exclude none" );
}
}
/**
* Convert an array of strings to a single semi-colon delimited string of the values. Blank values are discarded.
*
* @return the delimited string or an empty string if there are no non-blank values.
*/
protected String buildIncludeExcludeString( String[] list )
{
StringBuffer patternList;
patternList = new StringBuffer();
if ( list != null )
{
for ( int i = 0; i < list.length; i++ )
{
String include = list[i].trim();
if ( include.indexOf( ';' ) > 0 )
{
getLog().warn(
getMessage( "warn.config.include.exclude.delimiter.1" ) + " ':' "
+ getMessage( "warn.config.include.exclude.delimiter.2" ) + include );
}
if ( include.indexOf( ':' ) > 0 )
{
getLog().warn(
getMessage( "warn.config.include.exclude.delimiter.1" ) + " ';' "
+ getMessage( "warn.config.include.exclude.delimiter.2" ) + include );
}
if ( include.length() > 0 )
{
if ( patternList.length() > 0 )
{
patternList.append( ';' );
}
patternList.append( list[i] );
}
}
}
return patternList.toString();
}
/**
* Set the list of non-developers so these guys will be ignored in SCM info.
*/
private void configNonDeveloperLogins()
{
if ( nonDeveloperLogins != null )
{
for ( int i = 0; i < nonDeveloperLogins.length; i++ )
{
String login = nonDeveloperLogins[i].trim();
if ( login.length() > 0 )
{
statConf.addNonDeveloperLogin( login );
getLog().info( "Non-developer login: " + login );
}
}
}
}
/**
* Called my Maven Repoerint API.
*
* @return Null becuase we handel the rendering ourselves.
*/
protected Renderer getSiteRenderer()
{
return null;
}
/**
* String repesentation of the output generated XDOC Directory.
*
* @return Absolute path to the generated XDOC Directory.
*/
protected String getOutputDirectory()
{
return StatConf.getOutputDir();
}
/**
* String name of the html file that the Reporting Menu uses for a link.
*
* @return Name of Html file to link to.
*/
public String getOutputName()
{
return StatConf.STATSCM_DIR_NAME + "/statscm";
}
/**
* Menu Item name for Reporting API.
*
* @param locale
* Locale for i18n.
* @return link menu name.
*/
public String getName( Locale locale )
{
return "StatSCM";
}
/**
* Description of Report for Reporting API.
*
* @param loc Locale fro 118n.
* @return i18n Description of Report.
*/
public String getDescription( Locale loc )
{
return getMessage( "statscm.description" );
}
/**
* Utility method for copying resource files.
*
* @param src
* Source Directory.
* @param dest
* Target Directory.
*/
private void copyResourceFiles( String src, String dest )
{
File srcDir = new File( src );
if ( !srcDir.isDirectory() )
{
getLog().error( "Can not copy reources src is not a directory: " + srcDir.getAbsolutePath() );
return;
}
File destDir = new File( dest );
if ( !destDir.isDirectory() )
{
destDir.mkdirs();
}
String[] resoures = srcDir.list( new java.io.FilenameFilter()
{
public boolean accept( File dir, String name )
{
String[] extensions = { ".png", ".jar", ".txt" };
String fileName = name.toLowerCase( Locale.getDefault() );
for ( int i = 0; i < extensions.length; i++ )
{
if ( fileName.endsWith( extensions[i] ) )
{
return true;
}
}
return false;
}
} );
for ( int i = 0; i < resoures.length; i++ )
{
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream( new File( src + statConf.FILE_SEPARATOR + resoures[i] ) );
fos = new FileOutputStream( new File( dest + statConf.FILE_SEPARATOR + resoures[i] ) );
int b = -1;
while ( ( b = fis.read() ) != -1 )
{
fos.write( b );
}
fis.close();
fos.close();
}
catch ( FileNotFoundException e )
{
getLog().error( "Can not find file " + resoures[i], e );
}
catch ( IOException e )
{
getLog().error( "Error copying file: " + src + "/" + resoures[i], e );
}
finally
{
try
{
if ( fis != null )
{
fis.close();
}
if ( fos != null )
{
fos.close();
}
}
catch ( IOException e )
{
getLog().error( "I/O Exception copying resources.", e );
}
finally
{
fis = null;
fos = null;
}
}
if ( getLog().isDebugEnabled() )
{
getLog().debug(
"Copied file " + src + statConf.FILE_SEPARATOR + resoures[i] + " to " + dest
+ statConf.FILE_SEPARATOR + resoures[i] );
}
}
}
/**
* Create a structured StatSCM / StatSVN report front page.
*
* @param sink
* used to write structured report to.
*/
private void doGenerateReport( Sink sink )
{
// protect against direct runs.
if ( sink == null )
{
return;
}
sink.head();
sink.title();
sink.text( "StatSCM" );
sink.title_();
sink.head_();
sink.body();
sink.section1();
sink.sectionTitle1();
sink.text( getDescription( Locale.getDefault() ) );
sink.sectionTitle1_();
sink.bold();
sink.link( "index.html" );
sink.text( "Main page" );
sink.link_();
sink.bold_();
// sink.link_();
sink.lineBreak();
// TODO Think about adding first page links this back in once the StatSVN and StatCVS output stableises.
sink.link( "index.html" );
sink.figure();
sink.figureGraphics( "loc.png" );
sink.figure_();
sink.link_();
sink.lineBreak();
sink.text( "Generated using " );
sink.link( "http://stat-scm.sourceforge.net/" );
sink.text( "StatSCM" + getStatSCMVersion() );
sink.link_();
sink.text( "." );
sink.flush();
sink.close();
}
/**
* Get the version of StatSCM. This uses the filtered resource so that
* Maven automatically sets this at build time.
*
* @return The pom.version or an empty string if this fails.
*/
private String getStatSCMVersion() {
String versionText = getMessage("statscm.version");
if (versionText == null) {
return "";
} else if (versionText.equals("${pom.version}")) {
return "";
}
return " (" + versionText +")";
}
/**
* Access to the Maven Project representation for Reporting API.
*
* @return MavenProject.
*/
protected MavenProject getProject()
{
return project;
}
/**
* Setter to allow unit tests to set up Mojo.
*
* @param project Maven Project
*/
public void setProject( MavenProject project )
{
this.project = project;
}
public String getMessage(String messageKey) {
return ResourceBundle.getBundle( "net.sf.statscm.message", statConf.getLocale() ).getString( messageKey );
}
public StatConf getStatConf()
{
return statConf;
}
public void setStatConf( StatConf statConf )
{
this.statConf = statConf;
}
void setSkipParameter( boolean b )
{
skip = b;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy