package org.codehaus.mojo.smc; /* * Copyright 2006 The Apache Software Foundation. * * 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 org.apache.maven.project.MavenProject; import org.apache.maven.reporting.AbstractMavenReport; import org.apache.maven.reporting.MavenReportException; import org.codehaus.doxia.sink.Sink; import org.codehaus.doxia.site.renderer.SiteRenderer; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.cli.CommandLineException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.*; /** * Generate graphes and HTML tables for the various smc state diagrams. * * @author <a href="jerome@coffeebreaks.org">Jerome Lacoste</a> * @goal smcreports * @execute phase="generate-sources" */ public class SmcReportMojo extends AbstractMavenReport { /** * <i>Maven Internal</i>: List of artifacts for the plugin. * * @parameter expression="${plugin.artifacts}" * @required * @readonly */ protected List pluginClasspathList; /** * Source directory containing the *.sm files. * * @parameter expression="${project.basedir}/src/main/smc" * @required */ private File sourceDirectory; /** * The output directory for the report. * * @parameter expression="${project.reporting.outputDirectory}/smc" * @required */ private File outputDirectory; /** * <i>Maven Internal</i>: The Doxia Site Renderer. * * @component */ private SiteRenderer siteRenderer; /** * <i>Maven Internal</i>: Project to interact with. * * @parameter expression="${project}" * @required * @readonly */ private MavenProject project; /** * Graph verbosity level * {@link <a href="http://smc.sourceforge.net/SmcManSec10.htm#GraphLevels"/>} * * @parameter expression="${glevel}" */ private Integer glevel; /** * @see org.apache.maven.reporting.MavenReport#getName(java.util.Locale) */ public String getName( Locale locale ) { return "State Machine Compiler"; } /** * @see org.apache.maven.reporting.MavenReport#getDescription(java.util.Locale) */ public String getDescription( Locale locale ) { return "State Machine Compiler Diagrams."; } /** * @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory() */ protected String getOutputDirectory() { return outputDirectory.getAbsolutePath(); } /** * @see org.apache.maven.reporting.AbstractMavenReport#getProject() */ protected MavenProject getProject() { return project; } /** * @see org.apache.maven.reporting.AbstractMavenReport#getSiteRenderer() */ protected SiteRenderer getSiteRenderer() { return siteRenderer; } /** * Enable verbose. * * @parameter expression="${verbose}" default-value="false" */ private boolean verbose; /** * @see org.apache.maven.reporting.MavenReport#generate(org.codehaus.doxia.sink.Sink, java.util.Locale) */ public void generate( Sink sink, Locale locale ) throws MavenReportException { executeReport( locale ); } protected void executeReport(Locale locale) throws MavenReportException { if (!sourceDirectory.exists()) { getLog().error("sourceDirectory " + sourceDirectory + " doesn't exist."); return; } if (!sourceDirectory.isDirectory()) { throw new MavenReportException("sourceDirectory " + sourceDirectory + " isn't a directory"); } List files; try { files = Util.getSmFiles(sourceDirectory); } catch (IOException e) { throw new MavenReportException("Couldn't find the .sm files in " + sourceDirectory, e); } // FIXME catch errors (redirect System.err?) getLog().debug("Found " + files.size() + " .sm file(s) to process."); for (int i = 0; i < files.size(); i++) { File smFile = (File) files.get(i); getLog().debug("Handling " + smFile); /* Properties properties; String classPackage = null; String theClass = null; try { properties = Util.getSmFileHeader(smFile); classPackage = properties.getProperty("package"); theClass = properties.getProperty("class"); } catch (IOException e) { getLog().error("Couldn't identify the package for file " + smFile.getAbsolutePath(), e); } if (classPackage != null) { classPackage = classPackage.replace(".", File.separator); } File theOutputDirectory = new File(outputDirectory + File.separator + classPackage); */ if (! outputDirectory.exists() && ! outputDirectory.mkdirs()) { getLog().warn("the destination directory (" + outputDirectory + ") for file " + smFile.getAbsolutePath() + " doesn't exist and couldn't be created. The goal with probably fail."); } /* if (theClass != null) { File file = new File(theOutputDirectory, theClass + "Context.java"); if (file.exists() && file.lastModified() > smFile.lastModified()) { getLog().debug("Skipping regeneration of " + file + " as it is newer than " + smFile); continue; } } else { getLog().warn("Didn't identify the %class from the .sm file"); } */ // HTML page List arguments = new ArrayList(); if (verbose) { arguments.add("-verbose"); } arguments.add("-ret"); arguments.add("-d"); arguments.add(outputDirectory.getAbsolutePath()); arguments.add("-table"); // Scm uses too many class members... We have to override the _suffix variable // otherwise it is not taken into acocunt and the .dot file is written over the html one. arguments.add("-su"); arguments.add("html"); arguments.add(smFile.getAbsolutePath()); executeSmc(arguments); // HTML graph List arguments2 = new ArrayList(); if (verbose) { arguments2.add("-verbose"); } arguments2.add("-ret"); arguments2.add("-d"); arguments2.add(outputDirectory.getAbsolutePath()); arguments2.add("-graph"); if ( glevel != null ) { // let's smc validate... arguments2.add("-glevel"); arguments2.add(glevel.toString()); } // Scm uses too many class members... We have to override the _suffix variable // otherwise it is not taken into acocunt and the .dot file is written over the html one. arguments2.add("-su"); arguments2.add("dot"); arguments2.add(smFile.getAbsolutePath()); executeSmc(arguments2); } // try converting the .dot files into png try { List dotFiles = FileUtils.getFiles( outputDirectory, "**/*.dot", null ); DotConvertor.convert( dotFiles, new String[] { "png" }, getLog()); } catch ( CommandLineException e ) { getLog().warn( "Couldn't convert the .dot files: failed finding them.", e ); } catch ( IOException e ) { getLog().warn( "Couldn't convert the .dot files: failed finding them.", e ); } // trick the system InputStream stream = this.getClass().getClassLoader().getResourceAsStream("/refresh.html"); if ( stream == null ) { getLog().error( "Failure to generate refresh.html: template not found."); } else { try { Util.copyStreamToFile( stream, new File( outputDirectory, "refresh.html").getAbsolutePath() ); } catch (IOException e) { getLog().error( "Failure to generate refresh.html. ", e ); } } getLog().debug("Adding outputDirectory to source root: " + outputDirectory); this.project.addCompileSourceRoot(outputDirectory.getAbsolutePath()); } private void executeSmc(List arguments) throws MavenReportException { try { Util.executeSmc(arguments, getLog()); } catch (Exception e) { throw new MavenReportException("Failure to execute Smc", e); } } /** * @see org.apache.maven.reporting.MavenReport#getOutputName() */ public String getOutputName() { return "smc/refresh"; } public boolean isExternalReport() { return true; } public boolean canGenerateReport() { try { return sourceDirectory != null && sourceDirectory.exists() && Util.getSmFiles(sourceDirectory).size() > 0; } catch (IOException e) { getLog().error("error while searching for .sm files ", e); return false; } } }