Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular JDK support #61

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
build
.gradle
out/
.idea
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/*
* 04/21/2012
*
* Copyright (C) 2010 Robert Futrell
* robert_futrell at users.sourceforge.net
* http://fifesoft.com/rsyntaxtextarea
*
* This library is distributed under a modified BSD license. See the included
* RSTALanguageSupport.License.txt file for details.
*/
package org.fife.rsta.ac.java.buildpath;

import org.fife.rsta.ac.java.PackageMapNode;
import org.fife.rsta.ac.java.classreader.ClassFile;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;


/**
* Information about the JDK 9+ runtime classes to add to the "build path".
*
* Note: this introspects the modules delivered as prt of the JDJ, in jmods.
* A more complete implementation could look into the ct.sym file and rely on
* a JDK version to find the proper signatures:
* https://www.morling.dev/blog/the-anatomy-of-ct-sym-how-javac-ensures-backwards-compatibility/
*
*
* @author Robert Futrell
* @author Philippe Riand
* @version 1.0
* @see DirLibraryInfo
* @see ClasspathLibraryInfo
* @see JarLibraryInfo
*/
public class Jdk9LibraryInfo extends LibraryInfo {

private File[] jmodFiles;
private JarFile[] bulkCreateJmods;

public Jdk9LibraryInfo(File[] jmodFiles) {
this(jmodFiles, null);
}


public Jdk9LibraryInfo(File[] jmodFiles, SourceLocation sourceLoc) {
setJmodFiles(jmodFiles);
setSourceLocation(sourceLoc);
}


@Override
public void bulkClassFileCreationEnd() {
for( JarFile bulkCreateJar: bulkCreateJmods) {
try {
bulkCreateJar.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
bulkCreateJmods = null;
}


@Override
public void bulkClassFileCreationStart() {
bulkCreateJmods = new JarFile[jmodFiles.length];
for(int i = 0; i< jmodFiles.length; i++) {
File jarFile = jmodFiles[i];
try {
bulkCreateJmods[i] = new JarFile(jarFile);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}


/**
* Compares this <code>LibraryInfo</code> to another one. Two instances of
* this class are only considered equal if they represent the same class
* file location. Source attachment is irrelevant.
*
* @return The sort order of these two library infos.
*/
@Override
public int compareTo(LibraryInfo info) {
if (info==this) {
return 0;
}
int result = -1;
if (info instanceof Jdk9LibraryInfo) {
// Only compare the object refs
result = this==info ? 0 : -1;
}
return result;
}


@Override
public ClassFile createClassFile(String entryName) throws IOException {
for(File jarFile: jmodFiles) {
try (JarFile jar = new JarFile(jarFile)) {
ClassFile c = createClassFileImpl(jar, entryName);
if(c!=null) {
return c;
}
}
}
System.err.println("ERROR: Invalid entry: " + entryName);
return null;
}


@Override
public ClassFile createClassFileBulk(String entryName) throws IOException {
for( JarFile bulkCreateJar: bulkCreateJmods) {
ClassFile c = createClassFileImpl(bulkCreateJar, entryName);
if(c!=null) {
return c;
}
}
System.err.println("ERROR: Invalid entry: " + entryName);
return null;
}


private static ClassFile createClassFileImpl(JarFile jar,
String entryName) throws IOException {
JarEntry entry = (JarEntry)jar.getEntry("classes/"+entryName);
if (entry==null) {
return null;
}
DataInputStream in = new DataInputStream(
new BufferedInputStream(jar.getInputStream(entry)));
ClassFile cf;
try {
cf = new ClassFile(in);
} finally {
in.close();
}
return cf;
}


@Override
public PackageMapNode createPackageMap() throws IOException {
PackageMapNode root = new PackageMapNode();

for( File jarFile: jmodFiles) {
try (JarFile jar = new JarFile(jarFile)) {

Enumeration<JarEntry> e = jar.entries();
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
String entryName = entry.getName();
if(entryName.startsWith("classes/")) {
entryName = entryName.substring(8);
if (entryName.endsWith(".class")) {
root.add(entryName);
}
}
}

}
}

return root;

}


@Override
public long getLastModified() {
return 0; //jarFile.lastModified();
}


@Override
public String getLocationAsString() {
return ""; //jarFile.getAbsolutePath();
}


@Override
public int hashCodeImpl() {
int h = 0;
for( File jarFile: jmodFiles) {
h += jarFile.hashCode();
}
return h;
}


/**
* Sets the jar file location.
*
* @param jmodFiles The jar files location. This cannot be <code>null</code>.
*/
private void setJmodFiles(File[] jmodFiles) {
for( File jarFile: jmodFiles) {
if (jarFile==null || !jarFile.exists()) {
String name = jarFile==null ? "null" : jarFile.getAbsolutePath();
throw new IllegalArgumentException("Jar does not exist: " + name);
}
}
this.jmodFiles = jmodFiles;
}


/**
* Returns a string representation of this jar information. Useful for
* debugging.
*
* @return A string representation of this object.
*/
@Override
public String toString() {
return "[JarLibraryInfo: " +
"jars=" + jmodFiles.toString() +
"; source=" + getSourceLocation() +
"]";
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package org.fife.rsta.ac.java.buildpath;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;

import org.fife.rsta.ac.java.JarManager;
Expand Down Expand Up @@ -171,6 +172,28 @@ public boolean equals(Object o) {
* @see #getMainJreJarInfo()
*/
public static LibraryInfo getJreJarInfo(File jreHome) {
// Check if the Jre is made of modules
File mods = new File(jreHome,"jmods");
if(mods.isDirectory()) {
File[] files = mods.listFiles( new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.isFile()) {
String name = pathname.getName();
return name.endsWith(".jmod") && (name.startsWith("java.") || name.startsWith("jdk."));
}
return false;
}
});

LibraryInfo info = new Jdk9LibraryInfo(files);
File sourceZip = new File(jreHome,"lib"+File.separator+"src.zip");
if (sourceZip.isFile()) { // Make sure our last guess actually exists
info.setSourceLocation(new ZipSourceLocation(sourceZip));
}

return info;
}

LibraryInfo info = null;

Expand Down