207 //<editor-fold defaultstate="collapsed" desc="ct.sym construction"> |
207 //<editor-fold defaultstate="collapsed" desc="ct.sym construction"> |
208 /**Create sig files for ct.sym reading the classes description from the directory that contains |
208 /**Create sig files for ct.sym reading the classes description from the directory that contains |
209 * {@code ctDescriptionFile}, using the file as a recipe to create the sigfiles. |
209 * {@code ctDescriptionFile}, using the file as a recipe to create the sigfiles. |
210 */ |
210 */ |
211 @SuppressWarnings("unchecked") |
211 @SuppressWarnings("unchecked") |
212 public void createSymbols(String ctDescriptionFileExtra, String ctDescriptionFile, String ctSymLocation, CtSymKind ctSymKind) throws IOException { |
212 public void createSymbols(String ctDescriptionFileExtra, String ctDescriptionFile, String ctSymLocation) throws IOException { |
213 LoadDescriptions data = load(ctDescriptionFileExtra != null ? Paths.get(ctDescriptionFileExtra) |
213 LoadDescriptions data = load(ctDescriptionFileExtra != null ? Paths.get(ctDescriptionFileExtra) |
214 : null, |
214 : null, |
215 Paths.get(ctDescriptionFile), null); |
215 Paths.get(ctDescriptionFile), null); |
216 |
216 |
217 splitHeaders(data.classes); |
217 splitHeaders(data.classes); |
|
218 |
|
219 Map<String, Map<Character, String>> package2Version2Module = new HashMap<>(); |
218 |
220 |
219 for (ModuleDescription md : data.modules.values()) { |
221 for (ModuleDescription md : data.modules.values()) { |
220 for (ModuleHeaderDescription mhd : md.header) { |
222 for (ModuleHeaderDescription mhd : md.header) { |
221 List<String> versionsList = |
223 List<String> versionsList = |
222 Collections.singletonList(mhd.versions); |
224 Collections.singletonList(mhd.versions); |
223 writeModulesForVersions(ctSymLocation, |
225 writeModulesForVersions(ctSymLocation, |
224 md, |
226 md, |
225 mhd, |
227 mhd, |
226 versionsList); |
228 versionsList); |
|
229 mhd.exports.stream().forEach(pkg -> { |
|
230 for (char v : mhd.versions.toCharArray()) { |
|
231 package2Version2Module.computeIfAbsent(pkg, dummy -> new HashMap<>()).put(v, md.name); |
|
232 } |
|
233 }); |
227 } |
234 } |
228 } |
235 } |
229 |
236 |
230 for (ClassDescription classDescription : data.classes) { |
237 for (ClassDescription classDescription : data.classes) { |
|
238 Map<Character, String> version2Module = package2Version2Module.getOrDefault(classDescription.packge().replace('.', '/'), Collections.emptyMap()); |
231 for (ClassHeaderDescription header : classDescription.header) { |
239 for (ClassHeaderDescription header : classDescription.header) { |
232 switch (ctSymKind) { |
240 Set<String> jointVersions = new HashSet<>(); |
233 case JOINED_VERSIONS: |
241 jointVersions.add(header.versions); |
234 Set<String> jointVersions = new HashSet<>(); |
242 limitJointVersion(jointVersions, classDescription.fields); |
235 jointVersions.add(header.versions); |
243 limitJointVersion(jointVersions, classDescription.methods); |
236 limitJointVersion(jointVersions, classDescription.fields); |
244 Map<String, StringBuilder> module2Versions = new HashMap<>(); |
237 limitJointVersion(jointVersions, classDescription.methods); |
245 for (char v : header.versions.toCharArray()) { |
238 writeClassesForVersions(ctSymLocation, classDescription, header, jointVersions); |
246 String module = version2Module.get(v); |
239 break; |
247 if (module == null) { |
240 case SEPARATE: |
248 if (v >= '9') { |
241 Set<String> versions = new HashSet<>(); |
249 throw new AssertionError("No module for " + classDescription.name + |
242 for (char v : header.versions.toCharArray()) { |
250 " and version " + v); |
243 versions.add("" + v); |
|
244 } |
251 } |
245 writeClassesForVersions(ctSymLocation, classDescription, header, versions); |
252 module = version2Module.get('9'); |
246 break; |
253 if (module == null) { |
|
254 module = "java.base"; |
|
255 } |
|
256 } |
|
257 module2Versions.computeIfAbsent(module, dummy -> new StringBuilder()).append(v); |
|
258 } |
|
259 for (Entry<String, StringBuilder> e : module2Versions.entrySet()) { |
|
260 Set<String> currentVersions = new HashSet<>(jointVersions); |
|
261 limitJointVersion(currentVersions, e.getValue().toString()); |
|
262 currentVersions = currentVersions.stream().filter(vers -> !disjoint(vers, e.getValue().toString())).collect(Collectors.toSet()); |
|
263 writeClassesForVersions(ctSymLocation, classDescription, header, e.getKey(), currentVersions); |
247 } |
264 } |
248 } |
265 } |
249 } |
266 } |
250 } |
267 } |
251 |
268 |
601 } |
618 } |
602 } |
619 } |
603 |
620 |
604 void limitJointVersion(Set<String> jointVersions, List<? extends FeatureDescription> features) { |
621 void limitJointVersion(Set<String> jointVersions, List<? extends FeatureDescription> features) { |
605 for (FeatureDescription feature : features) { |
622 for (FeatureDescription feature : features) { |
606 for (String version : jointVersions) { |
623 limitJointVersion(jointVersions, feature.versions); |
607 if (!containsAll(feature.versions, version) && |
624 } |
608 !disjoint(feature.versions, version)) { |
625 } |
609 StringBuilder featurePart = new StringBuilder(); |
626 |
610 StringBuilder otherPart = new StringBuilder(); |
627 void limitJointVersion(Set<String> jointVersions, String versions) { |
611 for (char v : version.toCharArray()) { |
628 for (String version : jointVersions) { |
612 if (feature.versions.indexOf(v) != (-1)) { |
629 if (!containsAll(versions, version) && |
613 featurePart.append(v); |
630 !disjoint(versions, version)) { |
614 } else { |
631 StringBuilder featurePart = new StringBuilder(); |
615 otherPart.append(v); |
632 StringBuilder otherPart = new StringBuilder(); |
616 } |
633 for (char v : version.toCharArray()) { |
|
634 if (versions.indexOf(v) != (-1)) { |
|
635 featurePart.append(v); |
|
636 } else { |
|
637 otherPart.append(v); |
617 } |
638 } |
618 jointVersions.remove(version); |
639 } |
619 if (featurePart.length() == 0 || otherPart.length() == 0) { |
640 jointVersions.remove(version); |
620 throw new AssertionError(); |
641 if (featurePart.length() == 0 || otherPart.length() == 0) { |
621 } |
642 throw new AssertionError(); |
622 jointVersions.add(featurePart.toString()); |
643 } |
623 jointVersions.add(otherPart.toString()); |
644 jointVersions.add(featurePart.toString()); |
624 break; |
645 jointVersions.add(otherPart.toString()); |
625 } |
646 break; |
626 } |
647 } |
627 } |
648 } |
628 } |
649 } |
629 |
650 |
630 private static boolean containsAll(String versions, String subVersions) { |
651 private static boolean containsAll(String versions, String subVersions) { |
644 } |
665 } |
645 |
666 |
646 void writeClassesForVersions(String ctSymLocation, |
667 void writeClassesForVersions(String ctSymLocation, |
647 ClassDescription classDescription, |
668 ClassDescription classDescription, |
648 ClassHeaderDescription header, |
669 ClassHeaderDescription header, |
|
670 String module, |
649 Iterable<String> versions) |
671 Iterable<String> versions) |
650 throws IOException { |
672 throws IOException { |
651 for (String ver : versions) { |
673 for (String ver : versions) { |
652 writeClass(ctSymLocation, classDescription, header, ver); |
674 writeClass(ctSymLocation, classDescription, header, module, ver); |
653 } |
675 } |
654 } |
676 } |
655 |
677 |
656 void writeModulesForVersions(String ctSymLocation, |
678 void writeModulesForVersions(String ctSymLocation, |
657 ModuleDescription moduleDescription, |
679 ModuleDescription moduleDescription, |
711 } |
728 } |
712 |
729 |
713 void writeClass(String ctSymLocation, |
730 void writeClass(String ctSymLocation, |
714 ClassDescription classDescription, |
731 ClassDescription classDescription, |
715 ClassHeaderDescription header, |
732 ClassHeaderDescription header, |
|
733 String module, |
716 String version) throws IOException { |
734 String version) throws IOException { |
717 List<CPInfo> constantPool = new ArrayList<>(); |
735 List<CPInfo> constantPool = new ArrayList<>(); |
718 constantPool.add(null); |
736 constantPool.add(null); |
719 List<Method> methods = new ArrayList<>(); |
737 List<Method> methods = new ArrayList<>(); |
720 for (MethodDescription methDesc : classDescription.methods) { |
738 for (MethodDescription methDesc : classDescription.methods) { |
763 interfaces, |
781 interfaces, |
764 fields.toArray(new Field[0]), |
782 fields.toArray(new Field[0]), |
765 methods.toArray(new Method[0]), |
783 methods.toArray(new Method[0]), |
766 attributes); |
784 attributes); |
767 |
785 |
768 Path outputClassFile = Paths.get(ctSymLocation, version, classDescription.name + EXTENSION); |
786 Path outputClassFile = Paths.get(ctSymLocation, version); |
|
787 |
|
788 if (module != null) { |
|
789 outputClassFile = outputClassFile.resolve(module); |
|
790 } |
|
791 |
|
792 outputClassFile = outputClassFile.resolve(classDescription.name + EXTENSION); |
769 |
793 |
770 Files.createDirectories(outputClassFile.getParent()); |
794 Files.createDirectories(outputClassFile.getParent()); |
771 |
795 |
772 try (OutputStream out = Files.newOutputStream(outputClassFile)) { |
796 try (OutputStream out = Files.newOutputStream(outputClassFile)) { |
773 ClassWriter w = new ClassWriter(); |
797 ClassWriter w = new ClassWriter(); |