All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dynatrace.buildtools.graalnative.DynatraceAgentDirectory Maven / Gradle / Ivy

The newest version!
package com.dynatrace.buildtools.graalnative;

import com.dynatrace.buildtools.graalnative.shared.Constants;
import com.dynatrace.buildtools.graalnative.shared.DownloadException;
import com.dynatrace.buildtools.graalnative.shared.DynatraceAgentDirectoryUtils;
import com.dynatrace.buildtools.graalnative.shared.DynatraceRestApi;
import org.apache.maven.project.MavenProject;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public final class DynatraceAgentDirectory {

	public static File setup(final String agentDir,
							 final String agentZip,
							 final AgentDownload agentDownload,
							 final MavenProject project,
							 final MavenProject topLevelProject,
							 final DynatraceLogger logger) throws ConfigurationException, IOException, DownloadException {

		if (areMultiplePropertiesPresent(agentDir, agentZip, agentDownload.isPresent() ? agentDownload : null)) {
			throw new ConfigurationException("""
				multiple agent properties are present: only one of
				  * 'agentDir',
				  * 'agentZip', or
				  * 'agentDownload'
				can be configured.
				"""
			);
		}

		final File preparedAgentDir;

		if (agentDir != null && !agentDir.isEmpty()) {
			final File configuredAgentDir = new File(agentDir);

			// to be compatible with older plugin versions which required to specify the `graalnative` directory
			if (configuredAgentDir.getAbsolutePath().endsWith("graalnative")) {
				preparedAgentDir = configuredAgentDir.getParentFile();
			} else {
				preparedAgentDir = configuredAgentDir;
			}
		} else if (agentZip != null && !agentZip.isEmpty()) {
			final File dynatraceAgentZip = new File(agentZip);
			final File extractDir = new File(project.getBuild().getDirectory(), "tmp");
			preparedAgentDir = extractDir;
			if (!preparedAgentDir.exists()) {
				extractZip(dynatraceAgentZip.toPath(), extractDir.toPath(), logger);
			}
		} else if (agentDownload.isPresent()) {
			final String environmentUrl = agentDownload.getEnvironmentUrl();
			if (environmentUrl == null || environmentUrl.isEmpty()) {
				throw new ConfigurationException("agentDownload: 'environmentUrl' has to be configured.");
			}

			final String apiToken = agentDownload.getApiToken();
			if (apiToken == null || apiToken.isEmpty()) {
				throw new ConfigurationException("agentDownload: 'apiToken' has to be configured.");
			}

			// TODO: verify checksum of downloaded agent?

			final String agentVersion = getOneAgentInstallerVersion(agentDownload.getAgentVersion(), environmentUrl, apiToken, logger);
			logger.info("Using OneAgent installer version '%s'", agentVersion);

			final File agentDownloadCacheDir = new File(topLevelProject.getBasedir(), Constants.AGENT_DOWNLOAD_CACHE_DIRECTORY_NAME);
			final File agentInstallerDir = new File(agentDownloadCacheDir, DynatraceAgentDirectoryUtils.getOneAgentInstallerCacheDirName(agentVersion));

			if (!agentInstallerDir.exists()) {
				logger.info("OneAgent installer for version '%s' doesn't exist", agentVersion);

				final File downloadDir = new File(topLevelProject.getBuild().getDirectory(), "tmp");
				final String installerZipName = DynatraceAgentDirectoryUtils.getOneAgentInstallerZipName(agentVersion);
				final File installerZip = new File(downloadDir, installerZipName);

				if (!installerZip.exists()) {
					logger.info("Downloading OneAgent installer for version '%s'", agentVersion);

					DynatraceRestApi.downloadOneAgentInstaller(
						environmentUrl,
						apiToken,
						agentVersion,
						downloadDir.toPath(),
						installerZipName
					);
				}

				extractZip(
					installerZip.toPath(),
					agentInstallerDir.toPath(),
					logger
				);
			}

			preparedAgentDir = agentInstallerDir;
		} else {
			final DynatraceProperties dynatraceProperties = new DynatraceProperties(project.getProperties());

			final Optional agentDirProperty = dynatraceProperties.getAgentDir();
			if (agentDirProperty.isPresent()) {
				throw new ConfigurationException("""
					property '%s' is no longer supported; please use
						
							%s
						
					For more information, go to https://docs.dynatrace.com/docs/setup-and-configuration/technology-support/application-software/java/graalvm-native-image#maven
					""",
					DynatraceProperties.DYNATRACE_AGENT_DIR_PROPERTY_NAME,
					agentDirProperty
				);
			}

			final Optional agentZipProperty = dynatraceProperties.getAgentZip();
			if (agentZipProperty.isPresent()) {
				throw new ConfigurationException("""
					property '%s' is no longer supported; please use
						
							%s
						
					For more information, go to https://docs.dynatrace.com/docs/setup-and-configuration/technology-support/application-software/java/graalvm-native-image#maven
					""",
					DynatraceProperties.DYNATRACE_AGENT_ZIP_PROPERTY_NAME,
					agentZipProperty
				);
			}

			throw new ConfigurationException("""
				missing agent property: either
				  * 'agentDir',
				  * 'agentZip', or
				  * 'agentDownload' with 'environmentUrl' and 'apiToken'
				has to be configured.
				"""
			);
		}

		DynatraceAgentDirectoryUtils.checkAgentDirStructure(preparedAgentDir);
		logger.info("Prepared Dynatrace agent directory: '%s'", preparedAgentDir);

		return preparedAgentDir;
	}

	private static void extractZip(final Path archive, final Path destination, final DynatraceLogger logger) throws IOException {
		try (final ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(archive))) {
			for (ZipEntry zipEntry = zipInputStream.getNextEntry(); zipEntry != null; zipEntry = zipInputStream.getNextEntry()) {
				final Optional sanitizedPath = sanitizePath(zipEntry, destination);
				if (sanitizedPath.isEmpty()) {
					logger.warn("invalid zip entry '%s' in archive '%s'", zipEntry.getName(), archive);
					continue;
				}

				final Path zipEntryPath = sanitizedPath.get();
				if (zipEntry.isDirectory()) {
					Files.createDirectories(zipEntryPath);
				} else {
					final Path zipEntryParentPath = zipEntryPath.getParent();
					if (zipEntryParentPath != null && !Files.exists(zipEntryParentPath)) {
						Files.createDirectories(zipEntryParentPath);
					}
					Files.copy(zipInputStream, zipEntryPath, StandardCopyOption.REPLACE_EXISTING);
				}

				zipInputStream.closeEntry();
			}
		}
	}

	private static String getOneAgentInstallerVersion(final String configuredAgentVersion,
													  final String environmentUrl,
													  final String apiToken,
													  final DynatraceLogger logger) throws DownloadException {
		if (configuredAgentVersion != null && !configuredAgentVersion.isEmpty()) {
			return configuredAgentVersion;
		}

		logger.info("No OneAgent installer version configured -> using latest");
		return DynatraceRestApi.getLatestOneAgentInstallerVersion(environmentUrl, apiToken);
	}

	private static Optional sanitizePath(final ZipEntry entry, final Path destination) {
		final Path normalizedPath = destination.resolve(entry.getName()).normalize();

		if (!normalizedPath.startsWith(destination)) {
			return Optional.empty();
		}

		return Optional.of(normalizedPath);
	}

	private static boolean areMultiplePropertiesPresent(final Object... properties) {
		final long numPresentProperties = Arrays.stream(properties)
			.filter(Objects::nonNull)
			.count();

		return numPresentProperties > 1;
	}

	private DynatraceAgentDirectory() {}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy