Loading packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java +119 −40 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.zip.GZIPInputStream; /** Loading @@ -54,6 +56,7 @@ class LicenseHtmlGeneratorFromXml { private static final String TAG_FILE_NAME = "file-name"; private static final String TAG_FILE_CONTENT = "file-content"; private static final String ATTR_CONTENT_ID = "contentId"; private static final String ATTR_LIBRARY_NAME = "lib"; private static final String HTML_HEAD_STRING = "<html><head>\n" Loading @@ -67,8 +70,12 @@ class LicenseHtmlGeneratorFromXml { + "</style>\n" + "</head>" + "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n" + "<div class=\"toc\">\n" + "<ul>"; + "<div class=\"toc\">\n"; private static final String LIBRARY_HEAD_STRING = "<strong>Libraries</strong>\n<ul class=\"libraries\">"; private static final String LIBRARY_TAIL_STRING = "</ul>\n<strong>Files</strong>"; private static final String FILES_HEAD_STRING = "<ul class=\"files\">"; private static final String HTML_MIDDLE_STRING = "</ul>\n" Loading @@ -81,12 +88,14 @@ class LicenseHtmlGeneratorFromXml { private final List<File> mXmlFiles; /* * A map from a file name to a content id (MD5 sum of file content) for its license. * For example, "/system/priv-app/TeleService/TeleService.apk" maps to * A map from a file name to a library name (may be empty) to a content id (MD5 sum of file * content) for its license. * For example, "/system/priv-app/TeleService/TeleService.apk" maps to "service/Telephony" to * "9645f39e9db895a4aa6e02cb57294595". Here "9645f39e9db895a4aa6e02cb57294595" is a MD5 sum * of the content of packages/services/Telephony/MODULE_LICENSE_APACHE2. */ private final Map<String, Set<String>> mFileNameToContentIdMap = new HashMap(); private final Map<String, Map<String, Set<String>>> mFileNameToLibraryToContentIdMap = new HashMap(); /* * A map from a content id (MD5 sum of file content) to a license file content. Loading @@ -98,7 +107,7 @@ class LicenseHtmlGeneratorFromXml { static class ContentIdAndFileNames { final String mContentId; final List<String> mFileNameList = new ArrayList(); final Map<String, List<String>> mLibraryToFileNameMap = new TreeMap(); ContentIdAndFileNames(String contentId) { mContentId = contentId; Loading @@ -120,7 +129,7 @@ class LicenseHtmlGeneratorFromXml { parse(xmlFile); } if (mFileNameToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) { if (mFileNameToLibraryToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) { return false; } Loading @@ -128,7 +137,7 @@ class LicenseHtmlGeneratorFromXml { try { writer = new PrintWriter(outputFile); generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer, generateHtml(mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap, writer, noticeHeader); writer.flush(); Loading Loading @@ -157,7 +166,7 @@ class LicenseHtmlGeneratorFromXml { in = new FileReader(xmlFile); } parse(in, mFileNameToContentIdMap, mContentIdToFileContentMap); parse(in, mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap); in.close(); } catch (XmlPullParserException | IOException e) { Loading @@ -180,7 +189,8 @@ class LicenseHtmlGeneratorFromXml { * * <licenses> * <file-name contentId="content_id_of_license1">file1</file-name> * <file-name contentId="content_id_of_license2">file2</file-name> * <file-name contentId="content_id_of_license2" lib="name of library">file2</file-name> * <file-name contentId="content_id_of_license2" lib="another library">file2</file-name> * ... * <file-content contentId="content_id_of_license1">license1 file contents</file-content> * <file-content contentId="content_id_of_license2">license2 file contents</file-content> Loading @@ -188,10 +198,12 @@ class LicenseHtmlGeneratorFromXml { * </licenses> */ @VisibleForTesting static void parse(InputStreamReader in, Map<String, Set<String>> outFileNameToContentIdMap, static void parse(InputStreamReader in, Map<String, Map<String, Set<String>>> outFileNameToLibraryToContentIdMap, Map<String, String> outContentIdToFileContentMap) throws XmlPullParserException, IOException { Map<String, Set<String>> fileNameToContentIdMap = new HashMap<String, Set<String>>(); Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<String, Map<String, Set<String>>>(); Map<String, String> contentIdToFileContentMap = new HashMap<String, String>(); XmlPullParser parser = Xml.newPullParser(); Loading @@ -205,12 +217,15 @@ class LicenseHtmlGeneratorFromXml { if (state == XmlPullParser.START_TAG) { if (TAG_FILE_NAME.equals(parser.getName())) { String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID); String libraryName = parser.getAttributeValue("", ATTR_LIBRARY_NAME); if (!TextUtils.isEmpty(contentId)) { String fileName = readText(parser).trim(); if (!TextUtils.isEmpty(fileName)) { Set<String> contentIds = fileNameToContentIdMap.computeIfAbsent( fileName, k -> new HashSet<>()); Map<String, Set<String>> libs = fileNameToLibraryToContentIdMap.computeIfAbsent( fileName, k -> new HashMap<>()); Set<String> contentIds = libs.computeIfAbsent( libraryName, k -> new HashSet<>()); contentIds.add(contentId); } } Loading @@ -229,13 +244,19 @@ class LicenseHtmlGeneratorFromXml { state = parser.next(); } for (Map.Entry<String, Set<String>> entry : fileNameToContentIdMap.entrySet()) { outFileNameToContentIdMap.merge( entry.getKey(), entry.getValue(), (s1, s2) -> { for (Map.Entry<String, Map<String, Set<String>>> mapEntry : fileNameToLibraryToContentIdMap.entrySet()) { outFileNameToLibraryToContentIdMap.merge( mapEntry.getKey(), mapEntry.getValue(), (m1, m2) -> { for (Map.Entry<String, Set<String>> entry : m2.entrySet()) { m1.merge(entry.getKey(), entry.getValue(), (s1, s2) -> { s1.addAll(s2); return s1; }); } return m1; }); } outContentIdToFileContentMap.putAll(contentIdToFileContentMap); } Loading @@ -251,13 +272,28 @@ class LicenseHtmlGeneratorFromXml { } @VisibleForTesting static void generateHtml(Map<String, Set<String>> fileNameToContentIdMap, static void generateHtml(Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap, Map<String, String> contentIdToFileContentMap, PrintWriter writer, String noticeHeader) { List<String> fileNameList = new ArrayList(); fileNameList.addAll(fileNameToContentIdMap.keySet()); fileNameList.addAll(fileNameToLibraryToContentIdMap.keySet()); Collections.sort(fileNameList); SortedMap<String, Set<String>> libraryToContentIdMap = new TreeMap(); for (Map<String, Set<String>> libraryToContentValue : fileNameToLibraryToContentIdMap.values()) { for (Map.Entry<String, Set<String>> entry : libraryToContentValue.entrySet()) { if (TextUtils.isEmpty(entry.getKey())) { continue; } libraryToContentIdMap.merge( entry.getKey(), entry.getValue(), (s1, s2) -> { s1.addAll(s2); return s1; }); } } writer.println(HTML_HEAD_STRING); if (!TextUtils.isEmpty(noticeHeader)) { Loading @@ -268,9 +304,35 @@ class LicenseHtmlGeneratorFromXml { Map<String, Integer> contentIdToOrderMap = new HashMap(); List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList(); if (!libraryToContentIdMap.isEmpty()) { writer.println(LIBRARY_HEAD_STRING); for (Map.Entry<String, Set<String>> entry: libraryToContentIdMap.entrySet()) { String libraryName = entry.getKey(); for (String contentId : entry.getValue()) { // Assigns an id to a newly referred license file content. if (!contentIdToOrderMap.containsKey(contentId)) { contentIdToOrderMap.put(contentId, count); // An index in contentIdAndFileNamesList is the order of each element. contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId)); count++; } int id = contentIdToOrderMap.get(contentId); writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, libraryName); } } writer.println(LIBRARY_TAIL_STRING); } // Prints all the file list with a link to its license file content. for (String fileName : fileNameList) { for (String contentId : fileNameToContentIdMap.get(fileName)) { for (Map.Entry<String, Set<String>> libToContentId : fileNameToLibraryToContentIdMap.get(fileName).entrySet()) { String libraryName = libToContentId.getKey(); if (libraryName == null) { libraryName = ""; } for (String contentId : libToContentId.getValue()) { // Assigns an id to a newly referred license file content. if (!contentIdToOrderMap.containsKey(contentId)) { contentIdToOrderMap.put(contentId, count); Loading @@ -281,8 +343,17 @@ class LicenseHtmlGeneratorFromXml { } int id = contentIdToOrderMap.get(contentId); contentIdAndFileNamesList.get(id).mFileNameList.add(fileName); ContentIdAndFileNames elem = contentIdAndFileNamesList.get(id); List<String> files = elem.mLibraryToFileNameMap.computeIfAbsent( libraryName, k -> new ArrayList()); files.add(fileName); if (TextUtils.isEmpty(libraryName)) { writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName); } else { writer.format("<li><a href=\"#id%d\">%s - %s</a></li>\n", id, fileName, libraryName); } } } } Loading @@ -292,19 +363,27 @@ class LicenseHtmlGeneratorFromXml { // Prints all contents of the license files in order of id. for (ContentIdAndFileNames contentIdAndFileNames : contentIdAndFileNamesList) { writer.format("<tr id=\"id%d\"><td class=\"same-license\">\n", count); for (Map.Entry<String, List<String>> libraryFiles : contentIdAndFileNames.mLibraryToFileNameMap.entrySet()) { String libraryName = libraryFiles.getKey(); if (TextUtils.isEmpty(libraryName)) { writer.println("<div class=\"label\">Notices for file(s):</div>"); } else { writer.format("<div class=\"label\"><strong>%s</strong> used by:</div>\n", libraryName); } writer.println("<div class=\"file-list\">"); for (String fileName : contentIdAndFileNames.mFileNameList) { for (String fileName : libraryFiles.getValue()) { writer.format("%s <br/>\n", fileName); } writer.println("</div><!-- file-list -->"); count++; } writer.println("<pre class=\"license-text\">"); writer.println(contentIdToFileContentMap.get( contentIdAndFileNames.mContentId)); writer.println("</pre><!-- license-text -->"); writer.println("</td></tr><!-- same-license -->"); count++; } writer.println(HTML_REAR_STRING); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java +152 −29 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java +119 −40 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.zip.GZIPInputStream; /** Loading @@ -54,6 +56,7 @@ class LicenseHtmlGeneratorFromXml { private static final String TAG_FILE_NAME = "file-name"; private static final String TAG_FILE_CONTENT = "file-content"; private static final String ATTR_CONTENT_ID = "contentId"; private static final String ATTR_LIBRARY_NAME = "lib"; private static final String HTML_HEAD_STRING = "<html><head>\n" Loading @@ -67,8 +70,12 @@ class LicenseHtmlGeneratorFromXml { + "</style>\n" + "</head>" + "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n" + "<div class=\"toc\">\n" + "<ul>"; + "<div class=\"toc\">\n"; private static final String LIBRARY_HEAD_STRING = "<strong>Libraries</strong>\n<ul class=\"libraries\">"; private static final String LIBRARY_TAIL_STRING = "</ul>\n<strong>Files</strong>"; private static final String FILES_HEAD_STRING = "<ul class=\"files\">"; private static final String HTML_MIDDLE_STRING = "</ul>\n" Loading @@ -81,12 +88,14 @@ class LicenseHtmlGeneratorFromXml { private final List<File> mXmlFiles; /* * A map from a file name to a content id (MD5 sum of file content) for its license. * For example, "/system/priv-app/TeleService/TeleService.apk" maps to * A map from a file name to a library name (may be empty) to a content id (MD5 sum of file * content) for its license. * For example, "/system/priv-app/TeleService/TeleService.apk" maps to "service/Telephony" to * "9645f39e9db895a4aa6e02cb57294595". Here "9645f39e9db895a4aa6e02cb57294595" is a MD5 sum * of the content of packages/services/Telephony/MODULE_LICENSE_APACHE2. */ private final Map<String, Set<String>> mFileNameToContentIdMap = new HashMap(); private final Map<String, Map<String, Set<String>>> mFileNameToLibraryToContentIdMap = new HashMap(); /* * A map from a content id (MD5 sum of file content) to a license file content. Loading @@ -98,7 +107,7 @@ class LicenseHtmlGeneratorFromXml { static class ContentIdAndFileNames { final String mContentId; final List<String> mFileNameList = new ArrayList(); final Map<String, List<String>> mLibraryToFileNameMap = new TreeMap(); ContentIdAndFileNames(String contentId) { mContentId = contentId; Loading @@ -120,7 +129,7 @@ class LicenseHtmlGeneratorFromXml { parse(xmlFile); } if (mFileNameToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) { if (mFileNameToLibraryToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) { return false; } Loading @@ -128,7 +137,7 @@ class LicenseHtmlGeneratorFromXml { try { writer = new PrintWriter(outputFile); generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer, generateHtml(mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap, writer, noticeHeader); writer.flush(); Loading Loading @@ -157,7 +166,7 @@ class LicenseHtmlGeneratorFromXml { in = new FileReader(xmlFile); } parse(in, mFileNameToContentIdMap, mContentIdToFileContentMap); parse(in, mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap); in.close(); } catch (XmlPullParserException | IOException e) { Loading @@ -180,7 +189,8 @@ class LicenseHtmlGeneratorFromXml { * * <licenses> * <file-name contentId="content_id_of_license1">file1</file-name> * <file-name contentId="content_id_of_license2">file2</file-name> * <file-name contentId="content_id_of_license2" lib="name of library">file2</file-name> * <file-name contentId="content_id_of_license2" lib="another library">file2</file-name> * ... * <file-content contentId="content_id_of_license1">license1 file contents</file-content> * <file-content contentId="content_id_of_license2">license2 file contents</file-content> Loading @@ -188,10 +198,12 @@ class LicenseHtmlGeneratorFromXml { * </licenses> */ @VisibleForTesting static void parse(InputStreamReader in, Map<String, Set<String>> outFileNameToContentIdMap, static void parse(InputStreamReader in, Map<String, Map<String, Set<String>>> outFileNameToLibraryToContentIdMap, Map<String, String> outContentIdToFileContentMap) throws XmlPullParserException, IOException { Map<String, Set<String>> fileNameToContentIdMap = new HashMap<String, Set<String>>(); Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<String, Map<String, Set<String>>>(); Map<String, String> contentIdToFileContentMap = new HashMap<String, String>(); XmlPullParser parser = Xml.newPullParser(); Loading @@ -205,12 +217,15 @@ class LicenseHtmlGeneratorFromXml { if (state == XmlPullParser.START_TAG) { if (TAG_FILE_NAME.equals(parser.getName())) { String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID); String libraryName = parser.getAttributeValue("", ATTR_LIBRARY_NAME); if (!TextUtils.isEmpty(contentId)) { String fileName = readText(parser).trim(); if (!TextUtils.isEmpty(fileName)) { Set<String> contentIds = fileNameToContentIdMap.computeIfAbsent( fileName, k -> new HashSet<>()); Map<String, Set<String>> libs = fileNameToLibraryToContentIdMap.computeIfAbsent( fileName, k -> new HashMap<>()); Set<String> contentIds = libs.computeIfAbsent( libraryName, k -> new HashSet<>()); contentIds.add(contentId); } } Loading @@ -229,13 +244,19 @@ class LicenseHtmlGeneratorFromXml { state = parser.next(); } for (Map.Entry<String, Set<String>> entry : fileNameToContentIdMap.entrySet()) { outFileNameToContentIdMap.merge( entry.getKey(), entry.getValue(), (s1, s2) -> { for (Map.Entry<String, Map<String, Set<String>>> mapEntry : fileNameToLibraryToContentIdMap.entrySet()) { outFileNameToLibraryToContentIdMap.merge( mapEntry.getKey(), mapEntry.getValue(), (m1, m2) -> { for (Map.Entry<String, Set<String>> entry : m2.entrySet()) { m1.merge(entry.getKey(), entry.getValue(), (s1, s2) -> { s1.addAll(s2); return s1; }); } return m1; }); } outContentIdToFileContentMap.putAll(contentIdToFileContentMap); } Loading @@ -251,13 +272,28 @@ class LicenseHtmlGeneratorFromXml { } @VisibleForTesting static void generateHtml(Map<String, Set<String>> fileNameToContentIdMap, static void generateHtml(Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap, Map<String, String> contentIdToFileContentMap, PrintWriter writer, String noticeHeader) { List<String> fileNameList = new ArrayList(); fileNameList.addAll(fileNameToContentIdMap.keySet()); fileNameList.addAll(fileNameToLibraryToContentIdMap.keySet()); Collections.sort(fileNameList); SortedMap<String, Set<String>> libraryToContentIdMap = new TreeMap(); for (Map<String, Set<String>> libraryToContentValue : fileNameToLibraryToContentIdMap.values()) { for (Map.Entry<String, Set<String>> entry : libraryToContentValue.entrySet()) { if (TextUtils.isEmpty(entry.getKey())) { continue; } libraryToContentIdMap.merge( entry.getKey(), entry.getValue(), (s1, s2) -> { s1.addAll(s2); return s1; }); } } writer.println(HTML_HEAD_STRING); if (!TextUtils.isEmpty(noticeHeader)) { Loading @@ -268,9 +304,35 @@ class LicenseHtmlGeneratorFromXml { Map<String, Integer> contentIdToOrderMap = new HashMap(); List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList(); if (!libraryToContentIdMap.isEmpty()) { writer.println(LIBRARY_HEAD_STRING); for (Map.Entry<String, Set<String>> entry: libraryToContentIdMap.entrySet()) { String libraryName = entry.getKey(); for (String contentId : entry.getValue()) { // Assigns an id to a newly referred license file content. if (!contentIdToOrderMap.containsKey(contentId)) { contentIdToOrderMap.put(contentId, count); // An index in contentIdAndFileNamesList is the order of each element. contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId)); count++; } int id = contentIdToOrderMap.get(contentId); writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, libraryName); } } writer.println(LIBRARY_TAIL_STRING); } // Prints all the file list with a link to its license file content. for (String fileName : fileNameList) { for (String contentId : fileNameToContentIdMap.get(fileName)) { for (Map.Entry<String, Set<String>> libToContentId : fileNameToLibraryToContentIdMap.get(fileName).entrySet()) { String libraryName = libToContentId.getKey(); if (libraryName == null) { libraryName = ""; } for (String contentId : libToContentId.getValue()) { // Assigns an id to a newly referred license file content. if (!contentIdToOrderMap.containsKey(contentId)) { contentIdToOrderMap.put(contentId, count); Loading @@ -281,8 +343,17 @@ class LicenseHtmlGeneratorFromXml { } int id = contentIdToOrderMap.get(contentId); contentIdAndFileNamesList.get(id).mFileNameList.add(fileName); ContentIdAndFileNames elem = contentIdAndFileNamesList.get(id); List<String> files = elem.mLibraryToFileNameMap.computeIfAbsent( libraryName, k -> new ArrayList()); files.add(fileName); if (TextUtils.isEmpty(libraryName)) { writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName); } else { writer.format("<li><a href=\"#id%d\">%s - %s</a></li>\n", id, fileName, libraryName); } } } } Loading @@ -292,19 +363,27 @@ class LicenseHtmlGeneratorFromXml { // Prints all contents of the license files in order of id. for (ContentIdAndFileNames contentIdAndFileNames : contentIdAndFileNamesList) { writer.format("<tr id=\"id%d\"><td class=\"same-license\">\n", count); for (Map.Entry<String, List<String>> libraryFiles : contentIdAndFileNames.mLibraryToFileNameMap.entrySet()) { String libraryName = libraryFiles.getKey(); if (TextUtils.isEmpty(libraryName)) { writer.println("<div class=\"label\">Notices for file(s):</div>"); } else { writer.format("<div class=\"label\"><strong>%s</strong> used by:</div>\n", libraryName); } writer.println("<div class=\"file-list\">"); for (String fileName : contentIdAndFileNames.mFileNameList) { for (String fileName : libraryFiles.getValue()) { writer.format("%s <br/>\n", fileName); } writer.println("</div><!-- file-list -->"); count++; } writer.println("<pre class=\"license-text\">"); writer.println(contentIdToFileContentMap.get( contentIdAndFileNames.mContentId)); writer.println("</pre><!-- license-text -->"); writer.println("</td></tr><!-- same-license -->"); count++; } writer.println(HTML_REAR_STRING); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java +152 −29 File changed.Preview size limit exceeded, changes collapsed. Show changes