diff --git a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java index c6bb1f199b0e..be42dd7fbf8b 100644 --- a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java +++ b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java @@ -67,7 +67,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { @NotNull @Override public Collection getActions(List orderEntries, final PsiFile psiFile) { - VirtualFile jar = getJarByPsiFile(psiFile); + final VirtualFile jar = getJarByPsiFile(psiFile); if (jar == null) return Collections.emptyList(); final String jarName = jar.getNameWithoutExtension(); @@ -145,7 +145,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { SourceSearcher[] searchers = {new MavenCentralSourceSearcher(), new SonatypeSourceSearcher()}; for (SourceSearcher searcher : searchers) { try { - artifactUrl = searcher.findSourceJar(indicator, artifactId, version); + artifactUrl = searcher.findSourceJar(indicator, artifactId, version, jar); } catch (SourceSearchException e) { LOG.warn(e); diff --git a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java index aeb6c7574a01..7e4ed5639904 100644 --- a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java @@ -2,6 +2,7 @@ package com.intellij.jarFinder; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; @@ -21,13 +22,19 @@ public class MavenCentralSourceSearcher extends SourceSearcher { @Override protected String findSourceJar(@NotNull ProgressIndicator indicator, @NotNull String artifactId, - @NotNull String version) throws SourceSearchException { + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { try { indicator.setText("Connecting to https://search.maven.org"); indicator.checkCanceled(); - String url = "https://search.maven.org/solrsearch/select?rows=3&wt=xml&q=a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22"; + String url = "https://search.maven.org/solrsearch/select?rows=3&wt=xml&q="; + final String groupId = findMavenGroupId(classesJar, artifactId); + if (groupId != null) { + url += "g:%22" + groupId + "%22%20AND%20"; + } + url += "a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22"; @SuppressWarnings("unchecked") List artifactList = (List)XPath.newInstance("/response/result/doc/str[@name='g']").selectNodes(readDocumentCancelable(indicator, url)); if (artifactList.isEmpty()) { diff --git a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java index b4251970fc10..76d713055a4a 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java @@ -2,6 +2,7 @@ package com.intellij.jarFinder; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; @@ -19,7 +20,10 @@ public class SonatypeSourceSearcher extends SourceSearcher { @Nullable @Override - public String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) + public String findSourceJar(@NotNull final ProgressIndicator indicator, + @NotNull String artifactId, + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { try { indicator.setIndeterminate(true); @@ -28,6 +32,11 @@ public class SonatypeSourceSearcher extends SourceSearcher { indicator.checkCanceled(); String url = "https://oss.sonatype.org/service/local/lucene/search?collapseresults=true&c=sources&a=" + artifactId + "&v=" + version; + String groupId = findMavenGroupId(classesJar, artifactId); + if(groupId != null) { + url += ("&g=" + groupId); + } + List artifactList = (List)XPath.newInstance("/searchNGResponse/data/artifact").selectNodes(readDocumentCancelable(indicator, url)); if (artifactList.isEmpty()) { return null; @@ -50,7 +59,7 @@ public class SonatypeSourceSearcher extends SourceSearcher { return null; } - String groupId = element.getChildTextTrim("groupId"); + groupId = element.getChildTextTrim("groupId"); String repositoryId = artifactHintList.get(0).getChildTextTrim("repositoryId"); return "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=" + diff --git a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java index 3c5d138e2b13..0b97e631148b 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java @@ -2,6 +2,10 @@ package com.intellij.jarFinder; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.StreamUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.HttpRequests; import org.jdom.Document; import org.jdom.JDOMException; @@ -9,19 +13,43 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** * @author Sergey Evdokimov */ public abstract class SourceSearcher { + + private static final String MAVEN_POM_ENTRY_PREFIX = "META-INF/maven/"; + /** * @param indicator * @param artifactId * @param version - * @return groupId of found artifact and url. + * @return url of found artifact */ @Nullable - protected abstract String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) throws SourceSearchException; + protected String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) + throws SourceSearchException { + return null; + } + + /** + * @param indicator + * @param artifactId + * @param version + * @param classesJar classes jar + * @return url of found artifact + */ + @Nullable + protected String findSourceJar(@NotNull final ProgressIndicator indicator, + @NotNull String artifactId, + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { + return findSourceJar(indicator, artifactId, version); + } @NotNull protected static Document readDocumentCancelable(final ProgressIndicator indicator, String url) throws IOException { @@ -39,6 +67,30 @@ public abstract class SourceSearcher { } }); } + + @Nullable + protected static String findMavenGroupId(@NotNull VirtualFile classesJar, String artifactId) { + try { + JarFile jarFile = new JarFile(VfsUtilCore.virtualToIoFile(classesJar)); + try { + final Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + final String name = entry.getName(); + if (StringUtil.startsWith(name, MAVEN_POM_ENTRY_PREFIX) && StringUtil.endsWith(name, "/" + artifactId + "/pom.xml")) { + final int index = name.indexOf('/', MAVEN_POM_ENTRY_PREFIX.length()); + return index != -1 ? name.substring(MAVEN_POM_ENTRY_PREFIX.length(), index) : null; + } + } + } + finally { + StreamUtil.closeStream(jarFile); + } + } + catch (IOException ignore) { + } + return null; + } } class SourceSearchException extends Exception {