/******************************************************************************* * Copyright (c) 2011-2016 Igor Fedorenko * 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: * Igor Fedorenko - initial API and implementation *******************************************************************************/ package org.eclipse.m2e.sourcelookup.internal.launch; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.ArtifactKey; import org.eclipse.m2e.core.internal.index.IIndex; import org.eclipse.m2e.core.internal.index.IndexedArtifactFile; import org.eclipse.m2e.core.internal.index.nexus.CompositeIndex; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableSet; import com.google.common.hash.Hashing; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @SuppressWarnings("restriction") public class MavenArtifactIdentifier { // reads META-INF/maven/**/pom.properties private static final MetaInfMavenScanner scanner = new MetaInfMavenScanner() { @Override protected Properties visitFile(File file) throws IOException { // TODO validate properties and path match try (InputStream is = new BufferedInputStream(new FileInputStream(file))) { return loadProperties(is); } } @Override protected Properties visitJarEntry(JarFile jar, JarEntry entry) throws IOException { // TODO validate properties and path match try (InputStream is = jar.getInputStream(entry)) { return loadProperties(is); } } private Properties loadProperties(InputStream is) throws IOException { Properties properties = new Properties(); properties.load(is); return properties; } }; public Collection identify(File classesLocation, IProgressMonitor monitor) { // checksum-based lookup in nexus index // checksum-based lookup in central // GAV extracted from pom.properties Collection classesArtifacts = identifyNexusIndexer(classesLocation); if (classesArtifacts == null) { classesArtifacts = identifyCentralSearch(classesLocation); } if (classesArtifacts == null) { classesArtifacts = scanPomProperties(classesLocation); } return classesArtifacts; } protected Collection identifyNexusIndexer(File file) { if (!file.isFile()) { return null; } try { IIndex index = MavenPlugin.getIndexManager().getAllIndexes(); List identified; if (index instanceof CompositeIndex) { identified = ((CompositeIndex) index).identifyAll(file); } else { IndexedArtifactFile indexed = index.identify(file); if (indexed != null) { identified = Collections.singletonList(indexed); } else { identified = Collections.emptyList(); } } for (IndexedArtifactFile indexed : identified) { if (indexed.sourcesExists == IIndex.PRESENT) { return Collections.singleton(indexed.getArtifactKey()); } } } catch (CoreException e) { // TODO maybe log, but ignore otherwise } return null; } protected Collection identifyCentralSearch(File file) { if (!file.isFile()) { return null; } try { String sha1 = Files.hash(file, Hashing.sha1()).toString(); // TODO use Locations for caching URL url = new URL("https://search.maven.org/solrsearch/select?q=1:" + sha1); try (InputStreamReader reader = new InputStreamReader(url.openStream(), Charsets.UTF_8)) { Set result = new LinkedHashSet<>(); JsonObject container = new Gson().fromJson(reader, JsonObject.class); JsonArray docs = container.get("response").getAsJsonObject().get("docs").getAsJsonArray(); for (int i = 0; i < docs.size(); i++) { JsonObject doc = docs.get(i).getAsJsonObject(); String g = doc.get("g").getAsString(); String a = doc.get("a").getAsString(); String v = doc.get("v").getAsString(); result.add(new ArtifactKey(g, a, v, null)); } return !result.isEmpty() ? ImmutableSet.copyOf(result) : null; } } catch (IOException e) { // TODO maybe log, ignore otherwise } return null; } public Collection scanPomProperties(File classesLocation) { Set artifacts = new LinkedHashSet<>(); for (Properties pomProperties : scanner.scan(classesLocation, "pom.properties")) { String groupId = pomProperties.getProperty("groupId"); String artifactId = pomProperties.getProperty("artifactId"); String version = pomProperties.getProperty("version"); if (groupId != null && artifactId != null && version != null) { artifacts.add(new ArtifactKey(groupId, artifactId, version, /* classifier= */null)); } } return ImmutableSet.copyOf(artifacts); } }