8202387: javac --release 11 not supported

Adding historical data for JDK 10; adding ability to produce the historical data incrementally.

Reviewed-by: erikj, forax, jjg
This commit is contained in:
Jan Lahoda 2018-05-07 10:37:46 +02:00
parent 29b1984560
commit 81bad1fe6b
71 changed files with 3231 additions and 242 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,6 +31,7 @@ import build.tools.symbolgenerator.CreateSymbols
import build.tools.symbolgenerator.CreateSymbols
.ModuleHeaderDescription
.RequiresDescription;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -38,8 +39,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
@ -49,23 +50,34 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.stream.Stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.Annotation;
import com.sun.tools.classfile.Annotation.Annotation_element_value;
@ -115,18 +127,20 @@ import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.Signature_attribute;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Pair;
import java.io.StringWriter;
/**
* A tool for processing the .sym.txt files. It allows to:
* * convert the .sym.txt into class/sig files for ct.sym
* * in cooperation with the adjacent history Probe, construct .sym.txt files for previous platforms
* * enhance existing .sym.txt files with a a new set .sym.txt for the current platform
*
* To convert the .sym.txt files to class/sig files from ct.sym, run:
* java build.tool.symbolgenerator.CreateSymbols build-ctsym [JOINED_VERSIONS|SEPARATE] <platform-description-file> <target-directory>
* java build.tool.symbolgenerator.CreateSymbols build-ctsym <platform-description-file> <target-directory>
*
* The <platform-description-file> is a file of this format:
* generate platforms <platform-ids-to-generate separate with ':'>
@ -166,11 +180,15 @@ import java.io.StringWriter;
* To generate the .sym.txt files for OpenJDK 7 and 8:
* <jdk-7>/bin/java build.tools.symbolgenerator.Probe OpenJDK7.classes
* <jdk-8>/bin/java build.tools.symbolgenerator.Probe OpenJDK8.classes
* java build.tools.symbolgenerator.CreateSymbols build-description langtools/make/data/symbols $TOPDIR langtools/make/data/symbols/include.list
* java build.tools.symbolgenerator.CreateSymbols build-description make/data/symbols $TOPDIR make/data/symbols/include.list
* 8 OpenJDK8.classes '<none>'
* 7 OpenJDK7.classes 8
*
* Note: the versions are expected to be a single character.
*
* To enhance existing historical data with data for JDK N, run:
* <jdk-N>/bin/java build.tools.symbolgenerator.CreateSymbols build-description-incremental make/data/symbols/symbols make/data/symbols/include.list
*
*/
public class CreateSymbols {
@ -180,11 +198,11 @@ public class CreateSymbols {
*/
@SuppressWarnings("unchecked")
public void createSymbols(String ctDescriptionFile, String ctSymLocation, CtSymKind ctSymKind) throws IOException {
Pair<ClassList, List<ModuleDescription>> data = load(Paths.get(ctDescriptionFile));
LoadDescriptions data = load(Paths.get(ctDescriptionFile), null);
splitHeaders(data.fst);
splitHeaders(data.classes);
for (ModuleDescription md : data.snd) {
for (ModuleDescription md : data.modules.values()) {
for (ModuleHeaderDescription mhd : md.header) {
List<String> versionsList =
Collections.singletonList(mhd.versions);
@ -195,7 +213,7 @@ public class CreateSymbols {
}
}
for (ClassDescription classDescription : data.fst) {
for (ClassDescription classDescription : data.classes) {
for (ClassHeaderDescription header : classDescription.header) {
switch (ctSymKind) {
case JOINED_VERSIONS:
@ -219,7 +237,7 @@ public class CreateSymbols {
public static String EXTENSION = ".sig";
Pair<ClassList, List<ModuleDescription>> load(Path ctDescription) throws IOException {
LoadDescriptions load(Path ctDescription, String deletePlatform) throws IOException {
List<PlatformInput> platforms = new ArrayList<>();
Set<String> generatePlatforms = null;
@ -228,11 +246,14 @@ public class CreateSymbols {
switch (reader.lineKey) {
case "generate":
String[] platformsAttr = reader.attributes.get("platforms").split(":");
generatePlatforms = new HashSet<>(Arrays.asList(platformsAttr));
generatePlatforms = new HashSet<>(List.of(platformsAttr));
generatePlatforms.remove(deletePlatform);
reader.moveNext();
break;
case "platform":
platforms.add(PlatformInput.load(reader));
PlatformInput platform = PlatformInput.load(reader);
if (!platform.version.equals(deletePlatform))
platforms.add(platform);
reader.moveNext();
break;
default:
@ -250,7 +271,9 @@ public class CreateSymbols {
addNewVersion(cd.fields, platform.basePlatform, platform.version);
addNewVersion(cd.methods, platform.basePlatform, platform.version);
}
//XXX: enhance module versions
for (ModuleDescription md : modules.values()) {
addNewVersion(md.header, platform.basePlatform, platform.version);
}
for (String input : platform.files) {
Path inputFile = ctDescription.getParent().resolve(input);
try (LineBasedReader reader = new LineBasedReader(inputFile)) {
@ -270,13 +293,23 @@ public class CreateSymbols {
cd.read(reader, platform.basePlatform,
platform.version);
break;
case "module":
case "module": {
ModuleDescription md =
modules.computeIfAbsent(nameAttr,
n -> new ModuleDescription());
md.read(reader, platform.basePlatform,
platform.version);
break;
}
case "-module": {
ModuleDescription md =
modules.computeIfAbsent(nameAttr,
n -> new ModuleDescription());
removeVersion(md.header, h -> true,
platform.version);
reader.moveNext();
break;
}
}
}
}
@ -323,7 +356,7 @@ public class CreateSymbols {
result.add(desc);
}
List<ModuleDescription> moduleList = new ArrayList<>();
Map<String, ModuleDescription> moduleList = new HashMap<>();
for (ModuleDescription desc : modules.values()) {
Iterator<ModuleHeaderDescription> mhdIt = desc.header.iterator();
@ -340,10 +373,25 @@ public class CreateSymbols {
continue;
}
moduleList.add(desc);
moduleList.put(desc.name, desc);
}
return new LoadDescriptions(result, moduleList, platforms);
}
static final class LoadDescriptions {
public final ClassList classes;
public final Map<String, ModuleDescription> modules;
public final List<PlatformInput> versions;
public LoadDescriptions(ClassList classes,
Map<String, ModuleDescription> modules,
List<PlatformInput> versions) {
this.classes = classes;
this.modules = modules;
this.versions = versions;
}
return Pair.of(result, moduleList);
}
static final class LineBasedReader implements AutoCloseable {
@ -423,7 +471,7 @@ public class CreateSymbols {
public static PlatformInput load(LineBasedReader in) throws IOException {
return new PlatformInput(in.attributes.get("version"),
in.attributes.get("base"),
Arrays.asList(in.attributes.get("files").split(":")));
List.of(in.attributes.get("files").split(":")));
}
}
@ -792,7 +840,7 @@ public class CreateSymbols {
private void addAttributes(MethodDescription desc, List<CPInfo> constantPool, Map<String, Attribute> attributes) {
addGenericAttributes(desc, constantPool, attributes);
if (desc.thrownTypes != null && !desc.thrownTypes.isEmpty()) {
if (desc.thrownTypes != null) {
int[] exceptions = new int[desc.thrownTypes.size()];
int i = 0;
for (String exc : desc.thrownTypes) {
@ -1081,175 +1129,228 @@ public class CreateSymbols {
Map<String, ModuleDescription> modules = new HashMap<>();
for (VersionDescription desc : versions) {
Map<String, ModuleDescription> currentVersionModules =
new HashMap<>();
List<byte[]> classFileData = new ArrayList<>();
try (BufferedReader descIn =
Files.newBufferedReader(Paths.get(desc.classes))) {
String classFileData;
while ((classFileData = descIn.readLine()) != null) {
String line;
while ((line = descIn.readLine()) != null) {
ByteArrayOutputStream data = new ByteArrayOutputStream();
for (int i = 0; i < classFileData.length(); i += 2) {
String hex = classFileData.substring(i, i + 2);
for (int i = 0; i < line.length(); i += 2) {
String hex = line.substring(i, i + 2);
data.write(Integer.parseInt(hex, 16));
}
try (InputStream in =
new ByteArrayInputStream(data.toByteArray())) {
inspectModuleInfoClassFile(in,
currentVersionModules, desc.version);
} catch (IOException | ConstantPoolException ex) {
throw new IllegalStateException(ex);
}
classFileData.add(data.toByteArray());
}
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
ExcludeIncludeList currentEIList = excludesIncludes;
loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version);
}
if (!currentVersionModules.isEmpty()) {
Set<String> includes = new HashSet<>();
List<PlatformInput> platforms =
versions.stream()
.map(desc -> new PlatformInput(desc.version,
desc.primaryBaseline,
null))
.collect(Collectors.toList());
for (ModuleDescription md : currentVersionModules.values()) {
md.header.get(0).exports.stream().map(e -> e + '/')
.forEach(includes::add);
}
dumpDescriptions(classes, modules, platforms, descDest.resolve("symbols"), args);
}
//where:
private static final String DO_NO_MODIFY =
"#\n" +
"# Copyright (c) {YEAR}, Oracle and/or its affiliates. All rights reserved.\n" +
"# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n" +
"#\n" +
"# This code is free software; you can redistribute it and/or modify it\n" +
"# under the terms of the GNU General Public License version 2 only, as\n" +
"# published by the Free Software Foundation. Oracle designates this\n" +
"# particular file as subject to the \"Classpath\" exception as provided\n" +
"# by Oracle in the LICENSE file that accompanied this code.\n" +
"#\n" +
"# This code is distributed in the hope that it will be useful, but WITHOUT\n" +
"# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n" +
"# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n" +
"# version 2 for more details (a copy is included in the LICENSE file that\n" +
"# accompanied this code).\n" +
"#\n" +
"# You should have received a copy of the GNU General Public License version\n" +
"# 2 along with this work; if not, write to the Free Software Foundation,\n" +
"# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n" +
"#\n" +
"# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n" +
"# or visit www.oracle.com if you need additional information or have any\n" +
"# questions.\n" +
"#\n" +
"# ##########################################################\n" +
"# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ###\n" +
"# ##########################################################\n" +
"#\n";
currentEIList = new ExcludeIncludeList(includes,
Collections.emptySet());
private void loadVersionClasses(ClassList classes,
Map<String, ModuleDescription> modules,
Iterable<byte[]> classData,
ExcludeIncludeList excludesIncludes,
String version) {
Map<String, ModuleDescription> currentVersionModules =
new HashMap<>();
for (byte[] classFileData : classData) {
try (InputStream in = new ByteArrayInputStream(classFileData)) {
inspectModuleInfoClassFile(in,
currentVersionModules, version);
} catch (IOException | ConstantPoolException ex) {
throw new IllegalStateException(ex);
}
}
ExcludeIncludeList currentEIList = excludesIncludes;
if (!currentVersionModules.isEmpty()) {
Set<String> includes = new HashSet<>();
for (ModuleDescription md : currentVersionModules.values()) {
md.header.get(0).exports.stream().map(e -> e + '/')
.forEach(includes::add);
}
ClassList currentVersionClasses = new ClassList();
try (BufferedReader descIn =
Files.newBufferedReader(Paths.get(desc.classes))) {
String classFileData;
currentEIList = new ExcludeIncludeList(includes,
Collections.emptySet());
}
while ((classFileData = descIn.readLine()) != null) {
ByteArrayOutputStream data = new ByteArrayOutputStream();
for (int i = 0; i < classFileData.length(); i += 2) {
String hex = classFileData.substring(i, i + 2);
data.write(Integer.parseInt(hex, 16));
}
try (InputStream in =
new ByteArrayInputStream(data.toByteArray())) {
inspectClassFile(in, currentVersionClasses,
currentEIList, desc.version);
} catch (IOException | ConstantPoolException ex) {
throw new IllegalStateException(ex);
}
}
ClassList currentVersionClasses = new ClassList();
for (byte[] classFileData : classData) {
try (InputStream in = new ByteArrayInputStream(classFileData)) {
inspectClassFile(in, currentVersionClasses,
currentEIList, version);
} catch (IOException | ConstantPoolException ex) {
throw new IllegalStateException(ex);
}
}
ModuleDescription unsupported =
currentVersionModules.get("jdk.unsupported");
ModuleDescription unsupported =
currentVersionModules.get("jdk.unsupported");
if (unsupported != null) {
for (ClassDescription cd : currentVersionClasses.classes) {
if (unsupported.header
.get(0)
.exports
.contains(cd.packge().replace('.', '/'))) {
ClassHeaderDescription ch = cd.header.get(0);
if (ch.classAnnotations == null) {
ch.classAnnotations = new ArrayList<>();
}
AnnotationDescription ad;
ad = new AnnotationDescription(PROPERITARY_ANNOTATION,
Collections.emptyMap());
ch.classAnnotations.add(ad);
if (unsupported != null) {
for (ClassDescription cd : currentVersionClasses.classes) {
if (unsupported.header
.get(0)
.exports
.contains(cd.packge().replace('.', '/'))) {
ClassHeaderDescription ch = cd.header.get(0);
if (ch.classAnnotations == null) {
ch.classAnnotations = new ArrayList<>();
}
}
}
Set<String> includedClasses = new HashSet<>();
boolean modified;
do {
modified = false;
for (ClassDescription clazz : currentVersionClasses) {
ClassHeaderDescription header = clazz.header.get(0);
if (includeEffectiveAccess(currentVersionClasses, clazz)) {
modified |= include(includedClasses, currentVersionClasses, clazz.name);
}
if (includedClasses.contains(clazz.name)) {
modified |= include(includedClasses, currentVersionClasses, header.extendsAttr);
for (String i : header.implementsAttr) {
modified |= include(includedClasses, currentVersionClasses, i);
}
modified |= includeOutputType(Collections.singleton(header),
h -> "",
includedClasses,
currentVersionClasses);
modified |= includeOutputType(clazz.fields,
f -> f.descriptor,
includedClasses,
currentVersionClasses);
modified |= includeOutputType(clazz.methods,
m -> m.descriptor,
includedClasses,
currentVersionClasses);
}
}
} while (modified);
for (ClassDescription clazz : currentVersionClasses) {
if (!includedClasses.contains(clazz.name)) {
continue;
}
ClassHeaderDescription header = clazz.header.get(0);
if (header.innerClasses != null) {
Iterator<InnerClassInfo> innerClassIt = header.innerClasses.iterator();
while(innerClassIt.hasNext()) {
InnerClassInfo ici = innerClassIt.next();
if (!includedClasses.contains(ici.innerClass))
innerClassIt.remove();
}
}
ClassDescription existing = classes.find(clazz.name, true);
if (existing != null) {
addClassHeader(existing, header, desc.version);
for (MethodDescription currentMethod : clazz.methods) {
addMethod(existing, currentMethod, desc.version);
}
for (FieldDescription currentField : clazz.fields) {
addField(existing, currentField, desc.version);
}
} else {
classes.add(clazz);
}
}
for (ModuleDescription module : currentVersionModules.values()) {
ModuleHeaderDescription header = module.header.get(0);
if (header.innerClasses != null) {
Iterator<InnerClassInfo> innerClassIt =
header.innerClasses.iterator();
while(innerClassIt.hasNext()) {
InnerClassInfo ici = innerClassIt.next();
if (!includedClasses.contains(ici.innerClass))
innerClassIt.remove();
}
}
ModuleDescription existing = modules.get(module.name);
if (existing != null) {
addModuleHeader(existing, header, desc.version);
} else {
modules.put(module.name, module);
AnnotationDescription ad;
ad = new AnnotationDescription(PROPERITARY_ANNOTATION,
Collections.emptyMap());
ch.classAnnotations.add(ad);
}
}
}
Set<String> includedClasses = new HashSet<>();
boolean modified;
do {
modified = false;
for (ClassDescription clazz : currentVersionClasses) {
ClassHeaderDescription header = clazz.header.get(0);
if (includeEffectiveAccess(currentVersionClasses, clazz)) {
modified |= include(includedClasses, currentVersionClasses, clazz.name);
}
if (includedClasses.contains(clazz.name)) {
modified |= include(includedClasses, currentVersionClasses, header.extendsAttr);
for (String i : header.implementsAttr) {
modified |= include(includedClasses, currentVersionClasses, i);
}
modified |= includeOutputType(Collections.singleton(header),
h -> "",
includedClasses,
currentVersionClasses);
modified |= includeOutputType(clazz.fields,
f -> f.descriptor,
includedClasses,
currentVersionClasses);
modified |= includeOutputType(clazz.methods,
m -> m.descriptor,
includedClasses,
currentVersionClasses);
}
}
} while (modified);
for (ClassDescription clazz : currentVersionClasses) {
if (!includedClasses.contains(clazz.name)) {
continue;
}
ClassHeaderDescription header = clazz.header.get(0);
if (header.innerClasses != null) {
Iterator<InnerClassInfo> innerClassIt = header.innerClasses.iterator();
while(innerClassIt.hasNext()) {
InnerClassInfo ici = innerClassIt.next();
if (!includedClasses.contains(ici.innerClass))
innerClassIt.remove();
}
}
ClassDescription existing = classes.find(clazz.name, true);
if (existing != null) {
addClassHeader(existing, header, version);
for (MethodDescription currentMethod : clazz.methods) {
addMethod(existing, currentMethod, version);
}
for (FieldDescription currentField : clazz.fields) {
addField(existing, currentField, version);
}
} else {
classes.add(clazz);
}
}
for (ModuleDescription module : currentVersionModules.values()) {
ModuleHeaderDescription header = module.header.get(0);
if (header.innerClasses != null) {
Iterator<InnerClassInfo> innerClassIt =
header.innerClasses.iterator();
while(innerClassIt.hasNext()) {
InnerClassInfo ici = innerClassIt.next();
if (!includedClasses.contains(ici.innerClass))
innerClassIt.remove();
}
}
ModuleDescription existing = modules.get(module.name);
if (existing != null) {
addModuleHeader(existing, header, version);
} else {
modules.put(module.name, module);
}
}
}
//where:
private static final String PROPERITARY_ANNOTATION =
"Lsun/Proprietary+Annotation;";
private void dumpDescriptions(ClassList classes,
Map<String, ModuleDescription> modules,
List<PlatformInput> versions,
Path ctDescriptionFile,
String[] args) throws IOException {
classes.sort();
Map<String, String> package2Modules = new HashMap<>();
@ -1298,46 +1399,52 @@ public class CreateSymbols {
.filter(m -> !module2Classes.containsKey(m))
.forEach(m -> module2Classes.put(m, Collections.emptyList()));
Path symbolsFile = descDest.resolve("symbols");
Files.createDirectories(ctDescriptionFile.getParent());
Files.createDirectories(symbolsFile.getParent());
int year = Calendar.getInstance(TimeZone.getTimeZone("UTF"), Locale.ROOT)
.get(Calendar.YEAR);
try (Writer symbolsOut = Files.newBufferedWriter(symbolsFile)) {
Map<VersionDescription, List<Path>> outputFiles = new LinkedHashMap<>();
try (Writer symbolsOut = Files.newBufferedWriter(ctDescriptionFile)) {
Map<PlatformInput, List<String>> outputFiles = new LinkedHashMap<>();
for (Entry<String, List<ClassDescription>> e : module2Classes.entrySet()) {
for (VersionDescription desc : versions) {
StringWriter data = new StringWriter();
ModuleDescription module = modules.get(e.getKey());
for (PlatformInput desc : versions) {
List<String> files = desc.files;
module.write(data, desc.primaryBaseline, desc.version);
if (files == null) {
files = new ArrayList<>();
for (Entry<String, List<ClassDescription>> e : module2Classes.entrySet()) {
StringWriter data = new StringWriter();
ModuleDescription module = modules.get(e.getKey());
for (ClassDescription clazz : e.getValue()) {
clazz.write(data, desc.primaryBaseline, desc.version);
}
module.write(data, desc.basePlatform, desc.version);
Path f = descDest.resolve(e.getKey() + "-" + desc.version + ".sym.txt");
String dataString = data.toString();
if (!dataString.isEmpty()) {
try (Writer out = Files.newBufferedWriter(f)) {
out.append(DO_NO_MODIFY);
out.write(dataString);
for (ClassDescription clazz : e.getValue()) {
clazz.write(data, desc.basePlatform, desc.version);
}
outputFiles.computeIfAbsent(desc, d -> new ArrayList<>())
.add(f);
String fileName = e.getKey() + "-" + desc.version + ".sym.txt";
Path f = ctDescriptionFile.getParent().resolve(fileName);
String dataString = data.toString();
if (!dataString.isEmpty()) {
try (Writer out = Files.newBufferedWriter(f)) {
out.append(DO_NO_MODIFY.replace("{YEAR}", String.valueOf(year)));
out.write(dataString);
}
files.add(f.getFileName().toString());
}
}
}
outputFiles.put(desc, files);
}
symbolsOut.append(DO_NO_MODIFY);
symbolsOut.append(DO_NO_MODIFY.replace("{YEAR}", "2015, " + year));
symbolsOut.append("#command used to generate this file:\n");
symbolsOut.append("#")
.append(CreateSymbols.class.getName())
.append(" ")
.append(Arrays.asList(args)
.stream()
.append(Arrays.stream(args)
.collect(Collectors.joining(" ")))
.append("\n");
symbolsOut.append("#\n");
@ -1347,31 +1454,102 @@ public class CreateSymbols {
.sorted()
.collect(Collectors.joining(":")))
.append("\n");
for (Entry<VersionDescription, List<Path>> versionFileEntry : outputFiles.entrySet()) {
for (Entry<PlatformInput, List<String>> versionFileEntry : outputFiles.entrySet()) {
symbolsOut.append("platform version ")
.append(versionFileEntry.getKey().version);
if (versionFileEntry.getKey().primaryBaseline != null) {
if (versionFileEntry.getKey().basePlatform != null) {
symbolsOut.append(" base ")
.append(versionFileEntry.getKey().primaryBaseline);
.append(versionFileEntry.getKey().basePlatform);
}
symbolsOut.append(" files ")
.append(versionFileEntry.getValue()
.stream()
.map(p -> p.getFileName().toString())
.map(p -> p)
.sorted()
.collect(Collectors.joining(":")))
.append("\n");
}
}
}
public void createIncrementalBaseLine(String ctDescriptionFile,
String excludeFile,
String[] args) throws IOException {
String specVersion = System.getProperty("java.specification.version");
String currentVersion =
Integer.toString(Integer.parseInt(specVersion), Character.MAX_RADIX);
currentVersion = currentVersion.toUpperCase(Locale.ROOT);
Path ctDescriptionPath = Paths.get(ctDescriptionFile).toAbsolutePath();
LoadDescriptions data = load(ctDescriptionPath, currentVersion);
ClassList classes = data.classes;
Map<String, ModuleDescription> modules = data.modules;
List<PlatformInput> versions = data.versions;
ExcludeIncludeList excludeList =
ExcludeIncludeList.create(excludeFile);
Iterable<byte[]> classBytes = dumpCurrentClasses();
loadVersionClasses(classes, modules, classBytes, excludeList, currentVersion);
String baseline;
if (versions.isEmpty()) {
baseline = null;
} else {
baseline = versions.stream()
.sorted((v1, v2) -> v2.version.compareTo(v1.version))
.findFirst()
.get()
.version;
}
versions.add(new PlatformInput(currentVersion, baseline, null));
dumpDescriptions(classes, modules, versions, ctDescriptionPath, args);
}
private List<byte[]> dumpCurrentClasses() throws IOException {
JavacTool tool = JavacTool.create();
Context ctx = new Context();
String version = System.getProperty("java.specification.version");
JavacTask task = tool.getTask(null, null, null,
List.of("--release", version),
null, null, ctx);
task.getElements().getTypeElement("java.lang.Object");
JavaFileManager fm = ctx.get(JavaFileManager.class);
List<byte[]> data = new ArrayList<>();
for (Location modLoc : LOCATIONS) {
for (Set<JavaFileManager.Location> module :
fm.listLocationsForModules(modLoc)) {
for (JavaFileManager.Location loc : module) {
Iterable<JavaFileObject> files =
fm.list(loc,
"",
EnumSet.of(Kind.CLASS),
true);
for (JavaFileObject jfo : files) {
try (InputStream is = jfo.openInputStream();
InputStream in =
new BufferedInputStream(is)) {
ByteArrayOutputStream baos =
new ByteArrayOutputStream();
in.transferTo(baos);
data.add(baos.toByteArray());
}
}
}
}
}
return data;
}
//where:
private static final String DO_NO_MODIFY =
"# ##########################################################\n" +
"# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ###\n" +
"# ##########################################################\n" +
"#\n";
private static final String PROPERITARY_ANNOTATION =
"Lsun/Proprietary+Annotation;";
private static final List<StandardLocation> LOCATIONS =
List.of(StandardLocation.SYSTEM_MODULES,
StandardLocation.UPGRADE_MODULE_PATH);
//<editor-fold defaultstate="collapsed" desc="Class Reading">
//non-final for tests:
@ -2006,11 +2184,11 @@ public class CreateSymbols {
signature = reader.attributes.get("signature");
String inClassAnnotations = reader.attributes.get("classAnnotations");
if (inClassAnnotations != null) {
classAnnotations = parseAnnotations(unquote(inClassAnnotations), new int[1]);
classAnnotations = parseAnnotations(inClassAnnotations, new int[1]);
}
String inRuntimeAnnotations = reader.attributes.get("runtimeAnnotations");
if (inRuntimeAnnotations != null) {
runtimeAnnotations = parseAnnotations(unquote(inRuntimeAnnotations), new int[1]);
runtimeAnnotations = parseAnnotations(inRuntimeAnnotations, new int[1]);
}
}
@ -2115,6 +2293,7 @@ public class CreateSymbols {
ModuleHeaderDescription mhd =
new ModuleHeaderDescription();
mhd.read(reader);
mhd.name = name;
mhd.versions = version;
header.add(mhd);
break;
@ -2695,7 +2874,11 @@ public class CreateSymbols {
name = reader.attributes.get("name");
descriptor = reader.attributes.get("descriptor");
thrownTypes = deserializeList(reader.attributes.get("thrownTypes"));
String thrownTypesValue = reader.attributes.get("thrownTypes");
if (thrownTypesValue != null) {
thrownTypes = deserializeList(thrownTypesValue);
}
String inAnnotationDefaultValue = reader.attributes.get("annotationDefaultValue");
@ -2803,9 +2986,9 @@ public class CreateSymbols {
if (inConstantValue != null) {
switch (descriptor) {
case "Z": constantValue = "true".equals(inConstantValue); break;
case "B": constantValue = Byte.parseByte(inConstantValue); break;
case "B": constantValue = Integer.parseInt(inConstantValue); break;
case "C": constantValue = inConstantValue.charAt(0); break;
case "S": constantValue = Short.parseShort(inConstantValue); break;
case "S": constantValue = Integer.parseInt(inConstantValue); break;
case "I": constantValue = Integer.parseInt(inConstantValue); break;
case "J": constantValue = Long.parseLong(inConstantValue); break;
case "F": constantValue = Float.parseFloat(inConstantValue); break;
@ -3141,7 +3324,7 @@ public class CreateSymbols {
serialized = unquote ? unquote(serialized) : serialized;
if (serialized == null)
return new ArrayList<>();
return new ArrayList<>(Arrays.asList(serialized.split(",")));
return new ArrayList<>(List.of(serialized.split(",")));
}
private static String quote(String value, boolean quoteQuotes) {
@ -3291,7 +3474,7 @@ public class CreateSymbols {
}
switch (args[0]) {
case "build-description":
case "build-description": {
if (args.length < 3) {
help();
return ;
@ -3332,6 +3515,16 @@ public class CreateSymbols {
descDest,
args);
break;
}
case "build-description-incremental": {
if (args.length != 3) {
help();
return ;
}
new CreateSymbols().createIncrementalBaseLine(args[1], args[2], args);
break;
}
case "build-ctsym":
if (args.length != 3) {
help();