--- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java Mon May 07 08:56:35 2018 +0200
+++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java Mon May 07 10:37:46 2018 +0200
@@ -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
.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.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.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.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 @@
* 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 @@
*/
@SuppressWarnings("unchecked")
public void createSymbols(String ctDescriptionFile, String ctSymLocation, CtSymKind ctSymKind) throws IOException {
- Pair<ClassList, List<ModuleDescription>> data = load(Paths.get(ctDescriptionFile));
-
- splitHeaders(data.fst);
-
- for (ModuleDescription md : data.snd) {
+ LoadDescriptions data = load(Paths.get(ctDescriptionFile), null);
+
+ splitHeaders(data.classes);
+
+ for (ModuleDescription md : data.modules.values()) {
for (ModuleHeaderDescription mhd : md.header) {
List<String> versionsList =
Collections.singletonList(mhd.versions);
@@ -195,7 +213,7 @@
}
}
- 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 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 @@
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 @@
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 @@
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 @@
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 @@
continue;
}
- moduleList.add(desc);
+ moduleList.put(desc.name, desc);
}
- return Pair.of(result, moduleList);
+ 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;
+ }
+
}
static final class LineBasedReader implements AutoCloseable {
@@ -423,7 +471,7 @@
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 @@
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 @@
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);
- 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);
- }
- }
- }
-
- 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);
- }
-
- currentEIList = new ExcludeIncludeList(includes,
- Collections.emptySet());
- }
-
- ClassList currentVersionClasses = new ClassList();
- try (BufferedReader descIn =
- Files.newBufferedReader(Paths.get(desc.classes))) {
- String classFileData;
-
- 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);
+ 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())) {
- inspectClassFile(in, currentVersionClasses,
- currentEIList, desc.version);
- } catch (IOException | ConstantPoolException ex) {
- throw new IllegalStateException(ex);
- }
+ classFileData.add(data.toByteArray());
}
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
}
- 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);
- }
- }
+ loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version);
+ }
+
+ List<PlatformInput> platforms =
+ versions.stream()
+ .map(desc -> new PlatformInput(desc.version,
+ desc.primaryBaseline,
+ null))
+ .collect(Collectors.toList());
+
+ 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";
+
+ 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);
}
-
- 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);
+ }
+
+ 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);
+ }
+
+ currentEIList = new ExcludeIncludeList(includes,
+ Collections.emptySet());
+ }
+
+ 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");
+
+ 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<>();
}
-
- 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 @@
.filter(m -> !module2Classes.containsKey(m))
.forEach(m -> module2Classes.put(m, Collections.emptyList()));
- Path symbolsFile = descDest.resolve("symbols");
-
- Files.createDirectories(symbolsFile.getParent());
-
- try (Writer symbolsOut = Files.newBufferedWriter(symbolsFile)) {
- Map<VersionDescription, List<Path>> 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());
-
- module.write(data, desc.primaryBaseline, desc.version);
-
- for (ClassDescription clazz : e.getValue()) {
- clazz.write(data, desc.primaryBaseline, 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);
+ Files.createDirectories(ctDescriptionFile.getParent());
+
+ int year = Calendar.getInstance(TimeZone.getTimeZone("UTF"), Locale.ROOT)
+ .get(Calendar.YEAR);
+
+ try (Writer symbolsOut = Files.newBufferedWriter(ctDescriptionFile)) {
+ Map<PlatformInput, List<String>> outputFiles = new LinkedHashMap<>();
+
+ for (PlatformInput desc : versions) {
+ List<String> files = desc.files;
+
+ if (files == null) {
+ files = new ArrayList<>();
+ for (Entry<String, List<ClassDescription>> e : module2Classes.entrySet()) {
+ StringWriter data = new StringWriter();
+ ModuleDescription module = modules.get(e.getKey());
+
+ module.write(data, desc.basePlatform, desc.version);
+
+ 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 @@
.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 @@
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 @@
ModuleHeaderDescription mhd =
new ModuleHeaderDescription();
mhd.read(reader);
+ mhd.name = name;
mhd.versions = version;
header.add(mhd);
break;
@@ -2695,7 +2874,11 @@
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 @@
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 @@
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 @@
}
switch (args[0]) {
- case "build-description":
+ case "build-description": {
if (args.length < 3) {
help();
return ;
@@ -3332,6 +3515,16 @@
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();