All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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.model.Reporting;
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(), getReportingTargetDirectory() ); } 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(); } /** * Returns the StatSCM report target directory. * * @return Absolute path to the directory with final HTML result. */ protected String getReportingTargetDirectory() { String targetBaseDirectory = null; Reporting reporting = getProject().getReporting(); if ( reporting != null) { targetBaseDirectory = reporting.getOutputDirectory(); } if ( targetBaseDirectory == null) { targetBaseDirectory = getStatConf().getBaseDirectory().getAbsolutePath() + statConf.FILE_SEPARATOR + "target" + statConf.FILE_SEPARATOR + "site"; } return targetBaseDirectory + statConf.FILE_SEPARATOR + StatConf.STATSCM_DIR_NAME; } /** * 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