This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 23202a3 Context API refactoring.
23202a3 is described below
commit 23202a3c67a1795f79c9accf7129170a3a63bef4
Author: JamesBognar <[email protected]>
AuthorDate: Sun Sep 12 10:55:44 2021 -0400
Context API refactoring.
---
.../org/apache/juneau/cp/DefaultClassList.java | 96 +++++
.../apache/juneau/rest/mock/MockRestClient.java | 2 +-
.../java/org/apache/juneau/rest/RestContext.java | 157 +-------
.../org/apache/juneau/rest/RestContextBuilder.java | 395 ++++++++++----------
.../org/apache/juneau/rest/annotation/Rest.java | 3 +-
.../juneau/rest/annotation/RestAnnotation.java | 2 +-
.../juneau/rest/logging/BasicRestLogger.java | 7 +-
.../rest/logging/BasicTestCaptureRestLogger.java | 4 +-
.../juneau/rest/logging/BasicTestRestLogger.java | 2 +-
.../org/apache/juneau/rest/logging/RestLogger.java | 403 ++++++++++++++++++++-
.../juneau/rest/logging/RestLoggerBuilder.java | 346 ------------------
.../apache/juneau/rest/logging/RestLoggerRule.java | 262 +++++++++++++-
.../juneau/rest/logging/RestLoggerRuleBuilder.java | 280 --------------
.../apache/juneau/cp/DefaultClassList_Test.java | 41 +++
14 files changed, 1001 insertions(+), 999 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/DefaultClassList.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/DefaultClassList.java
new file mode 100644
index 0000000..81c1d5e
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/DefaultClassList.java
@@ -0,0 +1,96 @@
+//
***************************************************************************************************************************
+// * 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.cp;
+
+import static java.util.Arrays.*;
+import static org.apache.juneau.assertions.Assertions.*;
+
+import java.util.*;
+
+/**
+ * A list of default implementation classes.
+ */
+public class DefaultClassList {
+
+ /**
+ * Static creator.
+ *
+ * @return A new object.
+ */
+ public static DefaultClassList create() {
+ return new DefaultClassList();
+ }
+
+ /**
+ * Static creator.
+ *
+ * @param values Initial entries in this list.
+ * @return A new object initialized with the specified values.
+ */
+ public static DefaultClassList of(Class<?>...values) {
+ return new DefaultClassList().add(values);
+ }
+
+ private final List<Class<?>> entries;
+
+ /**
+ * Constructor.
+ */
+ protected DefaultClassList() {
+ entries = new ArrayList<>();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param value The object to copy.
+ */
+ public DefaultClassList(DefaultClassList value) {
+ entries = new ArrayList<>(value.entries);
+ }
+
+ /**
+ * Prepends the specified values to the beginning of this list.
+ *
+ * @param values The values to prepend to this list.
+ * @return This object.
+ */
+ public DefaultClassList add(Class<?>...values) {
+ entries.addAll(0, asList(values));
+ return this;
+ }
+
+ /**
+ * Returns the first class in this list which is a subclass of (or same
as) the specified type.
+ *
+ * @param type The parent type to check for.
+ * @return The first class in this list which is a subclass of the
specified type.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> Optional<Class<? extends T>> get(Class<T> type) {
+ assertArgNotNull("type", type);
+ for (Class<?> e : entries)
+ if (e != null && type.isAssignableFrom(e))
+ return Optional.of((Class<? extends T>)e);
+ return Optional.empty();
+ }
+
+ /**
+ * Creates a copy of this list.
+ *
+ * @return A copy of this list.
+ */
+ public DefaultClassList copy() {
+ return new DefaultClassList(this);
+ }
+}
diff --git
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
index ca9436f..851ef4e 100644
---
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
+++
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
@@ -282,7 +282,7 @@ public class MockRestClient extends RestClient implements
HttpClientConnection {
RestContext rc = RestContext
.create(o.getClass(), null, null)
.init(o)
-
.callLoggerDefault(BasicTestRestLogger.class)
+
.defaultClasses(BasicTestRestLogger.class)
.debugDefault(CONDITIONAL)
.build()
.postInit()
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 4699829..7fdf04f 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
@@ -19,9 +19,7 @@ import static org.apache.juneau.internal.IOUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.rest.HttpRuntimeException.*;
import static org.apache.juneau.rest.ResponseProcessor.*;
-import static org.apache.juneau.rest.logging.RestLoggingDetail.*;
import static java.util.Collections.*;
-import static java.util.logging.Level.*;
import static java.util.Optional.*;
import java.io.*;
@@ -194,9 +192,8 @@ public class RestContext extends Context {
final Charset defaultCharset;
final long maxInput;
- final BeanRef<RestLogger> callLoggerDefault;
-
final Enablement debugDefault;
+ final DefaultClassList defaultClasses;
// Lifecycle methods
private final MethodInvoker[]
@@ -246,6 +243,7 @@ public class RestContext extends Context {
resource = builder.resource;
parentContext = builder.parentContext;
rootBeanStore = builder.beanStore();
+ defaultClasses = builder.defaultClasses();
BeanStore bs = beanStore = rootBeanStore.copy().build();
beanStore
@@ -262,14 +260,10 @@ public class RestContext extends Context {
varResolver = bs.add(VarResolver.class,
builder.varResolver().bean(Messages.class, messages).build());
config = bs.add(Config.class,
builder.config().resolving(varResolver.createSession()));
responseProcessors = bs.add(ResponseProcessor[].class,
builder.responseProcessors().build().toArray());
-
- Object r = resource.get();
-
- callLoggerDefault = builder.callLoggerDefault;
debugDefault = builder.debugDefault;
+ callLogger = bs.add(RestLogger.class,
builder.callLogger().beanStore(beanStore).loggerOnce(logger).thrownStoreOnce(thrownStore).build());
- callLogger = createCallLogger(r, builder, bs, logger,
thrownStore);
- bs.addBean(RestLogger.class, callLogger);
+ Object r = resource.get();
partSerializer = createPartSerializer(r, builder, bs);
bs.addBean(HttpPartSerializer.class, partSerializer);
@@ -627,146 +621,6 @@ public class RestContext extends Context {
}
/**
- * Instantiates the call logger this REST resource.
- *
- * <p>
- * Instantiates based on the following logic:
- * <ul>
- * <li>Returns the resource class itself is an instance of
RestLogger.
- * <li>Looks for REST call logger set via any of the following:
- * <ul>
- * <li>{@link
RestContextBuilder#callLogger(Class)}/{@link
RestContextBuilder#callLogger(RestLogger)}
- * <li>{@link Rest#callLogger()}.
- * </ul>
- * <li>Looks for a static or non-static <c>createCallLogger()</>
method that returns {@link RestLogger} on the
- * resource class with any of the following arguments:
- * <ul>
- * <li>{@link RestContext}
- * <li>{@link BeanStore}
- * <li>{@link BasicFileFinder}
- * <li>Any {@doc RestInjection injected beans}.
- * </ul>
- * <li>Resolves it via the bean store registered in this context.
- * <li>Looks for {@link
RestContextBuilder#callLoggerDefault(RestLogger)}.
- * <li>Instantiates a {@link BasicFileFinder}.
- * </ul>
- *
- * <ul class='seealso'>
- * <li class='jm'>{@link RestContextBuilder#callLogger(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLogger(RestLogger)}
- * </ul>
- *
- * @param resource
- * The REST servlet or bean that this context defines.
- * @param builder
- * The builder for this object.
- * @param beanStore
- * The factory used for creating beans and retrieving injected
beans.
- * <br>Created by {@link RestContextBuilder#beanStore()}.
- * @param logger
- * The Java logger to use for logging messages.
- * @param thrownStore
- * The thrown exception statistics store.
- * @return The file finder for this REST resource.
- * @throws Exception If file finder could not be instantiated.
- */
- protected RestLogger createCallLogger(Object resource,
RestContextBuilder builder, BeanStore beanStore, Logger logger, ThrownStore
thrownStore) throws Exception {
-
- RestLogger x = null;
-
- if (resource instanceof RestLogger)
- x = (RestLogger)resource;
-
- if (x == null)
- x = builder.callLogger.value().orElse(null);
-
- if (x == null)
- x = beanStore.getBean(RestLogger.class).orElse(null);
-
- if (x == null)
- x = builder.callLoggerDefault.value().orElse(null);
-
- if (x == null)
- x = createCallLoggerBuilder(resource, builder,
beanStore, logger, thrownStore).build();
-
- x = BeanStore
- .of(beanStore, resource)
- .addBean(RestLogger.class, x)
- .beanCreateMethodFinder(RestLogger.class, resource)
- .find("createCallLogger")
- .withDefault(x)
- .run();
-
- return x;
- }
-
- /**
- * Instantiates the call logger builder for this REST resource.
- *
- * <p>
- * Allows subclasses to intercept and modify the builder used by the
{@link
#createCallLogger(Object,RestContextBuilder,BeanStore,Logger,ThrownStore)}
method.
- *
- * @param resource
- * The REST servlet or bean that this context defines.
- * @param builder
- * The builder for this object.
- * @param beanStore
- * The factory used for creating beans and retrieving injected
beans.
- * <br>Created by {@link RestContextBuilder#beanStore()}.
- * @param logger
- * The Java logger to use for logging messages.
- * @param thrownStore
- * The thrown exception statistics store.
- * @return The call logger builder for this REST resource.
- * @throws Exception If call logger builder could not be instantiated.
- */
- protected RestLoggerBuilder createCallLoggerBuilder(Object resource,
RestContextBuilder builder, BeanStore beanStore, Logger logger, ThrownStore
thrownStore) throws Exception {
-
- Class<? extends RestLogger> c =
builder.callLogger.type().orElse(null);
-
- if (c == null)
- c = builder.callLoggerDefault.type().orElse(null);
-
- RestLoggerBuilder x = RestLogger
- .create()
- .beanStore(beanStore)
- .implClass(c)
- .normalRules( // Rules when debugging is not enabled.
- RestLoggerRule.create() // Log 500+ errors
with status-line and header information.
- .statusFilter(a -> a >= 500)
- .level(SEVERE)
- .requestDetail(HEADER)
- .responseDetail(HEADER)
- .build(),
- RestLoggerRule.create() // Log 400-500 errors
with just status-line information.
- .statusFilter(a -> a >= 400)
- .level(WARNING)
- .requestDetail(STATUS_LINE)
- .responseDetail(STATUS_LINE)
- .build()
- )
- .debugRules( // Rules when debugging is enabled.
- RestLoggerRule.create() // Log everything with
full details.
- .level(SEVERE)
- .requestDetail(ENTITY)
- .responseDetail(ENTITY)
- .build()
- )
- .logger(logger)
- .thrownStore(thrownStore);
-
- x = BeanStore
- .of(beanStore, resource)
- .addBean(RestLoggerBuilder.class, x)
- .beanCreateMethodFinder(RestLoggerBuilder.class,
resource)
- .find("createCallLoggerBuilder")
- .withDefault(x)
- .run();
-
- return x;
- }
-
- /**
* Instantiates the HTTP part serializer for this REST resource.
*
* <p>
@@ -1916,8 +1770,7 @@ public class RestContext extends Context {
* Returns the call logger to use for this resource.
*
* <ul class='seealso'>
- * <li class='jm'>{@link RestContextBuilder#callLogger(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLogger(RestLogger)}
+ * <li class='jm'>{@link RestContextBuilder#callLogger()}
* </ul>
*
* @return
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index b0518bc..0b56553 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -20,9 +20,11 @@ import static org.apache.juneau.internal.ObjectUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.parser.Parser.*;
import static org.apache.juneau.rest.HttpRuntimeException.*;
+import static org.apache.juneau.rest.logging.RestLoggingDetail.*;
import static org.apache.juneau.serializer.Serializer.*;
import static java.util.Arrays.*;
import static java.util.Optional.*;
+import static java.util.logging.Level.*;
import java.lang.annotation.*;
import java.lang.reflect.Method;
@@ -119,6 +121,8 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
final ServletConfig inner;
final Class<?> resourceClass;
final RestContext parentContext;
+
+ private DefaultClassList defaultClasses;
private BeanStore beanStore;
private Config config;
private VarResolver.Builder varResolver;
@@ -127,6 +131,7 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
private MethodExecStore.Builder methodExecStore;
private Messages.Builder messages;
private ResponseProcessorList.Builder responseProcessors;
+ private RestLogger.Builder callLogger;
String
allowedHeaderParams = env("RestContext.allowedHeaderParams",
"Accept,Content-Type"),
@@ -150,8 +155,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
Class<? extends RestOperations> operationsClass = RestOperations.class;
BeanRef<SwaggerProvider> swaggerProvider =
BeanRef.of(SwaggerProvider.class);
- BeanRef<RestLogger> callLoggerDefault = BeanRef.of(RestLogger.class);
- BeanRef<RestLogger> callLogger = BeanRef.of(RestLogger.class);
BeanRef<DebugEnablement> debugEnablement =
BeanRef.of(DebugEnablement.class);
BeanRef<StaticFiles> staticFiles = BeanRef.of(StaticFiles.class);
BeanRef<StaticFiles> staticFilesDefault = BeanRef.of(StaticFiles.class);
@@ -233,10 +236,12 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
// Pass-through default values.
if (parentContext != null) {
- callLoggerDefault =
parentContext.callLoggerDefault;
debugDefault = parentContext.debugDefault;
staticFilesDefault.value(parentContext.staticFilesDefault);
fileFinderDefault.value(parentContext.fileFinderDefault);
+ defaultClasses =
parentContext.defaultClasses.copy();
+ } else {
+ defaultClasses = DefaultClassList.create();
}
beanStore = createBeanStore(resourceClass,
parentContext)
@@ -351,6 +356,29 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
+ * Returns access to the default classes list.
+ *
+ * <p>
+ * This defines the implementation classes for a variety of bean types.
+ *
+ * @return The default classes list for this builder.
+ */
+ public DefaultClassList defaultClasses() {
+ return defaultClasses;
+ }
+
+ /**
+ * Adds default implementation classes to use.
+ *
+ * @param values The values to add to the list of default classes.
+ * @return This object.
+ */
+ public RestContextBuilder defaultClasses(Class<?>...values) {
+ defaultClasses().add(values);
+ return this;
+ }
+
+ /**
* Returns access to the bean store being used by this builder.
*
* <p>
@@ -489,18 +517,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
- * Sets the variable resolver for this builder.
- *
- * @param value The new variable resolver.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder varResolver(VarResolver.Builder value) {
- varResolver = value;
- return this;
- }
-
- /**
* Creates the var resolver builder.
*
* <p>
@@ -804,18 +820,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
- * Sets the builder for the {@link ThrownStore} object in the REST
context.
- *
- * @param value The builder for the {@link ThrownStore} object in the
REST context.
- * @return This object.
- * @throws RuntimeException If {@link #init(Object)} has not been
called.
- */
- public final RestContextBuilder thrownStore(ThrownStore value) {
- thrownStore().impl(value);
- return this;
- }
-
- /**
* Instantiates the thrown exception store for this REST resource.
*
* <p>
@@ -866,6 +870,9 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
);
}
+ // Specify the implementation class if its set as a default.
+ defaultClasses().get(ThrownStore.class).ifPresent(x ->
v.get().implClass(x));
+
BeanStore
.of(beanStore, r)
.addBean(ThrownStore.Builder.class, v.get())
@@ -889,18 +896,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
- * Sets the builder for the {@link MethodExecStore} object in the REST
context.
- *
- * @param value The builder for the {@link MethodExecStore} object in
the REST context.
- * @return This object.
- * @throws RuntimeException If {@link #init(Object)} has not been
called.
- */
- public final RestContextBuilder methodExecStore(MethodExecStore value) {
- methodExecStore().impl(value);
- return this;
- }
-
- /**
* Instantiates the method execution statistics store for this REST
resource.
*
* @param beanStore
@@ -932,6 +927,9 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
);
}
+ // Specify the implementation class if its set as a default.
+ defaultClasses().get(MethodExecStore.class).ifPresent(x ->
v.get().implClass(x));
+
BeanStore
.of(beanStore, r)
.addBean(MethodExecStore.Builder.class, v.get())
@@ -955,18 +953,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
- * Sets the builder for the {@link MethodExecStore} object in the REST
context.
- *
- * @param value The builder for the {@link MethodExecStore} object in
the REST context.
- * @return This object.
- * @throws RuntimeException If {@link #init(Object)} has not been
called.
- */
- public final RestContextBuilder messages(Messages value) {
- messages().impl(value);
- return this;
- }
-
- /**
* Instantiates the messages for this REST object.
*
* <p>
@@ -1171,18 +1157,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
- * Sets the builder for the {@link ResponseProcessorList} object in the
REST context.
- *
- * @param value The builder for the {@link ResponseProcessorList}
object in the REST context.
- * @return This object.
- * @throws RuntimeException If {@link #init(Object)} has not been
called.
- */
- public final RestContextBuilder
responseProcessors(ResponseProcessorList value) {
- responseProcessors().impl(value);
- return this;
- }
-
- /**
* Instantiates the response handlers for this REST resource.
*
* <p>
@@ -1257,7 +1231,170 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
return v.get();
}
+ /**
+ * Returns the builder for the {@link RestLogger} object in the REST
context.
+ *
+ * <p>
+ * Specifies the logger to use for logging of HTTP requests and
responses.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Our customized logger.</jc>
+ * <jk>public class</jk> MyLogger <jk>extends</jk> BasicRestLogger
{
+ *
+ * <ja>@Override</ja>
+ * <jk>protected void</jk> log(Level
<jv>level</jv>, String <jv>msg</jv>, Throwable <jv>e</jv>) {
+ * <jc>// Handle logging ourselves.</jc>
+ * }
+ * }
+ *
+ * <jc>// Option #1 - Registered via annotation resolving to a
config file setting with default value.</jc>
+ * <ja>@Rest</ja>(callLogger=MyLogger.<jk>class</jk>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Registered via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ *
<jv>builder</jv>.callLogger(MyLogger.<jk>class</jk>);
+ * }
+ *
+ * <jc>// Option #3 - Registered via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
<jv>builder</jv>.callLogger(MyLogger.<jk>class</jk>);
+ * }
+ * }
+ * </p>
+ *
+ * <ul class='notes'>
+ * <li>
+ * The default call logger if not specified is {@link
BasicRestLogger}.
+ * <li>
+ * The resource class itself will be used if it implements
the {@link RestLogger} interface and not
+ * explicitly overridden via this annotation.
+ * <li>
+ * When defined as a class, the implementation must have
one of the following constructors:
+ * <ul>
+ * <li><code><jk>public</jk> T(RestContext)</code>
+ * <li><code><jk>public</jk> T()</code>
+ * <li><code><jk>public static</jk> T
<jsm>create</jsm>(RestContext)</code>
+ * <li><code><jk>public static</jk> T
<jsm>create</jsm>()</code>
+ * </ul>
+ * <li>
+ * Inner classes of the REST resource class are allowed.
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * <li class='link'>{@doc RestLoggingAndDebugging}
+ * <li class='ja'>{@link Rest#callLogger()}
+ * </ul>
+ *
+ * @return The builder for the {@link RestLogger} object in the REST
context.
+ * @throws RuntimeException If {@link #init(Object)} has not been
called.
+ */
+ public final RestLogger.Builder callLogger() {
+ if (callLogger == null)
+ callLogger = createCallLogger(beanStore(), resource());
+ return callLogger;
+ }
+ /**
+ * Instantiates the call logger this REST resource.
+ *
+ * <p>
+ * Instantiates based on the following logic:
+ * <ul>
+ * <li>Returns the resource class itself is an instance of
RestLogger.
+ * <li>Looks for REST call logger set via any of the following:
+ * <ul>
+ * <li>{@link RestContextBuilder#callLogger()}
+ * <li>{@link Rest#callLogger()}.
+ * </ul>
+ * <li>Looks for a static or non-static <c>createCallLogger()</>
method that returns {@link RestLogger} on the
+ * resource class with any of the following arguments:
+ * <ul>
+ * <li>{@link RestContext}
+ * <li>{@link BeanStore}
+ * <li>{@link BasicFileFinder}
+ * <li>Any {@doc RestInjection injected beans}.
+ * </ul>
+ * <li>Resolves it via the bean store registered in this context.
+ * <li>Instantiates a {@link BasicFileFinder}.
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * <li class='jm'>{@link RestContextBuilder#callLogger()}
+ * </ul>
+ *
+ * @param beanStore
+ * The factory used for creating beans and retrieving injected
beans.
+ * @param resource
+ * The REST servlet or bean that this context defines.
+ * @return The call logger builder for this REST resource.
+ */
+ protected RestLogger.Builder createCallLogger(BeanStore beanStore,
Supplier<?> resource) {
+
+ Value<RestLogger.Builder> v = Value.empty();
+ Object r = resource.get();
+
+ beanStore.getBean(RestLogger.Builder.class).map(x ->
x.copy()).ifPresent(x-> v.set(x));
+
+ BeanStore
+ .of(beanStore, r)
+ .addBean(RestLogger.Builder.class, v.get())
+ .beanCreateMethodFinder(RestLogger.Builder.class,
resource)
+ .find("createCallLogger")
+ .execute()
+ .ifPresent(x -> v.set(x));
+
+ if (v.isEmpty()) {
+ v.set(
+ RestLogger
+ .create()
+ .beanStore(beanStore)
+ .normalRules( // Rules when debugging
is not enabled.
+ RestLoggerRule.create() // Log
500+ errors with status-line and header information.
+ .statusFilter(a -> a >=
500)
+ .level(SEVERE)
+ .requestDetail(HEADER)
+ .responseDetail(HEADER)
+ .build(),
+ RestLoggerRule.create() // Log
400-500 errors with just status-line information.
+ .statusFilter(a -> a >=
400)
+ .level(WARNING)
+
.requestDetail(STATUS_LINE)
+
.responseDetail(STATUS_LINE)
+ .build()
+ )
+ .debugRules( // Rules when debugging
is enabled.
+ RestLoggerRule.create() // Log
everything with full details.
+ .level(SEVERE)
+ .requestDetail(ENTITY)
+ .responseDetail(ENTITY)
+ .build()
+ )
+ );
+ }
+
+ if (r instanceof RestLogger)
+ v.get().impl((RestLogger)r);
+
+ beanStore.getBean(RestLogger.class).ifPresent(x->
v.get().impl(x));
+
+ // Specify the implementation class if its set as a default.
+ defaultClasses().get(RestLogger.class).ifPresent(x ->
v.get().implClass(x));
+
+ BeanStore
+ .of(beanStore, r)
+ .addBean(RestLogger.Builder.class, v.get())
+ .beanCreateMethodFinder(RestLogger.class, resource)
+ .find("createCallLogger")
+ .execute()
+ .ifPresent(x -> v.get().impl(x));
+
+ return v.get();
+ }
//----------------------------------------------------------------------------------------------------
// Methods that give access to the config file, var resolver, and
properties.
@@ -1562,138 +1699,6 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
}
/**
- * REST call logger.
- *
- * <p>
- * Specifies the logger to use for logging of HTTP requests and
responses.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Our customized logger.</jc>
- * <jk>public class</jk> MyLogger <jk>extends</jk> BasicRestLogger
{
- *
- * <ja>@Override</ja>
- * <jk>protected void</jk> log(Level
<jv>level</jv>, String <jv>msg</jv>, Throwable <jv>e</jv>) {
- * <jc>// Handle logging ourselves.</jc>
- * }
- * }
- *
- * <jc>// Option #1 - Registered via annotation resolving to a
config file setting with default value.</jc>
- * <ja>@Rest</ja>(callLogger=MyLogger.<jk>class</jk>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Registered via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.callLogger(MyLogger.<jk>class</jk>);
- * }
- *
- * <jc>// Option #3 - Registered via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
<jv>builder</jv>.callLogger(MyLogger.<jk>class</jk>);
- * }
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * The default call logger if not specified is {@link
BasicRestLogger} unless overwritten by {@link
RestContextBuilder#callLoggerDefault(RestLogger)}.
- * <li>
- * The resource class itself will be used if it implements
the {@link RestLogger} interface and not
- * explicitly overridden via this annotation.
- * <li>
- * When defined as a class, the implementation must have
one of the following constructors:
- * <ul>
- * <li><code><jk>public</jk> T(RestContext)</code>
- * <li><code><jk>public</jk> T()</code>
- * <li><code><jk>public static</jk> T
<jsm>create</jsm>(RestContext)</code>
- * <li><code><jk>public static</jk> T
<jsm>create</jsm>()</code>
- * </ul>
- * <li>
- * Inner classes of the REST resource class are allowed.
- * </ul>
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc RestLoggingAndDebugging}
- * <li class='ja'>{@link Rest#callLogger()}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link BasicRestLogger}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder callLogger(Class<? extends RestLogger> value)
{
- callLogger.type(value);
- return this;
- }
-
- /**
- * REST call logger.
- *
- * <p>
- * Same as {@link #callLogger(Class)} but specifies an
already-instantiated call logger.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc RestLoggingAndDebugging}
- * <li class='ja'>{@link Rest#callLogger()}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link BasicRestLogger}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder callLogger(RestLogger value) {
- callLogger.value(value);
- return this;
- }
-
- /**
- * Default REST call logger.
- *
- * <p>
- * The default logger to use if one is not specified.
- *
- * <p>
- * This logger is inherited by child resources if not specified on
those resources.
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link BasicRestLogger}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder callLoggerDefault(Class<? extends RestLogger>
value) {
- callLoggerDefault.type(value);
- return this;
- }
-
- /**
- * Default REST call logger.
- *
- * <p>
- * The default logger to use if one is not specified.
- *
- * <p>
- * This logger is inherited by child resources if not specified on
those resources.
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link BasicRestLogger}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder callLoggerDefault(RestLogger value) {
- callLoggerDefault.value(value);
- return this;
- }
-
- /**
* Child REST resources.
*
* <p>
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 4765ad2..c659545 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
@@ -198,8 +198,7 @@ public @interface Rest {
* </ul>
*
* <ul class='seealso'>
- * <li class='jm'>{@link RestContextBuilder#callLogger(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLogger(RestLogger)}
+ * <li class='jm'>{@link RestContextBuilder#callLogger()}
* <li class='link'>{@doc RestLoggingAndDebugging}
* </ul>
*/
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 55157e4..2219373 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
@@ -1072,7 +1072,7 @@ public class RestAnnotation {
type(a.staticFiles()).ifPresent(x -> b.staticFiles(x));
string(a.path()).ifPresent(x -> b.path(x));
string(a.clientVersionHeader()).ifPresent(x ->
b.clientVersionHeader(x));
- type(a.callLogger()).ifPresent(x -> b.callLogger(x));
+ type(a.callLogger()).ifPresent(x ->
b.callLogger().implClass(x));
type(a.swaggerProvider()).ifPresent(x ->
b.swaggerProvider(x));
type(a.restOpContextClass()).ifPresent(x ->
b.restOpContextClass(x));
type(a.restChildrenClass()).ifPresent(x ->
b.restChildrenClass(x));
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
index d601e53..373e416 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
@@ -82,10 +82,7 @@ import org.apache.juneau.rest.util.*;
* </p>
*
* <ul class='seealso'>
- * <li class='jm'>{@link RestContextBuilder#callLogger(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLogger(RestLogger)}
- * <li class='jm'>{@link RestContextBuilder#callLoggerDefault(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLoggerDefault(RestLogger)}
+ * <li class='jm'>{@link RestContextBuilder#callLogger()}
* <li class='jm'>{@link RestContextBuilder#debug(Enablement)}
* <li class='jm'>{@link RestContextBuilder#debugOn(String)}
* <li class='ja'>{@link Rest#debug}
@@ -110,7 +107,7 @@ public class BasicRestLogger implements RestLogger {
*
* @param builder The builder object.
*/
- public BasicRestLogger(RestLoggerBuilder builder) {
+ public BasicRestLogger(RestLogger.Builder builder) {
this.logger = firstNonNull(builder.logger,
Logger.getLogger(getProperty(String.class, SP_logger, "global")));
this.thrownStore = builder.thrownStore;
this.normalRules = builder.normalRules.toArray(new
RestLoggerRule[builder.normalRules.size()]);
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
index 99b80c1..ec70a16 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
@@ -74,7 +74,7 @@ public class BasicTestCaptureRestLogger extends
BasicRestLogger {
*
* @param builder The settings to use for this logger.
*/
- public BasicTestCaptureRestLogger(RestLoggerBuilder builder) {
+ public BasicTestCaptureRestLogger(RestLogger.Builder builder) {
super(builder);
}
@@ -87,7 +87,7 @@ public class BasicTestCaptureRestLogger extends
BasicRestLogger {
super(builder());
}
- private static RestLoggerBuilder builder() {
+ private static RestLogger.Builder builder() {
return RestLogger.create()
.normalRules( // Rules when debugging is not enabled.
RestLoggerRule.create() // Log 500+ errors
with status-line and header information.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
index e4836d2..1a88e62 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
@@ -58,7 +58,7 @@ public class BasicTestRestLogger extends BasicRestLogger {
super(builder().logger(context.getLogger()).thrownStore(context.getThrownStore()));
}
- private static RestLoggerBuilder builder() {
+ private static RestLogger.Builder builder() {
return RestLogger.create()
.normalRules( // Rules when debugging is not enabled.
RestLoggerRule.create() // Log 500+ errors
with status-line and header information.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
index ac376e4..625febe 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
@@ -12,12 +12,21 @@
//
***************************************************************************************************************************
package org.apache.juneau.rest.logging;
+import static org.apache.juneau.Enablement.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.rest.HttpRuntimeException.*;
+
+import java.util.*;
import java.util.function.*;
import java.util.logging.*;
import javax.servlet.http.*;
import org.apache.juneau.*;
+import org.apache.juneau.collections.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.mstat.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
@@ -25,7 +34,7 @@ import org.apache.juneau.rest.annotation.*;
* Interface class used for logging HTTP requests.
*
* <p>
- * The {@link RestLoggerBuilder#implClass(Class)} method has been provided for
easy extension of this class.
+ * The {@link Builder#implClass(Class)} method has been provided for easy
extension of this class.
*
* <p>
* The following default implementations are also provided:
@@ -37,10 +46,7 @@ import org.apache.juneau.rest.annotation.*;
* </ul>
*
* <ul class='seealso'>
- * <li class='jm'>{@link RestContextBuilder#callLogger(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLogger(RestLogger)}
- * <li class='jm'>{@link RestContextBuilder#callLoggerDefault(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLoggerDefault(RestLogger)}
+ * <li class='jm'>{@link RestContextBuilder#callLogger()}
* <li class='jm'>{@link RestContextBuilder#debug(Enablement)}
* <li class='jm'>{@link RestContextBuilder#debugOn(String)}
* <li class='ja'>{@link Rest#debug}
@@ -71,7 +77,7 @@ public interface RestLogger {
* <ul>
* <li>{@link Enablement#ALWAYS "ALWAYS"} (default) - Logging is
enabled.
* <li>{@link Enablement#NEVER "NEVER"} - Logging is disabled.
- * <li>{@link Enablement#CONDITIONAL "CONDITIONALLY"} - Logging is
enabled if it passes the {@link RestLoggerBuilder#enabledTest(Predicate)} test.
+ * <li>{@link Enablement#CONDITIONAL "CONDITIONALLY"} - Logging is
enabled if it passes the {@link Builder#enabledTest(Predicate)} test.
* </ul>
*/
public static final String SP_enabled = "juneau.restLogger.enabled";
@@ -128,8 +134,389 @@ public interface RestLogger {
*
* @return A new builder for this object.
*/
- public static RestLoggerBuilder create() {
- return new RestLoggerBuilder();
+ public static Builder create() {
+ return new Builder();
+ }
+
+ /**
+ * The builder for this object.
+ */
+ public static class Builder {
+
+ Logger logger;
+ ThrownStore thrownStore;
+ List<RestLoggerRule> normalRules = AList.create(), debugRules =
AList.create();
+ Enablement enabled;
+ Predicate<HttpServletRequest> enabledTest;
+ RestLoggingDetail requestDetail, responseDetail;
+ Level level;
+ BeanStore beanStore;
+ Class<? extends RestLogger> implClass;
+ RestLogger impl;
+
+ /**
+ * Constructor.
+ */
+ protected Builder() {}
+
+ /**
+ * Copy constuctor.
+ *
+ * @param copyFrom The builder to copy.
+ */
+ protected Builder(Builder copyFrom) {
+ logger = copyFrom.logger;
+ thrownStore = copyFrom.thrownStore;
+ normalRules =
AList.<RestLoggerRule>create().append(copyFrom.normalRules);
+ debugRules =
AList.<RestLoggerRule>create().append(copyFrom.debugRules);
+ enabled = copyFrom.enabled;
+ enabledTest = copyFrom.enabledTest;
+ requestDetail = copyFrom.requestDetail;
+ responseDetail = copyFrom.responseDetail;
+ level = copyFrom.level;
+ beanStore = copyFrom.beanStore;
+ implClass = copyFrom.implClass;
+ impl = copyFrom.impl;
+ }
+
+ /**
+ * Creates a new {@link RestLogger} object from this builder.
+ *
+ * <p>
+ * Instantiates an instance of the {@link #implClass(Class)
implementation class} or
+ * else {@link BasicRestLogger} if implementation class was not
specified.
+ *
+ * @return A new {@link RestLogger} object.
+ */
+ public RestLogger build() {
+ try {
+ if (impl != null)
+ return impl;
+ Class<? extends RestLogger> ic =
isConcrete(implClass) ? implClass : BasicRestLogger.class;
+ return
BeanStore.of(beanStore).addBeans(Builder.class, this).createBean(ic);
+ } catch (Exception e) {
+ throw toHttpException(e,
InternalServerError.class);
+ }
+ }
+
+ /**
+ * Specifies the bean store to use for instantiating the {@link
RestLogger} object.
+ *
+ * @param value The new value for this setting.
+ * @return This object.
+ */
+ public Builder beanStore(BeanStore value) {
+ beanStore = value;
+ return this;
+ }
+
+ /**
+ * Specifies a subclass of {@link RestLogger} to create when
the {@link #build()} method is called.
+ *
+ * @param value The new value for this setting.
+ * @return This object.
+ */
+ public Builder implClass(Class<? extends RestLogger> value) {
+ implClass = value;
+ return this;
+ }
+
+ /**
+ * Specifies the logger to use for logging the request.
+ *
+ * <p>
+ * If not specified, the logger name is determined in the
following order:
+ * <ol>
+ * <li><js>{@link RestLogger#SP_logger
"juneau.restLogger.logger"} system property.
+ * <li><js>{@link RestLogger#SP_logger
"JUNEAU_RESTLOGGER_LOGGER"} environment variable.
+ * <li><js>"global"</js>.
+ * </ol>
+ *
+ * <p>
+ * The {@link BasicRestLogger#getLogger()} method can also be
overridden to provide different logic.
+ *
+ * @param value
+ * The logger to use for logging the request.
+ * @return This object.
+ */
+ public Builder logger(Logger value) {
+ logger = value;
+ return this;
+ }
+
+ /**
+ * Specifies the logger to use for logging the request.
+ *
+ * <p>
+ * Shortcut for calling
<c>logger(Logger.<jsm>getLogger</jsm>(value))</c>.
+ *
+ * <p>
+ * If not specified, the logger name is determined in the
following order:
+ * <ol>
+ * <li><js>{@link RestLogger#SP_logger
"juneau.restLogger.logger"} system property.
+ * <li><js>{@link RestLogger#SP_logger
"JUNEAU_RESTLOGGER_LOGGER"} environment variable.
+ * <li><js>"global"</js>.
+ * </ol>
+ *
+ * <p>
+ * The {@link BasicRestLogger#getLogger()} method can also be
overridden to provide different logic.
+ *
+ * @param value
+ * The logger to use for logging the request.
+ * @return This object.
+ */
+ public Builder logger(String value) {
+ logger = value == null ? null :Logger.getLogger(value);
+ return this;
+ }
+
+ /**
+ * Same as {@link #logger(Logger)} but only sets the value if
it's currently <jk>null</jk>.
+ *
+ * @param value The logger to use for logging the request.
+ * @return This object.
+ */
+ public Builder loggerOnce(Logger value) {
+ if (logger == null)
+ logger = value;
+ return this;
+ }
+
+ /**
+ * Specifies the thrown exception store to use for getting
stack trace information (hash IDs and occurrence counts).
+ *
+ * @param value
+ * The stack trace store.
+ * <br>If <jk>null</jk>, stack trace information will not
be logged.
+ * @return This object.
+ */
+ public Builder thrownStore(ThrownStore value) {
+ thrownStore = value;
+ return this;
+ }
+
+ /**
+ * Same as {@link #thrownStore(ThrownStore)} but only sets the
value if it's currently <jk>null</jk>.
+ *
+ * @param value
+ * The stack trace store.
+ * <br>If <jk>null</jk>, stack trace information will not
be logged.
+ * @return This object.
+ */
+ public Builder thrownStoreOnce(ThrownStore value) {
+ if (thrownStore == null)
+ thrownStore = value;
+ return this;
+ }
+ /**
+ * Specifies the default logging enablement setting.
+ *
+ * <p>
+ * This specifies the default logging enablement value if not
set on the first matched rule or if no rules match.
+ *
+ * <p>
+ * The possible values are:
+ * <ul>
+ * <li>{@link Enablement#ALWAYS ALWAYS} (default) -
Logging is enabled.
+ * <li>{@link Enablement#NEVER NEVER} - Logging is
disabled.
+ * <li>{@link Enablement#CONDITIONAL CONDITIONALLY} -
Logging is enabled if it passes the {@link #enabledTest(Predicate)} test.
+ * </ul>
+ *
+ * <p>
+ * If not specified, the setting is determined via the
following:
+ * <ul>
+ * <li><js>{@link RestLogger#SP_enabled
"juneau.restLogger.enabled"} system property.
+ * <li><js>{@link RestLogger#SP_enabled
"JUNEAU_RESTLOGGER_ENABLED"} environment variable.
+ * <li><js>"ALWAYS"</js>.
+ * </ul>
+ *
+ * <p>
+ * @param value
+ * The default enablement flag value. Can be
<jk>null</jk> to use the default.
+ * @return This object.
+ */
+ public Builder enabled(Enablement value) {
+ enabled = value;
+ return this;
+ }
+
+ /**
+ * Specifies the default logging enablement test predicate.
+ *
+ * <p>
+ * This specifies the default logging enablement test if not
set on the first matched rule or if no rules match.
+ *
+ * <p>
+ * This setting has no effect if the enablement setting is not
{@link Enablement#CONDITIONAL CONDITIONALLY}.
+ *
+ * <p>
+ * The default if not specified is <c><jv>x</jv> ->
<jk>false</jk></c> (never log).
+ *
+ * @param value
+ * The default enablement flag value. Can be
<jk>null</jk> to use the default.
+ * @return This object.
+ */
+ public Builder enabledTest(Predicate<HttpServletRequest> value)
{
+ enabledTest = value;
+ return this;
+ }
+
+ /**
+ * Shortcut for calling <c>enabled(<jsf>NEVER</jsf>)</c>.
+ *
+ * @return This object.
+ */
+ public Builder disabled() {
+ return enabled(NEVER);
+ }
+
+ /**
+ * The default level of detail to log on a request.
+ *
+ * <p>
+ * This specifies the default level of request detail if not
set on the first matched rule or if no rules match.
+ *
+ * <p>
+ * The possible values are:
+ * <ul>
+ * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} -
Log only the status line.
+ * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the
status line and headers.
+ * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the
status line and headers and body if available.
+ * </ul>
+ *
+ * <p>
+ * If not specified, the setting is determined via the
following:
+ * <ul>
+ * <li><js>{@link RestLogger#SP_requestDetail
"juneau.restLogger.requestDetail"} system property.
+ * <li><js>{@link RestLogger#SP_requestDetail
"JUNEAU_RESTLOGGER_requestDetail"} environment variable.
+ * <li><js>"STATUS_LINE"</js>.
+ * </ul>
+ *
+ * @param value
+ * The new value for this property, or <jk>null</jk> to
use the default.
+ * @return This object.
+ */
+ public Builder requestDetail(RestLoggingDetail value) {
+ requestDetail = value;
+ return this;
+ }
+
+ /**
+ * The default level of detail to log on a response.
+ *
+ * <p>
+ * This specifies the default level of response detail if not
set on the first matched rule or if no rules match.
+ *
+ * <p>
+ * The possible values are:
+ * <ul>
+ * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} -
Log only the status line.
+ * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the
status line and headers.
+ * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the
status line and headers and body if available.
+ * </ul>
+ *
+ * <p>
+ * If not specified, the setting is determined via the
following:
+ * <ul>
+ * <li><js>{@link RestLogger#SP_responseDetail
"juneau.restLogger.responseDetail"} system property.
+ * <li><js>{@link RestLogger#SP_responseDetail
"JUNEAU_RESTLOGGER_responseDetail"} environment variable.
+ * <li><js>"STATUS_LINE"</js>.
+ * </ul>
+ *
+ * @param value
+ * The new value for this property, or <jk>null</jk> to
use the default.
+ * @return This object.
+ */
+ public Builder responseDetail(RestLoggingDetail value) {
+ responseDetail = value;
+ return this;
+ }
+
+ /**
+ * The default logging level to use for logging the
request/response.
+ *
+ * <p>
+ * This specifies the default logging level if not set on the
first matched rule or if no rules match.
+ *
+ * <p>
+ * If not specified, the setting is determined via the
following:
+ * <ul>
+ * <li><js>{@link RestLogger#SP_level
"juneau.restLogger.level"} system property.
+ * <li><js>{@link RestLogger#SP_level
"JUNEAU_RESTLOGGER_level"} environment variable.
+ * <li><js>"OFF"</js>.
+ * </ul>
+ *
+ * @param value
+ * The new value for this property, or <jk>null</jk> to
use the default value.
+ * @return This object.
+ */
+ public Builder level(Level value) {
+ level = value;
+ return this;
+ }
+
+ /**
+ * Adds logging rules to use when debug mode is not enabled.
+ *
+ * <p>
+ * Logging rules are matched in the order they are added. The
first to match wins.
+ *
+ * @param values The logging rules to add to the list of rules.
+ * @return This object.
+ */
+ public Builder normalRules(RestLoggerRule...values) {
+ for (RestLoggerRule rule : values)
+ normalRules.add(rule);
+ return this;
+ }
+
+ /**
+ * Adds logging rules to use when debug mode is enabled.
+ *
+ * <p>
+ * Logging rules are matched in the order they are added. The
first to match wins.
+ *
+ * @param values The logging rules to add to the list of rules.
+ * @return This object.
+ */
+ public Builder debugRules(RestLoggerRule...values) {
+ for (RestLoggerRule rule : values)
+ debugRules.add(rule);
+ return this;
+ }
+
+ /**
+ * Shortcut for adding the same rules as normal and debug rules.
+ *
+ * <p>
+ * Logging rules are matched in the order they are added. The
first to match wins.
+ *
+ * @param values The logging rules to add to the list of rules.
+ * @return This object.
+ */
+ public Builder rules(RestLoggerRule...values) {
+ return normalRules(values).debugRules(values);
+ }
+
+ /**
+ * Specifies an already-instantiated bean for the {@link
#build()} method to return.
+ *
+ * @param value The value for this setting.
+ * @return This object.
+ */
+ public Builder impl(RestLogger value) {
+ impl = value;
+ return this;
+ }
+
+ /**
+ * Creates a copy of this builder.
+ *
+ * @return A copy of this builder.
+ */
+ public Builder copy() {
+ return new Builder(this);
+ }
}
/**
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
deleted file mode 100644
index b78afd2..0000000
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
+++ /dev/null
@@ -1,346 +0,0 @@
-//
***************************************************************************************************************************
-// * 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.logging;
-
-import static org.apache.juneau.Enablement.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.rest.HttpRuntimeException.*;
-
-import java.util.*;
-import java.util.function.*;
-import java.util.logging.*;
-
-import javax.servlet.http.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.cp.*;
-import org.apache.juneau.http.response.*;
-import org.apache.juneau.mstat.*;
-
-/**
- * Builder class for {@link BasicRestLogger} objects.
- */
-public class RestLoggerBuilder {
-
- Logger logger;
- ThrownStore thrownStore;
- List<RestLoggerRule> normalRules = AList.create(), debugRules =
AList.create();
- Enablement enabled;
- Predicate<HttpServletRequest> enabledTest;
- RestLoggingDetail requestDetail, responseDetail;
- Level level;
- BeanStore beanStore;
- Class<? extends RestLogger> implClass;
-
- /**
- * Creates a new {@link RestLogger} object from this builder.
- *
- * <p>
- * Instantiates an instance of the {@link #implClass(Class)
implementation class} or
- * else {@link BasicRestLogger} if implementation class was not
specified.
- *
- * @return A new {@link RestLogger} object.
- */
- public RestLogger build() {
- try {
- Class<? extends RestLogger> ic = isConcrete(implClass)
? implClass : getDefaultImplClass();
- return
BeanStore.of(beanStore).addBeans(RestLoggerBuilder.class, this).createBean(ic);
- } catch (Exception e) {
- throw toHttpException(e, InternalServerError.class);
- }
- }
-
- /**
- * Specifies the default implementation class if not specified via
{@link #implClass(Class)}.
- *
- * @return The default implementation class if not specified via {@link
#implClass(Class)}.
- */
- protected Class<? extends RestLogger> getDefaultImplClass() {
- return BasicRestLogger.class;
- }
-
- /**
- * Specifies the bean store to use for instantiating the {@link
RestLogger} object.
- *
- * @param value The new value for this setting.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder beanStore(BeanStore value) {
- this.beanStore = value;
- return this;
- }
-
- /**
- * Specifies a subclass of {@link RestLogger} to create when the {@link
#build()} method is called.
- *
- * @param value The new value for this setting.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder implClass(Class<? extends RestLogger> value) {
- this.implClass = value;
- return this;
- }
-
- /**
- * Specifies the logger to use for logging the request.
- *
- * <p>
- * If not specified, the logger name is determined in the following
order:
- * <ol>
- * <li><js>{@link RestLogger#SP_logger "juneau.restLogger.logger"}
system property.
- * <li><js>{@link RestLogger#SP_logger "JUNEAU_RESTLOGGER_LOGGER"}
environment variable.
- * <li><js>"global"</js>.
- * </ol>
- *
- * <p>
- * The {@link BasicRestLogger#getLogger()} method can also be
overridden to provide different logic.
- *
- * @param value
- * The logger to use for logging the request.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder logger(Logger value) {
- this.logger = value;
- return this;
- }
-
- /**
- * Specifies the logger to use for logging the request.
- *
- * <p>
- * Shortcut for calling
<c>logger(Logger.<jsm>getLogger</jsm>(value))</c>.
- *
- * <p>
- * If not specified, the logger name is determined in the following
order:
- * <ol>
- * <li><js>{@link RestLogger#SP_logger "juneau.restLogger.logger"}
system property.
- * <li><js>{@link RestLogger#SP_logger "JUNEAU_RESTLOGGER_LOGGER"}
environment variable.
- * <li><js>"global"</js>.
- * </ol>
- *
- * <p>
- * The {@link BasicRestLogger#getLogger()} method can also be
overridden to provide different logic.
- *
- * @param value
- * The logger to use for logging the request.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder logger(String value) {
- this.logger = value == null ? null :Logger.getLogger(value);
- return this;
- }
-
- /**
- * Specifies the thrown exception store to use for getting stack trace
information (hash IDs and occurrence counts).
- *
- * @param value
- * The stack trace store.
- * <br>If <jk>null</jk>, stack trace information will not be
logged.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder thrownStore(ThrownStore value) {
- this.thrownStore = value;
- return this;
- }
-
- /**
- * Specifies the default logging enablement setting.
- *
- * <p>
- * This specifies the default logging enablement value if not set on
the first matched rule or if no rules match.
- *
- * <p>
- * The possible values are:
- * <ul>
- * <li>{@link Enablement#ALWAYS ALWAYS} (default) - Logging is
enabled.
- * <li>{@link Enablement#NEVER NEVER} - Logging is disabled.
- * <li>{@link Enablement#CONDITIONAL CONDITIONALLY} - Logging is
enabled if it passes the {@link #enabledTest(Predicate)} test.
- * </ul>
- *
- * <p>
- * If not specified, the setting is determined via the following:
- * <ul>
- * <li><js>{@link RestLogger#SP_enabled
"juneau.restLogger.enabled"} system property.
- * <li><js>{@link RestLogger#SP_enabled
"JUNEAU_RESTLOGGER_ENABLED"} environment variable.
- * <li><js>"ALWAYS"</js>.
- * </ul>
- *
- * <p>
- * @param value
- * The default enablement flag value. Can be <jk>null</jk> to use
the default.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder enabled(Enablement value) {
- this.enabled = value;
- return this;
- }
-
- /**
- * Specifies the default logging enablement test predicate.
- *
- * <p>
- * This specifies the default logging enablement test if not set on the
first matched rule or if no rules match.
- *
- * <p>
- * This setting has no effect if the enablement setting is not {@link
Enablement#CONDITIONAL CONDITIONALLY}.
- *
- * <p>
- * The default if not specified is <c><jv>x</jv> -> <jk>false</jk></c>
(never log).
- *
- * @param value
- * The default enablement flag value. Can be <jk>null</jk> to use
the default.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder enabledTest(Predicate<HttpServletRequest>
value) {
- this.enabledTest = value;
- return this;
- }
-
- /**
- * Shortcut for calling <c>enabled(<jsf>NEVER</jsf>)</c>.
- *
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder disabled() {
- return this.enabled(NEVER);
- }
-
- /**
- * The default level of detail to log on a request.
- *
- * <p>
- * This specifies the default level of request detail if not set on the
first matched rule or if no rules match.
- *
- * <p>
- * The possible values are:
- * <ul>
- * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} - Log
only the status line.
- * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the status
line and headers.
- * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the status
line and headers and body if available.
- * </ul>
- *
- * <p>
- * If not specified, the setting is determined via the following:
- * <ul>
- * <li><js>{@link RestLogger#SP_requestDetail
"juneau.restLogger.requestDetail"} system property.
- * <li><js>{@link RestLogger#SP_requestDetail
"JUNEAU_RESTLOGGER_requestDetail"} environment variable.
- * <li><js>"STATUS_LINE"</js>.
- * </ul>
- *
- * @param value
- * The new value for this property, or <jk>null</jk> to use the
default.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder requestDetail(RestLoggingDetail value) {
- this.requestDetail = value;
- return this;
- }
-
- /**
- * The default level of detail to log on a response.
- *
- * <p>
- * This specifies the default level of response detail if not set on
the first matched rule or if no rules match.
- *
- * <p>
- * The possible values are:
- * <ul>
- * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} - Log
only the status line.
- * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the status
line and headers.
- * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the status
line and headers and body if available.
- * </ul>
- *
- * <p>
- * If not specified, the setting is determined via the following:
- * <ul>
- * <li><js>{@link RestLogger#SP_responseDetail
"juneau.restLogger.responseDetail"} system property.
- * <li><js>{@link RestLogger#SP_responseDetail
"JUNEAU_RESTLOGGER_responseDetail"} environment variable.
- * <li><js>"STATUS_LINE"</js>.
- * </ul>
- *
- * @param value
- * The new value for this property, or <jk>null</jk> to use the
default.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder responseDetail(RestLoggingDetail value) {
- this.responseDetail = value;
- return this;
- }
-
- /**
- * The default logging level to use for logging the request/response.
- *
- * <p>
- * This specifies the default logging level if not set on the first
matched rule or if no rules match.
- *
- * <p>
- * If not specified, the setting is determined via the following:
- * <ul>
- * <li><js>{@link RestLogger#SP_level "juneau.restLogger.level"}
system property.
- * <li><js>{@link RestLogger#SP_level "JUNEAU_RESTLOGGER_level"}
environment variable.
- * <li><js>"OFF"</js>.
- * </ul>
- *
- * @param value
- * The new value for this property, or <jk>null</jk> to use the
default value.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder level(Level value) {
- this.level = value;
- return this;
- }
-
- /**
- * Adds logging rules to use when debug mode is not enabled.
- *
- * <p>
- * Logging rules are matched in the order they are added. The first to
match wins.
- *
- * @param rules The logging rules to add to the list of rules.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder normalRules(RestLoggerRule...rules) {
- for (RestLoggerRule rule : rules)
- this.normalRules.add(rule);
- return this;
- }
-
- /**
- * Adds logging rules to use when debug mode is enabled.
- *
- * <p>
- * Logging rules are matched in the order they are added. The first to
match wins.
- *
- * @param rules The logging rules to add to the list of rules.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder debugRules(RestLoggerRule...rules) {
- for (RestLoggerRule rule : rules)
- this.debugRules.add(rule);
- return this;
- }
-
- /**
- * Shortcut for adding the same rules as normal and debug rules.
- *
- * <p>
- * Logging rules are matched in the order they are added. The first to
match wins.
- *
- * @param rules The logging rules to add to the list of rules.
- * @return This object (for method chaining).
- */
- public RestLoggerBuilder rules(RestLoggerRule...rules) {
- return normalRules(rules).debugRules(rules);
- }
-}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRule.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRule.java
index 61d202d..ae7bc4d 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRule.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRule.java
@@ -26,6 +26,15 @@ import org.apache.juneau.json.*;
*/
public class RestLoggerRule {
+ /**
+ * Creates a new builder for this object.
+ *
+ * @return A new builder for this object.
+ */
+ public static Builder create() {
+ return new Builder();
+ }
+
private final Predicate<Integer> statusFilter;
private final Predicate<HttpServletRequest> requestFilter;
private final Predicate<HttpServletResponse> responseFilter;
@@ -41,7 +50,7 @@ public class RestLoggerRule {
*
* @param b Builder
*/
- RestLoggerRule(RestLoggerRuleBuilder b) {
+ RestLoggerRule(Builder b) {
this.statusFilter = b.statusFilter;
this.exceptionFilter = b.exceptionFilter;
this.requestFilter = b.requestFilter;
@@ -55,12 +64,253 @@ public class RestLoggerRule {
}
/**
- * Creates a new builder for this object.
- *
- * @return A new builder for this object.
+ * The builder for this object.
*/
- public static RestLoggerRuleBuilder create() {
- return new RestLoggerRuleBuilder();
+ public static class Builder {
+
+ Predicate<Integer> statusFilter;
+ Predicate<HttpServletRequest> requestFilter;
+ Predicate<HttpServletResponse> responseFilter;
+ Predicate<Throwable> exceptionFilter;
+ Enablement enabled;
+ Predicate<HttpServletRequest> enabledTest;
+ Level level;
+ RestLoggingDetail requestDetail, responseDetail;
+ boolean logStackTrace;
+
+ /**
+ * Apply a status-based predicate check for this rule to match
against.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Create a logger rule that only matches if the
status code is greater than or equal to 500.</jc>
+ * RestLogger
+ * .<jsm>createRule</jsm>()
+ * .statusFilter(<jv>x</jv> -> <jv>x</jv> >=
500)
+ * .build();
+ * </p>
+ *
+ * @param value
+ * The predicate check, or <jk>null</jk> to not use any
filtering based on status code.
+ * @return This object (for method chaining).
+ */
+ public Builder statusFilter(Predicate<Integer> value) {
+ this.statusFilter = value;
+ return this;
+ }
+
+ /**
+ * Apply a throwable-based predicate check for this rule to
match against.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Create a logger rule that only matches if a
NotFound exception was thrown.</jc>
+ * RestLogger
+ * .<jsm>createRule</jsm>()
+ * .exceptionFilter(<jv>x</jv> -> <jv>x</jv>
<jk>instanceof</jk> NotFound)
+ * .build();
+ * </p>
+ *
+ * <p>
+ * This check is only performed if an actual throwable was
thrown. Therefore it's not necessary to perform a
+ * null check in the predicate.
+ *
+ * @param value
+ * The predicate check, or <jk>null</jk> to not use any
filtering based on exceptions.
+ * @return This object (for method chaining).
+ */
+ public Builder exceptionFilter(Predicate<Throwable> value) {
+ this.exceptionFilter = value;
+ return this;
+ }
+
+ /**
+ * Apply a request-based predicate check for this rule to match
against.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Create a logger rule that only matches if the
servlet path contains "foobar".</jc>
+ * RestLogger
+ * .<jsm>createRule</jsm>()
+ * .requestFilter(<jv>x</jv> ->
<jv>x</jv>.getServletPath().contains(<js>"foobar"</js>))
+ * .build();
+ * </p>
+ *
+ * @param value
+ * The predicate check, or <jk>null</jk> to not use any
filtering based on the request.
+ * @return This object (for method chaining).
+ */
+ public Builder requestFilter(Predicate<HttpServletRequest>
value) {
+ this.requestFilter = value;
+ return this;
+ }
+
+ /**
+ * Apply a response-based predicate check for this rule to
match against.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Create a logger rule that only matches if the
servlet path contains "foobar".</jc>
+ * RestLogger
+ * .<jsm>createRule</jsm>()
+ * .responseFilter(<jv>x</jv> ->
<jv>x</jv>.getStatus() >= 500)
+ * .build();
+ * </p>
+ *
+ * <p>
+ * Note that the {@link #statusFilter(Predicate)} and {@link
#exceptionFilter(Predicate)} methods are simply
+ * convenience response filters.
+ *
+ * @param value
+ * The predicate check, or <jk>null</jk> to not use any
filtering based on the response.
+ * @return This object (for method chaining).
+ */
+ public Builder responseFilter(Predicate<HttpServletResponse>
value) {
+ this.responseFilter = value;
+ return this;
+ }
+
+ /**
+ * Specifies whether logging is enabled when using this rule.
+ *
+ * <p>
+ * The possible values are:
+ * <ul>
+ * <li>{@link Enablement#ALWAYS ALWAYS} - Logging is
enabled.
+ * <li>{@link Enablement#NEVER NEVER} - Logging is
disabled.
+ * <li>{@link Enablement#CONDITIONAL CONDITIONALLY} -
Logging is enabled if it passes the {@link #enabledTest(Predicate)} test.
+ * </ul>
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Create a logger rule where logging is only
enabled if the query string contains "foobar".</jc>
+ * RestLogger
+ * .<jsm>createRule</jsm>()
+ * .enabled(<jsf>CONDITIONALLY</jsf>)
+ * .enabledTest(<jv>x</jv> ->
<jv>x</jv>.getQueryString().contains(<js>"foobar"</js>))
+ * .build();
+ * </p>
+ *
+ * @param value
+ * The enablement flag value, or <jk>null</jk> to inherit
from the call logger whose default value is {@link Enablement#ALWAYS ALWAYS}
+ * unless overridden via a
<js>"juneau.restCallLogger.enabled"</js> system property or
<js>"JUNEAU_RESTCALLLOGGER_ENABLED"</js> environment variable.
+ * @return This object (for method chaining).
+ */
+ public Builder enabled(Enablement value) {
+ this.enabled = value;
+ return this;
+ }
+
+ /**
+ * Specifies the predicate test to use when the enabled setting
is set to {@link Enablement#CONDITIONAL CONDITIONALLY}.
+ *
+ * <p>
+ * This setting has no effect if the enablement value is not
{@link Enablement#CONDITIONAL CONDITIONALLY}.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Create a logger rule where logging is only
enabled if the query string contains "foobar".</jc>
+ * RestLogger
+ * .<jsm>createRule</jsm>()
+ * .enabled(<jsf>CONDITIONALLY</jsf>)
+ * .enabledTest(<jv>x</jv> ->
<jv>x</jv>.getQueryString().contains(<js>"foobar"</js>))
+ * .build();
+ * </p>
+ *
+ * @param value
+ * The enablement predicate test, or <jk>null</jk> to
inherit from the call logger whose default value is <c><jv>x</jv> ->
<jk>false</jk></c>.
+ * @return This object (for method chaining).
+ */
+ public Builder enabledTest(Predicate<HttpServletRequest> value)
{
+ this.enabledTest = value;
+ return this;
+ }
+
+ /**
+ * Shortcut for calling <c>enabled(<jsf>NEVER</jsf>)</c>.
+ *
+ * @return This object (for method chaining).
+ */
+ public Builder disabled() {
+ return this.enabled(Enablement.NEVER);
+ }
+
+ /**
+ * The level of detail to log on a request.
+ *
+ * <p>
+ * The possible values are:
+ * <ul>
+ * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} -
Log only the status line.
+ * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the
status line and headers.
+ * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the
status line and headers and body if available.
+ * </ul>
+ *
+ * @param value
+ * The new value for this property, or <jk>null</jk> to
inherit from the call logger.
+ * @return This object (for method chaining).
+ */
+ public Builder requestDetail(RestLoggingDetail value) {
+ this.requestDetail = value;
+ return this;
+ }
+
+ /**
+ * The level of detail to log on a response.
+ *
+ * <p>
+ * The possible values are:
+ * <ul>
+ * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} -
Log only the status line.
+ * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the
status line and headers.
+ * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the
status line and headers and body if available.
+ * </ul>
+ *
+ * @param value
+ * The new value for this property, or <jk>null</jk> to
inherit from the call logger.
+ * @return This object (for method chaining).
+ */
+ public Builder responseDetail(RestLoggingDetail value) {
+ this.responseDetail = value;
+ return this;
+ }
+
+ /**
+ * The logging level to use for logging the request/response.
+ *
+ * <p>
+ * The default value is {@link Level#INFO}.
+ *
+ * @param value
+ * The new value for this property, or <jk>null</jk> to
inherit from the call logger.
+ * @return This object (for method chaining).
+ */
+ public Builder level(Level value) {
+ this.level = value;
+ return this;
+ }
+
+ /**
+ * Log a stack trace as part of the log entry.
+ *
+ * <p>
+ * The default value is <jk>false</jk>.
+ *
+ * @return This object (for method chaining).
+ */
+ public Builder logStackTrace() {
+ this.logStackTrace = true;
+ return this;
+ }
+
+ /**
+ * Instantiates a new {@link RestLoggerRule} object using the
settings in this builder.
+ *
+ * @return A new {@link RestLoggerRule} object.
+ */
+ public RestLoggerRule build() {
+ return new RestLoggerRule(this);
+ }
}
/**
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
deleted file mode 100644
index d76d515..0000000
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
+++ /dev/null
@@ -1,280 +0,0 @@
-//
***************************************************************************************************************************
-// * 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.logging;
-
-import java.util.function.*;
-import java.util.logging.*;
-
-import javax.servlet.http.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.rest.*;
-
-/**
- * Creator for {@link RestLoggerRule} objects.
- *
- * <p>
- * See the {@link BasicRestLogger} for usage.
- *
- * <ul class='seealso'>
- * <li class='jm'>{@link RestContextBuilder#callLogger(Class)}
- * <li class='jm'>{@link RestContextBuilder#callLogger(RestLogger)}
- * <li class='link'>{@doc RestLoggingAndDebugging}
- * </ul>
- */
-public class RestLoggerRuleBuilder {
-
- Predicate<Integer> statusFilter;
- Predicate<HttpServletRequest> requestFilter;
- Predicate<HttpServletResponse> responseFilter;
- Predicate<Throwable> exceptionFilter;
- Enablement enabled;
- Predicate<HttpServletRequest> enabledTest;
- Level level;
- RestLoggingDetail requestDetail, responseDetail;
- boolean logStackTrace;
-
- /**
- * Apply a status-based predicate check for this rule to match against.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Create a logger rule that only matches if the status
code is greater than or equal to 500.</jc>
- * RestLogger
- * .<jsm>createRule</jsm>()
- * .statusFilter(<jv>x</jv> -> <jv>x</jv> >= 500)
- * .build();
- * </p>
- *
- * @param value
- * The predicate check, or <jk>null</jk> to not use any filtering
based on status code.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder statusFilter(Predicate<Integer> value) {
- this.statusFilter = value;
- return this;
- }
-
- /**
- * Apply a throwable-based predicate check for this rule to match
against.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Create a logger rule that only matches if a NotFound
exception was thrown.</jc>
- * RestLogger
- * .<jsm>createRule</jsm>()
- * .exceptionFilter(<jv>x</jv> -> <jv>x</jv>
<jk>instanceof</jk> NotFound)
- * .build();
- * </p>
- *
- * <p>
- * This check is only performed if an actual throwable was thrown.
Therefore it's not necessary to perform a
- * null check in the predicate.
- *
- * @param value
- * The predicate check, or <jk>null</jk> to not use any filtering
based on exceptions.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder exceptionFilter(Predicate<Throwable>
value) {
- this.exceptionFilter = value;
- return this;
- }
-
- /**
- * Apply a request-based predicate check for this rule to match against.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Create a logger rule that only matches if the servlet
path contains "foobar".</jc>
- * RestLogger
- * .<jsm>createRule</jsm>()
- * .requestFilter(<jv>x</jv> ->
<jv>x</jv>.getServletPath().contains(<js>"foobar"</js>))
- * .build();
- * </p>
- *
- * @param value
- * The predicate check, or <jk>null</jk> to not use any filtering
based on the request.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder
requestFilter(Predicate<HttpServletRequest> value) {
- this.requestFilter = value;
- return this;
- }
-
- /**
- * Apply a response-based predicate check for this rule to match
against.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Create a logger rule that only matches if the servlet
path contains "foobar".</jc>
- * RestLogger
- * .<jsm>createRule</jsm>()
- * .responseFilter(<jv>x</jv> -> <jv>x</jv>.getStatus()
>= 500)
- * .build();
- * </p>
- *
- * <p>
- * Note that the {@link #statusFilter(Predicate)} and {@link
#exceptionFilter(Predicate)} methods are simply
- * convenience response filters.
- *
- * @param value
- * The predicate check, or <jk>null</jk> to not use any filtering
based on the response.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder
responseFilter(Predicate<HttpServletResponse> value) {
- this.responseFilter = value;
- return this;
- }
-
- /**
- * Specifies whether logging is enabled when using this rule.
- *
- * <p>
- * The possible values are:
- * <ul>
- * <li>{@link Enablement#ALWAYS ALWAYS} - Logging is enabled.
- * <li>{@link Enablement#NEVER NEVER} - Logging is disabled.
- * <li>{@link Enablement#CONDITIONAL CONDITIONALLY} - Logging is
enabled if it passes the {@link #enabledTest(Predicate)} test.
- * </ul>
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Create a logger rule where logging is only enabled if
the query string contains "foobar".</jc>
- * RestLogger
- * .<jsm>createRule</jsm>()
- * .enabled(<jsf>CONDITIONALLY</jsf>)
- * .enabledTest(<jv>x</jv> ->
<jv>x</jv>.getQueryString().contains(<js>"foobar"</js>))
- * .build();
- * </p>
- *
- * @param value
- * The enablement flag value, or <jk>null</jk> to inherit from the
call logger whose default value is {@link Enablement#ALWAYS ALWAYS}
- * unless overridden via a
<js>"juneau.restCallLogger.enabled"</js> system property or
<js>"JUNEAU_RESTCALLLOGGER_ENABLED"</js> environment variable.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder enabled(Enablement value) {
- this.enabled = value;
- return this;
- }
-
- /**
- * Specifies the predicate test to use when the enabled setting is set
to {@link Enablement#CONDITIONAL CONDITIONALLY}.
- *
- * <p>
- * This setting has no effect if the enablement value is not {@link
Enablement#CONDITIONAL CONDITIONALLY}.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Create a logger rule where logging is only enabled if
the query string contains "foobar".</jc>
- * RestLogger
- * .<jsm>createRule</jsm>()
- * .enabled(<jsf>CONDITIONALLY</jsf>)
- * .enabledTest(<jv>x</jv> ->
<jv>x</jv>.getQueryString().contains(<js>"foobar"</js>))
- * .build();
- * </p>
- *
- * @param value
- * The enablement predicate test, or <jk>null</jk> to inherit from
the call logger whose default value is <c><jv>x</jv> -> <jk>false</jk></c>.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder enabledTest(Predicate<HttpServletRequest>
value) {
- this.enabledTest = value;
- return this;
- }
-
- /**
- * Shortcut for calling <c>enabled(<jsf>NEVER</jsf>)</c>.
- *
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder disabled() {
- return this.enabled(Enablement.NEVER);
- }
-
- /**
- * The level of detail to log on a request.
- *
- * <p>
- * The possible values are:
- * <ul>
- * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} - Log
only the status line.
- * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the status
line and headers.
- * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the status
line and headers and body if available.
- * </ul>
- *
- * @param value
- * The new value for this property, or <jk>null</jk> to inherit
from the call logger.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder requestDetail(RestLoggingDetail value) {
- this.requestDetail = value;
- return this;
- }
-
- /**
- * The level of detail to log on a response.
- *
- * <p>
- * The possible values are:
- * <ul>
- * <li>{@link RestLoggingDetail#STATUS_LINE STATUS_LINE} - Log
only the status line.
- * <li>{@link RestLoggingDetail#HEADER HEADER} - Log the status
line and headers.
- * <li>{@link RestLoggingDetail#ENTITY ENTITY} - Log the status
line and headers and body if available.
- * </ul>
- *
- * @param value
- * The new value for this property, or <jk>null</jk> to inherit
from the call logger.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder responseDetail(RestLoggingDetail value) {
- this.responseDetail = value;
- return this;
- }
-
- /**
- * The logging level to use for logging the request/response.
- *
- * <p>
- * The default value is {@link Level#INFO}.
- *
- * @param value
- * The new value for this property, or <jk>null</jk> to inherit
from the call logger.
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder level(Level value) {
- this.level = value;
- return this;
- }
-
- /**
- * Log a stack trace as part of the log entry.
- *
- * <p>
- * The default value is <jk>false</jk>.
- *
- * @return This object (for method chaining).
- */
- public RestLoggerRuleBuilder logStackTrace() {
- this.logStackTrace = true;
- return this;
- }
-
- /**
- * Instantiates a new {@link RestLoggerRule} object using the settings
in this builder.
- *
- * @return A new {@link RestLoggerRule} object.
- */
- public RestLoggerRule build() {
- return new RestLoggerRule(this);
- }
-}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/cp/DefaultClassList_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/cp/DefaultClassList_Test.java
new file mode 100644
index 0000000..db8038a
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/cp/DefaultClassList_Test.java
@@ -0,0 +1,41 @@
+//
***************************************************************************************************************************
+// * 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.cp;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.runners.MethodSorters.*;
+import static org.apache.juneau.cp.DefaultClassList.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class DefaultClassList_Test {
+
+
//-----------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//-----------------------------------------------------------------------------------------------------------------
+
+ @Test
+ public void a01_basic() {
+ DefaultClassList x = create();
+ assertOptional(x.get(String.class)).isNull();
+
+ x = of(Long.class,null);
+ assertOptional(x.get(String.class)).isNull();
+ assertOptional(x.get(Long.class)).isNotNull();
+ assertOptional(x.get(Number.class)).isNotNull();
+ assertOptional(x.get(Object.class)).isNotNull();
+
+ assertThrown(()->create().get(null)).message().is("Argument
'type' cannot be null.");
+ }
+}