/** * Write the XML representation of the API to a file. * * @param root the RootDoc object passed by Javadoc * @return true if no problems encountered */ public static boolean writeXML(RootDoc root) { String tempFileName = outputFileName; if (outputDirectory != null) { tempFileName = outputDirectory; if (!tempFileName.endsWith(JDiff.DIR_SEP)) tempFileName += JDiff.DIR_SEP; tempFileName += outputFileName; } try { FileOutputStream fos = new FileOutputStream(tempFileName); outputFile = new PrintWriter(fos); System.out.println("JDiff: writing the API to file '" + tempFileName + "'..."); if (root.specifiedPackages().length != 0 || root.specifiedClasses().length != 0) { RootDocToXML apiWriter = new RootDocToXML(); apiWriter.emitXMLHeader(); apiWriter.logOptions(); apiWriter.processPackages(root); apiWriter.emitXMLFooter(); } outputFile.close(); } catch (IOException e) { System.out.println("IO Error while attempting to create " + tempFileName); System.out.println("Error: " + e.getMessage()); System.exit(1); } // If validation is desired, write out the appropriate api.xsd file // in the same directory as the XML file. if (XMLToAPI.validateXML) { writeXSD(); } return true; }
public static boolean start(RootDoc root) { ClassDoc[] classDocs = root.classes(); if (ArrayUtils.isNotEmpty(classDocs)) { for (ClassDoc classDoc : root.classes()) scanClassDoc(result.docs, classDoc); } return true; }
/** * The entry point into the Parser class. * * @param root A RootDoc intstance obtained via the doclet API * @return A XML (XStream) serializable element, containing everything parsed from javadoc doclet */ public static Root ParseRoot(RootDoc root) { processingStorage = new HashMap<PackageDoc, ParserMediary>(); try { md5 = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { log.error("unable to acquire MD5 algorithm", e); return null; } rootXml = new Root(); ClassDoc[] allClasses = root.classes(); for (ClassDoc classDoc : allClasses) { PackageDoc doc = classDoc.containingPackage(); ParserMediary mediary = null; // the age old 'if I have it pull out existing, if I don't make a new one' if (processingStorage.containsKey(doc)) { mediary = processingStorage.get(doc); } else { mediary = new ParserMediary( doc.name(), doc.commentText(), ParseAnnotationInstances(doc.annotations(), doc.name())); processingStorage.put(doc, mediary); } if (classDoc.isIncluded()) { // dev comment--why do enums show up as ordinary class? if (classDoc.isOrdinaryClass() || classDoc.isException() || classDoc.isError()) { mediary.addClass(ParseClass(classDoc)); } else if (classDoc.isEnum()) { mediary.addEnum(ParseEnum(classDoc)); } else if (isAnnotation(classDoc)) { mediary.addAnnotation(ParseAnnotation(classDoc)); } else if (classDoc.isInterface()) { mediary.addInterface(ParseInterface(classDoc)); } } else { log.debug("Skipping not-included class " + classDoc.qualifiedName()); } } if (processingStorage.size() > 0) { List list = new ArrayList<Package>(); for (ParserMediary mediary : processingStorage.values()) { list.add(mediary.wrapup()); } rootXml.packages = (Package[]) list.toArray(new Package[] {}); } else { log.warn("No packages found!"); } return rootXml; }
/** * Constructor. Build the Tree using the Root of this Javadoc run. * * @param root Root of the Document. * @param configuration The curren configuration of the doclet. */ public ClassTree(RootDoc root, Configuration configuration) { buildTree(root.classes(), configuration); }
/** * Add at least the first sentence from a doc block for a package to the API. This is used by the * report generator if no comment is provided. The default source tree may not include the * package.html files, so this may be unavailable in many cases. Need to make sure that HTML tags * are not confused with XML tags. This could be done by stuffing the < character to another * string or by handling HTML in the parser. This second option is neater. Note that XML expects * all element tags to have either a closing "/>" or a matching end element tag. Due to the * difficulties of converting incorrect HTML to XHTML, the first option is used. */ public void addPkgDocumentation(RootDoc root, PackageDoc pd, int indent) { String rct = null; String filename = pd.name(); try { // See if the source path was specified as part of the // options and prepend it if it was. String srcLocation = null; String[][] options = root.options(); for (int opt = 0; opt < options.length; opt++) { if ((options[opt][0]).compareTo("-sourcepath") == 0) { srcLocation = options[opt][1]; break; } } filename = filename.replace('.', JDiff.DIR_SEP.charAt(0)); if (srcLocation != null) { // Make a relative location absolute if (srcLocation.startsWith("..")) { String curDir = System.getProperty("user.dir"); while (srcLocation.startsWith("..")) { srcLocation = srcLocation.substring(3); int idx = curDir.lastIndexOf(JDiff.DIR_SEP); curDir = curDir.substring(0, idx + 1); } srcLocation = curDir + srcLocation; } filename = srcLocation + JDiff.DIR_SEP + filename; } // Try both ".htm" and ".html" filename += JDiff.DIR_SEP + "package.htm"; File f2 = new File(filename); if (!f2.exists()) { filename += "l"; } FileInputStream f = new FileInputStream(filename); BufferedReader d = new BufferedReader(new InputStreamReader(f)); String str = d.readLine(); // Ignore everything except the lines between <body> elements boolean inBody = false; while (str != null) { if (!inBody) { if (str.toLowerCase().trim().startsWith("<body")) { inBody = true; } str = d.readLine(); // Get the next line continue; // Ignore the line } else { if (str.toLowerCase().trim().startsWith("</body")) { inBody = false; continue; // Ignore the line } } if (rct == null) rct = str + "\n"; else rct += str + "\n"; str = d.readLine(); } } catch (java.io.FileNotFoundException e) { // If it doesn't exist, that's fine if (trace) System.out.println("No package level documentation file at '" + filename + "'"); } catch (java.io.IOException e) { System.out.println("Error reading file \"" + filename + "\": " + e.getMessage()); System.exit(5); } if (rct != null) { rct = stripNonPrintingChars(rct, (Doc) pd); rct = rct.trim(); if (rct.compareTo("") != 0 && rct.indexOf(Comments.placeHolderText) == -1 && rct.indexOf("InsertOtherCommentsHere") == -1) { int idx = endOfFirstSentence(rct); if (idx == 0) return; for (int i = 0; i < indent; i++) outputFile.print(" "); outputFile.println("<doc>"); for (int i = 0; i < indent; i++) outputFile.print(" "); String firstSentence = null; if (idx == -1) firstSentence = rct; else firstSentence = rct.substring(0, idx + 1); String firstSentenceNoTags = API.stuffHTMLTags(firstSentence); outputFile.println(firstSentenceNoTags); for (int i = 0; i < indent; i++) outputFile.print(" "); outputFile.println("</doc>"); } } }
/** * Process each package and the classes/interfaces within it. * * @param pd an array of PackageDoc objects */ public void processPackages(RootDoc root) { PackageDoc[] specified_pd = root.specifiedPackages(); Map pdl = new TreeMap(); for (int i = 0; specified_pd != null && i < specified_pd.length; i++) { pdl.put(specified_pd[i].name(), specified_pd[i]); } // Classes may be specified separately, so merge their packages into the // list of specified packages. ClassDoc[] cd = root.specifiedClasses(); // This is lists of the specific classes to document Map classesToUse = new HashMap(); for (int i = 0; cd != null && i < cd.length; i++) { PackageDoc cpd = cd[i].containingPackage(); if (cpd == null && !packagesOnly) { // If the RootDoc object has been created from a jar file // this duplicates classes, so we have to be able to disable it. // TODO this is still null? cpd = root.packageNamed("anonymous"); } String pkgName = cpd.name(); String className = cd[i].name(); if (trace) System.out.println("Found package " + pkgName + " for class " + className); if (!pdl.containsKey(pkgName)) { if (trace) System.out.println("Adding new package " + pkgName); pdl.put(pkgName, cpd); } // Keep track of the specific classes to be used for this package List classes; if (classesToUse.containsKey(pkgName)) { classes = (ArrayList) classesToUse.get(pkgName); } else { classes = new ArrayList(); } classes.add(cd[i]); classesToUse.put(pkgName, classes); } PackageDoc[] pd = (PackageDoc[]) pdl.values().toArray(new PackageDoc[0]); for (int i = 0; pd != null && i < pd.length; i++) { String pkgName = pd[i].name(); // Check for an exclude tag in the package doc block, but not // in the package.htm[l] file. if (!shownElement(pd[i], null)) continue; if (trace) System.out.println("PROCESSING PACKAGE: " + pkgName); outputFile.println("<package name=\"" + pkgName + "\">"); int tagCount = pd[i].tags().length; if (trace) System.out.println("#tags: " + tagCount); List classList; if (classesToUse.containsKey(pkgName)) { // Use only the specified classes in the package System.out.println("Using the specified classes"); classList = (ArrayList) classesToUse.get(pkgName); } else { // Use all classes in the package classList = new LinkedList(Arrays.asList(pd[i].allClasses())); } Collections.sort(classList); ClassDoc[] classes = new ClassDoc[classList.size()]; classes = (ClassDoc[]) classList.toArray(classes); processClasses(classes, pkgName); addPkgDocumentation(root, pd[i], 2); outputFile.println("</package>"); } } // processPackages