package org.codehaus.mojo.dashboard.report.plugin;
/*
* Copyright 2006 David Vicente
*
* 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 java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.mojo.dashboard.report.plugin.beans.DashBoardMavenProject;
import org.codehaus.mojo.dashboard.report.plugin.configuration.Configuration;
import org.codehaus.mojo.dashboard.report.plugin.configuration.ConfigurationService;
import org.codehaus.mojo.dashboard.report.plugin.configuration.ConfigurationServiceException;
import org.codehaus.mojo.dashboard.report.plugin.configuration.IConfigurationService;
import org.codehaus.mojo.dashboard.report.plugin.hibernate.HibernateService;
import org.codehaus.plexus.resource.ResourceManager;
import org.codehaus.plexus.resource.loader.FileResourceCreationException;
import org.codehaus.plexus.resource.loader.FileResourceLoader;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringInputStream;
import org.codehaus.plexus.util.StringUtils;
/**
* A Dashboard report which aggregates all other report results.
*
* @author <a href="dvicente72@gmail.com">David Vicente</a>
* @goal dashboard
* @phase post-site
*/
public class DashBoardReportMojo extends AbstractMavenReport
{
/**
* The maven project
*
* @parameter expression="${project}"
* @readonly
*/
private MavenProject project;
/**
* Directory containing The generated DashBoard report Datafile "dashboard-report.xml".
*
* @parameter expression="${project.reporting.outputDirectory}"
* @required
*/
private File outputDirectory;
/**
* Renderer
*
* @component
*/
private Renderer siteRenderer;
/**
* <p>
* The generated DashBoard report Datafile.
* </p>
*
* @parameter default-value="dashboard-report.xml"
* @readonly
*/
protected String dashboardDataFile;
/**
* The filename to use for the report.
*
* @parameter default-value="dashboard-report"
* @readonly
*/
private String outputName;
/**
* The local repository.
*
* @parameter expression="${localRepository}"
* @readonly
*/
protected ArtifactRepository localRepository;
/**
* number of XRef JDepend/Cobertura packages to export in dashboard summary page
*
* @parameter default-value="10"
*/
private int nbExportedPackagesSummary;
/**
* Project builder
*
* @component
*/
protected MavenProjectBuilder mavenProjectBuilder;
/**
* Hibernate Service
*
* @component
*/
protected HibernateService hibernateService;
/**
* Hibernate dialect
*
* @parameter expression="${dialect}"
*/
protected String dialect;
/**
* Hibernate driver class
*
* @parameter expression="${driverClass}"
*/
protected String driverClass;
/**
* Hibernate connection URL
*
* @parameter expression="${connectionUrl}"
*/
protected String connectionUrl;
/**
* Hibernate database username
*
* @parameter expression="${username}"
*/
protected String username;
/**
* Hibernate database password
*
* @parameter expression="${password}"
*/
protected String password;
/**
* <p>
* Specifies the location of the XML configuration to use.
* </p>
* <p>
* Potential values are a filesystem path, a URL, or a classpath resource. This parameter expects that the contents
* of the location conform to the xml format (<a href="http://mojo.codehaus.org/dashboard-maven-plugin/">Dashboard
* Maven plugin</a>) configuration .
* </p>
* <p>
* This parameter is resolved as resource, URL, then file. If successfully resolved, the contents of the
* configuration is copied into the <code>${project.build.directory}/default-dashboard-config.xml</code> file
* before being passed to dashboard as a configuration.
* </p>
* <p>
* There are 1 predefined config.
* </p>
* <ul>
* <li><code>config/default-dashboard-config.xml</code>: default config.</li>
* </ul>
*
* @parameter expression="${configLocation}" default-value="config/default-dashboard-config.xml"
*/
private String configLocation;
/**
* @component
* @required
* @readonly
*/
private ResourceManager locator;
/**
* Used to generate a dashboard report as Maven 1, only for multi-modules project. It also merges the 2 reports
* (Summary and detailled) as only one.
*
* @parameter expression="${m1LikeRendering}" default-value="false"
*/
private boolean m1LikeRendering;
/**
* This parameter is used to keep the version as a discriminant criteria of a project. If set as "true", the data of
* reports will be specific to this version of a project. If set as "false", the data of reports will be associated
* with the project regardless of its version.
*
* @parameter expression="${keepVersionAsDiscriminantCriteria}" default-value="true"
*/
private boolean keepVersionAsDiscriminantCriteria;
/**
* <p>
* This parameter is used to disable the graphics generation to avoid unexpected error when X11 window server not
* installed on Linux/Unix machine.
* </p>
* <p>
* <ul>
* <li>If set as "true" or not set (default value is used) , all graphics will be generated.</li>
* <li>> If set as "false", the Dashboard won't generate graphics for summary and detailled reports and the
* historic report will be disabled.</li>
* </ul>
* </p>
*
* @parameter expression="${generateGraphs}" default-value="true"
*/
private boolean generateGraphs;
private DashBoardUtils dashBoardUtils;
private Locale locale;
/**
*
*/
protected void executeReport( Locale arg0 ) throws MavenReportException
{
this.locale = arg0;
// Thanks to the Checkstyle Maven plugin team for this part of code.
this.locator.addSearchPath( FileResourceLoader.ID, this.project.getFile().getParentFile().getAbsolutePath() );
this.locator.addSearchPath( "url", "" );
this.locator.setOutputDirectory( new File( this.project.getBuild().getDirectory() ) );
// Thanks end.
this.getLog().info( "MultiReportMojo project = " + this.project.getName() );
this.getLog().info( "MultiReportMojo nb modules = " + this.project.getModules().size() );
this.getLog().info( "MultiReportMojo base directory = " + this.project.getBasedir() );
this.getLog().info( "MultiReportMojo output directory = " + this.outputDirectory );
this.getLog().info( "MultiReportMojo report output directory = " + this.getReportOutputDirectory() );
this.getLog().info( "MultiReportMojo project language = "
+ this.project.getArtifact().getArtifactHandler().getLanguage() );
this.copyStaticResources();
this.dashBoardUtils =
DashBoardUtils.getInstance( this.getLog(), this.mavenProjectBuilder, this.localRepository, false );
if ( canGenerateReport() )
{
DashBoardMavenProject mavenProject = null;
if ( isDBAvailable() )
{
configureHibernateDriver();
}
mavenProject =
this.dashBoardUtils.getDashBoardMavenProject( this.project, this.dashboardDataFile,
new Date( System.currentTimeMillis() ) );
this.dashBoardUtils.saveXMLDashBoardReport( this.project, mavenProject, this.dashboardDataFile );
if ( mavenProject != null )
{
boolean isSummary = ( mavenProject.getModules() != null && !mavenProject.getModules().isEmpty() );
AbstractDashBoardGenerator reportGenerator = null;
if ( isSummary && this.m1LikeRendering )
{
reportGenerator =
new DashBoardMaven1ReportGenerator( mavenProject, isDBAvailable(), this.getLog() );
}
else
{
reportGenerator =
new DashBoardReportGenerator( mavenProject, isSummary, isDBAvailable(),
this.generateGraphs, this.getLog() );
}
reportGenerator.setImagesPath( getReportOutputDirectory() + "/images" );
reportGenerator.setNbExportedPackagesSummary( this.nbExportedPackagesSummary );
reportGenerator.doGenerateReport( getBundle( this.locale ), getSink() );
if ( isDBAvailable() )
{
// Thanks to the Checkstyle Maven plugin team for this part of code.
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
Configuration dashConfig = null;
try
{
// dashboard will always use the context classloader in order
// to load resources (xml schema)
ClassLoader dashboardClassLoader = DashBoardUtils.class.getClassLoader();
Thread.currentThread().setContextClassLoader( dashboardClassLoader );
String configFile = this.getConfigFile();
getLog().info( "getConfigFile() = " + configFile );
IConfigurationService configService = new ConfigurationService( configFile );
dashConfig = configService.getConfiguration();
if ( !configService.isValidConfig() )
{
List warningMsg = configService.getWarningMessages();
Iterator iter = warningMsg.iterator();
while ( iter.hasNext() )
{
getLog().error( (String) iter.next() );
}
throw new MavenReportException( "The maven-dashboard-config.xml is not valid. " +
"See error messages above or see the maven-dashboard-config.xsd file." );
}
}
catch ( ConfigurationServiceException e )
{
this.getLog().error( "DashBoardHistoricReportMojo executeReport() failed.", e );
throw new MavenReportException( "The maven-dashboard-config.xml is not valid. " +
"See error messages above or see the maven-dashboard-config.xsd file." );
}
catch ( Exception e )
{
this.getLog().error( "DashBoardHistoricReportMojo executeReport() failed.", e );
throw new MavenReportException( "The maven-dashboard-config.xml is not valid. " +
"See error messages above or see the maven-dashboard-config.xsd file." );
}
finally
{
// be sure to restore original context classloader
Thread.currentThread().setContextClassLoader( currentClassLoader );
}
// Thanks end.
try
{
if ( dashConfig != null )
{
DashBoardHistoricReportGenerator histoReportGenerator =
new DashBoardHistoricReportGenerator( mavenProject, this.hibernateService, dashConfig,
this.keepVersionAsDiscriminantCriteria,
this.generateGraphs, getLog() );
histoReportGenerator.setImagesPath( getReportOutputDirectory() + "/images" );
histoReportGenerator.doGenerateReport( getBundle( locale ), getSink() );
}
}
catch ( Exception e )
{
this.getLog().error( "DashBoardHistoricReportMojo executeReport() failed.", e );
}
}
if ( isSummary && !this.m1LikeRendering )
{
try
{
DashBoardMultiReportGenerator detailReportGenerator =
new DashBoardMultiReportGenerator( mavenProject, isDBAvailable(),
this.generateGraphs, getLog() );
detailReportGenerator.setImagesPath( getReportOutputDirectory() + "/images" );
detailReportGenerator.doGenerateReport( getBundle( locale ), getSink() );
}
catch ( Exception e )
{
this.getLog().error( "DashBoardReportMojo executeReport() failed.", e );
}
}
}
}
}
/**
*
*/
protected String getOutputDirectory()
{
return this.outputDirectory.getPath();
}
/**
*
*/
protected MavenProject getProject()
{
return this.project;
}
protected Renderer getSiteRenderer()
{
return this.siteRenderer;
}
public String getDescription( Locale locale )
{
String description = "";
if ( this.project.getModules().size() > 0 )
{
description = this.getBundle( locale ).getString( "dashboard.multireport.description" );
}
else
{
description = this.getBundle( locale ).getString( "dashboard.report.description" );
}
return description;
}
public String getName( Locale locale )
{
String name = "";
if ( this.project.getModules().size() > 0 )
{
name = this.getBundle( locale ).getString( "dashboard.multireport.name" );
}
else
{
name = this.getBundle( locale ).getString( "dashboard.report.name" );
}
return name;
}
public String getOutputName()
{
return this.outputName;
}
public ResourceBundle getBundle( Locale locale )
{
return ResourceBundle.getBundle( "dashboard-report-plugin", locale, this.getClass().getClassLoader() );
}
public boolean usePageLinkBar()
{
return true;
}
private InputStream getSiteDescriptor() throws MojoExecutionException
{
String siteDescriptorContent = "";
try
{
siteDescriptorContent = IOUtil.toString( this.getClass().getResourceAsStream( "/default-report.xml" ) );
}
catch ( IOException e )
{
throw new MojoExecutionException( "The site descriptor cannot be read!", e );
}
Map props = new HashMap();
props.put( "reports", this.getReportsMenu() );
if ( this.getProject().getName() != null )
{
props.put( "project.name", this.getProject().getName() );
}
else
{
props.put( "project.name", "NO_PROJECT_NAME_SET" );
}
if ( this.getProject().getUrl() != null )
{
props.put( "project.url", this.getProject().getUrl() );
}
else
{
props.put( "project.url", "NO_PROJECT_URL_SET" );
}
siteDescriptorContent = StringUtils.interpolate( siteDescriptorContent, props );
return new StringInputStream( siteDescriptorContent );
}
private String getReportsMenu()
{
StringBuffer buffer = new StringBuffer();
buffer.append( "<menu name=\"Project Reports\">\n" );
buffer.append( " <item name=\"Root\" href=\"/project-reports.html\"/>\n" );
buffer.append( " <item name=\"" + this.getName( this.locale ) + "\" href=\"/" + this.getOutputName()
+ ".html\"/>\n" );
buffer.append( "</menu>\n" );
return buffer.toString();
}
public boolean canGenerateReport()
{
if ( this.project.getCollectedProjects().size() < this.project.getModules().size() )
{
this.getLog().info( "DashBoardReportMojo: Not recursive into sub-projects - skipping report." );
return false;
}
return true;
}
protected void configureHibernateDriver()
{
this.hibernateService.setDialect( this.dialect );
this.hibernateService.setDriverClass( this.driverClass );
this.hibernateService.setConnectionUrl( this.connectionUrl );
this.hibernateService.setUsername( this.username );
this.hibernateService.setPassword( this.password );
}
protected boolean isDBAvailable()
{
boolean isDBAvailable = false;
if ( ( this.dialect != null && this.dialect.length() > 0 )
&& ( this.driverClass != null && this.driverClass.length() > 0 )
&& ( this.connectionUrl != null && this.connectionUrl.length() > 0 )
&& ( this.username != null && this.username.length() > 0 )
&& ( this.password != null && this.password.length() > 0 ) )
{
isDBAvailable = true;
}
return isDBAvailable;
}
/**
* @return
* @throws MavenReportException
*/
private String getConfigFile() throws MavenReportException
{
// Thanks to the Checkstyle Maven plugin team for this part of code.
try
{
this.getLog().info( "getConfigFile() = " + this.configLocation );
File configFile = this.locator.getResourceAsFile( this.configLocation, "default-dashboard-config.xml" );
if ( configFile == null )
{
throw new MavenReportException( "Unable to process dashboard config location: " + this.configLocation );
}
return configFile.getAbsolutePath();
}
catch ( org.codehaus.plexus.resource.loader.ResourceNotFoundException e )
{
throw new MavenReportException( "Unable to find dashboard configuration file at location "
+ this.configLocation, e );
}
catch ( FileResourceCreationException e )
{
throw new MavenReportException( "Unable to process dashboard configuration file location "
+ this.configLocation, e );
}
// Thanks end.
}
/**
* Thanks to the maven-changes-plugin team for this part of code.
*
* @throws MavenReportException
*/
private void copyStaticResources() throws MavenReportException
{
String resourceNames[] =
{ "images/down.gif", "images/Down-green-full.jpg", "images/Down-red-full.jpg",
"images/Down-orange-full.jpg", "images/next.gif", "images/previous.gif", "images/up.gif",
"images/Stable-green-full.jpg", "images/Stable-red-full.jpg", "images/Stable-orange-full.jpg",
"images/Up-green-full.jpg", "images/Up-red-full.jpg", "images/Up-orange-full.jpg",
"css/dashboard.css", "css/dashboard2.css", "css/dashboard2IE.css" };
try
{
this.getLog().debug( "Copying static resources." );
for ( int i = 0; i < resourceNames.length; i++ )
{
URL url = this.getClass().getClassLoader().getResource( resourceNames[i] );
FileUtils.copyURLToFile( url, new File( this.getReportOutputDirectory(), resourceNames[i] ) );
}
}
catch ( IOException e )
{
throw new MavenReportException( "Unable to copy static resources." );
}
}
}