KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > java > plugin > tools > docgen > DocGenerator


1 /*****************************************************************************
2  * Java Plug-in Framework (JPF)
3  * Copyright (C) 2004-2006 Dmitry Olshansky
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *****************************************************************************/

19 package org.java.plugin.tools.docgen;
20
21 import java.io.BufferedOutputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.OutputStreamWriter JavaDoc;
25 import java.io.Writer JavaDoc;
26 import java.net.MalformedURLException JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.Comparator JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.LinkedList JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36
37 import org.java.plugin.PathResolver;
38 import org.java.plugin.registry.Documentation;
39 import org.java.plugin.registry.Extension;
40 import org.java.plugin.registry.ExtensionPoint;
41 import org.java.plugin.registry.Identity;
42 import org.java.plugin.registry.PluginDescriptor;
43 import org.java.plugin.registry.PluginElement;
44 import org.java.plugin.registry.PluginFragment;
45 import org.java.plugin.registry.PluginPrerequisite;
46 import org.java.plugin.registry.PluginRegistry;
47 import org.java.plugin.util.IoUtil;
48 import org.onemind.jxp.FilePageSource;
49 import org.onemind.jxp.JxpProcessingContext;
50 import org.onemind.jxp.JxpProcessor;
51
52 /**
53  * Tool class to generate documentation for plug-ins using
54  * <a HREF="http://jxp.sourceforge.net" target="_new">JXP</a> templates.
55  * @version $Id: DocGenerator.java,v 1.7 2006/08/26 15:14:10 ddimon Exp $
56  */

