blob: ba60da28fa2b8a6eed5666df2b626e9ab570ed45 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.accumulo.core.conf;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.io.PrintStream;
import java.util.TreeMap;
/**
* This class generates documentation to inform users of the available configuration properties in a
* presentable form.
*/
public class ConfigurationDocGen {
private PrintStream doc;
private final TreeMap<String,Property> sortedProps = new TreeMap<>();
void generate() {
pageHeader();
beginTable("Property");
for (Property prop : sortedProps.values()) {
if (prop.getType() == PropertyType.PREFIX) {
prefixSection(prop);
} else {
property(prop);
}
}
beginSection("Property Types");
beginTable("Type");
propertyTypeDescriptions();
doc.close();
}
void beginSection(String section) {
doc.println("\n### " + section + "\n");
}
void beginTable(String name) {
doc.println("| " + name + " | Description |");
doc.println("|--------------|-------------|");
}
void pageHeader() {
doc.println("---");
doc.println("title: Server Properties");
doc.println("category: configuration");
doc.println("order: 4");
doc.println("---\n");
doc.println("<!-- WARNING: Do not edit this file. It is a generated file"
+ " that is copied from Accumulo build (from core/target/generated-docs)" + " -->\n");
doc.println("Below are properties set in `accumulo.properties` or the"
+ " Accumulo shell that configure Accumulo servers (i.e tablet server,"
+ " manager, etc). Properties labeled 'Experimental' could be part of an incomplete"
+ " feature or have a higher risk of changing in the future.\n");
}
void prefixSection(Property prefix) {
boolean depr = prefix.isDeprecated();
doc.print("| <a name=\"" + prefix.getKey().replace(".", "_") + "prefix\" class=\"prop\"></a> **"
+ prefix.getKey() + "*** | ");
doc.print(prefix.isExperimental() ? "**Experimental.** " : "");
doc.println(
(depr ? "**Deprecated.** " : "") + strike(sanitize(prefix.getDescription()), depr) + " |");
}
void property(Property prop) {
boolean depr = prop.isDeprecated();
doc.print("| <a name=\"" + prop.getKey().replace(".", "_") + "\" class=\"prop\"></a> "
+ prop.getKey() + " | ");
doc.print(prop.isExperimental() ? "**Experimental.** " : "");
doc.print(
(depr ? "**Deprecated.** " : "") + strike(sanitize(prop.getDescription()), depr) + "<br>");
doc.print(strike("**type:** " + prop.getType().name(), depr) + ", ");
doc.print(strike("**zk mutable:** " + isZooKeeperMutable(prop), depr) + ", ");
String defaultValue = sanitize(prop.getDefaultValue()).trim();
if (defaultValue.isEmpty()) {
defaultValue = strike("**default value:** empty", depr);
} else if (defaultValue.contains("\n")) {
// deal with multi-line values, skip strikethrough of value
defaultValue = strike("**default value:** ", depr) + "\n```\n" + defaultValue + "\n```\n";
} else {
if (prop.getType() == PropertyType.CLASSNAME
&& defaultValue.startsWith("org.apache.accumulo")) {
defaultValue = strike("**default value:** " + "{% jlink -f " + defaultValue + " %}", depr);
} else {
defaultValue = strike("**default value:** " + "`" + defaultValue + "`", depr);
}
}
doc.println(defaultValue + " |");
}
private String strike(String s, boolean isDeprecated) {
return (isDeprecated ? "~~" : "") + s + (isDeprecated ? "~~" : "");
}
void propertyTypeDescriptions() {
for (PropertyType type : PropertyType.values()) {
if (type == PropertyType.PREFIX) {
continue;
}
doc.println(
"| " + sanitize(type.toString()) + " | " + sanitize(type.getFormatDescription()) + " |");
}
}
String sanitize(String str) {
return str.replace("\n", "<br>");
}
private ConfigurationDocGen(PrintStream doc) {
this.doc = doc;
for (Property prop : Property.values()) {
this.sortedProps.put(prop.getKey(), prop);
}
}
private String isZooKeeperMutable(Property prop) {
if (!Property.isValidZooPropertyKey(prop.getKey())) {
return "no";
}
if (Property.isFixedZooPropertyKey(prop)) {
return "yes but requires restart of the " + prop.getKey().split("[.]")[0];
}
return "yes";
}
/**
* Generates documentation for accumulo.properties file usage. Arguments are: "--generate-markdown
* filename"
*
* @param args
* command-line arguments
* @throws IllegalArgumentException
* if args is invalid
*/
public static void main(String[] args) throws IOException {
if (args.length == 2 && args[0].equals("--generate-markdown")) {
try (var printStream = new PrintStream(args[1], UTF_8)) {
new ConfigurationDocGen(printStream).generate();
}
} else {
throw new IllegalArgumentException(
"Usage: " + ConfigurationDocGen.class.getName() + " --generate-markdown <filename>");
}
}
}