/******************************************************************************* * Copyright (c) 2015 IBH SYSTEMS GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBH SYSTEMS GmbH - initial API and implementation *******************************************************************************/ package org.eclipse.packagedrone.repo.importer.aether.web; import static org.eclipse.packagedrone.repo.importer.aether.AetherImporter.prepareDependencies; import java.nio.file.Files; import java.nio.file.Path; import org.eclipse.packagedrone.job.AbstractJsonJobFactory; import org.eclipse.packagedrone.job.JobFactoryDescriptor; import org.eclipse.packagedrone.job.JobInstance.Context; import org.eclipse.packagedrone.repo.MetaKey; import org.eclipse.packagedrone.repo.channel.ArtifactInformation; import org.eclipse.packagedrone.repo.channel.ChannelNotFoundException; import org.eclipse.packagedrone.repo.channel.ChannelService; import org.eclipse.packagedrone.repo.channel.ChannelService.By; import org.eclipse.packagedrone.repo.channel.ReadableChannel; import org.eclipse.packagedrone.repo.importer.aether.ImportConfiguration; import org.eclipse.packagedrone.web.LinkTarget; import org.eclipse.scada.utils.io.RecursiveDeleteVisitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; public class AetherResolver extends AbstractJsonJobFactory<ImportConfiguration, AetherResult> { private final static Logger logger = LoggerFactory.getLogger ( AetherResolver.class ); public static final String ID = "org.eclipse.packagedrone.repo.importer.aether.web.resolver"; private static final JobFactoryDescriptor DESCRIPTOR = new JobFactoryDescriptor () { @Override public LinkTarget getResultTarget () { return null; } }; private static final MetaKey KEY_GROUP_ID = new MetaKey ( "mvn", "groupId" ); private static final MetaKey KEY_ARTIFACT_ID = new MetaKey ( "mvn", "artifactId" ); private static final MetaKey KEY_CLASSIFIER = new MetaKey ( "mvn", "classifier" ); private static final MetaKey KEY_EXTENSION = new MetaKey ( "mvn", "extension" ); private static final MetaKey KEY_VERSION = new MetaKey ( "mvn", "version" ); private ChannelService channelService; public AetherResolver () { super ( ImportConfiguration.class ); } public void setChannelService ( final ChannelService channelService ) { this.channelService = channelService; } @Override protected String makeLabelFromData ( final ImportConfiguration data ) { String label = ""; if ( !data.getCoordinates ().isEmpty () ) { label = data.getCoordinates ().get ( 0 ).toString (); if ( data.getCoordinates ().size () > 1 ) { label += String.format ( " (and %s more)", data.getCoordinates ().size () - 1 ); } } return String.format ( "Resolve maven dependencies: %s", label ); } @Override public JobFactoryDescriptor getDescriptor () { return DESCRIPTOR; } @Override protected AetherResult process ( final Context context, final ImportConfiguration cfg ) throws Exception { final Path tmpDir = Files.createTempDirectory ( "aether" ); try { return markExisting ( prepareDependencies ( tmpDir, cfg ), cfg, this.channelService ); } catch ( final Exception e ) { logger.warn ( "Failed to test", e ); throw e; } finally { Files.walkFileTree ( tmpDir, new RecursiveDeleteVisitor () ); Files.deleteIfExists ( tmpDir ); } } private static AetherResult markExisting ( final AetherResult result, final ImportConfiguration cfg, final ChannelService channelService ) { final String channelId = cfg.getValidationChannelId (); if ( channelId == null || channelId.isEmpty () ) { return result; } try { channelService.accessRun ( By.id ( cfg.getValidationChannelId () ), ReadableChannel.class, channel -> { markExisting ( result, channel ); } ); } catch ( final ChannelNotFoundException e ) { // silently ignore } return result; } private static void markExisting ( final AetherResult result, final ReadableChannel channel ) { // build version map final Multimap<String, String> existing = HashMultimap.create (); for ( final ArtifactInformation ai : channel.getArtifacts () ) { final String groupId = ai.getMetaData ().get ( KEY_GROUP_ID ); final String artifactId = ai.getMetaData ().get ( KEY_ARTIFACT_ID ); final String classifier = ai.getMetaData ().get ( KEY_CLASSIFIER ); final String extension = ai.getMetaData ().get ( KEY_EXTENSION ); final String version = ai.getMetaData ().get ( KEY_VERSION ); if ( groupId != null && artifactId != null && version != null ) { final String key = makeExistingKey ( groupId, artifactId, classifier, extension ); existing.put ( key, version ); } } // match for ( final AetherResult.Entry entry : result.getArtifacts () ) { final String key = makeExistingKey ( entry.getCoordinates ().getGroupId (), entry.getCoordinates ().getArtifactId (), entry.getCoordinates ().getClassifier (), entry.getCoordinates ().getExtension () ); entry.getExistingVersions ().addAll ( existing.get ( key ) ); } } private static String makeExistingKey ( final String groupId, final String artifactId, final String classifier, final String extension ) { final StringBuilder sb = new StringBuilder (); sb.append ( groupId ); sb.append ( ':' ).append ( artifactId ); if ( classifier != null && !classifier.isEmpty () ) { sb.append ( ':' ).append ( classifier ); } if ( extension != null && !extension.isEmpty () ) { sb.append ( ':' ).append ( extension ); } return sb.toString (); } }