Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
</dependency>

<!-- Resolver -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@

import static java.util.Objects.requireNonNull;

import eu.maveniverse.maven.njord.shared.impl.repository.DefaultArtifactStoreManager;
import eu.maveniverse.maven.njord.shared.store.ArtifactStoreManager;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.function.Function;
import org.eclipse.aether.RepositorySystemSession;

public final class NjordUtils {
private NjordUtils() {}

public static boolean lazyInitConfig(
RepositorySystemSession repositorySystemSession, Supplier<Config> configSupplier) {
RepositorySystemSession repositorySystemSession,
Config config,
Function<Config, ArtifactStoreManager> artifactStoreManagerFactory) {
requireNonNull(repositorySystemSession, "repositorySystemSession");
requireNonNull(configSupplier, "configSupplier");
Config config = mayGetConfig(repositorySystemSession).orElse(null);
requireNonNull(config, "config");
Config oldConfig = mayGetConfig(repositorySystemSession).orElse(null);
boolean result = false;
if (config == null) {
config = configSupplier.get();
if (oldConfig == null) {
setConfig(repositorySystemSession, config);
if (config.enabled()) {
setArtifactStoreManager(repositorySystemSession, new DefaultArtifactStoreManager(config));
setArtifactStoreManager(repositorySystemSession, artifactStoreManagerFactory.apply(config));
result = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package eu.maveniverse.maven.njord.shared.impl.repository;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;

import eu.maveniverse.maven.njord.shared.impl.DirectoryLocker;
import eu.maveniverse.maven.njord.shared.store.ArtifactStore;
Expand All @@ -14,34 +15,42 @@
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.metadata.DefaultMetadata;
import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;

public class DefaultArtifactStore implements ArtifactStore {
private final String name;
private final Instant created;
private final RepositoryMode repositoryMode;
private final boolean allowRedeploy;
private final List<ChecksumAlgorithmFactory> checksumAlgorithmFactories;
private final Path basedir;

private final AtomicBoolean closed;

/**
* Creates instance out for existing store.
*/
public DefaultArtifactStore(Path basedir) throws IOException {
public DefaultArtifactStore(Path basedir, ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector)
throws IOException {
DirectoryLocker.INSTANCE.lockDirectory(basedir, false);
Properties properties = new Properties();
Path meta = basedir.resolve(".meta").resolve("repository.properties");
Expand All @@ -55,14 +64,27 @@ public DefaultArtifactStore(Path basedir) throws IOException {
this.repositoryMode = requireNonNull(
RepositoryMode.valueOf(properties.getProperty("repositoryMode")), "RepositoryMode not provided");
this.allowRedeploy = Boolean.parseBoolean(properties.getProperty("allowRedeploy"));
if (properties.containsKey("checksumAlgorithms")) {
this.checksumAlgorithmFactories = checksumAlgorithmFactorySelector.selectList(Arrays.stream(
properties.getProperty("checksumAlgorithmFactories").split(","))
.filter(s -> !s.trim().isEmpty())
.collect(toList()));
} else {
this.checksumAlgorithmFactories = null;
}
this.basedir = requireNonNull(basedir);
this.closed = new AtomicBoolean(false);
}

/**
* Creates and inits brand-new store.
*/
public DefaultArtifactStore(String name, RepositoryMode repositoryMode, boolean allowRedeploy, Path basedir)
public DefaultArtifactStore(
String name,
RepositoryMode repositoryMode,
boolean allowRedeploy,
List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
Path basedir)
throws IOException {
Files.createDirectories(basedir); // if brand new, we must create it first
DirectoryLocker.INSTANCE.lockDirectory(basedir, true);
Expand All @@ -71,6 +93,7 @@ public DefaultArtifactStore(String name, RepositoryMode repositoryMode, boolean
this.created = Instant.now();
this.repositoryMode = requireNonNull(repositoryMode);
this.allowRedeploy = allowRedeploy;
this.checksumAlgorithmFactories = checksumAlgorithmFactories;
this.basedir = requireNonNull(basedir);
this.closed = new AtomicBoolean(false);

Expand All @@ -79,6 +102,13 @@ public DefaultArtifactStore(String name, RepositoryMode repositoryMode, boolean
properties.put("created", Long.toString(created.toEpochMilli()));
properties.put("repositoryMode", repositoryMode.name());
properties.put("allowRedeploy", Boolean.toString(allowRedeploy));
if (checksumAlgorithmFactories != null) {
properties.put(
"checksumAlgorithmFactories",
checksumAlgorithmFactories.stream()
.map(ChecksumAlgorithmFactory::getName)
.collect(Collectors.joining(",")));
}
Path meta = basedir.resolve(".meta").resolve("repository.properties");
Files.createDirectories(meta.getParent());
try (OutputStream out = Files.newOutputStream(meta, StandardOpenOption.CREATE_NEW)) {
Expand Down Expand Up @@ -114,6 +144,12 @@ public boolean allowRedeploy() {
return allowRedeploy;
}

@Override
public Optional<List<ChecksumAlgorithmFactory>> checksumAlgorithmFactories() {
checkClosed();
return Optional.ofNullable(checksumAlgorithmFactories);
}

@Override
public Collection<Artifact> artifacts() {
checkClosed();
Expand Down Expand Up @@ -148,6 +184,21 @@ public Path basedir() {
return basedir;
}

@Override
public RepositorySystemSession storeRepositorySession(RepositorySystemSession session) {
checkClosed();
requireNonNull(session);
DefaultRepositorySystemSession session2 = new DefaultRepositorySystemSession(session);
if (checksumAlgorithmFactories().isPresent()) {
session2.setUserProperty(
"aether.checksums.algorithms",
checksumAlgorithmFactories().orElseThrow().stream()
.map(ChecksumAlgorithmFactory::getName)
.collect(Collectors.joining(",")));
}
return session2;
}

@Override
public RemoteRepository storeRemoteRepository() {
return new RemoteRepository.Builder(name(), "default", "file://" + basedir()).build();
Expand All @@ -169,12 +220,13 @@ public Operation put(Collection<Artifact> artifacts, Collection<Metadata> metada
throw new IllegalArgumentException("Passed in metadata must have set existing file");
}
// check RepositoryMode (snapshot vs release)
boolean expected = repositoryMode != RepositoryMode.RELEASE;
boolean expected = repositoryMode() != RepositoryMode.RELEASE;
if (artifacts.stream().anyMatch(a -> a.isSnapshot() != expected)) {
throw new IllegalArgumentException("Passed in artifacts repository policy mismatch");
}
// check DeployMode (already exists)
if (!allowRedeploy && artifacts.stream().anyMatch(a -> Files.isRegularFile(basedir.resolve(artifactPath(a))))) {
if (!allowRedeploy()
&& artifacts.stream().anyMatch(a -> Files.isRegularFile(basedir.resolve(artifactPath(a))))) {
throw new IllegalArgumentException("Redeployment is forbidden (artifact already exists)");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;

public class DefaultArtifactStoreManager implements ArtifactStoreManager {
private final Config config;
private final ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector;

private final AtomicBoolean closed;
private final Map<String, ArtifactStoreTemplate> templates;

public DefaultArtifactStoreManager(Config config) {
public DefaultArtifactStoreManager(
Config config, ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector) {
this.config = requireNonNull(config);
this.checksumAlgorithmFactorySelector = requireNonNull(checksumAlgorithmFactorySelector);

this.closed = new AtomicBoolean(false);
this.templates = new HashMap<>();
templates.put(ArtifactStoreTemplate.RELEASE.name(), ArtifactStoreTemplate.RELEASE);
Expand Down Expand Up @@ -56,7 +62,7 @@ public Optional<ArtifactStore> selectArtifactStore(String name) throws IOExcepti
checkClosed();
Path artifactStoreBasedir = config.basedir().resolve(name);
if (Files.isDirectory(artifactStoreBasedir)) {
return Optional.of(new DefaultArtifactStore(artifactStoreBasedir));
return Optional.of(new DefaultArtifactStore(artifactStoreBasedir, checksumAlgorithmFactorySelector));
}
return Optional.empty();
}
Expand All @@ -81,6 +87,10 @@ public ArtifactStore createArtifactStore(ArtifactStoreTemplate template) throws
name,
template.repositoryMode(),
template.allowRedeploy(),
template.checksumAlgorithmFactories().isPresent()
? checksumAlgorithmFactorySelector.selectList(
template.checksumAlgorithmFactories().orElseThrow())
: null,
config.basedir().resolve(name));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package eu.maveniverse.maven.njord.shared.impl.repository;

import static java.util.Objects.requireNonNull;

import eu.maveniverse.maven.njord.shared.Config;
import eu.maveniverse.maven.njord.shared.store.ArtifactStoreManager;
import eu.maveniverse.maven.njord.shared.store.ArtifactStoreManagerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;

@Singleton
@Named
public class DefaultArtifactStoreManagerFactory implements ArtifactStoreManagerFactory {
private final ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector;

@Inject
public DefaultArtifactStoreManagerFactory(ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector) {
this.checksumAlgorithmFactorySelector = requireNonNull(checksumAlgorithmFactorySelector);
}

@Override
public ArtifactStoreManager create(Config config) {
return new DefaultArtifactStoreManager(config, checksumAlgorithmFactorySelector);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
import java.nio.file.Path;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;

public interface ArtifactStore extends Closeable {
/**
Expand All @@ -31,6 +35,11 @@ public interface ArtifactStore extends Closeable {
*/
boolean allowRedeploy();

/**
* The checksum algorithm factories this store uses, or empty if globally configured are wanted.
*/
Optional<List<ChecksumAlgorithmFactory>> checksumAlgorithmFactories();

/**
* Index of artifacts in this store, never {@code null}.
*/
Expand All @@ -46,8 +55,17 @@ public interface ArtifactStore extends Closeable {
*/
Path basedir();

/**
* Customizes the session to access this store.
*
* @see #storeRemoteRepository()
*/
RepositorySystemSession storeRepositorySession(RepositorySystemSession session);

/**
* The Resolver remote repository access to underlying store.
*
* @see #storeRepositorySession(RepositorySystemSession)
*/
RemoteRepository storeRemoteRepository();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package eu.maveniverse.maven.njord.shared.store;

import eu.maveniverse.maven.njord.shared.Config;

public interface ArtifactStoreManagerFactory {
/**
* Creates instance of artifact store manager.
*/
ArtifactStoreManager create(Config config);
}
Loading