You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Javadoc.java 33 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.tools.ant.taskdefs;
  55. import org.apache.tools.ant.BuildException;
  56. import org.apache.tools.ant.DirectoryScanner;
  57. import org.apache.tools.ant.Project;
  58. import org.apache.tools.ant.types.Path;
  59. import java.io.*;
  60. import java.util.*;
  61. /**
  62. * This task makes it easy to generate Javadoc documentation for a collection
  63. * of source code.
  64. *
  65. * <P>Current known limitations are:
  66. *
  67. * <P><UL>
  68. * <LI>patterns must be of the form "xxx.*", every other pattern doesn't
  69. * work.
  70. * <LI>the java comment-stripper reader is horribly slow
  71. * <LI>there is no control on arguments sanity since they are left
  72. * to the javadoc implementation.
  73. * <LI>argument J in javadoc1 is not supported (what is that for anyway?)
  74. * </UL>
  75. *
  76. * <P>If no <CODE>doclet</CODE> is set, then the <CODE>version</CODE> and
  77. * <CODE>author</CODE> are by default <CODE>"yes"</CODE>.
  78. *
  79. * <P>Note: This task is run on another VM because the Javadoc code calls
  80. * <CODE>System.exit()</CODE> which would break Ant functionality.
  81. *
  82. * @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a>
  83. * @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">stefano@apache.org</a>
  84. * @author Patrick Chanezon <a href="mailto:chanezon@netscape.com">chanezon@netscape.com</a>
  85. * @author Ernst de Haan <a href="mailto:ernst@jollem.com">ernst@jollem.com</a>
  86. */
  87. public class Javadoc extends Exec {
  88. public class DocletParam {
  89. private String name;
  90. private String value;
  91. public void setName(String name) {
  92. this.name = name;
  93. }
  94. public String getName() {
  95. return name;
  96. }
  97. public void setValue(String value) {
  98. this.value = value;
  99. }
  100. public String getValue() {
  101. return value;
  102. }
  103. }
  104. public class DocletInfo {
  105. private String name;
  106. private Path path;
  107. private Vector params = new Vector();
  108. public void setName(String name) {
  109. this.name = name;
  110. }
  111. public String getName() {
  112. return name;
  113. }
  114. public void setPath(Path path) {
  115. if (this.path == null) {
  116. this.path = path;
  117. } else {
  118. this.path.append(path);
  119. }
  120. }
  121. public Path getPath() {
  122. return path;
  123. }
  124. public Path createPath() {
  125. if (path == null) {
  126. path = new Path(getProject());
  127. }
  128. return path;
  129. }
  130. public DocletParam createParam() {
  131. DocletParam param = new DocletParam();
  132. params.addElement(param);
  133. return param;
  134. }
  135. public Enumeration getParams() {
  136. return params.elements();
  137. }
  138. }
  139. private String maxmemory = null;
  140. private Path sourcePath = null;
  141. private String additionalParam = null;
  142. private File destDir = null;
  143. private File overviewFile = null;
  144. private String sourceFiles = null;
  145. private String packageNames = null;
  146. private boolean pub = false;
  147. private boolean prot = false;
  148. private boolean pack = false;
  149. private boolean priv = false;
  150. private boolean author = true;
  151. private boolean version = true;
  152. private DocletInfo doclet = null;
  153. private boolean old = false;
  154. private Path classpath = null;
  155. private Path bootclasspath = null;
  156. private String extdirs = null;
  157. private boolean verbose = false;
  158. private String locale = null;
  159. private String encoding = null;
  160. private boolean use = false;
  161. private boolean splitindex = false;
  162. private String windowtitle = null;
  163. private String doctitle = null;
  164. private String header = null;
  165. private String footer = null;
  166. private String bottom = null;
  167. private String linkoffline = null;
  168. private String link = null;
  169. private String group = null;
  170. private boolean nodeprecated = false;
  171. private boolean nodeprecatedlist = false;
  172. private boolean notree = false;
  173. private boolean noindex = false;
  174. private boolean nohelp = false;
  175. private boolean nonavbar = false;
  176. private boolean serialwarn = false;
  177. private File stylesheetfile = null;
  178. private File helpfile = null;
  179. private String docencoding = null;
  180. private Vector compileList = new Vector(10);
  181. private String packageList = null;
  182. private Vector links = new Vector(2);
  183. private Vector groups = new Vector(2);
  184. private String charset = null;
  185. public void setMaxmemory(String src){
  186. maxmemory = src;
  187. }
  188. public void setadditionalParam(String src){
  189. additionalParam = src;
  190. }
  191. public void setSourcepath(Path src) {
  192. if (sourcePath == null) {
  193. sourcePath = src;
  194. } else {
  195. sourcePath.append(src);
  196. }
  197. }
  198. public Path createSourcepath() {
  199. if (sourcePath == null) {
  200. sourcePath = new Path(project);
  201. }
  202. return sourcePath;
  203. }
  204. public void setDestdir(String src) {
  205. destDir = project.resolveFile(src);
  206. }
  207. public void setSourcefiles(String src) {
  208. sourceFiles = src;
  209. }
  210. public void setPackagenames(String src) {
  211. packageNames = src;
  212. }
  213. public void setOverview(String src) {
  214. overviewFile = project.resolveFile(src);
  215. }
  216. public void setPublic(String src) {
  217. pub = Project.toBoolean(src);
  218. }
  219. public void setProtected(String src) {
  220. prot = Project.toBoolean(src);
  221. }
  222. public void setPackage(String src) {
  223. pack = Project.toBoolean(src);
  224. }
  225. public void setPrivate(String src) {
  226. priv = Project.toBoolean(src);
  227. }
  228. public void setDoclet(String src) {
  229. if (doclet == null) {
  230. doclet = new DocletInfo();
  231. }
  232. doclet.setName(src);
  233. }
  234. public void setDocletPath(Path src) {
  235. if (doclet == null) {
  236. doclet = new DocletInfo();
  237. }
  238. doclet.setPath(src);
  239. }
  240. public DocletInfo createDoclet() {
  241. doclet = new DocletInfo();
  242. return doclet;
  243. }
  244. public void setOld(String src) {
  245. old = Project.toBoolean(src);
  246. }
  247. public void setClasspath(Path src) {
  248. if (classpath == null) {
  249. classpath = src;
  250. } else {
  251. classpath.append(src);
  252. }
  253. }
  254. public Path createClasspath() {
  255. if (classpath == null) {
  256. classpath = new Path(project);
  257. }
  258. return classpath;
  259. }
  260. public void setBootclasspath(Path src) {
  261. if (bootclasspath == null) {
  262. bootclasspath = src;
  263. } else {
  264. bootclasspath.append(src);
  265. }
  266. }
  267. public Path createBootclasspath() {
  268. if (bootclasspath == null) {
  269. bootclasspath = new Path(project);
  270. }
  271. return bootclasspath;
  272. }
  273. public void setExtdirs(String src) {
  274. extdirs = src;
  275. }
  276. public void setVerbose(String src) {
  277. verbose = Project.toBoolean(src);
  278. }
  279. public void setLocale(String src) {
  280. locale = src;
  281. }
  282. public void setEncoding(String src) {
  283. encoding = src;
  284. }
  285. public void setVersion(String src) {
  286. version = Project.toBoolean(src);
  287. }
  288. public void setUse(String src) {
  289. use = Project.toBoolean(src);
  290. }
  291. public void setAuthor(String src) {
  292. author = Project.toBoolean(src);
  293. }
  294. public void setSplitindex(String src) {
  295. splitindex = Project.toBoolean(src);
  296. }
  297. public void setWindowtitle(String src) {
  298. windowtitle = src;
  299. }
  300. public void setDoctitle(String src) {
  301. doctitle = src;
  302. }
  303. public void setHeader(String src) {
  304. header = src;
  305. }
  306. public void setFooter(String src) {
  307. footer = src;
  308. }
  309. public void setBottom(String src) {
  310. bottom = src;
  311. }
  312. public void setLinkoffline(String src) {
  313. linkoffline = src;
  314. }
  315. public void setGroup(String src) {
  316. group = src;
  317. }
  318. public void setLink(String src) {
  319. link = src;
  320. }
  321. public void setNodeprecated(String src) {
  322. nodeprecated = Project.toBoolean(src);
  323. }
  324. public void setNodeprecatedlist(String src) {
  325. nodeprecatedlist = Project.toBoolean(src);
  326. }
  327. public void setNotree(String src) {
  328. notree = Project.toBoolean(src);
  329. }
  330. public void setNoindex(String src) {
  331. noindex = Project.toBoolean(src);
  332. }
  333. public void setNohelp(String src) {
  334. nohelp = Project.toBoolean(src);
  335. }
  336. public void setNonavbar(String src) {
  337. nonavbar = Project.toBoolean(src);
  338. }
  339. public void setSerialwarn(String src) {
  340. serialwarn = Project.toBoolean(src);
  341. }
  342. public void setStylesheetfile(String src) {
  343. stylesheetfile = project.resolveFile(src);
  344. }
  345. public void setDocencoding(String src) {
  346. docencoding = src;
  347. }
  348. public void setPackageList(String src) {
  349. packageList = src;
  350. }
  351. public LinkArgument createLink() {
  352. LinkArgument la = new LinkArgument();
  353. links.addElement(la);
  354. return la;
  355. }
  356. public class LinkArgument {
  357. private String href;
  358. private boolean offline = false;
  359. private String packagelistLoc;
  360. public LinkArgument() {
  361. }
  362. public void setHref(String hr) {
  363. href = hr;
  364. }
  365. public String getHref() {
  366. return href;
  367. }
  368. public void setPackagelistLoc(String src) {
  369. packagelistLoc = src;
  370. }
  371. public String getPackagelistLoc() {
  372. return packagelistLoc;
  373. }
  374. public void setOffline(String offline) {
  375. this.offline = Project.toBoolean(offline);
  376. }
  377. public boolean isLinkOffline() {
  378. return offline;
  379. }
  380. }
  381. public GroupArgument createGroup() {
  382. GroupArgument ga = new GroupArgument();
  383. groups.addElement(ga);
  384. return ga;
  385. }
  386. public class GroupArgument {
  387. private String title;
  388. private String packages;
  389. public GroupArgument() {
  390. }
  391. public void setTitle(String src) {
  392. title = src;
  393. }
  394. public String getTitle() {
  395. return title;
  396. }
  397. public void setPackages(String src) {
  398. packages = src;
  399. }
  400. public String getPackages() {
  401. return packages;
  402. }
  403. }
  404. public void setCharset(String src) {
  405. charset = src;
  406. }
  407. public void execute() throws BuildException {
  408. if ("javadoc2".equals(taskType)) {
  409. log("!! javadoc2 is deprecated. Use javadoc instead. !!");
  410. }
  411. if (sourcePath == null || destDir == null ) {
  412. String msg = "sourcePath and destDir attributes must be set!";
  413. throw new BuildException(msg);
  414. }
  415. boolean javadoc1 = (Project.getJavaVersion() == Project.JAVA_1_1);
  416. log("Generating Javadoc", Project.MSG_INFO);
  417. Vector argList = new Vector();
  418. // ------------------------------------------------ general javadoc arguments
  419. if (classpath == null)
  420. classpath = Path.systemClasspath;
  421. if(maxmemory != null){
  422. if(javadoc1){
  423. argList.addElement("-J-mx" + maxmemory);
  424. }
  425. else{
  426. argList.addElement("-J-Xmx" + maxmemory);
  427. }
  428. }
  429. if ( (!javadoc1) || (sourcePath == null) ) {
  430. argList.addElement("-classpath");
  431. argList.addElement(classpath.toString());
  432. if (sourcePath != null) {
  433. argList.addElement("-sourcepath");
  434. argList.addElement(sourcePath.toString());
  435. }
  436. } else {
  437. argList.addElement("-classpath");
  438. argList.addElement(sourcePath.toString() +
  439. System.getProperty("path.separator") + classpath.toString());
  440. }
  441. if (destDir != null) {
  442. argList.addElement("-d");
  443. argList.addElement(destDir.getAbsolutePath());
  444. }
  445. if (version && doclet == null)
  446. argList.addElement ("-version");
  447. if (nodeprecated)
  448. argList.addElement ("-nodeprecated");
  449. if (author && doclet == null)
  450. argList.addElement ("-author");
  451. if (noindex)
  452. argList.addElement ("-noindex");
  453. if (notree)
  454. argList.addElement ("-notree");
  455. if (pub)
  456. argList.addElement ("-public");
  457. if (prot)
  458. argList.addElement ("-protected");
  459. if (pack)
  460. argList.addElement ("-package");
  461. if (priv)
  462. argList.addElement ("-private");
  463. if (encoding != null) {
  464. argList.addElement("-encoding");
  465. argList.addElement(encoding);
  466. }
  467. if (docencoding != null) {
  468. argList.addElement("-docencoding");
  469. argList.addElement(docencoding);
  470. }
  471. // --------------------------------- javadoc2 arguments for default doclet
  472. // XXX: how do we handle a custom doclet?
  473. if (!javadoc1) {
  474. if (overviewFile != null) {
  475. argList.addElement("-overview");
  476. argList.addElement(overviewFile.getAbsolutePath());
  477. }
  478. if (old)
  479. argList.addElement("-1.1");
  480. if (verbose)
  481. argList.addElement("-verbose");
  482. if (use)
  483. argList.addElement("-use");
  484. if (splitindex)
  485. argList.addElement("-splitindex");
  486. if (nodeprecatedlist)
  487. argList.addElement("-nodeprecatedlist");
  488. if (nohelp)
  489. argList.addElement("-nohelp");
  490. if (nonavbar)
  491. argList.addElement("-nonavbar");
  492. if (serialwarn)
  493. argList.addElement("-serialwarn");
  494. if (doclet != null) {
  495. if (doclet.getName() == null) {
  496. throw new BuildException("The doclet name must be specified.");
  497. }
  498. else {
  499. argList.addElement("-doclet");
  500. argList.addElement(doclet.getName());
  501. if (doclet.getPath() != null) {
  502. argList.addElement("-docletpath");
  503. argList.addElement(doclet.getPath().toString());
  504. }
  505. for (Enumeration e = doclet.getParams(); e.hasMoreElements();) {
  506. DocletParam param = (DocletParam)e.nextElement();
  507. if (param.getName() == null) {
  508. throw new BuildException("Doclet parameters must have a name");
  509. }
  510. argList.addElement(param.getName());
  511. if (param.getValue() != null) {
  512. argList.addElement(param.getValue());
  513. }
  514. }
  515. }
  516. }
  517. if (bootclasspath != null) {
  518. argList.addElement("-bootclasspath");
  519. argList.addElement(bootclasspath.toString());
  520. }
  521. if (extdirs != null) {
  522. argList.addElement("-extdirs");
  523. argList.addElement(extdirs);
  524. }
  525. if (locale != null) {
  526. argList.addElement("-locale");
  527. argList.addElement(locale);
  528. }
  529. if (encoding != null) {
  530. argList.addElement("-encoding");
  531. argList.addElement(encoding);
  532. }
  533. if (windowtitle != null) {
  534. argList.addElement("-windowtitle");
  535. argList.addElement(windowtitle);
  536. }
  537. if (doctitle != null) {
  538. argList.addElement("-doctitle");
  539. argList.addElement(doctitle);
  540. }
  541. if (header != null) {
  542. argList.addElement("-header");
  543. argList.addElement(header);
  544. }
  545. if (footer != null) {
  546. argList.addElement("-footer");
  547. argList.addElement(footer);
  548. }
  549. if (bottom != null) {
  550. argList.addElement("-bottom");
  551. argList.addElement(bottom);
  552. }
  553. // add the single link arguments
  554. if (link != null) {
  555. argList.addElement("-link");
  556. argList.addElement(link);
  557. }
  558. // add the links arguments
  559. if (links.size() != 0) {
  560. for (Enumeration e = links.elements(); e.hasMoreElements(); ) {
  561. LinkArgument la = (LinkArgument)e.nextElement();
  562. if (la.getHref() == null) {
  563. throw new BuildException("Links must provide the RUL to the external class documentation.");
  564. }
  565. if (la.isLinkOffline()) {
  566. String packageListLocation = la.getPackagelistLoc();
  567. if (packageListLocation == null) {
  568. throw new BuildException("The package list location for link " + la.getHref() +
  569. " must be provided because the link is offline");
  570. }
  571. argList.addElement("-linkoffline");
  572. argList.addElement(la.getHref());
  573. argList.addElement(packageListLocation);
  574. }
  575. else {
  576. argList.addElement("-link");
  577. argList.addElement(la.getHref());
  578. }
  579. }
  580. }
  581. // add the single linkoffline arguments
  582. if (linkoffline != null) {
  583. argList.addElement("-linkoffline");
  584. argList.addElement(linkoffline);
  585. }
  586. // add the single group arguments
  587. // Javadoc 1.2 rules:
  588. // Multiple -group args allowed.
  589. // Each arg includes 3 strings: -group [name] [packagelist].
  590. // Elements in [packagelist] are colon-delimited.
  591. // An element in [packagelist] may end with the * wildcard.
  592. // Ant javadoc task rules for group attribute:
  593. // Args are comma-delimited.
  594. // Each arg is 2 space-delimited strings.
  595. // E.g., group="XSLT_Packages org.apache.xalan.xslt*,XPath_Packages orgapache.xalan.xpath*"
  596. if (group != null) {
  597. StringTokenizer tok = new StringTokenizer(group, ",", false);
  598. while (tok.hasMoreTokens()) {
  599. String grp = tok.nextToken().trim();
  600. int space = grp.indexOf(" ");
  601. if (space > 0){
  602. String name = grp.substring(0, space);
  603. String pkgList = grp.substring(space + 1);
  604. argList.addElement("-group");
  605. argList.addElement(name);
  606. argList.addElement(pkgList);
  607. }
  608. }
  609. }
  610. // add the group arguments
  611. if (groups.size() != 0) {
  612. for (Enumeration e = groups.elements(); e.hasMoreElements(); ) {
  613. GroupArgument ga = (GroupArgument)e.nextElement();
  614. String title = ga.getTitle();
  615. String packages = ga.getPackages();
  616. if (title == null || packages == null) {
  617. throw new BuildException("The title and packages must be specified for group elements.");
  618. }
  619. argList.addElement("-group");
  620. argList.addElement(title);
  621. argList.addElement(packages);
  622. }
  623. }
  624. if (stylesheetfile != null) {
  625. argList.addElement("-stylesheetfile");
  626. argList.addElement(stylesheetfile.getAbsolutePath());
  627. }
  628. if (helpfile != null) {
  629. argList.addElement("-helpfile");
  630. argList.addElement(helpfile.getAbsolutePath());
  631. }
  632. if (charset != null) {
  633. argList.addElement("-charset");
  634. argList.addElement(charset);
  635. }
  636. if (additionalParam != null) {
  637. argList.addElement(additionalParam);
  638. }
  639. }
  640. if ((packageNames != null) && (packageNames.length() > 0)) {
  641. Vector packages = new Vector();
  642. StringTokenizer tok = new StringTokenizer(packageNames, ",", false);
  643. while (tok.hasMoreTokens()) {
  644. String name = tok.nextToken().trim();
  645. if (name.endsWith(".*")) {
  646. packages.addElement(name);
  647. } else {
  648. argList.addElement(name);
  649. }
  650. }
  651. if (packages.size() > 0) {
  652. evaluatePackages(sourcePath, packages, argList);
  653. }
  654. }
  655. if ((sourceFiles != null) && (sourceFiles.length() > 0)) {
  656. StringTokenizer tok = new StringTokenizer(sourceFiles, ",", false);
  657. while (tok.hasMoreTokens()) {
  658. argList.addElement(tok.nextToken().trim());
  659. }
  660. }
  661. if (packageList != null) {
  662. argList.addElement("@" + packageList);
  663. }
  664. log("Javadoc args: " + argList.toString(), Project.MSG_VERBOSE);
  665. log("Javadoc execution", Project.MSG_INFO);
  666. StringBuffer b = new StringBuffer();
  667. b.append("javadoc ");
  668. Enumeration e = argList.elements();
  669. while (e.hasMoreElements()) {
  670. String arg = (String) e.nextElement();
  671. if (!arg.startsWith("-")) {
  672. b.append("\"");
  673. b.append(arg);
  674. b.append("\"");
  675. } else {
  676. b.append(arg);
  677. }
  678. if (e.hasMoreElements()) b.append(" ");
  679. }
  680. run(b.toString());
  681. }
  682. /**
  683. * Given a source path, a list of package patterns, fill the given list
  684. * with the packages found in that path subdirs matching one of the given
  685. * patterns.
  686. */
  687. private void evaluatePackages(Path sourcePath, Vector packages, Vector argList) {
  688. log("Parsing source files for packages", Project.MSG_INFO);
  689. log("Source path = " + sourcePath.toString(), Project.MSG_VERBOSE);
  690. log("Packages = " + packages, Project.MSG_VERBOSE);
  691. Vector addedPackages = new Vector();
  692. String[] list = sourcePath.list();
  693. for (int j=0; j<list.length; j++) {
  694. File source = project.resolveFile(list[j]);
  695. Hashtable map = mapClasses(source);
  696. Enumeration e = map.keys();
  697. while (e.hasMoreElements()) {
  698. String pack = (String) e.nextElement();
  699. for (int i = 0; i < packages.size(); i++) {
  700. if (matches(pack, (String) packages.elementAt(i))) {
  701. if (!addedPackages.contains(pack)) {
  702. argList.addElement(pack);
  703. addedPackages.addElement(pack);
  704. }
  705. break;
  706. }
  707. }
  708. }
  709. }
  710. }
  711. /**
  712. * Implements the pattern matching. For now it's only able to
  713. * guarantee that "aaa.bbb.ccc" matches "aaa.*" and "aaa.bbb.*"
  714. * FIXME: this code needs much improvement.
  715. */
  716. private boolean matches(String string, String pattern) {
  717. return string.startsWith(pattern.substring(0, pattern.length() - 2));
  718. }
  719. /**
  720. * Returns an hashtable of packages linked to the last parsed
  721. * file in that package. This map is use to return a list of unique
  722. * packages as map keys.
  723. */
  724. private Hashtable mapClasses(File path) {
  725. Hashtable map = new Hashtable();
  726. Vector files = new Vector();
  727. getFiles(path, files);
  728. Enumeration e = files.elements();
  729. while (e.hasMoreElements()) {
  730. File file = (File) e.nextElement();
  731. String packageName = getPackageName(file);
  732. if (packageName != null) map.put(packageName, file);
  733. }
  734. return map;
  735. }
  736. /**
  737. * Fills the given vector with files under the given path filtered
  738. * by the given file filter.
  739. */
  740. private void getFiles(File path, Vector list) {
  741. if (!path.exists()) {
  742. throw new BuildException("Path " + path + " does not exist.");
  743. }
  744. String[] files = path.list();
  745. String cwd = path.getPath() + System.getProperty("file.separator");
  746. if (files != null) {
  747. int count = 0;
  748. for (int i = 0; i < files.length; i++) {
  749. File file = new File(cwd + files[i]);
  750. if (file.isDirectory()) {
  751. getFiles(file, list);
  752. } else if (files[i].endsWith(".java")) {
  753. count++;
  754. list.addElement(file);
  755. }
  756. }
  757. if (count > 0) {
  758. log("found " + count + " source files in " + path, Project.MSG_VERBOSE);
  759. }
  760. } else {
  761. throw new BuildException("Error occurred during " + path + " evaluation.");
  762. }
  763. }
  764. /**
  765. * Return the package name of the given java source file.
  766. * This method performs valid java parsing to figure out the package.
  767. */
  768. private String getPackageName(File file) {
  769. String name = null;
  770. try {
  771. // do not remove the double buffered reader, this is a _major_ speed up in this special case!
  772. BufferedReader reader = new BufferedReader(new JavaReader(new BufferedReader(new FileReader(file))));
  773. String line;
  774. while (true) {
  775. line = reader.readLine();
  776. if (line == null) {
  777. log("Could not evaluate package for " + file, Project.MSG_WARN);
  778. return null;
  779. }
  780. if (line.trim().startsWith("package ") ||
  781. line.trim().startsWith("package\t")) {
  782. name = line.substring(8, line.indexOf(";")).trim();
  783. break;
  784. }
  785. }
  786. reader.close();
  787. } catch (Exception e) {
  788. log("Exception " + e + " parsing " + file, Project.MSG_WARN);
  789. return null;
  790. }
  791. log(file + " --> " + name, Project.MSG_VERBOSE);
  792. return name;
  793. }
  794. //
  795. // Override the logging of output in order to filter out Generating
  796. // messages. Generating messages are set to a priority of VERBOSE
  797. // unless they appear after what could be an informational message.
  798. //
  799. private String queuedLine = null;
  800. protected void outputLog(String line, int messageLevel) {
  801. if (messageLevel==project.MSG_INFO && line.startsWith("Generating ")) {
  802. if (queuedLine != null) {
  803. super.outputLog(queuedLine, Project.MSG_VERBOSE);
  804. }
  805. queuedLine = line;
  806. } else {
  807. if (queuedLine != null) {
  808. if (line.startsWith("Building "))
  809. super.outputLog(queuedLine, Project.MSG_VERBOSE);
  810. else
  811. super.outputLog(queuedLine, Project.MSG_INFO);
  812. queuedLine = null;
  813. }
  814. super.outputLog(line, messageLevel);
  815. }
  816. }
  817. protected void logFlush() {
  818. if (queuedLine != null) {
  819. super.outputLog(queuedLine, Project.MSG_VERBOSE);
  820. queuedLine = null;
  821. }
  822. super.logFlush();
  823. }
  824. /**
  825. * This is a java comment and string stripper reader that filters
  826. * these lexical tokens out for purposes of simple Java parsing.
  827. * (if you have more complex Java parsing needs, use a real lexer).
  828. * Since this class heavily relies on the single char read function,
  829. * you are reccomended to make it work on top of a buffered reader.
  830. */
  831. class JavaReader extends FilterReader {
  832. public JavaReader(Reader in) {
  833. super(in);
  834. }
  835. public int read() throws IOException {
  836. int c = in.read();
  837. if (c == '/') {
  838. c = in.read();
  839. if (c == '/') {
  840. while (c != '\n' && c != -1) c = in.read();
  841. } else if (c == '*') {
  842. while (c != -1) {
  843. c = in.read();
  844. if (c == '*') {
  845. c = in.read();
  846. while (c == '*' && c != -1) {
  847. c = in.read();
  848. }
  849. if (c == '/') {
  850. c = read();
  851. break;
  852. }
  853. }
  854. }
  855. }
  856. }
  857. if (c == '"') {
  858. while (c != -1) {
  859. c = in.read();
  860. if (c == '\\') {
  861. c = in.read();
  862. } else if (c == '"') {
  863. c = read();
  864. break;
  865. }
  866. }
  867. }
  868. if (c == '\'') {
  869. c = in.read();
  870. if (c == '\\') c = in.read();
  871. c = in.read();
  872. c = read();
  873. }
  874. return c;
  875. }
  876. public int read(char cbuf[], int off, int len) throws IOException {
  877. for (int i = 0; i < len; i++) {
  878. int c = read();
  879. if (c == -1) {
  880. if (i == 0) {
  881. return -1;
  882. } else {
  883. return i;
  884. }
  885. }
  886. cbuf[off + i] = (char) c;
  887. }
  888. return len;
  889. }
  890. public long skip(long n) throws IOException {
  891. for (long i = 0; i < n; i++) {
  892. if (in.read() == -1) return i;
  893. }
  894. return n;
  895. }
  896. }
  897. }