package org.jboss.windup.tooling;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.forge.arquillian.AddonDependencies;
import org.jboss.forge.arquillian.AddonDependency;
import org.jboss.forge.arquillian.archive.AddonArchive;
import org.jboss.logmanager.Level;
import org.jboss.shrinkwrap.api.ShrinkWrap;
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.exec.configuration.options.OnlineModeOption;
import org.jboss.windup.exec.configuration.options.SourceOption;
import org.jboss.windup.exec.configuration.options.TargetOption;
import org.jboss.windup.graph.model.WindupConfigurationModel;
import org.jboss.windup.graph.service.WindupConfigurationService;
import org.jboss.windup.reporting.config.Hint;
import org.jboss.windup.reporting.quickfix.Quickfix;
import org.jboss.windup.reporting.config.classification.Classification;
import org.jboss.windup.rules.apps.java.condition.JavaClass;
import org.jboss.windup.rules.apps.java.config.SourceModeOption;
import org.jboss.windup.rules.apps.java.model.WindupJavaConfigurationModel;
import org.jboss.windup.rules.apps.java.service.WindupJavaConfigurationService;
import org.jboss.windup.tooling.data.QuickfixType;
import org.jboss.windup.tooling.rules.RuleProvider;
import org.jboss.windup.tooling.rules.RuleProviderRegistry;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*/
@RunWith(Arquillian.class)
public class ExecutionBuilderTest
{
private static final int PORT = 9874;
private static Logger LOG = Logger.getLogger(ExecutionBuilderTest.class.getName());
@Inject
private ExecutionBuilder builder;
@Inject
private GraphLoader graphLoader;
@Inject
private TestProvider testProvider;
@Inject
private ToolingXMLService toolingXMLService;
@Inject
private ToolingRMIServer rmiServer;
@Deployment
@AddonDependencies({
@AddonDependency(name = "org.jboss.windup:windup-tooling"),
@AddonDependency(name = "org.jboss.windup.config:windup-config"),
@AddonDependency(name = "org.jboss.windup.config:windup-config-xml"),
@AddonDependency(name = "org.jboss.windup.exec:windup-exec"),
@AddonDependency(name = "org.jboss.windup.reporting:windup-reporting"),
@AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-java"),
@AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-java-ee"),
@AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-java-project"),
@AddonDependency(name = "org.jboss.windup.utils:windup-utils"),
@AddonDependency(name = "org.jboss.forge.furnace.container:cdi"),
})
public static AddonArchive getDeployment()
{
return ShrinkWrap
.create(AddonArchive.class)
.addBeansXML();
}
public static Path getDefaultPath()
{
return FileUtils.getTempDirectory().toPath().resolve("Windup").resolve("execbuildertest_" + RandomStringUtils.randomAlphanumeric(6));
}
private static ExecutionBuilder getExecutionBuilderFromRMIRegistry()
{
try
{
Registry registry = LocateRegistry.getRegistry(PORT);
ExecutionBuilder executionBuilder = (ExecutionBuilder) registry.lookup(ExecutionBuilder.LOOKUP_NAME);
executionBuilder.clear();
return executionBuilder;
}
catch (RemoteException | NotBoundException e)
{
LOG.log(Level.SEVERE, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
@Test
public void testRuleProviderRegistry() throws RemoteException
{
rmiServer.startServer(PORT, "");
ExecutionBuilder builder = getExecutionBuilderFromRMIRegistry();
Assert.assertNotNull(builder);
List<String> paths = Collections.singletonList("src/test/resources/rules");
RuleProviderRegistry registry = builder.getRuleProviderRegistry(paths);
Assert.assertNotNull(registry);
Assert.assertFalse(registry.getRuleProviders().isEmpty());
List<RuleProvider> xmlProviders = registry.getRuleProviders().stream()
.filter(provider -> provider.getOrigin() != null)
.filter(provider -> provider.getRuleProviderType() == RuleProvider.RuleProviderType.XML)
.collect(Collectors.toList());
Assert.assertTrue(xmlProviders.size() > 0);
}
@Test
public void testSystemRuleProviderRegistry() throws RemoteException
{
rmiServer.startServer(PORT, "");
ExecutionBuilder builder = getExecutionBuilderFromRMIRegistry();
Assert.assertNotNull(builder);
RuleProviderRegistry registry = builder.getSystemRuleProviderRegistry();
Assert.assertNotNull(registry);
Assert.assertFalse(registry.getRuleProviders().isEmpty());
}
@Test
public void testSchemaGeneration() throws Exception
{
Path outputDirectory = getDefaultPath();
Files.createDirectories(outputDirectory);
Path output = outputDirectory.resolve("sample.xsd");
try
{
LOG.info("Generating test schema at: " + output);
toolingXMLService.generateSchema(output);
Assert.assertTrue(Files.isRegularFile(output));
}
finally
{
FileUtils.deleteDirectory(outputDirectory.toFile());
}
}
@Test
public void testExecutionBuilder() throws Exception
{
Assert.assertNotNull(builder);
Assert.assertNotNull(testProvider);
Path input = Paths.get("../../test-files/src_example");
Path output = getDefaultPath();
TestProgressMonitor progressWithLogging = new TestProgressMonitor();
ExecutionResults results = executeWindup(input, output, progressWithLogging);
Assert.assertNotNull(results.getClassifications());
Assert.assertNotNull(results.getHints());
Assert.assertTrue(results.getHints().iterator().hasNext());
checkQuickfixInHints(results.getHints());
Assert.assertTrue(results.getClassifications().iterator().hasNext());
Assert.assertTrue(testProvider.sourceMode);
Assert.assertFalse(testProvider.onlineMode);
Path xmlResultsFile = output.resolve("sample_results.xml");
LOG.info("Serializing results to: " + xmlResultsFile);
results.serializeToXML(xmlResultsFile);
Assert.assertTrue(Files.isRegularFile(xmlResultsFile));
Assert.assertTrue(Files.size(xmlResultsFile) > 100);
Assert.assertTrue(progressWithLogging.logRecords.size() > 10);
}
private void checkQuickfixInHints(Iterable<org.jboss.windup.tooling.data.Hint> hints)
{
int quickfixCount = 0;
for (org.jboss.windup.tooling.data.Hint hintDTO : hints)
{
Iterable<org.jboss.windup.tooling.data.Quickfix> quickfixes = hintDTO.getQuickfixes();
for (org.jboss.windup.tooling.data.Quickfix quickfix : quickfixes)
{
Assert.assertEquals("quickfix1", quickfix.getName());
Assert.assertEquals(QuickfixType.DELETE_LINE, quickfix.getType());
quickfixCount++;
}
}
Assert.assertTrue(quickfixCount > 0);
}
@Test
public void testReloadGraph() throws IOException
{
Path input = Paths.get("../../test-files/src_example");
Path output = getDefaultPath();
ExecutionResults resultsOriginal = executeWindup(input, output, new TestProgressMonitor());
ExecutionResults resultsLater = graphLoader.loadResults(output);
Assert.assertTrue(resultsLater.getClassifications().iterator().hasNext());
Assert.assertTrue(resultsLater.getHints().iterator().hasNext());
Assert.assertEquals(Iterables.size(resultsOriginal.getClassifications()), Iterables.size(resultsLater.getClassifications()));
Assert.assertEquals(Iterables.size(resultsOriginal.getHints()), Iterables.size(resultsLater.getHints()));
Assert.assertEquals(Iterables.size(resultsOriginal.getReportLinks()), Iterables.size(resultsLater.getReportLinks()));
}
private ExecutionResults executeWindup(Path input, Path output, WindupToolingProgressMonitor progressMonitor) throws RemoteException
{
builder.setWindupHome(Paths.get(".").toString());
builder.setInput(input.toString());
builder.setOutput(output.toString());
builder.setProgressMonitor(progressMonitor);
builder.includePackage("org.windup.examples.ejb.messagedriven");
builder.ignore("\\.class$");
builder.setOption(SourceModeOption.NAME, true);
builder.setOption(OnlineModeOption.NAME, false);
return builder.execute();
}
@Test
public void testExecutionBuilderRegistered() throws Exception
{
rmiServer.startServer(PORT, "");
Path input = Paths.get("../../test-files/src_example");
Path output = ExecutionBuilderTest.getDefaultPath();
ExecutionBuilder builder = getExecutionBuilderFromRMIRegistry();
Assert.assertNotNull(builder);
builder.setWindupHome(Paths.get(".").toString());
builder.setInput(input.toString());
builder.setOutput(output.toString());
builder.setProgressMonitor(new TestProgressMonitor());
builder.setOption(SourceModeOption.NAME, true);
builder.setOption(TargetOption.NAME, Lists.newArrayList("eap"));
builder.setOption(SourceOption.NAME, Lists.newArrayList("eap"));
builder.setOption(OnlineModeOption.NAME, false);
builder.includePackage("org.windup.examples.ejb.messagedriven");
builder.ignore("\\.class$");
ExecutionResults results = builder.execute();
Assert.assertNotNull(results);
}
@Singleton
public static class TestProvider extends AbstractRuleProvider
{
private boolean sourceMode = false;
private boolean onlineMode = false;
public TestProvider()
{
super(MetadataBuilder.forProvider(TestProvider.class));
}
@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
return ConfigurationBuilder.begin()
.addRule()
.when(JavaClass.references("javax.{*}"))
.perform(Hint.withText("References javax.*").withQuickfix(createTestQuickfix()).withEffort(43)
.and(Classification.as("References some javax stuff")))
.addRule()
.perform(new GraphOperation()
{
@Override
public void perform(GraphRewrite event, EvaluationContext context)
{
WindupConfigurationModel configuration = WindupConfigurationService.getConfigurationModel(event.getGraphContext());
onlineMode = configuration.isOnlineMode();
WindupJavaConfigurationModel javaConfiguration = WindupJavaConfigurationService.getJavaConfigurationModel(event
.getGraphContext());
sourceMode = javaConfiguration.isSourceMode();
}
});
}
/**
* Create a delete quickfix type for test
*/
private Quickfix createTestQuickfix()
{
Quickfix quickfix = new Quickfix();
quickfix.setName("quickfix1");
quickfix.setType(org.jboss.windup.reporting.model.QuickfixType.DELETE_LINE);
return quickfix;
}
}
class TestProgressMonitor extends UnicastRemoteObject implements WindupToolingProgressMonitor, Remote
{
private static final long serialVersionUID = 1L;
final List<LogRecord> logRecords = new ArrayList<>();
private int totalWork;
private int completed;
private boolean done;
protected TestProgressMonitor() throws RemoteException
{
super();
}
@Override
public void logMessage(LogRecord logRecord)
{
logRecords.add(logRecord);
}
@Override
public void beginTask(String name, int totalWork)
{
this.totalWork = totalWork;
}
@Override
public void done()
{
this.done = true;
}
@Override
public boolean isCancelled()
{
return false;
}
@Override
public void setCancelled(boolean value)
{
}
@Override
public void setTaskName(String name)
{
}
@Override
public void subTask(String name)
{
}
@Override
public void worked(int work)
{
this.completed = work;
}
}
}