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

net.adamcin.blunderbuss.mojo.IndexBuilder Maven / Gradle / Ivy

/*
 * Copyright 2020 Mark Adamcin
 *
 * 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 net.adamcin.blunderbuss.mojo;

import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.CompletableEmitter;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.shared.transfer.artifact.deploy.ArtifactDeployerException;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Clock;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class IndexBuilder {
	private final Path indexDir;

	private final Artifact indexBuilderMetadataArtifact;

	private final Artifact indexBuilderArtifact;

	private final Context context;

	private volatile boolean dirty;

	public IndexBuilder(
			@NotNull final Path indexDir,
			@NotNull final Artifact indexBuilderArtifact,
			@NotNull final Artifact indexBuilderMetadataArtifact,
			@NotNull final Context context) {
		this.indexDir = indexDir;
		this.indexBuilderArtifact = indexBuilderArtifact;
		this.indexBuilderMetadataArtifact = indexBuilderMetadataArtifact;
		this.context = context;
	}

	public static Single fromIndex(
			@NotNull final Index index,
			@NotNull final Context context) {
		return Single.create(emitter -> {
			final Artifact indexArtifact = index.getIndexArtifact();
			final Artifact indexMetadataArtifact = index.getIndexMetadataArtifact();
			final String groupId = indexArtifact.getGroupId();
			final String artifactId = indexArtifact.getArtifactId();
			final String version = DateTimeFormatter.ofPattern("'v'uuuuMMddHHmmss").format(ZonedDateTime.now(Clock.systemUTC()));
			final Path tempDir = context.getTempDir();
			final File pomFile = tempDir.resolve(artifactId + "-" + version + ".pom").toFile();
			final File jarFile = tempDir.resolve(artifactId + "-" + version + ".jar").toFile();
			final Path indexDir = tempDir.resolve(artifactId + "-" + version + ".dir");
			final Model model = new Model();
			model.setModelVersion("4.0.0");
			model.setGroupId(groupId);
			model.setArtifactId(artifactId);
			model.setVersion(version);
			final MavenXpp3Writer writer = new MavenXpp3Writer();
			try (OutputStream outputStream = new FileOutputStream(pomFile)) {
				writer.write(outputStream, model);
			}
			if (indexArtifact.getFile() == null || !indexArtifact.getFile().isFile()) {
				Files.createDirectories(indexDir);
			} else {
				JarUtils.extractJarFile(indexArtifact.getFile(), indexDir).blockingAwait();
			}
			final Artifact indexBuilderArtifact = new DefaultArtifact(groupId, artifactId, version, indexArtifact.getScope(),
					indexArtifact.getType(), indexArtifact.getClassifier(), indexArtifact.getArtifactHandler());
			indexBuilderArtifact.setFile(jarFile);
			final Artifact indexBuilderMetadataArtifact = new DefaultArtifact(groupId, artifactId, version, indexMetadataArtifact.getScope(),
					indexMetadataArtifact.getType(), indexMetadataArtifact.getClassifier(), indexMetadataArtifact.getArtifactHandler());
			indexBuilderMetadataArtifact.setFile(pomFile);
			emitter.onSuccess(new IndexBuilder(indexDir, indexBuilderArtifact, indexBuilderMetadataArtifact, context));
		});
	}

	public List getArtifacts() {
		return Arrays.asList(indexBuilderMetadataArtifact, indexBuilderArtifact);
	}

	Consumer onNextArtifactGroup(@NotNull final CompletableEmitter emitter) {
		return artifactGroup -> {
			final Set indexed = new HashSet<>(artifactGroup.getIndexed());
			final Map deployables = artifactGroup.getDeployables().entrySet().stream()
					.filter(entry -> !indexed.contains(entry.getKey()))
					.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
			boolean doSave = !deployables.isEmpty();
			try {
				if (!deployables.isEmpty()) {
					context.deploy(deployables.values());
					indexed.addAll(deployables.keySet());
				}
			} catch (ArtifactDeployerException deployAllError) {
				for (Map.Entry deployableEntry : deployables.entrySet()) {
					try {
						context.resolve(deployableEntry.getValue());
						indexed.add(deployableEntry.getKey());
					} catch (ArtifactResolverException resolveOneError) {
						try {
							context.deploy(deployableEntry.getValue());
							indexed.add(deployableEntry.getKey());
						} catch (ArtifactDeployerException deployOneError) {
							doSave = false;
							break;
						}
					}
				}
			}
			if (doSave) {
				Path indexFile = indexDir.resolve(artifactGroup.getIndexFileRelPath());
				if (!Files.isDirectory(indexFile.getParent())) {
					Files.createDirectories(indexFile.getParent());
				}
				Files.write(indexFile, indexed.stream().map(Path::toString).collect(Collectors.toList()), StandardCharsets.UTF_8);
				dirty = true;
			}
		};
	}

	Completable buildIndexFrom(@NotNull final Flowable artifactGroups) {
		return Completable.create(emitter -> {
			emitter.setDisposable(
					artifactGroups
							.observeOn(Schedulers.io())
							.subscribe(this.onNextArtifactGroup(emitter), emitter::onError, emitter::onComplete));
		});
	}

	Completable finishAndUpload(final boolean noUpload) {
		return JarUtils.createJarFile(indexBuilderArtifact.getFile(), indexDir)
				.andThen(Completable.create(emitter -> {
					if (dirty && !noUpload) {
						context.deploy(this.getArtifacts());
					}
					emitter.onComplete();
				}));
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy