1. /**
  2. * Copyright: Copyright (c) 2002-2004
  3. * Company: JavaResearch(http://www.javaresearch.org)
  4. */
  5. package org.jr.java2html;
  6. import java.io.BufferedReader;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileNotFoundException;
  10. import java.io.IOException;
  11. import java.io.PrintStream;
  12. import java.io.StringWriter;
  13. import java.util.ArrayList;
  14. import java.util.Collections;
  15. import java.util.Enumeration;
  16. import java.util.HashMap;
  17. import java.util.Iterator;
  18. import java.util.Properties;
  19. import java.util.ResourceBundle;
  20. import java.util.TreeMap;
  21. import org.jr.io.FileUtil;
  22. import org.jr.io.FileWriter;
  23. import org.jr.util.StringUtil;
  24. /**
  25. * 将一个目录下的源代码全部转换为类似javadoc生成的文档的结构的HTML版本源代码生成器。
  26. * 这个类是应用的主类,如果你使用其他几个类并且模仿本类的代码可以生成你自己的应用,当然不局限于生成源代码文档,可能是其他的什么文档都可以。
  27. * 底层的设计是没有针对性的,但是可能不能考虑所有的应用。
  28. * 请注意这个根工具和javadoc的不同在于它没有javadoc那样的功能可以调用javac完成类的解析。
  29. * 这个工具生成良好的文档需要依赖你的源代码的组织是良好的,例如符合JBuilder的源代码组织的强制要求(包名和源代码的组织应该一致)。
  30. * <br>最后更新日期:2004年8月31日
  31. * @author cherami@javaresearch.org
  32. * @version 0.9
  33. */
  34. public class JavaToHTMLCreator {
  35. /**
  36. * 替换模版中CREATOR属性用的字符串。
  37. */
  38. static final String CREATOR =
  39. "JavaToHTMLCreator(http://www.javaresearch.org)";
  40. /**
  41. * 替换模版中的其他区域相关的常量的资源束。
  42. */
  43. static final ResourceBundle resources = ResourceBundle.getBundle(
  44. "org.jr.java2html.resources");
  45. TemplatePropertyMap properties = Utility.convertTo(resources);
  46. String templatePath="templates/";
  47. public static final String INDEX_TEMPLATE = "index.html";
  48. public static final String ALL_PACKAGES_TEMPLATE = "allpackages.html";
  49. public static final String ALL_CLASSES_TEMPLATE = "allclasses.html";
  50. public static final String COPYRIGHT_TEMPLATE = "copyright.html";
  51. public static final String PACKAGE_TEMPLATE = "package.html";
  52. public static final String CLASS_TEMPLATE = "class.html";
  53. public static final String JAVA2HTML_JS = "java2html.js";
  54. public static final String STYLESHEET_CSS = "stylesheet.css";
  55. public static final String MAP_LIST = "maplist.txt";
  56. public static final String CLASS_MAP = "classpath.map";
  57. protected static final String HTML_EXT = ".java.html";
  58. static LinkableJavaToHTML converter ;
  59. String code = "gb2312";
  60. String userPropertiesFile;
  61. /**
  62. * 构造一个JavaToHTMLCreator并添加共通的属性。
  63. */
  64. public JavaToHTMLCreator() {
  65. addCommonProperties();
  66. }
  67. /**
  68. * 应用的入口方法。
  69. * @param args 命令行参数数组
  70. */
  71. public static void main(String[] args) {
  72. if (args.length < 2) {
  73. printUsage(System.out);
  74. StringUtil.printStrings(args);
  75. System.exit(1);
  76. }
  77. JavaToHTMLCreator htmlCreator = new JavaToHTMLCreator();
  78. String sourcePath = args[0];
  79. String destPath = args[1];
  80. if (args.length > 2) {
  81. htmlCreator.setUserPropertyFile(args[2]);
  82. }
  83. if (args.length > 3) {
  84. htmlCreator.setTemplatePath(args[3]+"/");
  85. }
  86. String code=System.getProperty("java2html.code");
  87. if (code!=null) {
  88. htmlCreator.setCode(code);
  89. }
  90. String debug=System.getProperty("java2html.debugable");
  91. if (debug!=null) {
  92. boolean debugable=Boolean.getBoolean(debug);
  93. Utility.setDebugable(debugable);
  94. }
  95. try {
  96. File dest=new File(destPath);
  97. if (!dest.exists()) {
  98. dest.mkdirs();
  99. }
  100. FileUtil.copy(htmlCreator.templatePath + JAVA2HTML_JS, (destPath + "/" + JAVA2HTML_JS).replace('\\','/'), true);
  101. FileUtil.copy(htmlCreator.templatePath + STYLESHEET_CSS,
  102. (destPath + "/" + STYLESHEET_CSS).replace('\\','/'), true);
  103. htmlCreator.createIndexFile(destPath);
  104. htmlCreator.createCopyrightFile(destPath);
  105. HashMap classMap=new HashMap();
  106. TreeMap dirs = Utility.analyseDirectory(sourcePath,classMap);
  107. FileWriter.writeObject(destPath+"/"+CLASS_MAP,classMap);
  108. ClassLink classLink=ClassLink.getClassLink(MAP_LIST);
  109. classLink.put(classMap,"");
  110. converter = new LinkableJavaToHTML(classLink);
  111. htmlCreator.createAllPackagesFile(destPath, dirs);
  112. htmlCreator.createAllClassesFile(destPath, dirs);
  113. htmlCreator.createPackageFiles(destPath, dirs);
  114. htmlCreator.createClassFiles(sourcePath, destPath, dirs);
  115. }
  116. catch (IOException e) {
  117. e.printStackTrace();
  118. }
  119. }
  120. public static void printUsage(PrintStream out) {
  121. out.println(
  122. "Usage:java [-Djava2html.code=code] [-Djava2html.debugable=false/true] org.jr.java2html.JavaToHTMLCreator sourceDir destDir [userPropertiesFile] [templatePath]");
  123. out.println(
  124. " or java -jar [-Djava2html.code=code] [-Djava2html.debugable=false/true] java2html.jar sourceDir destDir [userPropertiesFile] [templatePath]");
  125. }
  126. /**
  127. * 设置生成的HTML文件的编码方式。
  128. * @param code 编码方式
  129. */
  130. public void setCode(String code) {
  131. this.code = code;
  132. properties.put("CODE", code);
  133. }
  134. /**
  135. * 设置用户定义的属性文件的文件名
  136. * @param fileName 属性文件文件名
  137. */
  138. public void setUserPropertyFile(String fileName) {
  139. userPropertiesFile = fileName;
  140. Properties userProperties=new Properties();
  141. try {
  142. userProperties.load(new FileInputStream(userPropertiesFile));
  143. Enumeration keys=userProperties.propertyNames();
  144. while (keys.hasMoreElements()) {
  145. String key=(String)keys.nextElement();
  146. String value=userProperties.getProperty(key);
  147. properties.put(key,value);
  148. }
  149. }
  150. catch (FileNotFoundException fe) {
  151. System.err.println(fe.getMessage());
  152. }
  153. catch (IOException ioe) {
  154. System.err.println(ioe.getMessage());
  155. }
  156. }
  157. /**
  158. * 设置模版文件的目录。
  159. * 因此可以自己修改模版,但是还不能支持动态的设置模版的文件名。
  160. * 文件名必须和自带的模版的文件名完全一致。
  161. * @param templatePath 模版目录
  162. */
  163. public void setTemplatePath(String templatePath) {
  164. this.templatePath = templatePath;
  165. }
  166. private boolean createIndexFile(String destPath) throws IOException {
  167. TemplateFile file = new TemplateFile(templatePath + INDEX_TEMPLATE);
  168. file.setFile(destPath + "/" + INDEX_TEMPLATE);
  169. file.setProperties(properties);
  170. return file.createFile();
  171. }
  172. private boolean createCopyrightFile(String destPath) throws
  173. IOException {
  174. TemplateFile file = new TemplateFile(templatePath +
  175. COPYRIGHT_TEMPLATE);
  176. file.setFile(destPath + "/" + COPYRIGHT_TEMPLATE);
  177. file.setProperties(properties);
  178. return file.createFile();
  179. }
  180. private boolean createAllPackagesFile(String destPath,
  181. TreeMap packages) throws
  182. IOException {
  183. TemplateFile file = new TemplateFile(templatePath +
  184. ALL_PACKAGES_TEMPLATE);
  185. file.setFile(destPath + "/" + ALL_PACKAGES_TEMPLATE);
  186. TemplatePropertyMap loopProperties = new TemplatePropertyMap();
  187. properties.put(TemplateFile.getLoopName(0), loopProperties);
  188. int packageCount = packages.size() - 1;
  189. loopProperties.put(TemplateFile.SIZE, String.valueOf(packageCount));
  190. Iterator keys = packages.keySet().iterator();
  191. keys.next(); //跳过全部类对应的那个元素
  192. ArrayList packageNames = new ArrayList();
  193. ArrayList packagePaths = new ArrayList();
  194. while (keys.hasNext()) {
  195. String packageName = (String) keys.next();
  196. packageNames.add(packageName);
  197. packagePaths.add(packageName.replace('.', '/'));
  198. }
  199. loopProperties.put("PACKAGE_PATH", packagePaths);
  200. loopProperties.put("PACKAGE_NAME", packageNames);
  201. file.setProperties(properties);
  202. return file.createFile();
  203. }
  204. private boolean createAllClassesFile(String destPath, TreeMap packages) throws
  205. IOException {
  206. boolean result;
  207. TemplateFile file = new TemplateFile(templatePath +
  208. ALL_CLASSES_TEMPLATE);
  209. file.setFile(destPath + "/" + ALL_CLASSES_TEMPLATE);
  210. TemplatePropertyMap loopProperties = new TemplatePropertyMap();
  211. properties.put(TemplateFile.getLoopName(0), loopProperties);
  212. ArrayList fullClassNames = (ArrayList) packages.get(Utility.ALL_CLASSES);
  213. Collections.sort(fullClassNames, new ClassNameComparator());
  214. loopProperties.put(TemplateFile.SIZE,
  215. String.valueOf(fullClassNames.size()));
  216. ArrayList packagePaths = new ArrayList();
  217. ArrayList classFiles = new ArrayList();
  218. ArrayList classNames = new ArrayList();
  219. for (int i = 0; i < fullClassNames.size(); i++) {
  220. String fullClassName = (String) fullClassNames.get(i);
  221. int lastIndex = fullClassName.lastIndexOf(".");
  222. if (lastIndex > 0) {
  223. packagePaths.add(fullClassName.substring(0, lastIndex).replace('.', '/'));
  224. classFiles.add(fullClassName.substring(lastIndex + 1) + HTML_EXT);
  225. classNames.add(fullClassName.substring(lastIndex + 1));
  226. }
  227. else {
  228. packagePaths.add(".");
  229. classFiles.add(fullClassName + HTML_EXT);
  230. classNames.add(fullClassName);
  231. }
  232. }
  233. loopProperties.put("PACKAGE_PATH", packagePaths);
  234. loopProperties.put("CLASS_FILE", classFiles);
  235. loopProperties.put("CLASS_NAME", classNames);
  236. file.setProperties(properties);
  237. result = file.createFile();
  238. return result;
  239. }
  240. private boolean createPackageFiles(String destPath, TreeMap packages) throws
  241. IOException {
  242. boolean result = true;
  243. TemplateFile file = new TemplateFile(templatePath +
  244. PACKAGE_TEMPLATE);
  245. file.setBufferable(true);
  246. Iterator keys = packages.keySet().iterator();
  247. keys.next(); //跳过全部类对应的那个元素
  248. while (keys.hasNext()) {
  249. String packageName = (String) keys.next();
  250. String packagePath = packageName.replace('.', '/');
  251. int packageDeep = 0;
  252. if (packageName.length() > 0) {
  253. packageDeep = 1;
  254. }
  255. String stylePath = Utility.fill("../",
  256. StringUtil.getSubtringCount(packageName, ".") +
  257. packageDeep);
  258. stylePath = stylePath.substring(0, stylePath.length() - 1);
  259. properties.put("PACKAGE_TITLE", packageName);
  260. properties.put("PACKAGE_NAME", packageName);
  261. properties.put("COMMONFILE_PATH", stylePath);
  262. file.setFile(destPath + "/" + packagePath + "/" + PACKAGE_TEMPLATE);
  263. file.setProperties(properties);
  264. TemplatePropertyMap loopProperties = new TemplatePropertyMap();
  265. properties.put(TemplateFile.getLoopName(0), loopProperties);
  266. ArrayList classNames = (ArrayList) packages.get(packageName);
  267. Collections.sort(classNames, new ClassNameComparator());
  268. ArrayList classFiles = new ArrayList();
  269. for (int i = 0; i < classNames.size(); i++) {
  270. classFiles.add(classNames.get(i) + HTML_EXT);
  271. }
  272. int classCount = classNames.size();
  273. loopProperties.put(TemplateFile.SIZE, String.valueOf(classCount));
  274. loopProperties.put("CLASS_FILE", classFiles);
  275. loopProperties.put("CLASS_NAME", classNames);
  276. if (!file.createFile()) {
  277. result = false;
  278. }
  279. }
  280. return result;
  281. }
  282. private boolean createClassFiles(String sourcePath, String destPath,
  283. TreeMap packages) throws
  284. IOException {
  285. boolean result = true;
  286. TemplateFile file = new TemplateFile(templatePath +
  287. CLASS_TEMPLATE);
  288. file.setBufferable(true);
  289. file.setProperties(properties);
  290. ArrayList fullClassNames = (ArrayList) packages.get(Utility.ALL_CLASSES);
  291. for (int i = 0; i < fullClassNames.size(); i++) {
  292. String fullClassName = (String) fullClassNames.get(i);
  293. String packagePath;
  294. String className;
  295. int lastIndex = fullClassName.lastIndexOf(".");
  296. if (lastIndex > 0) {
  297. packagePath = fullClassName.substring(0, lastIndex).replace('.', '/');
  298. className = fullClassName.substring(lastIndex + 1);
  299. }
  300. else {
  301. packagePath = ".";
  302. className = fullClassName;
  303. }
  304. int packageDeep = 0;
  305. if (!packagePath.equals(".")) {
  306. packageDeep = 1;
  307. }
  308. String stylePath = Utility.fill("../",
  309. StringUtil.getSubtringCount(packagePath, "/") +
  310. packageDeep);
  311. if (packageDeep != 0) {
  312. stylePath = Utility.trimLastChar(stylePath);
  313. }
  314. else {
  315. stylePath = ".";
  316. }
  317. properties.put("CLASS_TITLE", className);
  318. properties.put("COMMONFILE_PATH", stylePath);
  319. BufferedReader reader = new BufferedReader(new java.io.FileReader(sourcePath +
  320. "/" + packagePath + "/" + className + ".java"));
  321. StringWriter writer = new StringWriter();
  322. converter.convert(reader, writer,packagePath);
  323. properties.put("CLASS_SOURCE", writer.toString());
  324. file.setFile(destPath + "/" + packagePath + "/" + className +
  325. HTML_EXT);
  326. if (!file.createFile()) {
  327. result = false;
  328. }
  329. }
  330. return result;
  331. }
  332. private void addCommonProperties() {
  333. properties.put("CREATOR", CREATOR);
  334. properties.put("CODE", code);
  335. }
  336. }