diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index d5aefcfa64..aa092bdc3a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -158,6 +158,84 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
*/
public static final String HTMLDOC_asideFloat = PREFIX + ".asideFloat.s";
+ /**
+ * Configuration property: Content Security Policy (CSP) Hash algorithm name.
+ *
+ *
Property:
+ *
+ * - ID: {@link org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_cspHash HTMLDOC_cspHash}
+ *
- Name: "HtmlDocSerializer.cspHash.s"
+ *
- Data type: {@link org.apache.juneau.html.annotation.CspHash}
+ *
- System property: HtmlDocSerializer.cspHash
+ *
- Environment variable: HTMLDOCSERIALIZER_CSPHASH
+ *
- Default: {@link org.apache.juneau.html.annotation.CspHash#DEFAULT}
+ *
- Session property: true
+ *
- Annotations:
+ *
+ * - {@link org.apache.juneau.html.annotation.HtmlDocConfig#cspHash()}
+ *
+ * - Methods:
+ *
+ * - {@link org.apache.juneau.html.HtmlDocSerializerBuilder#cspHash(org.apache.juneau.html.annotation.CspHash)}
+ *
+ *
+ *
+ * Description:
+ *
+ * Allows you to set a CSP Hash algorithm name.
+ *
+ *
+ * By default, this feature is disabled.
+ *
+ *
Example:
+ *
+ * @HtmlDocConfig(
+ * cspHash="sha256"
+ * )
+ *
+ * @since 9.0.0
+ */
+ public static final String HTMLDOC_cspHash = PREFIX + ".cspHash.s";
+
+ /**
+ * Configuration property: Content Security Policy (CSP) nonce algorithm name.
+ *
+ * Property:
+ *
+ * - ID: {@link org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_cspNonce HTMLDOC_cspNonce}
+ *
- Name: "HtmlDocSerializer.cspNonce.s"
+ *
- Data type: {@link org.apache.juneau.html.annotation.CspNonce}
+ *
- System property: HtmlDocSerializer.cspNonce
+ *
- Environment variable: HTMLDOCSERIALIZER_CSPNONCE
+ *
- Default: {@link org.apache.juneau.html.annotation.CspNonce#DEFAULT}
+ *
- Session property: true
+ *
- Annotations:
+ *
+ * - {@link org.apache.juneau.html.annotation.HtmlDocConfig#cspNonce()}
+ *
+ * - Methods:
+ *
+ * - {@link org.apache.juneau.html.HtmlDocSerializerBuilder#cspNonce(org.apache.juneau.html.annotation.CspNonce)}
+ *
+ *
+ *
+ * Description:
+ *
+ * Allows you to set a CSP nonce algorithm name.
+ *
+ *
+ * By default, this feature is disabled.
+ *
+ *
Example:
+ *
+ * @HtmlDocConfig(
+ * cspNonce="SecureRandom"
+ * )
+ *
+ * @since 9.0.0
+ */
+ public static final String HTMLDOC_cspNonce = PREFIX + ".cspNonce.s";
+
/**
* Configuration property: Footer section contents.
*
@@ -717,6 +795,8 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
//-------------------------------------------------------------------------------------------------------------------
private final String[] style, stylesheet, script, navlinks, head, header, nav, aside, footer;
+ private final CspHash cspHash;
+ private final CspNonce cspNonce;
private final AsideFloat asideFloat;
private final String noResultsMessage;
private final boolean nowrap;
@@ -776,6 +856,9 @@ public HtmlDocSerializer(ContextProperties cp, String produces, String accept) {
navlinks = cp.getArray(HTMLDOC_navlinks, String.class).orElse(new String[0]);
noResultsMessage = cp.getString(HTMLDOC_noResultsMessage).orElse("no results
");
template = cp.getInstance(HTMLDOC_template, HtmlDocTemplate.class).orElseGet(BasicHtmlDocTemplate::new);
+
+ cspHash = cp.get(HTMLDOC_cspHash, CspHash.class).orElse(CspHash.DEFAULT);
+ cspNonce = cp.get(HTMLDOC_cspNonce, CspNonce.class).orElse(CspNonce.DEFAULT);
widgets = new HtmlWidgetMap();
widgets.append(cp.getInstanceArray(HTMLDOC_widgets, HtmlWidget.class).orElse(new HtmlWidget[0]));
@@ -845,6 +928,26 @@ protected final AsideFloat getAsideFloat() {
return asideFloat;
}
+ /**
+ * CSP hash algorithm name.
+ * @return
+ * CSP hash algorithm name.
+ * @since 9.0.0
+ */
+ protected final CspHash getCspHash() {
+ return cspHash;
+ }
+
+ /**
+ * CSP nonce algorithm name.
+ * @return
+ * CSP nonce algorithm name.
+ * @since 9.0.0
+ */
+ protected final CspNonce getCspNonce() {
+ return cspNonce;
+ }
+
/**
* Footer section contents.
*
@@ -996,6 +1099,8 @@ public OMap toMap() {
.a("asideFloat", asideFloat)
.a("footer", footer)
.a("style", style)
+ .a("cspHash", cspHash)
+ .a("cspNonce", cspNonce)
.a("head", head)
.a("stylesheet", stylesheet)
.a("nowrap", nowrap)
@@ -1004,4 +1109,5 @@ public OMap toMap() {
.a("widgets", widgets.keySet())
);
}
+
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
index bb6f618894..be39e5f3ce 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
@@ -12,19 +12,48 @@
// ***************************************************************************************************************************
package org.apache.juneau.html;
-import static org.apache.juneau.html.HtmlDocSerializer.*;
-
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.nio.charset.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.http.header.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.reflect.*;
-import org.apache.juneau.svl.*;
-import org.apache.juneau.xml.*;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_aside;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_asideFloat;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_cspHash;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_cspNonce;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_footer;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_head;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_header;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_nav;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_navlinks;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_navlinks_add;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_noResultsMessage;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_nowrap;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_script;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_script_add;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_style;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_style_add;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_stylesheet;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_stylesheet_add;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_template;
+import static org.apache.juneau.html.HtmlDocSerializer.HTMLDOC_widgets;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.juneau.ContextProperties;
+import org.apache.juneau.UriContext;
+import org.apache.juneau.UriRelativity;
+import org.apache.juneau.UriResolution;
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.Visibility;
+import org.apache.juneau.html.annotation.CspHash;
+import org.apache.juneau.html.annotation.CspNonce;
+import org.apache.juneau.http.header.MediaType;
+import org.apache.juneau.internal.FluentSetter;
+import org.apache.juneau.internal.FluentSetters;
+import org.apache.juneau.reflect.AnnotationList;
+import org.apache.juneau.svl.VarResolverSession;
+import org.apache.juneau.xml.Namespace;
/**
* Builder class for building instances of HTML Doc serializers.
@@ -624,6 +653,98 @@ public HtmlDocSerializerBuilder applyAnnotations(AnnotationList al, VarResolverS
return this;
}
+ /**
+ * Configuration property: Content Security Policy (CSP) Hash algorithm name.
+ *
+ * Property:
+ *
+ * - ID: {@link org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_cspHash HTMLDOC_cspHash}
+ *
- Name: "HtmlDocSerializer.cspHash.s"
+ *
- Data type: {@link org.apache.juneau.html.annotation.CspHash}
+ *
- System property: HtmlDocSerializer.cspHash
+ *
- Environment variable: HTMLDOCSERIALIZER_CSPHASH
+ *
- Default: {@link org.apache.juneau.html.annotation.CspHash#DEFAULT}
+ *
- Session property: true
+ *
- Annotations:
+ *
+ * - {@link org.apache.juneau.html.annotation.HtmlDocConfig#cspHash()}
+ *
+ * - Methods:
+ *
+ * - {@link org.apache.juneau.html.HtmlDocSerializerBuilder#cspHash(org.apache.juneau.html.annotation.CspHash)}
+ *
+ *
+ *
+ * Description:
+ *
+ * Allows you to set a CSP Hash algorithm name.
+ *
+ *
+ * By default, this feature is disabled.
+ *
+ *
Example:
+ *
+ * @HtmlDocConfig(
+ * cspHash="sha256"
+ * )
+ *
+ * @param value
+ * The new value for this property.
+ * @return This object (for method chaining).
+ * @since 9.0.0
+ */
+ @FluentSetter
+ public HtmlDocSerializerBuilder cspHash(CspHash value) {
+ set(HTMLDOC_cspHash, value);
+ return this;
+ }
+
+ /**
+ * Configuration property: Content Security Policy (CSP) nonce algorithm name.
+ *
+ * Property:
+ *
+ * - ID: {@link org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_cspNonce HTMLDOC_cspNonce}
+ *
- Name: "HtmlDocSerializer.cspNonce.s"
+ *
- Data type: {@link org.apache.juneau.html.annotation.CspNonce}
+ *
- System property: HtmlDocSerializer.cspNonce
+ *
- Environment variable: HTMLDOCSERIALIZER_CSPNONCE
+ *
- Default: {@link org.apache.juneau.html.annotation.CspNonce#DEFAULT}
+ *
- Session property: true
+ *
- Annotations:
+ *
+ * - {@link org.apache.juneau.html.annotation.HtmlDocConfig#cspNonce()}
+ *
+ * - Methods:
+ *
+ * - {@link org.apache.juneau.html.HtmlDocSerializerBuilder#cspNonce(org.apache.juneau.html.annotation.CspNonce)}
+ *
+ *
+ *
+ * Description:
+ *
+ * Allows you to set a CSP nonce algorithm name.
+ *
+ *
+ * By default, this feature is disabled.
+ *
+ *
Example:
+ *
+ * @HtmlDocConfig(
+ * cspNonce="SecureRandom"
+ * )
+ *
+ * @param value
+ * The new value for this property.
+ * @return This object (for method chaining).
+ * @since 9.0.0
+ */
+ @FluentSetter
+ public HtmlDocSerializerBuilder cspNonce(CspNonce value) {
+ set(HTMLDOC_cspNonce, value);
+ return this;
+ }
+
@Override /* GENERATED - ContextBuilder */
public HtmlDocSerializerBuilder debug() {
super.debug();
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index 719202f3ed..6c18145a57 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -19,6 +19,8 @@
import org.apache.juneau.*;
import org.apache.juneau.collections.*;
+import org.apache.juneau.html.annotation.CspHash;
+import org.apache.juneau.html.annotation.CspNonce;
import org.apache.juneau.serializer.*;
import org.apache.juneau.svl.*;
@@ -40,6 +42,8 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
private final AsideFloat asideFloat;
private final Set style, stylesheet, script;
private final boolean nowrap;
+ private final CspHash cspHash;
+ private final CspNonce cspNonce;
/**
* Create a new session using properties specified in the context.
@@ -67,6 +71,9 @@ protected HtmlDocSerializerSession(HtmlDocSerializer ctx, SerializerSessionArgs
style = ASet.of(sp.get(HTMLDOC_style, String[].class).orElse(ctx.getStyle()));
stylesheet = ASet.of(sp.get(HTMLDOC_stylesheet, String[].class).orElse(ctx.getStylesheet()));
script = ASet.of(sp.get(HTMLDOC_script, String[].class).orElse(ctx.getScript()));
+
+ cspHash = sp.get(HTMLDOC_cspHash, CspHash.class).orElse(ctx.getCspHash());
+ cspNonce = sp.get(HTMLDOC_cspNonce, CspNonce.class).orElse(ctx.getCspNonce());
head = sp.get(HTMLDOC_head, String[].class).orElse(ctx.getHead());
nowrap = sp.get(HTMLDOC_nowrap, boolean.class).orElse(ctx.isNowrap());
@@ -142,6 +149,30 @@ protected final AsideFloat getAsideFloat() {
return asideFloat;
}
+ /**
+ * Configuration property: CSP hash algorithm name.
+ *
+ * @see HtmlDocSerializer#HTMLDOC_cspHash
+ * @return
+ * CSP hash algorithm name.
+ * @since 9.0.0
+ */
+ protected final CspHash getCspHash() {
+ return cspHash;
+ }
+
+ /**
+ * Configuration property: CSP nonce algorithm name.
+ *
+ * @see HtmlDocSerializer#HTMLDOC_cspNonce
+ * @return
+ * CSP nonce algorithm name.
+ * @since 9.0.0
+ */
+ protected final CspNonce getCspNonce() {
+ return cspNonce;
+ }
+
/**
* Configuration property: Footer section contents.
*
@@ -294,8 +325,11 @@ public OMap toMap() {
.a("navlinks", navlinks)
.a("script", script)
.a("style", style)
+ .a("cspHash", cspHash)
+ .a("cspNonce", cspNonce)
.a("stylesheet", stylesheet)
.a("varResolver", getVarResolver())
);
}
+
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/CspHash.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/CspHash.java
new file mode 100644
index 0000000000..bb704c2529
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/CspHash.java
@@ -0,0 +1,76 @@
+// ***************************************************************************************************************************
+// * 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.juneau.html.annotation;
+
+/**
+ * Hash algorithms defined for
+ * Content Security Policy
+ * elements {@code script} and {@code style}.
+ *
+ * @see Content Security Policy
+ * Level 2 (W3C Recommendation, 15 December 2016)
+ * @see CSP 2
+ * valid hashes
+ * @see CSP 3
+ * valid hashes
+ * @since 9.0.0
+ */
+public enum CspHash {
+
+ /**
+ * Don't use a hash algorithm.
+ */
+ DEFAULT(""),
+
+ /**
+ * SHA-256 hash algorithm.
+ *
+ * @see Valid
+ * hashes.
+ */
+ SHA256("sha256"),
+
+ /**
+ * SHA-384 hash algorithm.
+ *
+ * @see Valid
+ * hashes.
+ */
+
+ SHA384("sha384"),
+ /**
+ * SHA-512 hash algorithm.
+ *
+ * @see Valid
+ * hashes.
+ */
+ SHA512("sha512");
+
+ /** Value in HTML. */
+ private final String value;
+
+ /** Constructs a new instance. */
+ CspHash(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value for HTML.
+ *
+ * @return the value for HTML.
+ */
+ public String value() {
+ return value;
+ }
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/CspNonce.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/CspNonce.java
new file mode 100644
index 0000000000..aeed0a15eb
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/CspNonce.java
@@ -0,0 +1,62 @@
+// ***************************************************************************************************************************
+// * 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.juneau.html.annotation;
+
+/**
+ * Nonce algorithms defined for use with
+ * Content Security Policy
+ * elements {@code script} and {@code style}.
+ *
+ * @see Content Security Policy
+ * Level 2 (W3C Recommendation, 15 December 2016)
+ * @see Content Security Policy
+ * Level 3 (W3C Working Draft, 15 October 2018)
+ * @see Nonce reuse
+ * @since 9.0.0
+ */
+public enum CspNonce {
+
+ /**
+ * Don't use a nonce.
+ */
+ DEFAULT(""),
+
+ /**
+ * The secure random algorithm.
+ *
+ * @see Valid
+ * hashes.
+ * @see Nonce reuse
+ */
+ // Assumes we are using java.security.SecureRandom as opposed to java.util.Random
+ // But leave room for other sources of randomness.
+ SECURE_RANDOM("SecureRandom");
+
+ /** Value in HTML. */
+ private final String value;
+
+ /** Constructs a new instance. */
+ CspNonce(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value for HTML.
+ *
+ * @return the value for HTML.
+ */
+ public String value() {
+ return value;
+ }
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
index 9b8051910c..e3139f0931 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
@@ -142,6 +142,92 @@
*/
String asideFloat() default "DEFAULT";
+ /**
+ * Configuration property: A hash algorithm defined in
+ * Content Security Policy for
+ * the elements {@code script} and {@code style}.
+ *
+ * The possible algorithm names from {@link CspHash} are:
+ *
+ * - "sha256"
+ *
- "sha384"
+ *
- "sha512"
+ *
+ *
+ *
+ * Adds the HTTP header in the form:
+ *
+ * Content-Security-Policy: script-src 'ALGORITHM-base64 encoded hash'
+ *
+ * Note that the header can carry the directives:
+ *
+ * - {@code script-src}, {@code script-src-attr}, and {@code script-src-elem}
+ * - {@code style-src}, {@code style-src-attr}, and {@code style-src-elem}
+ *
+ *
+ *
+ * Example:
+ *
+ * The annotation:
+ *
+ * @HtmlDocConfig(
+ * cspHash="sha256"
+ * )
+ *
+ * For the SHA-256 hash for the script {@code alert('Hello, world.');} is
+ * {@code qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=}.
+ *
+ * Generates the HTTP header:
+ *
+ * Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='
+ *
+ *
+ *
+ * @since 9.0.0
+ */
+ String cspHash() default "DEFAULT";
+
+ /**
+ * Configuration property: Nonce algorithms defined for use with
+ * Content Security Policy
+ * for the elements {@code script} and {@code style}.
+ *
+ * The possible algorithm names from {@link CspNonce} are:
+ *
+ *
+ *
+ * Adds the HTTP header in the form:
+ *
+ * Content-Security-Policy: script-src 'nonce-$RANDOM'
+ *
+ * Note that the header can carry the directives:
+ *
+ * - {@code script-src}, {@code script-src-attr}, and {@code script-src-elem}
+ * - {@code style-src}, {@code style-src-attr}, and {@code style-src-elem}
+ *
+ *
+ *
+ * Example:
+ *
+ * The annotation:
+ *
+ * @HtmlDocConfig(
+ * cspNonce="SecureRandom"
+ * )
+ *
+ *
+ * Generates the HTTP header like:
+ *
+ * Content-Security-Policy: script-src 'nonce-Nc3n83cnSAd3wc3Sasdfn939hc3'
+ *
+ *
+ *
+ * @since 9.0.0
+ */
+ String cspNonce() default "DEFAULT";
+
/**
* Configuration property: Footer section contents.
*
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
index 7b680f68af..8670c8f7eb 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
@@ -50,6 +50,8 @@ public void apply(AnnotationInfo ai, ContextPropertiesBuilder cpb
cpb.setIf(a.aside().length > 0, HTMLDOC_aside, resolveList(a.aside(), cpb.peek(String[].class, HTMLDOC_aside)));
cpb.setIf(! "DEFAULT".equalsIgnoreCase(a.asideFloat()), HTMLDOC_asideFloat, a.asideFloat().toUpperCase());
+ cpb.setIf(! "DEFAULT".equalsIgnoreCase(a.cspHash()), HTMLDOC_cspHash, a.cspHash().toUpperCase());
+ cpb.setIf(! "DEFAULT".equalsIgnoreCase(a.cspNonce()), HTMLDOC_cspNonce, a.cspNonce().toUpperCase());
cpb.setIf(a.footer().length > 0, HTMLDOC_footer, resolveList(a.footer(), cpb.peek(String[].class, HTMLDOC_footer)));
cpb.setIf(a.head().length > 0, HTMLDOC_head, resolveList(a.head(), cpb.peek(String[].class, HTMLDOC_head)));
cpb.setIf(a.header().length > 0, HTMLDOC_header, resolveList(a.header(), cpb.peek(String[].class, HTMLDOC_header)));
diff --git a/juneau-utest/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotation_Test.java
index 53bf83a15e..52ef5a02e9 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotation_Test.java
@@ -60,6 +60,9 @@ public String apply(Object t) {
@HtmlDocConfig(
aside="$X{foo}",
+ asideFloat="DEFAULT",
+ cspHash="sha256",
+ cspNonce="SECURE_RANDOM",
footer="$X{foo}",
head="$X{foo}",
header="$X{foo}",
@@ -80,6 +83,9 @@ public void basic() throws Exception {
AnnotationList al = a.getAnnotationList();
HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(al, sr).build().createSession();
check("foo", x.getAside());
+ check("RIGHT", x.getAsideFloat());
+ check("SHA256", x.getCspHash());
+ check("SECURE_RANDOM", x.getCspNonce());
check("foo", x.getFooter());
check("foo", x.getHead());
check("foo", x.getHeader());
@@ -106,6 +112,7 @@ public void defaults() throws Exception {
AnnotationList al = b.getAnnotationList();
HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(al, sr).build().createSession();
check("", x.getAside());
+ check("RIGHT", x.getAsideFloat());
check("", x.getFooter());
check("", x.getHead());
check("", x.getHeader());
@@ -131,6 +138,9 @@ public void noAnnotation() throws Exception {
AnnotationList al = c.getAnnotationList();
HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(al, sr).build().createSession();
check("", x.getAside());
+ check("RIGHT", x.getAsideFloat());
+ check("DEFAULT", x.getCspHash());
+ check("DEFAULT", x.getCspNonce());
check("", x.getFooter());
check("", x.getHead());
check("", x.getHeader());