001: package de.webman.generator;
002:
003: import com.teamkonzept.lib.*;
004:
005: import java.io.*;
006: import java.util.*;
007: import org.apache.log4j.Category;
008:
009: /**
010: * @author $Author: gregor $
011: * @version $Revision: 1.6 $
012: */
013: public class GenNode {
014: /**
015: Verweis zurueck auf den aktuellen statischen Kontext des laufenden Threads
016: */
017: private GeneratorContext context;
018:
019: /** Log4J Category */
020: private static Category cat = Category.getInstance(GenNode.class
021: .getName());
022:
023: /** ... */
024: private String nodeName;
025: private String description;
026:
027: /** alle Kinder - GenNodes */
028: private TKVector subNodes;
029:
030: /** alle Dokumente key:shortName Value: GenDocument */
031: private TKHashtable documents;
032:
033: private GenNode parent;
034: private int parentNodePos;
035: private SiteNode siteNode;
036: private SiteContent primContent;
037:
038: public GenNode(GeneratorContext context, SiteNode siteNode,
039: GenNode parent, String nodeName, String _description,
040: TKVector documents, SiteContent primContent,
041: int parentNodePos) {
042: this .context = context != null ? context : GeneratorContext
043: .setup();
044:
045: this .parent = parent;
046: this .nodeName = nodeName;
047: description = _description;
048: this .subNodes = this .context.genNodes.isRecursiveBuild() ? siteNode
049: .getSubGenNodes(this )
050: : new TKVector();
051: this .documents = new TKHashtable();
052: this .siteNode = siteNode;
053: this .parentNodePos = parentNodePos;
054: this .primContent = primContent;
055: if (!this .context.genNodes.isRecursiveBuild())
056: return;
057:
058: Enumeration e = documents.elements();
059: while (e.hasMoreElements()) {
060: SiteDocument doc = (SiteDocument) e.nextElement();
061: if (doc != null) {
062: if (doc.isRefered()) {
063: this .documents.put(doc.getShortName(), doc
064: .getGenDocument(primContent, this ));
065: }
066: } else {
067: cat.warn("got hole in document-list");
068: }
069: }
070: }
071:
072: public SiteContent getPrimaryContent() {
073: return primContent;
074: }
075:
076: public TKHashtable getDocuments() {
077: return documents;
078: }
079:
080: public TKVector getSubNodes() {
081: return subNodes;
082: }
083:
084: /**
085: Returns the path-string of this site node.
086: The root-node's name is omitted.
087: Example: "/PressReleases/".
088: */
089: public String getPath() {
090: return (parent == null ? "/" : parent.getPath() + nodeName
091: + "/");
092: }
093:
094: /**
095: Returns the relative path from the root node to this node.
096: The returned string does not include starting and trailing File.separator.
097: In contrast to the aboves getPath-method, the root's node name is NOT omitted!
098: Examples: "root" or "root/PressPreleases" etc.
099: */
100: public String getSubPathDir() {
101: /*
102: return ( parent == null ? nodeName : parent.getSubPathDir() + File.separator + nodeName ) ;
103: */
104: return (parent == null ? "" : (parent.parent == null ? nodeName
105: : parent.getSubPathDir() + File.separator + nodeName));
106: }
107:
108: public SiteNode getSiteNode() {
109: return siteNode;
110: }
111:
112: public String getDescription() {
113: return description;
114: }
115:
116: public GenNode getParent() {
117: return parent;
118: }
119:
120: public String getNodeName() {
121: return nodeName;
122: }
123:
124: public int depth() {
125: return (parent == null ? 1 : parent.depth() + 1);
126: }
127:
128: public String makePathRelativeTo(GenNode other) {
129: int this Depth = depth();
130: int otherDepth = other.depth();
131: StringBuffer up = new StringBuffer(this Depth * 10);
132: StringBuffer down = new StringBuffer(otherDepth * 10);
133: GenNode this Node = this ;
134: GenNode otherNode = other;
135:
136: while (this Depth > otherDepth) {
137: if (up.length() > 0)
138: up.append('/');
139: up.append("..");
140: this Node = this Node.parent;
141: this Depth--;
142: }
143:
144: while (this Depth < otherDepth) {
145: if (down.length() > 0)
146: down.insert(0, '/');
147: down.insert(0, otherNode.nodeName);
148: otherNode = otherNode.parent;
149: otherDepth--;
150: }
151:
152: GenNode this Up = this Node;
153: GenNode otherUp = otherNode;
154: int shared = 0;
155:
156: while (this Up != null) {
157: if (this Up.nodeName.compareTo(otherUp.nodeName) == 0)
158: shared++;
159: else
160: shared = 0;
161: this Up = this Up.parent;
162: otherUp = otherUp.parent;
163: }
164:
165: while (this Depth > shared) {
166: if (up.length() > 0)
167: up.append('/');
168: up.append("..");
169: this Node = this Node.parent;
170: if (down.length() > 0)
171: down.insert(0, '/');
172: down.insert(0, otherNode.nodeName);
173: otherNode = otherNode.parent;
174: this Depth--;
175: }
176:
177: if ((up.length() > 0) && (down.length() > 0))
178: return up.append('/').append(down.toString()).append('/')
179: .toString();
180: else if (up.length() > 0)
181: return up.append('/').toString();
182: else if (down.length() > 0)
183: return down.append('/').toString();
184: else
185: return "";
186: }
187:
188: public void prepareGeneration() {
189: Enumeration e = documents.elements();
190: while (e.hasMoreElements()) {
191: ((GenDocument) e.nextElement()).prepareGeneration();
192: }
193:
194: e = subNodes.elements();
195: while (e.hasMoreElements()) {
196: ((GenNode) e.nextElement()).prepareGeneration();
197: }
198: }
199:
200: /**
201: Generates the node by creating a directory with name
202: <code>nodeName</code> in the directory <code>baseDir</code>.
203: It also recursively generates all sub documents and sub nodes,
204: if this node isn't excluded by subtree generation (as specified by
205: a <code>refs</code> command line option).
206: @param baseDir the parent directory path of this node
207: @param rootDir the path to the document root
208: @param tmplBase the absoulte path to the template directory
209: @param genFileLogStream a logstream to which the generated files are written
210: @param cleanup: if true certain files will be removed from the directory
211: */
212: public void generate(File baseDir, String rootDir, String tmplBase,
213: PrintStream genFileLogStream, boolean cleanup)
214: throws Exception {
215: cat.debug("generate " + nodeName + " in "
216: + baseDir.getAbsolutePath());
217: File sourceDir = baseDir;
218: if (parent != null) {
219: /*This condition assures that the document root coincides with the
220: the site root node. Removed by frank because output should be
221: generated in its proper 'root' directory below the document root
222: re-removed by alex */
223: sourceDir = new File(baseDir, nodeName);
224: }
225:
226: String siteNodePath = siteNode.getPath();
227: if (context.siteNodes.getIncludeSubtreePath() != null
228: && !context.siteNodes.getIncludeSubtreePath()
229: .startsWith(siteNodePath)
230: && !siteNodePath.startsWith(context.siteNodes
231: .getIncludeSubtreePath())) {
232: cat.info(new Date().toString()
233: + ": start subtree generation of node "
234: + sourceDir.getAbsolutePath()
235: + " stopped due to constraint");
236: return;
237: }
238: if (sourceDir.exists()) {
239: if (!sourceDir.isDirectory()) {
240: throw new Error("existing file "
241: + sourceDir.getAbsolutePath()
242: + " prevents creation of new directory");
243: }
244: } else {
245: if (!sourceDir.mkdirs()) {
246: throw new Error("could not create file "
247: + sourceDir.getAbsolutePath());
248: }
249: }
250:
251: DirectoryFileListing genList = createGenList(sourceDir
252: .getAbsolutePath());
253: Enumeration e = documents.elements();
254: while (e.hasMoreElements()) {
255: GenDocument nextDoc = (GenDocument) e.nextElement();
256: try {
257: nextDoc.generate(sourceDir, rootDir, tmplBase,
258: genFileLogStream);
259: if (genList != null) {
260: genList.generatedFile(nextDoc.getDocumentName());
261: }
262: } catch (Exception ex) {
263: cat.error("generation of document "
264: + nextDoc.getDocumentName() + " in "
265: + sourceDir.getAbsolutePath() + " failed: "
266: + ex.getMessage(), ex);
267: // ex.printStackTrace(System.out);
268: }
269: }
270: e = subNodes.elements();
271: while (e.hasMoreElements()) {
272: GenNode nextNode = (GenNode) e.nextElement();
273: try {
274: nextNode.generate(sourceDir, rootDir, tmplBase,
275: genFileLogStream, cleanup);
276: if (genList != null) {
277: genList.generatedDirectory(nextNode.nodeName);
278: }
279: } catch (Exception ex) {
280: cat.error("generation of node " + nextNode.nodeName
281: + " in " + sourceDir.getAbsolutePath()
282: + " failed: ", ex);
283: }
284: }
285: if (genList != null && cleanup) {
286: deleteFiles(sourceDir.getAbsolutePath(), genList
287: .getFilesToDelete());
288: deleteFiles(sourceDir.getAbsolutePath(), genList
289: .getDirectoriesToDelete());
290: }
291: saveGenList(genList, false);
292: }
293:
294: public GenDocument getDocument(String name) {
295: return (GenDocument) documents.get(name);
296: }
297:
298: /**
299: Deletes a list of files and directories.
300: @param path the directory, where the files an directories are located
301: @param filesToDelete the list of files to delete (relative names
302: with respect to 'path').
303: */
304: private static boolean deleteFiles(String path,
305: Enumeration filesToDelete) {
306: boolean successful = true;
307: while (filesToDelete.hasMoreElements()) {
308: String name = (String) filesToDelete.nextElement();
309: File f = new File(path, name);
310: if (f.isDirectory()) {
311: if (f.delete() == false
312: && tryRecursiveDelete(f) == false) {
313: successful = false;
314: }
315: } else {
316: if (f.delete() == false) {
317: successful = false;
318: }
319: }
320: }
321: return successful;
322: }
323:
324: /**
325: Tries to delete the directory <code>dir</code> by
326: deleting recursively all sub directores and sub files listed in
327: the generated-files list of this directory.
328: After this, the directory is deleted <code>dir</code> if it is empty.
329: */
330: private static boolean tryRecursiveDelete(File dir) {
331: DirectoryFileListing genList = createGenList(dir
332: .getAbsolutePath());
333: if (genList == null) {
334: return false;
335: }
336:
337: boolean successful = true;
338:
339: Enumeration subdirs = genList.getDirectoryEntries();
340: while (subdirs.hasMoreElements()) {
341: File file = new File(dir.getAbsolutePath(),
342: (String) subdirs.nextElement());
343: if (tryRecursiveDelete(file) == false) {
344: successful = false;
345: }
346: }
347:
348: Enumeration files = genList.getFileEntries();
349: while (files.hasMoreElements()) {
350: File file = new File(dir.getAbsolutePath(), (String) files
351: .nextElement());
352: if (file.delete() == false) {
353: successful = false;
354: }
355: }
356:
357: //this deletes the "generated_files.list":
358: saveGenList(genList, false);
359:
360: if (!successful) {
361: return false;
362: }
363: File file = new File(dir.getAbsolutePath());
364: return file.delete();
365: }
366:
367: /**
368: Creates the <code>DirectoryFileListing</code> of the given
369: directory <code>dir</code>.
370: @return the DirectoryFileListing instance or null in case of error
371: */
372: private static DirectoryFileListing createGenList(String dir) {
373: DirectoryFileListing genList = null;
374: try {
375: genList = new DirectoryFileListing(dir);
376: } catch (IOException e) {
377: cat
378: .warn("Unable to open log file of generated files in directory "
379: + dir);
380: return null;
381: }
382: return genList;
383: }
384:
385: /**
386: Saves the DirectoryFileListing <code>genNode</code>.
387: IOExceptions during save are catched and ignored.
388: @param addonly if set to false, the new listing will consist
389: of all file and directory names added through
390: <code>generatedFile(String)</code> or <code>generatedDirectory(String)</code>
391: if set to true, the new listing will consist of all old and new entries
392: */
393: private static void saveGenList(DirectoryFileListing genList,
394: boolean addOnly) {
395: try {
396: genList.save(addOnly);
397: } catch (IOException e) {
398: cat.warn("Unable to save log file of generated files", e);
399: }
400: }
401: }
|