package org.carlspring.strongbox.providers.repository; import org.carlspring.strongbox.client.ArtifactTransportException; import org.carlspring.strongbox.io.ArtifactInputStream; import org.carlspring.strongbox.io.ArtifactOutputStream; import org.carlspring.strongbox.providers.ProviderImplementationException; import org.carlspring.strongbox.providers.layout.LayoutProvider; import org.carlspring.strongbox.storage.Storage; import org.carlspring.strongbox.storage.repository.Repository; import org.carlspring.strongbox.storage.routing.RoutingRule; import org.carlspring.strongbox.storage.routing.RoutingRules; import org.carlspring.strongbox.storage.routing.RuleSet; import javax.annotation.PostConstruct; import java.io.FileNotFoundException; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import static org.carlspring.strongbox.providers.layout.LayoutProviderRegistry.getLayoutProvider; /** * @author carlspring */ @Component public class GroupRepositoryProvider extends AbstractRepositoryProvider { private static final Logger logger = LoggerFactory.getLogger(GroupRepositoryProvider.class); private static final String ALIAS = "group"; @PostConstruct @Override public void register() { getRepositoryProviderRegistry().addProvider(ALIAS, this); logger.info("Registered repository provider '" + getClass().getCanonicalName() + "' with alias '" + ALIAS + "'."); } @Override public String getAlias() { return ALIAS; } @Override public ArtifactInputStream getInputStream(String storageId, String repositoryId, String artifactPath) throws IOException, NoSuchAlgorithmException, ArtifactTransportException, ProviderImplementationException { Storage storage = getConfiguration().getStorage(storageId); logger.debug("Checking in " + storage.getId() + ":" + repositoryId + "..."); Repository groupRepository = storage.getRepository(repositoryId); // Check the routing rules first. // Check the routing accept rules for the specified repository. final ArtifactInputStream isRepositoryAccept = getInputStreamFromRepositoryAcceptRules(repositoryId, artifactPath, storage); if (isRepositoryAccept != null) { return isRepositoryAccept; } // Check the routing rules for wildcard accept rules final ArtifactInputStream isWildcardRepositoryAccept = getInputStreamFromWildcardRepositoryAcceptRules(artifactPath, storage); if (isWildcardRepositoryAccept != null) { return isWildcardRepositoryAccept; } // Handle: // - Repository deny // - Repository wildcard repository deny final RuleSet denyRules = getRoutingRules().getDenyRules(repositoryId); final RuleSet wildcardDenyRules = getRoutingRules().getWildcardDeniedRules(); // If there are no matches in the routing rules, then loop as usual: for (String storageAndRepositoryId : groupRepository.getGroupRepositories()) { String sId = getConfigurationManager().getStorageId(storage, storageAndRepositoryId); String rId = getConfigurationManager().getRepositoryId(storageAndRepositoryId); Repository r = getConfiguration().getStorage(sId).getRepository(rId); if (r.isInService() && !repositoryRejects(r.getId(), artifactPath, denyRules) && !repositoryRejects(r.getId(), artifactPath, wildcardDenyRules)) { ArtifactInputStream is; try { is = resolveArtifact(sId, r.getId(), artifactPath); } catch (FileNotFoundException e) { continue; } if (is != null) { return is; } } } return null; } public boolean repositoryRejects(String repositoryId, String artifactPath, RuleSet denyRules) { if (denyRules != null && !denyRules.getRoutingRules().isEmpty()) { for (RoutingRule rule : denyRules.getRoutingRules()) { if (rule.getRepositories().contains(repositoryId) && artifactPath.matches(rule.getPattern())) { return true; } } } return false; } private ArtifactInputStream getInputStreamFromWildcardRepositoryAcceptRules(String artifactPath, Storage storage) throws IOException, NoSuchAlgorithmException, ArtifactTransportException, ProviderImplementationException { RuleSet globalAcceptRules = getRoutingRules().getWildcardAcceptedRules(); return getArtifactInputStreamViaAcceptedRules(artifactPath, storage, globalAcceptRules); } private ArtifactInputStream getInputStreamFromRepositoryAcceptRules(String repositoryId, String artifactPath, Storage storage) throws IOException, NoSuchAlgorithmException, ArtifactTransportException, ProviderImplementationException { RuleSet acceptRules = getRoutingRules().getAcceptRules(repositoryId); return getArtifactInputStreamViaAcceptedRules(artifactPath, storage, acceptRules); } private ArtifactInputStream getArtifactInputStreamViaAcceptedRules(String artifactPath, Storage storage, RuleSet acceptRules) throws ProviderImplementationException, NoSuchAlgorithmException, IOException, ArtifactTransportException { if (acceptRules != null && acceptRules.getRoutingRules() != null && !acceptRules.getRoutingRules().isEmpty()) { final List<RoutingRule> routingRules = acceptRules.getRoutingRules(); for (RoutingRule rule : routingRules) { if (artifactPath.matches(rule.getPattern())) { for (String rId : rule.getRepositories()) { String sId = getConfigurationManager().getStorageId(storage, rId); rId = getConfigurationManager().getRepositoryId(rId); Repository repository = getConfiguration().getStorage(sId).getRepository(rId); LayoutProvider layoutProvider = getLayoutProvider(repository, getLayoutProviderRegistry()); if (repository.isInService() && layoutProvider.containsPath(repository, artifactPath)) { return resolveArtifact(sId, repository.getId(), artifactPath); } } } } } return null; } /** * Returns the artifact associated to artifactPath if repository type isn't GROUP or * returns the product of calling getInputStream recursively otherwise. * * @param storageId The storage id * @param repositoryId The repository * @param artifactPath The path to the artifact * @return * @throws NoSuchAlgorithmException * @throws IOException * @throws ArtifactTransportException */ private ArtifactInputStream resolveArtifact(String storageId, String repositoryId, String artifactPath) throws NoSuchAlgorithmException, IOException, ArtifactTransportException, ProviderImplementationException { ArtifactInputStream is; Repository repository = getConfiguration().getStorage(storageId).getRepository(repositoryId); if (!getAlias().equals(repository.getType())) { is = getInputStream(repository, artifactPath); if (is != null) { logger.debug("Located artifact: [" + storageId + ":" + repository.getId() + "]"); return is; } } else { is = getInputStream(storageId, repository.getId(), artifactPath); if (is != null) { logger.debug("Located artifact: [" + storageId + ":" + repository.getId() + "]"); return is; } } return null; } private ArtifactInputStream getInputStream(Repository repository, String artifactPath) throws IOException, NoSuchAlgorithmException, ArtifactTransportException, ProviderImplementationException { RepositoryProvider provider = getRepositoryProviderRegistry().getProvider(repository.getType()); ArtifactInputStream is = provider.getInputStream(repository.getStorage().getId(), repository.getId(), artifactPath); return is; } @Override public ArtifactOutputStream getOutputStream(String storageId, String repositoryId, String artifactPath) throws IOException { // It should not be possible to write artifacts to a group repository. // A group repository should only serve artifacts that already exist // in the repositories within the group. throw new UnsupportedOperationException(); } public RoutingRules getRoutingRules() { return getConfiguration().getRoutingRules(); } }