Skip to content

Commit

Permalink
[NETBEANS-1396] Fall back to main javadoc and source jars for Maven d…
Browse files Browse the repository at this point in the history
…ependencies with classifiers

OpenJFX uses Maven classifiers for platform dependent code, i.e. javafx-graphics-13.jar does not contain any code, but it depends through build profiles on javafx-graphics-13-linux.jar. There is however no javafx-graphics-13-linux-javadoc.jar, only a javafx-graphics-13-javadoc.jar, which NetBeans doesn't find. This patch lets NetBeans fall back to the main javadoc jar if there is none associated with the one with the classifier.

The contents of the javadoc jars of OpenJFX are prefixed by module name, which is different from the default output of the maven-javadoc-plugin. This patch does some bytecode reading to still find the correct .html file.

Fix RepositoryForBinaryQueryImplTest::testResultChanging which was broken because of a missing test resource.
  • Loading branch information
zimmi committed Nov 17, 2019
1 parent 1b50f1e commit 35afb62
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.java.source.SourceUtils;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.modules.classfile.ClassFile;
import org.netbeans.modules.classfile.Module;
import org.netbeans.modules.java.source.base.Bundle;
import org.netbeans.modules.java.source.indexing.JavaIndex;
import org.netbeans.modules.java.source.parsing.CachingArchiveProvider;
Expand Down Expand Up @@ -768,7 +770,31 @@ private static List<TextStream> findJavadoc(
LOG.log(Level.FINE, "assumed valid Javadoc stream at {0}", url);
} else if (!speculative || !isRemote) {
try {
is = openStream(url, Bundle.LBL_HTTPJavadocDownload());
try {
is = openStream(url, Bundle.LBL_HTTPJavadocDownload());
} catch (InterruptedIOException iioe) {
throw iioe;
} catch (IOException x) {
// Some libraries like OpenJFX prefix their
// javadoc by module, similar to the JDK.
// Only search there when the default fails
// to avoid additional I/O.
// NOTE: No multi-release jar support for now.
URL moduleInfo = new URL(binary, "module-info.class");
try (InputStream classData = moduleInfo.openStream()) {
ClassFile clazz = new ClassFile(classData, false);
Module module = clazz.getModule();
if (module == null) {
throw x;
}
String moduleName = module.getName();
if (moduleName == null) {
throw x;
}
url = new URL(root, moduleName + "/" + pkgName + "/" + pageName + ".html");
is = openStream(url, Bundle.LBL_HTTPJavadocDownload());
}
}
if (useKnownGoodRoots) {
knownGoodRoots.add(rootS);
LOG.log(Level.FINE, "found valid Javadoc stream at {0}", url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public JavadocForBinaryQuery.Result findJavadoc(URL url) {
//we have classifier here..
String end = jarFile.getName().substring((start + "-").length());
if (end.indexOf('.') > -1) {
classifier = end.substring(end.indexOf('.'));
classifier = end.substring(0, end.indexOf('.'));
}
}
File javadoc = new File(parent, start + (classifier != null ? ("-" + ("tests".equals(classifier) ? "test" : classifier)) : "") + "-javadoc.jar"); //NOI18N
Expand All @@ -290,6 +290,7 @@ private static class SrcResult implements SourceForBinaryQueryImplementation2.Re
private static final String ATTR_PATH = "lastRootCheckPath"; //NOI18N
private static final String ATTR_STAMP = "lastRootCheckStamp"; //NOI18N
private final File sourceJarFile;
private final File fallbackSourceJarFile;
private final ChangeSupport support;
private final ChangeListener mfoListener;
private final PropertyChangeListener projectListener;
Expand Down Expand Up @@ -365,7 +366,17 @@ public void fileDataCreated(FileEvent fe) {

if (sourceJarFile != null) {
FileUtil.addFileChangeListener(FileUtil.weakFileChangeListener(sourceJarChangeListener, null));
if (classifier != null) {
// fall back to regular sources if attached sources for classifier are missing
String regularSources = artifactId + "-" + version + "-sources.jar"; //NOI18N
if (!sourceJarFile.getName().equals(regularSources)) {
fallbackSourceJarFile = new File(sourceJarFile.getParentFile(), regularSources);
// already listening for changes through the file change listener above
return;
}
}
}
fallbackSourceJarFile = null;
}

private void checkChanges(boolean fireChanges) {
Expand Down Expand Up @@ -448,7 +459,9 @@ public FileObject[] getRoots() {
// the only way to let user decide would be some sort of stamp file inside maven local repository.
if (sourceJarFile != null && sourceJarFile.exists()) {
add(fos, getSourceJarRoot(sourceJarFile));
}
} else if (fallbackSourceJarFile != null && fallbackSourceJarFile.exists()) {
add(fos, getSourceJarRoot(fallbackSourceJarFile));
}
add(fos, getShadedJarSources());
toRet = fos.toArray(new FileObject[0]);
}
Expand Down Expand Up @@ -635,6 +648,7 @@ public static List<Coordinates> getJarMetadataCoordinates(File binaryFile) {

private static class JavadocResult implements JavadocForBinaryQuery.Result {
private final File javadocJarFile;
private final File fallbackJavadocJarFile;
private final String groupId;
private final String artifactId;
private final String version;
Expand Down Expand Up @@ -689,7 +703,17 @@ public void fileDataCreated(FileEvent fe) {
WeakListeners.create(ChangeListener.class, mfoListener, MavenFileOwnerQueryImpl.getInstance()));
if (javadocJarFile != null) {
FileUtil.addFileChangeListener(javadocJarChangeListener, javadocJarFile);
if (classifier != null) {
// listen for regular javadoc because attached javadoc for classifier might be missing
String regularJavadoc = artifactId + "-" + version + "-javadoc.jar"; //NOI18N
if (!javadocJarFile.getName().equals(regularJavadoc)) {
fallbackJavadocJarFile = new File(javadocJarFile.getParentFile(), regularJavadoc);
FileUtil.addFileChangeListener(javadocJarChangeListener, fallbackJavadocJarFile);
return;
}
}
}
fallbackJavadocJarFile = null;
}

@Override
Expand All @@ -713,6 +737,8 @@ public synchronized URL[] getRoots() {
toRet = accum.toArray(new URL[0]);
} else if (javadocJarFile != null && javadocJarFile.exists()) {
toRet = getJavadocJarRoot(javadocJarFile);
} else if (fallbackJavadocJarFile != null && fallbackJavadocJarFile.exists()) {
toRet = getJavadocJarRoot(fallbackJavadocJarFile);
} else {
toRet = checkShadedMultiJars();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.util.Arrays;
import org.junit.Test;
import static org.junit.Assert.*;
import org.netbeans.api.java.queries.JavadocForBinaryQuery;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.maven.NbMavenProjectImpl;
Expand Down Expand Up @@ -59,6 +61,10 @@ protected void tearDown() throws Exception {
super.tearDown();
File prj10 = new File(getWorkDir(), "prj10");
org.codehaus.plexus.util.FileUtils.deleteDirectory(prj10);

File repo = EmbedderFactory.getProjectEmbedder().getLocalRepositoryFile();
File nbtest = new File(repo, "nbtest");
org.codehaus.plexus.util.FileUtils.deleteDirectory(nbtest);
}


Expand All @@ -79,9 +85,8 @@ public void testResultChanging() throws IOException {


// now create source jar
File sourceJar = new File(this.getDataDir(), "source.jar");
File repoSourceJar = new File(art10.getParentFile(), "testprj-1.0-sources.jar");
org.codehaus.plexus.util.FileUtils.copyFile(sourceJar, repoSourceJar);
org.codehaus.plexus.util.FileUtils.copyFile(art10, repoSourceJar);
assertEquals(1, result.getRoots().length);
assertEquals(FileUtil.getArchiveRoot(FileUtil.toFileObject(repoSourceJar)), result.getRoots()[0]);

Expand Down Expand Up @@ -128,5 +133,107 @@ public void testResultChanging() throws IOException {


}

@Test
public void testFindJavadoc() throws IOException {
File repo = EmbedderFactory.getProjectEmbedder().getLocalRepositoryFile();
File parent = new File(repo, "nbtest/testprj/1.0");
RepositoryForBinaryQueryImpl query = new RepositoryForBinaryQueryImpl();

// find nothing
File artifact = new File(parent, "testprj-1.0.jar");
TestFileUtils.writeZipFile(artifact, "META-INF/MANIFEST.MF:Version:1.0");
URL artifactRoot = FileUtil.getArchiveRoot(artifact.toURI().toURL());
JavadocForBinaryQuery.Result result = query.findJavadoc(artifactRoot);
assertNotNull(result);
assertEquals(0, result.getRoots().length);

// find regular javadoc
File javadoc = new File(parent, "testprj-1.0-javadoc.jar");
TestFileUtils.writeZipFile(javadoc, "META-INF/MANIFEST.MF:Version:1.0");
URL javadocRoot = FileUtil.getArchiveRoot(javadoc.toURI().toURL());
result = query.findJavadoc(artifactRoot);
assertEquals(1, result.getRoots().length);
assertEquals(javadocRoot, result.getRoots()[0]);

// classifier attachments should fall back to the regular javadoc
File attachment = new File(parent, "testprj-1.0-attachment.jar");
TestFileUtils.writeZipFile(attachment, "META-INF/MANIFEST.MF:Version:1.0");
URL attachmentRoot = FileUtil.getArchiveRoot(attachment.toURI().toURL());
result = query.findJavadoc(attachmentRoot);
assertEquals(1, result.getRoots().length);
assertEquals(javadocRoot, result.getRoots()[0]);

// classifier attachments should find their own javadoc
File attachmentJavadoc = new File(parent, "testprj-1.0-attachment-javadoc.jar");
TestFileUtils.writeZipFile(attachmentJavadoc, "META-INF/MANIFEST.MF:Version:1.0");
URL attachmentJavadocRoot = FileUtil.getArchiveRoot(attachmentJavadoc.toURI().toURL());
result = query.findJavadoc(attachmentRoot);
assertEquals(1, result.getRoots().length);
assertEquals(attachmentJavadocRoot, result.getRoots()[0]);

// result reacts to filesystem changes
org.codehaus.plexus.util.FileUtils.forceDelete(attachmentJavadoc);
assertEquals(1, result.getRoots().length);
assertEquals(javadocRoot, result.getRoots()[0]);

org.codehaus.plexus.util.FileUtils.forceDelete(javadoc);
assertEquals(0, result.getRoots().length);

TestFileUtils.writeZipFile(javadoc, "META-INF/MANIFEST.MF:Version:1.0");
assertEquals(1, result.getRoots().length);
assertEquals(javadocRoot, result.getRoots()[0]);
}

@Test
public void testFindSources() throws IOException {
File repo = EmbedderFactory.getProjectEmbedder().getLocalRepositoryFile();
File parent = new File(repo, "nbtest/testprj/1.0");
RepositoryForBinaryQueryImpl query = new RepositoryForBinaryQueryImpl();

// find nothing
File artifact = new File(parent, "testprj-1.0.jar");
TestFileUtils.writeZipFile(artifact, "META-INF/MANIFEST.MF:Version:1.0");
URL artifactRoot = FileUtil.getArchiveRoot(artifact.toURI().toURL());
SourceForBinaryQuery.Result result = query.findSourceRoots(artifactRoot);
assertNotNull(result);
assertEquals(0, result.getRoots().length);

// find regular sources
File sources = new File(parent, "testprj-1.0-sources.jar");
TestFileUtils.writeZipFile(sources, "META-INF/MANIFEST.MF:Version:1.0");
URL sourcesRoot = FileUtil.getArchiveRoot(sources.toURI().toURL());
result = query.findSourceRoots(artifactRoot);
assertEquals(1, result.getRoots().length);
assertEquals(sourcesRoot, result.getRoots()[0].toURL());

// classifier attachments should fall back to the regular sources
File attachment = new File(parent, "testprj-1.0-attachment.jar");
TestFileUtils.writeZipFile(attachment, "META-INF/MANIFEST.MF:Version:1.0");
URL attachmentRoot = FileUtil.getArchiveRoot(attachment.toURI().toURL());
result = query.findSourceRoots(attachmentRoot);
assertEquals(1, result.getRoots().length);
assertEquals(sourcesRoot, result.getRoots()[0].toURL());

// classifier attachments should find their own sources
File attachmentSources = new File(parent, "testprj-1.0-attachment-sources.jar");
TestFileUtils.writeZipFile(attachmentSources, "META-INF/MANIFEST.MF:Version:1.0");
URL attachmentSourcesRoot = FileUtil.getArchiveRoot(attachmentSources.toURI().toURL());
result = query.findSourceRoots(attachmentRoot);
assertEquals(1, result.getRoots().length);
assertEquals(attachmentSourcesRoot, result.getRoots()[0].toURL());

// result reacts to filesystem changes
org.codehaus.plexus.util.FileUtils.forceDelete(attachmentSources);
assertEquals(1, result.getRoots().length);
assertEquals(sourcesRoot, result.getRoots()[0].toURL());

org.codehaus.plexus.util.FileUtils.forceDelete(sources);
assertEquals(0, result.getRoots().length);

TestFileUtils.writeZipFile(sources, "META-INF/MANIFEST.MF:Version:1.0");
assertEquals(1, result.getRoots().length);
assertEquals(sourcesRoot, result.getRoots()[0].toURL());
}

}

0 comments on commit 35afb62

Please sign in to comment.