package edu.uiuc.cs.fsl.propertydocs.util; import com.sun.javadoc.Tag; import java.io.*; import java.util.HashSet; public class CreatePropertyFile { private static final String dir = System.getProperty( "outputpath" ); private static HashSet<String> seenPositions = new HashSet<String> (); //this is to ensure that we don't link back //to the same location multiple times private static HashSet<String> seenNames = new HashSet<String>(); //since we modify property files in place, we need this to //ensure that we delete the files on a fresh run public static final String PROPDIR = "propertypath"; private static final String propDir = System.getProperty(PROPDIR); static { File propertyDir = new File(dir + "/" + "__properties"); if(!propertyDir.exists()) propertyDir.mkdir(); File htmlDir = new File(dir + "/" + "__properties" + "/" + "html"); if(!htmlDir.exists()) htmlDir.mkdir(); File rvmDir = new File(dir + "/" + "__properties" + "/" + "rvm"); if(!rvmDir.exists()) rvmDir.mkdir(); } public static void forceInit() { /* call this method to force this class to be initialized */ } //Name is the name of the property //tag is the PropertyOpen Tag referencing the property //depth is the depth of the Property File, e.g., the depth of java.io.UnsafeIterator.rvm // is 4 (3 + 1, + 1 because of __properties dir) public static void createOrModifyPropertyFile(String name, PositionWrapper p, Tag tag, int depth){ if(seenPositions.contains(p.toString() + name)) return; seenPositions.add(p.toString() + name); String pathifiedName = name.replaceAll("[.]",("/".equals("/"))?"/":"\\"); StringBuilder relativeUrlPrefix = new StringBuilder(); for(int i = 0; i < depth; ++i){ relativeUrlPrefix.append("../"); } String linkBack = relativeUrlPrefix.append(GenerateUrls.getUrl(tag)).toString(); String nameBack = tag.holder().toString().replaceAll("<","<").replaceAll(">",">"); String htmlOutName = dir + "/" + "__properties" + "/" + "html" + "/" + pathifiedName + ".html"; try { //copy specified rvm file final String inName = propDir + File.separator + pathifiedName + "" + ".rvm"; File in = new File(inName); File htmlOut = new File(htmlOutName); //create the HTML file that will link to the given rvm file populate(htmlOutName); String outName = dir + File.separator + "__properties" + File.separator + "rvm" + File.separator + pathifiedName + ".rvm"; // System.out.println("inName: " + inName); // System.out.println("outName: " + outName); populate(outName); File out = new File(outName); if(!seenNames.contains(name)){ out.delete(); htmlOut.delete(); seenNames.add(name); } if(out.exists()) { modifyPropertyFile(htmlOutName, linkBack, nameBack); return; } FileReader fr = new FileReader(in); FileOutputStream fos = new FileOutputStream(out); BufferedReader br = new BufferedReader(fr); PrintStream ps = new PrintStream(fos); String s; while (true) { s = br.readLine(); if(s == null) break; ps.println(s); } br.close(); ps.close(); FileOutputStream htmlfos = new FileOutputStream(htmlOut); PrintStream htmlps = new PrintStream(htmlfos); htmlps.print(getHtmlHeader(pathifiedName)); htmlps.print("<P><IFRAME SRC='" + buildRelativeUrlFromName(pathifiedName) + "/rvm/" + pathifiedName + ".rvm' WIDTH='100%' HEIGHT='600'></IFRAME></P>\n"); htmlps.print("<P>This property is referenced in the following locations:</P>\n"); htmlps.print("<UL>\n<LI><A HREF='" + linkBack +"'>" + nameBack + "</A></LI></UL>\n"); htmlps.print(getHtmlFooter(pathifiedName)); htmlps.close(); } catch (Exception e){ throw new RuntimeException(e); } } //This is for adding a link on an already existing HTML file. Because I don't want to //deal with collecting a list and generating the HTML property file at the end... because //such would require using a finalizer or some such thanks to how JavaDoc works (sigh), //I, instead, modify the HTML files as each new link is found. This is sort of ugly, //but it's better than messing with finalizers that may or may not get called private static void modifyPropertyFile(String htmlOutName, String linkBack, String nameBack) throws java.io.FileNotFoundException, java.io.IOException{ FileReader htmlReader = new FileReader(htmlOutName); StringBuilder htmlText = new StringBuilder(); int b; while((b = htmlReader.read()) != -1){ htmlText.append((char) b); } String[] parts = htmlText.toString().split("</UL>"); FileOutputStream htmlfos = new FileOutputStream(htmlOutName); PrintStream htmlps = new PrintStream(htmlfos); htmlps.print(parts[0]); htmlps.print(linkBackItem(linkBack, nameBack)); htmlps.print("</UL>"); htmlps.print(parts[1]); } //Simple helper method, see usage points in this file private static String linkBackItem(String linkBack, String nameBack){ return "<LI><A HREF='" + linkBack + "'>" + nameBack + "</A></LI>"; } //This method generates the necessary directory structure for a deeply //nested file, like java/util/concurrent/Foo.java // //Why the hell doesn't the standard library do this if you try to create //a long path with non-existent intervening directories already? public static void populate(String path){ String[] dirs = path.split("[/]"); String currPath = dirs[0]; for(int i = 1; i < dirs.length; ++i) { File f = new File(currPath); if(!f.exists()) f.mkdir(); if(!dirs[i].equals("")) currPath += "/" + dirs[i]; } } //perhaps put this in GenerateUrls? Lazy public static String buildRelativeUrlFromName(String path){ String[] dirs = path.split("[/]"); String ret = ".."; for(int i = 0; i < dirs.length - 1; ++i) { ret += "/.."; } return ret; } private static String getHtmlHeader(String name) { return "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n" + "<!--NewPage-->\n" + "<HTML>\n" + "<HEAD>\n" + "<!-- Generated by docsp on " + Util.getDate() + " -->\n" + "<TITLE>\n" + "Test\n" + "</TITLE>\n" + "\n" + "<META NAME=\"date\" CONTENT=\"2011-07-13\">\n" + "\n" + "<LINK REL =\"stylesheet\" TYPE=\"text/css\" HREF=\"" + buildRelativeUrlFromName(name) + "/../" + "stylesheet.css\" TITLE=\"Style\">\n" + "\n" + "<SCRIPT type=\"text/javascript\">\n" + "function windowTitle()\n" + "{\n" + " if (location.href.indexOf('is-external=true') == -1) {\n" + " parent.document.title=\"Test\";\n" + " }\n" + "}\n" + "</SCRIPT>\n" + "<NOSCRIPT>\n" + "</NOSCRIPT>\n" + "\n" + "</HEAD>\n" + "\n" + "<BODY BGCOLOR=\"white\" onload=\"windowTitle();\">\n" + "<HR>\n" + "\n" + "\n" + "<!-- ========= START OF TOP NAVBAR ======= -->\n" + "<A NAME=\"navbar_top\"><!-- --></A>\n" + "<A HREF=\"#skip-navbar_top\" title=\"Skip navigation links\"></A>\n" + "<TABLE BORDER=\"0\" WNAMETH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\" SUMMARY=\"\">\n" + "<TR>\n" + "<TD COLSPAN=2 BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\">\n" + "<A NAME=\"navbar_top_firstrow\"><!-- --></A>\n" + "<TABLE BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"3\" SUMMARY=\"\">\n" + " <TR ALIGN=\"center\" VALIGN=\"top\">\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"package-summary.html\"><FONT CLASS=\"NavBarFont1\"><B>Package</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1Rev\">  <FONT CLASS=\"NavBarFont1Rev\"><B>Class</B></FONT> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"package-tree.html\"><FONT CLASS=\"NavBarFont1\"><B>Tree</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"deprecated-list.html\"><FONT CLASS=\"NavBarFont1\"><B>Deprecated</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"index-all.html\"><FONT CLASS=\"NavBarFont1\"><B>Index</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"help-doc.html\"><FONT CLASS=\"NavBarFont1\"><B>Help</B></FONT></A> </TD>\n" + " </TR>\n" + "</TABLE>\n" + "</TD>\n" + "<TD ALIGN=\"right\" VALIGN=\"top\" ROWSPAN=3><EM>\n" + "<TD BGCOLOR=#FFFFFF CLASS=\"NavBarCell\"> <A HREF='" + buildRelativeUrlFromName(name) + "/property-list.html" + "'><FONT CLASS=NavBarFont1><B>Properties</B></FONT></EM>\n" + "</TR>\n" + "\n" // + "<TD BGCOLOR=\"white\" CLASS=\"NavBarCell2\"><FONT SIZE=\"-2\">\n" // + " <A HREF=\"index.html?Test.html\" target=\"_top\"><B>FRAMES</B></A>  \n" // + " <A HREF=\"Test.html\" target=\"_top\"><B>NO FRAMES</B></A>  \n" + " <SCRIPT type=\"text/javascript\">\n" + " <!--\n" + " if(window==top) {\n" + " document.writeln('<A HREF=\"allclasses-noframe.html\"><B>All Classes</B></A>');\n" + " }\n" + " //-->\n" + "</SCRIPT>\n" + "<NOSCRIPT>\n" + " <A HREF=\"allclasses-noframe.html\"><B>All Classes</B></A>\n" + "</NOSCRIPT>\n" + "\n" + "\n" + "</FONT></TD>\n" + "</TR>\n" + "</TABLE>\n" + "<A NAME=\"skip-navbar_top\"></A>\n" + "<!-- ========= END OF TOP NAVBAR ========= -->\n" + "<HR>\n"; } private static String getHtmlFooter(String name){ return "<!-- ======= START OF BOTTOM NAVBAR ====== -->\n" + "<A NAME=\"navbar_bottom\"><!-- --></A>\n" + "<A HREF=\"#skip-navbar_bottom\" title=\"Skip navigation links\"></A>\n" + "<TABLE BORDER=\"0\" WNAMETH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\" SUMMARY=\"\">\n" + "<TR>\n" + "<TD COLSPAN=2 BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\">\n" + "<A NAME=\"navbar_bottom_firstrow\"><!-- --></A>\n" + "<TABLE BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"3\" SUMMARY=\"\">\n" + " <TR ALIGN=\"center\" VALIGN=\"top\">\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"package-summary.html\"><FONT CLASS=\"NavBarFont1\"><B>Package</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1Rev\">  <FONT CLASS=\"NavBarFont1Rev\"><B>Class</B></FONT> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"package-tree.html\"><FONT CLASS=\"NavBarFont1\"><B>Tree</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"deprecated-list.html\"><FONT CLASS=\"NavBarFont1\"><B>Deprecated</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"index-all.html\"><FONT CLASS=\"NavBarFont1\"><B>Index</B></FONT></A> </TD>\n" + " <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"help-doc.html\"><FONT CLASS=\"NavBarFont1\"><B>Help</B></FONT></A> </TD>\n" + " </TR>\n" + "</TABLE>\n" + "</TD>\n" + "<TD ALIGN=\"right\" VALIGN=\"top\" ROWSPAN=3><EM>\n" + "<TD BGCOLOR=#FFFFFF CLASS=\"NavBarCell\"> <A HREF='" + buildRelativeUrlFromName(name) + "/property-list.html" + "'><FONT CLASS=NavBarFont1><B>Properties</B></FONT></EM>\n" + "</TD>\n" + "</TR>\n" + " <SCRIPT type=\"text/javascript\">\n" + " <!--\n" + " if(window==top) {\n" + " document.writeln('<A HREF=\"allclasses-noframe.html\"><B>All Classes</B></A>');\n" + " }\n" + " //-->\n" + "</SCRIPT>\n" + "<NOSCRIPT>\n" + " <A HREF=\"allclasses-noframe.html\"><B>All Classes</B></A>\n" + "</NOSCRIPT>\n" + "\n" + "\n" + "</FONT></TD>\n" + "</TR>\n" + "</TABLE>\n" + "<A NAME=\"skip-navbar_bottom\"></A>\n" + "<!-- ======== END OF BOTTOM NAVBAR ======= -->\n" + "\n" + "<HR>\n" + "\n" + "</BODY>\n" + "</HTML>\n"; } }