| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.google.gwt.soyc; |
| |
| import com.google.gwt.dev.util.Util; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| import java.util.jar.JarInputStream; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * A utility to make the top level HTTML file for one permutation. |
| */ |
| public class MakeTopLevelHtmlForPerm { |
| /** |
| * A class that specifies the URL to which a class should be linked in a size |
| * breakdown. It is always either a dependencies page, an intermediate status |
| * page that itself links to dependencies pages, or <code>null</code>. If it's |
| * <code>null</code>, then no link should be created for the class. |
| */ |
| public interface DependencyLinker { |
| String dependencyLinkForClass(String className); |
| } |
| |
| /** |
| * A {@link DependencyLinker} for exclusive fragments. It doesn't link to any |
| * dependencies. |
| */ |
| public class DependencyLinkerForExclusiveFragment implements DependencyLinker { |
| public String dependencyLinkForClass(String className) { |
| return null; |
| } |
| } |
| |
| /** |
| * A {@link DependencyLinker} for the initially downloaded code. It links into |
| * the initial dependencies. |
| */ |
| public class DependencyLinkerForInitialCode implements DependencyLinker { |
| public String dependencyLinkForClass(String className) { |
| String packageName = GlobalInformation.classToPackage.get(className); |
| assert packageName != null; |
| return dependenciesFileName("initial", packageName) + "#" + className; |
| } |
| } |
| |
| /** |
| * A {@link DependencyLinker} for the leftovers fragment. It links a class to |
| * the leftovers status page for that class. |
| * |
| */ |
| public class DependencyLinkerForLeftoversFragment implements DependencyLinker { |
| public String dependencyLinkForClass(String className) { |
| return leftoversStatusFileName(className); |
| } |
| } |
| |
| /** |
| * A dependency linker for the size breakdown of the entire program. It links |
| * each class to a general split status page describing that class. |
| */ |
| public class DependencyLinkerForTotalBreakdown implements DependencyLinker { |
| public String dependencyLinkForClass(String className) { |
| return splitStatusFileName(className); |
| } |
| } |
| |
| /** |
| * By a convention shared with the compiler, the initial download is fragment |
| * number 0. |
| */ |
| private static final int FRAGMENT_NUMBER_INITIAL_DOWNLOAD = 0; |
| |
| /** |
| * Just within this file, the convention is that the total program is fragment |
| * number -1. |
| */ |
| private static final int FRAGMENT_NUMBER_TOTAL_PROGRAM = -1; |
| |
| /** |
| * A pattern describing the name of dependency graphs for code fragments |
| * corresponding to a specific split point. These can be either exclusive |
| * fragments or fragments of code for split points in the initial load |
| * sequence. |
| */ |
| private static final Pattern PATTERN_SP_INT = Pattern.compile("sp([0-9]+)"); |
| |
| public static void copyFileOrDirectory(File srcPath, File dstPath, |
| String classPath, String inputFileName, boolean isDirectory) |
| throws IOException { |
| if (srcPath.isDirectory()) { |
| if (!dstPath.exists()) { |
| dstPath.mkdir(); |
| } |
| String files[] = srcPath.list(); |
| for (int i = 0; i < files.length; i++) { |
| copyFileOrDirectory(new File(srcPath, files[i]), new File(dstPath, |
| files[i]), classPath, inputFileName, isDirectory); |
| } |
| } else { |
| if (!srcPath.exists()) { |
| copyFileOrDirectoryFromJar(classPath, inputFileName, dstPath, |
| isDirectory); |
| } else { |
| InputStream in = new FileInputStream(srcPath); |
| OutputStream out = new FileOutputStream(dstPath); |
| // Transfer bytes from in to out |
| byte[] buf = new byte[1024]; |
| int len; |
| while ((len = in.read(buf)) > 0) { |
| out.write(buf, 0, len); |
| } |
| in.close(); |
| out.close(); |
| } |
| } |
| } |
| |
| public static void copyFileOrDirectoryFromJar(String jarFileName, |
| String inputFileName, File dstPath, boolean isDirectory) |
| throws IOException { |
| |
| JarFile jarFile = new JarFile(jarFileName); |
| if (isDirectory) { |
| dstPath.mkdir(); |
| |
| JarInputStream jarFileIS = new JarInputStream(new FileInputStream( |
| jarFileName)); |
| JarEntry jarEntry = jarFileIS.getNextJarEntry(); |
| while (jarEntry != null) { |
| if (!inputFileName.endsWith("/")) { |
| inputFileName += "/"; |
| } |
| if ((jarEntry.getName().compareTo(inputFileName) != 0) |
| && (jarEntry.getName().startsWith(inputFileName))) { |
| File newDstPath = getOutFile(jarEntry.getName()); |
| copyFileOrDirectoryFromJar(jarFileName, jarEntry.getName(), |
| newDstPath, false); |
| } |
| jarEntry = jarFileIS.getNextJarEntry(); |
| } |
| jarFileIS.close(); |
| } else { |
| InputStream in = jarFile.getInputStream(jarFile.getEntry(inputFileName)); |
| OutputStream out = new FileOutputStream(dstPath); |
| |
| int c; |
| while ((c = in.read()) != -1) { |
| out.write(c); |
| } |
| in.close(); |
| out.close(); |
| jarFile.close(); |
| } |
| } |
| |
| public static String escapeXml(String unescaped) { |
| String escaped = unescaped.replaceAll("\\&", "&"); |
| escaped = escaped.replaceAll("\\<", "<"); |
| escaped = escaped.replaceAll("\\>", ">"); |
| escaped = escaped.replaceAll("\\\"", """); |
| escaped = escaped.replaceAll("\\'", "'"); |
| return escaped; |
| } |
| |
| private static void addCenteredHeader(final PrintWriter outFile, String header) { |
| outFile.println("<hr>"); |
| outFile.println("<b>" + header + "</b>"); |
| outFile.println("<hr>"); |
| } |
| |
| /** |
| * Adds a header line indicating which breakdown is being analyzed. |
| */ |
| private static void addHeaderWithBreakdownContext(SizeBreakdown breakdown, |
| final PrintWriter outFile) { |
| addCenteredHeader(outFile, headerLineForBreakdown(breakdown)); |
| } |
| |
| private static String classesInPackageFileName(SizeBreakdown breakdown, |
| String packageName) { |
| return breakdown.getId() + "_" + packageName + "_Classes.html"; |
| } |
| |
| /** |
| * Convert a potentially long string into a short file name. The current |
| * implementation simply hashes the long name. |
| */ |
| private static String filename(String longFileName) { |
| try { |
| return Util.computeStrongName(longFileName.getBytes(Util.DEFAULT_ENCODING)); |
| } catch (UnsupportedEncodingException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| /** |
| * Return a {@link File} object for a file to be emitted into the output |
| * directory. |
| */ |
| private static File getOutFile(String localFileName) { |
| File outDir = new File(GlobalInformation.settings.out.get()); |
| return new File(outDir, localFileName); |
| } |
| |
| private static String headerLineForBreakdown(SizeBreakdown breakdown) { |
| return "(Analyzing code subset: " + breakdown.getDescription() + ")"; |
| } |
| |
| /** |
| * Describe the code covered by the dependency graph with the supplied name. |
| */ |
| private static String inferDepGraphDescription(String depGraphName) { |
| if (depGraphName.equals("initial")) { |
| return "Initially Live Code"; |
| } |
| |
| if (depGraphName.equals("total")) { |
| return "All Code"; |
| } |
| |
| Matcher matcher = PATTERN_SP_INT.matcher(depGraphName); |
| if (matcher.matches()) { |
| int splitPoint = Integer.valueOf(matcher.group(1)); |
| if (isInitialSplitPoint(splitPoint)) { |
| return "Code Becoming Live at Split Point " + splitPoint; |
| } else { |
| return "Code not Exclusive to Split Point " + splitPoint; |
| } |
| } |
| |
| throw new RuntimeException("Unexpected dependency graph name: " |
| + depGraphName); |
| } |
| |
| private static boolean isInitialSplitPoint(int splitPoint) { |
| return GlobalInformation.splitPointInitialLoadSequence.contains(splitPoint); |
| } |
| |
| private static String makeCodeTypeHtml(SizeBreakdown breakdown, |
| Map<String, CodeCollection> nameToCodeColl) throws IOException { |
| String outFileName = breakdown.getId() + "_codeTypeBreakdown.html"; |
| float maxSize = 0f; |
| float sumSize = 0f; |
| TreeMap<Float, String> sortedCodeTypes = new TreeMap<Float, String>( |
| Collections.reverseOrder()); |
| |
| // TODO(kprobst): turn this into a multimap? |
| // com.google.common.collect.TreeMultimap |
| for (String codeType : nameToCodeColl.keySet()) { |
| float curSize = nameToCodeColl.get(codeType).getCumPartialSize(breakdown); |
| sumSize += curSize; |
| |
| if (curSize != 0f) { |
| sortedCodeTypes.put(curSize, codeType); |
| if (curSize > maxSize) { |
| maxSize = curSize; |
| } |
| } |
| } |
| |
| final PrintWriter outFile = new PrintWriter(getOutFile(outFileName)); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">"); |
| outFile.println("</head>"); |
| outFile.println("<body>"); |
| |
| int yOffset = 0; |
| for (float size : sortedCodeTypes.keySet()) { |
| |
| String codeType = sortedCodeTypes.get(size); |
| String drillDownFileName = breakdown.getId() + "_" + codeType |
| + "Classes.html"; |
| |
| float ratio = (size / maxSize) * 79; |
| float perc = (size / sumSize) * 100; |
| |
| if (ratio < 3) { |
| ratio = 3; |
| } |
| |
| outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " |
| + yOffset + "px; left: 110px;\">"); |
| outFile.println("<div id=\"lb\">"); |
| outFile.println("<div id=\"rb\">"); |
| outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| outFile.println("<div id=\"content\">"); |
| outFile.println("</div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div>"); |
| |
| int yOffsetText = yOffset + 8; |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:5px;\">%d</div>\n", (int) size); |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:70px;\">%.1f", perc); |
| outFile.println("%</div>\n"); |
| outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:110px;\"><a href=\"" + drillDownFileName |
| + "\" target=\"_top\">" + codeType + "</a></div>"); |
| |
| yOffset = yOffset + 25; |
| } |
| outFile.println("</body>"); |
| outFile.println("</html>"); |
| outFile.close(); |
| |
| return outFileName; |
| } |
| |
| private static String shellFileName(SizeBreakdown breakdown) { |
| return breakdown.getId() + "-overallBreakdown.html"; |
| } |
| |
| public void makeBreakdownShell(SizeBreakdown breakdown) throws IOException { |
| // this will contain the place holder iframes where the actual information |
| // is going to go. |
| |
| Map<String, CodeCollection> nameToCodeColl = breakdown.nameToCodeColl; |
| Map<String, LiteralsCollection> nameToLitColl = breakdown.nameToLitColl; |
| |
| // copy from the bin directory to the current directory |
| String classPath = GlobalInformation.settings.resources.get(); |
| if (classPath == null) { |
| classPath = System.getProperty("java.class.path"); |
| } |
| if (!classPath.endsWith("/")) { |
| classPath += "/"; |
| } |
| String inputFileName = "roundedCorners.css"; |
| File inputFile = new File(classPath + inputFileName); |
| File outputFile = getOutFile("roundedCorners.css"); |
| copyFileOrDirectory(inputFile, outputFile, classPath, inputFileName, false); |
| |
| inputFileName = "classLevel.css"; |
| File inputFile2 = new File(classPath + inputFileName); |
| File outputFile2 = getOutFile("classLevel.css"); |
| copyFileOrDirectory(inputFile2, outputFile2, classPath, inputFileName, |
| false); |
| |
| inputFileName = "images"; |
| File inputDir = new File(classPath + "images"); |
| File outputDir = getOutFile("images"); |
| copyFileOrDirectory(inputDir, outputDir, classPath, inputFileName, true); |
| |
| final PrintWriter outFile = new PrintWriter( |
| getOutFile(shellFileName(breakdown))); |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<title>Story of Your Compile - Top Level Dashboard for Permutation</title>"); |
| |
| outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\">"); |
| outFile.println("<style type=\"text/css\">"); |
| outFile.println("body {background-color: #728FCE}"); |
| outFile.println("h2 {background-color: transparent}"); |
| outFile.println("p {background-color: fuchsia}"); |
| outFile.println("</style>"); |
| outFile.println("</head>"); |
| |
| outFile.println("<body>"); |
| outFile.println("<center>"); |
| outFile.println("<h3>Story of Your Compile Dashboard</h3>"); |
| addHeaderWithBreakdownContext(breakdown, outFile); |
| |
| outFile.println("</center>"); |
| outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">"); |
| outFile.println("<b>Package breakdown</b>"); |
| outFile.println(" </div>"); |
| |
| outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">"); |
| outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>"); |
| outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Package Name</div>"); |
| outFile.println(" </div>"); |
| |
| String packageBreakdownFileName = makePackageHtml(breakdown); |
| outFile.println("<div style=\"height:35%; width:100%; margin:0 auto; background-color:white; float:left;\">"); |
| outFile.println("<iframe src=\"" + packageBreakdownFileName |
| + "\" width=100% height=100% scrolling=auto></iframe>"); |
| outFile.println(" </div>"); |
| |
| outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">"); |
| outFile.println("<b>Literals breakdown</b>"); |
| outFile.println(" </div>"); |
| outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">"); |
| outFile.println("<b>Code type breakdown</b>"); |
| outFile.println(" </div>"); |
| |
| outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">"); |
| outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>"); |
| outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Literal Type</div>"); |
| outFile.println(" </div>"); |
| |
| outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">"); |
| outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>"); |
| outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Code Type</div>"); |
| outFile.println(" </div>"); |
| |
| String literalsBreakdownFileName = makeLiteralsHtml(breakdown, |
| nameToLitColl); |
| outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:left;\">"); |
| outFile.println("<iframe src=\"" + literalsBreakdownFileName |
| + "\" width=100% height=100% scrolling=auto></iframe>"); |
| outFile.println("</div>"); |
| |
| String codeTypeBreakdownFileName = makeCodeTypeHtml(breakdown, |
| nameToCodeColl); |
| outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">"); |
| outFile.println("<iframe src=\"" + codeTypeBreakdownFileName |
| + "\" width=100% height=100% scrolling=auto></iframe>"); |
| outFile.println(" </div>"); |
| |
| outFile.println(" </body>"); |
| outFile.println("</html>"); |
| outFile.close(); |
| } |
| |
| public void makeCodeTypeClassesHtmls(SizeBreakdown breakdown) |
| throws IOException { |
| HashMap<String, CodeCollection> nameToCodeColl = breakdown.nameToCodeColl; |
| |
| for (String codeType : nameToCodeColl.keySet()) { |
| |
| // construct file name |
| String outFileName = breakdown.getId() + "_" + codeType + "Classes.html"; |
| |
| float maxSize = 0f; |
| TreeMap<Float, String> sortedClasses = new TreeMap<Float, String>( |
| Collections.reverseOrder()); |
| |
| for (String className : nameToCodeColl.get(codeType).classes) { |
| if (breakdown.classToSize.containsKey(className)) { |
| |
| float curSize = 0f; |
| if (breakdown.classToSize.containsKey(className)) { |
| curSize = breakdown.classToSize.get(className); |
| } |
| |
| if (curSize != 0f) { |
| sortedClasses.put(curSize, className); |
| if (curSize > maxSize) { |
| maxSize = curSize; |
| } |
| } |
| } |
| } |
| |
| final PrintWriter outFile = new PrintWriter(getOutFile(outFileName)); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| |
| outFile.println("<style type=\"text/css\">"); |
| outFile.println("body {background-color: #728FCE}"); |
| outFile.println("h2 {background-color: transparent}"); |
| outFile.println("p {background-color: fuchsia}"); |
| outFile.println("</style>"); |
| |
| outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| outFile.println("<link rel=\"stylesheet\" href=\"classLevel.css\" media=\"screen\">"); |
| outFile.println("<title>Classes of type \"" + codeType + "\"</title>"); |
| outFile.println("</head>"); |
| outFile.println("<body>"); |
| |
| outFile.println("<center>"); |
| outFile.println("<h2>Classes of type \"" + codeType + "\"</h2>"); |
| addHeaderWithBreakdownContext(breakdown, outFile); |
| outFile.println("</center>"); |
| |
| outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 120px; left:70px; position:absolute; background-color:white\""); |
| |
| int yOffset = 0; |
| for (float size : sortedClasses.keySet()) { |
| |
| String className = sortedClasses.get(size); |
| |
| float ratio = (size / maxSize) * 85; |
| |
| if (ratio < 3) { |
| ratio = 3; |
| } |
| |
| outFile.println("<div class=\"box\" style=\"width:" + ratio |
| + "%; top: " + yOffset + "px; left: 60px;\">"); |
| outFile.println("<div id=\"lb\">"); |
| outFile.println("<div id=\"rb\">"); |
| outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| outFile.println("<div id=\"content\">"); |
| outFile.println("</div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div>"); |
| |
| int yOffsetText = yOffset + 8; |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:5px;\">%d</div>\n", (int) size); |
| outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:70px;\">" + className + "</div>"); |
| |
| yOffset = yOffset + 25; |
| } |
| |
| addStandardHtmlEnding(outFile); |
| outFile.close(); |
| } |
| } |
| |
| public void makeDependenciesHtml( |
| Map<String, Map<String, String>> allDependencies) throws IOException { |
| for (String depGraphName : allDependencies.keySet()) { |
| makeDependenciesHtml(depGraphName, allDependencies.get(depGraphName)); |
| } |
| } |
| |
| public void makeLeftoverStatusPages() throws IOException { |
| for (String className : GlobalInformation.classToPackage.keySet()) { |
| makeLeftoversStatusPage(className); |
| } |
| } |
| |
| public void makeLiteralsClassesTableHtmls(SizeBreakdown breakdown) |
| throws IOException { |
| Map<String, LiteralsCollection> nameToLitColl = breakdown.nameToLitColl; |
| |
| for (String literalType : nameToLitColl.keySet()) { |
| |
| String outFileName = literalType + "Lits.html"; |
| final PrintWriter outFile = new PrintWriter(getOutFile(breakdown.getId() |
| + "_" + outFileName)); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| outFile.println("<title>Literals of type \"" + literalType + "\"</title>"); |
| outFile.println("</head>"); |
| |
| outFile.println("<style type=\"text/css\">"); |
| outFile.println("body {background-color: #728FCE}"); |
| outFile.println("h2 {background-color: transparent}"); |
| outFile.println("p {background-color: fuchsia}"); |
| outFile.println("</style>"); |
| |
| outFile.println("<body>"); |
| outFile.println("<center>"); |
| outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>"); |
| addHeaderWithBreakdownContext(breakdown, outFile); |
| outFile.println("</center>"); |
| |
| outFile.println("<center>"); |
| outFile.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">"); |
| |
| for (String literal : nameToLitColl.get(literalType).literals) { |
| String newLiteral = ""; |
| if (literal.length() > 80) { |
| int i; |
| for (i = 80; i < literal.length(); i = i + 80) { |
| String part1 = literal.substring(i - 80, i); |
| newLiteral = newLiteral + part1 + " "; |
| } |
| if (i - 80 > 0) { |
| newLiteral = newLiteral + literal.substring(i - 80); |
| } |
| } else { |
| newLiteral = literal; |
| } |
| |
| if (newLiteral.trim().length() == 0) { |
| newLiteral = "[whitespace only string]"; |
| } |
| String escliteral = escapeXml(newLiteral); |
| |
| outFile.println("<tr>"); |
| outFile.println("<td>" + escliteral + "</td>"); |
| outFile.println("</tr>"); |
| } |
| |
| outFile.println("</table>"); |
| outFile.println("<center>"); |
| |
| addStandardHtmlEnding(outFile); |
| outFile.close(); |
| } |
| } |
| |
| /** |
| * Make size breakdowns for each package for one code collection. |
| */ |
| public void makePackageClassesHtmls(SizeBreakdown breakdown, |
| DependencyLinker depLinker) throws IOException { |
| for (String packageName : GlobalInformation.packageToClasses.keySet()) { |
| |
| TreeMap<Float, String> sortedClasses = new TreeMap<Float, String>( |
| Collections.reverseOrder()); |
| float maxSize = 0f; |
| |
| int maxDepCount = 1; |
| |
| for (String className : GlobalInformation.packageToClasses.get(packageName)) { |
| |
| float curSize = 0f; |
| if (!breakdown.classToSize.containsKey(className)) { |
| // This class not present in this code collection |
| } else { |
| curSize = breakdown.classToSize.get(className); |
| } |
| |
| int depCount = 0; |
| if (GlobalInformation.classToWhatItDependsOn.containsKey(className)) { |
| depCount = GlobalInformation.classToWhatItDependsOn.get(className).size(); |
| } |
| |
| if (curSize != 0f) { |
| |
| sortedClasses.put(curSize, className); |
| if (curSize > maxSize) { |
| maxSize = curSize; |
| } |
| if (depCount > maxDepCount) { |
| maxDepCount = depCount; |
| } |
| } |
| } |
| |
| PrintWriter outFile = new PrintWriter( |
| getOutFile(classesInPackageFileName(breakdown, packageName))); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| outFile.println("<link rel=\"stylesheet\" href=\"classLevel.css\" media=\"screen\">"); |
| outFile.println("<title>Classes in package \"" + packageName |
| + "\"</title>"); |
| outFile.println("</head>"); |
| outFile.println("<body>"); |
| |
| outFile.println("<center>"); |
| outFile.println("<h2>Classes in package \"" + packageName + "\"</h2>"); |
| addHeaderWithBreakdownContext(breakdown, outFile); |
| outFile.println("</center>"); |
| |
| outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 120px; left:70px; position:absolute; background-color:white\""); |
| |
| int yOffset = 0; |
| for (float size : sortedClasses.keySet()) { |
| |
| String className = sortedClasses.get(size); |
| |
| // TODO(kprobst): switch out the commented/uncommented lines below when |
| // showing dependencies |
| // float ratio = (size / maxSize) * 45; |
| float ratio = (size / maxSize) * 85; |
| |
| if (ratio < 3) { |
| ratio = 3; |
| } |
| |
| // TODO(kprobst): not currently used, but will be for dependencies |
| // get the dependency count |
| int depCount = 0; |
| if (GlobalInformation.classToWhatItDependsOn.containsKey(className)) { |
| depCount = GlobalInformation.classToWhatItDependsOn.get(className).size(); |
| } |
| float depRatio = ((float) depCount / (float) maxDepCount) * 45f; |
| if (depRatio < 3.0) { |
| depRatio = 3; |
| } |
| |
| outFile.println("<div class=\"box\" style=\"width:" + ratio |
| + "%; top: " + yOffset + "px; left: 60px;\">"); |
| outFile.println("<div id=\"lb\">"); |
| outFile.println("<div id=\"rb\">"); |
| outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| outFile.println("<div id=\"content\">"); |
| outFile.println("</div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div>"); |
| |
| // TODO(kprobst): not currently used, but will be for dependencies |
| /* |
| * outFile.println("<div class=\"box-right\" style=\"width:" + depRatio |
| * + "%; top: " + yOffset + "px; left: 50%\">"); |
| * outFile.println("<div id=\"lb\">"); |
| * outFile.println("<div id=\"rb\">"); |
| * outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| * outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| * outFile.println("<div id=\"content\">"); outFile.println("</div>"); |
| * outFile.println("</div></div></div></div>"); |
| * outFile.println("</div></div></div></div>"); |
| * outFile.println("</div>"); |
| */ |
| |
| int yOffsetText = yOffset + 8; |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:5px;\">%d</div>\n", (int) size); |
| if (GlobalInformation.displayDependencies == true) { |
| String dependencyLink = depLinker.dependencyLinkForClass(className); |
| outFile.print("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:70px;\">"); |
| if (dependencyLink != null) { |
| outFile.print("<a href=\"" + dependencyLink + "\">"); |
| } |
| outFile.print(className); |
| if (dependencyLink != null) { |
| outFile.print("</a>"); |
| } |
| outFile.println("</div>"); |
| } else { |
| outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:70px;\">" + className + "</div>"); |
| } |
| /* |
| * //TODO(kprobst) make this a link String drillDownFileName = className |
| * + "Deps.html"; outFile.println("<div class=\"barlabel\" style=\"top:" |
| * + yOffsetText + "px; left:50%;\"><a href=\"" + drillDownFileName + |
| * "\" target=\"_top\">Dependencies: " + depCount + "</a></div>"); |
| */ |
| yOffset = yOffset + 25; |
| } |
| |
| addStandardHtmlEnding(outFile); |
| outFile.close(); |
| } |
| } |
| |
| public void makeSplitStatusPages() throws IOException { |
| for (String className : GlobalInformation.classToPackage.keySet()) { |
| makeSplitStatusPage(className); |
| } |
| } |
| |
| public void makeTopLevelShell() throws IOException { |
| PrintWriter outFile = new PrintWriter( |
| getOutFile("SoycDashboard-index.html")); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<title>Story of Your Compile - Top Level Dashboard for Permutation</title>"); |
| |
| outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\">"); |
| outFile.println("<style type=\"text/css\">"); |
| outFile.println("body {background-color: #728FCE}"); |
| outFile.println("h2 {background-color: transparent}"); |
| outFile.println("p {background-color: fuchsia}"); |
| outFile.println("</style>"); |
| outFile.println("</head>"); |
| |
| outFile.println("<body>"); |
| outFile.println("<center>"); |
| outFile.println("<h3>Story of Your Compile Dashboard</h3>"); |
| outFile.println("<hr>"); |
| if (GlobalInformation.splitPointToLocation.size() > 1) { |
| outFile.println("<b>Initial download size: <span style=\"color:maroon\">" |
| + GlobalInformation.initialCodeBreakdown.sizeAllCode |
| + "</span></span></b>"); |
| } else { |
| outFile.println("<b>Full code size: <span style=\"color:maroon\">" |
| + GlobalInformation.totalCodeBreakdown.sizeAllCode |
| + "</span></span></b>"); |
| } |
| |
| outFile.println("<hr>"); |
| |
| outFile.println("Available code subsets to analyze"); |
| |
| int numSplitPoints = GlobalInformation.splitPointToLocation.size(); |
| |
| int numRows = 2; |
| if (numSplitPoints > 0) { |
| // add one for the leftovers fragment |
| numRows += numSplitPoints + 1; |
| } |
| int outerHeight = 25 * numRows; |
| outFile.println("<div style=\"width:100%; margin:20px 0 20px 0; background-color:white;position:relative;height:" |
| + outerHeight + "\">"); |
| int maxSize = GlobalInformation.totalCodeBreakdown.sizeAllCode; |
| |
| int yOffset = 0; |
| for (int i = FRAGMENT_NUMBER_TOTAL_PROGRAM; i <= numSplitPoints + 1; i++) { |
| if (i == 1 && numSplitPoints == 0) { |
| // don't show the leftovers fragment if the split points aren't known |
| continue; |
| } |
| |
| SizeBreakdown breakdown; |
| if (i == FRAGMENT_NUMBER_TOTAL_PROGRAM) { |
| breakdown = GlobalInformation.totalCodeBreakdown; |
| } else if (i == numSplitPoints + 1) { |
| breakdown = GlobalInformation.leftoversBreakdown; |
| } else if (i == FRAGMENT_NUMBER_INITIAL_DOWNLOAD) { |
| breakdown = GlobalInformation.initialCodeBreakdown; |
| } else { |
| breakdown = GlobalInformation.splitPointCodeBreakdown(i); |
| } |
| |
| String drillDownFileName = shellFileName(breakdown); |
| String splitPointDescription = breakdown.getDescription(); |
| |
| int size = breakdown.sizeAllCode; |
| float ratio = (1.0F * size / maxSize) * 79; |
| if (ratio < 3) { |
| ratio = 3; |
| } |
| |
| outFile.println("<div id=\"box\" style=\"width: " + ratio + "%; top: " |
| + yOffset + "px; left: 110px;\">"); |
| outFile.println("<div id=\"lb\">"); |
| outFile.println("<div id=\"rb\">"); |
| outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| outFile.println("<div id=\"content\">"); |
| outFile.println("</div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div>"); |
| |
| int yOffsetText = yOffset + 8; |
| outFile.printf("<div class=\"barlabel\" style=\"top: " + yOffsetText |
| + "px; left:5px;\">%d</div>\n", size); |
| outFile.println("<div class=\"barlabel\" style=\"top: " + yOffsetText |
| + "px; left:120px;\"><a href=\"" + drillDownFileName |
| + "\" target=\"_top\">" + splitPointDescription + "</a></div>"); |
| |
| yOffset = yOffset + 25; |
| } |
| outFile.println("</div>"); |
| outFile.println("</body></html>"); |
| outFile.close(); |
| } |
| |
| private void addLefttoversStatus(String className, String packageName, |
| PrintWriter out) { |
| out.println("<tr><td> <a href=\"" |
| + dependenciesFileName("total", packageName) + "#" + className |
| + "\">See why it's live</a></td></tr>"); |
| for (int sp = 1; sp <= GlobalInformation.numSplitPoints; sp++) { |
| out.println("<tr><td> <a href=\"" |
| + dependenciesFileName("sp" + sp, packageName) + "#" + className |
| + "\">See why it's not exclusive to s.p. #" + sp + " (" |
| + GlobalInformation.splitPointToLocation.get(sp) + ")</a></td></tr>"); |
| } |
| } |
| |
| private void addStandardHtmlEnding(final PrintWriter out) { |
| out.println("</div>"); |
| out.println("</body>"); |
| out.println("</html>"); |
| } |
| |
| private void addStandardHtmlProlog(final PrintWriter out, String title, |
| String header) { |
| out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| out.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| out.println("<html>"); |
| out.println("<head>"); |
| out.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| out.println("<title>" + title + "</title>"); |
| out.println("</head>"); |
| |
| out.println("<style type=\"text/css\">"); |
| out.println("body {background-color: #728FCE}"); |
| out.println("h2 {background-color: transparent}"); |
| out.println("p {background-color: fuchsia}"); |
| out.println("</style>"); |
| |
| out.println("<body>"); |
| out.println("<center>"); |
| out.println("<h2>" + title + "</h2>"); |
| if (header != null) { |
| addCenteredHeader(out, header); |
| } |
| out.println("</center>"); |
| } |
| |
| private String dependenciesFileName(String depGraphName, String packageName) { |
| return "methodDependencies-" + depGraphName + "-" + filename(packageName) |
| + ".html"; |
| } |
| |
| private String leftoversStatusFileName(String className) { |
| return "leftoverStatus-" + filename(className) + ".html"; |
| } |
| |
| private void makeDependenciesHtml(String depGraphName, |
| Map<String, String> dependencies) throws FileNotFoundException { |
| String depGraphDescription = inferDepGraphDescription(depGraphName); |
| PrintWriter outFile = null; |
| String curPackageName = ""; |
| String curClassName = ""; |
| |
| for (String method : dependencies.keySet()) { |
| // this key set is already in alphabetical order |
| // get the package of this method, i.e., everything up to .[A-Z] |
| |
| String packageName = method; |
| packageName = packageName.replaceAll("\\.\\p{Upper}.*", ""); |
| |
| String className = method; |
| className = className.replaceAll("::.*", ""); |
| |
| if ((curPackageName.compareTo("") == 0) |
| || (curPackageName.compareTo(packageName) != 0)) { |
| |
| curPackageName = packageName; |
| if (outFile != null) { |
| // finish up the current file |
| outFile.println("</table>"); |
| outFile.println("<center>"); |
| |
| addStandardHtmlEnding(outFile); |
| outFile.close(); |
| } |
| |
| String outFileName = dependenciesFileName(depGraphName, curPackageName); |
| outFile = new PrintWriter(getOutFile(outFileName)); |
| |
| String packageDescription = packageName.length() == 0 |
| ? "the default package" : packageName; |
| addStandardHtmlProlog(outFile, "Method Dependencies for " |
| + depGraphDescription, "Showing Package: " + packageDescription); |
| outFile.println("<center>"); |
| outFile.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">"); |
| } |
| outFile.println("<tr>"); |
| if (curClassName.compareTo(className) != 0) { |
| outFile.println("<td width=\"80%\"><a name=\"" + className + "\">" |
| + "<a name=\"" + method + "\">" + method |
| + "</a></a><font color=\"green\"> called by</font></td>"); |
| curClassName = className; |
| } else { |
| outFile.println("<td width=\"80%\"><a name=\"" + method + "\">" |
| + method + "</a><font color=\"green\"> called by</font></td>"); |
| } |
| outFile.println("</tr>"); |
| |
| String depMethod = dependencies.get(method); |
| while (depMethod != null) { |
| String nextDep = dependencies.get(depMethod); |
| outFile.println("<tr>"); |
| outFile.println("<td width=\"20%\"></td>"); |
| if (nextDep != null) { |
| outFile.println("<td width=\"60%\">" + depMethod |
| + "<font color=\"green\"> called by</font></td>"); |
| } else { |
| outFile.println("<td width=\"60%\">" + depMethod + "</td>"); |
| } |
| outFile.println("</tr>"); |
| depMethod = nextDep; |
| } |
| } |
| } |
| |
| private void makeLeftoversStatusPage(String className) throws IOException { |
| String packageName = GlobalInformation.classToPackage.get(className); |
| PrintWriter out = new PrintWriter( |
| getOutFile(leftoversStatusFileName(className))); |
| |
| addStandardHtmlProlog(out, "Leftovers page for " + className, null); |
| |
| out.println("<center>"); |
| out.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">"); |
| |
| out.println("<tr><td>This class has some leftover code, neither initial nor exclusive to any split point:</td></tr>"); |
| addLefttoversStatus(className, packageName, out); |
| out.println("</table>"); |
| |
| addStandardHtmlEnding(out); |
| |
| out.close(); |
| } |
| |
| private String makeLiteralsHtml(SizeBreakdown breakdown, |
| Map<String, LiteralsCollection> nameToLitColl) throws IOException { |
| String outFileName = breakdown.getId() + "_literalsBreakdown.html"; |
| float maxSize = 0f; |
| float sumSize = 0f; |
| TreeMap<Float, String> sortedLitTypes = new TreeMap<Float, String>( |
| Collections.reverseOrder()); |
| |
| for (String literal : nameToLitColl.keySet()) { |
| float curSize = nameToLitColl.get(literal).size; |
| sumSize += curSize; |
| |
| if (curSize != 0f) { |
| sortedLitTypes.put(curSize, literal); |
| |
| if (curSize > maxSize) { |
| maxSize = curSize; |
| } |
| } |
| } |
| |
| final PrintWriter outFile = new PrintWriter(getOutFile(outFileName)); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">"); |
| outFile.println("</head>"); |
| outFile.println("<body>"); |
| |
| int yOffset = 0; |
| for (float size : sortedLitTypes.keySet()) { |
| |
| String literal = sortedLitTypes.get(size); |
| String drillDownFileName = breakdown.getId() + "_" + literal |
| + "Lits.html"; |
| |
| float ratio = (size / maxSize) * 79; |
| float perc = (size / sumSize) * 100; |
| |
| if (ratio < 3) { |
| ratio = 3; |
| } |
| |
| outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " |
| + yOffset + "px; left: 110px;\">"); |
| outFile.println("<div id=\"lb\">"); |
| outFile.println("<div id=\"rb\">"); |
| outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| outFile.println("<div id=\"content\">"); |
| outFile.println("</div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div>"); |
| |
| int yOffsetText = yOffset + 8; |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:5px;\">%d</div>\n", (int) size); |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:70px;\">%.1f", perc); |
| outFile.println("%</div>\n"); |
| outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:110px;\"><a href=\"" + drillDownFileName |
| + "\" target=\"_top\">" + literal + "</a></div>"); |
| |
| yOffset = yOffset + 25; |
| } |
| outFile.println("</body>"); |
| outFile.println("</html>"); |
| outFile.close(); |
| |
| return outFileName; |
| } |
| |
| private String makePackageHtml(SizeBreakdown breakdown) |
| throws FileNotFoundException { |
| String outFileName = breakdown.getId() + "_" + "packageBreakdown.html"; |
| Map<String, Integer> packageToPartialSize = breakdown.packageToSize; |
| TreeMap<Integer, String> sortedPackages = new TreeMap<Integer, String>( |
| Collections.reverseOrder()); |
| float maxSize = 0f; |
| float sumSize = 0f; |
| for (String packageName : packageToPartialSize.keySet()) { |
| sortedPackages.put(packageToPartialSize.get(packageName), packageName); |
| sumSize += packageToPartialSize.get(packageName); |
| if (packageToPartialSize.get(packageName) > maxSize) { |
| maxSize = packageToPartialSize.get(packageName); |
| } |
| } |
| |
| final PrintWriter outFile = new PrintWriter(getOutFile(outFileName)); |
| |
| outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""); |
| outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">"); |
| outFile.println("<html>"); |
| outFile.println("<head>"); |
| outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">"); |
| outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">"); |
| |
| outFile.println("</head>"); |
| outFile.println("<body>"); |
| |
| int yOffset = 0; |
| for (int size : sortedPackages.keySet()) { |
| String packageName = sortedPackages.get(size); |
| String drillDownFileName = classesInPackageFileName(breakdown, |
| packageName); |
| |
| float ratio = (size / maxSize) * 79; |
| |
| if (ratio < 3) { |
| ratio = 3; |
| } |
| |
| float perc = (size / sumSize) * 100; |
| |
| outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " |
| + yOffset + "px; left: 110px;\">"); |
| outFile.println("<div id=\"lb\">"); |
| outFile.println("<div id=\"rb\">"); |
| outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">"); |
| outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">"); |
| outFile.println("<div id=\"content\">"); |
| outFile.println("</div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div></div></div></div>"); |
| outFile.println("</div>"); |
| |
| int yOffsetText = yOffset + 8; |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:5px;\">%d</div>\n", size); |
| outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:70px;\">%.1f", perc); |
| outFile.println("%</div>\n"); |
| outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText |
| + "px; left:110px;\"><a href=\"" + drillDownFileName |
| + "\" target=\"_top\">" + packageName + "</a></div>"); |
| |
| yOffset = yOffset + 25; |
| } |
| outFile.println("</body>"); |
| outFile.println("</html>"); |
| outFile.close(); |
| |
| return outFileName; |
| } |
| |
| private void makeSplitStatusPage(String className) throws IOException { |
| String packageName = GlobalInformation.classToPackage.get(className); |
| PrintWriter out = new PrintWriter( |
| getOutFile(splitStatusFileName(className))); |
| |
| addStandardHtmlProlog(out, "Split point status for " + className, null); |
| |
| out.println("<center>"); |
| out.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">"); |
| |
| if (GlobalInformation.initialCodeBreakdown.classToSize.containsKey(className)) { |
| out.println("<tr><td>Some code is initial (<a href=\"" |
| + dependenciesFileName("initial", packageName) + "#" + className |
| + "\">see why</a>)</td></tr>"); |
| } |
| for (int sp : splitPointsWithClass(className)) { |
| out.println("<tr><td>Some code downloads with s.p. #" + sp + " (" |
| + GlobalInformation.splitPointToLocation.get(sp) + ")</td></tr>"); |
| } |
| if (GlobalInformation.leftoversBreakdown.classToSize.containsKey(className)) { |
| out.println("<tr><td>Some code is left over:</td></tr>"); |
| addLefttoversStatus(className, packageName, out); |
| } |
| out.println("</table>"); |
| |
| addStandardHtmlEnding(out); |
| |
| out.close(); |
| } |
| |
| /** |
| * Find which split points include code belonging to <code>className</code>. |
| */ |
| private Iterable<Integer> splitPointsWithClass(String className) { |
| List<Integer> sps = new ArrayList<Integer>(); |
| for (int sp = 1; sp <= GlobalInformation.numSplitPoints; sp++) { |
| Map<String, Integer> classToSize = GlobalInformation.splitPointCodeBreakdown(sp).classToSize; |
| if (classToSize.containsKey(className)) { |
| sps.add(sp); |
| } |
| } |
| return sps; |
| } |
| |
| private String splitStatusFileName(String className) { |
| return "splitStatus-" + filename(className) + ".html"; |
| } |
| } |