package org.jboss.windup.rules.apps.tattletale;
import java.io.File;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.StandardSystemProperty;
import org.jboss.tattletale.Main;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.MetadataBuilder;
import org.jboss.windup.config.operation.GraphOperation;
import org.jboss.windup.graph.GraphContext;
import org.jboss.windup.graph.model.ProjectModel;
import org.jboss.windup.graph.model.WindupConfigurationModel;
import org.jboss.windup.graph.model.resource.FileModel;
import org.jboss.windup.graph.service.WindupConfigurationService;
import org.jboss.windup.reporting.model.ApplicationReportModel;
import org.jboss.windup.reporting.model.TemplateType;
import org.jboss.windup.reporting.service.ApplicationReportService;
import org.jboss.windup.reporting.service.ReportService;
import org.jboss.windup.util.exception.WindupException;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;
/**
* Runs Tattletale on the Windup's input.
*/
public class TattletaleRuleProvider extends AbstractRuleProvider
{
public static final String REPORT_TEMPLATE = "/reports/templates/embedded.ftl";
private static final String TATTLETALE_REPORT_SUBDIR = "tattletale";
public static final String REPORT_DESCRIPTION = "This report contains the results of running Tattletale on the input application.";
public TattletaleRuleProvider()
{
super(MetadataBuilder.forProvider(TattletaleRuleProvider.class));
}
@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
return ConfigurationBuilder.begin()
.addRule()
.perform(new TattletaleOperation());
}
private class TattletaleOperation extends GraphOperation
{
private static final String TTALE_CONFIG_FILE_NAME = "tattletale-config.properties";
@Override
public void perform(GraphRewrite event, EvaluationContext context)
{
Boolean generateReport = (Boolean) event.getGraphContext().getOptionMap().get(EnableTattletaleReportOption.NAME);
if (generateReport == null || !generateReport)
return;
WindupConfigurationModel configuration = WindupConfigurationService.getConfigurationModel(event.getGraphContext());
for (FileModel input : configuration.getInputPaths())
{
String inputPath = input.getFilePath();
Path reportDirectory = new ReportService(event.getGraphContext()).getReportDirectory();
String tattletaleRelativePath = TATTLETALE_REPORT_SUBDIR + File.separator + input.getFileName();
Path tattletaleReportPath = reportDirectory.resolve(tattletaleRelativePath);
for (int i = 1; Files.exists(tattletaleReportPath); i++)
{
tattletaleRelativePath = TATTLETALE_REPORT_SUBDIR + File.separator + input.getFileName() + "." + i;
tattletaleReportPath = reportDirectory.resolve(tattletaleRelativePath);
}
String tattletaleDir = tattletaleReportPath.toString();
Main main = new Main();
main.setSource(inputPath);
main.setDestination(tattletaleDir);
try
{
// The only way Tattletale accepts configuration is through a file.
new File(tattletaleDir).mkdirs();
File configPath = new File(tattletaleDir, TTALE_CONFIG_FILE_NAME);
try (PrintStream str = new PrintStream(configPath))
{
str.append("enableDot=false\n"); // Whether to generate .dot and .png
str.append("graphvizDot=dot\n"); // Dot executable
str.close();
}
main.setConfiguration(configPath.getAbsolutePath());
/*
* HACK - reset temp directory temporarily as otherwise there are cases where tattletale
* will actually overwrite the input file. This can happen in cases where the application
* being analyzed is actually in the temp directory, due to a bug in Tattletale. (2016/05/19)
*/
String previousTmpDir = StandardSystemProperty.JAVA_IO_TMPDIR.value();
System.setProperty(StandardSystemProperty.JAVA_IO_TMPDIR.key(), Paths.get(tattletaleDir).resolve("tattletaletmp").toString());
main.execute();
System.setProperty(StandardSystemProperty.JAVA_IO_TMPDIR.key(), previousTmpDir);
createReportModel(event.getGraphContext(), input, tattletaleRelativePath);
}
catch (Exception e)
{
throw new WindupException("Failed to run Tattletale due to: " + e.getMessage());
}
}
}
private void createReportModel(GraphContext context, FileModel input, String reportRelativePath)
{
ProjectModel inputProjectModel = input.getProjectModel();
ApplicationReportModel applicationReportModel = new ApplicationReportService(context).create();
applicationReportModel.setReportName("Tattletale");
applicationReportModel.setDescription(REPORT_DESCRIPTION);
applicationReportModel.setReportIconClass("glyphicon tattletale-nav-logo");
applicationReportModel.setReportPriority(500);
applicationReportModel.setDisplayInApplicationReportIndex(true);
applicationReportModel.setProjectModel(inputProjectModel);
applicationReportModel.setTemplatePath(REPORT_TEMPLATE);
applicationReportModel.setTemplateType(TemplateType.FREEMARKER);
Map<String, String> reportProperties = new HashMap<>();
reportProperties.put("embeddedTitle", "Tattletale Report");
reportProperties.put("embeddedUrl", reportRelativePath + "/index.html");
applicationReportModel.setReportProperties(reportProperties);
ReportService reportService = new ReportService(context);
reportService.setUniqueFilename(applicationReportModel, "tattletale" + "_" + inputProjectModel.getName(), "html");
}
}
}