blob: eb3776bd4ea6ae21cba55c609523ad0f493135f6 [file] [log] [blame]
/*******************************************************************************
* 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.nio.charset.StandardCharsets;
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.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<Properties> scanner = new MetaInfMavenScanner<Properties>() {
@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<ArtifactKey> identify(File classesLocation, IProgressMonitor monitor) {
// checksum-based lookup in nexus index
// checksum-based lookup in central
// GAV extracted from pom.properties
Collection<ArtifactKey> classesArtifacts = identifyNexusIndexer(classesLocation);
if (classesArtifacts == null) {
classesArtifacts = identifyCentralSearch(classesLocation);
}
if (classesArtifacts == null) {
classesArtifacts = scanPomProperties(classesLocation);
}
return classesArtifacts;
}
protected Collection<ArtifactKey> identifyNexusIndexer(File file) {
if (!file.isFile()) {
return null;
}
try {
IIndex index = MavenPlugin.getIndexManager().getAllIndexes();
List<IndexedArtifactFile> 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<ArtifactKey> 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(), StandardCharsets.UTF_8)) {
Set<ArtifactKey> 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<ArtifactKey> scanPomProperties(File classesLocation) {
Set<ArtifactKey> 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);
}
}