57 public final class DocGenerator {
58     private static String JavaDoc getRelativePath(final int level) {
59         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
60         if (level > 0) {
61             for (int i = 0; i < level; i++) {
62                 if (i > 0) {
63                     result.append("/"); //$NON-NLS-1$
64
}
65                 result.append(".."); //$NON-NLS-1$
66
}
67         } else {
68             result.append("."); //$NON-NLS-1$
69
}
70         return result.toString();
71     }
72
73     private final PluginRegistry registry;
74     private final PathResolver pathResolver;
75     private JxpProcessor processor;
76     private Collection JavaDoc allPluginDescriptors;
77     private Collection JavaDoc allPluginFragments;
78     private Collection JavaDoc allExtensionPoints;
79     private Collection JavaDoc allExtensions;
80     private String JavaDoc documentationOverview;
81     private String JavaDoc stylesheet;
82     private String JavaDoc outputEncoding = "UTF-8"; //$NON-NLS-1$
83

84     /**
85      * Constructs generator configured to use pre-defined set of templates.
86      * @param aRegistry plug-ins registry
87      * @param aPathResolver path resolver
88      * @throws Exception if an error has occurred
89      */

90     public DocGenerator(final PluginRegistry aRegistry,
91             final PathResolver aPathResolver)
92             throws Exception JavaDoc {
93         this(aRegistry, aPathResolver,
94                 DocGenerator.class.getName().substring(0,
95                         DocGenerator.class.getName().lastIndexOf('.'))
96                         .replace('.', '/') + "/templates/", null); //$NON-NLS-1$
97
}
98
99     /**
100      * Constructs generator configured to use custom templates available in the
101      * classpath.
102      * @param aRegistry plug-ins registry
103      * @param aPathResolver path resolver
104      * @param templatesPath path to templates
105      * (should be available in classpath)
106      * @param templatesEncoding templates characters encoding, if
107      * <code>null</code>, system default will be used
108      * @throws Exception if an error has occurred
109      */

110     public DocGenerator(final PluginRegistry aRegistry,
111             final PathResolver aPathResolver, final String JavaDoc templatesPath,
112             final String JavaDoc templatesEncoding) throws Exception JavaDoc {
113         this(aRegistry, aPathResolver, new JxpProcessor(
114                 new ClassPathPageSource(templatesPath, templatesEncoding)));
115     }
116     
117     /**
118      * Constructs generator configured to use custom templates located somewhere
119      * in the local file system.
120      * @param aRegistry plug-ins registry
121      * @param aPathResolver path resolver
122      * @param templatesFolder folder with templates
123      * @param templatesEncoding templates characters encoding, if
124      * <code>null</code>, system default will be used
125      * @throws Exception if an error has occurred
126      */

127     public DocGenerator(final PluginRegistry aRegistry,
128             final PathResolver aPathResolver, final File JavaDoc templatesFolder,
129             final String JavaDoc templatesEncoding) throws Exception JavaDoc {
130         //TODO: use character encoding when that will be possible in JXP library
131
this(aRegistry, aPathResolver, new JxpProcessor(
132                 new FilePageSource(templatesFolder.getCanonicalPath())));
133     }
134     
135     private DocGenerator(final PluginRegistry aRegistry,
136             final PathResolver aPathResolver, final JxpProcessor proc) {
137         registry = aRegistry;
138         pathResolver = aPathResolver;
139         processor = proc;
140         allPluginDescriptors = getAllPluginDescriptors();
141         allPluginFragments = getAllPluginFragments();
142         allExtensionPoints = getAllExtensionPoints();
143         allExtensions = getAllExtensions();
144     }
145
146     /**
147      * @return documentation overview HTML content
148      */

149     public String JavaDoc getDocumentationOverview() {
150         return documentationOverview;
151     }
152
153     /**
154      * @param aDocumentationOverview documentation overview HTML content
155      */

156     public void setDocumentationOverview(final String JavaDoc aDocumentationOverview) {
157         this.documentationOverview = aDocumentationOverview;
158     }
159
160     /**
161      * @return CSS style sheet content
162      */

163     public String JavaDoc getStylesheet() {
164         return stylesheet;
165     }
166     
167     /**
168      * @param aStylesheet CSS style sheet content
169      */

170     public void setStylesheet(final String JavaDoc aStylesheet) {
171         this.stylesheet = aStylesheet;
172     }
173     
174     /**
175      * @return output files encoding name
176      */

177     public String JavaDoc getOutputEncoding() {
178         return outputEncoding;
179     }
180     
181     /**
182      * @param encoding output files encoding name (default is UTF-8)
183      */

184     public void setOutputEncoding(final String JavaDoc encoding) {
185         this.outputEncoding = encoding;
186     }
187
188     private void processTemplateFile(final Map JavaDoc ctx, final String JavaDoc template,
189             final File JavaDoc outFile) throws Exception JavaDoc {
190         Writer JavaDoc out = new OutputStreamWriter JavaDoc(new BufferedOutputStream JavaDoc(
191                 new FileOutputStream JavaDoc(outFile, false)), outputEncoding);
192         try {
193             processor.process(template, new JxpProcessingContext(out, ctx));
194         } finally {
195             out.close();
196         }
197     }
198     
199     private void processTemplateContent(final Map JavaDoc ctx,
200             final String JavaDoc template, final File JavaDoc outFile) throws Exception JavaDoc {
201         File JavaDoc tmpFile = File.createTempFile("~jpf-jxp", null); //$NON-NLS-1$
202
tmpFile.deleteOnExit();
203         Writer JavaDoc tmpOut = new OutputStreamWriter JavaDoc(new BufferedOutputStream JavaDoc(
204                 new FileOutputStream JavaDoc(tmpFile, false)), "UTF-8"); //$NON-NLS-1$
205
try {
206             tmpOut.write(template);
207         } finally {
208             tmpOut.close();
209         }
210         Writer JavaDoc out = new OutputStreamWriter JavaDoc(new BufferedOutputStream JavaDoc(
211                 new FileOutputStream JavaDoc(outFile, false)), outputEncoding);
212         try {
213             JxpProcessor proc = new JxpProcessor(new FilePageSource(
214                     tmpFile.getParentFile().getCanonicalPath()));
215             //TODO: use character encoding when that will be possible in JXP
216
// library (UTF-8 in this case)
217
proc.process(tmpFile.getName(), new JxpProcessingContext(out, ctx));
218         } finally {
219             tmpFile.delete();
220             out.close();
221         }
222     }
223     
224     /**
225      * Generates documentation for all registered plug-ins.
226      * @param destDir target folder
227      * @throws Exception if an error has occurred
228      */

229     public void generate(final File JavaDoc destDir) throws Exception JavaDoc {
230         // generating index page
231
Map JavaDoc ctx = createConext(0);
232         processTemplateFile(ctx, "index.jxp", //$NON-NLS-1$
233
new File JavaDoc(destDir, "index.html")); //$NON-NLS-1$
234
// generating style sheet file
235
generateCss(destDir);
236         // generating menu page
237
ctx = createConext(0);
238         processTemplateFile(ctx, "menu.jxp", //$NON-NLS-1$
239
new File JavaDoc(destDir, "menu.html")); //$NON-NLS-1$
240
// generating overview page
241
ctx = createConext(0);
242         if (documentationOverview != null) {
243             ctx.put("overview", documentationOverview.replaceAll( //$NON-NLS-1$
244
"(?i)(?d)(?m).*<body>(.*)</body>.*", "$1")); //$NON-NLS-1$ //$NON-NLS-2$
245
} else {
246             ctx.put("overview", ""); //$NON-NLS-1$ //$NON-NLS-2$
247
}
248         processTemplateFile(ctx, "overview.jxp", //$NON-NLS-1$
249
new File JavaDoc(destDir, "overview.html")); //$NON-NLS-1$
250
// generating "all plug-ins" page
251
ctx = createConext(0);
252         processTemplateFile(ctx, "allplugins.jxp", //$NON-NLS-1$
253
new File JavaDoc(destDir, "allplugins.html")); //$NON-NLS-1$
254
// generating "all plug-in fragments" page
255
ctx = createConext(0);
256         processTemplateFile(ctx, "allfragments.jxp", //$NON-NLS-1$
257
new File JavaDoc(destDir, "allfragments.html")); //$NON-NLS-1$
258
// generating "all extension points" page
259
ctx = createConext(0);
260         processTemplateFile(ctx, "allextpoints.jxp", //$NON-NLS-1$
261
new File JavaDoc(destDir, "allextpoints.html")); //$NON-NLS-1$
262
// generating "all extensions" page
263
ctx = createConext(0);
264         processTemplateFile(ctx, "allexts.jxp", //$NON-NLS-1$
265
new File JavaDoc(destDir, "allexts.html")); //$NON-NLS-1$
266
// generating tree page
267
ctx = createConext(0);
268         processTemplateFile(ctx, "tree.jxp", //$NON-NLS-1$
269
new File JavaDoc(destDir, "tree.html")); //$NON-NLS-1$
270
// per plug-in generation
271
for (Iterator JavaDoc it = registry.getPluginDescriptors().iterator();
272                 it.hasNext();) {
273             generateForPluginDescriptor(destDir, (PluginDescriptor) it.next());
274         }
275     }
276     
277     private void generateCss(final File JavaDoc destDir) throws Exception JavaDoc {
278         Map JavaDoc ctx = createConext(0);
279         if (stylesheet == null) {
280             processTemplateFile(ctx, "stylesheet.jxp", //$NON-NLS-1$
281
new File JavaDoc(destDir, "stylesheet.css")); //$NON-NLS-1$
282
} else {
283             processTemplateContent(ctx, stylesheet,
284                     new File JavaDoc(destDir, "stylesheet.css")); //$NON-NLS-1$
285
}
286     }
287     
288     private void generateForPluginDescriptor(final File JavaDoc baseDir,
289             final PluginDescriptor descr) throws Exception JavaDoc {
290         File JavaDoc destDir = new File JavaDoc(baseDir, descr.getId());
291         destDir.mkdirs();
292         File JavaDoc srcDocsFolder = IoUtil.url2file(
293                 pathResolver.resolvePath(descr, descr.getDocsPath()));
294         if ((srcDocsFolder != null) && srcDocsFolder.isDirectory()) {
295             File JavaDoc destDocsFolder = new File JavaDoc(destDir, "extra"); //$NON-NLS-1$
296
destDocsFolder.mkdir();
297             IoUtil.copyFolder(srcDocsFolder, destDocsFolder, true);
298         }
299         List JavaDoc depenededPlugins = new LinkedList JavaDoc();
300         for (Iterator JavaDoc it = registry.getPluginDescriptors().iterator();
301                 it.hasNext();) {
302             PluginDescriptor dependedDescr = (PluginDescriptor) it.next();
303             if (dependedDescr.getId().equals(descr.getId())) {
304                 continue;
305             }
306             for (Iterator JavaDoc it2 = dependedDescr.getPrerequisites().iterator();
307                     it2.hasNext();) {
308                 PluginPrerequisite pre = (PluginPrerequisite) it2.next();
309                 if (pre.getPluginId().equals(descr.getId())
310                         && pre.matches()) {
311                     depenededPlugins.add(dependedDescr);
312                     break;
313                 }
314             }
315         }
316         Map JavaDoc ctx = createConext(1);
317         ctx.put("descriptor", descr); //$NON-NLS-1$
318
ctx.put("dependedPlugins", depenededPlugins); //$NON-NLS-1$
319
processTemplateFile(ctx, "plugin.jxp", //$NON-NLS-1$
320
new File JavaDoc(destDir, "index.html")); //$NON-NLS-1$
321
// per plug-in fragment generation
322
for (Iterator JavaDoc it = descr.getFragments().iterator(); it.hasNext();) {
323             generateForPluginFragment(baseDir, (PluginFragment) it.next());
324         }
325         // generating extension points
326
if (!descr.getExtensionPoints().isEmpty()) {
327             File JavaDoc extPointsDir = new File JavaDoc(destDir, "extp"); //$NON-NLS-1$
328
extPointsDir.mkdir();
329             for (Iterator JavaDoc it = descr.getExtensionPoints().iterator();
330                     it.hasNext();) {
331                 ExtensionPoint extPoint = (ExtensionPoint) it.next();
332                 ctx = createConext(3);
333                 ctx.put("extPoint", extPoint); //$NON-NLS-1$
334
File JavaDoc dir = new File JavaDoc(extPointsDir, extPoint.getId());
335                 dir.mkdir();
336                 processTemplateFile(ctx, "extpoint.jxp", //$NON-NLS-1$
337
new File JavaDoc(dir, "index.html")); //$NON-NLS-1$
338
}
339         }
340         // generating extensions
341
if (!descr.getExtensions().isEmpty()) {
342             File JavaDoc extsDir = new File JavaDoc(destDir, "ext"); //$NON-NLS-1$
343
extsDir.mkdir();
344             for (Iterator JavaDoc it = descr.getExtensions().iterator();
345                     it.hasNext();) {
346                 Extension ext = (Extension) it.next();
347                 ctx = createConext(3);
348                 ctx.put("ext", ext); //$NON-NLS-1$
349
File JavaDoc dir = new File JavaDoc(extsDir, ext.getId());
350                 dir.mkdir();
351                 processTemplateFile(ctx, "ext.jxp", //$NON-NLS-1$
352
new File JavaDoc(dir, "index.html")); //$NON-NLS-1$
353
}
354         }
355     }
356     
357     private void generateForPluginFragment(final File JavaDoc baseDir,
358             final PluginFragment fragment) throws Exception JavaDoc {
359         File JavaDoc destDir = new File JavaDoc(baseDir, fragment.getId());
360         destDir.mkdirs();
361         Map JavaDoc ctx = createConext(1);
362         ctx.put("fragment", fragment); //$NON-NLS-1$
363
processTemplateFile(ctx, "fragment.jxp", //$NON-NLS-1$
364
new File JavaDoc(destDir, "index.html")); //$NON-NLS-1$
365
}
366
367     private Map JavaDoc createConext(final int level) {
368         Map JavaDoc result = new HashMap JavaDoc();
369         String JavaDoc relativePath = getRelativePath(level);
370         result.put("tool", new Tool(relativePath)); //$NON-NLS-1$
371
result.put("relativePath", relativePath); //$NON-NLS-1$
372
result.put("registry", registry); //$NON-NLS-1$
373
result.put("allPluginDescriptors", allPluginDescriptors); //$NON-NLS-1$
374
result.put("allPluginFragments", allPluginFragments); //$NON-NLS-1$
375
result.put("allExtensionPoints", allExtensionPoints); //$NON-NLS-1$
376
result.put("allExtensions", allExtensions); //$NON-NLS-1$
377
return result;
378     }
379     
380     private Collection JavaDoc getAllPluginDescriptors() {
381         List JavaDoc result = new LinkedList JavaDoc();
382         result.addAll(registry.getPluginDescriptors());
383         Collections.sort(result, new IdentityComparator());
384         return Collections.unmodifiableCollection(result);
385     }
386
387     private Collection JavaDoc getAllPluginFragments() {
388         List JavaDoc result = new LinkedList JavaDoc();
389         result.addAll(registry.getPluginFragments());
390         Collections.sort(result, new IdentityComparator());
391         return Collections.unmodifiableCollection(result);
392     }
393     
394     private Collection JavaDoc getAllExtensionPoints() {
395         List JavaDoc result = new LinkedList JavaDoc();
396         for (Iterator JavaDoc it = registry.getPluginDescriptors().iterator();
397                 it.hasNext();) {
398             result.addAll(((PluginDescriptor) it.next()).getExtensionPoints());
399         }
400         Collections.sort(result, new IdentityComparator());
401         return Collections.unmodifiableCollection(result);
402     }
403     
404     private Collection JavaDoc getAllExtensions() {
405         List JavaDoc result = new LinkedList JavaDoc();
406         for (Iterator JavaDoc it = registry.getPluginDescriptors().iterator();
407                 it.hasNext();) {
408             result.addAll(((PluginDescriptor) it.next()).getExtensions());
409         }
410         Collections.sort(result, new IdentityComparator());
411         return Collections.unmodifiableCollection(result);
412     }
413
414     /**
415      * Utility class to be used from JXP templates.
416      * @version $Id: DocGenerator.java,v 1.7 2006/08/26 15:14:10 ddimon Exp $
417      */

418     public static final class Tool {
419         private String JavaDoc relativePath;
420
421         protected Tool(final String JavaDoc aRelativePath) {
422             this.relativePath = aRelativePath;
423         }
424         
425         /**
426          * @param ref documentation reference element
427          * @return link to be used in "href" attribute
428          */

429         public String JavaDoc getLink(final Documentation.Reference ref) {
430             if (isAbsoluteUrl(ref.getRef())) {
431                 return ref.getRef();
432             }
433             String JavaDoc id;
434             Identity idt = ref.getDeclaringIdentity();
435             if (idt instanceof PluginElement) {
436                 PluginElement element = (PluginElement) idt;
437                 PluginFragment fragment = element.getDeclaringPluginFragment();
438                 if (fragment != null) {
439                     id = fragment.getId();
440                 } else {
441                     id = element.getDeclaringPluginDescriptor().getId();
442                 }
443             } else {
444                 id = idt.getId();
445             }
446             return relativePath + "/" + id + "/extra/" + ref.getRef(); //$NON-NLS-1$ //$NON-NLS-2$
447
}
448         
449         /**
450          * @param url an URL to check
451          * @return <code>true</code> if given link is an absolute URL
452          */

453         public boolean isAbsoluteUrl(final String JavaDoc url) {
454             try {
455                 String JavaDoc protocol = new URL JavaDoc(url).getProtocol();
456                 return (protocol != null) && (protocol.length() > 0);
457             } catch (MalformedURLException JavaDoc e) {
458                 return false;
459             }
460         }
461         
462         /**
463          * Substitutes all ${relativePath} variables with their values.
464          * @param text text to be processed
465          * @return processed documentation text
466          */

467         public String JavaDoc processDocText(final String JavaDoc text) {
468             if ((text == null) || (text.length() == 0)) {
469                 return ""; //$NON-NLS-1$
470
}
471             return text.replaceAll("(?d)(?m)\\$\\{relativePath\\}", //$NON-NLS-1$
472
relativePath);
473         }
474     }
475     
476     static final class IdentityComparator implements Comparator JavaDoc {
477         /**
478          * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
479          */

480         public int compare(final Object JavaDoc o1, final Object JavaDoc o2) {
481             return ((Identity) o1).getId().compareTo(
482                     ((Identity) o2).getId());
483         }
484     }
485 }
486
Popular Tags