You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2022/07/10 16:10:25 UTC
[juneau] branch jbFixRestNpe updated: Rest bean refactoring.
This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch jbFixRestNpe
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/jbFixRestNpe by this push:
new 8361e5498 Rest bean refactoring.
8361e5498 is described below
commit 8361e5498ee84509face84a4e4e87e3cc776b2cf
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Sun Jul 10 12:10:05 2022 -0400
Rest bean refactoring.
---
.../org/apache/juneau/rest/ResourceSupplier.java | 40 ++++++
.../java/org/apache/juneau/rest/RestContext.java | 141 +++++----------------
.../java/org/apache/juneau/rest/RestOpContext.java | 2 +-
.../org/apache/juneau/rest/annotation/Rest.java | 4 -
.../juneau/rest/annotation/RestAnnotation.java | 2 -
.../juneau/rest/debug/BasicDebugEnablement.java | 128 +++++++++++--------
.../apache/juneau/rest/debug/DebugEnablement.java | 94 +++++++++++++-
.../org/apache/juneau/rest/logger/CallLogger.java | 2 -
8 files changed, 239 insertions(+), 174 deletions(-)
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ResourceSupplier.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ResourceSupplier.java
new file mode 100644
index 000000000..63c836ebb
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ResourceSupplier.java
@@ -0,0 +1,40 @@
+// ***************************************************************************************************************************
+// * 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.rest;
+
+import java.util.function.*;
+
+/**
+ * A supplier of a REST resource bean.
+ *
+ * <p>
+ * Pretty much just a normal supplier, but wrapped in a concrete class so that it can be retrieved by class name.
+ */
+public class ResourceSupplier implements Supplier<Object> {
+
+ private final Supplier<?> supplier;
+
+ /**
+ * Constructor.
+ *
+ * @param supplier The supplier of the bean.
+ */
+ public ResourceSupplier(Supplier<?> supplier) {
+ this.supplier = supplier;
+ }
+
+ @Override
+ public Object get() {
+ return supplier.get();
+ }
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 74bc6a91b..7726c50f2 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -211,7 +211,7 @@ public class RestContext extends Context {
private boolean initialized;
- Supplier<?> resource;
+ ResourceSupplier resource;
ServletContext servletContext;
final ServletConfig inner;
@@ -238,7 +238,7 @@ public class RestContext extends Context {
private HeaderList.Builder defaultRequestHeaders, defaultResponseHeaders;
private NamedAttributeList.Builder defaultRequestAttributes;
private RestOpArgList.Builder restOpArgs;
- private DebugEnablement.Builder debugEnablement;
+ private BeanCreator<DebugEnablement> debugEnablement;
private MethodList startCallMethods, endCallMethods, postInitMethods, postInitChildFirstMethods, destroyMethods, preCallMethods, postCallMethods;
private RestOperations.Builder restOperations;
private RestChildren.Builder restChildren;
@@ -324,13 +324,14 @@ public class RestContext extends Context {
return this;
initialized = true;
- this.resource = resource;
+ this.resource = new ResourceSupplier(resource);
Supplier<?> r = this.resource;
Class<?> rc = resourceClass;
beanStore = createBeanStore(rc, r)
.build()
.addBean(Builder.class, this)
+ .addBean(ResourceSupplier.class, this.resource)
.addBean(ServletConfig.class, inner != null ? inner : this)
.addBean(ServletContext.class, (inner != null ? inner : this).getServletContext());
@@ -3359,7 +3360,7 @@ public class RestContext extends Context {
//-----------------------------------------------------------------------------------------------------------------
/**
- * Returns the debug enablement sub-builder.
+ * Returns the debug enablement bean creator.
*
* <p>
* Enables the following:
@@ -3372,149 +3373,74 @@ public class RestContext extends Context {
*
* @return The debug enablement sub-builder.
*/
- public DebugEnablement.Builder debugEnablement() {
+ public BeanCreator<DebugEnablement> debugEnablement() {
if (debugEnablement == null)
- debugEnablement = createDebugEnablement(beanStore(), resource());
+ debugEnablement = createDebugEnablement();
return debugEnablement;
}
/**
- * Applies an operation to the debug enablement sub-builder.
+ * Specifies the debug enablement class to use for this REST context.
*
- * <p>
- * Typically used to allow you to execute operations without breaking the fluent flow of the context builder.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bjava'>
- * RestContext <jv>context</jv> = RestContext
- * .<jsm>create</jsm>(<jv>resourceClass</jv>, <jv>parentContext</jv>, <jv>servletConfig</jv>)
- * .debugEnablement(<jv>x</jv> -> <jv>x</jv>.defaultEnable(<jsf>ALWAYS</jsf>))
- * .build();
- * </p>
- *
- * @param operation The operation to apply.
- * @return This object.
- */
- public Builder debugEnablement(Consumer<DebugEnablement.Builder> operation) {
- operation.accept(debugEnablement());
- return this;
- }
-
- /**
- * Sets the debug default value.
- *
- * <p>
- * The default debug value is the enablement value if not otherwise overridden at the class or method level.
- *
- * @param value The debug default value.
+ * @param value The new value for this setting.
* @return This object.
*/
- @FluentSetter
- public Builder debugDefault(Enablement value) {
- defaultSettings().set("RestContext.debugDefault", value);
+ public Builder debugEnablement(Class<? extends DebugEnablement> value) {
+ debugEnablement().type(value);
return this;
}
/**
- * Specifies the debug level on this REST resource.
+ * Specifies the debug enablement class to use for this REST context.
*
- * @param value The value for this setting.
+ * @param value The new value for this setting.
* @return This object.
*/
- public Builder debug(Enablement value) {
- debugEnablement().enable(value, this.resourceClass);
+ public Builder debugEnablement(DebugEnablement value) {
+ debugEnablement().impl(value);
return this;
}
/**
- * Debug mode on specified classes/methods.
- *
- * Enables the following:
- * <ul class='spaced-list'>
- * <li>
- * HTTP request/response bodies are cached in memory for logging purposes.
- * <li>
- * Request/response messages are automatically logged.
- * </ul>
+ * Sets the debug default value.
*
- * <ul class='seealso'>
- * <li class='ja'>{@link Rest#debugOn}
- * </ul>
+ * <p>
+ * The default debug value is the enablement value if not otherwise overridden at the class or method level.
*
- * @param value The new value for this setting.
+ * @param value The debug default value.
* @return This object.
*/
@FluentSetter
- public Builder debugOn(String value) {
- for (Map.Entry<String,String> e : splitMap(value != null ? value : "", true).entrySet()) {
- String k = e.getKey(), v = e.getValue();
- if (v.isEmpty())
- v = "ALWAYS";
- if (! k.isEmpty())
- debugEnablement().enable(Enablement.fromString(v), k);
- }
+ public Builder debugDefault(Enablement value) {
+ defaultSettings().set("RestContext.debugDefault", value);
return this;
}
/**
- * Instantiates the debug enablement sub-builder.
+ * Instantiates the debug enablement bean creator.
*
- * @param beanStore
- * The factory used for creating beans and retrieving injected beans.
- * @param resource
- * The REST servlet/bean instance that this context is defined against.
- * @return A new debug enablement sub-builder.
+ * @return A new debug enablement bean creator.
*/
- protected DebugEnablement.Builder createDebugEnablement(BeanStore beanStore, Supplier<?> resource) {
-
- // Default value.
- Value<DebugEnablement.Builder> v = Value.of(
- DebugEnablement
- .create(beanStore)
- );
-
- // Default debug enablement if not overridden at class/method level.
- Enablement debugDefault = defaultSettings.get(Enablement.class, "RestContext.debugDefault").orElse(isDebug() ? Enablement.ALWAYS : Enablement.NEVER);
- v.get().defaultEnable(debugDefault);
-
- // Gather @RestOp(debug) settings.
- Consumer<MethodInfo> consumer = x -> {
- Value<String> debug = Value.empty();
- x.getAnnotationList(REST_OP_GROUP).forEachValue(String.class, "debug", NOT_EMPTY, y -> debug.set(y));
- if (debug.isPresent())
- v.get().enable(Enablement.fromString(debug.get()), x.getFullName());
- };
- ClassInfo.ofProxy(resource.get()).forEachPublicMethod(x -> true, consumer);
-
- // Replace with bean from bean store.
- rootBeanStore
- .getBean(DebugEnablement.class)
- .ifPresent(x -> v.get().impl(x));
+ protected BeanCreator<DebugEnablement> createDebugEnablement() {
- // Replace with this bean.
- resourceAs(DebugEnablement.class)
- .ifPresent(x -> v.get().impl(x));
+ BeanCreator<DebugEnablement> creator = beanStore.createBean(DebugEnablement.class).type(BasicDebugEnablement.class);
- // Specify the implementation class if its set as a default.
+ // Specify the bean type if its set as a default.
defaultClasses()
.get(DebugEnablement.class)
- .ifPresent(x -> v.get().type(x));
+ .ifPresent(x -> creator.type(x));
- // Replace with builder from: public [static] DebugEnablement.Builder createDebugEnablement(<args>)
- beanStore
- .createMethodFinder(DebugEnablement.Builder.class)
- .addBean(DebugEnablement.Builder.class, v.get())
- .find("createDebugEnablement")
- .run(x -> v.set(x));
+ rootBeanStore
+ .getBean(DebugEnablement.class)
+ .ifPresent(x -> creator.impl(x));
// Replace with bean from: public [static] DebugEnablement createDebugEnablement(<args>)
beanStore
.createMethodFinder(DebugEnablement.class)
- .addBean(DebugEnablement.Builder.class, v.get())
.find("createDebugEnablement")
- .run(x -> v.get().impl(x));
+ .run(x -> creator.impl(x));
- return v.get();
+ return creator;
}
//-----------------------------------------------------------------------------------------------------------------
@@ -5871,6 +5797,7 @@ public class RestContext extends Context {
.addBean(BeanStore.class, beanStore)
.addBean(RestContext.class, this)
.addBean(Object.class, resource.get())
+ .addBean(DefaultSettingsMap.class, defaultSettings)
.addBean(Builder.class, builder)
.addBean(AnnotationWorkList.class, builder.getApplied());
@@ -5915,7 +5842,7 @@ public class RestContext extends Context {
defaultResponseHeaders = bs.add(HeaderList.class, builder.defaultResponseHeaders().build(), "RestContext.defaultResponseHeaders");
defaultRequestAttributes = bs.add(NamedAttributeList.class, builder.defaultRequestAttributes().build(), "RestContext.defaultRequestAttributes");
restOpArgs = builder.restOpArgs().build().asArray();
- debugEnablement = builder.debugEnablement().build();
+ debugEnablement = bs.add(DebugEnablement.class, builder.debugEnablement().orElse(null));
startCallMethods = builder.startCallMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
endCallMethods = builder.endCallMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
postInitMethods = builder.postInitMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
index 8875054ed..b301c738a 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
@@ -2238,7 +2238,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
if (builder.debug == null)
debug = context.getDebugEnablement();
else
- debug = DebugEnablement.create(context.getRootBeanStore()).enable(builder.debug, "*").build();
+ debug = DebugEnablement.create(context.getBeanStore()).enable(builder.debug, "*").build();
mi = MethodInfo.of(method).accessible();
Object r = context.getResource();
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
index 2d4216476..9550d8c21 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
@@ -523,10 +523,6 @@ public @interface Rest {
* These debug settings can be overridden at runtime by directly calling {@link RestRequest#setDebug()}.
* </ul>
*
- * <ul class='seealso'>
- * <li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugOn(String)}
- * </ul>
- *
* @return The annotation value.
*/
String debugOn() default "";
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
index f02087f22..e939d7c81 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
@@ -1109,8 +1109,6 @@ public class RestAnnotation {
string(a.allowedMethodHeaders()).ifPresent(x -> b.allowedMethodHeaders(x));
string(a.allowedMethodParams()).ifPresent(x -> b.allowedMethodParams(x));
bool(a.renderResponseStackTraces()).ifPresent(x -> b.renderResponseStackTraces(x));
- string(a.debug()).map(Enablement::fromString).ifPresent(x -> b.debug(x));
- string(a.debugOn()).ifPresent(x -> b.debugOn(x));
}
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/BasicDebugEnablement.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/BasicDebugEnablement.java
index acd47cf8d..86a8c4bf8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/BasicDebugEnablement.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/BasicDebugEnablement.java
@@ -12,82 +12,104 @@
// ***************************************************************************************************************************
package org.apache.juneau.rest.debug;
-import static org.apache.juneau.internal.ObjectUtils.*;
-import static org.apache.juneau.Enablement.*;
-import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.rest.annotation.RestOpAnnotation.*;
-import java.lang.reflect.*;
-import java.util.function.*;
-
-import javax.servlet.http.*;
+import java.util.*;
import org.apache.juneau.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.svl.*;
/**
* Default implementation of the {@link DebugEnablement} interface.
+ *
+ * <p>
+ * Enables debug mode based on the following annotations:
+ * <ul>
+ * <li class='ja'>{@link Rest#debug()}
+ * <li class='ja'>{@link RestOp#debug()}
+ * <li class='ja'>{@link Rest#debugOn()}
+ * </ul>
*
* <ul class='seealso'>
* <li class='link'>{@doc jrs.LoggingAndDebugging}
* <li class='extlink'>{@source}
* </ul>
*/
-public class BasicDebugEnablement implements DebugEnablement {
-
- private final Enablement defaultEnablement;
- private final ReflectionMap<Enablement> enablementMap;
- private final Predicate<HttpServletRequest> conditionalPredicate;
+public class BasicDebugEnablement extends DebugEnablement {
/**
* Constructor.
*
- * @param builder The builder containing the settings for this bean.
+ * @param beanStore The bean store containing injectable beans for this enablement.
*/
- public BasicDebugEnablement(DebugEnablement.Builder builder) {
- this.defaultEnablement = firstNonNull(builder.defaultEnablement, NEVER);
- this.enablementMap = builder.mapBuilder.build();
- this.conditionalPredicate = firstNonNull(builder.conditional, x -> "true".equalsIgnoreCase(x.getHeader("Debug")));
+ public BasicDebugEnablement(BeanStore beanStore) {
+ super(beanStore);
}
@Override
- public boolean isDebug(RestOpContext context, HttpServletRequest req) {
- Method m = context.getJavaMethod();
- Enablement e = enablementMap.find(m).orElse(enablementMap.find(m.getDeclaringClass()).orElse(defaultEnablement));
- return e == ALWAYS || (e == CONDITIONAL && isConditionallyEnabled(req));
- }
+ protected Builder init(BeanStore beanStore) {
+ Builder b = super.init(beanStore);
- @Override
- public boolean isDebug(RestContext context, HttpServletRequest req) {
- Class<?> c = context.getResourceClass();
- Enablement e = enablementMap.find(c).orElse(defaultEnablement);
- return e == ALWAYS || (e == CONDITIONAL && isConditionallyEnabled(req));
- }
+ DefaultSettingsMap defaultSettings = beanStore.getBean(DefaultSettingsMap.class).get();
+ RestContext.Builder builder = beanStore.getBean(RestContext.Builder.class).get();
+ ResourceSupplier resource = beanStore.getBean(ResourceSupplier.class).get();
+ VarResolver varResolver = beanStore.getBean(VarResolver.class).get();
- /**
- * Returns <jk>true</jk> if debugging is conditionally enabled on the specified request.
- *
- * <p>
- * This method only gets called when the enablement value resolves to {@link Enablement#CONDITIONAL CONDITIONAL}.
- *
- * <p>
- * Subclasses can override this method to provide their own implementation.
- * The default implementation is provided by {@link DebugEnablement.Builder#conditional(Predicate)}
- * which has a default predicate of <c><jv>x</jv> -> <js>"true"</js>.equalsIgnoreCase(<jv>x</jv>.getHeader(<js>"Debug"</js>)</c>.
- *
- * @param req The incoming HTTP request.
- * @return <jk>true</jk> if debugging is conditionally enabled on the specified request.
- */
- protected boolean isConditionallyEnabled(HttpServletRequest req) {
- return conditionalPredicate.test(req);
- }
+ // Default debug enablement if not overridden at class/method level.
+ Enablement debugDefault = defaultSettings.get(Enablement.class, "RestContext.debugDefault").orElse(builder.isDebug() ? Enablement.ALWAYS : Enablement.NEVER);
+ b.defaultEnable(debugDefault);
+
+ ClassInfo ci = ClassInfo.ofProxy(resource.get());
+
+ // Gather @Rest(debug) settings.
+ ci.forEachAnnotation(
+ Rest.class,
+ x -> true,
+ x -> {
+ String x2 = varResolver.resolve(x.debug());
+ if (! x2.isEmpty())
+ b.enable(Enablement.fromString(x2), ci.getFullName());
+ }
+ );
+
+ // Gather @RestOp(debug) settings.
+ ci.forEachPublicMethod(
+ x -> true,
+ x -> {
+ x.getAnnotationList(REST_OP_GROUP).forEachValue(
+ String.class,
+ "debug",
+ y -> true,
+ y -> {
+ String y2 = varResolver.resolve(y);
+ if (! y2.isEmpty())
+ b.enable(Enablement.fromString(y2), x.getFullName());
+ }
+ );
+ }
+ );
+
+ // Gather @Rest(debugOn) settings.
+ ci.forEachAnnotation(
+ Rest.class,
+ x -> true,
+ x -> {
+ String x2 = varResolver.resolve(x.debugOn());
+ for (Map.Entry<String,String> e : splitMap(x2, true).entrySet()) {
+ String k = e.getKey(), v = e.getValue();
+ if (v.isEmpty())
+ v = "ALWAYS";
+ if (! k.isEmpty())
+ b.enable(Enablement.fromString(v), k);
+ }
+ }
+ );
- @Override /* Object */
- public String toString() {
- return filteredMap()
- .append("defaultEnablement", defaultEnablement)
- .append("enablementMap", enablementMap)
- .append("conditionalPredicate", conditionalPredicate)
- .asString();
+ return b;
}
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
index 3eb452965..a3cfa5bad 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
@@ -13,8 +13,11 @@
package org.apache.juneau.rest.debug;
import static org.apache.juneau.Enablement.*;
+import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.internal.ObjectUtils.*;
import static org.apache.juneau.rest.HttpRuntimeException.*;
+import java.lang.reflect.Method;
import java.util.function.*;
import javax.servlet.http.*;
@@ -34,7 +37,7 @@ import org.apache.juneau.utils.*;
* <li class='extlink'>{@source}
* </ul>
*/
-public interface DebugEnablement {
+public abstract class DebugEnablement {
//-----------------------------------------------------------------------------------------------------------------
// Static
@@ -43,7 +46,11 @@ public interface DebugEnablement {
/**
* Represents no DebugEnablement.
*/
- public abstract class Void implements DebugEnablement {};
+ public abstract class Void extends DebugEnablement {
+ Void(BeanStore beanStore) {
+ super(beanStore);
+ }
+ };
/**
* Static creator.
@@ -62,7 +69,7 @@ public interface DebugEnablement {
/**
* Builder class.
*/
- public class Builder {
+ public static class Builder {
ReflectionMap.Builder<Enablement> mapBuilder;
Enablement defaultEnablement = NEVER;
@@ -214,6 +221,48 @@ public interface DebugEnablement {
// Instance
//-----------------------------------------------------------------------------------------------------------------
+ private final Enablement defaultEnablement;
+ private final ReflectionMap<Enablement> enablementMap;
+ private final Predicate<HttpServletRequest> conditionalPredicate;
+
+ /**
+ * Constructor.
+ * <p>
+ * Subclasses typically override the {@link #init(BeanStore)} method when using this constructor.
+ *
+ * @param beanStore The bean store containing injectable beans for this enablement.
+ */
+ public DebugEnablement(BeanStore beanStore) {
+ Builder builder = init(beanStore);
+ this.defaultEnablement = firstNonNull(builder.defaultEnablement, NEVER);
+ this.enablementMap = builder.mapBuilder.build();
+ this.conditionalPredicate = firstNonNull(builder.conditional, x -> "true".equalsIgnoreCase(x.getHeader("Debug")));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param builder The builder for this enablement.
+ */
+ public DebugEnablement(Builder builder) {
+ this.defaultEnablement = firstNonNull(builder.defaultEnablement, NEVER);
+ this.enablementMap = builder.mapBuilder.build();
+ this.conditionalPredicate = firstNonNull(builder.conditional, x -> "true".equalsIgnoreCase(x.getHeader("Debug")));
+
+ }
+
+ /**
+ * Initializer.
+ * <p>
+ * Subclasses should override this method to make modifications to the builder used to create this logger.
+ *
+ * @param beanStore The bean store containing injectable beans for this logger.
+ * @return A new builder object.
+ */
+ protected Builder init(BeanStore beanStore) {
+ return new Builder(beanStore);
+ }
+
/**
* Returns <jk>true</jk> if debug is enabled on the specified class and request.
*
@@ -225,7 +274,11 @@ public interface DebugEnablement {
* @param req The HTTP request.
* @return <jk>true</jk> if debug is enabled on the specified method and request.
*/
- public boolean isDebug(RestContext context, HttpServletRequest req);
+ public boolean isDebug(RestContext context, HttpServletRequest req) {
+ Class<?> c = context.getResourceClass();
+ Enablement e = enablementMap.find(c).orElse(defaultEnablement);
+ return e == ALWAYS || (e == CONDITIONAL && isConditionallyEnabled(req));
+ }
/**
* Returns <jk>true</jk> if debug is enabled on the specified method and request.
@@ -238,5 +291,36 @@ public interface DebugEnablement {
* @param req The HTTP request.
* @return <jk>true</jk> if debug is enabled on the specified method and request.
*/
- public boolean isDebug(RestOpContext context, HttpServletRequest req);
+ public boolean isDebug(RestOpContext context, HttpServletRequest req) {
+ Method m = context.getJavaMethod();
+ Enablement e = enablementMap.find(m).orElse(enablementMap.find(m.getDeclaringClass()).orElse(defaultEnablement));
+ return e == ALWAYS || (e == CONDITIONAL && isConditionallyEnabled(req));
+ }
+
+ /**
+ * Returns <jk>true</jk> if debugging is conditionally enabled on the specified request.
+ *
+ * <p>
+ * This method only gets called when the enablement value resolves to {@link Enablement#CONDITIONAL CONDITIONAL}.
+ *
+ * <p>
+ * Subclasses can override this method to provide their own implementation.
+ * The default implementation is provided by {@link DebugEnablement.Builder#conditional(Predicate)}
+ * which has a default predicate of <c><jv>x</jv> -> <js>"true"</js>.equalsIgnoreCase(<jv>x</jv>.getHeader(<js>"Debug"</js>)</c>.
+ *
+ * @param req The incoming HTTP request.
+ * @return <jk>true</jk> if debugging is conditionally enabled on the specified request.
+ */
+ protected boolean isConditionallyEnabled(HttpServletRequest req) {
+ return conditionalPredicate.test(req);
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return filteredMap()
+ .append("defaultEnablement", defaultEnablement)
+ .append("enablementMap", enablementMap)
+ .append("conditionalPredicate", conditionalPredicate)
+ .asString();
+ }
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
index ffe38a9f8..7a471c8f8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
@@ -84,7 +84,6 @@ import org.apache.juneau.rest.util.*;
* <ul class='seealso'>
* <li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#callLogger()}
* <li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugEnablement()}
- * <li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugOn(String)}
* <li class='ja'>{@link Rest#debug}
* <li class='ja'>{@link RestOp#debug}
* <li class='link'>{@doc jrs.LoggingAndDebugging}
@@ -714,7 +713,6 @@ public class CallLogger {
* @param req The HTTP request being logged.
* @return <jk>true</jk> if debug is enabled on this request.
* @see org.apache.juneau.rest.RestContext.Builder#debugEnablement()
- * @see org.apache.juneau.rest.RestContext.Builder#debugOn(String)
* @see Rest#debug()
* @see RestOp#debug()
*/