Skip to content

Commit

Permalink
#36: Tool Commandlet for tomcat (#250)
Browse files Browse the repository at this point in the history
  • Loading branch information
aBega2000 authored Jul 3, 2024
1 parent 625b5c5 commit 97734be
Show file tree
Hide file tree
Showing 20 changed files with 589 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.devonfw.tools.ide.tool.quarkus.Quarkus;
import com.devonfw.tools.ide.tool.sonar.Sonar;
import com.devonfw.tools.ide.tool.terraform.Terraform;
import com.devonfw.tools.ide.tool.tomcat.Tomcat;
import com.devonfw.tools.ide.tool.vscode.Vscode;

import java.util.Collection;
Expand Down Expand Up @@ -92,6 +93,7 @@ public CommandletManagerImpl(IdeContext context) {
add(new Quarkus(context));
add(new Kotlinc(context));
add(new KotlincNative(context));
add(new Tomcat(context));
add(new Vscode(context));
add(new Azure(context));
add(new Aws(context));
Expand Down
136 changes: 136 additions & 0 deletions cli/src/main/java/com/devonfw/tools/ide/tool/Dependency.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.devonfw.tools.ide.tool;

import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.json.mapping.JsonMapping;
import com.devonfw.tools.ide.url.model.file.dependencyJson.DependencyInfo;
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;

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;

/**
* Class to represent the functionality of installing the dependencies when a tool is being installed.
*/
public class Dependency {

private final IdeContext context;

private final String tool;

private static final String DEPENDENCY_FILENAME = "dependencies.json";

private static final ObjectMapper MAPPER = JsonMapping.create();

/**
* The constructor.
*
* @param context the {@link IdeContext}.
* @param tool the tool of the context
*/
public Dependency(IdeContext context, String tool) {

this.context = context;
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) {

Path toolPath = this.context.getUrlsPath().resolve(tool).resolve(toolEdition);
return toolPath.resolve(DEPENDENCY_FILENAME);
}

/**
* Method to read the Json file
*
* @param version of the main tool to be installed.
* @param toolEdition of the main tool, so that the correct folder can be checked to find the dependency json file
* @return the {@link List} of {@link DependencyInfo} to be installed
*/
public List<DependencyInfo> readJson(VersionIdentifier version, String toolEdition) {

Path dependencyJsonPath = getDependencyJsonPath(toolEdition);

try (BufferedReader reader = Files.newBufferedReader(dependencyJsonPath)) {
TypeReference<HashMap<VersionRange, List<DependencyInfo>>> typeRef = new TypeReference<>() {
};
Map<VersionRange, List<DependencyInfo>> dependencyJson = MAPPER.readValue(reader, typeRef);
return findDependenciesFromJson(dependencyJson, version);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/**
* Method to search the List of versions available in the ide and find the right version to install
*
* @param dependencyFound the {@link DependencyInfo} of the dependency that was found that needs to be installed
* @return {@link VersionIdentifier} of the dependency that is to be installed
*/
public VersionIdentifier findDependencyVersionToInstall(DependencyInfo dependencyFound) {

String dependencyEdition = this.context.getVariables().getToolEdition(dependencyFound.getTool());

List<VersionIdentifier> versions = this.context.getUrls().getSortedVersions(dependencyFound.getTool(), dependencyEdition);

for (VersionIdentifier vi : versions) {
if (dependencyFound.getVersionRange().contains(vi)) {
return vi;
}
}
return null;
}

/**
* Method to check if in the repository of the dependency there is a Version greater or equal to the version range to be installed, and to return the path of
* this version if it exists
*
* @param dependencyRepositoryPath the {@link Path} of the dependency repository
* @param dependencyVersionRangeFound the {@link VersionRange} of the dependency version to be installed
* @return the {@link Path} of such version if it exists in repository already, an empty Path
*/
public Path versionExistsInRepository(Path dependencyRepositoryPath, VersionRange dependencyVersionRangeFound) {

try (Stream<Path> versions = Files.list(dependencyRepositoryPath)) {
Iterator<Path> versionsIterator = versions.iterator();
while (versionsIterator.hasNext()) {
VersionIdentifier versionFound = VersionIdentifier.of(versionsIterator.next().getFileName().toString());
if (dependencyVersionRangeFound.contains(versionFound)) {
assert versionFound != null;
return dependencyRepositoryPath.resolve(versionFound.toString());
}
}
} catch (IOException e) {
throw new IllegalStateException("Failed to iterate through " + dependencyRepositoryPath, e);
}
return Path.of("");
}

private List<DependencyInfo> findDependenciesFromJson(Map<VersionRange, List<DependencyInfo>> dependencies, VersionIdentifier toolVersionToCheck) {

for (Map.Entry<VersionRange, List<DependencyInfo>> map : dependencies.entrySet()) {

VersionRange foundToolVersionRange = map.getKey();

if (foundToolVersionRange.contains(toolVersionToCheck)) {
return map.getValue();
}
}
return null;
}
}
145 changes: 145 additions & 0 deletions cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,33 @@
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.repo.ToolRepository;
import com.devonfw.tools.ide.step.Step;
import com.devonfw.tools.ide.url.model.file.dependencyJson.DependencyInfo;
import com.devonfw.tools.ide.version.VersionIdentifier;

import java.io.IOException;
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.Set;

/**
* {@link ToolCommandlet} that is installed locally into the IDE.
*/
public abstract class LocalToolCommandlet extends ToolCommandlet {

protected HashMap<String, String> dependenciesEnvVariableNames = null;

protected HashMap<String, String> dependenciesEnvVariablePaths = new HashMap<>();

private final Dependency dependency = new Dependency(this.context, this.tool);

/**
* The constructor.
*
Expand Down Expand Up @@ -133,6 +145,13 @@ public ToolInstallation installInRepo(VersionIdentifier version, String edition)
public ToolInstallation installInRepo(VersionIdentifier version, String edition, ToolRepository toolRepository) {

VersionIdentifier resolvedVersion = toolRepository.resolveVersion(this.tool, edition, version);

if (Files.exists(this.dependency.getDependencyJsonPath(getEdition()))) {
installDependencies(resolvedVersion);
} else {
this.context.trace("No Dependencies file found");
}

Path toolPath = this.context.getSoftwareRepositoryPath().resolve(toolRepository.getId()).resolve(this.tool).resolve(edition)
.resolve(resolvedVersion.toString());
Path toolVersionFile = toolPath.resolve(IdeContext.FILE_SOFTWARE_VERSION);
Expand Down Expand Up @@ -283,4 +302,130 @@ 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(getEdition()))) {
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()) {

String dependencyPath = this.dependenciesEnvVariablePaths.get(key);
pc = pc.withEnvVar(key, dependencyPath);
}

pc.run(processMode);
}

private void installDependencies(VersionIdentifier version) {

List<DependencyInfo> dependencies = this.dependency.readJson(version, getEdition());

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.getEdition());

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);
}
}
}
}

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.installInRepo(dependencyVersionToInstall);
this.context.info("The version {} of the dependency {} was successfully installed", dependencyVersionToInstall, dependencyName);
}

protected void setDependencyRepository(VersionIdentifier version) {

List<DependencyInfo> dependencies = this.dependency.readJson(version, getEdition());

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.getEdition());
Path versionExistingInRepository = this.dependency.versionExistsInRepository(dependencyRepository, dependencyInfo.getVersionRange());
Path dependencyPath;

if (versionExistingInRepository.equals(Path.of(""))) {
dependencyPath = dependencyRepository.resolve(dependencyVersionToInstall.toString());
} else {
dependencyPath = dependencyRepository.resolve(versionExistingInRepository);
}
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 )
*/

protected HashMap<String, String> listOfDependencyEnvVariableNames() {

return dependenciesEnvVariableNames;
}

private String getDependencyEnvironmentName(String dependencyName) {

HashMap<String, String> envVariableName = listOfDependencyEnvVariableNames();

if (envVariableName != null) {
return envVariableName.get(dependencyName);
}

return dependencyName.toUpperCase() + "_HOME";
}

private Path getDependencySoftwareRepository(String dependencyName, String dependencyEdition) {

String defaultToolRepositoryId = this.context.getDefaultToolRepository().getId();
Path dependencyRepository = this.context.getSoftwareRepositoryPath().resolve(defaultToolRepositoryId).resolve(dependencyName).resolve(dependencyEdition);

return dependencyRepository;
}

}
Loading

0 comments on commit 97734be

Please sign in to comment.