Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[SMA-1] Add support for scanning mutiple archives at a time

The inputPath may now point to a single archive or to a directory. In the event
of it pointing to a directory the directory structure is scanned and every
archive that's found is analyzed. An archive is identified by the file being in
Zip format, i.e. there's no requirement for an archive to have a well-known
file suffix for it to be analyzed.

A separate report is produced for each archive that's analyzed. Each report is
written into its own directory beneath the configured outputPath location. In
the case of multiple archives being scanned, the directory structure of the
reports that are produced will mirror the structure of the directory that was
provided as input.
  • Loading branch information...
commit 93dcbb6f4880e799abcb0fa008cef9d781174267 1 parent 09ce1b7
@wilkinsona wilkinsona authored
View
5 command-line/pom.xml
@@ -38,6 +38,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
View
33 command-line/src/main/java/org/springframework/migrationanalyzer/commandline/ArchiveDiscoverer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * 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.
+ */
+
+package org.springframework.migrationanalyzer.commandline;
+
+import java.io.File;
+import java.util.List;
+
+interface ArchiveDiscoverer {
+
+ /**
+ * Discovers the archives that are to be analyzed by examining the given <code>location</code>. If no archives are
+ * found, an empty list must be returned, <strong>not</strong> null.
+ *
+ * @param location The location to examine
+ *
+ * @return the discovered archives that are to be analyzed
+ */
+ List<File> discover(File location);
+}
View
46 ...rc/main/java/org/springframework/migrationanalyzer/commandline/CommandLineMigrationAnalysisExecutor.java
@@ -18,6 +18,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.List;
import org.springframework.migrationanalyzer.analyze.AnalysisEngine;
import org.springframework.migrationanalyzer.analyze.AnalysisResult;
@@ -38,6 +39,8 @@
private final FileSystemFactory fileSystemFactory;
+ private final ArchiveDiscoverer archiveDiscoverer;
+
private final String inputPath;
private final String outputPath;
@@ -50,41 +53,60 @@
private static final String DEFAULT_OUTPUT_PATH = ".";
- CommandLineMigrationAnalysisExecutor(String inputPath, String outputType, String outputPath, String[] excludes) {
- this(inputPath, outputType, outputPath, excludes, new StandardAnalysisEngineFactory(), new StandardRenderEngineFactory(),
- new DirectoryFileSystemFactory());
+ CommandLineMigrationAnalysisExecutor(String inputPath, String outputType, String outputDirectory, String[] excludes) {
+ this(inputPath, outputType, outputDirectory, excludes, new StandardAnalysisEngineFactory(), new StandardRenderEngineFactory(),
+ new DirectoryFileSystemFactory(), new ZipArchiveDiscoverer());
}
- CommandLineMigrationAnalysisExecutor(String inputPath, String outputType, String outputPath, String[] excludes,
- AnalysisEngineFactory analysisEngineFactory, RenderEngineFactory renderEngineFactory, FileSystemFactory fileSystemFactory) {
+ CommandLineMigrationAnalysisExecutor(String inputPath, String outputType, String outputDirectory, String[] excludes,
+ AnalysisEngineFactory analysisEngineFactory, RenderEngineFactory renderEngineFactory, FileSystemFactory fileSystemFactory,
+ ArchiveDiscoverer archiveDiscoverer) {
this.analysisEngineFactory = analysisEngineFactory;
this.renderEngineFactory = renderEngineFactory;
this.fileSystemFactory = fileSystemFactory;
+ this.archiveDiscoverer = archiveDiscoverer;
this.inputPath = inputPath;
this.outputType = outputType;
- this.outputPath = outputPath == null ? DEFAULT_OUTPUT_PATH : outputPath;
+ this.outputPath = outputDirectory == null ? DEFAULT_OUTPUT_PATH : outputDirectory;
this.excludes = excludes == null ? DEFAULT_EXCLUDES : excludes;
}
@Override
public void execute() {
- FileSystem fileSystem = createFileSystem();
+ File inputFile = new File(this.inputPath);
+
+ List<File> discoveredArchives = this.archiveDiscoverer.discover(inputFile);
+

In case of many files, user would want to see progress of analysis. We can at least notify messages like: x no of archives found, analyzing x package.

@wilkinsona Owner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ for (File discoveredArchive : discoveredArchives) {
+ analyzeArchive(discoveredArchive, inputFile);
+ }
+ }
+
+ private void analyzeArchive(File archive, File inputFile) {
+ FileSystem fileSystem = createFileSystem(archive);
AnalysisEngine analysisEngine = this.analysisEngineFactory.createAnalysisEngine(fileSystem, this.excludes);
- RenderEngine renderEngine = this.renderEngineFactory.create(this.outputType, this.outputPath);
+ RenderEngine renderEngine = this.renderEngineFactory.create(this.outputType, getOutputPath(inputFile, archive));
AnalysisResult analysis = analysisEngine.analyze();
renderEngine.render(analysis);
fileSystem.cleanup();
}
- private FileSystem createFileSystem() {
+ private String getOutputPath(File inputFile, File archive) {
+ if (inputFile.equals(archive)) {
+ return new File(this.outputPath, archive.getName()).getAbsolutePath();
+ } else {
+ return new File(this.outputPath, inputFile.toURI().relativize(archive.toURI()).getPath()).getAbsolutePath();
+ }
+ }
+
+ private FileSystem createFileSystem(File archive) {
FileSystem fileSystem;
- File inputFile = new File(this.inputPath);
try {
- fileSystem = this.fileSystemFactory.createFileSystem(inputFile);
+ fileSystem = this.fileSystemFactory.createFileSystem(archive);
} catch (IOException e) {
- throw new IllegalArgumentException(String.format("Failed to create FileSystem for input '" + inputFile.getAbsolutePath() + "'"), e);
+ throw new IllegalArgumentException(String.format("Failed to create FileSystem for archive '%s'", archive), e);
}
return fileSystem;
}
View
5 command-line/src/main/java/org/springframework/migrationanalyzer/commandline/OptionsFactory.java
@@ -34,7 +34,8 @@ Options create() {
Options options = new Options();
options.addOption(OptionBuilder //
- .withDescription("The path to the input location") //
+ .withDescription(
+ "The path of the input location; either a single archive or a directory. In the case of a directory, the entire directory structure is examined and all archives that are found are analyzed") //
.isRequired() //
.hasArg() //
.withArgName("inputPath") //
@@ -48,7 +49,7 @@ Options create() {
.create(OPTION_KEY_OUTPUT_TYPE));
options.addOption(OptionBuilder //
- .withDescription("The path to the output location. Defaults to the current working directory") //
+ .withDescription("The path of the output directory. Defaults to the current working directory") //
.hasArg() //
.withArgName("outputPath") //
.create(OPTION_KEY_OUTPUT_PATH));
View
60 command-line/src/main/java/org/springframework/migrationanalyzer/commandline/ZipArchiveDiscoverer.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * 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.
+ */
+
+package org.springframework.migrationanalyzer.commandline;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.migrationanalyzer.util.IoUtils;
+import org.springframework.migrationanalyzer.util.ZipUtils;
+
+final class ZipArchiveDiscoverer implements ArchiveDiscoverer {
+
+ private final Logger logger = LoggerFactory.getLogger(ZipArchiveDiscoverer.class);
+
+ @Override
+ public List<File> discover(File location) {
+ List<File> discovered = new ArrayList<File>();
+ doDiscover(location, discovered);
+ return discovered;
+ }
+
+ private void doDiscover(File candidate, List<File> discovered) {
+ if (candidate.isDirectory()) {
+ for (File inDirectory : candidate.listFiles()) {
+ doDiscover(inDirectory, discovered);
+ }
+ } else {
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(candidate);
+ if (ZipUtils.isZipFile(in)) {
+ discovered.add(candidate);
+ }
+ } catch (IOException ioe) {
+ this.logger.warn("Unable to examine candidate archive '{}', it will not be analyzed", candidate);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+ }
+}
View
170 ...st/java/org/springframework/migrationanalyzer/commandline/CommandLineMigrationAnalysisExecutorTests.java
@@ -16,151 +16,133 @@
package org.springframework.migrationanalyzer.commandline;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
import org.junit.Test;
import org.springframework.migrationanalyzer.analyze.AnalysisEngine;
import org.springframework.migrationanalyzer.analyze.AnalysisResult;
-import org.springframework.migrationanalyzer.analyze.AnalysisResultEntry;
import org.springframework.migrationanalyzer.analyze.fs.FileSystem;
-import org.springframework.migrationanalyzer.analyze.fs.FileSystemEntry;
+import org.springframework.migrationanalyzer.analyze.fs.FileSystemFactory;
import org.springframework.migrationanalyzer.analyze.support.AnalysisEngineFactory;
import org.springframework.migrationanalyzer.render.RenderEngine;
import org.springframework.migrationanalyzer.render.support.RenderEngineFactory;
-public class CommandLineMigrationAnalysisExecutorTests {
+public final class CommandLineMigrationAnalysisExecutorTests {
- @Test
- public void execute() {
- StubAnalysisEngineFactory analysisEngineFactory = new StubAnalysisEngineFactory();
- StubRenderEngineFactory renderEngineFactory = new StubRenderEngineFactory();
+ private final AnalysisEngineFactory analysisEngineFactory = mock(AnalysisEngineFactory.class);
- CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("input", "type", "output", new String[0],
- analysisEngineFactory, renderEngineFactory, new StubFileSystemFactory());
- executor.execute();
+ private final AnalysisEngine analysisEngine = mock(AnalysisEngine.class);
- assertEquals(1, analysisEngineFactory.analysisEngines.size());
- assertEquals(1, analysisEngineFactory.analysisEngines.get(0).analysisPerformed);
+ private final RenderEngineFactory renderEngineFactory = mock(RenderEngineFactory.class);
- assertEquals(1, renderEngineFactory.renderEngines.size());
- assertEquals(1, renderEngineFactory.renderEngines.get(0).rendersPerformed);
- }
+ private final RenderEngine renderEngine = mock(RenderEngine.class);
- @Test
- public void handlingOfNullExcludes() {
- StubAnalysisEngineFactory analysisEngineFactory = new StubAnalysisEngineFactory();
- StubRenderEngineFactory renderEngineFactory = new StubRenderEngineFactory();
+ private final FileSystemFactory fileSystemFactory = mock(FileSystemFactory.class);
- CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("input", "type", "output", null,
- analysisEngineFactory, renderEngineFactory, new StubFileSystemFactory());
+ private final FileSystem fileSystem = mock(FileSystem.class);
- executor.execute();
+ private final ArchiveDiscoverer archiveDiscoverer = mock(ArchiveDiscoverer.class);
- String[] excludes = analysisEngineFactory.getExcludes();
- assertNotNull(excludes);
- assertEquals(0, excludes.length);
- }
+ private final AnalysisResult analysisResult = mock(AnalysisResult.class);
@Test
- public void handlingOfNullOutputPath() {
- StubAnalysisEngineFactory analysisEngineFactory = new StubAnalysisEngineFactory();
- StubRenderEngineFactory renderEngineFactory = new StubRenderEngineFactory();
+ public void execute() throws IOException {
+ File outputLocation = new File("output");
+
+ File archive = new File("alpha.ear");
- CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("input", "type", null, new String[0],
- analysisEngineFactory, renderEngineFactory, new StubFileSystemFactory());
+ configureBehaviour(outputLocation, archive, archive);
+ CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("alpha.ear", "type", "output", new String[0],
+ this.analysisEngineFactory, this.renderEngineFactory, this.fileSystemFactory, this.archiveDiscoverer);
executor.execute();
- assertEquals(".", renderEngineFactory.getOutputPath());
+ verifyBehaviour(outputLocation, archive, archive);
}
- private static final class StubAnalysisEngineFactory implements AnalysisEngineFactory {
-
- private final List<StubAnalysisEngine> analysisEngines = new ArrayList<StubAnalysisEngine>();
+ @Test
+ public void handlingOfNullExcludes() throws IOException {
+ File outputLocation = new File("output");
- private volatile String[] excludes;
+ File archive = new File("alpha.ear");
- @Override
- public AnalysisEngine createAnalysisEngine(FileSystem fileSystem, String[] excludes) {
- this.excludes = excludes;
+ configureBehaviour(outputLocation, archive, archive);
- StubAnalysisEngine analysisEngine = new StubAnalysisEngine();
- this.analysisEngines.add(analysisEngine);
- return analysisEngine;
- }
+ CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("alpha.ear", "type", "output", null,
+ this.analysisEngineFactory, this.renderEngineFactory, this.fileSystemFactory, this.archiveDiscoverer);
+ executor.execute();
- String[] getExcludes() {
- return this.excludes;
- }
+ verifyBehaviour(outputLocation, archive, archive);
}
- private static final class StubAnalysisEngine implements AnalysisEngine {
+ @Test
+ public void handlingOfNullOutputPath() throws IOException {
+ File outputLocation = new File(".");
- private int analysisPerformed = 0;
+ File archive = new File("alpha.ear");
- @Override
- public AnalysisResult analyze() {
- this.analysisPerformed++;
- return new StubAnalysisResult();
- }
+ configureBehaviour(outputLocation, archive, archive);
+
+ CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("alpha.ear", "type", null, new String[0],
+ this.analysisEngineFactory, this.renderEngineFactory, this.fileSystemFactory, this.archiveDiscoverer);
+ executor.execute();
+
+ verifyBehaviour(outputLocation, archive, archive);
}
- private static final class StubAnalysisResult implements AnalysisResult {
+ @Test
+ public void handlingOfMultipleArchives() throws IOException {
+ File outputLocation = new File("output");
+ File inputLocation = new File("my-apps");
- @Override
- public <T> Set<AnalysisResultEntry<T>> getResultEntries(Class<T> type) {
- return null;
- }
+ File archive1 = new File(inputLocation, "alpha.ear");
+ File archive2 = new File(new File(inputLocation, "bravo"), "charlie.war");
- @Override
- public Set<FileSystemEntry> getFileSystemEntries() {
- return null;
- }
+ configureBehaviour(new File("output"), new File("my-apps"), archive1, archive2);
- @Override
- public AnalysisResult getResultForEntry(FileSystemEntry fileSystemEntry) {
- return null;
- }
+ CommandLineMigrationAnalysisExecutor executor = new CommandLineMigrationAnalysisExecutor("my-apps", "type", "output", new String[0],
+ this.analysisEngineFactory, this.renderEngineFactory, this.fileSystemFactory, this.archiveDiscoverer);
+ executor.execute();
- @Override
- public Set<Class<?>> getResultTypes() {
- return null;
- }
+ verifyBehaviour(outputLocation, inputLocation, archive1, archive2);
}
- private static final class StubRenderEngineFactory implements RenderEngineFactory {
+ private void configureBehaviour(File outputLocation, File inputLocation, File... archives) throws IOException {
- private final List<StubRenderEngine> renderEngines = new ArrayList<StubRenderEngine>();
+ when(this.archiveDiscoverer.discover(inputLocation)).thenReturn(Arrays.asList(archives));
- private volatile String outputPath;
+ for (File archive : archives) {
+ when(this.fileSystemFactory.createFileSystem(archive)).thenReturn(this.fileSystem);
+ when(this.renderEngineFactory.create("type", getOutputPath(inputLocation, outputLocation, archive))).thenReturn(this.renderEngine);
+ }
- @Override
- public RenderEngine create(String outputType, String outputPath) {
- this.outputPath = outputPath;
+ when(this.analysisEngineFactory.createAnalysisEngine(this.fileSystem, new String[0])).thenReturn(this.analysisEngine);
+ when(this.analysisEngine.analyze()).thenReturn(this.analysisResult);
+ }
- StubRenderEngine renderEngine = new StubRenderEngine();
- this.renderEngines.add(renderEngine);
- return renderEngine;
- }
+ private void verifyBehaviour(File outputLocation, File inputLocation, File... archives) {
+ verify(this.analysisEngineFactory, times(archives.length)).createAnalysisEngine(this.fileSystem, new String[0]);
+ verify(this.analysisEngine, times(archives.length)).analyze();
- String getOutputPath() {
- return this.outputPath;
+ for (File archive : archives) {
+ verify(this.renderEngineFactory).create("type", getOutputPath(inputLocation, outputLocation, archive));
}
+ verify(this.renderEngine, times(archives.length)).render(this.analysisResult);
}
- private static final class StubRenderEngine implements RenderEngine {
-
- private int rendersPerformed = 0;
-
- @Override
- public void render(AnalysisResult analysis) {
- this.rendersPerformed++;
+ private String getOutputPath(File inputLocation, File outputLocation, File archive) {
+ if (inputLocation.equals(archive)) {
+ return new File(outputLocation, inputLocation.getPath()).getAbsolutePath();
+ } else {
+ return new File(outputLocation, archive.getPath().substring(inputLocation.getName().length())).getAbsolutePath();
}
}
}
View
6 pom.xml
@@ -38,6 +38,7 @@
<jta.version>1.1.1</jta.version>
<junit.version>4.8.2</junit.version>
<logback.version>1.0.0</logback.version>
+ <mockito.version>1.8.5</mockito.version>
<slf4j.version>1.6.4</slf4j.version>
<spring.version>3.0.5.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -87,6 +88,11 @@
<version>${jta.version}</version>
</dependency>
<dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
@snehalmistry

In case of many files, user would want to see progress of analysis. We can at least notify messages like: x no of archives found, analyzing x package.

@wilkinsona
Please sign in to comment.
Something went wrong with that request. Please try again.