/** * Copyright (c) 2010, 2013 Darmstadt University of Technology. * 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: * Andreas Sewe - initial API and implementation */ package org.eclipse.recommenders.coordinates.maven; import static com.google.common.base.Optional.absent; import static java.util.concurrent.TimeUnit.SECONDS; import static org.eclipse.recommenders.coordinates.Coordinates.tryNewProjectCoordinate; import static org.eclipse.recommenders.coordinates.DependencyType.JAR; import static org.eclipse.recommenders.utils.Versions.canonicalizeVersion; import java.net.URL; import java.util.Arrays; import java.util.List; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.XMLResponseParser; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.eclipse.recommenders.coordinates.AbstractProjectCoordinateAdvisor; import org.eclipse.recommenders.coordinates.DependencyInfo; import org.eclipse.recommenders.coordinates.DependencyType; import org.eclipse.recommenders.coordinates.ProjectCoordinate; import org.eclipse.recommenders.utils.Fingerprints; import org.eclipse.recommenders.utils.Urls; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; public class MavenCentralFingerprintSearchAdvisor extends AbstractProjectCoordinateAdvisor { public static final URL SEARCH_MAVEN_ORG = Urls.toUrl("http://search.maven.org/solrsearch"); private static final Logger LOG = LoggerFactory.getLogger(MavenCentralFingerprintSearchAdvisor.class); private static final int NETWORK_TIMEOUT = (int) SECONDS.toMillis(3); private static final List<String> SUPPORTED_PACKAGINGS = Arrays.asList("jar", "war", "bundle"); private static final String FIELD_GROUP_ID = "g"; private static final String FIELD_ARTIFACT_ID = "a"; private static final String FIELD_VERSION = "v"; private static final String FIELD_PACKAGING = "p"; private SolrServer server; public MavenCentralFingerprintSearchAdvisor() { this(null, -1); } public MavenCentralFingerprintSearchAdvisor(String proxyHost, int proxyPort) { this(proxyHost, proxyPort, null); } public MavenCentralFingerprintSearchAdvisor(String proxyHost, int proxyPort, String proxyUser) { this(proxyHost, proxyPort, proxyUser, null); } public MavenCentralFingerprintSearchAdvisor(String proxyHost, int proxyPort, String proxyUser, String proxyPassword) { server = createSolrServer(proxyHost, proxyPort, proxyUser, proxyPassword); } @Override protected boolean isApplicable(DependencyType dependencyType) { return dependencyType == JAR; } @Override protected Optional<ProjectCoordinate> doSuggest(DependencyInfo dependencyInfo) { if (!dependencyInfo.getFile().isFile()) { return absent(); } try { SolrQuery query = new SolrQuery(); query.setQuery("1:\"" + Fingerprints.sha1(dependencyInfo.getFile()) + "\""); query.setRows(1); QueryResponse response = server.query(query); SolrDocumentList results = response.getResults(); for (SolrDocument document : results) { if (!SUPPORTED_PACKAGINGS.contains(document.get(FIELD_PACKAGING))) { continue; } String groupId = (String) document.get(FIELD_GROUP_ID); String artifactId = (String) document.get(FIELD_ARTIFACT_ID); String version = (String) document.get(FIELD_VERSION); return tryNewProjectCoordinate(groupId, artifactId, canonicalizeVersion(version)); } return absent(); } catch (SolrServerException e) { LOG.error("Exception when querying Solr Server <{}>", SEARCH_MAVEN_ORG, e); return absent(); } } public void setProxy(String host, int port, String user, String password) { server = createSolrServer(host, port, user, password); } private CommonsHttpSolrServer createSolrServer(String proxyHost, int proxyPort, String proxyUser, String proxyPassword) { HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); // Need to set these on the connection manager ourselves rather than using // CommonsHttpSolrServer.setConnectionTimeout and CommonsHttpSolrServer.setSoTimeout, as the bundle // org.apache.solr.client.solrj is missing a necessary import of package org.apache.commons.httpclient.params. // See <https://bugs.eclipse.org/bugs/show_bug.cgi?id=413496>. connectionManager.getParams().setConnectionTimeout(NETWORK_TIMEOUT); connectionManager.getParams().setSoTimeout(NETWORK_TIMEOUT); final HttpClient httpClient = new HttpClient(connectionManager); if (proxyHost != null) { httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort); } if (proxyUser != null) { Credentials credentials = new UsernamePasswordCredentials(proxyUser, proxyPassword); httpClient.getState().setProxyCredentials(AuthScope.ANY, credentials); } final CommonsHttpSolrServer server = new CommonsHttpSolrServer(SEARCH_MAVEN_ORG, httpClient); server.setAllowCompression(true); server.setParser(new XMLResponseParser()); return server; } }