Skip to content

Commit f7d9238

Browse files
authored
Merge pull request #9331 from smowton/smowton/fix/kotlin-jar-file-entry-mtimes
Kotlin: use the same mtimes as Java
2 parents 4cf3467 + 1f2248c commit f7d9238

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
import java.io.File;
55
import java.io.IOException;
66
import java.util.Arrays;
7+
import java.util.Enumeration;
8+
import java.util.HashMap;
79
import java.util.LinkedHashMap;
810
import java.util.Map;
911
import java.util.Objects;
1012
import java.util.regex.Pattern;
13+
import java.util.zip.ZipEntry;
14+
import java.util.zip.ZipFile;
1115

1216
import com.github.codeql.Logger;
1317
import static com.github.codeql.ClassNamesKt.getIrDeclBinaryName;
@@ -547,6 +551,51 @@ else if (majorVersion==0)
547551
(tcv.majorVersion == majorVersion && tcv.minorVersion == minorVersion &&
548552
tcv.lastModified < lastModified);
549553
}
554+
555+
private static Map<String, Map<String, Long>> jarFileEntryTimeStamps = new HashMap<>();
556+
557+
private static Map<String, Long> getZipFileEntryTimeStamps(String path, Logger log) {
558+
try {
559+
Map<String, Long> result = new HashMap<>();
560+
ZipFile zf = new ZipFile(path);
561+
Enumeration<? extends ZipEntry> entries = zf.entries();
562+
while (entries.hasMoreElements()) {
563+
ZipEntry ze = entries.nextElement();
564+
result.put(ze.getName(), ze.getLastModifiedTime().toMillis());
565+
}
566+
return result;
567+
} catch(IOException e) {
568+
log.warn("Failed to get entry timestamps from " + path, e);
569+
return null;
570+
}
571+
}
572+
573+
private static long getVirtualFileTimeStamp(VirtualFile vf, Logger log) {
574+
if (vf.getFileSystem().getProtocol().equals("jar")) {
575+
String[] parts = vf.getPath().split("!/");
576+
if (parts.length == 2) {
577+
String jarFilePath = parts[0];
578+
String entryPath = parts[1];
579+
if (!jarFileEntryTimeStamps.containsKey(jarFilePath)) {
580+
jarFileEntryTimeStamps.put(jarFilePath, getZipFileEntryTimeStamps(jarFilePath, log));
581+
}
582+
Map<String, Long> entryTimeStamps = jarFileEntryTimeStamps.get(jarFilePath);
583+
if (entryTimeStamps != null) {
584+
Long entryTimeStamp = entryTimeStamps.get(entryPath);
585+
if (entryTimeStamp != null)
586+
return entryTimeStamp;
587+
else
588+
log.warn("Couldn't find timestamp for jar file " + jarFilePath + " entry " + entryPath);
589+
}
590+
} else {
591+
log.warn("Expected JAR-file path " + vf.getPath() + " to have exactly one '!/' separator");
592+
}
593+
}
594+
595+
// For all files except for jar files, and a fallback in case of I/O problems reading a jar file:
596+
return vf.getTimeStamp();
597+
}
598+
550599
private static TrapClassVersion fromSymbol(IrDeclaration sym, Logger log) {
551600
VirtualFile vf = sym instanceof IrClass ? getIrClassVirtualFile((IrClass)sym) :
552601
sym.getParent() instanceof IrClass ? getIrClassVirtualFile((IrClass)sym.getParent()) :
@@ -583,7 +632,7 @@ public void visit(int version, int access, java.lang.String name, java.lang.Stri
583632
};
584633
(new ClassReader(vf.contentsToByteArray())).accept(versionGetter, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
585634

586-
return new TrapClassVersion(versionStore[0] & 0xffff, versionStore[0] >> 16, vf.getTimeStamp(), "kotlin");
635+
return new TrapClassVersion(versionStore[0] & 0xffff, versionStore[0] >> 16, getVirtualFileTimeStamp(vf, log), "kotlin");
587636
}
588637
catch(IllegalAccessException e) {
589638
log.warn("Failed to read class file version information", e);

0 commit comments

Comments
 (0)