From f16a87f10d5c028aa2614dedc833b9c780fbe5f0 Mon Sep 17 00:00:00 2001
From: jcambon <jcambon@localhost>
Date: Thu, 17 Jan 2008 09:59:46 +0000
Subject: [PATCH] This is a new feature : automatically generate HTML configuration guide (issue #2004)
---
opendj-sdk/opends/build.xml | 24 +
opendj-sdk/opends/resource/config/opends-config.css | 92 ++++
opendj-sdk/opends/src/server/org/opends/server/admin/doc/ConfigGuideGeneration.java | 1037 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1,150 insertions(+), 3 deletions(-)
diff --git a/opendj-sdk/opends/build.xml b/opendj-sdk/opends/build.xml
index 8226932..8e4f4bb 100644
--- a/opendj-sdk/opends/build.xml
+++ b/opendj-sdk/opends/build.xml
@@ -42,6 +42,8 @@
<property name="ext.dir" location="ext" />
<property name="package.dir" location="${build.dir}/package" />
<property name="javadoc.dir" location="${build.dir}/javadoc" />
+ <property name="docgen.dir" location="${build.dir}/docgen" />
+ <property name="configguide.dir" location="${docgen.dir}/configuration_guide" />
<property name="resource.dir" location="resource" />
<property name="scripts.dir" location="${resource.dir}/bin" />
<property name="config.dir" location="${resource.dir}/config" />
@@ -157,7 +159,7 @@
<!-- The build target that should be used for nightly builds. -->
<target name="nightly"
- depends="checkstyle,dsml,srczip,javadoc,coverage,testallwithcoverage"
+ depends="checkstyle,dsml,srczip,javadoc,docgen,coverage,testallwithcoverage"
description="Perform all processing needed for nightly builds.">
</target>
@@ -174,7 +176,7 @@
<!-- The build target that should be used to build everything. -->
<target name="all"
- depends="checkstyle,clean,checkprecommit,dsml,srczip,javadoc,testallwithcoverage"
+ depends="checkstyle,clean,checkprecommit,dsml,srczip,javadoc,docgen,testallwithcoverage"
description="Build using all defined targets.">
</target>
@@ -758,7 +760,23 @@
</target>
-
+ <!-- Generate the Configuration guide. -->
+ <target name="docgen" depends="compile,copymessages"
+ description="Generate the Configuration guide (html).">
+ <mkdir dir="${configguide.dir}" />
+ <!-- copy the stylesheet file -->
+ <copy todir="${configguide.dir}"
+ file="${config.dir}/opends-config.css" />
+ <java fork="true" classname="org.opends.server.admin.doc.ConfigGuideGeneration" failonerror="true">
+ <classpath>
+ <fileset dir="${lib.dir}">
+ <include name="*.jar" />
+ </fileset>
+ <dirset dir="${classes.dir}" />
+ </classpath>
+ <arg value="${configguide.dir}"/>
+ </java>
+ </target>
<!-- Populate the Directory Server package, but don't zip it up. -->
<target name="prepackage" depends="cleancompile"
diff --git a/opendj-sdk/opends/resource/config/opends-config.css b/opendj-sdk/opends/resource/config/opends-config.css
new file mode 100644
index 0000000..3a50069
--- /dev/null
+++ b/opendj-sdk/opends/resource/config/opends-config.css
@@ -0,0 +1,92 @@
+
+body { font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ color: #333; background-color: #fff; margin:20px }
+
+/* +++ 210 Page titles, headings, and paragraphs +++ */
+.pagename { font-size: 1.7em; font-weight: normal;color:#5F6466;
+ margin: 0.5em 0.5em 0.5em 0; }
+h1 { font-size: 2.0em; font-weight: normal;
+ margin-top: 0em; margin-bottom: 0em; }
+h2 { font-size: 1.7em; font-weight: normal;
+ margin: 2.1em 0em 1em 0em;
+
+ border-bottom: 1px #D9D9D9 solid; padding-bottom:5px }
+h3 { font-size: 1.4em; font-weight: bold;
+ margin: 1.2em 0em .8em 0em; }
+h4 { font-size: 1.2em; font-weight: bold;
+ margin: 1.2em 0em .8em 0em; }
+h5 { font-size: 1.0em; font-weight: bold;
+ margin: 1.2em 0em .8em 0em; }
+h6 { font-size: 0.8em; font-weight: bold;
+ margin: 1.2em 0em .8em 0em; }
+p { margin: .75em 0 1em 0; }
+strong, b { font-weight: bold; }
+
+a { color: #006699; }
+
+
+ol { margin: 0.8em 0 0.8em 0.8em }
+ul { margin: 0.8em 0.2em }
+li { margin: 0.6em 0.1em}
+li > p { margin-top: 0.2em }
+ol { list-style-type:decimal }
+ol ol { list-style-type:lower-alpha }
+ol ol ol { list-style-type:lower-roman }
+ol ol ol ol { list-style-type:decimal }
+ol ol ol ol ol { list-style-type:lower-alpha }
+ol ol ol ol ol ol { list-style-type:lower-roman }
+ul ol { list-style-type:decimal }
+ul ol ol { list-style-type:lower-alpha }
+ul ol ol ol { list-style-type:lower-roman }
+ul ol ol ol ol { list-style-type:decimal }
+ul ol ol ol ol ol { list-style-type:lower-alpha }
+ul ol ol ol ol ol ol { list-style-type:lower-roman }
+ul { list-style:square }
+
+dl {margin-top:10px}
+dl dt { font-weight: bold;margin-bottom:3px }
+dl dd { margin-left: 10px; }
+
+
+.tabmenu { margin: 0; margin-left: -10px;padding: 0.25em 0 0.25em 1em;
+ border-bottom: 1px solid #8f989f;margin-bottom:20px }
+.tabmenu span { margin: 0; padding: 0; overflow: hidden; }
+.tabmenu span a { color: #1A1A1A; background: #eee;
+ margin: 0 0 0 -4px; padding: 4px 9px 3px;
+ text-decoration: none; cursor: pointer;
+ border: 1px solid gray; border-bottom:none;background-image:url(tab_deselected.jpg); }
+.tabmenu span a:hover {text-decoration:underline; }
+
+.tabmenu .activetab { color: #1A1A1A;
+ font-weight: normal;
+ background-image:url(tab_selected.gif);background-color: #fff; cursor: default; border-bottom: 1px solid #fff; }
+
+
+
+
+table { border:none;border-bottom:dotted 1px #ccc;margin: 0px 0px 20px;font-size: 12px;}
+table tr th { border:none;border-top: dotted 1px #ccc;padding:5px 10px;background-color:#f5f5f5;font-weight:bold;text-align:left;vertical-align:bottom;
+ empty-cells: show;font-size: 12px; }
+table tr td { border:none;border-top: dotted 1px #ccc;padding:4px 10px;vertical-align:top;
+ empty-cells: show;font-size: 12px; }
+
+.breadcrumb { background-color:#f5f5f5; color:#f5994f; position:absolute;top:0;left:0;width:100%; padding:6px 15px;font-weight:normal;border-bottom:dotted 1px #ccc; }
+/*.breadcrumb a {color: #f5994f} */
+.pageactions a { background-color: #f5f5f5;
+ font-size:10px;
+ border: 1px solid #999;
+ background-image:url(pageaction.gif);
+ text-decoration:none;
+ line-height: normal; padding: 0.25em 0.5em;
+ color:#333;
+ }
+
+
+/*.titletable {border-top:none;border-bottom: 1px #D9D9D9 solid;margin-bottom:20px } */
+.titletable {border:none;margin-bottom:5px;margin-top:10px }
+.titletable h2 {border:none; margin-bottom: .4em; margin-top:.8em }
+.titletable td { vertical-align:middle; border-top:none;padding-left:0px }
+.propertyname {font-size: 14px; font-weight: bold;padding:3px 0px 3px 10px;margin: 0px;border-top: dotted 1px #ccc;background-color:#f5f5f5; }
+
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/doc/ConfigGuideGeneration.java b/opendj-sdk/opends/src/server/org/opends/server/admin/doc/ConfigGuideGeneration.java
new file mode 100644
index 0000000..a02642a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/doc/ConfigGuideGeneration.java
@@ -0,0 +1,1037 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.doc;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import org.opends.messages.Message;
+import org.opends.server.admin.ACIPropertyDefinition;
+import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
+import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AdministratorAction.Type;
+import org.opends.server.admin.AggregationPropertyDefinition;
+import org.opends.server.admin.AliasDefaultBehaviorProvider;
+import org.opends.server.admin.AttributeTypePropertyDefinition;
+import org.opends.server.admin.BooleanPropertyDefinition;
+import org.opends.server.admin.ClassLoaderProvider;
+import org.opends.server.admin.ClassPropertyDefinition;
+import org.opends.server.admin.DNPropertyDefinition;
+import org.opends.server.admin.DefaultBehaviorProvider;
+import org.opends.server.admin.DefinedDefaultBehaviorProvider;
+import org.opends.server.admin.DurationPropertyDefinition;
+import org.opends.server.admin.EnumPropertyDefinition;
+import org.opends.server.admin.IPAddressMaskPropertyDefinition;
+import org.opends.server.admin.IPAddressPropertyDefinition;
+import org.opends.server.admin.IntegerPropertyDefinition;
+import org.opends.server.admin.LDAPProfile;
+import org.opends.server.admin.PropertyDefinition;
+import org.opends.server.admin.PropertyDefinitionVisitor;
+import org.opends.server.admin.PropertyOption;
+import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
+import org.opends.server.admin.SizePropertyDefinition;
+import org.opends.server.admin.StringPropertyDefinition;
+import org.opends.server.admin.TopCfgDefn;
+import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
+import org.opends.server.admin.std.meta.RootCfgDefn;
+import org.opends.server.types.InitializationException;
+import org.opends.server.util.EmbeddedUtils;
+
+/**
+ * This class allow Configuration Guide documentation generation (html format).
+ * It is based on the Admin Framework Introspection API
+ *
+ */
+public class ConfigGuideGeneration {
+
+ // Note : still to be done :
+ // I18n support. Today all the strings are hardcoded in this file
+
+ private final String OPENDS_WIKI = "https://www.opends.org/wiki";
+ private final String ACI_SYNTAX_PAGE = OPENDS_WIKI + "/page/ACISyntax";
+ private final String CSS_FILE = "opends-config.css";
+
+ /**
+ * Entry point for documentation generation.
+ *
+ * @param args The output generation directory (optional)
+ */
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ // Default dir is prefixed by the system-dependent default temporary dir
+ generationDir = System.getProperty("java.io.tmpdir") + File.separator +
+ "opends_config_guide";
+ } else if ((args.length != 1) || !(new File(args[0])).isDirectory()) {
+ usage();
+ } else {
+ generationDir = args[0];
+ }
+ // Create new dir if necessary
+ try {
+ (new File(generationDir)).mkdir();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ System.out.println("Generation directory is : " + generationDir);
+ ConfigGuideGeneration myGen = new ConfigGuideGeneration();
+ myGen.generate();
+ }
+
+ private void generate() {
+ init();
+
+ // Generate the inheritance tree of all the managed objects
+ genManagedObjectInheritanceTree(topMoList);
+
+ // Generate the relation tree of all the managed objects
+ genManagedObjectRelationTree(topRelList);
+
+ // Generate all the managed objects and their children
+ genAllManagedObject(topMoList);
+
+ // Generate a list of managed objects
+ genManagedObjectList(moList);
+
+ // Generate an index of properties
+ genPropertiesIndex();
+ }
+
+ private void init() {
+
+ // Build a list of top relations
+ RootCfgDefn rootCfg = RootCfgDefn.getInstance();
+ for (RelationDefinition rel : rootCfg.getAllRelationDefinitions()) {
+ topRelList.put(rel.getChildDefinition().getName(), rel);
+ }
+
+ // Enable the client-side class loader to explicitly load classes
+ // which are not directly reachable from the root configuration
+ EmbeddedUtils.initializeForClientUse();
+ // Bootstrap definition classes.
+ try {
+ ClassLoaderProvider.getInstance().enable();
+ } catch (InitializationException e) {
+ System.err.println("ERROR : Cannot enable the client-side class loader.");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ // Switch off class name validation in client.
+ ClassPropertyDefinition.setAllowClassValidation(false);
+ // Switch off attribute type name validation in client.
+ AttributeTypePropertyDefinition.setCheckSchema(false);
+
+ // Build a sorted list of top managed objects
+ TopCfgDefn topCfg = TopCfgDefn.getInstance();
+ Collection<AbstractManagedObjectDefinition<?, ?>> topObjects =
+ topCfg.getChildren();
+ for (AbstractManagedObjectDefinition topObject : topObjects) {
+ if (topObject.getName().equals("")) {
+ // root
+ continue;
+ }
+ topMoList.put(topObject.getName(), topObject);
+ }
+
+ }
+
+ /**
+ * Generate the inheritance tree of all the managed objects.
+ */
+ private void genManagedObjectInheritanceTree(
+ TreeMap<String, AbstractManagedObjectDefinition> list) {
+
+ htmlHeader("OpenDS - Configuring Specific Server Components - " +
+ "Inheritance tree");
+ heading2("Configuring Specific Server Components - Inheritance tree");
+ genMoInheritanceTree(list);
+ generateFile("ManagedObjectInheritanceTree.html");
+ }
+
+ @SuppressWarnings("unchecked")
+ private void genMoInheritanceTree(
+ TreeMap<String, AbstractManagedObjectDefinition> list) {
+
+ beginList();
+ for (AbstractManagedObjectDefinition mo : list.values()) {
+ if (listLevel == 1) {
+ paragraph(
+ getLink(mo.getUserFriendlyPluralName().toString(),
+ mo.getName() + ".html"));
+ } else {
+ link(mo.getUserFriendlyName().toString(), mo.getName() + ".html");
+ }
+ if (mo.hasChildren()) {
+ genMoInheritanceTree(makeMOTreeMap(mo.getChildren()));
+ }
+ }
+ endList();
+ if (listLevel == 1) {
+ newline();
+ }
+ }
+
+ /**
+ * Generate the relation tree of all the managed objects.
+ */
+ private void genManagedObjectRelationTree(
+ TreeMap<String, RelationDefinition> list) {
+
+ htmlHeader("OpenDS - Configuring Specific Server Components - " +
+ "Containment tree");
+ heading2("Configuring Specific Server Components - Containment tree");
+ paragraph(
+ "This tree represents the composition relation between components. " +
+ "This means that a child component is deleted " +
+ "when its parent is deleted.");
+ genMORelationTree(list);
+ generateFile("ManagedObjectRelationTree.html");
+ }
+
+ @SuppressWarnings("unchecked")
+ private void genMORelationTree(TreeMap<String, RelationDefinition> subList) {
+ if (!subList.values().isEmpty()) {
+ beginList();
+ for (RelationDefinition rel : subList.values()) {
+ AbstractManagedObjectDefinition childMo = rel.getChildDefinition();
+ AbstractManagedObjectDefinition parentMo = rel.getParentDefinition();
+ relList.put(childMo.getName(), rel);
+ String linkStr = getLink(childMo.getUserFriendlyName().toString(),
+ childMo.getName() + ".html");
+ String fromStr = "";
+ if (!parentMo.getName().equals("")) {
+ fromStr = " (from " +
+ getLink(parentMo.getUserFriendlyName().toString(),
+ parentMo.getName() + ".html") + ")";
+ }
+ bullet(linkStr + fromStr);
+ genMORelationTree(makeRelTreeMap(childMo.getAllRelationDefinitions()));
+ if (childMo.hasChildren()) {
+ for (Iterator<AbstractManagedObjectDefinition> it =
+ childMo.getChildren().iterator(); it.hasNext();) {
+
+ AbstractManagedObjectDefinition mo = it.next();
+ genMORelationTree(makeRelTreeMap(mo.getAllRelationDefinitions()));
+ }
+ }
+ if (listLevel == 1) {
+ newline();
+ }
+ }
+ endList();
+ }
+ }
+
+ /**
+ * Generate all the managed objects HTML pages.
+ */
+ @SuppressWarnings("unchecked")
+ private void genAllManagedObject(
+ TreeMap<String, AbstractManagedObjectDefinition> list) {
+
+ for (AbstractManagedObjectDefinition mo : list.values()) {
+ moList.put(mo.getName(), mo);
+ genManagedObject(mo);
+ if (mo.hasChildren()) {
+ genAllManagedObject(makeMOTreeMap(mo.getChildren()));
+ }
+ }
+ }
+
+ private void genManagedObject(AbstractManagedObjectDefinition mo) {
+ //------------------------------------------------------------------------
+ // Header
+ //------------------------------------------------------------------------
+
+ String title = "The " + mo.getUserFriendlyName() + " Configuration";
+ htmlHeader("OpenDS - " + title);
+
+ // title
+ heading2(title);
+
+ // description
+ paragraph(mo.getSynopsis());
+ paragraph(mo.getDescription());
+
+ newline();
+ horizontalLine();
+
+ // sub-components
+ if (mo.hasChildren()) {
+ heading4("Direct Subcomponents");
+ paragraph("The following " + mo.getUserFriendlyPluralName() +
+ " are available in the server :");
+ beginList();
+ @SuppressWarnings("unchecked")
+ TreeMap<String, AbstractManagedObjectDefinition> children =
+ makeMOTreeMap(mo.getChildren());
+ for ( AbstractManagedObjectDefinition child : children.values()) {
+ link(child.getUserFriendlyName().toString(), child.getName() + ".html");
+ }
+ endList();
+
+ paragraph("All the " + mo.getUserFriendlyPluralName() +
+ " inherit from the properties described below.");
+ }
+
+ // Parent
+ if (!mo.getParent().isTop()) {
+ heading4("Parent Component");
+ paragraph("The " + mo.getUserFriendlyName() + " component inherits from "
+ + getLink(mo.getParent().getUserFriendlyName().toString(),
+ mo.getParent().getName() + ".html"));
+ }
+
+ // Relations
+ if (!mo.getRelationDefinitions().isEmpty()) {
+ heading4("Relations From this Component");
+ paragraph(
+ "The following components have a direct composition relation FROM " +
+ mo.getUserFriendlyPluralName() + " :");
+ @SuppressWarnings("unchecked")
+ Collection<RelationDefinition> rels = mo.getRelationDefinitions();
+ for ( RelationDefinition rel : rels) {
+ beginList();
+ AbstractManagedObjectDefinition childRel = rel.getChildDefinition();
+ link(childRel.getUserFriendlyName().toString(), childRel.getName() +
+ ".html");
+ endList();
+ }
+ }
+ if (!mo.getReverseRelationDefinitions().isEmpty()) {
+ boolean isRoot = false;
+ @SuppressWarnings("unchecked")
+ Collection<RelationDefinition> rels = mo.getReverseRelationDefinitions();
+ for ( RelationDefinition rel : rels) {
+ // only check if it is not root
+ if (rel.getParentDefinition().getName().equals("")) {
+ isRoot = true;
+ }
+ }
+ if (!isRoot) {
+ heading4("Relations To this Component");
+ paragraph(
+ "The following components have a direct composition relation TO " +
+ mo.getUserFriendlyPluralName() + " :");
+ for ( RelationDefinition rel : rels) {
+ beginList();
+ AbstractManagedObjectDefinition childRel = rel.getParentDefinition();
+ link(childRel.getUserFriendlyName().toString(), childRel.getName() +
+ ".html");
+ endList();
+ }
+ }
+ }
+
+ newline();
+ horizontalLine();
+ newline();
+
+ // Page links
+ paragraph("This page describes the " + mo.getUserFriendlyName() + ":");
+ beginList();
+ link("Properties", "#Properties");
+ link("LDAP Mapping", "#LDAP Mapping");
+ endList();
+ newline();
+
+
+ //------------------------------------------------------------------------
+ // Properties
+ //------------------------------------------------------------------------
+
+ heading3("Properties");
+
+ paragraph(mo.getUserFriendlyPluralName() +
+ " contain the following properties:");
+ newline();
+
+ // Properties actually defined in this managed object
+ @SuppressWarnings("unchecked")
+ Collection<PropertyDefinition> props = mo.getAllPropertyDefinitions();
+ TreeMap<String, PropertyDefinition> propList = makePropTreeMap(props);
+ for ( PropertyDefinition prop : propList.values()) {
+ generateProperty(mo, prop);
+ newline();
+ }
+
+ newline();
+
+ //------------------------------------------------------------------------
+ // LDAP mapping
+ //------------------------------------------------------------------------
+
+ heading3("LDAP Mapping");
+ paragraph(
+ "Each dscfg configuration property can be mapped to a specific " +
+ "LDAP attribute under the \"cn=config\" entry. " +
+ "The mappings that follow are provided for information only. " +
+ "In general, you should avoid changing the server configuration " +
+ "by manipulating the LDAP attributes directly.");
+
+ // Managed object table
+ startTable();
+
+ LDAPProfile ldapProfile = LDAPProfile.getInstance();
+ tableRow("Base DN", getBaseDN(mo, ldapProfile));
+
+ tableRow("objectclass name", ldapProfile.getObjectClass(mo));
+ if (mo.getParent().getName() != null) {
+ String superior = "";
+ if (mo.getParent().getName().equals("top")) {
+ superior = "top";
+ } else {
+ if (moList.get(mo.getParent().getName()) != null) {
+ superior =
+ ldapProfile.getObjectClass(moList.get(mo.getParent().getName()));
+ } else {
+ System.err.println(
+ "Error: managed object " + mo.getName() + " not found.");
+ }
+ }
+ tableRow("objectclass superior", superior);
+ } else {
+ System.err.println(
+ "Error: objectclass superior not found for " + mo.getName());
+ }
+ endTable();
+
+ newline();
+ // Properties table
+ startTable();
+ tableRow("Property", "LDAP attribute");
+ for ( PropertyDefinition prop : propList.values()) {
+ tableRow(prop.getName(), ldapProfile.getAttributeName(mo, prop));
+ }
+
+ endTable();
+
+ htmlFooter();
+
+ generateFile(mo.getName() + ".html");
+ }
+
+ private void generateProperty(
+ AbstractManagedObjectDefinition mo, PropertyDefinition prop) {
+
+ // Property name
+ paragraph(getAnchor(prop.getName()) + prop.getName(), TextStyle.BOLD);
+
+ // Property table
+ startTable();
+ tableRow("Description",
+ ((prop.getSynopsis() != null) ? prop.getSynopsis().toString() : "") +
+ ((prop.getDescription() != null) ?
+ prop.getDescription().toString() : ""));
+
+ // Default value
+ String defValueStr = getDefaultBehaviorString(prop);
+ tableRow("Default Value", defValueStr);
+
+ tableRow("Allowed Values", getSyntaxStr(prop));
+
+ tableRow("Multi-valued",
+ (prop.hasOption(PropertyOption.MULTI_VALUED) ? "Yes" : "No"));
+
+ if (prop.hasOption(PropertyOption.MANDATORY)) {
+ tableRow("Required", "Yes");
+ }
+
+ if (prop.getAdministratorAction() != null) {
+ Message synopsis = prop.getAdministratorAction().getSynopsis();
+ Type actionType = prop.getAdministratorAction().getType();
+ String actionStr = "";
+ if (actionType == actionType.COMPONENT_RESTART) {
+ actionStr = "The " + mo.getUserFriendlyName() +
+ " must be disabled and re-enabled for changes to this setting " +
+ "to take effect";
+ } else if (actionType == actionType.SERVER_RESTART) {
+ actionStr = "Restart the server";
+ } else if (actionType == actionType.NONE) {
+ actionStr = "None";
+ }
+ String action = actionStr +
+ ((synopsis != null) ? ". " + synopsis : "");
+ tableRow("Admin Action Required", action);
+ }
+
+
+ if (prop.hasOption(PropertyOption.ADVANCED)) {
+ tableRow("Advanced Property", "Yes");
+ }
+
+ endTable();
+
+ }
+
+ private void genManagedObjectList(
+ TreeMap<String, AbstractManagedObjectDefinition> list) {
+
+ htmlHeader("Component List");
+ for (AbstractManagedObjectDefinition mo : list.values()) {
+ link(mo.getUserFriendlyName().toString(), mo.getName() + ".html");
+ }
+ htmlFooter();
+ generateFile("ManagedObjectList.html");
+ }
+
+ private void genPropertiesIndex() {
+
+ // Build a sorted list of (property name + its managed object name)
+ TreeSet<String> propMoList = new TreeSet<String>();
+ for (AbstractManagedObjectDefinition<?, ?> mo : moList.values()) {
+ for (PropertyDefinition<?> prop : mo.getPropertyDefinitions()) {
+ propMoList.add(
+ prop.getName() + "," + prop.getManagedObjectDefinition().getName());
+ }
+ }
+
+ String lettersPointers = "";
+ String firstChar = ".";
+ for (String propMoStr : propMoList) {
+ String[] propMoArray = propMoStr.split(",");
+ String propName = propMoArray[0];
+ AbstractManagedObjectDefinition mo = moList.get(propMoArray[1]);
+ if (!propName.startsWith(firstChar)) {
+ firstChar = propName.substring(0, 1);
+ String letter = firstChar.toUpperCase();
+ htmlBuff.append(getAnchor(letter) + getHeading2(letter));
+ lettersPointers += getLink(letter, "#" + letter) + " ";
+ }
+ String propLink = getLink(propName,
+ mo.getName() + ".html" + "#" + propName);
+ String moLink =
+ getLink(mo.getUserFriendlyName().toString(), mo.getName() + ".html");
+ paragraph(propLink + " (" + moLink + ")");
+ }
+
+ String indexBody = htmlBuff.toString();
+ htmlBuff = new StringBuffer();
+ htmlHeader("Properties Index");
+ paragraph(lettersPointers);
+ htmlBuff.append(indexBody);
+ htmlFooter();
+ generateFile("PropertiesIndex.html");
+ }
+
+ private String getBaseDN(
+ AbstractManagedObjectDefinition mo, LDAPProfile ldapProfile) {
+
+ if (relList.get(mo.getName()) != null) {
+ return ldapProfile.getRelationRDNSequence(relList.get(mo.getName()));
+ } else if (moList.get(mo.getParent().getName()) != null) {
+ // check its superior
+ return getBaseDN(moList.get(mo.getParent().getName()), ldapProfile);
+ } else {
+ System.err.println("Error: Base DN not found for " + mo.getName());
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getSyntaxStr(PropertyDefinition prop) {
+ // Create a visitor for performing syntax specific processing.
+ PropertyDefinitionVisitor<String, Void> visitor =
+ new PropertyDefinitionVisitor<String, Void>() {
+
+ @Override
+ public String visitACI(ACIPropertyDefinition prop, Void p) {
+ return getLink("An ACI Syntax", ACI_SYNTAX_PAGE);
+ }
+
+ @Override
+ public String visitAggregation(
+ AggregationPropertyDefinition prop, Void p) {
+
+ RelationDefinition rel = prop.getRelationDefinition();
+ String linkStr = getLink(rel.getUserFriendlyName().toString(),
+ rel.getName() + ".html");
+ return "The DN of any " + linkStr + ". " +
+ ((prop.getSourceConstraintSynopsis() != null) ?
+ prop.getSourceConstraintSynopsis().toString() : "");
+ }
+
+ @Override
+ public String visitAttributeType(
+ AttributeTypePropertyDefinition prop, Void p) {
+
+ return "The name of an attribute type defined in the server schema.";
+ }
+
+ @Override
+ public String visitBoolean(BooleanPropertyDefinition prop, Void p) {
+ return "true" + getNewLine() + "false";
+ }
+
+ @Override
+ public String visitClass(ClassPropertyDefinition prop, Void p) {
+ String classStr =
+ "A java class that implements or extends the class(es) :";
+ for (String clazz : prop.getInstanceOfInterface()) {
+ classStr += getNewLine() + clazz;
+ }
+ return classStr;
+ }
+
+ @Override
+ public String visitDN(DNPropertyDefinition prop, Void p) {
+ String retStr = "A valid DN.";
+ if (prop.getBaseDN() != null) {
+ retStr += prop.getBaseDN().toString();
+ }
+ return retStr;
+ }
+
+ @Override
+ public String visitDuration(DurationPropertyDefinition prop, Void p) {
+ String durationStr = "";
+
+ if (prop.isAllowUnlimited()) {
+ durationStr += "A value of \"-1\" or \"unlimited\" for no limit. ";
+ }
+ if (prop.getMaximumUnit() != null) {
+ durationStr += "Maximum unit is \"" +
+ prop.getMaximumUnit().getLongName() + "\". ";
+ }
+ long lowerLimitStr = new Double(prop.getBaseUnit().
+ fromMilliSeconds(prop.getLowerLimit())).longValue();
+ durationStr += "Lower limit is " + lowerLimitStr +
+ " " + prop.getBaseUnit().getLongName() + ". ";
+ if (prop.getUpperLimit() != null) {
+ long upperLimitStr = new Double(prop.getBaseUnit().
+ fromMilliSeconds(prop.getUpperLimit())).longValue();
+ durationStr += "Upper limit is " + upperLimitStr +
+ " " + prop.getBaseUnit().getLongName() + ". ";
+ }
+
+ return durationStr;
+ }
+
+ @Override
+ public String visitEnum(EnumPropertyDefinition prop, Void p) {
+ String enumStr = "";
+ Class en = prop.getEnumClass();
+ for (Object cst : en.getEnumConstants()) {
+ enumStr += cst.toString();
+ if (prop.getValueSynopsis((Enum) cst) != null) {
+ enumStr += " - " + prop.getValueSynopsis((Enum) cst).toString();
+ }
+ enumStr += getNewLine() + getNewLine();
+ }
+ return enumStr;
+ }
+
+ @Override
+ public String visitInteger(IntegerPropertyDefinition prop, Void p) {
+ String intStr = "An integer value.";
+ intStr += " Lower value is " + prop.getLowerLimit() + ".";
+ if (prop.getUpperLimit() != null) {
+ intStr += " Upper value is " + prop.getUpperLimit() + " .";
+ }
+ if (prop.isAllowUnlimited()) {
+ intStr += " A value of \"-1\" or \"unlimited\" for no limit.";
+ }
+ if (prop.getUnitSynopsis() != null) {
+ intStr += " Unit is " + prop.getUnitSynopsis() + ".";
+ }
+ return intStr;
+ }
+
+ @Override
+ public String visitIPAddress(IPAddressPropertyDefinition prop, Void p) {
+ return "An IP address";
+ }
+
+ @Override
+ public String visitIPAddressMask(
+ IPAddressMaskPropertyDefinition prop, Void p) {
+
+ return "An IP address mask";
+ }
+
+ @Override
+ public String visitSize(SizePropertyDefinition prop, Void p) {
+ String sizeStr = "A positive integer representing a size.";
+ if (prop.getLowerLimit() != 0) {
+ sizeStr += " Lower value is " + prop.getLowerLimit() + ".";
+ }
+ if (prop.getUpperLimit() != null) {
+ sizeStr += " Upper value is " + prop.getUpperLimit() + " .";
+ }
+ if (prop.isAllowUnlimited()) {
+ sizeStr += " A value of \"-1\" or \"unlimited\" for no limit.";
+ }
+ return sizeStr;
+ }
+
+ @Override
+ public String visitString(StringPropertyDefinition prop, Void p) {
+ return "A String";
+ }
+
+ @Override
+ public String visitUnknown(PropertyDefinition prop, Void p) {
+ return "Unknown";
+ }
+ };
+
+ // Invoke the visitor against the property definition.
+ return (String) prop.accept(visitor, null);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getDefaultBehaviorString(PropertyDefinition prop) {
+ DefaultBehaviorProvider defaultBehav = prop.getDefaultBehaviorProvider();
+ String defValueStr = "";
+ if (defaultBehav instanceof UndefinedDefaultBehaviorProvider) {
+ defValueStr = "None";
+ } else if (defaultBehav instanceof DefinedDefaultBehaviorProvider) {
+ DefinedDefaultBehaviorProvider defBehav =
+ (DefinedDefaultBehaviorProvider) defaultBehav;
+ for (Iterator<String> it = defBehav.getDefaultValues().iterator();
+ it.hasNext();) {
+
+ String str = it.next();
+ defValueStr += str + (it.hasNext() ? "\n" : "");
+ }
+ } else if (defaultBehav instanceof AliasDefaultBehaviorProvider) {
+ AliasDefaultBehaviorProvider aliasBehav = (
+ AliasDefaultBehaviorProvider) defaultBehav;
+ defValueStr = aliasBehav.getSynopsis().toString();
+ } else if
+ (defaultBehav instanceof RelativeInheritedDefaultBehaviorProvider) {
+ RelativeInheritedDefaultBehaviorProvider relativBehav =
+ (RelativeInheritedDefaultBehaviorProvider) defaultBehav;
+ defValueStr = getDefaultBehaviorString(
+ relativBehav.getManagedObjectDefinition().
+ getPropertyDefinition(relativBehav.getPropertyName()));
+ } else if
+ (defaultBehav instanceof AbsoluteInheritedDefaultBehaviorProvider) {
+ AbsoluteInheritedDefaultBehaviorProvider absoluteBehav =
+ (AbsoluteInheritedDefaultBehaviorProvider) defaultBehav;
+ defValueStr = getDefaultBehaviorString(
+ absoluteBehav.getManagedObjectDefinition().
+ getPropertyDefinition(absoluteBehav.getPropertyName()));
+ }
+ return defValueStr;
+ }
+
+ private TreeMap<String, AbstractManagedObjectDefinition> makeMOTreeMap(
+ Collection<AbstractManagedObjectDefinition> coll) {
+
+ if (coll == null) {
+ return null;
+ }
+ TreeMap<String, AbstractManagedObjectDefinition> map =
+ new TreeMap<String, AbstractManagedObjectDefinition>();
+ for (AbstractManagedObjectDefinition mo : coll) {
+ map.put(mo.getName(), mo);
+ }
+ return map;
+ }
+
+ private TreeMap<String, RelationDefinition> makeRelTreeMap(
+ Collection<RelationDefinition> coll) {
+
+ if (coll == null) {
+ return null;
+ }
+ TreeMap<String, RelationDefinition> map =
+ new TreeMap<String, RelationDefinition>();
+ for (RelationDefinition rel : coll) {
+ map.put(rel.getChildDefinition().getName(), rel);
+ }
+ return map;
+ }
+
+ private TreeMap<String, PropertyDefinition> makePropTreeMap(
+ Collection<PropertyDefinition> coll) {
+
+ if (coll == null) {
+ return null;
+ }
+ TreeMap<String, PropertyDefinition> map =
+ new TreeMap<String, PropertyDefinition>();
+ for (PropertyDefinition prop : coll) {
+ map.put(prop.getName(), prop);
+ }
+ return map;
+ }
+
+ private void horizontalLine() {
+ htmlBuff.append("<hr style=\"width: 100%; height: 2px;\">");
+ }
+
+ private void endTable() {
+ htmlBuff.append("</tbody>\n");
+ htmlBuff.append("</table>\n");
+ }
+
+ private void bullet(String str) {
+ htmlBuff.append(
+ "<li>" +
+ str +
+ "</li>\n");
+ }
+
+ private void heading2(String string) {
+ heading(string, 2);
+ }
+
+ private void heading3(String string) {
+ heading(string, 3);
+ }
+
+ private void heading4(String string) {
+ heading(string, 4);
+ }
+
+ private void heading(String str, int level) {
+ htmlBuff.append(getHeading(str, level));
+ }
+
+ private String getHeading(String str, int level) {
+ String strLevel = (new Integer(level)).toString();
+ return "<h" + strLevel + ">" +
+ "<a name=\"" + str + "\"></a>" +
+ str +
+ "</h" + strLevel + ">\n";
+ }
+
+ private String getHeading2(String str) {
+ return getHeading(str, 2);
+ }
+
+ private String getAnchor(String str) {
+ return "<a name=\"" + str + "\"></a>";
+ }
+
+ private void htmlHeader(String pageTitle) {
+ htmlBuff.append(getHtmlHeader(pageTitle) +
+ "<body style=\"color: rgb(0, 0, 0); " +
+ "background-color: rgb(255, 255, 255);\">\n");
+
+ }
+
+// private void htmlHeaderForFrames(String pageTitle) {
+// htmlBuff.append(getHtmlHeader(pageTitle));
+// }
+ private String getHtmlHeader(String pageTitle) {
+ return ("<html>\n" +
+ "<head>\n" +
+ "<meta http-equiv=\"content-type\"\n" +
+ "content=\"text/html; charset=ISO-8859-1\">\n" +
+ "<title>" + pageTitle + "</title>\n" +
+ "<link rel=\"stylesheet\" type=\"text/css\"\n" +
+ "href=\"" + CSS_FILE + "\">\n" +
+ "</head>\n");
+ }
+
+ private String getLink(String str, String link) {
+ return "<a href=\"" + link + "\">" + str + "</a>";
+ }
+
+ private void link(String str, String link) {
+ String htmlStr = "";
+ if (!inList && getIndentPixels() > 0) {
+ htmlStr += "<div style=\"margin-left: " + getIndentPixels() + "px;\">";
+ } else if (inList) {
+ htmlStr += "<li>";
+ }
+ htmlStr += getLink(str, link);
+ if (!inList && getIndentPixels() > 0) {
+ htmlStr += "</div>";
+ } else if (inList) {
+ htmlStr += "</li>";
+ }
+ if (!inList) {
+ htmlStr += "<br>";
+ }
+ htmlBuff.append(htmlStr + "\n");
+ }
+
+ private void newline() {
+ htmlBuff.append(
+ getNewLine());
+ }
+
+ private String getNewLine() {
+ return "<br>\n";
+ }
+
+ private void paragraph(Message description) {
+ if (description != null) {
+ paragraph(description.toString());
+ }
+ }
+
+ private void paragraph(Message description, TextStyle style) {
+ if (description != null) {
+ paragraph(description.toString(), style);
+ }
+ }
+
+ private void paragraph(String description) {
+ paragraph(description, TextStyle.STANDARD);
+ }
+
+ private void paragraph(String description, TextStyle style) {
+ String firstTag;
+ if (getIndentPixels() > 0) {
+ firstTag = "<p style=\"margin-left: " + getIndentPixels() + "px;\">";
+ } else if (style == style.BOLD) {
+ firstTag = "<p style=\"font-weight: bold;\">";
+ } else {
+ firstTag = "<p>";
+ }
+ htmlBuff.append(
+ firstTag +
+ description +
+ "</p>\n");
+ }
+
+ private int getIndentPixels() {
+ return (ind * 40);
+ }
+
+ private void startTable() {
+ htmlBuff.append(
+ "<table " +
+ "style=\"width: 100%; text-align: left;\"" +
+ "border=\"1\"" +
+ "cellpadding=\"1\"" +
+ "cellspacing=\"0\"" +
+ ">\n");
+
+ htmlBuff.append("<tbody>\n");
+ }
+
+ private void tableRow(String... strings) {
+ htmlBuff.append(
+ "<tr>\n");
+ for (int ii = 0; ii < strings.length; ii++) {
+ String string = strings[ii];
+ htmlBuff.append(
+ "<td style=\"" +
+ "vertical-align: top; " +
+ ((ii == 0) ? "width: 20%;" : "") +
+ "\">" +
+ string +
+ "<br></td>");
+ }
+ htmlBuff.append(
+ "</tr>\n");
+ }
+
+ /**
+ * Text style.
+ */
+ private enum TextStyle {
+
+ STANDARD, BOLD, ITALIC, UNDERLINE, FIXED_WIDTH
+ }
+
+ /**
+ * List style.
+ */
+ private enum ListStyle {
+
+ STANDARD, BULLET, NUMBER
+ }
+
+ private void indent() {
+ ind++;
+ }
+
+ private void outdent() {
+ ind--;
+ }
+
+ private void beginList() {
+ inList = true;
+ listLevel++;
+ htmlBuff.append(
+ "<ul>\n");
+ }
+
+ private void endList() {
+ listLevel--;
+ if (listLevel == 0) {
+ inList = false;
+ }
+ htmlBuff.append(
+ "</ul>\n");
+ }
+
+ private void htmlFooter() {
+ htmlBuff.append(
+ "</body>\n" +
+ "</html>\n");
+ }
+
+ private static void usage() {
+ System.err.println(
+ "Usage : Provide the argument : output generation directory.");
+ System.exit(1);
+ }
+
+ private void generateFile(String fileName) {
+ // Write the html buffer in a file
+ try {
+ PrintWriter file = new java.io.PrintWriter(
+ new java.io.FileWriter(generationDir + File.separator + fileName));
+ file.write(htmlBuff.toString());
+ file.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ // re-init html buffer
+ htmlBuff = new StringBuffer();
+ }
+
+ // Relation List from RootConfiguration
+ private TreeMap<String, RelationDefinition> topRelList =
+ new TreeMap<String, RelationDefinition>();
+ private TreeMap<String, RelationDefinition> relList =
+ new TreeMap<String, RelationDefinition>();
+ // managed object list
+ private TreeMap<String, AbstractManagedObjectDefinition> moList =
+ new TreeMap<String, AbstractManagedObjectDefinition>();
+ private TreeMap<String, AbstractManagedObjectDefinition> topMoList =
+ new TreeMap<String, AbstractManagedObjectDefinition>();
+ private int ind = 0;
+ private StringBuffer htmlBuff = new StringBuffer();
+ private static String generationDir;
+ private boolean inList = false;
+ private int listLevel = 0;
+}
--
Gitblit v1.10.0