001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.tools.website;
051:
052: import java.io.File;
053: import java.io.BufferedReader;
054: import java.io.FileReader;
055: import java.io.FilenameFilter;
056: import java.io.IOException;
057: import java.net.URI;
058: import org.jaffa.util.StringHelper;
059: import java.io.BufferedWriter;
060: import java.io.Writer;
061: import java.io.FileWriter;
062: import org.jaffa.datatypes.DateTime;
063:
064: /**
065: *
066: * @author PaulE
067: */
068: public class GenerateTOC {
069:
070: private static String DEFAULT_ROOT = "c:/sandbox.sf/WebSite/dist";
071: private static String DEFAULT_OUTFILE = "toc.html";
072:
073: StringBuffer html = new StringBuffer();
074: int lastlevel = 0;
075: File root = null;
076:
077: GenerateTOC(String useRoot, String useOutfile) {
078: startHtml();
079: root = new File((useRoot == null ? DEFAULT_ROOT : useRoot));
080: processDir(root, 0, null);
081: endHtml();
082: //System.out.prinln("-------------------------------");
083: //System.out.println(html.toString());
084: try {
085: File out = new File(root.getAbsolutePath()
086: + File.separator
087: + (useOutfile == null ? DEFAULT_OUTFILE
088: : useOutfile));
089: Writer writer = new BufferedWriter(new FileWriter(out,
090: false));
091: writer.write(html.toString());
092: writer.close();
093: } catch (IOException e) {
094: System.out
095: .println("Failed to write out table of contents - "
096: + e.getMessage());
097: }
098:
099: }
100:
101: void processDir(File dir, int level, String prefix) {
102: if (!dir.isDirectory()) {
103: System.out.println("Not A Directory!");
104: return;
105: }
106: System.out.println("Process Dir " + prefix + ": "
107: + dir.getAbsolutePath());
108: int indexCounter = 1;
109: File[] contents = dir.listFiles(new DirFilter());
110: for (int i = 0; i < contents.length; i++) {
111: File file = contents[i];
112: System.out.println("..Process " + file.getAbsolutePath());
113: if (file.isDirectory()) {
114: // see if there is an index.htm* file
115: File[] idxs = file.listFiles(new IndexFilter());
116: boolean indexed = false;
117: for (int j = 0; j < idxs.length; j++) {
118: File idx = idxs[j];
119: if (includeInIndex(idx, level, (prefix == null ? ""
120: : prefix + ".")
121: + indexCounter)) {
122: indexed = true;
123: break;
124: }
125: }
126:
127: // if(!indexed) {
128: // // Fake index
129: // System.out.println("Make Fake index entry for " + file.getName());
130: // writeHtml(file.getAbsolutePath(), file.getName(), "Browse this folder", level, (prefix==null?"":prefix + ".") + indexCounter);
131: // }
132: // this was a good directory, look for more
133: if (indexed) {
134: processDir(file, level + 1, (prefix == null ? ""
135: : prefix + ".")
136: + indexCounter);
137: indexCounter++;
138: }
139: } else {
140: // process this file (ignore indexes!)
141: if (!file.getName().toLowerCase().startsWith("index."))
142: if (includeInIndex(file, level,
143: (prefix == null ? "" : prefix + ".")
144: + indexCounter)) {
145: indexCounter++;
146: }
147: }
148: }
149: }
150:
151: boolean includeInIndex(File f, int level, String section) {
152: try {
153: System.out.println("File : " + f.getAbsolutePath());
154: // Read the file into a buffer
155: StringBuffer data = new StringBuffer();
156: BufferedReader reader = new BufferedReader(
157: new FileReader(f));
158: String line = null;
159: while ((line = reader.readLine()) != null) {
160: data.append(line);
161: }
162: reader.close();
163:
164: String contents = data.toString();
165: String search = contents.toLowerCase();
166:
167: String title = null;
168: String desc = null;
169: int p1 = search.indexOf("<title>");
170: if (p1 > 0) {
171: p1 = p1 + 7;
172: int p2 = search.indexOf("</title>", p1);
173: if (p2 > 0) {
174: title = contents.substring(p1, p2);
175: }
176: }
177:
178: int startTag = 0;
179: while (startTag >= 0) {
180: startTag = search.indexOf("<meta ", startTag);
181: if (startTag > 0) {
182: //System.out.println("a");
183: startTag = startTag + 6;
184: int endTag = search.indexOf(">", startTag);
185: if (endTag > 0) {
186: // must be in range p1->p2
187: //System.out.println("b "+startTag+"-"+endTag);
188: int p3 = search.indexOf("name=\"description\"",
189: startTag);
190: if (p3 > 0 && p3 < endTag) {
191: //System.out.println("c");
192: int p4 = search
193: .indexOf("content", startTag);
194: if (p4 > 0 && p4 < endTag) {
195: //System.out.println("d");
196: int start = search.indexOf("\"", p4);
197: if (start > 0 && start < endTag) {
198: //System.out.println("e");
199: start = start + 1;
200: int end = search.indexOf("\"",
201: start);
202: if (end > 0 && end < endTag) {
203: //System.out.println("f "+start+"-"+end);
204: desc = contents.substring(
205: start, end);
206: }
207: }
208: }
209: }
210: }
211: }
212: }
213:
214: System.out.println("Title : " + title);
215: System.out.println("Desc : " + desc);
216:
217: //if(desc==null) System.exit(1);
218:
219: if (title != null) {
220: writeHtml(f.getAbsolutePath(), title, desc, level,
221: section);
222: } else {
223: //System.out.println("..Skipped, null title");
224: }
225: return title != null;
226: } catch (IOException e) {
227: e.printStackTrace();
228: return false;
229: }
230: }
231:
232: void startHtml() {
233: lastlevel = 0;
234: html.append("<html><head>\n");
235: html.append(" <title>Table Of Contents</title>\n");
236: html
237: .append(" <link rel=\"stylesheet\" href=\"css/toc.css\" type=\"text/css\">\n");
238: html.append("</head>\n<body>\n");
239: html.append("<h1 class='toc'>Site Map</h1>\n");
240: html.append("<hr>\n");
241: html.append("<ul>\n");
242: }
243:
244: void writeHtml(String file, String title, String desc, int level,
245: String section) {
246: String pad = StringHelper.replicate(" ", level);
247: if (level > lastlevel) {
248: html.append(pad);
249: html.append("<ul>\n");
250: lastlevel = level;
251: } else {
252: while (level < lastlevel) {
253: html.append(StringHelper.replicate(" ", lastlevel--));
254: html.append("</ul>\n");
255: }
256: }
257:
258: String filePath = "#broken";
259: try {
260: URI base = new URI("file:///"
261: + StringHelper.replace(root.getAbsolutePath(),
262: File.separator, "/"));
263: URI f = new URI("file:///"
264: + StringHelper.replace(file, File.separator, "/"));
265: URI rel = base.relativize(f);
266: filePath = rel.toString();
267: } catch (java.net.URISyntaxException e) {
268: e.printStackTrace();
269: }
270:
271: html.append(pad);
272: html.append(" <li><a class='tocSectionId'>");
273: html.append(section);
274: html.append(".</a> <a class='tocTitle' href=\"");
275: html.append(filePath);
276: html.append("\">");
277: html.append(title);
278: html.append("</a>");
279: html.append(" - <a class='tocDescription'>");
280: if (desc == null)
281: html.append("No Description");
282: else
283: html.append(desc);
284: html.append("</a>\n");
285:
286: }
287:
288: void endHtml() {
289: while (lastlevel > 0) {
290: html.append(StringHelper.replicate(" ", lastlevel--));
291: html.append("</ul>\n");
292: }
293: html.append("</ul>\n");
294: html.append("<hr size=1>\n");
295: html.append("<span class='footer'>\n");
296: html.append("File: toc.html, Last Generated: "
297: + (new DateTime()) + ".\n");
298: html.append("</span>\n");
299: html.append("</body>\n</html>");
300: }
301:
302: /** Inner class used to filter the search results */
303: private class DirFilter implements FilenameFilter {
304: /** Tests if a specified file should be included in a file list.
305: *
306: * @param dir the directory in which the file was found
307: * @param name the name of the file
308: * @return <CODE>true</CODE> if and only if the name should be included in the file list; <CODE>false</CODE> otherwise
309: */
310: public boolean accept(File dir, String name) {
311: boolean accept = (dir.isDirectory() && !name.equals("CVS") && !name
312: .toLowerCase().endsWith(".zip"))
313: || (name.toLowerCase().endsWith(".html"))
314: || (name.toLowerCase().endsWith(".htm"));
315: System.out.println("accept = "
316: + (dir.isDirectory() && !name.equals("CVS")) + ","
317: + (name.toLowerCase().endsWith(".html")) + ","
318: + (name.toLowerCase().endsWith(".htm")));
319: if (!accept)
320: System.out.println("Ignore File - " + name);
321: else
322: System.out.println("Consume File - " + name);
323: return accept;
324: }
325: }
326:
327: /** Inner class used to filter the search results */
328: private class IndexFilter implements FilenameFilter {
329: /** Tests if a specified file should be included in a file list.
330: *
331: * @param dir the directory in which the file was found
332: * @param name the name of the file
333: * @return <CODE>true</CODE> if and only if the name should be included in the file list; <CODE>false</CODE> otherwise
334: */
335: public boolean accept(File dir, String name) {
336: return name.equalsIgnoreCase("index.htm")
337: || name.equalsIgnoreCase("index.html");
338: }
339: }
340:
341: /** Generate the Site Map / Table Of Contents for a web site
342: * @param args the command line arguments
343: * Parameter 0 -> The root folder of the site to be processed (Default is 'c:/sandbox.sf/WebSite/dist')
344: * Parameter 1 -> The name of the html file to generated in the root folder (Default is 'toc.html')
345: */
346: public static void main(String[] args) {
347: //LoggerHelper.init();
348: new GenerateTOC((args.length > 0 ? args[0] : null),
349: (args.length > 1 ? args[1] : null));
350: }
351:
352: }
|