diff --git a/cli/src/main/java/com/devonfw/tools/ide/process/EnvironmentContext.java b/cli/src/main/java/com/devonfw/tools/ide/process/EnvironmentContext.java new file mode 100644 index 000000000..8f9de3dd0 --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/process/EnvironmentContext.java @@ -0,0 +1,19 @@ +package com.devonfw.tools.ide.process; + +/** + * Interface for the environment context relatable in the case a tool needs to be run with an environment variable. + */ +public interface EnvironmentContext { + + /** + * Sets or overrides the specified environment variable only for the planned process execution. Please note that the environment variables are initialized + * when the {@link EnvironmentContext} is created. This method explicitly set an additional or overrides an existing environment and will have effect for each + * process execution invoked from this {@link EnvironmentContext} instance. + * + * @param key the name of the environment variable (E.g. "PATH"). + * @param value the value of the environment variable. + * @return this {@link EnvironmentContext} for fluent API calls. + */ + EnvironmentContext withEnvVar(String key, String value); + +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContext.java b/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContext.java index 982e9678b..7a2679250 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContext.java +++ b/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContext.java @@ -7,7 +7,7 @@ /** * Wrapper for {@link ProcessBuilder} to simplify its usage and avoid common mistakes and pitfalls. */ -public interface ProcessContext { +public interface ProcessContext extends EnvironmentContext { /** * @param handling the desired {@link ProcessErrorHandling}. diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/CustomToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/CustomToolCommandlet.java index 68d073843..e93f08017 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/CustomToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/CustomToolCommandlet.java @@ -1,6 +1,7 @@ package com.devonfw.tools.ide.tool; import com.devonfw.tools.ide.context.IdeContext; +import com.devonfw.tools.ide.process.EnvironmentContext; import com.devonfw.tools.ide.repo.CustomTool; import com.devonfw.tools.ide.version.VersionIdentifier; @@ -17,21 +18,29 @@ public CustomToolCommandlet(IdeContext context, CustomTool customTool) { this.customTool = customTool; } + @Override + public ToolInstallation installTool(VersionIdentifier version, EnvironmentContext environmentContext) { + + return installTool(version, this.customTool.getEdition(), environmentContext); + } + @Override public ToolInstallation installTool(VersionIdentifier version) { - return installTool(version, this.customTool.getEdition()); + return installTool(version, this.customTool.getEdition(), null); } @Override - public ToolInstallation installTool(VersionIdentifier version, String edition) { + public ToolInstallation installTool(VersionIdentifier version, String edition, EnvironmentContext environmentContext) { - return installTool(version, edition, this.context.getCustomToolRepository()); + return installTool(version, edition, this.context.getCustomToolRepository(), environmentContext); } + @Override public VersionIdentifier getConfiguredVersion() { return this.customTool.getVersion(); } + } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/Dependency.java b/cli/src/main/java/com/devonfw/tools/ide/tool/Dependency.java index 118b0e34d..0e6d4fa5a 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/Dependency.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/Dependency.java @@ -1,22 +1,19 @@ package com.devonfw.tools.ide.tool; -import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Stream; import com.devonfw.tools.ide.context.IdeContext; -import com.devonfw.tools.ide.json.mapping.JsonMapping; +import com.devonfw.tools.ide.url.model.file.UrlDependencyFile; import com.devonfw.tools.ide.url.model.file.dependencyJson.DependencyInfo; +import com.devonfw.tools.ide.url.model.folder.UrlEdition; import com.devonfw.tools.ide.version.VersionIdentifier; import com.devonfw.tools.ide.version.VersionRange; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; /** * Class to represent the functionality of installing the dependencies when a tool is being installed. @@ -27,10 +24,6 @@ public class Dependency { private final String tool; - private static final String DEPENDENCY_FILENAME = "dependencies.json"; - - private static final ObjectMapper MAPPER = JsonMapping.create(); - /** * The constructor. * @@ -43,16 +36,9 @@ public Dependency(IdeContext context, String tool) { this.tool = tool; } - /** - * Method to get the dependency json file path - * - * @param toolEdition the edition of the tool. - * @return the {@link Path} of the dependency.json file - */ - public Path getDependencyJsonPath(String toolEdition) { + private UrlEdition getDependencyUrlEdition(String toolEdition) { - Path toolPath = this.context.getUrlsPath().resolve(this.tool).resolve(toolEdition); - return toolPath.resolve(DEPENDENCY_FILENAME); + return this.context.getUrls().getEdition(this.tool, toolEdition); } /** @@ -64,16 +50,12 @@ public Path getDependencyJsonPath(String toolEdition) { */ public List readJson(VersionIdentifier version, String toolEdition) { - Path dependencyJsonPath = getDependencyJsonPath(toolEdition); - - try (BufferedReader reader = Files.newBufferedReader(dependencyJsonPath)) { - TypeReference>> typeRef = new TypeReference<>() { - }; - Map> dependencyJson = MAPPER.readValue(reader, typeRef); - return findDependenciesFromJson(dependencyJson, version); - } catch (IOException e) { - throw new RuntimeException(e); + UrlDependencyFile urlDependencyFile = getDependencyUrlEdition(toolEdition).getDependencyFile(); + if (!urlDependencyFile.isDependencyMapNull()) { + Map> dependencyMap = urlDependencyFile.getDependencyMap(); + return urlDependencyFile.findDependenciesFromJson(dependencyMap, version); } + return null; } /** @@ -121,16 +103,5 @@ public Path versionExistsInRepository(Path dependencyRepositoryPath, VersionRang return Path.of(""); } - private List findDependenciesFromJson(Map> dependencies, VersionIdentifier toolVersionToCheck) { - - for (Map.Entry> map : dependencies.entrySet()) { - VersionRange foundToolVersionRange = map.getKey(); - - if (foundToolVersionRange.contains(toolVersionToCheck)) { - return map.getValue(); - } - } - return null; - } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java index be2f97e30..556e628d8 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java @@ -10,6 +10,7 @@ import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.log.IdeLogLevel; +import com.devonfw.tools.ide.process.EnvironmentContext; import com.devonfw.tools.ide.process.ProcessContext; import com.devonfw.tools.ide.process.ProcessErrorHandling; import com.devonfw.tools.ide.repo.ToolRepository; @@ -106,6 +107,12 @@ protected boolean isExtract() { @Override protected boolean doInstall(boolean silent) { + return doInstall(null, silent); + } + + @Override + protected boolean doInstall(EnvironmentContext environmentContext, boolean silent) { + Path binaryPath = this.context.getPath().findBinary(Path.of(getBinaryName())); // if force mode is enabled, go through with the installation even if the tool is already installed if (binaryPath != null && Files.exists(binaryPath) && !this.context.isForceMode()) { diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java index ab62797ab..b9ab281ec 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java @@ -4,8 +4,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Set; import com.devonfw.tools.ide.common.Tag; @@ -13,9 +13,7 @@ import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.io.FileCopyMode; import com.devonfw.tools.ide.log.IdeLogLevel; -import com.devonfw.tools.ide.process.ProcessContext; -import com.devonfw.tools.ide.process.ProcessErrorHandling; -import com.devonfw.tools.ide.process.ProcessMode; +import com.devonfw.tools.ide.process.EnvironmentContext; import com.devonfw.tools.ide.repo.ToolRepository; import com.devonfw.tools.ide.step.Step; import com.devonfw.tools.ide.url.model.file.dependencyJson.DependencyInfo; @@ -26,10 +24,6 @@ */ public abstract class LocalToolCommandlet extends ToolCommandlet { - protected HashMap dependenciesEnvVariableNames = null; - - protected HashMap dependenciesEnvVariablePaths = new HashMap<>(); - private final Dependency dependency = new Dependency(this.context, this.tool); /** @@ -68,13 +62,25 @@ public Path getToolBinPath() { @Override protected boolean doInstall(boolean silent) { + return doInstall(null, silent); + } + + @Override + protected boolean doInstall(EnvironmentContext environmentContext, boolean silent) { + VersionIdentifier configuredVersion = getConfiguredVersion(); // get installed version before installInRepo actually may install the software VersionIdentifier installedVersion = getInstalledVersion(); Step step = this.context.newStep(silent, "Install " + this.tool, configuredVersion); try { + ToolInstallation installation; + if (environmentContext == null) { + installation = installTool(configuredVersion); + } else { + installation = installTool(configuredVersion, environmentContext); + } // install configured version of our tool in the software repository if not already installed - ToolInstallation installation = installTool(configuredVersion); + // check if we already have this version installed (linked) locally in IDE_HOME/software VersionIdentifier resolvedVersion = installation.resolvedVersion(); if (resolvedVersion.equals(installedVersion) && !installation.newInstallation()) { @@ -95,6 +101,7 @@ protected boolean doInstall(boolean silent) { } this.context.getPath().setPath(this.tool, installation.binDir()); postInstall(); + postInstall(); if (installedVersion == null) { step.success("Successfully installed {} in version {}", this.tool, resolvedVersion); } else { @@ -121,6 +128,19 @@ protected boolean isIgnoreSoftwareRepo() { return false; } + /** + * Performs the installation of the {@link #getName() tool} together with the environment context, managed by this + * {@link com.devonfw.tools.ide.commandlet.Commandlet}. + * + * @param environmentContext the {@link EnvironmentContext} of the tool + * @param version the {@link VersionIdentifier} requested to be installed. May also be a {@link VersionIdentifier#isPattern() version pattern}. + * @return the {@link ToolInstallation} matching the given {@code version}. + */ + public ToolInstallation installTool(VersionIdentifier version, EnvironmentContext environmentContext) { + + return installTool(version, getConfiguredEdition(), environmentContext); + } + /** * Performs the installation of the {@link #getName() tool} managed by this {@link com.devonfw.tools.ide.commandlet.Commandlet}. * @@ -132,6 +152,20 @@ public ToolInstallation installTool(VersionIdentifier version) { return installTool(version, getConfiguredEdition()); } + /** + * Performs the installation of the {@link #getName() tool} together with the environment context managed by this + * {@link com.devonfw.tools.ide.commandlet.Commandlet}. + * + * @param environmentContext the {@link EnvironmentContext} of the tool + * @param version the {@link VersionIdentifier} requested to be installed. May also be a {@link VersionIdentifier#isPattern() version pattern}. + * @param edition the specific edition to install. + * @return the {@link ToolInstallation} matching the given {@code version}. + */ + public ToolInstallation installTool(VersionIdentifier version, String edition, EnvironmentContext environmentContext) { + + return installTool(version, edition, this.context.getDefaultToolRepository(), environmentContext); + } + /** * Performs the installation of the {@link #getName() tool} managed by this {@link com.devonfw.tools.ide.commandlet.Commandlet}. * @@ -141,7 +175,7 @@ public ToolInstallation installTool(VersionIdentifier version) { */ public ToolInstallation installTool(VersionIdentifier version, String edition) { - return installTool(version, edition, this.context.getDefaultToolRepository()); + return installTool(version, edition, this.context.getDefaultToolRepository(), null); } /** @@ -150,16 +184,16 @@ public ToolInstallation installTool(VersionIdentifier version, String edition) { * @param version the {@link VersionIdentifier} requested to be installed. May also be a {@link VersionIdentifier#isPattern() version pattern}. * @param edition the specific edition to install. * @param toolRepository the {@link ToolRepository} to use. + * @param environmentContext the {@link EnvironmentContext} of the tool * @return the {@link ToolInstallation} matching the given {@code version}. */ - public ToolInstallation installTool(VersionIdentifier version, String edition, ToolRepository toolRepository) { + public ToolInstallation installTool(VersionIdentifier version, String edition, ToolRepository toolRepository, EnvironmentContext environmentContext) { VersionIdentifier resolvedVersion = toolRepository.resolveVersion(this.tool, edition, version); - if (Files.exists(this.dependency.getDependencyJsonPath(getConfiguredEdition()))) { - installDependencies(resolvedVersion); - } else { - this.context.trace("No Dependencies file found"); + DependencyInfo dependencyInfo = readDependencies(resolvedVersion); + if (dependencyInfo != null) { + installDependencies(dependencyInfo, environmentContext); } Path toolPath; @@ -323,127 +357,75 @@ private ToolInstallation createToolInstallation(Path rootDir, VersionIdentifier return createToolInstallation(rootDir, resolvedVersion, toolVersionFile, false); } - @Override - public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, String... args) { - - Path binaryPath; - Path toolPath = Path.of(getBinaryName()); - if (toolVersion == null) { - install(true); - binaryPath = toolPath; - } else { - throw new UnsupportedOperationException("Not yet implemented!"); - } - - if (Files.exists(this.dependency.getDependencyJsonPath(getConfiguredEdition()))) { - setDependencyRepository(getInstalledVersion()); - } else { - this.context.trace("No Dependencies file found"); - } - - ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING).executable(binaryPath).addArgs(args); - - for (String key : this.dependenciesEnvVariablePaths.keySet()) { + /** + * Method to set the environment variable for the dependency of the tool. + * + * @param envContext the {@link EnvironmentContext} of the tool. + * @param dependencyPath the {@link Path} of the dependency. + */ + private void setEnvironment(EnvironmentContext envContext, Path dependencyPath) { - String dependencyPath = this.dependenciesEnvVariablePaths.get(key); - pc = pc.withEnvVar(key, dependencyPath); + if (envContext != null) { + String pathVariable = this.tool.toUpperCase(Locale.ROOT) + "_HOME"; + envContext.withEnvVar(pathVariable, dependencyPath.toString()); } - - pc.run(processMode); } - private void installDependencies(VersionIdentifier version) { + private DependencyInfo readDependencies(VersionIdentifier toolVersion) { - List dependencies = this.dependency.readJson(version, getConfiguredEdition()); + List dependencies = this.dependency.readJson(toolVersion, getConfiguredEdition()); - for (DependencyInfo dependencyInfo : dependencies) { - - String dependencyName = dependencyInfo.getTool(); - VersionIdentifier dependencyVersionToInstall = this.dependency.findDependencyVersionToInstall(dependencyInfo); - if (dependencyVersionToInstall == null) { - continue; - } - - ToolCommandlet dependencyTool = this.context.getCommandletManager().getToolCommandlet(dependencyName); - Path dependencyRepository = getDependencySoftwareRepository(dependencyName, - dependencyTool.getConfiguredEdition()); - - if (!Files.exists(dependencyRepository)) { - installDependencyInRepo(dependencyName, dependencyTool, dependencyVersionToInstall); - } else { - Path versionExistingInRepository = this.dependency.versionExistsInRepository(dependencyRepository, dependencyInfo.getVersionRange()); - if (versionExistingInRepository.equals(Path.of(""))) { - installDependencyInRepo(dependencyName, dependencyTool, dependencyVersionToInstall); - } else { - this.context.info("Necessary version of the dependency {} is already installed in repository", dependencyName); + if (dependencies != null) { + for (DependencyInfo dependencyInfo : dependencies) { + VersionIdentifier dependencyVersionToInstall = this.dependency.findDependencyVersionToInstall(dependencyInfo); + if (dependencyVersionToInstall == null) { + continue; } + + return dependencyInfo; } } + return null; } - private void installDependencyInRepo(String dependencyName, ToolCommandlet dependencyTool, VersionIdentifier dependencyVersionToInstall) { - - this.context.info("The version {} of the dependency {} is being installed", dependencyVersionToInstall, dependencyName); - LocalToolCommandlet dependencyLocal = (LocalToolCommandlet) dependencyTool; - dependencyLocal.installTool(dependencyVersionToInstall); - this.context.info("The version {} of the dependency {} was successfully installed", dependencyVersionToInstall, dependencyName); - } - - protected void setDependencyRepository(VersionIdentifier version) { + private void installDependencies(DependencyInfo dependencyInfo, EnvironmentContext ec) { - List dependencies = this.dependency.readJson(version, getConfiguredEdition()); + String dependencyName = dependencyInfo.getTool(); + LocalToolCommandlet dependencyTool = (LocalToolCommandlet) this.context.getCommandletManager().getToolCommandlet(dependencyName); + VersionIdentifier dependencyVersionToInstall = this.dependency.findDependencyVersionToInstall(dependencyInfo); - for (DependencyInfo dependencyInfo : dependencies) { - String dependencyName = dependencyInfo.getTool(); - VersionIdentifier dependencyVersionToInstall = this.dependency.findDependencyVersionToInstall(dependencyInfo); - if (dependencyVersionToInstall == null) { - continue; - } + Path dependencyRepository = getDependencySoftwareRepository(dependencyName, dependencyTool.getConfiguredEdition()); - ToolCommandlet dependencyTool = this.context.getCommandletManager().getToolCommandlet(dependencyName); - Path dependencyRepository = getDependencySoftwareRepository(dependencyName, - dependencyTool.getConfiguredEdition()); - Path versionExistingInRepository = this.dependency.versionExistsInRepository(dependencyRepository, - dependencyInfo.getVersionRange()); - Path dependencyPath; + if (!Files.exists(dependencyRepository)) { + installDependencyInRepo(dependencyName, dependencyTool, dependencyVersionToInstall, ec); + dependencyTool.setEnvironment(ec, dependencyRepository.resolve(dependencyVersionToInstall.toString())); + } else { + Path versionExistingInRepository = this.dependency.versionExistsInRepository(dependencyRepository, dependencyInfo.getVersionRange()); + boolean versionExistingInRepositoryIsEmpty = versionExistingInRepository.equals(Path.of("")); - if (versionExistingInRepository.equals(Path.of(""))) { - dependencyPath = dependencyRepository.resolve(dependencyVersionToInstall.toString()); + if (versionExistingInRepositoryIsEmpty) { + installDependencyInRepo(dependencyName, dependencyTool, dependencyVersionToInstall, ec); + dependencyTool.setEnvironment(ec, dependencyRepository.resolve(dependencyVersionToInstall.toString())); } else { - dependencyPath = dependencyRepository.resolve(versionExistingInRepository); + dependencyTool.setEnvironment(ec, versionExistingInRepository); + this.context.info("Necessary version of the dependency {} is already installed in repository", dependencyName); } - setDependencyEnvironmentPath(getDependencyEnvironmentName(dependencyName), dependencyPath); } } - private void setDependencyEnvironmentPath(String dependencyEnvironmentName, Path dependencyPath) { - - this.dependenciesEnvVariablePaths.put(dependencyEnvironmentName, dependencyPath.toString()); - - } - - /** - * Method to return the list of the environment variable name for the dependencies. If necessary, it should be overridden in the specific tool - * - * @return the {@link HashMap} with the dependency name mapped to the env variable, for example ( java: JAVA_HOME ) - */ + private void installDependencyInRepo(String dependencyName, ToolCommandlet dependencyTool, VersionIdentifier dependencyVersionToInstall, + EnvironmentContext ec) { - protected HashMap listOfDependencyEnvVariableNames() { - - return this.dependenciesEnvVariableNames; - } - - private String getDependencyEnvironmentName(String dependencyName) { - - HashMap envVariableName = listOfDependencyEnvVariableNames(); - - if (envVariableName != null) { - return envVariableName.get(dependencyName); + if (dependencyTool instanceof LocalToolCommandlet) { + this.context.info("The version {} of the dependency {} is being installed", dependencyVersionToInstall, dependencyName); + ((LocalToolCommandlet) dependencyTool).installTool(dependencyVersionToInstall, ec); + this.context.info("The version {} of the dependency {} was successfully installed", dependencyVersionToInstall, dependencyName); + } else { + this.context.error("Cannot install dependency {} since the responsible commandlet does fit", dependencyName); } - - return dependencyName.toUpperCase() + "_HOME"; } + private Path getDependencySoftwareRepository(String dependencyName, String dependencyEdition) { String defaultToolRepositoryId = this.context.getDefaultToolRepository().getId(); diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java index fdd0810d8..a81186b2a 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java @@ -13,6 +13,7 @@ import com.devonfw.tools.ide.environment.EnvironmentVariablesFiles; import com.devonfw.tools.ide.nls.NlsBundle; import com.devonfw.tools.ide.os.MacOsHelper; +import com.devonfw.tools.ide.process.EnvironmentContext; import com.devonfw.tools.ide.process.ProcessContext; import com.devonfw.tools.ide.process.ProcessErrorHandling; import com.devonfw.tools.ide.process.ProcessMode; @@ -94,23 +95,43 @@ public void run() { * @param processMode see {@link ProcessMode} * @param toolVersion the explicit version (pattern) to run. Typically {@code null} to ensure the configured version is installed and use that one. * Otherwise, the specified version will be installed in the software repository without touching and IDE installation and used to run. + * @param existsEnvironmentContext the {@link Boolean} that checks if an environment context exits. If true, then the process context is passed to the + * installation method as an argument. * @param args the command-line arguments to run the tool. */ - public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, String... args) { + public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, boolean existsEnvironmentContext, String... args) { Path binaryPath; - Path toolPath = Path.of(getBinaryName()); - if (toolVersion == null) { - install(true); - binaryPath = toolPath; + binaryPath = Path.of(getBinaryName()); + ProcessContext pc; + + if (existsEnvironmentContext) { + pc = getProcessContext(binaryPath, args); + install(pc, true); } else { - throw new UnsupportedOperationException("Not yet implemented!"); + install(true); + pc = getProcessContext(binaryPath, args); } - ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING).executable(binaryPath).addArgs(args); pc.run(processMode); } + private ProcessContext getProcessContext(Path binaryPath, String... args) { + + return this.context.newProcess().errorHandling(ProcessErrorHandling.THROW).executable(binaryPath).addArgs(args); + } + + /** + * @param processMode see {@link ProcessMode} + * @param toolVersion the explicit {@link VersionIdentifier} of the tool to run. + * @param args the command-line arguments to run the tool. + * @see ToolCommandlet#runTool(ProcessMode, VersionIdentifier, boolean, String...) + */ + public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, String... args) { + + runTool(processMode, toolVersion, false, args); + } + /** * @param toolVersion the explicit {@link VersionIdentifier} of the tool to run. * @param args the command-line arguments to run the tool. @@ -159,6 +180,18 @@ public VersionIdentifier getConfiguredVersion() { return this.context.getVariables().getToolVersion(getName()); } + /** + * Method to be called for {@link #install(boolean)} from dependent {@link com.devonfw.tools.ide.commandlet.Commandlet}s. Additionally, contains the + * environmentContext of the tool + * + * @param environmentContext - the environment context that can be used for the dependencies + * @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and nothing has changed. + */ + public boolean install(EnvironmentContext environmentContext) { + + return install(environmentContext, true); + } + /** * Method to be called for {@link #install(boolean)} from dependent {@link com.devonfw.tools.ide.commandlet.Commandlet}s. * @@ -169,6 +202,19 @@ public boolean install() { return install(true); } + /** + * Performs the installation of the {@link #getName() tool} managed by this {@link com.devonfw.tools.ide.commandlet.Commandlet}. Additionally, contains the + * environmentContext of the tool + * + * @param environmentContext - the environment context that can be used for the dependencies + * @param silent - {@code true} if called recursively to suppress verbose logging, {@code false} otherwise. + * @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and nothing has changed. + */ + public boolean install(EnvironmentContext environmentContext, boolean silent) { + + return doInstall(environmentContext, silent); + } + /** * Performs the installation of the {@link #getName() tool} managed by this {@link com.devonfw.tools.ide.commandlet.Commandlet}. * @@ -180,6 +226,16 @@ public boolean install(boolean silent) { return doInstall(silent); } + + /** + * Installs or updates the managed {@link #getName() tool}. Additionally works with the environment context of the tool. + * + * @param environmentContext - the environment context that can be used for the dependencies + * @param silent - {@code true} if called recursively to suppress verbose logging, {@code false} otherwise. + * @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and nothing has changed. + */ + protected abstract boolean doInstall(EnvironmentContext environmentContext, boolean silent); + /** * Installs or updates the managed {@link #getName() tool}. * diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/Tomcat.java b/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/Tomcat.java index 4f32c0756..be8a2e061 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/Tomcat.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/Tomcat.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.HashMap; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -15,17 +14,18 @@ import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; -import com.devonfw.tools.ide.environment.EnvironmentVariables; -import com.devonfw.tools.ide.environment.EnvironmentVariablesType; -import com.devonfw.tools.ide.property.EnumProperty; +import com.devonfw.tools.ide.process.ProcessContext; +import com.devonfw.tools.ide.process.ProcessErrorHandling; +import com.devonfw.tools.ide.process.ProcessMode; import com.devonfw.tools.ide.tool.LocalToolCommandlet; +import com.devonfw.tools.ide.tool.ToolCommandlet; +import com.devonfw.tools.ide.version.VersionIdentifier; +/** + * {@link ToolCommandlet} for tomcat. + */ public class Tomcat extends LocalToolCommandlet { - private final HashMap dependenciesEnvVariableNames = new HashMap<>(); - - public final EnumProperty command; - /** * The constructor. * @@ -34,63 +34,46 @@ public class Tomcat extends LocalToolCommandlet { public Tomcat(IdeContext context) { super(context, "tomcat", Set.of(Tag.JAVA)); - this.command = add(new EnumProperty<>("", true, "command", TomcatCommand.class)); - // add(this.arguments); + add(this.arguments); } @Override - public void postInstall() { - - super.postInstall(); - - EnvironmentVariables variables = this.context.getVariables(); - EnvironmentVariables typeVariables = variables.getByType(EnvironmentVariablesType.CONF); + public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, String... args) { - typeVariables.set("CATALINA_HOME", getToolPath().toString(), true); - typeVariables.save(); + runTool(processMode, toolVersion, true, args); } @Override - protected void initProperties() { + public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, boolean existsEnvironmentContext, String... args) { - // Empty on purpose, because no initial properties are added to the tool - } + Path binaryPath; + binaryPath = Path.of(getBinaryName()); - @Override - public void run() { + if (existsEnvironmentContext) { + ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING).executable(binaryPath).addArgs(args); - Path toolPath = getToolPath(); - if (!toolPath.toFile().exists()) { - super.install(true); - } + if (toolVersion == null) { + install(pc, true); + } else { + throw new UnsupportedOperationException("Not yet implemented!"); + } - TomcatCommand command = this.command.getValue(); - - switch (command) { - case START: - printTomcatPort(); - this.arguments.setValueAsString("start", this.context); - super.run(); - break; - case STOP: - this.arguments.setValueAsString("stop", this.context); - super.run(); - break; - default: + pc.withEnvVar("CATALINA_HOME", getToolPath().toString()); + pc.run(processMode); } + printTomcatPort(); } @Override - protected String getBinaryName() { + protected void initProperties() { - return "catalina.sh"; + // Empty on purpose, because no initial properties are added to the tool } @Override - protected HashMap listOfDependencyEnvVariableNames() { + public String getBinaryName() { - this.dependenciesEnvVariableNames.put("java", "JRE_HOME"); - return this.dependenciesEnvVariableNames; + return "catalina.sh"; } private void printTomcatPort() { diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/TomcatCommand.java b/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/TomcatCommand.java deleted file mode 100644 index d3cdffcc2..000000000 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/tomcat/TomcatCommand.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.devonfw.tools.ide.tool.tomcat; - -public enum TomcatCommand { - START, STOP -} diff --git a/cli/src/main/java/com/devonfw/tools/ide/url/model/file/UrlDependencyFile.java b/cli/src/main/java/com/devonfw/tools/ide/url/model/file/UrlDependencyFile.java new file mode 100644 index 000000000..a89de2afb --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/url/model/file/UrlDependencyFile.java @@ -0,0 +1,96 @@ +package com.devonfw.tools.ide.url.model.file; + +import java.io.BufferedReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.devonfw.tools.ide.json.mapping.JsonMapping; +import com.devonfw.tools.ide.url.model.file.dependencyJson.DependencyInfo; +import com.devonfw.tools.ide.url.model.folder.UrlEdition; +import com.devonfw.tools.ide.version.VersionIdentifier; +import com.devonfw.tools.ide.version.VersionRange; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * {@link UrlFile} for the "dependency.json" file. + */ +public class UrlDependencyFile extends AbstractUrlFile { + + public static final String DEPENDENCY_JSON = "dependencies.json"; + + private static final ObjectMapper MAPPER = JsonMapping.create(); + + private Map> dependencyMap; + + /** + * The constructor. + * + * @param parent the {@link #getParent() parent folder}. + */ + public UrlDependencyFile(UrlEdition parent) { + + super(parent, DEPENDENCY_JSON); + } + + /** + * @return the content of the dependency map of the dependency.json file + */ + public Map> getDependencyMap() { + + return this.dependencyMap; + } + + /** + * Finds the dependency from Json file. + * + * @param dependencyMap the Map of the VersionRange and the List of DependencyInfo + * @param toolVersionToCheck the version of the tool to check + * @return The List of the DependencyInfo found in the Json file + */ + public List findDependenciesFromJson(Map> dependencyMap, VersionIdentifier toolVersionToCheck) { + + for (Map.Entry> map : dependencyMap.entrySet()) { + + VersionRange foundToolVersionRange = map.getKey(); + + if (foundToolVersionRange.contains(toolVersionToCheck)) { + return map.getValue(); + } + } + return null; + } + + /** + * Checks if the dependency map is null + */ + public boolean isDependencyMapNull() { + return dependencyMap == null; + } + + @Override + protected void doLoad() { + + Path path = getPath(); + if (Files.exists(path)) { + try (BufferedReader reader = Files.newBufferedReader(path)) { + + TypeReference>> typeRef = new TypeReference<>() { + }; + this.dependencyMap = MAPPER.readValue(reader, typeRef); + } catch (Exception e) { + throw new IllegalStateException("Failed to load " + path, e); + } + } else { + this.dependencyMap = new HashMap<>(); + } + } + + @Override + protected void doSave() { + + } +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/url/model/folder/UrlEdition.java b/cli/src/main/java/com/devonfw/tools/ide/url/model/folder/UrlEdition.java index 91c72c53d..86eb0573b 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/url/model/folder/UrlEdition.java +++ b/cli/src/main/java/com/devonfw/tools/ide/url/model/folder/UrlEdition.java @@ -1,6 +1,7 @@ package com.devonfw.tools.ide.url.model.folder; import com.devonfw.tools.ide.url.model.AbstractUrlFolderWithParent; +import com.devonfw.tools.ide.url.model.file.UrlDependencyFile; import com.devonfw.tools.ide.url.model.file.UrlSecurityFile; /** @@ -11,6 +12,8 @@ public class UrlEdition extends AbstractUrlFolderWithParent private UrlSecurityFile securityFile; + private UrlDependencyFile dependencyFile; + /** * The constructor. * @@ -35,7 +38,7 @@ protected UrlVersion newChild(String name) { /** * @return the {@link UrlSecurityFile} of this {@link UrlEdition}. Will be lazily initialized on the first call of this method. If the file exists, it will be - * loaded, otherwise it will be empty and only created on save if data was added. + * loaded, otherwise it will be empty and only created on save if data was added. */ public UrlSecurityFile getSecurityFile() { @@ -46,6 +49,19 @@ public UrlSecurityFile getSecurityFile() { return this.securityFile; } + /** + * @return the {@link UrlDependencyFile} of this {@link UrlEdition}. Will be lazily initialized on the first call of this method. If the file exists, it will + * be loaded, otherwise it will be empty and only created on save if data was added. + */ + public UrlDependencyFile getDependencyFile() { + + if (this.dependencyFile == null) { + this.dependencyFile = new UrlDependencyFile(this); + this.dependencyFile.load(false); + } + return dependencyFile; + } + @Override public void save() { diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/graalvm/GraalVmTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/graalvm/GraalVmTest.java index a31e093de..b7eb71719 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/graalvm/GraalVmTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/graalvm/GraalVmTest.java @@ -27,4 +27,4 @@ public void testGraalVmInstallInDirectoryExtra() { assertThat(context.getSoftwareExtraPath().resolve("graalvm/bin/HelloWorld.txt")).exists(); assertThat(context.getSoftwareExtraPath().resolve("graalvm/.ide.software.version")).exists().hasContent("22.3.3"); } -} \ No newline at end of file +} diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/tomcat/TomcatTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/tomcat/TomcatTest.java index 7bb057a19..5925bfe87 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/tomcat/TomcatTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/tomcat/TomcatTest.java @@ -4,6 +4,7 @@ import com.devonfw.tools.ide.context.AbstractIdeContextTest; import com.devonfw.tools.ide.context.IdeTestContext; +import com.devonfw.tools.ide.process.ProcessMode; public class TomcatTest extends AbstractIdeContextTest { @@ -16,12 +17,8 @@ public void testTomcat() { IdeTestContext context = newContext(PROJECT_TOMCAT); Tomcat tomcatCommandlet = new Tomcat(context); - // install - tomcatCommandlet.install(); - // run - tomcatCommandlet.command.setValue(TomcatCommand.START); - tomcatCommandlet.run(); + tomcatCommandlet.runTool(ProcessMode.DEFAULT, null, true); // assert checkInstallation(context); @@ -33,19 +30,17 @@ private void checkDependencyInstallation(IdeTestContext context) { assertThat(context).logAtInfo().hasEntries("The version 17.0.10_7 of the dependency java is being installed", "The version 17.0.10_7 of the dependency java was successfully installed"); - } private void checkRunningTomcat(IdeTestContext context) { - assertThat(context).logAtInfo().hasEntries("Tomcat is running at localhost on the following port (default 8080):", - "8080"); + assertThat(context).logAtInfo().hasEntries("Tomcat is running at localhost on the following port (default 8080):", "8080"); } private void checkInstallation(IdeTestContext context) { - assertThat(context.getSoftwarePath().resolve("tomcat/bin/startup.bat")).exists().hasContent("@echo test for windows"); - assertThat(context.getSoftwarePath().resolve("tomcat/bin/startup.sh")).exists().hasContent("#!/bin/bash\n" + "echo \"Test for linux and Mac\""); + assertThat(context.getSoftwarePath().resolve("tomcat/bin/catalina.bat")).exists().hasContent("@echo test for windows"); + assertThat(context.getSoftwarePath().resolve("tomcat/bin/catalina.sh")).exists().hasContent("#!/bin/bash\n" + "echo \"Test for linux and Mac\""); assertThat(context.getSoftwarePath().resolve("tomcat/.ide.software.version")).exists().hasContent("10.1.14"); assertThat(context).logAtSuccess().hasMessage("Successfully installed tomcat in version 10.1.14"); diff --git a/cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/startup.bat b/cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/catalina.bat similarity index 100% rename from cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/startup.bat rename to cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/catalina.bat diff --git a/cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/startup.sh b/cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/catalina.sh similarity index 100% rename from cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/startup.sh rename to cli/src/test/resources/ide-projects/tomcat/repository/tomcat/tomcat/default/bin/catalina.sh