001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2007-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.admin.doc;
028
029 import java.io.File;
030 import java.io.PrintWriter;
031 import java.util.Collection;
032 import java.util.Iterator;
033 import java.util.Properties;
034 import java.util.TreeMap;
035 import java.util.TreeSet;
036 import org.opends.messages.Message;
037 import org.opends.server.admin.ACIPropertyDefinition;
038 import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
039 import org.opends.server.admin.AbstractManagedObjectDefinition;
040 import org.opends.server.admin.AdministratorAction.Type;
041 import org.opends.server.admin.AggregationPropertyDefinition;
042 import org.opends.server.admin.AliasDefaultBehaviorProvider;
043 import org.opends.server.admin.AttributeTypePropertyDefinition;
044 import org.opends.server.admin.BooleanPropertyDefinition;
045 import org.opends.server.admin.ClassLoaderProvider;
046 import org.opends.server.admin.ClassPropertyDefinition;
047 import org.opends.server.admin.DNPropertyDefinition;
048 import org.opends.server.admin.DefaultBehaviorProvider;
049 import org.opends.server.admin.DefinedDefaultBehaviorProvider;
050 import org.opends.server.admin.DurationPropertyDefinition;
051 import org.opends.server.admin.EnumPropertyDefinition;
052 import org.opends.server.admin.IPAddressMaskPropertyDefinition;
053 import org.opends.server.admin.IPAddressPropertyDefinition;
054 import org.opends.server.admin.IntegerPropertyDefinition;
055 import org.opends.server.admin.LDAPProfile;
056 import org.opends.server.admin.PropertyDefinition;
057 import org.opends.server.admin.PropertyDefinitionVisitor;
058 import org.opends.server.admin.PropertyOption;
059 import org.opends.server.admin.RelationDefinition;
060 import org.opends.server.admin.RelationOption;
061 import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
062 import org.opends.server.admin.SizePropertyDefinition;
063 import org.opends.server.admin.StringPropertyDefinition;
064 import org.opends.server.admin.Tag;
065 import org.opends.server.admin.TopCfgDefn;
066 import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
067 import org.opends.server.admin.std.meta.RootCfgDefn;
068 import org.opends.server.types.InitializationException;
069 import org.opends.server.util.EmbeddedUtils;
070
071 /**
072 * This class allow Configuration Guide documentation generation (html format).
073 * It is based on the Admin Framework Introspection API
074 *
075 */
076 public class ConfigGuideGeneration {
077
078 // Note : still to be done :
079 // I18n support. Today all the strings are hardcoded in this file
080
081 private final static String ACI_SYNTAX_REL_URL = "/page/ACISyntax";
082 private final static String DURATION_SYNTAX_REL_URL =
083 "/page/DefinitionDuration";
084 private final String CSS_FILE = "opends-config.css";
085
086 private final String MAIN_FILE = "index.html";
087 private final String INHERITANCE_TREE_FILE =
088 "ManagedObjectInheritanceTree.html";
089 private final String RELATION_TREE_FILE = "ManagedObjectRelationTree.html";
090 private final String MO_LIST_FILE = "ManagedObjectList.html";
091 private final String PROPERTIES_INDEX_FILE = "PropertiesIndex.html";
092 private final String WELCOME_FILE = "welcome.html";
093 private final String MAINTOP_FILE = "maintop.html";
094 private final String INDEX_FILE = "index.html";
095
096 private static final String CONFIG_GUIDE_DIR = "opends_config_guide";
097 private final String MAIN_FRAME = "mainFrame";
098
099 /**
100 * Entry point for documentation generation.
101 *
102 * Properties:
103 * GenerationDir - The directory where the doc is generated
104 * (default is /var/tmp/[CONFIG_GUIDE_DIR>])
105 * LdapMapping - Presence means that the LDAP mapping section is to be
106 * generated (default is no)
107 * OpendsWiki - The URL of the OpenDS Wiki
108 * (default is "https://www.opends.org/wiki")
109 * OpendsHome - The URL of the OpenDS project Home page
110 * (default is "http://www.opends.org")
111 *
112 * @param args none.
113 */
114 public static void main(String[] args) {
115 Properties properties = System.getProperties();
116 generationDir = properties.getProperty("GenerationDir");
117 if (generationDir == null) {
118 // Default dir is prefixed by the system-dependent default temporary dir
119 generationDir = System.getProperty("java.io.tmpdir") + File.separator +
120 CONFIG_GUIDE_DIR;
121 }
122 // Create new dir if necessary
123 try {
124 (new File(generationDir)).mkdir();
125 } catch (Exception e) {
126 e.printStackTrace();
127 System.exit(1);
128 }
129 System.out.println("Generation directory is : " + generationDir);
130
131 if (properties.getProperty("LdapMapping") != null) {
132 ldapMapping = true;
133 }
134
135 opendsWiki = properties.getProperty("OpendsWiki");
136 if (opendsWiki == null) {
137 // Default is current wiki
138 opendsWiki = "https://www.opends.org/wiki";
139 }
140 aciSyntaxPage = opendsWiki + ACI_SYNTAX_REL_URL;
141 durationSyntaxPage = opendsWiki + DURATION_SYNTAX_REL_URL;
142
143 opendsHome = properties.getProperty("OpendsHome");
144 if (opendsHome == null) {
145 // Default is current OpenDS project home
146 opendsHome = "http://www.opends.org";
147 }
148
149 ConfigGuideGeneration myGen = new ConfigGuideGeneration();
150 myGen.generate();
151 }
152
153 private void generate() {
154 init();
155
156 // Generate the relation tree of all the managed objects
157 genManagedObjectRelationTree(catTopRelList);
158
159 // Generate the inheritance tree of all the managed objects
160 genManagedObjectInheritanceTree(catTopMoList);
161
162 // Generate all the managed objects and their children
163 genAllManagedObject(topMoList);
164
165 // Generate a list of managed objects
166 genManagedObjectList(moList);
167
168 // Generate an index of properties
169 genPropertiesIndex();
170
171 // Generate the Index page
172 genIndexPage();
173
174 // Generate the Main Top page
175 genMainTopPage();
176
177 // Generate the Welcome page
178 genWelcomePage();
179 }
180
181 private void init() {
182
183 // Build a list of top relations
184 RootCfgDefn rootCfg = RootCfgDefn.getInstance();
185 for (RelationDefinition rel : rootCfg.getAllRelationDefinitions()) {
186 topRelList.put(rel.getChildDefinition().getName(), rel);
187 }
188
189 // Enable the client-side class loader to explicitly load classes
190 // which are not directly reachable from the root configuration
191 EmbeddedUtils.initializeForClientUse();
192 // Bootstrap definition classes.
193 try {
194 ClassLoaderProvider.getInstance().enable();
195 } catch (InitializationException e) {
196 System.err.println("ERROR : Cannot enable the client-side class loader.");
197 e.printStackTrace();
198 System.exit(1);
199 }
200 // Switch off class name validation in client.
201 ClassPropertyDefinition.setAllowClassValidation(false);
202 // Switch off attribute type name validation in client.
203 AttributeTypePropertyDefinition.setCheckSchema(false);
204
205 // Build a sorted list of top managed objects
206 TopCfgDefn topCfg = TopCfgDefn.getInstance();
207 Collection<AbstractManagedObjectDefinition<?, ?>> topObjects =
208 topCfg.getChildren();
209 for (AbstractManagedObjectDefinition topObject : topObjects) {
210 if (topObject.getName().equals("")) {
211 // root
212 continue;
213 }
214 topMoList.put(topObject.getName(), topObject);
215 }
216
217
218 // Build a list of top relations by category (core, database, ...)
219 for (RelationDefinition rel : topRelList.values()) {
220 AbstractManagedObjectDefinition<?, ?> mo = rel.getChildDefinition();
221 Collection<Tag> tags = mo.getAllTags();
222 for (Tag tag : tags) {
223 TreeMap<String, RelationDefinition> catMap =
224 catTopRelList.get(tag.getName());
225 if (catMap == null) {
226 catMap = new TreeMap<String, RelationDefinition>();
227 catTopRelList.put(tag.getName(), catMap);
228 }
229 catMap.put(mo.getName(), rel);
230 }
231 }
232
233 // Build a list of top managed objects by category (core, database, ...)
234 for (AbstractManagedObjectDefinition<?, ?> topObject : topMoList.values()) {
235 Collection<Tag> tags = topObject.getAllTags();
236 for (Tag tag : tags) {
237 TreeMap<String, AbstractManagedObjectDefinition> catMap =
238 catTopMoList.get(tag.getName());
239 if (catMap == null) {
240 catMap = new TreeMap<String, AbstractManagedObjectDefinition>();
241 catTopMoList.put(tag.getName(), catMap);
242 }
243 catMap.put(topObject.getName(), topObject);
244 }
245 }
246
247 }
248
249 /**
250 * Generate the inheritance tree of all the managed objects.
251 */
252 @SuppressWarnings("unchecked")
253 private void genManagedObjectInheritanceTree(
254 TreeMap<String, TreeMap<String, AbstractManagedObjectDefinition>> list) {
255
256 htmlHeader("OpenDS Configuration Reference - Inheritance View");
257 tabMenu(INHERITANCE_TREE_FILE);
258 viewHelp("This view represents the inheritance relationships between " +
259 "configuration components.");
260 jumpSection();
261
262 for (String catName : list.keySet()) {
263 heading3(getFriendlyName(catName));
264 // Get the list of the category
265 TreeMap<String, AbstractManagedObjectDefinition> catList =
266 list.get(catName);
267 for (AbstractManagedObjectDefinition mo : catList.values()) {
268 if ((relList.get(mo.getName()) != null) &&
269 (relList.get(mo.getName()).hasOption(RelationOption.HIDDEN))) {
270 continue;
271 }
272 paragraph(
273 getLink(mo.getUserFriendlyName().toString(),
274 mo.getName() + ".html", MAIN_FRAME));
275 if (mo.hasChildren()) {
276 genMoInheritanceTree(makeMOTreeMap(mo.getChildren()));
277 }
278 }
279 }
280
281 htmlFooter();
282 generateFile(INHERITANCE_TREE_FILE);
283 }
284
285 @SuppressWarnings("unchecked")
286 private void genMoInheritanceTree(
287 TreeMap<String, AbstractManagedObjectDefinition> catList) {
288
289 beginList();
290 for (AbstractManagedObjectDefinition mo : catList.values()) {
291 link(mo.getUserFriendlyName().toString(), mo.getName() + ".html",
292 MAIN_FRAME);
293 if (mo.hasChildren()) {
294 genMoInheritanceTree(makeMOTreeMap(mo.getChildren()));
295 }
296 }
297 endList();
298 }
299
300 private void jumpSection() {
301 htmlBuff.append("<p class=\"category-index\">" +
302 "<strong>Jump To:</strong><br>\n");
303
304 String[] catNames = catTopMoList.keySet().toArray(new String[0]);
305 for (int ii=0; ii < catNames.length; ii++) {
306 if (ii != 0) {
307 htmlBuff.append(", ");
308 }
309 String catFriendlyName = getFriendlyName(catNames[ii]);
310 htmlBuff.append(getLink(catFriendlyName, "#" + catFriendlyName));
311 }
312 htmlBuff.append("</p>\n");
313 }
314
315
316 /**
317 * Generate the relation tree of all the managed objects.
318 */
319 private void genManagedObjectRelationTree(
320 TreeMap <String, TreeMap<String, RelationDefinition>> list) {
321
322 htmlHeader("OpenDS Configuration Reference - Structure View");
323 tabMenu(RELATION_TREE_FILE);
324 viewHelp("This view represents the structural relationships between " +
325 "components and indicates how certain components can exist only within " +
326 "container components.");
327 jumpSection();
328
329 for (String catName : list.keySet()) {
330 heading3(getFriendlyName(catName));
331 // Get the list of the category
332 TreeMap<String, RelationDefinition> catList = list.get(catName);
333 genMORelationTree(catList);
334 }
335
336 htmlFooter();
337 generateFile(RELATION_TREE_FILE);
338 }
339
340
341 @SuppressWarnings("unchecked")
342 private void genMORelationTree(TreeMap<String, RelationDefinition> list) {
343 for (RelationDefinition rel : list.values()) {
344 AbstractManagedObjectDefinition childMo = rel.getChildDefinition();
345 AbstractManagedObjectDefinition parentMo = rel.getParentDefinition();
346 relList.put(childMo.getName(), rel);
347 if (rel.hasOption(RelationOption.HIDDEN)) {
348 continue;
349 }
350 String linkStr = getLink(childMo.getUserFriendlyName().toString(),
351 childMo.getName() + ".html", MAIN_FRAME);
352 String fromStr = "";
353 if (!parentMo.getName().equals("")) {
354 fromStr = " (from " +
355 getLink(parentMo.getUserFriendlyName().toString(),
356 parentMo.getName() + ".html", MAIN_FRAME) + ")";
357 }
358 if (!inList) {
359 paragraph(linkStr + fromStr);
360 } else {
361 bullet(linkStr + fromStr);
362 }
363 genMORelationSubTree(makeRelTreeMap(childMo.getAllRelationDefinitions()));
364 if (childMo.hasChildren()) {
365 for (Iterator<AbstractManagedObjectDefinition> it =
366 childMo.getChildren().iterator(); it.hasNext();) {
367
368 AbstractManagedObjectDefinition mo = it.next();
369 genMORelationSubTree(makeRelTreeMap(mo.getAllRelationDefinitions()));
370 }
371 }
372 }
373 }
374
375
376 private void genMORelationSubTree(TreeMap<String, RelationDefinition> list) {
377 if (!list.values().isEmpty()) {
378 beginList();
379 genMORelationTree(list);
380 endList();
381 }
382 }
383
384
385 /**
386 * Generate all the managed objects HTML pages.
387 */
388 @SuppressWarnings("unchecked")
389 private void genAllManagedObject(
390 TreeMap<String, AbstractManagedObjectDefinition> list) {
391
392 for (AbstractManagedObjectDefinition mo : list.values()) {
393 if ((relList.get(mo.getName()) != null) &&
394 (relList.get(mo.getName()).hasOption(RelationOption.HIDDEN))) {
395 continue;
396 }
397 moList.put(mo.getName(), mo);
398 genManagedObject(mo);
399 if (mo.hasChildren()) {
400 genAllManagedObject(makeMOTreeMap(mo.getChildren()));
401 }
402 }
403 }
404
405 private void genManagedObject(AbstractManagedObjectDefinition mo) {
406 //------------------------------------------------------------------------
407 // Header
408 //------------------------------------------------------------------------
409
410 homeLink();
411 String title = mo.getUserFriendlyName().toString();
412 htmlHeader("OpenDS - " + title);
413
414 // title
415 heading2(title);
416
417 // Abstract notice
418 if (mo.hasChildren()) {
419 paragraph(
420 "Note: this is an abstract component, that cannot be instantiated.",
421 TextStyle.ITALIC);
422 }
423
424 // description
425 paragraph(mo.getSynopsis());
426 paragraph(mo.getDescription());
427
428 // sub-components
429 if (mo.hasChildren()) {
430 heading3("Direct Subcomponents");
431 paragraph("The following " + mo.getUserFriendlyPluralName() +
432 " are available in the server :");
433 beginList();
434 @SuppressWarnings("unchecked")
435 TreeMap<String, AbstractManagedObjectDefinition> children =
436 makeMOTreeMap(mo.getChildren());
437 for ( AbstractManagedObjectDefinition child : children.values()) {
438 link(child.getUserFriendlyName().toString(), child.getName() + ".html");
439 }
440 endList();
441
442 paragraph("These " + mo.getUserFriendlyPluralName() +
443 " inherit from the properties described below.");
444 }
445
446 // Parent
447 if (!mo.getParent().isTop()) {
448 heading3("Parent Component");
449 paragraph("The " + mo.getUserFriendlyName() +
450 " component inherits from the " +
451 getLink(mo.getParent().getUserFriendlyName().toString(),
452 mo.getParent().getName() + ".html"));
453 }
454
455 // Relations
456 generateRelationsSection(mo);
457
458 // Page links in case of LDAP mapping
459 if (ldapMapping) {
460 newline();
461 horizontalLine();
462 newline();
463 paragraph("This page describes the " + mo.getUserFriendlyName() + ":");
464 beginList();
465 link("Properties", "#Properties");
466 link("LDAP Mapping", "#LDAP Mapping");
467 endList();
468 newline();
469 }
470
471
472 //------------------------------------------------------------------------
473 // Properties
474 //------------------------------------------------------------------------
475
476 heading3("Properties");
477
478 paragraph("A description of each property follows.");
479 newline();
480
481 TreeMap<String, PropertyDefinition> basicProps =
482 new TreeMap<String, PropertyDefinition>();
483 TreeMap<String, PropertyDefinition> advancedProps =
484 new TreeMap<String, PropertyDefinition>();
485 // Properties actually defined in this managed object
486 @SuppressWarnings("unchecked")
487 Collection<PropertyDefinition> props = mo.getAllPropertyDefinitions();
488 for ( PropertyDefinition prop : props) {
489 if (prop.hasOption(PropertyOption.ADVANCED)) {
490 advancedProps.put(prop.getName(), prop);
491 } else {
492 basicProps.put(prop.getName(), prop);
493 }
494 }
495
496 propertiesLinkTable(basicProps, advancedProps);
497
498 // basic properties
499 if (basicProps.size() > 0) {
500 heading4("Basic Properties");
501 for ( PropertyDefinition prop : basicProps.values()) {
502 generateProperty(mo, prop);
503 newline();
504 }
505 newline();
506 }
507
508 // advanced properties
509 if (advancedProps.size() > 0) {
510 heading4("Advanced Properties");
511 for ( PropertyDefinition prop : advancedProps.values()) {
512 generateProperty(mo, prop);
513 newline();
514 }
515 newline();
516 }
517
518 if (ldapMapping) {
519 genLdapMapping(mo);
520 }
521
522 htmlFooter();
523
524 generateFile(mo.getName() + ".html");
525 }
526
527
528 private TreeMap<String, PropertyDefinition>
529 getPropertyList(AbstractManagedObjectDefinition mo) {
530
531 @SuppressWarnings("unchecked")
532 Collection<PropertyDefinition> props = mo.getAllPropertyDefinitions();
533 return makePropTreeMap(props);
534 }
535
536 private void homeLink() {
537 htmlBuff.append("<div style=\"font-size:11px;margin-top:-10px;" +
538 "margin-bottom:-10px; text-align:right\"><a href=\"" +
539 MAIN_FILE +
540 "\" target=\"_top\">Configuration Reference Home</a></div>");
541 }
542
543
544 private void generateRelationsSection(AbstractManagedObjectDefinition mo) {
545 // Composition relations
546 @SuppressWarnings("unchecked")
547 Collection<RelationDefinition> compRels = mo.getRelationDefinitions();
548 @SuppressWarnings("unchecked")
549 Collection<RelationDefinition> reverseCompRels =
550 mo.getReverseRelationDefinitions();
551 // Aggregation properties
552 @SuppressWarnings("unchecked")
553 Collection<AggregationPropertyDefinition> aggregProps =
554 mo.getAggregationPropertyDefinitions();
555 @SuppressWarnings("unchecked")
556 Collection<AggregationPropertyDefinition> reverseAggregProps =
557 mo.getReverseAggregationPropertyDefinitions();
558
559
560 // Check if something to print in composition relations
561 // (even if the list not empty, it may contain only hidden relations)
562 boolean isCompRelsEmpty = true;
563 if (!compRels.isEmpty()) {
564 for (RelationDefinition rel : compRels) {
565 if (rel.hasOption(RelationOption.HIDDEN)) {
566 continue;
567 }
568 isCompRelsEmpty = false;
569 }
570 }
571 boolean isReverseCompRelsEmpty = true;
572 if (!reverseCompRels.isEmpty()) {
573 for (RelationDefinition rel : reverseCompRels) {
574 if (rel.hasOption(RelationOption.HIDDEN)) {
575 continue;
576 }
577 // check if it is not root
578 if (rel.getParentDefinition().getName().equals("")) {
579 continue;
580 }
581 isReverseCompRelsEmpty = false;
582 }
583 }
584
585 //
586 // Relations FROM this component
587 //
588
589 if (!isCompRelsEmpty || !aggregProps.isEmpty()) {
590 heading3("Relations From this Component");
591 }
592
593 if (!isCompRelsEmpty) {
594 paragraph(
595 "The following components have a direct COMPOSITION relation FROM " +
596 mo.getUserFriendlyPluralName() + " :");
597 for ( RelationDefinition rel : compRels) {
598 if (rel.hasOption(RelationOption.HIDDEN)) {
599 continue;
600 }
601 beginList();
602 AbstractManagedObjectDefinition childRel = rel.getChildDefinition();
603 link(childRel.getUserFriendlyName().toString(), childRel.getName() +
604 ".html");
605 endList();
606 }
607 }
608 if (!aggregProps.isEmpty()) {
609 paragraph(
610 "The following components have a direct AGGREGATION relation FROM " +
611 mo.getUserFriendlyPluralName() + " :");
612 TreeMap<String, AbstractManagedObjectDefinition> componentList =
613 new TreeMap<String, AbstractManagedObjectDefinition>();
614 for ( AggregationPropertyDefinition agg : aggregProps) {
615 RelationDefinition rel = agg.getRelationDefinition();
616 AbstractManagedObjectDefinition childRel = rel.getChildDefinition();
617 componentList.put(childRel.getName(), childRel);
618 }
619 for (AbstractManagedObjectDefinition component : componentList.values()) {
620 beginList();
621 link(component.getUserFriendlyName().toString(), component.getName() +
622 ".html");
623 endList();
624 }
625 }
626
627
628 //
629 // Relations TO this component
630 //
631
632 if (!isReverseCompRelsEmpty || !reverseAggregProps.isEmpty()) {
633 heading3("Relations To this Component");
634 }
635
636 if (!mo.getReverseRelationDefinitions().isEmpty()) {
637 if (!isReverseCompRelsEmpty) {
638 paragraph(
639 "The following components have a direct COMPOSITION relation TO " +
640 mo.getUserFriendlyPluralName() + " :");
641 for ( RelationDefinition rel : reverseCompRels) {
642 beginList();
643 AbstractManagedObjectDefinition childRel = rel.getParentDefinition();
644 link(childRel.getUserFriendlyName().toString(), childRel.getName() +
645 ".html");
646 endList();
647 }
648 }
649 }
650 if (!reverseAggregProps.isEmpty()) {
651 paragraph(
652 "The following components have a direct AGGREGATION relation TO " +
653 mo.getUserFriendlyPluralName() + " :");
654 TreeMap<String, AbstractManagedObjectDefinition> componentList =
655 new TreeMap<String, AbstractManagedObjectDefinition>();
656 for ( AggregationPropertyDefinition agg : reverseAggregProps) {
657 AbstractManagedObjectDefinition fromMo =
658 agg.getManagedObjectDefinition();
659 componentList.put(fromMo.getName(), fromMo);
660 }
661 for (AbstractManagedObjectDefinition component : componentList.values()) {
662 beginList();
663 link(component.getUserFriendlyName().toString(), component.getName() +
664 ".html");
665 endList();
666
667 }
668 }
669
670 }
671
672 private void generateProperty(
673 AbstractManagedObjectDefinition mo, PropertyDefinition prop) {
674
675 // Property name
676 paragraph(getAnchor(prop.getName()) + prop.getName(), TextStyle.STANDARD,
677 "propertyname");
678
679 // Property table
680 startTable();
681 tableRow("Description",
682 ((prop.getSynopsis() != null) ? prop.getSynopsis().toString()+ " " : "") +
683 ((prop.getDescription() != null) ?
684 prop.getDescription().toString() : ""));
685
686 // Default value
687 String defValueStr = getDefaultBehaviorString(prop);
688 tableRow("Default Value", defValueStr);
689
690 tableRow("Allowed Values", getSyntaxStr(prop));
691
692 tableRow("Multi-valued",
693 (prop.hasOption(PropertyOption.MULTI_VALUED) ? "Yes" : "No"));
694
695 if (prop.hasOption(PropertyOption.MANDATORY)) {
696 tableRow("Required", "Yes");
697 } else {
698 tableRow("Required", "No");
699 }
700
701 String action = "None";
702 if (prop.getAdministratorAction() != null) {
703 Message synopsis = prop.getAdministratorAction().getSynopsis();
704 Type actionType = prop.getAdministratorAction().getType();
705 String actionStr = "";
706 if (actionType == actionType.COMPONENT_RESTART) {
707 actionStr = "The " + mo.getUserFriendlyName() +
708 " must be disabled and re-enabled for changes to this setting " +
709 "to take effect";
710 } else if (actionType == actionType.SERVER_RESTART) {
711 actionStr = "Restart the server";
712 } else if (actionType == actionType.NONE) {
713 actionStr = "None";
714 }
715 String dot = (actionStr.equals("") ? "" : ". ");
716 action = actionStr +
717 ((synopsis != null) ? dot + synopsis : "");
718 }
719 tableRow("Admin Action Required", action);
720
721 if (prop.hasOption(PropertyOption.ADVANCED)) {
722 tableRow("Advanced Property", "Yes");
723 } else {
724 tableRow("Advanced Property", "No");
725 }
726
727 endTable();
728
729 }
730
731
732 private void propertiesLinkTable(TreeMap<String,
733 PropertyDefinition> basicProps,
734 TreeMap<String, PropertyDefinition> advancedProps) {
735 htmlBuff.append(
736 "<table border=\"0\" cellspacing=\"0\" class=\"jump-table\">\n" +
737 " <tr>\n" +
738 " <th>Basic Properties:</th>\n" +
739 " <th>Advanced Properties:</th>\n" +
740 " </tr>\n");
741
742 PropertyDefinition[] basicPropsArray =
743 basicProps.values().toArray(new PropertyDefinition[0]);
744 PropertyDefinition[] advancedPropsArray =
745 advancedProps.values().toArray(new PropertyDefinition[0]);
746
747 for (int ii=0;
748 (ii < basicPropsArray.length) || (ii < advancedPropsArray.length);
749 ii++) {
750 String basicPropName =
751 ii < basicPropsArray.length ? basicPropsArray[ii].getName() : null;
752 String advancedPropName =
753 ii < advancedPropsArray.length ?
754 advancedPropsArray[ii].getName() : null;
755
756 String basicHtmlCell = "";
757 if (basicPropName != null) {
758 basicHtmlCell = " <td>↓ <a href=\"#" + basicPropName + "\">"
759 + basicPropName + "</a></td>\n";
760 } else if ((basicPropsArray.length == 0) && (ii == 0)) {
761 basicHtmlCell = " <td> None</td>\n";
762 } else if (ii >= basicPropsArray.length) {
763 // Case of nb of basic props < nb of advanced props
764 basicHtmlCell = " <td></td>\n";
765 }
766
767 String advancedHtmlCell = "";
768 if (advancedPropName != null) {
769 advancedHtmlCell = " <td>↓ <a href=\"#" + advancedPropName +
770 "\">" + advancedPropName + "</a></td>\n";
771 } else if ((advancedPropsArray.length == 0) && (ii == 0)) {
772 advancedHtmlCell = " <td> None</td>\n";
773 }
774
775 htmlBuff.append("<tr>\n");
776 htmlBuff.append(basicHtmlCell + advancedHtmlCell);
777 htmlBuff.append("</tr>\n");
778 }
779 htmlBuff.append("</table>\n");
780 }
781
782
783 private void genLdapMapping(AbstractManagedObjectDefinition mo) {
784 //------------------------------------------------------------------------
785 // LDAP mapping
786 //------------------------------------------------------------------------
787
788 heading3("LDAP Mapping");
789 paragraph(
790 "Each configuration property can be mapped to a specific " +
791 "LDAP attribute under the \"cn=config\" entry. " +
792 "The mappings that follow are provided for information only. " +
793 "In general, you should avoid changing the server configuration " +
794 "by manipulating the LDAP attributes directly.");
795
796 // Managed object table
797 startTable();
798
799 LDAPProfile ldapProfile = LDAPProfile.getInstance();
800 tableRow("Base DN", getBaseDN(mo, ldapProfile));
801
802 tableRow("objectclass name", ldapProfile.getObjectClass(mo));
803 if (mo.getParent().getName() != null) {
804 String superior = "";
805 if (mo.getParent().getName().equals("top")) {
806 superior = "top";
807 } else {
808 if (moList.get(mo.getParent().getName()) != null) {
809 superior =
810 ldapProfile.getObjectClass(moList.get(mo.getParent().getName()));
811 } else {
812 System.err.println(
813 "Error: managed object " + mo.getName() + " not found.");
814 }
815 }
816 tableRow("objectclass superior", superior);
817 } else {
818 System.err.println(
819 "Error: objectclass superior not found for " + mo.getName());
820 }
821 endTable();
822
823 newline();
824 // Properties table
825 startTable();
826 tableRow("Property", "LDAP attribute");
827 for ( PropertyDefinition prop : getPropertyList(mo).values()) {
828 tableRow(prop.getName(), ldapProfile.getAttributeName(mo, prop));
829 }
830
831 endTable();
832
833 }
834
835 private void genManagedObjectList(
836 TreeMap<String, AbstractManagedObjectDefinition> list) {
837
838 htmlHeader("OpenDS Configuration Reference - Components View");
839 tabMenu(MO_LIST_FILE);
840 viewHelp("This view provides a list of all configuration components, " +
841 "in alphabetical order.");
842
843 newline();
844 StringBuffer moPointers = new StringBuffer();
845 String lettersPointers = "";
846 String firstChar = ".";
847 for (AbstractManagedObjectDefinition mo : list.values()) {
848 if (!mo.getName().startsWith(firstChar)) {
849 firstChar = mo.getName().substring(0, 1);
850 String letter = firstChar.toUpperCase();
851 moPointers.append(getAnchor(letter) + getHeading2(letter));
852 lettersPointers += getLink(letter, "#" + letter) + " ";
853 }
854 moPointers.append(
855 "<p> " +
856 getLink(mo.getUserFriendlyName().toString(), mo.getName() + ".html",
857 MAIN_FRAME) +
858 "</p>\n");
859 }
860 paragraph(lettersPointers);
861 htmlBuff.append(moPointers);
862 htmlFooter();
863 generateFile(MO_LIST_FILE);
864 }
865
866 private void genPropertiesIndex() {
867
868 // Build a sorted list of (property name + its managed object name)
869 TreeSet<String> propMoList = new TreeSet<String>();
870 for (AbstractManagedObjectDefinition<?, ?> mo : moList.values()) {
871 for (PropertyDefinition<?> prop : mo.getPropertyDefinitions()) {
872 propMoList.add(
873 prop.getName() + "," + prop.getManagedObjectDefinition().getName());
874 }
875 }
876
877 String lettersPointers = "";
878 String firstChar = ".";
879 for (String propMoStr : propMoList) {
880 String[] propMoArray = propMoStr.split(",");
881 String propName = propMoArray[0];
882 AbstractManagedObjectDefinition mo = moList.get(propMoArray[1]);
883 if (!propName.startsWith(firstChar)) {
884 firstChar = propName.substring(0, 1);
885 String letter = firstChar.toUpperCase();
886 htmlBuff.append(getAnchor(letter) + getHeading2(letter));
887 lettersPointers += getLink(letter, "#" + letter) + " ";
888 }
889 String propLink = getLink(propName,
890 mo.getName() + ".html" + "#" + propName, MAIN_FRAME);
891 String moLink =
892 getLink(mo.getUserFriendlyName().toString(), mo.getName() + ".html",
893 MAIN_FRAME, "#666");
894 paragraph(propLink + " [ " + moLink + " ]");
895 }
896
897 String indexBody = htmlBuff.toString();
898 htmlBuff = new StringBuffer();
899 htmlHeader("OpenDS Configuration Reference - Properties View");
900 tabMenu(PROPERTIES_INDEX_FILE);
901 viewHelp("This view provides a list of all configuration properties, " +
902 "in alphabetical order, and indicates the configuration component to " +
903 "which each property applies.");
904
905 newline();
906 paragraph(lettersPointers);
907 htmlBuff.append(indexBody);
908 htmlFooter();
909 generateFile(PROPERTIES_INDEX_FILE);
910 }
911
912 private void genWelcomePage() {
913 htmlHeader("OpenDS Configuration Reference - Welcome");
914 heading2("About This Reference");
915 paragraph("This reference " +
916 "describes the OpenDS configuration properties that can be manipulated " +
917 "with the dsconfig command.");
918 paragraph("Configuration components are grouped according to the area of " +
919 "the server in which they are used, as follows:");
920
921 beginList();
922 for (String catName : catTopMoList.keySet()) {
923 bullet(getFriendlyName(catName));
924 }
925 endList();
926
927 paragraph(
928 "For ease of reference, the configuration is described on multiple " +
929 "tabs. These tabs provide alternative views of the configuration " +
930 "components:");
931 beginList();
932 bullet("The <strong>Inheritance</strong> view represents the inheritance " +
933 "relationships between configuration components. A sub-component " +
934 "inherits all of the properties of its parent component.");
935 bullet("The <strong>Structure</strong> view represents the structural " +
936 "relationships between components and indicates how certain components " +
937 "can exist only within container components. When a container " +
938 "component is deleted, all of the components within it are also " +
939 "deleted.");
940 bullet(
941 "The <strong>Components</strong> view provides an alphabetical list " +
942 "of all configuration components.");
943 bullet(
944 "The <strong>Properties</strong> view provides an alphabetical list " +
945 "of all configuration properties, and indicates the configuration " +
946 "component to which each property applies.");
947 endList();
948
949 newline();
950 paragraph("When you set up OpenDS, certain components are created in the " +
951 "configuration by default. These components are configured with " +
952 "specific values, which are not necessarily the same as the " +
953 "\"default values\" of new components that you create using dsconfig. " +
954 "The \"default values\" listed in this document refer to the values " +
955 "of the new components that you create using dsconfig.");
956
957 htmlFooter();
958 generateFile(WELCOME_FILE);
959
960 }
961
962 private void genMainTopPage() {
963 htmlHeader("OpenDS Configuration Reference - Main Top");
964 htmlBuff.append("<div class=\"breadcrumb\"><span class=\"pageactions\">" +
965 "<a href=\"" + opendsWiki + "\" target=\"_parent\">" +
966 "<span style=\"font-size: 12px;\">« </span>" +
967 "Back to OpenDS Wiki</a></span> </div>\n");
968 htmlBuff.append("<table class=\"titletable\" cellspacing=\"0\" " +
969 "width=\"100%\">\n");
970 htmlBuff.append("<tbody><tr>\n");
971 htmlBuff.append(" <td><h2>OpenDS Configuration Reference</h2></td>\n");
972 htmlBuff.append(" <td valign=\"bottom\" width=\"10%\">" +
973 "<a href=\"" + opendsHome + "\" target=\"_parent\">" +
974 "<img src=\"opends_logo_sm.png\" alt=\"OpenDS Logo\" align=\"bottom\" " +
975 "border=\"0\" height=\"33\" width=\"104\"></a></td>\n");
976 htmlBuff.append("</tr>\n");
977 htmlBuff.append("</tbody></table>\n");
978
979 htmlFooter();
980 generateFile(MAINTOP_FILE);
981
982 }
983
984 private void genIndexPage() {
985 htmlBuff.append(getHtmlHeader("OpenDS Configuration Reference"));
986
987 htmlBuff.append("<frameset rows=\"80,*\" framespacing=\"1\" " +
988 "frameborder=\"yes\" border=\"1\" bordercolor=\"#333333\">\n");
989 htmlBuff.append(" <frame src=\"" + MAINTOP_FILE + "\" name=\"topFrame\" " +
990 "id=\"topFrame\" border=\"1\" title=\"topFrame\" scrolling=\"no\">\n");
991 htmlBuff.append(" <frameset cols=\"375,*\" frameborder=\"yes\" " +
992 "border=\"1\" " +
993 "framespacing=\"1\">\n");
994 htmlBuff.append(" <frame src=\"" + INHERITANCE_TREE_FILE + "\" " +
995 "name=\"leftFrame\" id=\"leftFrame\" title=\"leftFrame\" " +
996 "scrolling=\"auto\">\n");
997 htmlBuff.append(" <frame src=\"" + WELCOME_FILE +
998 "\" name=\"mainFrame\" " +
999 "id=\"mainFrame\" title=\"mainFrame\" scrolling=\"auto\">\n");
1000 htmlBuff.append(" </frameset>\n");
1001 htmlBuff.append("</frameset>\n");
1002 htmlBuff.append("<noframes><body>\n");
1003 htmlBuff.append("</body>\n");
1004 htmlBuff.append("</noframes>\n");
1005 htmlBuff.append("</html>\n");
1006
1007 generateFile(INDEX_FILE);
1008 }
1009
1010 private String getBaseDN(
1011 AbstractManagedObjectDefinition mo, LDAPProfile ldapProfile) {
1012
1013 RelationDefinition rel = relList.get(mo.getName());
1014 if (rel != null) {
1015 String baseDn = ldapProfile.getRelationRDNSequence(rel);
1016 if (!baseDn.equals("")) {
1017 return baseDn;
1018 } else {
1019 // Check the parent relation
1020 return getBaseDN(rel.getParentDefinition(), ldapProfile);
1021 }
1022 } else if (moList.get(mo.getParent().getName()) != null) {
1023 // check its superior
1024 return getBaseDN(moList.get(mo.getParent().getName()), ldapProfile);
1025 } else {
1026 System.err.println("Error: Base DN not found for " + mo.getName());
1027 }
1028 return null;
1029 }
1030
1031 @SuppressWarnings("unchecked")
1032 private String getSyntaxStr(PropertyDefinition prop) {
1033 // Create a visitor for performing syntax specific processing.
1034 PropertyDefinitionVisitor<String, Void> visitor =
1035 new PropertyDefinitionVisitor<String, Void>() {
1036
1037 @Override
1038 public String visitACI(ACIPropertyDefinition prop, Void p) {
1039 return getLink("An ACI Syntax", aciSyntaxPage);
1040 }
1041
1042 @Override
1043 public String visitAggregation(
1044 AggregationPropertyDefinition prop, Void p) {
1045
1046 RelationDefinition rel = prop.getRelationDefinition();
1047 String linkStr = getLink(rel.getUserFriendlyName().toString(),
1048 rel.getName() + ".html");
1049 return "The DN of any " + linkStr + ". " +
1050 ((prop.getSourceConstraintSynopsis() != null) ?
1051 prop.getSourceConstraintSynopsis().toString() : "");
1052 }
1053
1054 @Override
1055 public String visitAttributeType(
1056 AttributeTypePropertyDefinition prop, Void p) {
1057 return "The name of an attribute type defined in the server schema.";
1058 }
1059
1060 @Override
1061 public String visitBoolean(BooleanPropertyDefinition prop, Void p) {
1062 return "true" + getNewLine() + "false";
1063 }
1064
1065 @Override
1066 public String visitClass(ClassPropertyDefinition prop, Void p) {
1067 String classStr =
1068 "A java class that implements or extends the class(es) :";
1069 for (String clazz : prop.getInstanceOfInterface()) {
1070 classStr += getNewLine() + clazz;
1071 }
1072 return classStr;
1073 }
1074
1075 @Override
1076 public String visitDN(DNPropertyDefinition prop, Void p) {
1077 String retStr = "A valid DN.";
1078 if (prop.getBaseDN() != null) {
1079 retStr += prop.getBaseDN().toString();
1080 }
1081 return retStr;
1082 }
1083
1084 @Override
1085 public String visitDuration(DurationPropertyDefinition prop, Void p) {
1086 String durationStr = "";
1087
1088 durationStr += getLink("A duration Syntax", durationSyntaxPage) +
1089 ". ";
1090 if (prop.isAllowUnlimited()) {
1091 durationStr += "A value of \"-1\" or \"unlimited\" for no limit. ";
1092 }
1093 if (prop.getMaximumUnit() != null) {
1094 durationStr += "Maximum unit is \"" +
1095 prop.getMaximumUnit().getLongName() + "\". ";
1096 }
1097 long lowerLimitStr = new Double(prop.getBaseUnit().
1098 fromMilliSeconds(prop.getLowerLimit())).longValue();
1099 durationStr += "Lower limit is " + lowerLimitStr +
1100 " " + prop.getBaseUnit().getLongName() + ". ";
1101 if (prop.getUpperLimit() != null) {
1102 long upperLimitStr = new Double(prop.getBaseUnit().
1103 fromMilliSeconds(prop.getUpperLimit())).longValue();
1104 durationStr += "Upper limit is " + upperLimitStr +
1105 " " + prop.getBaseUnit().getLongName() + ". ";
1106 }
1107
1108 return durationStr;
1109 }
1110
1111 @Override
1112 public String visitEnum(EnumPropertyDefinition prop, Void p) {
1113 String enumStr = "";
1114 Class en = prop.getEnumClass();
1115 for (Object cst : en.getEnumConstants()) {
1116 enumStr += cst.toString();
1117 if (prop.getValueSynopsis((Enum) cst) != null) {
1118 enumStr += " - " + prop.getValueSynopsis((Enum) cst).toString();
1119 }
1120 enumStr += getNewLine() + getNewLine();
1121 }
1122 return enumStr;
1123 }
1124
1125 @Override
1126 public String visitInteger(IntegerPropertyDefinition prop, Void p) {
1127 String intStr = "An integer value.";
1128 intStr += " Lower value is " + prop.getLowerLimit() + ".";
1129 if (prop.getUpperLimit() != null) {
1130 intStr += " Upper value is " + prop.getUpperLimit() + " .";
1131 }
1132 if (prop.isAllowUnlimited()) {
1133 intStr += " A value of \"-1\" or \"unlimited\" for no limit.";
1134 }
1135 if (prop.getUnitSynopsis() != null) {
1136 intStr += " Unit is " + prop.getUnitSynopsis() + ".";
1137 }
1138 return intStr;
1139 }
1140
1141 @Override
1142 public String visitIPAddress(IPAddressPropertyDefinition prop, Void p) {
1143 return "An IP address";
1144 }
1145
1146 @Override
1147 public String visitIPAddressMask(
1148 IPAddressMaskPropertyDefinition prop, Void p) {
1149
1150 return "An IP address mask";
1151 }
1152
1153 @Override
1154 public String visitSize(SizePropertyDefinition prop, Void p) {
1155 String sizeStr = "A positive integer representing a size.";
1156 if (prop.getLowerLimit() != 0) {
1157 sizeStr += " Lower value is " + prop.getLowerLimit() + ".";
1158 }
1159 if (prop.getUpperLimit() != null) {
1160 sizeStr += " Upper value is " + prop.getUpperLimit() + " .";
1161 }
1162 if (prop.isAllowUnlimited()) {
1163 sizeStr += " A value of \"-1\" or \"unlimited\" for no limit.";
1164 }
1165 return sizeStr;
1166 }
1167
1168 @Override
1169 public String visitString(StringPropertyDefinition prop, Void p) {
1170 String retStr = "A String";
1171 if (prop.getPatternSynopsis() != null) {
1172 retStr = prop.getPatternSynopsis().toString();
1173 }
1174 return retStr;
1175 }
1176
1177 @Override
1178 public String visitUnknown(PropertyDefinition prop, Void p) {
1179 return "Unknown";
1180 }
1181 };
1182
1183 // Invoke the visitor against the property definition.
1184 return (String) prop.accept(visitor, null);
1185
1186 }
1187
1188 @SuppressWarnings("unchecked")
1189 private String getDefaultBehaviorString(PropertyDefinition prop) {
1190 DefaultBehaviorProvider defaultBehav = prop.getDefaultBehaviorProvider();
1191 String defValueStr = "";
1192 if (defaultBehav instanceof UndefinedDefaultBehaviorProvider) {
1193 defValueStr = "None";
1194 } else if (defaultBehav instanceof DefinedDefaultBehaviorProvider) {
1195 DefinedDefaultBehaviorProvider defBehav =
1196 (DefinedDefaultBehaviorProvider) defaultBehav;
1197 for (Iterator<String> it = defBehav.getDefaultValues().iterator();
1198 it.hasNext();) {
1199
1200 String str = it.next();
1201 defValueStr += str + (it.hasNext() ? "\n" : "");
1202 }
1203 } else if (defaultBehav instanceof AliasDefaultBehaviorProvider) {
1204 AliasDefaultBehaviorProvider aliasBehav = (
1205 AliasDefaultBehaviorProvider) defaultBehav;
1206 defValueStr = aliasBehav.getSynopsis().toString();
1207 } else if
1208 (defaultBehav instanceof RelativeInheritedDefaultBehaviorProvider) {
1209 RelativeInheritedDefaultBehaviorProvider relativBehav =
1210 (RelativeInheritedDefaultBehaviorProvider) defaultBehav;
1211 defValueStr = getDefaultBehaviorString(
1212 relativBehav.getManagedObjectDefinition().
1213 getPropertyDefinition(relativBehav.getPropertyName()));
1214 } else if
1215 (defaultBehav instanceof AbsoluteInheritedDefaultBehaviorProvider) {
1216 AbsoluteInheritedDefaultBehaviorProvider absoluteBehav =
1217 (AbsoluteInheritedDefaultBehaviorProvider) defaultBehav;
1218 defValueStr = getDefaultBehaviorString(
1219 absoluteBehav.getManagedObjectDefinition().
1220 getPropertyDefinition(absoluteBehav.getPropertyName()));
1221 }
1222 return defValueStr;
1223 }
1224
1225 private TreeMap<String, AbstractManagedObjectDefinition> makeMOTreeMap(
1226 Collection<AbstractManagedObjectDefinition> coll) {
1227
1228 if (coll == null) {
1229 return null;
1230 }
1231 TreeMap<String, AbstractManagedObjectDefinition> map =
1232 new TreeMap<String, AbstractManagedObjectDefinition>();
1233 for (AbstractManagedObjectDefinition mo : coll) {
1234 map.put(mo.getName(), mo);
1235 }
1236 return map;
1237 }
1238
1239 private TreeMap<String, RelationDefinition> makeRelTreeMap(
1240 Collection<RelationDefinition> coll) {
1241
1242 if (coll == null) {
1243 return null;
1244 }
1245 TreeMap<String, RelationDefinition> map =
1246 new TreeMap<String, RelationDefinition>();
1247 for (RelationDefinition rel : coll) {
1248 map.put(rel.getChildDefinition().getName(), rel);
1249 }
1250 return map;
1251 }
1252
1253 private TreeMap<String, PropertyDefinition> makePropTreeMap(
1254 Collection<PropertyDefinition> coll) {
1255
1256 if (coll == null) {
1257 return null;
1258 }
1259 TreeMap<String, PropertyDefinition> map =
1260 new TreeMap<String, PropertyDefinition>();
1261 for (PropertyDefinition prop : coll) {
1262 map.put(prop.getName(), prop);
1263 }
1264 return map;
1265 }
1266
1267 private void horizontalLine() {
1268 htmlBuff.append("<hr style=\"width: 100%; height: 2px;\">");
1269 }
1270
1271 private void endTable() {
1272 htmlBuff.append("</tbody>\n");
1273 htmlBuff.append("</table>\n");
1274 }
1275
1276 private void bullet(String str) {
1277 htmlBuff.append(
1278 "<li>" +
1279 str +
1280 "</li>\n");
1281 }
1282
1283 private void heading2(String string) {
1284 heading(string, 2);
1285 }
1286
1287 private void heading3(String string) {
1288 heading(string, 3);
1289 }
1290
1291 private void heading4(String string) {
1292 heading(string, 4);
1293 }
1294
1295 private void heading(String str, int level) {
1296 htmlBuff.append(getHeading(str, level));
1297 }
1298
1299 private String getHeading(String str, int level) {
1300 String strLevel = (new Integer(level)).toString();
1301 return "<h" + strLevel + ">" +
1302 "<a name=\"" + str + "\"></a>" +
1303 str +
1304 "</h" + strLevel + ">\n";
1305 }
1306
1307 private String getHeading2(String str) {
1308 return getHeading(str, 2);
1309 }
1310
1311 private String getAnchor(String str) {
1312 return "<a name=\"" + str + "\"></a>";
1313 }
1314
1315 private void htmlHeader(String pageTitle) {
1316 htmlBuff.append(getHtmlHeader(pageTitle) +
1317 "<body>\n");
1318
1319 }
1320
1321 private String getHtmlHeader(String pageTitle) {
1322 return ("<html>\n" +
1323 "<head>\n" +
1324 "<meta http-equiv=\"content-type\"\n" +
1325 "content=\"text/html; charset=ISO-8859-1\">\n" +
1326 "<title>" + pageTitle + "</title>\n" +
1327 "<link rel=\"stylesheet\" type=\"text/css\"\n" +
1328 "href=\"" + CSS_FILE + "\">\n" +
1329 "</head>\n");
1330 }
1331
1332 // Add a Tab Menu, the active tab is the one given as parameter
1333 private void tabMenu(String activeTab) {
1334 htmlBuff.append(
1335 "<div class=\"tabmenu\"> " +
1336
1337 "<span><a " +
1338 (activeTab.equals(INHERITANCE_TREE_FILE) ? "class=\"activetab\" " : "") +
1339 "href=\"" + INHERITANCE_TREE_FILE + "\"" +
1340 " title=\"Inheritance View of Components\">Inheritance</a></span> " +
1341
1342 "<span><a " +
1343 (activeTab.equals(RELATION_TREE_FILE) ? "class=\"activetab\" " : "") +
1344 "href=\"" + RELATION_TREE_FILE + "\"" +
1345 " title=\"Relational View of Components\">Structure</a></span> " +
1346
1347 "<span><a " +
1348 (activeTab.equals(MO_LIST_FILE) ? "class=\"activetab\" " : "") +
1349 "href=\"" + MO_LIST_FILE + "\"" +
1350 " title=\"Alphabetical Index of Components\">Components</a></span> " +
1351
1352 "<span><a " +
1353 (activeTab.equals(PROPERTIES_INDEX_FILE) ? "class=\"activetab\" " : "") +
1354 "href=\"" + PROPERTIES_INDEX_FILE + "\"" +
1355 " title=\"Alphabetical Index of Properties\" >Properties</a></span>" +
1356
1357 "</div>" +
1358 "\n"
1359 );
1360 }
1361
1362 private String getLink(String str, String link) {
1363 return getLink(str, link, null, null);
1364 }
1365
1366 private String getLink(String str, String link, String target) {
1367 return getLink(str, link, target, null);
1368 }
1369
1370 private String getLink(String str, String link, String target, String color) {
1371 return "<a " +
1372 (color != null ? "style=\"color:" + color + "\" " : "") +
1373 "href=\"" + link + "\"" +
1374 (target == null ? "" : " target=\"" + target + "\"") +
1375 ">"
1376 + str + "</a>";
1377 }
1378
1379 private void link(String str, String link) {
1380 link(str, link, null, null);
1381 }
1382
1383 private void link(String str, String link, String target) {
1384 link(str, link, target, null);
1385 }
1386
1387 private void link(String str, String link, String target, String color) {
1388 String htmlStr = "";
1389 if (!inList && getIndentPixels() > 0) {
1390 htmlStr += "<div style=\"margin-left: " + getIndentPixels() + "px;\">";
1391 } else if (inList) {
1392 htmlStr += "<li>";
1393 }
1394 htmlStr += getLink(str, link, target, color);
1395 if (!inList && getIndentPixels() > 0) {
1396 htmlStr += "</div>";
1397 } else if (inList) {
1398 htmlStr += "</li>";
1399 }
1400 if (!inList) {
1401 htmlStr += "<br>";
1402 }
1403 htmlBuff.append(htmlStr + "\n");
1404 }
1405
1406 private void newline() {
1407 htmlBuff.append(
1408 getNewLine());
1409 }
1410
1411 private String getNewLine() {
1412 return "<br>\n";
1413 }
1414
1415 private void paragraph(Message description) {
1416 if (description != null) {
1417 paragraph(description.toString());
1418 }
1419 }
1420
1421 private void paragraph(Message description, TextStyle style) {
1422 if (description != null) {
1423 paragraph(description.toString(), style, null);
1424 }
1425 }
1426
1427 private void paragraph(String description) {
1428 paragraph(description, TextStyle.STANDARD, null);
1429 }
1430
1431 private void paragraph(String description, TextStyle style) {
1432 paragraph(description, style, null);
1433 }
1434
1435 private void paragraph(String description, TextStyle style, String pClass) {
1436 String indentStr = "";
1437 String styleStr = "";
1438 String classStr = "";
1439 if (getIndentPixels() > 0) {
1440 indentStr = "style=\"margin-left: " + getIndentPixels() + "px;\"";
1441 }
1442 if (style == style.BOLD) {
1443 styleStr = "style=\"font-weight: bold;\"";
1444 } else if (style == style.ITALIC) {
1445 styleStr = "style=\"font-style: italic;\"";
1446 }
1447 if (pClass != null) {
1448 classStr = "class=" + pClass;
1449 }
1450
1451 htmlBuff.append(
1452 "<p " +
1453 indentStr + " " +
1454 styleStr + " " +
1455 classStr +
1456 ">" +
1457 description +
1458 "</p>\n");
1459 }
1460
1461 private int getIndentPixels() {
1462 return (ind * 40);
1463 }
1464
1465 private void startTable() {
1466 htmlBuff.append(
1467 "<table " +
1468 "style=\"width: 100%; text-align: left;\"" +
1469 "border=\"1\"" +
1470 "cellpadding=\"1\"" +
1471 "cellspacing=\"0\"" +
1472 ">\n");
1473
1474 htmlBuff.append("<tbody>\n");
1475 }
1476
1477 /*
1478 * Generate a "friendly" name from a string :
1479 * '-' and '_' replaced by space
1480 * first letter of a word in uppercase
1481 */
1482 private String getFriendlyName(String str) {
1483 String retStr = "";
1484 String[] words = str.split("\\p{Punct}");
1485 for (int ii = 0; ii < words.length; ii++) {
1486 if (ii>0) {
1487 retStr += " ";
1488 }
1489 String word = words[ii];
1490 String firstChar = word.substring(0, 1).toUpperCase();
1491 retStr += firstChar + word.substring(1, word.length());
1492 }
1493 return retStr;
1494 }
1495
1496 private void tableRow(String... strings) {
1497 htmlBuff.append(
1498 "<tr>\n");
1499 for (int ii = 0; ii < strings.length; ii++) {
1500 String string = strings[ii];
1501 htmlBuff.append(
1502 "<td style=\"" +
1503 "vertical-align: top; " +
1504 ((ii == 0) ? "width: 20%;" : "") +
1505 "\">" +
1506 string +
1507 "<br></td>");
1508 }
1509 htmlBuff.append(
1510 "</tr>\n");
1511 }
1512
1513 /**
1514 * Text style.
1515 */
1516 private enum TextStyle {
1517
1518 STANDARD, BOLD, ITALIC, UNDERLINE, FIXED_WIDTH
1519 }
1520
1521 /**
1522 * List style.
1523 */
1524 private enum ListStyle {
1525
1526 STANDARD, BULLET, NUMBER
1527 }
1528
1529 private void indent() {
1530 ind++;
1531 }
1532
1533 private void outdent() {
1534 ind--;
1535 }
1536
1537 private void beginList() {
1538 inList = true;
1539 listLevel++;
1540 htmlBuff.append(
1541 "<ul>\n");
1542 }
1543
1544 private void endList() {
1545 listLevel--;
1546 if (listLevel == 0) {
1547 inList = false;
1548 }
1549 htmlBuff.append(
1550 "</ul>\n");
1551 }
1552
1553 private void htmlFooter() {
1554 htmlBuff.append(
1555 "</body>\n" +
1556 "</html>\n");
1557 }
1558
1559 private static void usage() {
1560 System.err.println(
1561 "Usage : Provide the argument : output generation directory.");
1562 System.exit(1);
1563 }
1564
1565 private void viewHelp(String helpStr) {
1566 htmlBuff.append(
1567 "<p class=\"view-help\" >" +
1568 helpStr +
1569 "</p>" +
1570 "\n"
1571 );
1572 }
1573
1574 private void generateFile(String fileName) {
1575 // Write the html buffer in a file
1576 try {
1577 PrintWriter file = new java.io.PrintWriter(
1578 new java.io.FileWriter(generationDir + File.separator + fileName));
1579 file.write(htmlBuff.toString());
1580 file.close();
1581 } catch (Exception e) {
1582 e.printStackTrace();
1583 System.exit(1);
1584 }
1585 // re-init html buffer
1586 htmlBuff = new StringBuffer();
1587 }
1588
1589 // Relation List from RootConfiguration
1590 private TreeMap<String, RelationDefinition> topRelList =
1591 new TreeMap<String, RelationDefinition>();
1592 private TreeMap<String, RelationDefinition> relList =
1593 new TreeMap<String, RelationDefinition>();
1594 private TreeMap<String, TreeMap<String, RelationDefinition>> catTopRelList =
1595 new TreeMap<String, TreeMap<String, RelationDefinition>>();
1596 // managed object list
1597 private TreeMap<String, AbstractManagedObjectDefinition> moList =
1598 new TreeMap<String, AbstractManagedObjectDefinition>();
1599 private TreeMap<String, AbstractManagedObjectDefinition> topMoList =
1600 new TreeMap<String, AbstractManagedObjectDefinition>();
1601 private TreeMap<String, TreeMap<String, AbstractManagedObjectDefinition>>
1602 catTopMoList =
1603 new TreeMap<String, TreeMap<String, AbstractManagedObjectDefinition>>();
1604 private int ind = 0;
1605 private StringBuffer htmlBuff = new StringBuffer();
1606 private static String generationDir;
1607 private static boolean ldapMapping = false;
1608 private static String opendsWiki;
1609 private static String opendsHome;
1610 private static String aciSyntaxPage;
1611 private static String durationSyntaxPage;
1612 private boolean inList = false;
1613 private int listLevel = 0;
1614 }