1 19 20 package org.netbeans.nbbuild; 21 22 import java.io.*; 23 import java.io.File ; 24 import java.util.*; 25 import java.util.ArrayList ; 26 import java.util.List ; 27 import java.util.regex.*; 28 29 import org.apache.tools.ant.BuildException; 30 import org.apache.tools.ant.DirectoryScanner; 31 import org.apache.tools.ant.Project; 32 import org.apache.tools.ant.Task; 33 import org.apache.tools.ant.types.FileSet; 34 35 39 public class JavadocIndex extends Task { 40 private File target; 41 private FileSet set; 42 private Map<String ,List <Clazz>> classes = new HashMap<String ,List <Clazz>>(101); 43 44 46 public void setTarget (File f) { 47 this.target = f; 48 } 49 50 52 public void addPackagesList(FileSet set) throws BuildException { 53 if (this.set != null) { 54 throw new BuildException ("Package list can be associated only once"); 55 } 56 this.set = set; 57 } 58 59 public void execute() throws BuildException { 60 if (target == null) { 61 throw new BuildException ("Target must be set"); } 63 if (set == null) { 64 throw new BuildException ("Set of files must be provided: " + set); } 66 67 DirectoryScanner scan = set.getDirectoryScanner(this.getProject()); 68 File bdir = scan.getBasedir(); 69 for (String n : scan.getIncludedFiles()) { 70 File f = new File (bdir, n); 71 parseForClasses (f); 72 } 73 74 try { 75 log ("Generating list of all classes to " + target); 76 PrintStream ps = new PrintStream (new BufferedOutputStream ( 77 new FileOutputStream (target) 78 )); 79 if (target.getName ().endsWith (".xml")) { 80 printClassesAsXML (ps); 81 } else { 82 printClassesAsHtml (ps); 83 } 84 ps.close (); 85 } catch (IOException ex) { 86 throw new BuildException (ex); 87 } 88 } 89 90 91 92 93 private void parseForClasses (File f) throws BuildException { 94 log ("Parsing file: " + f, Project.MSG_DEBUG); 95 try { 96 BufferedReader is = new BufferedReader (new FileReader (f)); 97 98 99 String urlPrefix; 100 try { 101 String fullDir = f.getParentFile ().getCanonicalPath (); 102 String fullTgz = target.getParentFile ().getCanonicalPath (); 103 104 if (!fullDir.startsWith (fullTgz)) { 105 throw new BuildException ("The directory of target file must be above all parsed files. Directory: " + fullTgz + " the file dir: " + fullDir); 106 } 107 108 urlPrefix = fullDir.substring (fullTgz.length () + 1); 109 } catch (IOException ex) { 110 throw new BuildException (ex); 111 } 112 113 String mask = ".*<A HREF=\"([^\"]*)\" title=\"(class|interface) in ([^\"]*)\"[><I]*>([\\p{Alnum}\\.]*)</.*A>.*"; 116 Pattern p = Pattern.compile (mask, Pattern.CASE_INSENSITIVE); 117 122 int matches = 0; 123 for (;;) { 124 String line = is.readLine (); 125 if (line == null) break; 126 127 Matcher m = p.matcher (line); 128 if (m.matches ()) { 129 matches++; 130 log ("Accepted line: " + line, Project.MSG_DEBUG); 131 132 if (m.groupCount () != 4) { 133 StringBuffer sb = new StringBuffer (); 134 sb.append ("Line " + line + " has " + m.groupCount () + " groups and not four"); 135 for (int i = 0; i <= m.groupCount (); i++) { 136 sb.append ("\n " + i + " grp: " + m.group (i)); 137 } 138 throw new BuildException (sb.toString ()); 139 } 140 141 Clazz c = new Clazz ( 142 m.group (3), 143 m.group (4), 144 "interface".equals (m.group (2)), 145 urlPrefix + "/" + m.group (1) 146 ); 147 if (c.name == null) throw new NullPointerException ("Null name for " + line + "\nclass: " + c); 148 if (c.name.length () == 0) throw new IllegalStateException ("Empty name for " + line + "\nclass: " + c); 149 150 log ("Adding class: " + c, Project.MSG_DEBUG); 151 152 List <Clazz> l = classes.get(c.pkg); 153 if (l == null) { 154 l = new ArrayList <Clazz>(); 155 classes.put (c.pkg, l); 156 } 157 l.add (c); 158 } else { 159 log ("Refused line: " + line, Project.MSG_DEBUG); 160 } 161 } 162 163 if (matches == 0) { 164 throw new BuildException ("No classes defined in file: " + f); 165 } 166 167 } catch (java.io.IOException ex) { 168 throw new BuildException (ex); 169 } 170 } 171 172 private void printClassesAsHtml (PrintStream ps) { 173 ps.println ("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"); 174 ps.println ("<HTML>\n<HEAD><TITLE>List of All Classes</TITLE></HEAD>"); 175 ps.println (); 176 for (String pkg : new TreeSet<String >(classes.keySet())) { 177 ps.println ("<H2>" + pkg + "</H2>"); 178 for (Clazz c : new TreeSet<Clazz>(classes.get(pkg))) { 179 ps.print ("<A HREF=\"" + c.url + "\">"); 180 if (c.isInterface) { 181 ps.print ("<I>"); 182 } 183 ps.print (c.name); 184 if (c.isInterface) { 185 ps.print ("</I>"); 186 } 187 ps.println ("</A>"); 188 } 189 } 190 ps.println ("</HTML>"); 191 } 192 193 private void printClassesAsXML (PrintStream ps) { 194 ps.println ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 195 ps.println ("<classes>"); 196 for (String pkg : new TreeSet<String >(classes.keySet())) { 197 for (Clazz c : new TreeSet<Clazz>(classes.get(pkg))) { 198 ps.print ("<class name=\""); 199 ps.print (c.name); 200 ps.print ("\""); 201 ps.print (" url=\""); 202 ps.print (c.url); 203 ps.print ("\""); 204 ps.print (" interface=\""); 205 ps.print (c.isInterface); 206 ps.print ("\""); 207 ps.print (" package=\""); 208 ps.print (c.pkg); 209 ps.print ("\""); 210 ps.println (" />"); 211 } 212 } 213 ps.println ("</classes>"); 214 } 215 216 217 private static final class Clazz extends Object implements Comparable <Clazz> { 218 public final String pkg; 219 public final String name; 220 public final String url; 221 public final boolean isInterface; 222 public Clazz (String pkg, String name, boolean isInterface, String url) { 223 this.pkg = pkg; 224 this.name = name; 225 this.isInterface = isInterface; 226 this.url = url; 227 } 228 229 230 public int compareTo(Clazz o) { 231 return name.compareTo(o.name); 232 } 233 234 public String toString () { 235 return "PKG: " + pkg + " NAME: " + name + " INTERFACE: " + isInterface + " url: " + url; 236 } 237 } } 239 | Popular Tags |