package org.jboss.windup.graph; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.inject.Inject; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; 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.shrinkwrap.api.ShrinkWrap; import org.jboss.windup.config.KeepWorkDirsOption; import org.jboss.windup.exec.WindupProcessor; import org.jboss.windup.exec.configuration.WindupConfiguration; import org.jboss.windup.graph.model.ArchiveModel; import org.jboss.windup.graph.traversal.ProjectModelTraversal; import org.jboss.windup.graph.model.WindupConfigurationModel; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.graph.service.WindupConfigurationService; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; /** * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a> */ @RunWith(Arquillian.class) public class ProjectModelTraversalTest { @Inject private GraphContextFactory factory; @Inject private WindupProcessor processor; @Deployment @AddonDependencies({ @AddonDependency(name = "org.jboss.windup.graph:windup-graph"), @AddonDependency(name = "org.jboss.windup.reporting:windup-reporting"), @AddonDependency(name = "org.jboss.windup.exec:windup-exec"), @AddonDependency(name = "org.jboss.windup.rules.apps:windup-rules-java"), @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(); } private Path getTempDirectory() { return FileUtils.getTempDirectory() .toPath() .resolve("Windup") .resolve("ProjectTraversalTest_" + RandomStringUtils.randomAlphanumeric(6)); } private GraphContext createGraphContext(Path temporaryDirectory) { return factory.create(temporaryDirectory.resolve("output")); } @Test public void testProjectDuplicateTraversal() throws Exception { Path tempDirectory = getTempDirectory(); try (GraphContext context = createGraphContext(tempDirectory)) { final Path inputPath1 = Paths.get("../../test-files/jee-example-app-1.0.0.ear"); final Path inputPath2 = tempDirectory.resolve("copy-of-ear.ear"); FileUtils.copyFile(inputPath1.toFile(), inputPath2.toFile()); runTest(context, Arrays.asList(inputPath1.toString(), inputPath2.toString())); final List<String> log4jPathList = new ArrayList<>(); final List<String> migrationSupportPathList = new ArrayList<>(); FileFoundCallback fileFoundCallback = new FileFoundCallback() { @Override public void fileFound(ProjectModelTraversal traversal, FileModel fileModel) { if (fileModel.getFileName().contains("log4j-1.2.6.jar")) log4jPathList.add(traversal.getFilePath(fileModel)); else if (fileModel.getFileName().contains("migration-support-1.0.0.jar")) migrationSupportPathList.add(traversal.getFilePath(fileModel)); } }; WindupConfigurationModel windupConfiguration = WindupConfigurationService.getConfigurationModel(context); for (FileModel inputApplication : windupConfiguration.getInputPaths()) { System.out.println("---------------------------------------------"); System.out.println("Input App: " + inputApplication.getFileName() + ", project: " + inputApplication.getProjectModel().getName()); traverse(new ProjectModelTraversal(inputApplication.getProjectModel()), 0, fileFoundCallback); } Assert.assertTrue(log4jPathList.contains("jee-example-app-1.0.0.ear/jee-example-web.war/WEB-INF/lib/log4j-1.2.6.jar")); Assert.assertTrue(log4jPathList.contains("copy-of-ear.ear/jee-example-web.war/WEB-INF/lib/log4j-1.2.6.jar")); Assert.assertTrue(log4jPathList.contains("shared-libs/jee-example-web.war/WEB-INF/lib/log4j-1.2.6.jar")); Assert.assertTrue(log4jPathList.contains("jee-example-app-1.0.0.ear/log4j-1.2.6.jar")); Assert.assertTrue(log4jPathList.contains("copy-of-ear.ear/log4j-1.2.6.jar")); Assert.assertTrue(log4jPathList.contains("shared-libs/log4j-1.2.6.jar")); Assert.assertTrue(migrationSupportPathList.contains("jee-example-app-1.0.0.ear/jee-example-web.war/WEB-INF/lib/migration-support-1.0.0.jar")); Assert.assertTrue(migrationSupportPathList.contains("copy-of-ear.ear/jee-example-web.war/WEB-INF/lib/migration-support-1.0.0.jar")); Assert.assertTrue(migrationSupportPathList.contains("shared-libs/jee-example-web.war/WEB-INF/lib/migration-support-1.0.0.jar")); Assert.assertTrue(migrationSupportPathList.contains("jee-example-app-1.0.0.ear/migration-support-1.0.0.jar")); Assert.assertTrue(migrationSupportPathList.contains("copy-of-ear.ear/migration-support-1.0.0.jar")); Assert.assertTrue(migrationSupportPathList.contains("shared-libs/migration-support-1.0.0.jar")); System.out.println("Done!"); } finally { FileUtils.deleteDirectory(tempDirectory.toFile()); } } @Test public void testDuplicateFilesWithDifferingNames() throws Exception { Path tempDirectory = getTempDirectory(); try (GraphContext context = createGraphContext(tempDirectory)) { final Path inputPath1 = Paths.get("src/test/resources/project_model_traversal/app.ear"); runTest(context, Collections.singleton(inputPath1.toString())); final List<String> pathList = new ArrayList<>(); FileFoundCallback fileFoundCallback = new FileFoundCallback() { @Override public void fileFound(ProjectModelTraversal traversal, FileModel fileModel) { if (!(fileModel instanceof ArchiveModel)) return; String path = traversal.getFilePath(fileModel); pathList.add(path); } }; WindupConfigurationModel windupConfiguration = WindupConfigurationService.getConfigurationModel(context); for (FileModel inputApplication : windupConfiguration.getInputPaths()) { System.out.println("---------------------------------------------"); System.out.println("Input App: " + inputApplication.getFileName() + ", project: " + inputApplication.getProjectModel().getName()); traverseRoots(new ProjectModelTraversal(inputApplication.getProjectModel()), fileFoundCallback); } Assert.assertTrue(pathList.contains("app.ear/xercesImpl-2.11.0.jar")); Assert.assertTrue(pathList.contains("app.ear/xercesImpl-other.jar")); System.out.println("Done!"); } finally { FileUtils.deleteDirectory(tempDirectory.toFile()); } } private void traverseRoots(ProjectModelTraversal traversal, FileFoundCallback callback) { callback.fileFound(traversal, traversal.getCurrent().getRootFileModel()); for (ProjectModelTraversal child : traversal.getChildren()) { traverseRoots(child, callback); } } private void traverse(ProjectModelTraversal traversal, int indentLevel, FileFoundCallback callback) { String indent = StringUtils.repeat(" ", indentLevel * 3); System.out.println(indent + "Project: " + traversal.getCanonicalProject().getName()); System.out.println("Root file: " + traversal.getFilePath(traversal.getCurrent().getRootFileModel())); System.out.println(indent + "Files: "); for (FileModel fileModel : traversal.getCanonicalProject().getFileModels()) { System.out.println(indent + " " + traversal.getFilePath(fileModel)); callback.fileFound(traversal, fileModel); } for (ProjectModelTraversal child : traversal.getChildren()) { traverse(child, indentLevel + 1, callback); } } void runTest(final GraphContext graphContext, Iterable<String> inputPaths) throws Exception { WindupConfiguration windupConfiguration = new WindupConfiguration().setGraphContext(graphContext); windupConfiguration.setAlwaysHaltOnException(true); windupConfiguration.setOptionValue(KeepWorkDirsOption.NAME, true); for (String inputPath : inputPaths) { windupConfiguration.addInputPath(Paths.get(inputPath)); } windupConfiguration.setOutputDirectory(graphContext.getGraphDirectory()); processor.execute(windupConfiguration); } private interface FileFoundCallback { void fileFound(ProjectModelTraversal traversal, FileModel fileModel); } }