1 19 package org.java.plugin.tools.docgen; 20 21 import java.io.BufferedOutputStream ; 22 import java.io.File ; 23 import java.io.FileOutputStream ; 24 import java.io.OutputStreamWriter ; 25 import java.io.Writer ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.util.Collection ; 29 import java.util.Collections ; 30 import java.util.Comparator ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.LinkedList ; 34 import java.util.List ; 35 import java.util.Map ; 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 57 public final class DocGenerator { 58 private static String getRelativePath(final int level) { 59 StringBuffer result = new StringBuffer (); 60 if (level > 0) { 61 for (int i = 0; i < level; i++) { 62 if (i > 0) { 63 result.append("/"); } 65 result.append(".."); } 67 } else { 68 result.append("."); } 70 return result.toString(); 71 } 72 73 private final PluginRegistry registry; 74 private final PathResolver pathResolver; 75 private JxpProcessor processor; 76 private Collection allPluginDescriptors; 77 private Collection allPluginFragments; 78 private Collection allExtensionPoints; 79 private Collection allExtensions; 80 private String documentationOverview; 81 private String stylesheet; 82 private String outputEncoding = "UTF-8"; 84 90 public DocGenerator(final PluginRegistry aRegistry, 91 final PathResolver aPathResolver) 92 throws Exception { 93 this(aRegistry, aPathResolver, 94 DocGenerator.class.getName().substring(0, 95 DocGenerator.class.getName().lastIndexOf('.')) 96 .replace('.', '/') + "/templates/", null); } 98 99 110 public DocGenerator(final PluginRegistry aRegistry, 111 final PathResolver aPathResolver, final String templatesPath, 112 final String templatesEncoding) throws Exception { 113 this(aRegistry, aPathResolver, new JxpProcessor( 114 new ClassPathPageSource(templatesPath, templatesEncoding))); 115 } 116 117 127 public DocGenerator(final PluginRegistry aRegistry, 128 final PathResolver aPathResolver, final File templatesFolder, 129 final String templatesEncoding) throws Exception { 130 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 149 public String getDocumentationOverview() { 150 return documentationOverview; 151 } 152 153 156 public void setDocumentationOverview(final String aDocumentationOverview) { 157 this.documentationOverview = aDocumentationOverview; 158 } 159 160 163 public String getStylesheet() { 164 return stylesheet; 165 } 166 167 170 public void setStylesheet(final String aStylesheet) { 171 this.stylesheet = aStylesheet; 172 } 173 174 177 public String getOutputEncoding() { 178 return outputEncoding; 179 } 180 181 184 public void setOutputEncoding(final String encoding) { 185 this.outputEncoding = encoding; 186 } 187 188 private void processTemplateFile(final Map ctx, final String template, 189 final File outFile) throws Exception { 190 Writer out = new OutputStreamWriter (new BufferedOutputStream ( 191 new FileOutputStream (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 ctx, 200 final String template, final File outFile) throws Exception { 201 File tmpFile = File.createTempFile("~jpf-jxp", null); tmpFile.deleteOnExit(); 203 Writer tmpOut = new OutputStreamWriter (new BufferedOutputStream ( 204 new FileOutputStream (tmpFile, false)), "UTF-8"); try { 206 tmpOut.write(template); 207 } finally { 208 tmpOut.close(); 209 } 210 Writer out = new OutputStreamWriter (new BufferedOutputStream ( 211 new FileOutputStream (outFile, false)), outputEncoding); 212 try { 213 JxpProcessor proc = new JxpProcessor(new FilePageSource( 214 tmpFile.getParentFile().getCanonicalPath())); 215 proc.process(tmpFile.getName(), new JxpProcessingContext(out, ctx)); 218 } finally { 219 tmpFile.delete(); 220 out.close(); 221 } 222 } 223 224 229 public void generate(final File destDir) throws Exception { 230 Map ctx = createConext(0); 232 processTemplateFile(ctx, "index.jxp", new File (destDir, "index.html")); generateCss(destDir); 236 ctx = createConext(0); 238 processTemplateFile(ctx, "menu.jxp", new File (destDir, "menu.html")); ctx = createConext(0); 242 if (documentationOverview != null) { 243 ctx.put("overview", documentationOverview.replaceAll( "(?i)(?d)(?m).*<body>(.*)</body>.*", "$1")); } else { 246 ctx.put("overview", ""); } 248 processTemplateFile(ctx, "overview.jxp", new File (destDir, "overview.html")); ctx = createConext(0); 252 processTemplateFile(ctx, "allplugins.jxp", new File (destDir, "allplugins.html")); ctx = createConext(0); 256 processTemplateFile(ctx, "allfragments.jxp", new File (destDir, "allfragments.html")); ctx = createConext(0); 260 processTemplateFile(ctx, "allextpoints.jxp", new File (destDir, "allextpoints.html")); ctx = createConext(0); 264 processTemplateFile(ctx, "allexts.jxp", new File (destDir, "allexts.html")); ctx = createConext(0); 268 processTemplateFile(ctx, "tree.jxp", new File (destDir, "tree.html")); for (Iterator it = registry.getPluginDescriptors().iterator(); 272 it.hasNext();) { 273 generateForPluginDescriptor(destDir, (PluginDescriptor) it.next()); 274 } 275 } 276 277 private void generateCss(final File destDir) throws Exception { 278 Map ctx = createConext(0); 279 if (stylesheet == null) { 280 processTemplateFile(ctx, "stylesheet.jxp", new File (destDir, "stylesheet.css")); } else { 283 processTemplateContent(ctx, stylesheet, 284 new File (destDir, "stylesheet.css")); } 286 } 287 288 private void generateForPluginDescriptor(final File baseDir, 289 final PluginDescriptor descr) throws Exception { 290 File destDir = new File (baseDir, descr.getId()); 291 destDir.mkdirs(); 292 File srcDocsFolder = IoUtil.url2file( 293 pathResolver.resolvePath(descr, descr.getDocsPath())); 294 if ((srcDocsFolder != null) && srcDocsFolder.isDirectory()) { 295 File destDocsFolder = new File (destDir, "extra"); destDocsFolder.mkdir(); 297 IoUtil.copyFolder(srcDocsFolder, destDocsFolder, true); 298 } 299 List depenededPlugins = new LinkedList (); 300 for (Iterator 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 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 ctx = createConext(1); 317 ctx.put("descriptor", descr); ctx.put("dependedPlugins", depenededPlugins); processTemplateFile(ctx, "plugin.jxp", new File (destDir, "index.html")); for (Iterator it = descr.getFragments().iterator(); it.hasNext();) { 323 generateForPluginFragment(baseDir, (PluginFragment) it.next()); 324 } 325 if (!descr.getExtensionPoints().isEmpty()) { 327 File extPointsDir = new File (destDir, "extp"); extPointsDir.mkdir(); 329 for (Iterator it = descr.getExtensionPoints().iterator(); 330 it.hasNext();) { 331 ExtensionPoint extPoint = (ExtensionPoint) it.next(); 332 ctx = createConext(3); 333 ctx.put("extPoint", extPoint); File dir = new File (extPointsDir, extPoint.getId()); 335 dir.mkdir(); 336 processTemplateFile(ctx, "extpoint.jxp", new File (dir, "index.html")); } 339 } 340 if (!descr.getExtensions().isEmpty()) { 342 File extsDir = new File (destDir, "ext"); extsDir.mkdir(); 344 for (Iterator it = descr.getExtensions().iterator(); 345 it.hasNext();) { 346 Extension ext = (Extension) it.next(); 347 ctx = createConext(3); 348 ctx.put("ext", ext); File dir = new File (extsDir, ext.getId()); 350 dir.mkdir(); 351 processTemplateFile(ctx, "ext.jxp", new File (dir, "index.html")); } 354 } 355 } 356 357 private void generateForPluginFragment(final File baseDir, 358 final PluginFragment fragment) throws Exception { 359 File destDir = new File (baseDir, fragment.getId()); 360 destDir.mkdirs(); 361 Map ctx = createConext(1); 362 ctx.put("fragment", fragment); processTemplateFile(ctx, "fragment.jxp", new File (destDir, "index.html")); } 366 367 private Map createConext(final int level) { 368 Map result = new HashMap (); 369 String relativePath = getRelativePath(level); 370 result.put("tool", new Tool(relativePath)); result.put("relativePath", relativePath); result.put("registry", registry); result.put("allPluginDescriptors", allPluginDescriptors); result.put("allPluginFragments", allPluginFragments); result.put("allExtensionPoints", allExtensionPoints); result.put("allExtensions", allExtensions); return result; 378 } 379 380 private Collection getAllPluginDescriptors() { 381 List result = new LinkedList (); 382 result.addAll(registry.getPluginDescriptors()); 383 Collections.sort(result, new IdentityComparator()); 384 return Collections.unmodifiableCollection(result); 385 } 386 387 private Collection getAllPluginFragments() { 388 List result = new LinkedList (); 389 result.addAll(registry.getPluginFragments()); 390 Collections.sort(result, new IdentityComparator()); 391 return Collections.unmodifiableCollection(result); 392 } 393 394 private Collection getAllExtensionPoints() { 395 List result = new LinkedList (); 396 for (Iterator 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 getAllExtensions() { 405 List result = new LinkedList (); 406 for (Iterator 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 418 public static final class Tool { 419 private String relativePath; 420 421 protected Tool(final String aRelativePath) { 422 this.relativePath = aRelativePath; 423 } 424 425 429 public String getLink(final Documentation.Reference ref) { 430 if (isAbsoluteUrl(ref.getRef())) { 431 return ref.getRef(); 432 } 433 String 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(); } 448 449 453 public boolean isAbsoluteUrl(final String url) { 454 try { 455 String protocol = new URL (url).getProtocol(); 456 return (protocol != null) && (protocol.length() > 0); 457 } catch (MalformedURLException e) { 458 return false; 459 } 460 } 461 462 467 public String processDocText(final String text) { 468 if ((text == null) || (text.length() == 0)) { 469 return ""; } 471 return text.replaceAll("(?d)(?m)\\$\\{relativePath\\}", relativePath); 473 } 474 } 475 476 static final class IdentityComparator implements Comparator { 477 480 public int compare(final Object o1, final Object o2) { 481 return ((Identity) o1).getId().compareTo( 482 ((Identity) o2).getId()); 483 } 484 } 485 } 486 | Popular Tags |