allowedDirectoryNames) {
- super(target, new String[] { source.getPath() },
+ super(target, new File[] { source },
new CopyMigratedFiles(source.toPath(), allowedDirectoryNames));
}
diff --git a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/CopyResourcesStep.java b/flow-migration/src/main/java/com/vaadin/flow/migration/CopyResourcesStep.java
similarity index 96%
rename from flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/CopyResourcesStep.java
rename to flow-migration/src/main/java/com/vaadin/flow/migration/CopyResourcesStep.java
index 167a13f597c..012be82be1e 100644
--- a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/CopyResourcesStep.java
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/CopyResourcesStep.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.File;
import java.io.IOException;
@@ -40,7 +40,7 @@
* Step which copies resources from provided collection of directories to the
* target folder. It keeps the files hierarchical structure.
*
- * The content of copied file is modified to correct URIs in the imports and
+ * The content of copied file is modified to correct URI in the imports and
* remove the comments.
*
* @author Vaadin Ltd
@@ -174,11 +174,11 @@ private void addBowerComponent(String uri) {
* @param resourceFolders
* an array of source folders
*/
- public CopyResourcesStep(File target, String[] resourceFolders) {
+ public CopyResourcesStep(File target, File[] resourceFolders) {
this(target, resourceFolders, new HashSet<>());
}
- private CopyResourcesStep(File target, String[] resourceFolders,
+ private CopyResourcesStep(File target, File[] resourceFolders,
Set bowerComponents) {
super(target, resourceFolders,
new HtmlImportRewriter(target, bowerComponents));
diff --git a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/CreateMigrationJsonsStep.java b/flow-migration/src/main/java/com/vaadin/flow/migration/CreateMigrationJsonsStep.java
similarity index 98%
rename from flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/CreateMigrationJsonsStep.java
rename to flow-migration/src/main/java/com/vaadin/flow/migration/CreateMigrationJsonsStep.java
index 359bf3473f7..cc4947e5a7e 100644
--- a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/CreateMigrationJsonsStep.java
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/CreateMigrationJsonsStep.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.BufferedReader;
import java.io.File;
diff --git a/flow-migration/src/main/java/com/vaadin/flow/migration/Migration.java b/flow-migration/src/main/java/com/vaadin/flow/migration/Migration.java
new file mode 100644
index 00000000000..e08b4bfe065
--- /dev/null
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/Migration.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.vaadin.flow.server.frontend.FrontendUtils;
+
+import elemental.json.Json;
+import elemental.json.JsonObject;
+import elemental.json.JsonValue;
+
+/**
+ * Migrates resource (template and CSS) files from provided directories and Java
+ * source files from V13 to V14.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class Migration {
+
+ private static final String DEPENDENCIES = "dependencies";
+
+ private final File tempMigrationFolder;
+
+ private final File targetDirectory;
+
+ private final File[] resourceDirectories;
+
+ private final MigrationConfiguration configuration;
+
+ /**
+ * Creates an instance with given {@code configuration} to migrate.
+ *
+ * @param configuration
+ * configuration to do migration
+ */
+ public Migration(MigrationConfiguration configuration) {
+ this.configuration = configuration;
+ if (getTempMigrationFolder() == null) {
+ if(configuration.getTempMigrationFolder() != null) {
+ tempMigrationFolder = configuration.getTempMigrationFolder();
+ } else {
+ try {
+ tempMigrationFolder = Files.createTempDirectory("migration")
+ .toFile();
+ } catch (IOException e) {
+ throw new RuntimeException("Could not create a new "
+ + "temporary folder for migration. You may specify it manually");
+ }
+ }
+ } else {
+ if (!getTempMigrationFolder().isDirectory()) {
+ String message = String
+ .format("Received temp migration folder value '%s' is not a directory.",
+ getTempMigrationFolder());
+ throw new IllegalArgumentException(message);
+ } else if (getTempMigrationFolder().list().length > 0) {
+ String message = String
+ .format("Received non empty directory '%s' for use as the temporary migration folder.",
+ getTempMigrationFolder());
+ throw new IllegalArgumentException(message);
+ }
+ tempMigrationFolder = getTempMigrationFolder();
+ }
+
+ if (configuration.getBaseDirectory() == null) {
+ throw new IllegalArgumentException(
+ "Configuration does not provide a base directory");
+ }
+
+ if (configuration.getResourceDirectories() != null
+ && configuration.getResourceDirectories().length == 0) {
+ throw new IllegalArgumentException(
+ "Configuration does not provide any resource directories");
+ } else if (configuration.getResourceDirectories() == null) {
+ resourceDirectories = new File[] { new File(
+ configuration.getBaseDirectory(), "src/main/webapp") };
+ } else {
+ resourceDirectories = configuration.getResourceDirectories();
+ }
+
+ if (configuration.getTargetDirectory() == null) {
+ targetDirectory = new File(configuration.getBaseDirectory(),
+ "frontend");
+ } else {
+ targetDirectory = configuration.getBaseDirectory();
+ }
+
+ if (configuration.getClassFinder() == null) {
+ throw new IllegalArgumentException(
+ "Configuration does not provide a class finder");
+ }
+
+ if (configuration.getJavaSourceDirectories() == null
+ || configuration.getJavaSourceDirectories().length == 0) {
+ throw new IllegalArgumentException(
+ "Configuration does not provide any java source directories");
+ }
+
+ if (configuration.getCompiledClassDirectory() == null) {
+ throw new IllegalArgumentException(
+ "Configuration does not provide a compiled class directory");
+ }
+ }
+
+ /**
+ * Performs the migration.
+ *
+ * @throws MigrationToolsException
+ * Thrown when migration tools are missing
+ * @throws MigrationFailureException
+ * Thrown for an exception during migration
+ */
+ public void migrate()
+ throws MigrationToolsException, MigrationFailureException {
+ prepareMigrationDirectory();
+
+ List bowerCommands = FrontendUtils
+ .getBowerExecutable(getTempMigrationFolder().getPath());
+ boolean needInstallBower = bowerCommands.isEmpty();
+ if (!ensureTools(needInstallBower)) {
+ throw new MigrationToolsException(
+ "Could not install tools required for migration (bower or modulizer)");
+ }
+ if (needInstallBower) {
+ bowerCommands = FrontendUtils
+ .getBowerExecutable(getTempMigrationFolder().getPath());
+ }
+
+ if (bowerCommands.isEmpty()) {
+ throw new MigrationToolsException(
+ "Could not locate bower. Install it manually on your system and re-run migration goal.");
+ }
+
+ Set externalComponents;
+ CopyResourcesStep copyStep = new CopyResourcesStep(
+ getTempMigrationFolder(), getResources());
+ Map> paths;
+ try {
+ paths = copyStep.copyResources();
+ externalComponents = copyStep.getBowerComponents();
+ } catch (IOException exception) {
+ throw new UncheckedIOException(
+ "Couldn't copy resources from source directories "
+ + Arrays.asList(getResources())
+ + " to the target directory "
+ + getTempMigrationFolder(),
+ exception);
+ }
+
+ Set migratedTopLevelDirs = Stream
+ .of(getTempMigrationFolder().listFiles())
+ .filter(File::isDirectory).map(File::getName)
+ .collect(Collectors.toSet());
+
+ List allPaths = new ArrayList<>();
+ paths.values().stream().forEach(allPaths::addAll);
+ try {
+ new CreateMigrationJsonsStep(getTempMigrationFolder())
+ .createJsons(allPaths);
+ } catch (IOException exception) {
+ throw new UncheckedIOException("Couldn't generate json files",
+ exception);
+ }
+
+ if (!saveBowerComponents(bowerCommands, externalComponents)) {
+ throw new MigrationFailureException(
+ "Could not install bower components");
+ }
+
+ installNpmPackages();
+
+ boolean modulizerHasErrors = false;
+ if (!runModulizer()) {
+ modulizerHasErrors = true;
+ if (configuration.isIgnoreModulizerErrors()) {
+ getLogger().info("Modulizer has exited with error");
+ } else {
+ throw new MigrationFailureException(
+ "Modulizer has exited with error. Unable to proceed.");
+ }
+ }
+
+ // copy the result JS files into target dir ("frontend")
+ if (!getTargetDirectory().exists()) {
+ try {
+ FileUtils.forceMkdir(getTargetDirectory());
+ } catch (IOException exception) {
+ throw new UncheckedIOException(
+ "Unable to create a target folder for migrated files: '"
+ + getTargetDirectory() + "'",
+ exception);
+ }
+ }
+ CopyMigratedResourcesStep copyMigratedStep = new CopyMigratedResourcesStep(
+ getTargetDirectory(), getTempMigrationFolder(),
+ migratedTopLevelDirs);
+ try {
+ copyMigratedStep.copyResources();
+ } catch (IOException exception) {
+ throw new UncheckedIOException(
+ "Couldn't copy migrated resources to the target directory "
+ + getTargetDirectory(),
+ exception);
+ }
+
+ try {
+ cleanUp(getTempMigrationFolder());
+ } catch (IOException exception) {
+ getLogger().debug(
+ "Couldn't remove " + getTempMigrationFolder().getPath(),
+ exception);
+ }
+
+ if (!modulizerHasErrors && !configuration.isKeepOriginalFiles()) {
+ removeOriginalResources(paths);
+ }
+
+ switch (configuration.getAnnotationRewriteStrategy()) {
+ case SKIP:
+ break;
+ case ALWAYS:
+ rewrite();
+ break;
+ case SKIP_ON_ERROR:
+ if (!modulizerHasErrors) {
+ rewrite();
+ }
+ break;
+ }
+ }
+
+ /**
+ * Prepare migration by cleaning everything, except if only node_modules
+ * exists in the target directory.
+ */
+ private void prepareMigrationDirectory() {
+ if (getTempMigrationFolder().exists()) {
+ String[] list = getTempMigrationFolder().list();
+ if (list.length == 1 && list[0].equals("node_modules")) {
+ return;
+ } else if (list.length == 2 &&
+ Stream.of(list).filter(file -> file.startsWith("node"))
+ .count() == 2) {
+ return;
+ }
+ try {
+ cleanUp(getTempMigrationFolder());
+ } catch (IOException exception) {
+ String message = String
+ .format("Unable to clean up directory '%s'",
+ getTempMigrationFolder());
+ throw new UncheckedIOException(message, exception);
+ }
+ } else {
+ try {
+ FileUtils.forceMkdir(getTempMigrationFolder());
+ } catch (IOException exception) {
+ String message = String
+ .format("Failed in creating migration folder '%s'",
+ getTempMigrationFolder());
+ throw new UncheckedIOException(message, exception);
+ }
+ }
+ }
+
+ private void removeOriginalResources(Map> paths) {
+ for (Entry> entry : paths.entrySet()) {
+ File resourceFolder = new File(entry.getKey());
+ entry.getValue()
+ .forEach(path -> new File(resourceFolder, path).delete());
+ }
+ }
+
+ private void installNpmPackages() throws MigrationFailureException {
+ List npmExec = FrontendUtils
+ .getNpmExecutable(configuration.getBaseDirectory().getPath());
+ List npmInstall = new ArrayList<>(npmExec.size());
+ npmInstall.addAll(npmExec);
+ npmInstall.add("i");
+
+ if (!executeProcess(npmInstall, "Couldn't install packages using npm",
+ "Packages successfully installed",
+ "Error when running `npm install`")) {
+ throw new MigrationFailureException(
+ "Error during package installation via npm");
+ }
+ }
+
+ private boolean runModulizer() {
+ Collection depMapping = makeDependencyMapping();
+
+ List command = new ArrayList<>();
+ command.add(FrontendUtils
+ .getNodeExecutable(configuration.getBaseDirectory().getPath()));
+ command.add("node_modules/polymer-modulizer/bin/modulizer.js");
+ command.add("--force");
+ command.add("--out");
+ command.add(".");
+ command.add("--import-style=name");
+ if (!depMapping.isEmpty()) {
+ command.add("--dependency-mapping");
+ command.addAll(depMapping);
+ }
+
+ return executeProcess(command, "Migration has finished with errors",
+ "Modulizer has completed successfully",
+ "Error when running moulizer");
+ }
+
+ private Collection makeDependencyMapping() {
+ File bower = new File(getTempMigrationFolder(), "bower.json");
+
+ try {
+ Set result = new HashSet<>();
+ String content = Files.readAllLines(bower.toPath()).stream()
+ .collect(Collectors.joining("\n"));
+ JsonObject object = Json.parse(content);
+ if (object.hasKey(DEPENDENCIES)) {
+ JsonObject deps = object.getObject(DEPENDENCIES);
+ Stream.of(deps.keys()).filter(key -> key.startsWith("vaadin-"))
+ .forEach(key -> result
+ .add(makeVaadinDependencyMapping(deps, key)));
+ }
+ return result;
+ } catch (IOException exception) {
+ throw new UncheckedIOException("Unable to read bower.json",
+ exception);
+ }
+ }
+
+ private String makeVaadinDependencyMapping(JsonObject deps, String key) {
+ JsonValue version = deps.get(key);
+ StringBuilder builder = new StringBuilder(key);
+ builder.append(',');
+ builder.append("@vaadin/");
+ builder.append(key).append(',');
+ builder.append(version.asString());
+ return builder.toString();
+ }
+
+ private boolean saveBowerComponents(List bowerCommands,
+ Collection components) {
+ List command = new ArrayList<>();
+ command.addAll(bowerCommands);
+ // install
+ command.add("i");
+ // -F option means: Force latest version on conflict
+ command.add("-F");
+ // disable interactive mode
+ command.add("--config.interactive=false");
+ // -S option means: Save installed packages into the project’s
+ // bower.json dependencies
+ command.add("-S");
+
+ // add all extracted bower components to install them and save
+
+ // the latest polymer version which is chosen by bower has only JS
+ // module file. It won't be resolved from the import properly. So we
+ // have to force 2.x.x version which is P2 based.
+ command.add("polymer#2.8.0");
+ components.stream().filter(component -> !"polymer".equals(component))
+ .forEach(command::add);
+
+ return executeProcess(command,
+ "Couldn't install and save bower components",
+ "All components are installed and saved successfully",
+ "Error when running `bower install`");
+ }
+
+ private boolean ensureTools(boolean needInstallBower) {
+ List npmExecutable = FrontendUtils
+ .getNpmExecutable(configuration.getBaseDirectory().getPath());
+ List command = new ArrayList<>();
+ command.addAll(npmExecutable);
+ command.add("install");
+ if (needInstallBower) {
+ command.add("bower");
+ }
+ command.add("polymer-modulizer");
+
+ return executeProcess(command, "Couldn't install migration tools",
+ "Bower is installed successfully",
+ "Error when running `npm install`");
+ }
+
+ protected boolean executeProcess(List command, String errorMsg,
+ String successMsg, String exceptionMsg) {
+ ProcessBuilder builder = FrontendUtils.createProcessBuilder(command);
+ builder.directory(getTempMigrationFolder());
+
+ Process process = null;
+ try {
+ process = builder.inheritIO().start();
+ int errorCode = process.waitFor();
+ if (errorCode != 0) {
+ getLogger().error(errorMsg);
+ return false;
+ } else {
+ getLogger().debug(successMsg);
+ }
+ } catch (InterruptedException | IOException e) {
+ getLogger().error(exceptionMsg, e);
+ return false;
+ } finally {
+ if (process != null) {
+ process.destroyForcibly();
+ }
+ }
+
+ return true;
+ }
+
+ private Logger getLogger() {
+ return LoggerFactory.getLogger(Migration.class);
+ }
+
+ private void cleanUp(File dir) throws IOException {
+ FileUtils.forceDelete(dir);
+ }
+
+ private File[] getResources() {
+ if (getResourceDirectories() == null) {
+ File webApp = new File(configuration.getBaseDirectory(),
+ "src/main/webapp");
+ return new File[] { webApp };
+ }
+ return getResourceDirectories();
+ }
+
+ private void rewrite() {
+ RewriteLegacyAnnotationsStep step = new RewriteLegacyAnnotationsStep(
+ configuration.getCompiledClassDirectory(),
+ configuration.getClassFinder(),
+ Stream.of(configuration.getJavaSourceDirectories())
+ .collect(Collectors.toList()));
+ step.rewrite();
+ }
+
+ private File getTempMigrationFolder() {
+ return tempMigrationFolder;
+ }
+
+ private File getTargetDirectory() {
+ return targetDirectory;
+ }
+
+ private File[] getResourceDirectories() {
+ return resourceDirectories;
+ }
+
+}
diff --git a/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationConfiguration.java b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationConfiguration.java
new file mode 100644
index 00000000000..58063b32156
--- /dev/null
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationConfiguration.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+import java.io.File;
+import java.util.Objects;
+
+import com.vaadin.flow.component.dependency.HtmlImport;
+import com.vaadin.flow.component.dependency.JsModule;
+import com.vaadin.flow.component.dependency.StyleSheet;
+import com.vaadin.flow.server.frontend.scanner.ClassFinder;
+
+/**
+ * Configuration for migration.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class MigrationConfiguration {
+
+ private File tempMigrationFolder;
+
+ private File[] resourceDirectories;
+
+ private File targetDirectory;
+
+ private boolean keepOriginalFiles;
+
+ private boolean ignoreModulizerErrors = true;
+
+ private AnnotationsRewriteStrategy annotationRewriteStrategy = AnnotationsRewriteStrategy.ALWAYS;
+
+ private final File baseDirectory;
+
+ private ClassFinder classFinder;
+
+ private File[] javaSourceDirectories;
+
+ private File compiledClassDirectory;
+
+ private MigrationConfiguration(File baseDir) {
+ baseDirectory = baseDir;
+ }
+
+ private MigrationConfiguration(MigrationConfiguration configuration) {
+ this.tempMigrationFolder = configuration.getTempMigrationFolder();
+ if (configuration.getResourceDirectories() != null) {
+ this.resourceDirectories = configuration.getResourceDirectories()
+ .clone();
+ }
+ this.targetDirectory = configuration.getTargetDirectory();
+ this.keepOriginalFiles = configuration.isKeepOriginalFiles();
+ this.ignoreModulizerErrors = configuration.isIgnoreModulizerErrors();
+ this.annotationRewriteStrategy = configuration
+ .getAnnotationRewriteStrategy();
+ this.baseDirectory = configuration.getBaseDirectory();
+ this.classFinder = configuration.getClassFinder();
+ if (configuration.getJavaSourceDirectories() != null) {
+ this.javaSourceDirectories = configuration
+ .getJavaSourceDirectories().clone();
+ }
+ this.compiledClassDirectory = configuration.getCompiledClassDirectory();
+ }
+
+ /**
+ * Gets the migration folder.
+ *
+ * @return the migration folder
+ */
+ public File getTempMigrationFolder() {
+ return tempMigrationFolder;
+ }
+
+ /**
+ * Gets the resource directories.
+ *
+ * @return the resource directories
+ */
+ public File[] getResourceDirectories() {
+ return resourceDirectories;
+ }
+
+ /**
+ * Gets the target directory.
+ *
+ * @return the target directory
+ */
+ public File getTargetDirectory() {
+ return targetDirectory;
+ }
+
+ /**
+ * Checks whether the original resource files should be preserved.
+ *
+ * @return whether the original resource files should be preserved
+ */
+ public boolean isKeepOriginalFiles() {
+ return keepOriginalFiles;
+ }
+
+ /**
+ * Checks whether Modulizer errors should be ignored.
+ *
+ * @return whether Modulizer errors should be ignored
+ */
+ public boolean isIgnoreModulizerErrors() {
+ return ignoreModulizerErrors;
+ }
+
+ /**
+ * Gets the base directory
+ *
+ * @return the base directory
+ */
+ public File getBaseDirectory() {
+ return baseDirectory;
+ }
+
+ /**
+ * Gets the compiled classes directory.
+ *
+ * @return the compiled classes directory
+ */
+ public File getCompiledClassDirectory() {
+ return compiledClassDirectory;
+ }
+
+ /**
+ * Gets the class finder.
+ *
+ * @return the class finder
+ */
+ public ClassFinder getClassFinder() {
+ return classFinder;
+ }
+
+ /**
+ * Gets the java source roots.
+ *
+ * @return the java source roots
+ */
+ public File[] getJavaSourceDirectories() {
+ return javaSourceDirectories;
+ }
+
+ /**
+ * Gets the annotation rewrite strategy.
+ *
+ * @return the annotation rewrite strategy
+ */
+ public AnnotationsRewriteStrategy getAnnotationRewriteStrategy() {
+ return annotationRewriteStrategy;
+ }
+
+ /**
+ * A builder for {@link MigrationConfiguration}. Allows to set all required
+ * parameters via setters fluent API.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+ public static class Builder {
+
+ private final MigrationConfiguration config;
+
+ /**
+ * Creates a new instance of the builded with provided {@code baseDir}.
+ *
+ * @param baseDir
+ * base project directory
+ */
+ public Builder(File baseDir) {
+ config = new MigrationConfiguration(baseDir);
+ }
+
+ /**
+ * Sets temporary migration folder where the migration happens.
+ *
+ * The folder value is not required. It it's not set then temporary
+ * folder will be used. This folder will be removed once the migration
+ * happens regardless of result.
+ *
+ * @param file
+ * the migration folder
+ * @return this builder
+ */
+ public Builder setTemporaryMigrationFolder(File file) {
+ config.tempMigrationFolder = Objects.requireNonNull(file);
+ return this;
+ }
+
+ /**
+ * Sets the resource files directories.
+ *
+ * There can be several resource roots. They contains HTML tempate files
+ * and stylesheet files. The hierarchical structure will be transfered
+ * into the target directory (see {@link #setTargetDirectory(File)} as
+ * is (except "frontend" directory whose files and subdirs are moved
+ * ignoring the "frontend" dir).
+ *
+ * @param resourceDirs
+ * resource roots
+ * @return this builder
+ */
+ public Builder setResourceDirectories(File[] resourceDirs) {
+ config.resourceDirectories = Objects.requireNonNull(resourceDirs);
+ return this;
+ }
+
+ /**
+ * Sets the target directory where the resource files will be stored
+ * after the migration.
+ *
+ * This directory is usually is "frontend" folder inside base dir
+ *
+ * @param targetDir
+ * the target directory
+ * @return this builder
+ */
+ public Builder setTargetDirectory(File targetDir) {
+ config.targetDirectory = Objects.requireNonNull(targetDir);
+ return this;
+ }
+
+ /**
+ * Sets whether the original resources should be preserved.
+ *
+ * By default the original resources are removed if there were no errors
+ * during migration.
+ *
+ * @param keepOriginal
+ * whether the original resources should be preserved
+ * @return this builder
+ */
+ public Builder setKeepOriginalFiles(boolean keepOriginal) {
+ config.keepOriginalFiles = keepOriginal;
+ return this;
+ }
+
+ /**
+ * Sets whether the build should be considered successful even if there
+ * are Modulizer errors.
+ *
+ * Modulizer is an external tool which is used internally for converting
+ * resource files. Modulizer process exit status may be non zero even if
+ * all files have been converted correctly. By default the exit status
+ * code is ignored.
+ *
+ * @param ignoreModulizerErrors
+ * whether the tool should fail is Modulizer fails
+ * @return this builder
+ */
+ public Builder setIgnoreModulizerErrors(boolean ignoreModulizerErrors) {
+ config.ignoreModulizerErrors = ignoreModulizerErrors;
+ return this;
+ }
+
+ /**
+ * Sets the class finder instance.
+ *
+ * @param finder
+ * a class finder
+ * @return this builder
+ */
+ public Builder setClassFinder(ClassFinder finder) {
+ config.classFinder = Objects.requireNonNull(finder);
+ return this;
+ }
+
+ /**
+ * Sets java source roots.
+ *
+ * Java source roots contain java files which should be rewritten to use
+ * {@link JsModule} annotation instead of {@link HtmlImport} and
+ * {@link StyleSheet}.
+ *
+ * @param sourceRoots
+ * java source roots
+ * @return this builder
+ */
+ public Builder setJavaSourceRoots(File[] sourceRoots) {
+ config.javaSourceDirectories = Objects.requireNonNull(sourceRoots);
+ return this;
+ }
+
+ /**
+ * Sets java binary (compiled) classes directory.
+ *
+ * The java files from source roots ({@link #setJavaSourceRoots(File[])}
+ * must be compiled when the migration is done into this directory.
+ *
+ * @param classDirectory
+ * compiled java classes directory
+ * @return this builder
+ */
+ public Builder setCompiledClassDirectory(File classDirectory) {
+ config.compiledClassDirectory = Objects
+ .requireNonNull(classDirectory);
+ return this;
+ }
+
+ /**
+ * Sets the annotation rewrite strategy.
+ *
+ * This strategy is used to control annotation ( {@link HtmlImport} and
+ * {@link StyleSheet} rewrite logic. By default the annotation are
+ * always rewritten regardless of conversation status.
+ *
+ * @param strategy
+ * the annotation rewrite strategy
+ * @return this builder
+ */
+ public Builder setAnnotationRewriteStrategy(
+ AnnotationsRewriteStrategy strategy) {
+ config.annotationRewriteStrategy = Objects.requireNonNull(strategy);
+ return this;
+
+ }
+
+ /**
+ * Builds the immutable configuration based on the builder.
+ *
+ * @return the resulting configuration
+ */
+ public MigrationConfiguration build() {
+ // return an immutable instance
+ return new MigrationConfiguration(config);
+ }
+ }
+
+}
diff --git a/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationFailureException.java b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationFailureException.java
new file mode 100644
index 00000000000..dd2660b2bbc
--- /dev/null
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationFailureException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class MigrationFailureException extends Exception {
+
+ public MigrationFailureException(String message) {
+ super(message);
+ }
+}
diff --git a/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationTool.java b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationTool.java
new file mode 100644
index 00000000000..5575f16a2db
--- /dev/null
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationTool.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.vaadin.flow.migration.MigrationConfiguration.Builder;
+import com.vaadin.flow.server.scanner.ReflectionsClassFinder;
+
+/**
+ * Main class which allow to call migration from the command line using
+ * arguments.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class MigrationTool {
+
+ private static final String DEP_URLS = "depUrls";
+ private static final String SOURCE_DIRS = "sourceDirs";
+ private static final String TARGET_DIR = "targetDir";
+ private static final String KEEP_ORIGINAL = "keepOriginal";
+ private static final String MIGRATION_DIR = "migrationDir";
+ private static final String RESOURCES_DIRS = "resourcesDirs";
+ private static final String STOP_ON_ERROR = "stopOnError";
+ private static final String CLASSES_DIR = "classesDir";
+ private static final String BASE_DIR = "baseDir";
+ private static final String ANNOTATION_REWRITE = "annRewrite";
+
+ /**
+ * Runs migration tool using command line {@code args}.
+ *
+ * @param args
+ * command line arguments
+ * @throws MigrationFailureException
+ * if migration failed because of errors during execution
+ * @throws MigrationToolsException
+ * if migration failed because some necessary tools installation
+ * failed
+ *
+ * @see #runMigration(String[])
+ */
+ public static void main(String[] args)
+ throws MigrationToolsException, MigrationFailureException {
+ MigrationTool tool = new MigrationTool();
+
+ HelpFormatter formatter = new HelpFormatter();
+ try {
+ tool.runMigration(args);
+ } catch (CommandArgumentException exception) {
+ System.out.println(exception.getCause().getMessage());
+ if (exception.getOptions().isPresent()) {
+ formatter.printHelp("migration tool",
+ exception.getOptions().get());
+ }
+
+ System.exit(1);
+ }
+
+ }
+
+ /**
+ * Runs migration tool using command line {@code args}.
+ *
+ * @param args
+ * command line arguments
+ * @throws MigrationFailureException
+ * if migration failed because of errors during execution
+ * @throws MigrationToolsException
+ * if migration failed because some necessary tools installation
+ * failed
+ */
+ protected void runMigration(String[] args) throws CommandArgumentException,
+ MigrationToolsException, MigrationFailureException {
+ Options options = makeOptions();
+
+ CommandLineParser parser = new DefaultParser();
+
+ CommandLine command = null;
+
+ try {
+ command = parser.parse(options, args);
+ } catch (ParseException exception) {
+ throw new CommandArgumentException(options, exception);
+ }
+
+ File baseDirValue = new File(command.getOptionValue(BASE_DIR));
+ Builder builder = new Builder(baseDirValue);
+
+ getLogger().debug("The base dir is {}",
+ command.getOptionValue(BASE_DIR));
+
+ File compiledClasses = setCompiledClasses(command, builder);
+
+ setIgnoreModulizerErrors(command, builder);
+
+ setResourcesDirs(command, baseDirValue, builder);
+
+ setMigrationDir(command, builder);
+
+ setTargetDir(command, baseDirValue, builder);
+
+ setKeepOriginal(command, builder);
+
+ setSourceDirs(command, builder);
+
+ setClassFinder(command, builder, compiledClasses);
+
+ setAnnotationRewriteStrategy(command, builder);
+
+ doMigration(builder.build());
+ }
+
+ /**
+ * Runs migration using the provided {@code configuration}.
+ *
+ * @param configuration
+ * the configuration
+ * @throws MigrationFailureException
+ * if migration failed because of errors during execution
+ * @throws MigrationToolsException
+ * if migration failed because some necessary tools installation
+ * failed
+ */
+ protected void doMigration(MigrationConfiguration configuration)
+ throws MigrationToolsException, MigrationFailureException {
+ Migration migration = new Migration(configuration);
+ migration.migrate();
+ }
+
+ private void setAnnotationRewriteStrategy(CommandLine command,
+ Builder builder) throws CommandArgumentException {
+ String annotationRewrite = command.getOptionValue(ANNOTATION_REWRITE);
+ if (annotationRewrite != null) {
+ try {
+ AnnotationsRewriteStrategy strategy = AnnotationsRewriteStrategy
+ .valueOf(annotationRewrite);
+ builder.setAnnotationRewriteStrategy(strategy);
+ getLogger().debug(
+ "Annotation rewrite strategy is set to " + strategy);
+ } catch (IllegalArgumentException exception) {
+ throw new CommandArgumentException(exception);
+ }
+ } else {
+ getLogger().debug(
+ "Annotation rewrite strategy is not explicitly set");
+ }
+ }
+
+ private void setClassFinder(CommandLine command, Builder builder,
+ File compiledClasses) throws CommandArgumentException {
+ URL compiledClassesURL;
+ try {
+ compiledClassesURL = compiledClasses.toURI().toURL();
+ } catch (MalformedURLException exception) {
+ throw new CommandArgumentException(exception);
+ }
+ String[] urls = command.getOptionValues(DEP_URLS);
+ URL[] depUrls = new URL[urls.length + 1];
+ depUrls[0] = compiledClassesURL;
+ for (int i = 0; i < urls.length; i++) {
+ try {
+ depUrls[i + 1] = new URL(urls[i]);
+ } catch (MalformedURLException exception) {
+ throw new CommandArgumentException(exception);
+ }
+ }
+
+ builder.setClassFinder(new ReflectionsClassFinder(depUrls));
+ }
+
+ private void setSourceDirs(CommandLine command, Builder builder) {
+ String[] sourceDirs = command.getOptionValues(SOURCE_DIRS);
+ List sourceRoots = Stream.of(sourceDirs).map(File::new)
+ .collect(Collectors.toList());
+ builder.setJavaSourceRoots(
+ sourceRoots.toArray(new File[sourceRoots.size()]));
+ getLogger().debug("The java source directories are {}", sourceRoots);
+ }
+
+ private void setKeepOriginal(CommandLine command, Builder builder) {
+ if (command.hasOption(KEEP_ORIGINAL)) {
+ builder.setKeepOriginalFiles(true);
+ getLogger().debug("Keep original resources value is true");
+ } else {
+ getLogger().debug("Keep original resources value is false");
+ }
+ }
+
+ private void setTargetDir(CommandLine command, File baseDirValue,
+ Builder builder) {
+ String targetDir = command.getOptionValue(TARGET_DIR);
+ if (targetDir != null) {
+ builder.setTargetDirectory(new File(targetDir));
+ getLogger().debug("The target directory is {}", targetDir);
+ } else {
+ getLogger().debug(
+ "The target directory is not set explicitly. "
+ + "The value is implicitly set to {}",
+ new File(baseDirValue, "frontend"));
+ }
+ }
+
+ private void setMigrationDir(CommandLine command, Builder builder) {
+ String tempMigrationFolder = command.getOptionValue(MIGRATION_DIR);
+ if (tempMigrationFolder != null) {
+ builder.setTemporaryMigrationFolder(new File(tempMigrationFolder));
+ getLogger().debug("The temporary migration directory is {}",
+ tempMigrationFolder);
+ } else {
+ getLogger().debug(
+ "The temporary migration directory is not set explicitely");
+ }
+ }
+
+ private void setResourcesDirs(CommandLine command, File baseDirValue,
+ Builder builder) {
+ String[] resourceDirs = command.getOptionValues(RESOURCES_DIRS);
+ if (resourceDirs != null) {
+ List folders = Stream.of(resourceDirs).map(File::new)
+ .collect(Collectors.toList());
+ builder.setResourceDirectories(
+ folders.toArray(new File[folders.size()]));
+ getLogger().debug("The resource directories are {}", folders);
+ } else {
+ getLogger().debug(
+ "The resource directories is not set explicitely. "
+ + "The value is implicitely set to {}",
+ new File(baseDirValue, "src/main/webapp"));
+ }
+ }
+
+ private void setIgnoreModulizerErrors(CommandLine command,
+ Builder builder) {
+ if (command.hasOption(STOP_ON_ERROR)) {
+ builder.setIgnoreModulizerErrors(false);
+ getLogger().debug("Ignore modulizer errors value is false");
+ } else {
+ getLogger().debug("Ignore modulizer errors value is true");
+ }
+ }
+
+ private File setCompiledClasses(CommandLine command, Builder builder) {
+ File compiledClasses = new File(command.getOptionValue(CLASSES_DIR));
+ builder.setCompiledClassDirectory(compiledClasses);
+
+ getLogger().debug("The classes directory is {}",
+ command.getOptionValue(CLASSES_DIR));
+ return compiledClasses;
+ }
+
+ private Options makeOptions() {
+ Options options = new Options();
+
+ // Not required
+ Option migrationDir = new Option("md", MIGRATION_DIR, true,
+ "temporary migration directory");
+ options.addOption(migrationDir);
+
+ Option baseDir = new Option("b", BASE_DIR, true,
+ "base project directory. Normally it is the root of the files to migrate. "
+ + "The directory will be used to search and install "
+ + "(if necessary) external tools like node, npm, etc..");
+ baseDir.setRequired(true);
+ options.addOption(baseDir);
+
+ Option resourceDirectories = new Option("res", RESOURCES_DIRS, true,
+ "comma separated resource directories relative to the baseDir, by default the value is one path 'src/main/webapp' inside base directory");
+ options.addOption(resourceDirectories);
+
+ Option target = new Option("t", TARGET_DIR, true,
+ "target directory for converted resource files. "
+ + "By default it's the path 'frontend' inside the base directory");
+ options.addOption(target);
+
+ Option stopOnError = new Option("se", STOP_ON_ERROR, false,
+ "whether migration should "
+ + "stop execution with error if modulizer has exited with not 0 status");
+ options.addOption(stopOnError);
+
+ Option javaSourceDirectories = new Option("src", SOURCE_DIRS, true,
+ "comma separated java source directories");
+ javaSourceDirectories.setRequired(true);
+ options.addOption(javaSourceDirectories);
+
+ Option compiledClassesDir = new Option("c", CLASSES_DIR, true,
+ "compiled classes directory. Java classes have to be compiled into "
+ + "this directory to be able to apply migration");
+ compiledClassesDir.setRequired(true);
+ options.addOption(compiledClassesDir);
+
+ Option dependenciesUrls = new Option("d", DEP_URLS, true,
+ "comma separated classpath URLs. The URLs should include all dependencies for "
+ + "the project such as Jars or filesystem paths to binary classes");
+ dependenciesUrls.setRequired(true);
+ options.addOption(dependenciesUrls);
+
+ Option keepOriginal = new Option("ko", KEEP_ORIGINAL, false,
+ "whether the original "
+ + "resource files should be preserved. By default the migrated files are removed.");
+ options.addOption(keepOriginal);
+
+ Option annotationRewrite = new Option("ars", ANNOTATION_REWRITE, true,
+ "annotation rewrite strategy. By default the value is ALWAYS. Other choices are SKIP, SKIP_ON_ERROR");
+ options.addOption(annotationRewrite);
+ return options;
+ }
+
+ private Logger getLogger() {
+ return LoggerFactory.getLogger(MigrationTool.class);
+ }
+
+}
diff --git a/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationToolsException.java b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationToolsException.java
new file mode 100644
index 00000000000..330644e26dd
--- /dev/null
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/MigrationToolsException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+/**
+ * Exception thrown for missing migration tools.
+ *
+ * @author Vaadin Ltd
+ */
+public class MigrationToolsException extends Exception {
+
+ /**
+ * Migration tool exception constructor.
+ *
+ * @param message
+ * message on why this exception was thrown
+ */
+ public MigrationToolsException(String message) {
+ super(message);
+ }
+
+}
diff --git a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/RewriteLegacyAnnotationsStep.java b/flow-migration/src/main/java/com/vaadin/flow/migration/RewriteLegacyAnnotationsStep.java
similarity index 92%
rename from flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/RewriteLegacyAnnotationsStep.java
rename to flow-migration/src/main/java/com/vaadin/flow/migration/RewriteLegacyAnnotationsStep.java
index 6f4d73313a8..43734732d4b 100644
--- a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/migration/RewriteLegacyAnnotationsStep.java
+++ b/flow-migration/src/main/java/com/vaadin/flow/migration/RewriteLegacyAnnotationsStep.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.File;
import java.io.IOException;
@@ -36,14 +36,13 @@
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.StyleSheet;
-import com.vaadin.flow.plugin.common.ClassPathIntrospector;
-import com.vaadin.flow.plugin.common.FlowPluginFileUtils;
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
import com.vaadin.flow.shared.ApplicationConstants;
+import com.vaadin.flow.utils.FlowFileUtils;
/**
- * Rewrites {@link HtmlImport} annotation to corresponding {@link JsModule}
- * annotation.
+ * Rewrites {@link HtmlImport}/{@link StyleSheet} annotation to corresponding
+ * {@link JsModule} annotation.
*
* @author Vaadin Ltd
*
@@ -52,7 +51,6 @@ public class RewriteLegacyAnnotationsStep extends ClassPathIntrospector {
private static final String HTML_EXTENSION = ".html";
private static final String CSS_EXTENSION = ".css";
-
private final URL compiledClassesURL;
private final Collection sourceRoots;
@@ -78,27 +76,25 @@ public class RewriteLegacyAnnotationsStep extends ClassPathIntrospector {
public RewriteLegacyAnnotationsStep(File compiledClassesDir,
ClassFinder finder, Collection sourceRoots) {
super(finder);
- compiledClassesURL = FlowPluginFileUtils
- .convertToUrl(compiledClassesDir);
+ compiledClassesURL = FlowFileUtils.convertToUrl(compiledClassesDir);
this.sourceRoots = sourceRoots;
}
/**
- * Search for java files in the project and replace
- * {@link HtmlImport}/{@link StyleSheet} annotations to {@link JsModule}
- * annotation with updated value.
+ * Search for java files in the project and replace {@link HtmlImport} to
+ * {@link JsModule} annotation with updated value.
*/
public void rewrite() {
- Map, Map, Collection>> annotationsPerClass = new HashMap<>();
+ Map, Map, Collection>> annotationPerClass = new HashMap<>();
collectAnnotatedClasses(
loadClassInProjectClassLoader(HtmlImport.class.getName()),
- annotationsPerClass);
+ annotationPerClass);
collectAnnotatedClasses(
loadClassInProjectClassLoader(StyleSheet.class.getName()),
- annotationsPerClass);
+ annotationPerClass);
- annotationsPerClass.forEach(this::rewriteAnnotations);
+ annotationPerClass.forEach(this::rewriteAnnotations);
}
private void collectAnnotatedClasses(Class extends Annotation> annotation,
@@ -135,6 +131,7 @@ private Collection collectAnnotationValues(Class> clazz,
String path = invokeAnnotationMethod(annotation, "value")
.toString();
result.add(path);
+
}
return result;
}
@@ -234,8 +231,10 @@ private void rewrite(File javaFile, Class> clazz,
String beforeClassDeclaration = content.substring(0,
classDeclarationStart);
+
for (Entry, Collection> entry : annotations
.entrySet()) {
+
beforeClassDeclaration = rewrite(beforeClassDeclaration,
entry.getKey(), entry.getValue());
}
@@ -247,7 +246,7 @@ private void rewrite(File javaFile, Class> clazz,
StandardCharsets.UTF_8);
} catch (IOException e) {
getLogger().warn("Could not write source code back to file '{}'",
- javaFile, e);
+ javaFile);
}
}
@@ -255,7 +254,8 @@ private String rewrite(String content,
Class extends Annotation> annotation, Collection paths) {
String result = content;
// replace FQN first
- result = replace(annotation.getName(), result, "\\b" + annotation.getName().replace(".", "\\.") + "\\b",
+ result = replace(annotation.getName(), result,
+ "\\b" + annotation.getName().replace(".", "\\.") + "\\b",
JsModule.class.getName());
// replace annotation attached to the class with @ sign
@@ -274,8 +274,8 @@ private String rewrite(String content,
* Does the same as {@link String#replaceAll(String, String)} but caches the
* compiled pattern
*/
- private String replace(String patternKey, String content,
- String regexp, String replacement) {
+ private String replace(String patternKey, String content, String regexp,
+ String replacement) {
Pattern pattern = compiledReplacePatterns.computeIfAbsent(patternKey,
key -> Pattern.compile(regexp));
return pattern.matcher(content).replaceAll(replacement);
diff --git a/flow-migration/src/main/java/com/vaadin/flow/server/scanner/ReflectionsClassFinder.java b/flow-migration/src/main/java/com/vaadin/flow/server/scanner/ReflectionsClassFinder.java
new file mode 100644
index 00000000000..2c55ac1b544
--- /dev/null
+++ b/flow-migration/src/main/java/com/vaadin/flow/server/scanner/ReflectionsClassFinder.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.server.scanner;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Repeatable;
+import java.lang.reflect.AnnotatedElement;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.reflections.Reflections;
+import org.reflections.util.ConfigurationBuilder;
+
+import com.vaadin.flow.server.frontend.scanner.ClassFinder;
+
+/**
+ * A class finder using org.reflections.
+ */
+public class ReflectionsClassFinder implements ClassFinder {
+ private final transient ClassLoader classLoader;
+
+ private final transient Reflections reflections;
+
+ /**
+ * Constructor.
+ *
+ * @param urls
+ * the list of urls for finding classes.
+ */
+ public ReflectionsClassFinder(URL... urls) {
+ classLoader = new URLClassLoader(urls, null); // NOSONAR
+ reflections = new Reflections(
+ new ConfigurationBuilder().addClassLoader(classLoader)
+ .setExpandSuperTypes(false).addUrls(urls));
+ }
+
+ @Override
+ public Set> getAnnotatedClasses(
+ Class extends Annotation> clazz) {
+ Set> classes = new HashSet<>();
+ classes.addAll(reflections.getTypesAnnotatedWith(clazz, true));
+ classes.addAll(getAnnotatedByRepeatedAnnotation(clazz));
+ return classes;
+
+ }
+
+ private Set> getAnnotatedByRepeatedAnnotation(
+ AnnotatedElement annotationClass) {
+ Repeatable repeatableAnnotation = annotationClass
+ .getAnnotation(Repeatable.class);
+ if (repeatableAnnotation != null) {
+ return reflections.getTypesAnnotatedWith(
+ repeatableAnnotation.value(), true);
+ }
+ return Collections.emptySet();
+ }
+
+ @Override
+ public URL getResource(String name) {
+ return classLoader.getResource(name);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Class loadClass(String name)
+ throws ClassNotFoundException {
+ return (Class) classLoader.loadClass(name);
+ }
+
+ @Override
+ public Set> getSubTypesOf(Class type) {
+ return reflections.getSubTypesOf(type);
+ }
+}
diff --git a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/common/FlowPluginFileUtils.java b/flow-migration/src/main/java/com/vaadin/flow/utils/FlowFileUtils.java
similarity index 94%
rename from flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/common/FlowPluginFileUtils.java
rename to flow-migration/src/main/java/com/vaadin/flow/utils/FlowFileUtils.java
index ca433b657c8..070a21ad756 100644
--- a/flow-maven-plugin/src/main/java/com/vaadin/flow/plugin/common/FlowPluginFileUtils.java
+++ b/flow-migration/src/main/java/com/vaadin/flow/utils/FlowFileUtils.java
@@ -14,7 +14,7 @@
* the License.
*/
-package com.vaadin.flow.plugin.common;
+package com.vaadin.flow.utils;
import java.io.File;
import java.io.IOException;
@@ -31,8 +31,8 @@
* @author Vaadin Ltd
* @since 1.0.
*/
-public final class FlowPluginFileUtils {
- private FlowPluginFileUtils() {
+public final class FlowFileUtils {
+ private FlowFileUtils() {
}
/**
diff --git a/flow-maven-plugin/src/main/resources/migration/bower.json b/flow-migration/src/main/resources/migration/bower.json
similarity index 100%
rename from flow-maven-plugin/src/main/resources/migration/bower.json
rename to flow-migration/src/main/resources/migration/bower.json
diff --git a/flow-maven-plugin/src/main/resources/migration/package.json b/flow-migration/src/main/resources/migration/package.json
similarity index 100%
rename from flow-maven-plugin/src/main/resources/migration/package.json
rename to flow-migration/src/main/resources/migration/package.json
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CopyMigratedResourcesStepTest.java b/flow-migration/src/test/java/com/vaadin/flow/migration/CopyMigratedResourcesStepTest.java
similarity index 98%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CopyMigratedResourcesStepTest.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/CopyMigratedResourcesStepTest.java
index 8d2fc43de17..0a6804e966b 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CopyMigratedResourcesStepTest.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/CopyMigratedResourcesStepTest.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.File;
import java.io.IOException;
@@ -33,6 +33,8 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import com.vaadin.flow.migration.CopyMigratedResourcesStep;
+
public class CopyMigratedResourcesStepTest {
@Rule
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CopyResourcesStepTest.java b/flow-migration/src/test/java/com/vaadin/flow/migration/CopyResourcesStepTest.java
similarity index 96%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CopyResourcesStepTest.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/CopyResourcesStepTest.java
index d53621d5aef..992f7f3257d 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CopyResourcesStepTest.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/CopyResourcesStepTest.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.File;
import java.io.IOException;
@@ -48,8 +48,7 @@ public void setUp() throws IOException {
target = temporaryFolder.newFolder();
source1 = temporaryFolder.newFolder();
source2 = temporaryFolder.newFolder();
- step = new CopyResourcesStep(target,
- new String[] { source1.getPath(), source2.getPath() });
+ step = new CopyResourcesStep(target, new File[] { source1, source2 });
}
@Test
@@ -219,8 +218,7 @@ private void assertCopiedResources(Map> copied,
List list = copied.get(source.getPath());
Assert.assertEquals(path.length, list.size());
for (int i = 0; i < path.length; i++) {
- Assert.assertTrue(String.format("copied files %s did not contain expected file '%s'", list.toString(), path[i]),
- list.contains(path[i]));
+ Assert.assertTrue("Copied resources didn't contain: " + path[i], list.contains(path[i]));
}
}
}
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CreateMigrationJsonsStepTest.java b/flow-migration/src/test/java/com/vaadin/flow/migration/CreateMigrationJsonsStepTest.java
similarity index 96%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CreateMigrationJsonsStepTest.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/CreateMigrationJsonsStepTest.java
index 0bcbf425615..e216979fe56 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/CreateMigrationJsonsStepTest.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/CreateMigrationJsonsStepTest.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.File;
import java.io.IOException;
@@ -27,6 +27,8 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import com.vaadin.flow.migration.CreateMigrationJsonsStep;
+
import elemental.json.Json;
import elemental.json.JsonArray;
import elemental.json.JsonObject;
diff --git a/flow-migration/src/test/java/com/vaadin/flow/migration/MigrationTest.java b/flow-migration/src/test/java/com/vaadin/flow/migration/MigrationTest.java
new file mode 100644
index 00000000000..c4f9de75a4c
--- /dev/null
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/MigrationTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+
+import com.vaadin.flow.server.frontend.scanner.ClassFinder;
+
+public class MigrationTest {
+
+ @Rule
+ public final TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ private MigrationConfiguration configuration = Mockito.mock(MigrationConfiguration.class);
+
+ @Test(expected = IllegalArgumentException.class)
+ public void createMigration_noBaseDir_throw() {
+ new Migration(configuration);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void createMigration_baseDirIsSet_noClassFinder_throw() {
+ Mockito.when(configuration.getClassFinder())
+ .thenReturn(Mockito.mock(ClassFinder.class));
+ Mockito.when(configuration.getJavaSourceDirectories())
+ .thenReturn(new File[] { new File("bar") });
+ Mockito.when(configuration.getCompiledClassDirectory())
+ .thenReturn(new File("foobar"));
+ new Migration(configuration);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void createMigration_noJavaSourceDirs_throw() {
+ Mockito.when(configuration.getBaseDirectory())
+ .thenReturn(new File("foo"));
+ Mockito.when(configuration.getClassFinder())
+ .thenReturn(Mockito.mock(ClassFinder.class));
+ Mockito.when(configuration.getCompiledClassDirectory())
+ .thenReturn(new File("foobar"));
+ new Migration(configuration);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void createMigration_emptyJavaSourceDirs_throw() {
+ Mockito.when(configuration.getBaseDirectory())
+ .thenReturn(new File("foo"));
+ Mockito.when(configuration.getClassFinder())
+ .thenReturn(Mockito.mock(ClassFinder.class));
+ Mockito.when(configuration.getCompiledClassDirectory())
+ .thenReturn(new File("foobar"));
+ Mockito.when(configuration.getJavaSourceDirectories())
+ .thenReturn(new File[] {});
+ new Migration(configuration);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void createMigration_noCompiledClassDir_throw() {
+ Mockito.when(configuration.getBaseDirectory())
+ .thenReturn(new File("foo"));
+ Mockito.when(configuration.getClassFinder())
+ .thenReturn(Mockito.mock(ClassFinder.class));
+ Mockito.when(configuration.getJavaSourceDirectories())
+ .thenReturn(new File[] { new File("bar") });
+ new Migration(configuration);
+ }
+
+ @Test
+ public void createMigration_allRequiredConfigParamsAreSet_doesnThrow() {
+ Mockito.when(configuration.getBaseDirectory())
+ .thenReturn(new File("foo"));
+ Mockito.when(configuration.getClassFinder())
+ .thenReturn(Mockito.mock(ClassFinder.class));
+ Mockito.when(configuration.getJavaSourceDirectories())
+ .thenReturn(new File[] { new File("bar") });
+ Mockito.when(configuration.getCompiledClassDirectory())
+ .thenReturn(new File("foobar"));
+
+ new Migration(configuration);
+ }
+
+ @Test
+ public void migratePassesHappyPath()
+ throws MigrationFailureException, MigrationToolsException,
+ IOException {
+ File sourcesFolder = makeTempDirectoryStructure();
+ File targetFolder = populateTargetWithApplications();
+
+ Mockito.when(configuration.getBaseDirectory())
+ .thenReturn(Paths.get(sourcesFolder.getPath(), "foo").toFile());
+ Mockito.when(configuration.getTempMigrationFolder()).
+ thenReturn(targetFolder);
+ Mockito.when(configuration.getAnnotationRewriteStrategy())
+ .thenReturn(AnnotationsRewriteStrategy.SKIP);
+ Mockito.when(configuration.isKeepOriginalFiles()).thenReturn(true);
+ Mockito.when(configuration.getClassFinder())
+ .thenReturn(Mockito.mock(ClassFinder.class));
+ Mockito.when(configuration.getJavaSourceDirectories()).thenReturn(
+ new File[] {
+ Paths.get(sourcesFolder.getPath(), "bar").toFile() });
+ Mockito.when(configuration.getCompiledClassDirectory()).thenReturn(
+ Paths.get(sourcesFolder.getPath(), "foobar").toFile());
+
+ // Expected execution calls:
+ // 1 - npm install polymer-modulizer
+ // 2 - node {tempFolder} i -F --confid.interactive=false -S polymer#2.8.0
+ // 3 - npm i
+ // 4 - node node_modules/polymer-modulizer/bin/modulizer.js --force --out , --import-style=name
+
+ LinkedList excecuteExpectations = Stream.of(3, 7, 2, 6)
+ .collect(Collectors.toCollection(LinkedList::new));
+
+ Migration migration = new Migration(configuration) {
+ @Override
+ protected boolean executeProcess(List command,
+ String errorMsg, String successMsg, String exceptionMsg) {
+ Assert.assertEquals("Unexpected command", (int)excecuteExpectations.pop(), command.size());
+ // Skip actual execution of commands.
+ return true;
+ }
+ };
+ migration.migrate();
+ }
+
+ private File populateTargetWithApplications() throws IOException {
+ File targetFolder = temporaryFolder.newFolder();
+ targetFolder.mkdirs();
+ Path bowerBin = Files.createDirectories(
+ Paths.get(targetFolder.getAbsolutePath(), "node_modules",
+ "bower", "bin"));
+ new File(bowerBin.toFile(), "bower").createNewFile();
+
+ // Add stub node for test. !note! will not work on windows which will
+ // need to have node installed
+ Path nodeDirectory = Files.createDirectories(
+ Paths.get(targetFolder.getAbsolutePath(), "node"));
+ File node = new File(nodeDirectory.toFile(),"node");
+ node.createNewFile();
+ node.setExecutable(true);
+ FileUtils.write(node,
+ "#!/bin/sh\n[ \"$1\" = -v ] && echo 8.0.0 || sleep 1\n",
+ "UTF-8");
+
+ return targetFolder;
+ }
+
+ private File makeTempDirectoryStructure() throws IOException {
+ File folder = temporaryFolder.newFolder();
+ folder.mkdirs();
+ Files.createDirectories(
+ Paths.get(folder.getAbsolutePath(), "foo", "src", "main",
+ "webapp"));
+ Files.createDirectories(
+ Paths.get(folder.getAbsolutePath(), "bar", "src", "main",
+ "java"));
+ Files.createDirectories(Paths.get(folder.getAbsolutePath(), "foobar"));
+ return folder;
+ }
+}
diff --git a/flow-migration/src/test/java/com/vaadin/flow/migration/MigrationToolTest.java b/flow-migration/src/test/java/com/vaadin/flow/migration/MigrationToolTest.java
new file mode 100644
index 00000000000..a2c27141dcd
--- /dev/null
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/MigrationToolTest.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * 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 com.vaadin.flow.migration;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+
+import org.apache.commons.cli.ParseException;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import com.vaadin.flow.server.frontend.scanner.ClassFinder;
+
+public class MigrationToolTest {
+
+ @Rule
+ public final TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ private static class TestMigrationTool extends MigrationTool {
+
+ private MigrationConfiguration conf;
+
+ @Override
+ protected void doMigration(MigrationConfiguration configuration) {
+ conf = configuration;
+ }
+ }
+
+ private TestMigrationTool tool = new TestMigrationTool();
+
+ @Test
+ public void passRequiredArguments_configurationIsPassed()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+ }
+
+ @Test
+ public void noBaseDir_throw()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ exception.expect(CommandArgumentException.class);
+ exception.expectCause(Matchers.any(ParseException.class));
+ tool.runMigration(new String[] { "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+ }
+
+ @Test
+ public void noSourceRoot_throw()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ exception.expect(CommandArgumentException.class);
+ exception.expectCause(Matchers.any(ParseException.class));
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+ }
+
+ @Test
+ public void noClassesDir_throw()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ exception.expect(CommandArgumentException.class);
+ exception.expectCause(Matchers.any(ParseException.class));
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-d", makeSomeFolder().toURI().toURL().toExternalForm() });
+ }
+
+ @Test
+ public void noDependeciesUrls_throw()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ exception.expect(CommandArgumentException.class);
+ exception.expectCause(Matchers.any(ParseException.class));
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), });
+ }
+
+ @Test
+ public void passBadDependencyUrl_throw()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ exception.expect(CommandArgumentException.class);
+ exception.expectCause(Matchers.any(MalformedURLException.class));
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d", "foo" });
+ }
+
+ @Test
+ public void passBaseDir_baseDirIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals("fooBaseDir",
+ tool.conf.getBaseDirectory().getPath());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "--baseDir", "barBaseDir", "-src",
+ "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals("barBaseDir",
+ tool.conf.getBaseDirectory().getPath());
+ }
+
+ @Test
+ public void passCompiledClassesDir_compiledClassesDirIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ File compileClasessDir = makeSomeFolder();
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", compileClasessDir.getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(compileClasessDir,
+ tool.conf.getCompiledClassDirectory());
+
+ tool.conf = null;
+
+ compileClasessDir = makeSomeFolder();
+
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "--classesDir", compileClasessDir.getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(compileClasessDir,
+ tool.conf.getCompiledClassDirectory());
+ }
+
+ @Test
+ public void passIgnoreModulizerError_theValueIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-stopOnError", "-b", "fooBaseDir",
+ "-src", "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertFalse(tool.conf.isIgnoreModulizerErrors());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertTrue(tool.conf.isIgnoreModulizerErrors());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "-se", "-b", "fooBaseDir", "-src",
+ "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertFalse(tool.conf.isIgnoreModulizerErrors());
+ }
+
+ @Test
+ public void passKeepOriginal_theValueIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-keepOriginal", "-b", "fooBaseDir",
+ "-src", "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertTrue(tool.conf.isKeepOriginalFiles());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertFalse(tool.conf.isKeepOriginalFiles());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "-ko", "-b", "fooBaseDir", "-src",
+ "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertTrue(tool.conf.isKeepOriginalFiles());
+ }
+
+ @Test
+ public void passResourcesDirs_resourcesDirsAreConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(
+ new String[] { "-res", "fooBarRes", "-b", "fooBaseDir", "-src",
+ "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(1, tool.conf.getResourceDirectories().length);
+ Assert.assertEquals("fooBarRes",
+ tool.conf.getResourceDirectories()[0].getPath());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "--resourcesDirs", "barFooRes", "-res",
+ "baz", "-b", "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(2, tool.conf.getResourceDirectories().length);
+ Assert.assertEquals("barFooRes",
+ tool.conf.getResourceDirectories()[0].getPath());
+ Assert.assertEquals("baz",
+ tool.conf.getResourceDirectories()[1].getPath());
+ }
+
+ @Test
+ public void dontPassResourcesDir_resourcesDirIsNotConfigured_noException()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertNull(tool.conf.getResourceDirectories());
+ }
+
+ @Test
+ public void passMigrationDir_migrationDirIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-md", "migrationFoo", "-b",
+ "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals("migrationFoo",
+ tool.conf.getTempMigrationFolder().getPath());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "--migrationDir", "fooMigration", "-b",
+ "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals("fooMigration",
+ tool.conf.getTempMigrationFolder().getPath());
+
+ }
+
+ @Test
+ public void dontPassMigrationDir_MigrationDirIsNotConfigured_noException()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertNull(tool.conf.getTempMigrationFolder());
+ }
+
+ @Test
+ public void passTargetDir_migrationTargetIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-t", "targetFoo", "-b", "fooBaseDir",
+ "-src", "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals("targetFoo",
+ tool.conf.getTargetDirectory().getPath());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "--targetDir", "fooTarget", "-b",
+ "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals("fooTarget",
+ tool.conf.getTargetDirectory().getPath());
+
+ }
+
+ @Test
+ public void dontPassTargetnDir_MigrationDirIsNotConfigured_noException()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertNull(tool.conf.getTargetDirectory());
+ }
+
+ @Test
+ public void passJavaSourceDirs_sourceDirsAreConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(1, tool.conf.getJavaSourceDirectories().length);
+ Assert.assertEquals("barSrcs",
+ tool.conf.getJavaSourceDirectories()[0].getPath());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "--sourceDirs", "fooSrc", "-b",
+ "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(2, tool.conf.getJavaSourceDirectories().length);
+ Assert.assertEquals("fooSrc",
+ tool.conf.getJavaSourceDirectories()[0].getPath());
+ Assert.assertEquals("barSrcs",
+ tool.conf.getJavaSourceDirectories()[1].getPath());
+ }
+
+ @Test
+ public void passDpeUrls_classFinderIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException,
+ URISyntaxException {
+ File depDir = makeSomeFolder();
+ File file = new File(depDir, "foo");
+ file.createNewFile();
+
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-d",
+ depDir.toURI().toURL().toExternalForm() });
+
+ ClassFinder classFinder = tool.conf.getClassFinder();
+ Assert.assertNotNull(classFinder);
+
+ Assert.assertEquals(file,
+ new File(classFinder.getResource("foo").toURI()));
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "-b", "fooBaseDir", "-src", "barSrcs",
+ "-c", makeSomeFolder().getPath(), "-depUrls",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertNotNull(tool.conf.getClassFinder());
+
+ }
+
+ @Test
+ public void passAnnotationRewriteStrategy_strategyIsConfigured()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-ars", "SKIP", "-t", "targetFoo",
+ "-b", "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(AnnotationsRewriteStrategy.SKIP,
+ tool.conf.getAnnotationRewriteStrategy());
+
+ tool.conf = null;
+
+ tool.runMigration(new String[] { "--annRewrite", "SKIP_ON_ERROR", "-t",
+ "targetFoo", "-b", "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(AnnotationsRewriteStrategy.SKIP_ON_ERROR,
+ tool.conf.getAnnotationRewriteStrategy());
+
+ }
+
+ @Test
+ public void passBadAnnotationRewriteStrategy_throw()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ exception.expect(CommandArgumentException.class);
+ exception.expectCause(Matchers.any(IllegalArgumentException.class));
+ tool.runMigration(new String[] { "-ars", "bar", "-t", "targetFoo", "-b",
+ "fooBaseDir", "-src", "barSrcs", "-c",
+ makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+ }
+
+ @Test
+ public void dontPassAnnotationRewriteStrategy_defaultStrategyIsInConfiguration()
+ throws CommandArgumentException, MigrationToolsException,
+ MigrationFailureException, IOException {
+ tool.runMigration(new String[] { "-t", "targetFoo", "-b", "fooBaseDir",
+ "-src", "barSrcs", "-c", makeSomeFolder().getPath(), "-d",
+ makeSomeFolder().toURI().toURL().toExternalForm() });
+
+ Assert.assertEquals(AnnotationsRewriteStrategy.ALWAYS,
+ tool.conf.getAnnotationRewriteStrategy());
+ }
+
+ private File makeSomeFolder() throws IOException {
+ File folder = temporaryFolder.newFolder();
+ folder.mkdirs();
+ return folder;
+ }
+}
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/RewriteLegacyAnnotationsStepTest.java b/flow-migration/src/test/java/com/vaadin/flow/migration/RewriteLegacyAnnotationsStepTest.java
similarity index 94%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/RewriteLegacyAnnotationsStepTest.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/RewriteLegacyAnnotationsStepTest.java
index 1528bc050ef..24d47828cfe 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/RewriteLegacyAnnotationsStepTest.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/RewriteLegacyAnnotationsStepTest.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration;
+package com.vaadin.flow.migration;
import java.io.File;
import java.io.IOException;
@@ -37,14 +37,14 @@
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.dependency.StyleSheet;
-import com.vaadin.flow.plugin.migration.samplecode.ClassUnitWithNonPublicClass;
-import com.vaadin.flow.plugin.migration.samplecode.Component1;
-import com.vaadin.flow.plugin.migration.samplecode.Component2;
-import com.vaadin.flow.plugin.migration.samplecode.Component3;
-import com.vaadin.flow.plugin.migration.samplecode.EnclosingClassWithNestedClass;
-import com.vaadin.flow.plugin.migration.samplecode.EnclosingClassWithNestedClass.NestedComponent;
-import com.vaadin.flow.plugin.migration.samplecode.ShouldNotBeRewritten;
-import com.vaadin.flow.plugin.migration.samplecode.StyledComponent;
+import com.vaadin.flow.migration.samplecode.ClassUnitWithNonPublicClass;
+import com.vaadin.flow.migration.samplecode.Component1;
+import com.vaadin.flow.migration.samplecode.Component2;
+import com.vaadin.flow.migration.samplecode.Component3;
+import com.vaadin.flow.migration.samplecode.EnclosingClassWithNestedClass;
+import com.vaadin.flow.migration.samplecode.EnclosingClassWithNestedClass.NestedComponent;
+import com.vaadin.flow.migration.samplecode.ShouldNotBeRewritten;
+import com.vaadin.flow.migration.samplecode.StyledComponent;
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
public class RewriteLegacyAnnotationsStepTest {
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/ClassUnitWithNonPublicClass.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/ClassUnitWithNonPublicClass.java
similarity index 89%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/ClassUnitWithNonPublicClass.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/ClassUnitWithNonPublicClass.java
index ec09154d6d3..f96b64012f1 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/ClassUnitWithNonPublicClass.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/ClassUnitWithNonPublicClass.java
@@ -13,14 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import java.io.Serializable;
import java.util.List;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.dependency.HtmlImport;
-import com.vaadin.flow.plugin.migration.samplecode.NonPublicClassWithNestedClass.NestedClassInsideNonPublicClass;
+import com.vaadin.flow.migration.samplecode.NonPublicClassWithNestedClass.NestedClassInsideNonPublicClass;
public class ClassUnitWithNonPublicClass {
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component1.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component1.java
similarity index 95%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component1.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component1.java
index 7b3329e9cb0..dcb322f4ece 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component1.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component1.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import java.io.Serializable;
import java.util.List;
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component2.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component2.java
similarity index 93%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component2.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component2.java
index 4b40df69eeb..4740781aea7 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component2.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component2.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.dependency.HtmlImport;
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component3.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component3.java
similarity index 93%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component3.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component3.java
index cf0ab628fab..7eac3807547 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/Component3.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/Component3.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.dependency.HtmlImport;
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/EnclosingClassWithNestedClass.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/EnclosingClassWithNestedClass.java
similarity index 94%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/EnclosingClassWithNestedClass.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/EnclosingClassWithNestedClass.java
index f1e8627a64c..7e2f60f2e42 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/EnclosingClassWithNestedClass.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/EnclosingClassWithNestedClass.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import java.io.Serializable;
import java.util.List;
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/GenericComponent.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/GenericComponent.java
similarity index 92%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/GenericComponent.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/GenericComponent.java
index bdf884a04ff..f71d8ea3c95 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/GenericComponent.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/GenericComponent.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import com.vaadin.flow.component.Component;
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/ShouldNotBeRewritten.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/ShouldNotBeRewritten.java
similarity index 86%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/ShouldNotBeRewritten.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/ShouldNotBeRewritten.java
index b0a41fc28f3..278e5fe786b 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/ShouldNotBeRewritten.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/ShouldNotBeRewritten.java
@@ -13,10 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import com.vaadin.flow.component.Component;
-import com.vaadin.flow.plugin.migration.samplecode.ShouldNotBeRewritten.MyStyleSheet;
+import com.vaadin.flow.migration.samplecode.ShouldNotBeRewritten.MyStyleSheet;
@MyStyleSheet
public class ShouldNotBeRewritten extends Component {
diff --git a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/StyledComponent.java b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/StyledComponent.java
similarity index 95%
rename from flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/StyledComponent.java
rename to flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/StyledComponent.java
index a8f785c6254..16dc6fe6237 100644
--- a/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/migration/samplecode/StyledComponent.java
+++ b/flow-migration/src/test/java/com/vaadin/flow/migration/samplecode/StyledComponent.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.flow.plugin.migration.samplecode;
+package com.vaadin.flow.migration.samplecode;
import java.io.Serializable;
import java.util.List;
diff --git a/pom.xml b/pom.xml
index e050e1bc852..b3abec0b932 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,7 @@
flow-server-production-mode
flow-server-compatibility-mode
flow-components-parent
+ flow-migration
flow-maven-plugin
flow-test-generic
flow-bom