001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest;
018
019import static jakarta.servlet.http.HttpServletResponse.*;
020import static java.util.Collections.*;
021import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
022import static org.apache.juneau.commons.utils.AssertionUtils.*;
023import static org.apache.juneau.commons.utils.ClassUtils.*;
024import static org.apache.juneau.commons.utils.CollectionUtils.*;
025import static org.apache.juneau.commons.utils.PredicateUtils.*;
026import static org.apache.juneau.commons.utils.IoUtils.*;
027import static org.apache.juneau.commons.utils.StringUtils.*;
028import static org.apache.juneau.commons.utils.Utils.*;
029import static org.apache.juneau.http.HttpHeaders.*;
030import static org.apache.juneau.rest.annotation.RestOpAnnotation.*;
031import static org.apache.juneau.rest.processor.ResponseProcessor.*;
032import static org.apache.juneau.rest.util.RestUtils.*;
033
034import java.io.*;
035import java.lang.annotation.*;
036import java.lang.reflect.*;
037import java.lang.reflect.Method;
038import java.nio.charset.*;
039import java.time.*;
040import java.util.*;
041import java.util.concurrent.*;
042import java.util.concurrent.atomic.*;
043import java.util.function.*;
044import java.util.logging.*;
045import java.util.stream.*;
046
047import org.apache.http.Header;
048import org.apache.juneau.*;
049import org.apache.juneau.bean.swagger.Swagger;
050import org.apache.juneau.commons.collections.*;
051import org.apache.juneau.commons.collections.FluentMap;
052import org.apache.juneau.commons.lang.*;
053import org.apache.juneau.commons.reflect.*;
054import org.apache.juneau.commons.utils.*;
055import org.apache.juneau.config.*;
056import org.apache.juneau.config.vars.*;
057import org.apache.juneau.cp.*;
058import org.apache.juneau.encoders.*;
059import org.apache.juneau.html.*;
060import org.apache.juneau.html.annotation.*;
061import org.apache.juneau.http.annotation.*;
062import org.apache.juneau.http.header.*;
063import org.apache.juneau.http.response.*;
064import org.apache.juneau.httppart.*;
065import org.apache.juneau.httppart.HttpPartSerializer.*;
066import org.apache.juneau.jsonschema.*;
067import org.apache.juneau.oapi.*;
068import org.apache.juneau.parser.*;
069import org.apache.juneau.parser.ParseException;
070import org.apache.juneau.rest.annotation.*;
071import org.apache.juneau.rest.arg.*;
072import org.apache.juneau.rest.debug.*;
073import org.apache.juneau.rest.httppart.*;
074import org.apache.juneau.rest.logger.*;
075import org.apache.juneau.rest.processor.*;
076import org.apache.juneau.rest.rrpc.*;
077import org.apache.juneau.rest.servlet.*;
078import org.apache.juneau.rest.staticfile.*;
079import org.apache.juneau.rest.stats.*;
080import org.apache.juneau.rest.swagger.*;
081import org.apache.juneau.rest.util.*;
082import org.apache.juneau.rest.vars.*;
083import org.apache.juneau.serializer.*;
084import org.apache.juneau.svl.*;
085import org.apache.juneau.svl.vars.*;
086import jakarta.servlet.*;
087import jakarta.servlet.http.*;
088
089/**
090 * Defines the initial configuration of a <c>RestServlet</c> or <c>@Rest</c> annotated object.
091 *
092 * <p>
093 * An extension of the {@link ServletConfig} object used during servlet initialization.
094 *
095 * <p>
096 * Methods are provided for overriding or augmenting the information provided by the <ja>@Rest</ja> annotation.
097 * In general, most information provided in the <ja>@Rest</ja> annotation can be specified programmatically
098 * through calls on this object.
099 *
100 * <p>
101 * To interact with this object, simply pass it in as a constructor argument or in an INIT hook.
102 * <p class='bjava'>
103 *    <jc>// Option #1 - Pass in through constructor.</jc>
104 *    <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) {
105 *          <jv>builder</jv>
106 *             .swaps(TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>);
107 *    }
108 *
109 *    <jc>// Option #2 - Use an init hook.</jc>
110 *    <ja>@RestInit</ja>
111 *    <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
112 *          <jv>builder</jv>
113 *             .swaps(TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>);
114 *    }
115 * </p>
116 *
117 * <h5 class='section'>Notes:</h5><ul>
118 *    <li class='note'>This class is thread safe and reusable.
119 * </ul>
120 *
121 * <h5 class='section'>See Also:</h5><ul>
122 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestContext">RestContext</a>
123
124 * </ul>
125 */
126public class RestContext extends Context {
127   /**
128    * Builder class.
129    */
130   public static class Builder extends Context.Builder implements ServletConfig {
131
132      private static final AnnotationProvider AP = AnnotationProvider.INSTANCE;
133
134      // @formatter:off
135      private static final Set<Class<?>> DELAYED_INJECTION = set(
136         BeanContext.Builder.class,
137         BeanStore.Builder.class,
138         BeanStore.class,
139         CallLogger.Builder.class,
140         CallLogger.class,
141         Config.class,
142         DebugEnablement.Builder.class,
143         DebugEnablement.class,
144         EncoderSet.Builder.class,
145         EncoderSet.class,
146         FileFinder.Builder.class,
147         FileFinder.class,
148         HttpPartParser.class,
149         HttpPartParser.Creator.class,
150         HttpPartSerializer.class,
151         HttpPartSerializer.Creator.class,
152         JsonSchemaGenerator.Builder.class,
153         JsonSchemaGenerator.class,
154         Logger.class,
155         Messages.Builder.class,
156         Messages.class,
157         MethodExecStore.Builder.class,
158         MethodExecStore.class,
159         ParserSet.Builder.class,
160         ParserSet.class,
161         ResponseProcessorList.Builder.class,
162         ResponseProcessorList.class,
163         RestChildren.Builder.class,
164         RestChildren.class,
165         RestOpArgList.Builder.class,
166         RestOpArgList.class,
167         RestOperations.Builder.class,
168         RestOperations.class,
169         SerializerSet.Builder.class,
170         SerializerSet.class,
171         StaticFiles.Builder.class,
172         StaticFiles.class,
173         SwaggerProvider.Builder.class,
174         SwaggerProvider.class,
175         ThrownStore.Builder.class,
176         ThrownStore.class,
177         VarList.class,
178         VarResolver.Builder.class,
179         VarResolver.class
180      );
181
182      private static final Set<String> DELAYED_INJECTION_NAMES = set(
183         "defaultRequestAttributes",
184         "defaultRequestHeaders",
185         "defaultResponseHeaders",
186         "destroyMethods",
187         "endCallMethods",
188         "postCallMethods",
189         "postInitChildFirstMethods",
190         "postInitMethods",
191         "preCallMethods",
192         "startCallMethods"
193      );
194      // @formatter:on
195
196      //-----------------------------------------------------------------------------------------------------------------
197      // The following fields are meant to be modifiable.
198      // They should not be declared final.
199      // Read-only snapshots of these will be made in RestServletContext.
200      //-----------------------------------------------------------------------------------------------------------------
201
202      private static <T extends Annotation> Stream<Method> getAnnotatedMethods(Supplier<?> resource, Class<T> annotation) {
203         return ClassInfo.ofProxy(resource.get()).getAllMethodsTopDown().stream()
204            .filter(y -> y.hasAnnotation(annotation))
205            .filter(distinctByKey(MethodInfo::getSignature))
206            .map(y -> y.accessible().inner());
207      }
208
209      private static boolean isRestInjectMethod(MethodInfo mi) {
210         return isRestInjectMethod(mi, null);
211      }
212
213      private static boolean isRestInjectMethod(MethodInfo mi, String name) {
214         return mi.getAnnotations(RestInject.class)
215            .map(AnnotationInfo::inner)
216            .filter(x -> nn(x) && x.methodScope().length == 0 && (n(name) || eq(x.name(), name)))
217            .findFirst()
218            .isPresent();
219      }
220
221      private BeanContext.Builder beanContext;
222      private BeanCreator<CallLogger> callLogger;
223      private BeanCreator<DebugEnablement> debugEnablement;
224      private BeanCreator<StaticFiles> staticFiles;
225      private BeanCreator<SwaggerProvider> swaggerProvider;
226      private BeanStore beanStore;
227      private BeanStore rootBeanStore;
228      private boolean disableContentParam = env("RestContext.disableContentParam", false);
229      private boolean initialized;
230      private boolean renderResponseStackTraces = env("RestContext.renderResponseStackTraces", false);
231      private Charset defaultCharset = env("RestContext.defaultCharset").map(Charset::forName).orElse(UTF8);
232      private Class<? extends RestChildren> childrenClass = RestChildren.class;
233      private Class<? extends RestOpContext> opContextClass = RestOpContext.class;
234      private final Class<?> resourceClass;
235      private Config config;
236      private DefaultClassList defaultClasses;
237      private DefaultSettingsMap defaultSettings;
238      private EncoderSet.Builder encoders;
239      private HeaderList defaultRequestHeaders;
240      private HeaderList defaultResponseHeaders;
241      private HttpPartParser.Creator partParser;
242      private HttpPartSerializer.Creator partSerializer;
243      private JsonSchemaGenerator.Builder jsonSchemaGenerator;
244      private List<MediaType> consumes;
245      private List<MediaType> produces;
246      private List<Object> children = list();
247      private Logger logger;
248      private long maxInput = env("RestContext.maxInput").map(StringUtils::parseLongWithSuffix).orElse(100_000_000l);
249      private MethodExecStore.Builder methodExecStore;
250      private MethodList destroyMethods;
251      private MethodList endCallMethods;
252      private MethodList postCallMethods;
253      private MethodList postInitChildFirstMethods;
254      private MethodList postInitMethods;
255      private MethodList preCallMethods;
256      private MethodList startCallMethods;
257      private Messages.Builder messages;
258      private NamedAttributeMap defaultRequestAttributes;
259      private ParserSet.Builder parsers;
260      private final RestContext parentContext;
261      private RestChildren.Builder restChildren;
262      private RestOpArgList.Builder restOpArgs;
263      private RestOperations.Builder restOperations;
264      private ResponseProcessorList.Builder responseProcessors;
265      private ResourceSupplier resource;
266      private SerializerSet.Builder serializers;
267      private final ServletConfig inner;
268      private String allowedHeaderParams = env("RestContext.allowedHeaderParams", "Accept,Content-Type");
269      private String allowedMethodHeaders = env("RestContext.allowedMethodHeaders", "");
270      private String allowedMethodParams = env("RestContext.allowedMethodParams", "HEAD,OPTIONS");
271      private String clientVersionHeader = env("RestContext.clientVersionHeader", "Client-Version");
272      private String path = null;
273      private String uriAuthority = env("RestContext.uriAuthority").orElse(null);
274      private String uriContext = env("RestContext.uriContext").orElse(null);
275      private ThrownStore.Builder thrownStore;
276      private UriRelativity uriRelativity = env("RestContext.uriRelativity", UriRelativity.RESOURCE);
277      private UriResolution uriResolution = env("RestContext.uriResolution", UriResolution.ROOT_RELATIVE);
278      private VarResolver.Builder varResolver;
279
280      /**
281       * Constructor.
282       *
283       * @param resourceClass
284       *    The REST servlet/bean type that this context is defined against.
285       * @param parentContext The parent context if this is a child of another resource.
286       * @param servletConfig The servlet config if available.
287       */
288      protected Builder(Class<?> resourceClass, RestContext parentContext, ServletConfig servletConfig) {
289
290         this.resourceClass = resourceClass;
291         this.inner = servletConfig;
292         this.parentContext = parentContext;
293
294         // Pass-through default values.
295         if (nn(parentContext)) {
296            defaultClasses = parentContext.defaultClasses.copy();
297            defaultSettings = parentContext.defaultSettings.copy();
298            rootBeanStore = parentContext.rootBeanStore;
299         } else {
300            defaultClasses = DefaultClassList.create();
301            defaultSettings = DefaultSettingsMap.create();
302         }
303      }
304
305      /**
306       * Allowed header URL parameters.
307       *
308       * <p>
309       * When specified, allows headers such as <js>"Accept"</js> and <js>"Content-Type"</js> to be passed in as URL query
310       * parameters.
311       * <br>
312       * For example:
313       * <p class='burlenc'>
314       *  ?Accept=text/json&amp;Content-Type=text/json
315       * </p>
316       *
317       * <h5 class='section'>Notes:</h5><ul>
318       *    <li class='note'>
319       *       Useful for debugging REST interface using only a browser so that you can quickly simulate header values
320       *       in the URL bar.
321       *    <li class='note'>
322       *       Header names are case-insensitive.
323       *    <li class='note'>
324       *       Use <js>"*"</js> to allow any headers to be specified as URL parameters.
325       *    <li class='note'>
326       *       Use <js>"NONE"</js> (case insensitive) to suppress inheriting a value from a parent class.
327       * </ul>
328       *
329       * <h5 class='section'>See Also:</h5><ul>
330       *    <li class='ja'>{@link Rest#allowedHeaderParams}
331       * </ul>
332       *
333       * @param value
334       *    The new value for this setting.
335       *    <br>The default is the first value found:
336       *    <ul>
337       *       <li>System property <js>"RestContext.allowedHeaderParams"
338       *       <li>Environment variable <js>"RESTCONTEXT_ALLOWEDHEADERPARAMS"
339       *       <li><js>"Accept,Content-Type"</js>
340       *    </ul>
341       *    <br>Cannot be <jk>null</jk>.
342       * @return This object.
343       */
344      public Builder allowedHeaderParams(String value) {
345         allowedHeaderParams = assertArgNotNull("value", value);
346         return this;
347      }
348
349      /**
350       * Allowed method headers.
351       *
352       * <p>
353       * A comma-delimited list of HTTP method names that are allowed to be passed as values in an <c>X-Method</c> HTTP header
354       * to override the real HTTP method name.
355       *
356       * <p>
357       * Allows you to override the actual HTTP method with a simulated method.
358       * <br>For example, if an HTTP Client API doesn't support <c>PATCH</c> but does support <c>POST</c> (because
359       * <c>PATCH</c> is not part of the original HTTP spec), you can add a <c>X-Method: PATCH</c> header on a normal
360       * <c>HTTP POST /foo</c> request call which will make the HTTP call look like a <c>PATCH</c> request in any of the REST APIs.
361       *
362       * <h5 class='section'>Example:</h5>
363       * <p class='bjava'>
364       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
365       *    <ja>@Rest</ja>(allowedMethodHeaders=<js>"PATCH"</js>)
366       *    <jk>public class</jk> MyResource {
367       *
368       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
369       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
370       *
371       *          <jc>// Using method on builder.</jc>
372       *          <jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
373       *       }
374       *
375       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
376       *       <ja>@RestInit</ja>
377       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
378       *          <jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
379       *       }
380       *    }
381       * </p>
382       *
383       * <h5 class='section'>Notes:</h5><ul>
384       *    <li class='note'>
385       *       Method names are case-insensitive.
386       *    <li class='note'>
387       *       Use <js>"*"</js> to represent all methods.
388       *    <li class='note'>
389       *       Use <js>"NONE"</js> (case insensitive) to suppress inheriting a value from a parent class.
390       * </ul>
391       *
392       * <h5 class='section'>See Also:</h5><ul>
393       *    <li class='ja'>{@link Rest#allowedMethodHeaders}
394       * </ul>
395       *
396       * @param value
397       *    The new value for this setting.
398       *    <br>The default is the first value found:
399       *    <ul>
400       *       <li>System property <js>"RestContext.allowedMethodHeaders"
401       *       <li>Environment variable <js>"RESTCONTEXT_ALLOWEDMETHODHEADERS"
402       *       <li><js>""</js>
403       *    </ul>
404       *    <br>Cannot be <jk>null</jk>.
405       * @return This object.
406       */
407      public Builder allowedMethodHeaders(String value) {
408         allowedMethodHeaders = assertArgNotNull("value", value);
409         return this;
410      }
411
412      /**
413       * Allowed method parameters.
414       *
415       * <p>
416       * When specified, the HTTP method can be overridden by passing in a <js>"method"</js> URL parameter on a regular
417       * GET request.
418       * <br>
419       * For example:
420       * <p class='burlenc'>
421       *  ?method=OPTIONS
422       * </p>
423       *
424       * <p>
425       *    Useful in cases where you want to simulate a non-GET request in a browser by simply adding a parameter.
426       *    <br>Also useful if you want to construct hyperlinks to non-GET REST endpoints such as links to <c>OPTIONS</c>
427       * pages.
428       *
429       * <p>
430       * Note that per the <a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">HTTP specification</a>, special care should
431       * be taken when allowing non-safe (<c>POST</c>, <c>PUT</c>, <c>DELETE</c>) methods to be invoked through GET requests.
432       *
433       * <h5 class='section'>Example:</h5>
434       * <p class='bjava'>
435       *    <jc>// Option #1 - Defined via annotation.</jc>
436       *    <ja>@Rest</ja>(allowedMethodParams=<js>"HEAD,OPTIONS,PUT"</js>)
437       *    <jk>public class</jk> MyResource {
438       *
439       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
440       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
441       *
442       *          <jc>// Using method on builder.</jc>
443       *          <jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
444       *       }
445       *
446       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
447       *       <ja>@RestInit</ja>
448       *       <jk>public void</jk> init(RestContext.Builder builder) <jk>throws</jk> Exception {
449       *          <jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
450       *       }
451       *    }
452       * </p>
453       *
454       * <h5 class='section'>Notes:</h5><ul>
455       *    <li class='note'>
456       *       Format is a comma-delimited list of HTTP method names that can be passed in as a method parameter.
457       *    <li class='note'>
458       *       <js>'method'</js> parameter name is case-insensitive.
459       *    <li class='note'>
460       *       Use <js>"*"</js> to represent all methods.
461       *    <li class='note'>
462       *       Use <js>"NONE"</js> (case insensitive) to suppress inheriting a value from a parent class.
463       * </ul>
464       *
465       * <h5 class='section'>See Also:</h5><ul>
466       *    <li class='ja'>{@link Rest#allowedMethodParams}
467       * </ul>
468       *
469       * @param value
470       *    The new value for this setting.
471       *    <br>The default is the first value found:
472       *    <ul>
473       *       <li>System property <js>"RestContext.allowedMethodParams"
474       *       <li>Environment variable <js>"RESTCONTEXT_ALLOWEDMETHODPARAMS"
475       *       <li><js>"HEAD,OPTIONS"</js>
476       *    </ul>
477       *    <br>Cannot be <jk>null</jk>.
478       * @return This object.
479       */
480      public Builder allowedMethodParams(String value) {
481         allowedMethodParams = assertArgNotNull("value", value);
482         return this;
483      }
484
485      @Override /* Overridden from Builder */
486      public Builder annotations(Annotation...values) {
487         super.annotations(values);
488         return this;
489      }
490
491      @Override /* Overridden from Builder */
492      public Builder apply(AnnotationWorkList work) {
493         super.apply(work);
494         return this;
495      }
496
497      @Override /* Overridden from Builder */
498      public Builder applyAnnotations(Class<?>...from) {
499         super.applyAnnotations(from);
500         return this;
501      }
502
503      @Override /* Overridden from Builder */
504      public Builder applyAnnotations(Object...from) {
505         super.applyAnnotations(from);
506         return this;
507      }
508
509      /**
510       * Returns the bean context sub-builder.
511       *
512       * <p>
513       * The bean context is used to retrieve metadata on Java beans.
514       *
515       * <p>
516       * The default bean context can overridden via any of the following:
517       * <ul class='spaced-list'>
518       *    <li>Injected via bean store.
519       * </ul>
520       *
521       * @return The bean context sub-builder.
522       */
523      public BeanContext.Builder beanContext() {
524         if (beanContext == null)
525            beanContext = createBeanContext(beanStore(), resource());
526         return beanContext;
527      }
528
529      /**
530       * Returns the bean store in this builder.
531       *
532       * <p>
533       * The bean store is a simple storage database for beans keyed by type and name.
534       *
535       * <p>
536       * The bean store is created with the parent root bean store as the parent, allowing any beans in the root bean store to be available
537       * in this builder.  The root bean store typically pulls from an injection framework such as Spring to allow injected beans to be used.
538       *
539       * <p>
540       * The default bean store can be overridden via any of the following:
541       * <ul class='spaced-list'>
542       *    <li>Class annotation:  {@link Rest#beanStore() @Rest(beanStore)}
543       *    <li>{@link RestInject @RestInject}-annotated methods:
544       *       <p class='bjava'>
545       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] BeanStore myMethod(<i>&lt;args&gt;</i>) {...}
546       *       </p>
547       *       Args can be any injected bean including {@link org.apache.juneau.cp.BeanStore.Builder}, the default builder.
548       * </ul>
549       *
550       * @return The bean store in this builder.
551       */
552      public BeanStore beanStore() {
553         return beanStore;
554      }
555
556      /**
557       * Adds a bean to the bean store of this class.
558       *
559       * <p>
560       * Equivalent to calling:
561       * <p class='bjava'>
562       *    <jv>builder</jv>.beanStore().add(<jv>beanType</jv>, <jv>bean</jv>);
563       * </p>
564       *
565       * <h5 class='section'>See Also:</h5><ul>
566       *    <li class='jm'>{@link #beanStore()}
567       * </ul>
568       *
569       * @param <T> The class to associate this bean with.
570       * @param beanType The class to associate this bean with.
571       * @param bean The bean.
572       *    <br>Can be <jk>null</jk> (a null bean will be stored in the bean store).
573       * @return This object.
574       */
575      public <T> Builder beanStore(Class<T> beanType, T bean) {
576         beanStore().addBean(beanType, bean);
577         return this;
578      }
579
580      /**
581       * Adds a bean to the bean store of this class.
582       *
583       * <p>
584       * Equivalent to calling:
585       * <p class='bjava'>
586       *    <jv>builder</jv>.beanStore().add(<jv>beanType</jv>, <jv>bean</jv>, <jv>name</jv>);
587       * </p>
588       *
589       * <h5 class='section'>See Also:</h5><ul>
590       *    <li class='jm'>{@link #beanStore()}
591       * </ul>
592       *
593       * @param <T> The class to associate this bean with.
594       * @param beanType The class to associate this bean with.
595       * @param bean The bean.
596       *    <br>Can be <jk>null</jk> (a null bean will be stored in the bean store).
597       * @param name The bean name if this is a named bean.
598       *    <br>Can be <jk>null</jk> (bean will be stored as an unnamed bean).
599       * @return This object.
600       */
601      public <T> Builder beanStore(Class<T> beanType, T bean, String name) {
602         beanStore().addBean(beanType, bean, name);
603         return this;
604      }
605
606      @Override /* Overridden from BeanContext.Builder */
607      public RestContext build() {
608         try {
609            return beanStore().createBean(RestContext.class).type(getType().orElse(RestContext.class)).builder(RestContext.Builder.class, this).run();
610         } catch (Exception e) {
611            e.printStackTrace();  // NOSONAR
612            throw new InternalServerError(e, "Could not instantiate RestContext.");
613         }
614      }
615
616      @Override /* Overridden from Builder */
617      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
618         super.cache(value);
619         return this;
620      }
621
622      /**
623       * Returns the call logger bean creator.
624       *
625       * <p>
626       * Specifies the logger to use for logging of HTTP requests and responses.
627       *
628       * <h5 class='section'>Example:</h5>
629       * <p class='bjava'>
630       *    <jc>// Our customized logger.</jc>
631       *    <jk>public class</jk> MyLogger <jk>extends</jk> BasicCallLogger {
632       *
633       *       <jk>public</jk> MyLogger(BeanStore <jv>beanStore</jv>) {
634       *       <jk>super</jk>(<jv>beanStore</jv>);
635       *    }
636       *
637       *       <ja>@Override</ja>
638       *          <jk>protected void</jk> log(Level <jv>level</jv>, String <jv>msg</jv>, Throwable <jv>e</jv>) {
639       *          <jc>// Handle logging ourselves.</jc>
640       *       }
641       *    }
642       *
643       *    <jc>// Option #1 - Registered via annotation resolving to a config file setting with default value.</jc>
644       *    <ja>@Rest</ja>(callLogger=MyLogger.<jk>class</jk>)
645       *    <jk>public class</jk> MyResource {
646       *
647       *       <jc>// Option #2 - Registered via builder passed in through init method.</jc>
648       *       <ja>@RestInit</ja>
649       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
650       *          <jv>builder</jv>.callLogger(MyLogger.<jk>class</jk>);
651       *       }
652       *    }
653       * </p>
654       *
655       * <p>
656       * The default call logger can overridden via any of the following:
657       * <ul class='spaced-list'>
658       *    <li>Injected via bean store.
659       *    <li>Class annotation:  {@link Rest#callLogger() @Rest(callLogger)}
660       *    <li>{@link RestInject @RestInject}-annotated method:
661       *       <p class='bjava'>
662       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] CallLogger myMethod(<i>&lt;args&gt;</i>) {...}
663       *       </p>
664       *       Args can be any injected bean.
665       * </ul>
666       *
667       * <h5 class='section'>Notes:</h5><ul>
668       *    <li class='note'>
669       *       The default call logger if not specified is {@link BasicCallLogger}.
670       *    <li class='note'>
671       *       The resource class itself will be used if it implements the {@link CallLogger} interface and not
672       *       explicitly overridden via this annotation.
673       *    <li class='note'>
674       *       When defined as a class, the implementation must have one of the following constructor:
675       *       <ul>
676       *          <li><code><jk>public</jk> T(BeanStore)</code>
677       *       </ul>
678       *    <li class='note'>
679       *       Inner classes of the REST resource class are allowed.
680       * </ul>
681       *
682       * <h5 class='section'>See Also:</h5><ul>
683       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
684       * </ul>
685       *
686       * @return The call logger sub-builder.
687       * @throws RuntimeException If {@link #init(Supplier)} has not been called.
688       */
689      public BeanCreator<CallLogger> callLogger() {
690         if (callLogger == null)
691            callLogger = createCallLogger(beanStore, resource);
692         return callLogger;
693      }
694
695      /**
696       * Specifies the call logger for this class.
697       *
698       * <p>
699       * Equivalent to calling:
700       * <p class='bjava'>
701       *    <jv>builder</jv>.callLogger().impl(<jv>value</jv>);
702       * </p>
703       *
704       * <h5 class='section'>See Also:</h5><ul>
705       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
706       *    <li class='jm'>{@link #callLogger()}
707       * </ul>
708       *
709       * @param value The new value.
710       *    <br>Cannot be <jk>null</jk>.
711       * @return This object.
712       */
713      public Builder callLogger(CallLogger value) {
714         callLogger().impl(assertArgNotNull("value", value));
715         return this;
716      }
717
718      /**
719       * Specifies the call logger for this class.
720       *
721       * <p>
722       * Equivalent to calling:
723       * <p class='bjava'>
724       *    <jv>builder</jv>.callLogger().type(<jv>value</jv>);
725       * </p>
726       *
727       * <h5 class='section'>See Also:</h5><ul>
728       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
729       *    <li class='jm'>{@link #callLogger()}
730       * </ul>
731       *
732       * @param value The new value.
733       *    <br>Cannot be <jk>null</jk>.
734       * @return This object.
735       */
736      public Builder callLogger(Class<? extends CallLogger> value) {
737         callLogger().type(assertArgNotNull("value", value));
738         return this;
739      }
740
741      /**
742       * Add a child REST resource.
743       *
744       * <p>
745       * Shortcut for adding a single child to this resource.
746       *
747       * <p>
748       * This can be used for resources that don't have a {@link Rest#path() @Rest(path)} annotation.
749       *
750       * @param path The child path relative to the parent resource URI.
751       *    <br>Cannot be <jk>null</jk>.
752       * @param child The child to add to this resource.
753       * @return This object.
754       */
755      public Builder child(String path, Object child) {
756         children.add(new RestChild(assertArgNotNull("path", path), child));
757         return this;
758      }
759
760      /**
761       * Child REST resources.
762       *
763       * <p>
764       * Defines children of this resource.
765       *
766       * <p>
767       * A REST child resource is simply another servlet or object that is initialized as part of the ascendant resource and has a
768       * servlet path directly under the ascendant resource object path.
769       * <br>The main advantage to defining servlets as REST children is that you do not need to define them in the
770       * <c>web.xml</c> file of the web application.
771       * <br>This can cut down on the number of entries that show up in the <c>web.xml</c> file if you are defining
772       * large numbers of servlets.
773       *
774       * <p>
775       * Child resources must specify a value for {@link Rest#path() @Rest(path)} that identifies the subpath of the child resource
776       * relative to the ascendant path UNLESS you use the {@link RestContext.Builder#child(String, Object)} method to register it.
777       *
778       * <p>
779       * Child resources can be nested arbitrarily deep using this technique (i.e. children can also have children).
780       *
781       * <dl>
782       *    <dt>Servlet initialization:</dt>
783       *    <dd>
784       *       <p>
785       *          A child resource will be initialized immediately after the ascendant servlet/resource is initialized.
786       *          <br>The child resource receives the same servlet config as the ascendant servlet/resource.
787       *          <br>This allows configuration information such as servlet initialization parameters to filter to child
788       *          resources.
789       *       </p>
790       *    </dd>
791       *    <dt>Runtime behavior:</dt>
792       *    <dd>
793       *       <p>
794       *          As a rule, methods defined on the <c>HttpServletRequest</c> object will behave as if the child
795       *          servlet were deployed as a top-level resource under the child's servlet path.
796       *          <br>For example, the <c>getServletPath()</c> and <c>getPathInfo()</c> methods on the
797       *          <c>HttpServletRequest</c> object will behave as if the child resource were deployed using the
798       *          child's servlet path.
799       *          <br>Therefore, the runtime behavior should be equivalent to deploying the child servlet in the
800       *          <c>web.xml</c> file of the web application.
801       *       </p>
802       *    </dd>
803       * </dl>
804       *
805       * <h5 class='section'>Example:</h5>
806       * <p class='bjava'>
807       *    <jc>// Our child resource.</jc>
808       *    <ja>@Rest</ja>(path=<js>"/child"</js>)
809       *    <jk>public class</jk> MyChildResource {...}
810       *
811       *    <jc>// Option #1 - Registered via annotation.</jc>
812       *    <ja>@Rest</ja>(children={MyChildResource.<jk>class</jk>})
813       *    <jk>public class</jk> MyResource {
814       *
815       *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
816       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
817       *
818       *          <jc>// Using method on builder.</jc>
819       *          <jv>builder</jv>.children(MyChildResource.<jk>class</jk>);
820       *
821       *          <jc>// Use a pre-instantiated object instead.</jc>
822       *          <jv>builder</jv>.child(<js>"/child"</js>, <jk>new</jk> MyChildResource());
823       *       }
824       *
825       *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
826       *       <ja>@RestInit</ja>
827       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
828       *          <jv>builder</jv>.children(MyChildResource.<jk>class</jk>);
829       *       }
830       *    }
831       * </p>
832       *
833       * <h5 class='section'>Notes:</h5><ul>
834       *    <li class='note'>
835       *       When defined as classes, instances are resolved using the registered bean store which
836       *       by default is {@link BeanStore} which requires the class have one of the following
837       *       constructors:
838       *       <ul>
839       *          <li><code><jk>public</jk> T(RestContext.Builder)</code>
840       *          <li><code><jk>public</jk> T()</code>
841       *       </ul>
842       * </ul>
843       *
844       * <h5 class='section'>See Also:</h5><ul>
845       *    <li class='ja'>{@link Rest#children()}
846       * </ul>
847       *
848       * @param values The child resources to add.
849       *    <br>Cannot contain <jk>null</jk> values.
850       *    <br>Objects can be any of the specified types:
851       *    <ul>
852       *       <li>A class that has a constructor described above.
853       *       <li>An instantiated resource object (such as a servlet object instantiated by a servlet container).
854       *       <li>An instance of {@link RestChild} containing an instantiated resource object and a subpath.
855       *    </ul>
856       * @return This object.
857       */
858      public Builder children(Object...values) {
859         assertArgNoNulls("values", values);
860         addAll(children, values);
861         return this;
862      }
863
864      /**
865       * Client version header.
866       *
867       * <p>
868       * Specifies the name of the header used to denote the client version on HTTP requests.
869       *
870       * <p>
871       * The client version is used to support backwards compatibility for breaking REST interface changes.
872       * <br>Used in conjunction with {@link RestOp#clientVersion() @RestOp(clientVersion)} annotation.
873       *
874       * <h5 class='section'>Example:</h5>
875       * <p class='bjava'>
876       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
877       *    <ja>@Rest</ja>(clientVersionHeader=<js>"$C{REST/clientVersionHeader,Client-Version}"</js>)
878       *    <jk>public class</jk> MyResource {
879       *
880       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
881       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
882       *
883       *          <jc>// Using method on builder.</jc>
884       *          <jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
885       *       }
886       *
887       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
888       *       <ja>@RestInit</ja>
889       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
890       *          <jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
891       *       }
892       *    }
893       * </p>
894       *
895       * <p class='bjava'>
896       *    <jc>// Call this method if Client-Version is at least 2.0.
897       *    // Note that this also matches 2.0.1.</jc>
898       *    <ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"2.0"</js>)
899       *    <jk>public</jk> Object method1() {
900       *       ...
901       *    }
902       *
903       *    <jc>// Call this method if Client-Version is at least 1.1, but less than 2.0.</jc>
904       *    <ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"[1.1,2.0)"</js>)
905       *    <jk>public</jk> Object method2() {
906       *       ...
907       *    }
908       *
909       *    <jc>// Call this method if Client-Version is less than 1.1.</jc>
910       *    <ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"[0,1.1)"</js>)
911       *    <jk>public</jk> Object method3() {
912       *       ...
913       *    }
914       * </p>
915       *
916       * <h5 class='section'>See Also:</h5><ul>
917       *    <li class='ja'>{@link Rest#clientVersionHeader}
918       * </ul>
919       *
920       * @param value
921       *    The new value for this setting.
922       *    <br>The default is the first value found:
923       *    <ul>
924       *       <li>System property <js>"RestContext.clientVersionHeader"
925       *       <li>Environment variable <js>"RESTCONTEXT_CLIENTVERSIONHEADER"
926       *       <li><js>"Client-Version"</js>
927       *    </ul>
928       *    <br>Cannot be <jk>null</jk>.
929       * @return This object.
930       */
931      public Builder clientVersionHeader(String value) {
932         clientVersionHeader = assertArgNotNull("value", value);
933         return this;
934      }
935
936      /**
937       * Returns the external configuration file for this resource.
938       *
939       * <p>
940       * The config file contains arbitrary configuration information that can be accessed by this class, usually
941       * via <c>$C</c> variables.
942       *
943       * <p>
944       * The default config can be overridden via any of the following:
945       * <ul class='spaced-list'>
946       *    <li>Injected via bean store.
947       *    <li>Class annotation:  {@link Rest#config() @Rest(config)}
948       *    <li>{@link RestInject @RestInject}-annotated method:
949       *       <p class='bjava'>
950       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] Config myMethod(<i>&lt;args&gt;</i>) {...}
951       *       </p>
952       *       Args can be any injected bean.
953       * </ul>
954       *
955       * <p>
956       * If a config file is not set up, then an empty config file will be returned that is not backed by any file.
957       *
958       * <p>
959       * This bean can be accessed directly via {@link RestContext#getConfig()} or passed in as a parameter
960       * on a {@link RestOp}-annotated method.
961       *
962       * <h5 class='section'>See Also:</h5><ul>
963       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ConfigurationFiles">Configuration Files</a>
964       * </ul>
965       *
966       * @return The external configuration file for this resource.
967       */
968      public Config config() {
969         return config;
970      }
971
972      /**
973       * Overwrites the default config file with a custom config file.
974       *
975       * <p>
976       * By default, the config file is determined using the {@link Rest#config() @Rest(config)}
977       * annotation.
978       * This method allows you to programmatically override it with your own custom config file.
979       *
980       * <h5 class='section'>See Also:</h5><ul>
981       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ConfigurationFiles">Configuration Files</a>
982       *    <li class='jm'>{@link #config()}
983       * </ul>
984       *
985       * @param value The new config file.
986       *    <br>Cannot be <jk>null</jk>.
987       * @return This object.
988       */
989      public Builder config(Config value) {
990         config = assertArgNotNull("value", value);
991         return this;
992      }
993
994      /**
995       * Returns the media types consumed by this resource if it's manually specified.
996       *
997       * @return The media types.
998       */
999      public Optional<List<MediaType>> consumes() {
1000         return opt(consumes);
1001      }
1002
1003      /**
1004       * Supported content media types.
1005       *
1006       * <p>
1007       * Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource.
1008       * <br>An example where this might be useful if you have parsers registered that handle media types that you
1009       * don't want exposed in the Swagger documentation.
1010       *
1011       * <h5 class='section'>Example:</h5>
1012       * <p class='bjava'>
1013       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1014       *    <ja>@Rest</ja>(consumes={<js>"$C{REST/supportedConsumes,application/json}"</js>})
1015       *    <jk>public class</jk> MyResource {
1016       *
1017       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1018       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1019       *
1020       *          <jc>// Using method on builder.</jc>
1021       *          <jv>builder</jv>.consumes(<jk>false</jk>, <js>"application/json"</js>)
1022       *       }
1023       *
1024       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1025       *       <ja>@RestInit</ja>
1026       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1027       *          <jv>builder</jv>.consumes(<jk>false</jk>, <js>"application/json"</js>);
1028       *       }
1029       *    }
1030       * </p>
1031       *
1032       * <p>
1033       * This affects the returned values from the following:
1034       * <ul class='javatree'>
1035       *    <li class='jm'>{@link RestContext#getConsumes() RestContext.getConsumes()}
1036       * </ul>
1037       *
1038       * <h5 class='section'>See Also:</h5><ul>
1039       *    <li class='ja'>{@link Rest#consumes}
1040       *    <li class='ja'>{@link RestOp#consumes}
1041       *    <li class='ja'>{@link RestPut#consumes}
1042       *    <li class='ja'>{@link RestPost#consumes}
1043       * </ul>
1044       *
1045       * @param values The values to add to this setting.
1046       *    <br>Cannot contain <jk>null</jk> values.
1047       * @return This object.
1048       */
1049      public Builder consumes(MediaType...values) {
1050         assertArgNoNulls("values", values);
1051         consumes = addAll(consumes, values);
1052         return this;
1053      }
1054
1055      @Override /* Overridden from Context.Builder */
1056      public Builder copy() {
1057         throw new NoSuchMethodError("Not implemented.");
1058      }
1059
1060      @Override /* Overridden from Builder */
1061      public Builder debug() {
1062         super.debug();
1063         return this;
1064      }
1065
1066      @Override /* Overridden from Builder */
1067      public Builder debug(boolean value) {
1068         super.debug(value);
1069         return this;
1070      }
1071
1072      /**
1073       * Sets the debug default value.
1074       *
1075       * <p>
1076       * The default debug value is the enablement value if not otherwise overridden at the class or method level.
1077       *
1078       * @param value The debug default value.
1079       *    <br>Cannot be <jk>null</jk>.
1080       * @return This object.
1081       */
1082      public Builder debugDefault(Enablement value) {
1083         defaultSettings().set("RestContext.debugDefault", assertArgNotNull("value", value));
1084         return this;
1085      }
1086
1087      /**
1088       * Returns the debug enablement bean creator.
1089       *
1090       * <p>
1091       * Enables the following:
1092       * <ul class='spaced-list'>
1093       *    <li>
1094       *       HTTP request/response bodies are cached in memory for logging purposes.
1095       *    <li>
1096       *       Request/response messages are automatically logged always or per request.
1097       * </ul>
1098       *
1099       * @return The debug enablement sub-builder.
1100       */
1101      public BeanCreator<DebugEnablement> debugEnablement() {
1102         if (debugEnablement == null)
1103            debugEnablement = createDebugEnablement(beanStore, resource);
1104         return debugEnablement;
1105      }
1106
1107      /**
1108       * Specifies the debug enablement class to use for this REST context.
1109       *
1110       * @param value The new value for this setting.
1111       *    <br>Cannot be <jk>null</jk>.
1112       * @return This object.
1113       */
1114      public Builder debugEnablement(Class<? extends DebugEnablement> value) {
1115         debugEnablement().type(assertArgNotNull("value", value));
1116         return this;
1117      }
1118
1119      /**
1120       * Specifies the debug enablement class to use for this REST context.
1121       *
1122       * @param value The new value for this setting.
1123       *    <br>Cannot be <jk>null</jk>.
1124       * @return This object.
1125       */
1126      public Builder debugEnablement(DebugEnablement value) {
1127         debugEnablement().impl(assertArgNotNull("value", value));
1128         return this;
1129      }
1130
1131      /**
1132       * Specifies a default <c>Accept</c> header value if not specified on a request.
1133       *
1134       * @param value
1135       *    The default value of the <c>Accept</c> header.
1136       *    <br>Ignored if <jk>null</jk> or empty.
1137       * @return This object.
1138       */
1139      public Builder defaultAccept(String value) {
1140         if (ne(value))
1141            defaultRequestHeaders(accept(value));
1142         return this;
1143      }
1144
1145      /**
1146       * Default character encoding.
1147       *
1148       * <p>
1149       * The default character encoding for the request and response if not specified on the request.
1150       *
1151       * <h5 class='section'>Example:</h5>
1152       * <p class='bjava'>
1153       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1154       *    <ja>@Rest</ja>(defaultCharset=<js>"$C{REST/defaultCharset,US-ASCII}"</js>)
1155       *    <jk>public class</jk> MyResource {
1156       *
1157       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1158       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1159       *
1160       *          <jc>// Using method on builder.</jc>
1161       *          <jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
1162       *       }
1163       *
1164       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1165       *       <ja>@RestInit</ja>
1166       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1167       *          <jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
1168       *       }
1169       *
1170       *       <jc>// Override at the method level.</jc>
1171       *       <ja>@RestGet</ja>(defaultCharset=<js>"UTF-16"</js>)
1172       *       <jk>public</jk> Object myMethod() {...}
1173       *    }
1174       * </p>
1175       *
1176       * <h5 class='section'>See Also:</h5><ul>
1177       *    <li class='ja'>{@link Rest#defaultCharset}
1178       *    <li class='ja'>{@link RestOp#defaultCharset}
1179       * </ul>
1180       *
1181       * @param value
1182       *    The new value for this setting.
1183       *    <br>The default is the first value found:
1184       *    <ul>
1185       *       <li>System property <js>"RestContext.defaultCharset"
1186       *       <li>Environment variable <js>"RESTCONTEXT_defaultCharset"
1187       *       <li><js>"utf-8"</js>
1188       *    </ul>
1189       *    <br>Cannot be <jk>null</jk>.
1190       * @return This object.
1191       */
1192      public Builder defaultCharset(Charset value) {
1193         defaultCharset = assertArgNotNull("value", value);
1194         return this;
1195      }
1196
1197      /**
1198       * Returns the default implementation class list.
1199       *
1200       * <p>
1201       * This defines the implementation classes for a variety of bean types.
1202       *
1203       * <p>
1204       * Default classes are inherited from the parent REST object.
1205       * Typically used on the top-level {@link RestContext.Builder} to affect class types for that REST object and all children.
1206       *
1207       * <p>
1208       * Modifying the default class list on this builder does not affect the default class list on the parent builder, but changes made
1209       * here are inherited by child builders.
1210       *
1211       * @return The default implementation class list.
1212       */
1213      public DefaultClassList defaultClasses() {
1214         return defaultClasses;
1215      }
1216
1217      /**
1218       * Adds to the default implementation class list.
1219       *
1220       * <p>
1221       * A shortcut for the following code:
1222       *
1223       * <p class='bjava'>
1224       *    <jv>builder</jv>.defaultClasses().add(<jv>values</jv>);
1225       * </p>
1226       *
1227       * @param values The values to add to the list of default classes.
1228       *    <br>Cannot contain <jk>null</jk> values.
1229       * @return This object.
1230       * @see #defaultClasses()
1231       */
1232      public Builder defaultClasses(Class<?>...values) {
1233         assertArgNoNulls("values", values);
1234         defaultClasses().add(values);
1235         return this;
1236      }
1237
1238      /**
1239       * Specifies a default <c>Content-Type</c> header value if not specified on a request.
1240       *
1241       * @param value
1242       *    The default value of the <c>Content-Type</c> header.
1243       *    <br>Ignored if <jk>null</jk> or empty.
1244       * @return This object.
1245       */
1246      public Builder defaultContentType(String value) {
1247         if (ne(value))
1248            defaultRequestHeaders(contentType(value));
1249         return this;
1250      }
1251
1252      /**
1253       * Returns the default request attributes sub-builder.
1254       *
1255       * @return The default request attributes sub-builder.
1256       */
1257      public NamedAttributeMap defaultRequestAttributes() {
1258         if (defaultRequestAttributes == null)
1259            defaultRequestAttributes = createDefaultRequestAttributes(beanStore(), resource());
1260         return defaultRequestAttributes;
1261      }
1262
1263      /**
1264       * Default request attributes.
1265       *
1266       * <p>
1267       * Specifies default values for request attributes if they're not already set on the request.
1268       *
1269       * Affects values returned by the following methods:
1270       * <ul>
1271       *    <li class='jm'>{@link RestRequest#getAttribute(String)}.
1272       *    <li class='jm'>{@link RestRequest#getAttributes()}.
1273       * </ul>
1274       *
1275       * <h5 class='section'>Example:</h5>
1276       * <p class='bjava'>
1277       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1278       *    <ja>@Rest</ja>(defaultRequestAttributes={<js>"Foo=bar"</js>, <js>"Baz: $C{REST/myAttributeValue}"</js>})
1279       *    <jk>public class</jk> MyResource {
1280       *
1281       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1282       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1283       *
1284       *          <jc>// Using method on builder.</jc>
1285       *          <jv>builder</jv>
1286       *             .defaultRequestAttributes(
1287       *                BasicNamedAttribute.<jsm>of</jsm>(<js>"Foo"</js>, <js>"bar"</js>),
1288       *                BasicNamedAttribute.<jsm>of</jsm>(<js>"Baz"</js>, <jk>true</jk>)
1289       *             );
1290       *       }
1291       *
1292       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1293       *       <ja>@RestInit</ja>
1294       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1295       *          <jv>builder</jv>.defaultRequestAttribute(<js>"Foo"</js>, <js>"bar"</js>);
1296       *       }
1297       *
1298       *       <jc>// Override at the method level.</jc>
1299       *       <ja>@RestGet</ja>(defaultRequestAttributes={<js>"Foo: bar"</js>})
1300       *       <jk>public</jk> Object myMethod() {...}
1301       *    }
1302       * </p>
1303       *
1304       * <h5 class='section'>Notes:</h5><ul>
1305       *    <li class='note'>Use {@link BasicNamedAttribute#of(String, Supplier)} to provide a dynamically changeable attribute value.
1306       * </ul>
1307       *
1308       * @param values The attributes.
1309       *    <br>Cannot contain <jk>null</jk> values.
1310       * @return This object.
1311       */
1312      public Builder defaultRequestAttributes(NamedAttribute...values) {
1313         assertArgNoNulls("values", values);
1314         defaultRequestAttributes().add(values);
1315         return this;
1316      }
1317
1318      /**
1319       * Returns the default request headers.
1320       *
1321       * @return The default request headers.
1322       */
1323      public HeaderList defaultRequestHeaders() {
1324         if (defaultRequestHeaders == null)
1325            defaultRequestHeaders = createDefaultRequestHeaders(beanStore(), resource());
1326         return defaultRequestHeaders;
1327      }
1328
1329      /**
1330       * Default request headers.
1331       *
1332       * <p>
1333       * Specifies default values for request headers if they're not passed in through the request.
1334       *
1335       * <h5 class='section'>Notes:</h5><ul>
1336       *    <li class='note'>
1337       *       Affects values returned by {@link RestRequest#getHeader(String)} when the header is not present on the request.
1338       *    <li class='note'>
1339       *       The most useful reason for this annotation is to provide a default <c>Accept</c> header when one is not
1340       *       specified so that a particular default {@link Serializer} is picked.
1341       * </ul>
1342       *
1343       * <h5 class='section'>Example:</h5>
1344       * <p class='bjava'>
1345       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1346       *    <ja>@Rest</ja>(defaultRequestHeaders={<js>"Accept: application/json"</js>, <js>"My-Header=$C{REST/myHeaderValue}"</js>})
1347       *    <jk>public class</jk> MyResource {
1348       *
1349       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1350       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1351       *
1352       *          <jc>// Using method on builder.</jc>
1353       *          <jv>builder</jv>
1354       *             .defaultRequestHeaders(
1355       *                Accept.<jsm>of</jsm>(<js>"application/json"</js>),
1356       *                BasicHeader.<jsm>of</jsm>(<js>"My-Header"</js>, <js>"foo"</js>)
1357       *             );
1358       *       }
1359       *
1360       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1361       *       <ja>@RestInit</ja>
1362       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1363       *          <jv>builder</jv>.defaultRequestHeaders(Accept.<jsm>of</jsm>(<js>"application/json"</js>));
1364       *       }
1365       *
1366       *       <jc>// Override at the method level.</jc>
1367       *       <ja>@RestGet</ja>(defaultRequestHeaders={<js>"Accept: text/xml"</js>})
1368       *       <jk>public</jk> Object myMethod() {...}
1369       *    }
1370       * </p>
1371       *
1372       * <h5 class='section'>See Also:</h5><ul>
1373       *    <li class='ja'>{@link Rest#defaultRequestHeaders}
1374       *    <li class='ja'>{@link RestOp#defaultRequestHeaders}
1375       *    <li class='ja'>{@link RestGet#defaultRequestHeaders}
1376       *    <li class='ja'>{@link RestPut#defaultRequestHeaders}
1377       *    <li class='ja'>{@link RestPost#defaultRequestHeaders}
1378       *    <li class='ja'>{@link RestDelete#defaultRequestHeaders}
1379       * </ul>
1380       *
1381       * @param values The headers to add.
1382       *    <br>Cannot contain <jk>null</jk> values.
1383       * @return This object.
1384       */
1385      public Builder defaultRequestHeaders(Header...values) {
1386         assertArgNoNulls("values", values);
1387         defaultRequestHeaders().setDefault(values);
1388         return this;
1389      }
1390
1391      /**
1392       * Returns the default response headers.
1393       *
1394       * @return The default response headers.
1395       */
1396      public HeaderList defaultResponseHeaders() {
1397         if (defaultResponseHeaders == null)
1398            defaultResponseHeaders = createDefaultResponseHeaders(beanStore(), resource());
1399         return defaultResponseHeaders;
1400      }
1401
1402      /**
1403       * Default response headers.
1404       *
1405       * <p>
1406       * Specifies default values for response headers if they're not set after the Java REST method is called.
1407       *
1408       * <h5 class='section'>Notes:</h5><ul>
1409       *    <li class='note'>
1410       *       This is equivalent to calling {@link RestResponse#setHeader(String, String)} programmatically in each of
1411       *       the Java methods.
1412       *    <li class='note'>
1413       *       The header value will not be set if the header value has already been specified (hence the 'default' in the name).
1414       * </ul>
1415       *
1416       * <h5 class='section'>Example:</h5>
1417       * <p class='bjava'>
1418       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1419       *    <ja>@Rest</ja>(defaultResponseHeaders={<js>"Content-Type: $C{REST/defaultContentType,text/plain}"</js>,<js>"My-Header: $C{REST/myHeaderValue}"</js>})
1420       *    <jk>public class</jk> MyResource {
1421       *
1422       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1423       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1424       *
1425       *          <jc>// Using method on builder.</jc>
1426       *          <jv>builder</jv>
1427       *             .defaultResponseHeaders(
1428       *                ContentType.<jsm>of</jsm>(<js>"text/plain"</js>),
1429       *                BasicHeader.<jsm>ofPair</jsm>(<js>"My-Header: foo"</js>)
1430       *             );
1431       *       }
1432       *
1433       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1434       *       <ja>@RestInit</ja>
1435       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1436       *          <jv>builder</jv>.defaultResponseHeaders(ContentType.<jsm>of</jsm>(<js>"text/plain"</js>));
1437       *       }
1438       *    }
1439       * </p>
1440       *
1441       * <h5 class='section'>See Also:</h5><ul>
1442       *    <li class='ja'>{@link Rest#defaultResponseHeaders}
1443       *    <li class='ja'>{@link RestOp#defaultResponseHeaders}
1444       *    <li class='ja'>{@link RestGet#defaultResponseHeaders}
1445       *    <li class='ja'>{@link RestPut#defaultResponseHeaders}
1446       *    <li class='ja'>{@link RestPost#defaultResponseHeaders}
1447       *    <li class='ja'>{@link RestDelete#defaultResponseHeaders}
1448       * </ul>
1449       *
1450       * @param values The headers to add.
1451       *    <br>Cannot contain <jk>null</jk> values.
1452       * @return This object.
1453       */
1454      public Builder defaultResponseHeaders(Header...values) {
1455         assertArgNoNulls("values", values);
1456         defaultResponseHeaders().setDefault(values);
1457         return this;
1458      }
1459
1460      /**
1461       * Sets a value in the default settings map.
1462       *
1463       * <p>
1464       * A shortcut for the following code:
1465       *
1466       * <p class='bjava'>
1467       *    <jv>builder</jv>.defaultSettings().add(<jv>key</jv>, <jv>value</jv>);
1468       *
1469       * </p>
1470       * @param key The setting key.
1471       *    <br>Cannot be <jk>null</jk>.
1472       * @param value The setting value.
1473       * @return This object.
1474       * @see #defaultSettings()
1475       */
1476      public Builder defaultSetting(String key, Object value) {
1477         defaultSettings().set(assertArgNotNull("key", key), value);
1478         return this;
1479      }
1480
1481      /**
1482       * Returns the default settings map.
1483       *
1484       * <p>
1485       * Default settings are inherited from the parent REST object.
1486       * Typically used on the top-level {@link RestContext.Builder} to affect settings for that REST object and all children.
1487       *
1488       * <p>
1489       * Modifying the default settings map on this builder does not affect the default settings on the parent builder, but changes made
1490       * here are inherited by child builders.
1491       *
1492       * @return The default settings map.
1493       */
1494      public DefaultSettingsMap defaultSettings() {
1495         return defaultSettings;
1496      }
1497
1498      /**
1499       * Returns the destroy method list.
1500       *
1501       * @return The destroy method list.
1502       */
1503      public MethodList destroyMethods() {
1504         if (destroyMethods == null)
1505            destroyMethods = createDestroyMethods(beanStore(), resource());
1506         return destroyMethods;
1507      }
1508
1509      /**
1510       * Disable content URL parameter.
1511       *
1512       * <p>
1513       * When enabled, the HTTP content content on PUT and POST requests can be passed in as text using the <js>"content"</js>
1514       * URL parameter.
1515       * <br>
1516       * For example:
1517       * <p class='burlenc'>
1518       *  ?content=(name='John%20Smith',age=45)
1519       * </p>
1520       *
1521       * <h5 class='section'>Example:</h5>
1522       * <p class='bjava'>
1523       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1524       *    <ja>@Rest</ja>(disableContentParam=<js>"$C{REST/disableContentParam,true}"</js>)
1525       *    <jk>public class</jk> MyResource {
1526       *
1527       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1528       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1529       *
1530       *          <jc>// Using method on builder.</jc>
1531       *          <jv>builder</jv>.disableContentParam();
1532       *       }
1533       *
1534       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1535       *       <ja>@RestInit</ja>
1536       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1537       *          <jv>builder</jv>.disableContentParam();
1538       *       }
1539       *    }
1540       * </p>
1541       *
1542       * <h5 class='section'>Notes:</h5><ul>
1543       *    <li class='note'>
1544       *       <js>'content'</js> parameter name is case-insensitive.
1545       *    <li class='note'>
1546       *       Useful for debugging PUT and POST methods using only a browser.
1547       * </ul>
1548       *
1549       * @return This object.
1550       */
1551      public Builder disableContentParam() {
1552         return disableContentParam(true);
1553      }
1554
1555      /**
1556       * Disable content URL parameter.
1557       *
1558       * <p>
1559       * Same as {@link #disableContentParam()} but allows you to set it as a boolean value.
1560       *
1561       * @param value The new value for this setting.
1562       * @return This object.
1563       */
1564      public Builder disableContentParam(boolean value) {
1565         disableContentParam = value;
1566         return this;
1567      }
1568
1569      /**
1570       * Returns the encoder group sub-builder.
1571       *
1572       * <p>
1573       * Encoders are used to decode HTTP requests and encode HTTP responses based on {@code Content-Encoding} and {@code Accept-Encoding}
1574       * headers.
1575       *
1576       * <p>
1577       * The default encoder set has support for identity incoding only.
1578       * It can be overridden via any of the following:
1579       * <ul class='spaced-list'>
1580       *    <li>Injected via bean store.
1581       *    <li>Class annotation: {@link Rest#encoders() @Rest(encoders)}
1582       *    <li>{@link RestInject @RestInject}-annotated method:
1583       *       <p class='bjava'>
1584       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] EncoderSet myMethod(<i>&lt;args&gt;</i>) {...}
1585       *       </p>
1586       *       Args can be any injected bean including EncoderSet.Builder, the default builder.
1587       * </ul>
1588       *
1589       * <h5 class='section'>See Also:</h5><ul>
1590       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerEncoders">Encoders</a>
1591       * </ul>
1592       *
1593       * @return The builder for the {@link EncoderSet} object in the REST context.
1594       */
1595      public EncoderSet.Builder encoders() {
1596         if (encoders == null)
1597            encoders = createEncoders(beanStore(), resource());
1598         return encoders;
1599      }
1600
1601      /**
1602       * Adds one or more encoders to this class.
1603       *
1604       * <p>
1605       * Equivalent to calling:
1606       * <p class='bjava'>
1607       *    <jv>builder</jv>.encoders().add(<jv>value</jv>);
1608       * </p>
1609       *
1610       * <h5 class='section'>See Also:</h5><ul>
1611       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerEncoders">Encoders</a>
1612       *    <li class='jm'>{@link #encoders()}
1613       * </ul>
1614       *
1615       * @param value The values to add.
1616       *    <br>Cannot contain <jk>null</jk> values.
1617       * @return This object.
1618       */
1619      @SafeVarargs
1620      public final Builder encoders(Class<? extends Encoder>...value) {
1621         assertArgNoNulls("value", value);
1622         encoders().add(value);
1623         return this;
1624      }
1625
1626      /**
1627       * Adds one or more encoders to this class.
1628       *
1629       * <p>
1630       * Equivalent to calling:
1631       * <p class='bjava'>
1632       *    <jv>builder</jv>.encoders().add(<jv>value</jv>);
1633       * </p>
1634       *
1635       * <h5 class='section'>See Also:</h5><ul>
1636       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerEncoders">Encoders</a>
1637       *    <li class='jm'>{@link #encoders()}
1638       * </ul>
1639       *
1640       * @param value The values to add.
1641       *    <br>Cannot contain <jk>null</jk> values.
1642       * @return This object.
1643       */
1644      public Builder encoders(Encoder...value) {
1645         assertArgNoNulls("value", value);
1646         encoders().add(value);
1647         return this;
1648      }
1649
1650      /**
1651       * Returns the end call method list.
1652       *
1653       * @return The end call method list.
1654       */
1655      public MethodList endCallMethods() {
1656         if (endCallMethods == null)
1657            endCallMethods = createEndCallMethods(beanStore(), resource());
1658         return endCallMethods;
1659      }
1660
1661      /**
1662       * Returns the encoder group builder containing the encoders for compressing/decompressing input and output streams.
1663       *
1664       * <p>
1665       * These can be used to enable various kinds of compression (e.g. <js>"gzip"</js>) on requests and responses.
1666       *
1667       * <p>
1668       * The builder is initialized with encoders defined via the {@link Rest#encoders()} annotation.  That annotation is applied
1669       * from parent-to-child order with child entries given priority over parent entries.
1670       *
1671       * <h5 class='section'>See Also:</h5><ul>
1672       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerEncoders">Encoders</a>
1673       * </ul>
1674       *
1675       * @return The encoder group builder for this context builder.
1676       */
1677      public EncoderSet.Builder getEncoders() { return encoders; }
1678
1679      @Override /* Overridden from ServletConfig */
1680      public String getInitParameter(String name) {
1681         return inner == null ? null : inner.getInitParameter(name);
1682      }
1683
1684      @Override /* Overridden from ServletConfig */
1685      public Enumeration<String> getInitParameterNames() { return inner == null ? new Vector<String>().elements() : inner.getInitParameterNames(); }
1686
1687      /**
1688       * Returns the parser group builder containing the parsers for converting HTTP request bodies into POJOs.
1689       *
1690       * <p>
1691       * Parsers are used to convert the content of HTTP requests into POJOs.
1692       * <br>Any of the Juneau framework parsers can be used in this setting.
1693       * <br>The parser selected is based on the request <c>Content-Type</c> header matched against the values returned by the following method
1694       * using a best-match algorithm:
1695       * <ul class='javatree'>
1696       *    <li class='jm'>{@link Parser#getMediaTypes()}
1697       * </ul>
1698       *
1699       * <p>
1700       * The builder is initialized with parsers defined via the {@link Rest#parsers()} annotation.  That annotation is applied
1701       * from parent-to-child order with child entries given priority over parent entries.
1702       *
1703       * <h5 class='section'>See Also:</h5><ul>
1704       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
1705       * </ul>
1706       *
1707       * @return The parser group builder for this context builder.
1708       */
1709      public ParserSet.Builder getParsers() { return parsers; }
1710
1711      /**
1712       * Returns the serializer group builder containing the serializers for marshalling POJOs into response bodies.
1713       *
1714       * <p>
1715       * Serializer are used to convert POJOs to HTTP response bodies.
1716       * <br>Any of the Juneau framework serializers can be used in this setting.
1717       * <br>The serializer selected is based on the request <c>Accept</c> header matched against the values returned by the following method
1718       * using a best-match algorithm:
1719       * <ul class='javatree'>
1720       *    <li class='jm'>{@link Serializer#getMediaTypeRanges()}
1721       * </ul>
1722       *
1723       * <p>
1724       * The builder is initialized with serializers defined via the {@link Rest#serializers()} annotation.  That annotation is applied
1725       * from parent-to-child order with child entries given priority over parent entries.
1726       *
1727       * <h5 class='section'>See Also:</h5><ul>
1728       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
1729       * </ul>
1730       *
1731       * @return The serializer group builder for this context builder.
1732       */
1733      public SerializerSet.Builder getSerializers() { return serializers; }
1734
1735      @Override /* Overridden from ServletConfig */
1736      public ServletContext getServletContext() {
1737         return nn(inner) ? inner.getServletContext() : nn(parentContext) ? parentContext.getBuilder().getServletContext() : null;
1738      }
1739
1740      @Override /* Overridden from ServletConfig */
1741      public String getServletName() { return inner == null ? null : inner.getServletName(); }
1742
1743      @Override /* Overridden from Builder */
1744      public Builder impl(Context value) {
1745         super.impl(value);
1746         return this;
1747      }
1748
1749      /**
1750       * Performs initialization on this builder against the specified REST servlet/bean instance.
1751       *
1752       * @param resource
1753       *    The REST servlet/bean instance that this context is defined against.
1754       *    <br>Cannot be <jk>null</jk>.
1755       * @return This object.
1756       * @throws ServletException If hook method calls failed.
1757       */
1758      public Builder init(Supplier<?> resource) throws ServletException {
1759
1760         if (initialized)
1761            return this;
1762         initialized = true;
1763
1764         this.resource = new ResourceSupplier(resourceClass, assertArgNotNull("resource", resource));
1765         var r = this.resource;
1766         var rc = resourceClass;
1767
1768         // @formatter:off
1769         beanStore = createBeanStore(resource)
1770            .build()
1771            .addBean(Builder.class, this)
1772            .addBean(ResourceSupplier.class, this.resource)
1773            .addBean(ServletConfig.class, nn(inner) ? inner : this)
1774            .addBean(ServletContext.class, (nn(inner) ? inner : this).getServletContext());
1775         // @formatter:on
1776
1777         if (rootBeanStore == null) {
1778            rootBeanStore = beanStore;
1779            beanStore = BeanStore.of(rootBeanStore, r.get());
1780         }
1781         var bs = beanStore;
1782
1783         beanStore.add(BeanStore.class, bs);
1784         varResolver = createVarResolver(bs, r, rc);
1785         beanStore.add(VarResolver.class, varResolver.build());
1786         config = beanStore.add(Config.class, createConfig(bs, r, rc));
1787         beanStore.add(VarResolver.class, varResolver.bean(Config.class, config).build());
1788
1789         var rci = ClassInfo.of(resourceClass);
1790
1791         // Get @RestInject fields initialized with values.
1792         // @formatter:off
1793         rci.getAllFields().stream()
1794            .filter(x -> x.hasAnnotation(RestInject.class))
1795            .forEach(x -> opt(x.get(resource.get())).ifPresent(
1796               y -> beanStore.add(
1797                  x.getFieldType().inner(),
1798                  y,
1799                  RestInjectAnnotation.name(x.getAnnotations(RestInject.class).findFirst().map(AnnotationInfo::inner).orElse(null))
1800               )
1801            ));
1802         // @formatter:on
1803
1804         rci.getAllMethods().stream().filter(x -> x.hasAnnotation(RestInject.class)).forEach(x -> {
1805            var rt = x.getReturnType().<Object>inner();
1806            var name = RestInjectAnnotation.name(x.getAnnotations(RestInject.class).findFirst().map(AnnotationInfo::inner).orElse(null));
1807            if (! (DELAYED_INJECTION.contains(rt) || DELAYED_INJECTION_NAMES.contains(name))) {
1808               // @formatter:off
1809               beanStore
1810                  .createMethodFinder(rt)
1811                  .find(Builder::isRestInjectMethod)
1812                  .run(y -> beanStore.add(rt, y, name));
1813               // @formatter:on
1814            }
1815         });
1816
1817         var vrs = varResolver().build().createSession();
1818         var work = AnnotationWorkList.of(vrs, rstream(AP.find(rci)).filter(CONTEXT_APPLY_FILTER));
1819
1820         apply(work);
1821         beanContext().apply(work);
1822         partSerializer().apply(work);
1823         partParser().apply(work);
1824         jsonSchemaGenerator().apply(work);
1825
1826         runInitHooks(bs, resource());
1827
1828         // Set @RestInject fields not initialized with values.
1829         // @formatter:off
1830         rci.getAllFields().stream()
1831            .filter(x -> x.hasAnnotation(RestInject.class))
1832            .forEach(x -> x.setIfNull(
1833               resource.get(),
1834               beanStore.getBean(
1835                  x.getFieldType().inner(),
1836                  RestInjectAnnotation.name(x.getAnnotations(RestInject.class).findFirst().map(AnnotationInfo::inner).orElse(null))
1837               ).orElse(null)
1838            ));
1839         // @formatter:on
1840
1841         return this;
1842      }
1843
1844      /**
1845       * Returns the JSON schema generator sub-builder.
1846       *
1847       * <p>
1848       * The JSON schema generator is used for generating JSON schema in the auto-generated Swagger documentation.
1849       *
1850       * <p>
1851       * The default JSON schema generator is a default {@link JsonSchemaGenerator}.
1852       * It can overridden via any of the following:
1853       * <ul class='spaced-list'>
1854       *    <li>Injected via bean store.
1855       *    <li>{@link RestInject @RestInject}-annotated method:
1856       *       <p class='bjava'>
1857       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] JsonSchemaGenerator myMethod(<i>&lt;args&gt;</i>) {...}
1858       *       </p>
1859       *       Args can be any injected bean including JsonSchemaGenerator.Builder, the default builder.
1860       * </ul>
1861       *
1862       * <h5 class='section'>See Also:</h5><ul>
1863       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
1864       * </ul>
1865       *
1866       * @return The JSON schema generator sub-builder.
1867       */
1868      public JsonSchemaGenerator.Builder jsonSchemaGenerator() {
1869         if (jsonSchemaGenerator == null)
1870            jsonSchemaGenerator = createJsonSchemaGenerator(beanStore(), resource());
1871         return jsonSchemaGenerator;
1872      }
1873
1874      /**
1875       * Specifies the JSON schema generator for this class.
1876       *
1877       * <p>
1878       * Equivalent to calling:
1879       * <p class='bjava'>
1880       *    <jv>builder</jv>.jsonSchemaGenerator().type(<jv>value</jv>);
1881       * </p>
1882       *
1883       * <h5 class='section'>See Also:</h5><ul>
1884       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
1885       *    <li class='jm'>{@link #jsonSchemaGenerator()}
1886       * </ul>
1887       *
1888       * @param value The new value.
1889       *    <br>Cannot be <jk>null</jk>.
1890       * @return This object.
1891       */
1892      public Builder jsonSchemaGenerator(Class<? extends JsonSchemaGenerator> value) {
1893         jsonSchemaGenerator().type(assertArgNotNull("value", value));
1894         return this;
1895      }
1896
1897      /**
1898       * Specifies the JSON schema generator for this class.
1899       *
1900       * <p>
1901       * Equivalent to calling:
1902       * <p class='bjava'>
1903       *    <jv>builder</jv>.jsonSchemaGenerator().impl(<jv>value</jv>);
1904       *    <li class='jm'>{@link #jsonSchemaGenerator()}
1905       * </p>
1906       *
1907       * <h5 class='section'>See Also:</h5><ul>
1908       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
1909       * </ul>
1910       *
1911       * @param value The new value.
1912       *    <br>Cannot be <jk>null</jk>.
1913       * @return This object.
1914       */
1915      public Builder jsonSchemaGenerator(JsonSchemaGenerator value) {
1916         jsonSchemaGenerator().impl(assertArgNotNull("value", value));
1917         return this;
1918      }
1919
1920      /**
1921       * Returns the logger for this resource.
1922       *
1923       * <p>
1924       * The logger is used in the following locations:
1925       * <ul>
1926       *    <li>{@link RestServlet#log(Level, Throwable, String, Object...)} and related methods.
1927       *    <li>{@link RestObject#log(Level, Throwable, String, Object...)} and related methods.
1928       *    <li>In the {@link #callLogger()} of this resource.
1929       * </ul>
1930       * It can also be accessed directly via {@link RestContext#getLogger()} or passed in as a parameter
1931       * on a {@link RestOp}-annotated method.
1932       *
1933       * <p>
1934       * The default config can be overridden via any of the following:
1935       * <ul class='spaced-list'>
1936       *    <li>Injected via bean store.
1937       *    <li>{@link RestInject @RestInject}-annotated method:
1938       *       <p class='bjava'>
1939       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] Logger myMethod(<i>&lt;args&gt;</i>) {...}
1940       *       </p>
1941       *       Args can be any injected bean.
1942       * </ul>
1943       *
1944       * <h5 class='section'>See Also:</h5><ul>
1945       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
1946       * </ul>
1947       *
1948       * @return The logger for this resource.
1949       */
1950      public Logger logger() {
1951         if (logger == null)
1952            logger = createLogger(beanStore(), resource, resourceClass);
1953         return logger;
1954      }
1955
1956      /**
1957       * Sets the logger for this resource.
1958       *
1959       * <h5 class='section'>See Also:</h5><ul>
1960       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
1961       *    <li class='jm'>{@link #logger()}
1962       * </ul>
1963       *
1964       * @param value The logger to use for the REST resource.
1965       *    <br>Cannot be <jk>null</jk>.
1966       * @return This object.
1967       */
1968      public Builder logger(Logger value) {
1969         logger = assertArgNotNull("value", value);
1970         return this;
1971      }
1972
1973      /**
1974       * The maximum allowed input size (in bytes) on HTTP requests.
1975       *
1976       * <p>
1977       * Useful for alleviating DoS attacks by throwing an exception when too much input is received instead of resulting
1978       * in out-of-memory errors which could affect system stability.
1979       *
1980       * <h5 class='section'>Example:</h5>
1981       * <p class='bjava'>
1982       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1983       *    <ja>@Rest</ja>(maxInput=<js>"$C{REST/maxInput,10M}"</js>)
1984       *    <jk>public class</jk> MyResource {
1985       *
1986       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1987       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1988       *
1989       *          <jc>// Using method on builder.</jc>
1990       *          <jv>builder</jv>.maxInput(<js>"10M"</js>);
1991       *       }
1992       *
1993       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1994       *       <ja>@RestInit</ja>
1995       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
1996       *          <jv>builder</jv>.maxInput(<js>"10M"</js>);
1997       *       }
1998       *
1999       *       <jc>// Override at the method level.</jc>
2000       *       <ja>@RestPost</ja>(maxInput=<js>"10M"</js>)
2001       *       <jk>public</jk> Object myMethod() {...}
2002       *    }
2003       * </p>
2004       *
2005       * <h5 class='section'>Notes:</h5><ul>
2006       *    <li class='note'>
2007       *       String value that gets resolved to a <jk>long</jk>.
2008       *    <li class='note'>
2009       *       Can be suffixed with any of the following representing kilobytes, megabytes, and gigabytes:
2010       *       <js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
2011       *    <li class='note'>
2012       *       A value of <js>"-1"</js> can be used to represent no limit.
2013       * </ul>
2014       *
2015       * <h5 class='section'>See Also:</h5><ul>
2016       *    <li class='ja'>{@link Rest#maxInput}
2017       *    <li class='ja'>{@link RestOp#maxInput}
2018       *    <li class='jm'>{@link RestOpContext.Builder#maxInput(String)}
2019       * </ul>
2020       *
2021       * @param value
2022       *    The new value for this setting.
2023       *    <br>The default is the first value found:
2024       *    <ul>
2025       *       <li>System property <js>"RestContext.maxInput"
2026       *       <li>Environment variable <js>"RESTCONTEXT_MAXINPUT"
2027       *       <li><js>"100M"</js>
2028       *    </ul>
2029       *    <br>The default is <js>"100M"</js>.
2030       *    <br>Cannot be <jk>null</jk>.
2031       * @return This object.
2032       */
2033      public Builder maxInput(String value) {
2034         maxInput = StringUtils.parseLongWithSuffix(assertArgNotNull("value", value));
2035         return this;
2036      }
2037
2038      /**
2039       * Returns the messages sub-builder.
2040       *
2041       * <p>
2042       * Messages beans are wrappers around resource bundles containing localized messages.
2043       *
2044       * <p>
2045       * By default, the resource bundle name is assumed to match the class name.  For example, given the class
2046       * <c>MyClass.java</c>, the resource bundle is assumed to be <c>MyClass.properties</c>.  This property
2047       * allows you to override this setting to specify a different location such as <c>MyMessages.properties</c> by
2048       * specifying a value of <js>"MyMessages"</js>.
2049       *
2050       * <p>
2051       *    Resource bundles are searched using the following base name patterns:
2052       *    <ul>
2053       *       <li><js>"{package}.{name}"</js>
2054       *       <li><js>"{package}.i18n.{name}"</js>
2055       *       <li><js>"{package}.nls.{name}"</js>
2056       *       <li><js>"{package}.messages.{name}"</js>
2057       *    </ul>
2058       *
2059       * <p>
2060       * This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following methods:
2061       * <ul class='javatree'>
2062       *    <li class='jm'>{@link RestRequest#getMessage(String, Object...)}
2063       *    <li class='jm'>{@link RestContext#getMessages() RestContext.getMessages()}
2064       * </ul>
2065       *
2066       * <p>
2067       * Request-localized messages are also available by passing either of the following parameter types into your Java method:
2068       * <ul class='javatree'>
2069       *    <li class='jc'>{@link ResourceBundle} - Basic Java resource bundle.
2070       *    <li class='jc'>{@link Messages} - Extended resource bundle with several convenience methods.
2071       * </ul>
2072       *
2073       * The value can be a relative path like <js>"nls/Messages"</js>, indicating to look for the resource bundle
2074       * <js>"com.foo.sample.nls.Messages"</js> if the resource class is in <js>"com.foo.sample"</js>, or it can be an
2075       * absolute path like <js>"com.foo.sample.nls.Messages"</js>
2076       *
2077       * <h5 class='section'>Examples:</h5>
2078       * <p class='bini'>
2079       *    <cc># Contents of org/apache/foo/nls/MyMessages.properties</cc>
2080       *
2081       *    <ck>HelloMessage</ck> = <cv>Hello {0}!</cv>
2082       * </p>
2083       * <p class='bjava'>
2084       *    <jc>// Contents of org/apache/foo/MyResource.java</jc>
2085       *
2086       *    <ja>@Rest</ja>(messages=<js>"nls/MyMessages"</js>)
2087       *    <jk>public class</jk> MyResource {...}
2088       *
2089       *       <ja>@RestGet</ja>(<js>"/hello/{you}"</js>)
2090       *       <jk>public</jk> Object helloYou(RestRequest <jv>req</jv>, Messages <jv>messages</jv>, <ja>@Path</ja>(<js>"name"</js>) String <jv>you</jv>) {
2091       *          String <jv>string</jv>;
2092       *
2093       *          <jc>// Get it from the RestRequest object.</jc>
2094       *          <jv>string</jv> = <jv>req</jv>.getMessage(<js>"HelloMessage"</js>, <jv>you</jv>);
2095       *
2096       *          <jc>// Or get it from the method parameter.</jc>
2097       *          <jv>string</jv> = <jv>messages</jv>.getString(<js>"HelloMessage"</js>, <jv>you</jv>);
2098       *
2099       *          <jc>// Or get the message in a locale different from the request.</jc>
2100       *          <jv>string</jv> = <jv>messages</jv>.forLocale(Locale.<jsf>UK</jsf>).getString(<js>"HelloMessage"</js>, <jv>you</jv>);
2101       *
2102       *          <jk>return</jk> <jv>string</jv>;
2103       *       }
2104       *    }
2105       * </p>
2106       *
2107       * <p>
2108       * The default messages can overridden via any of the following:
2109       * <ul class='spaced-list'>
2110       *    <li>Injected via bean store.
2111       *    <li>Class annotation:  {@link Rest#messages() @Rest(messages)}
2112       *    <li>{@link RestInject @RestInject}-annotated method:
2113       *       <p class='bjava'>
2114       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] Messages myMethod(<i>&lt;args&gt;</i>) {...}
2115       *       </p>
2116       *       Args can be any injected bean including Messages.Builder, the default builder.
2117       * </ul>
2118       *
2119       * <h5 class='section'>Notes:</h5><ul>
2120       *    <li class='note'>Mappings are cumulative from super classes.
2121       *       <br>Therefore, you can find and retrieve messages up the class-hierarchy chain.
2122       * </ul>
2123       *
2124       * <h5 class='section'>See Also:</h5><ul>
2125       *    <li class='jc'>{@link Messages}
2126       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/LocalizedMessages">Localized Messages</a>
2127       * </ul>
2128       *
2129       * @return The messages sub-builder.
2130       */
2131      public Messages.Builder messages() {
2132         if (messages == null)
2133            messages = createMessages(beanStore(), resource());
2134         return messages;
2135      }
2136
2137      /**
2138       * Specifies the messages bundle for this class.
2139       *
2140       * <p>
2141       * Equivalent to calling:
2142       * <p class='bjava'>
2143       *    <jv>builder</jv>.messages().type(<jv>value</jv>);
2144       * </p>
2145       *
2146       * <h5 class='section'>See Also:</h5><ul>
2147       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/LocalizedMessages">Localized Messages</a>
2148       *    <li class='jm'>{@link #messages()}
2149       * </ul>
2150       *
2151       * @param value The new value.
2152       *    <br>Cannot be <jk>null</jk>.
2153       * @return This object.
2154       */
2155      public Builder messages(Class<? extends Messages> value) {
2156         messages().type(assertArgNotNull("value", value));
2157         return this;
2158      }
2159
2160      /**
2161       * Specifies the messages bundle for this class.
2162       *
2163       * <p>
2164       * Equivalent to calling:
2165       * <p class='bjava'>
2166       *    <jv>builder</jv>.messages().impl(<jv>value</jv>);
2167       * </p>
2168       *
2169       * <h5 class='section'>See Also:</h5><ul>
2170       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/LocalizedMessages">Localized Messages</a>
2171       *    <li class='jm'>{@link #messages()}
2172       * </ul>
2173       *
2174       * @param value The new value.
2175       *    <br>Cannot be <jk>null</jk>.
2176       * @return This object.
2177       */
2178      public Builder messages(Messages value) {
2179         messages().impl(assertArgNotNull("value", value));
2180         return this;
2181      }
2182
2183      /**
2184       * Returns the method execution statistics store sub-builder.
2185       *
2186       * <p>
2187       * Used for tracking basic call statistics on Java methods in this class.
2188       * It can be accessed directly via {@link RestContext#getMethodExecStore()} or passed in as a parameter
2189       * on a {@link RestOp}-annotated method.
2190       *
2191       * <p>
2192       * The default method exec store can overridden via any of the following:
2193       * <ul class='spaced-list'>
2194       *    <li>Injected via bean store.
2195       *    <li>{@link RestInject @RestInject}-annotated method:
2196       *       <p class='bjava'>
2197       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] MethodExecStore myMethod(<i>&lt;args&gt;</i>) {...}
2198       *       </p>
2199       *       Args can be any injected bean including MethodExecStore.Builder, the default builder.
2200       * </ul>
2201       *
2202       * <h5 class='section'>See Also:</h5><ul>
2203       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
2204       * </ul>
2205       *
2206       * @return The method execution statistics store sub-builder.
2207       */
2208      public MethodExecStore.Builder methodExecStore() {
2209         if (methodExecStore == null)
2210            methodExecStore = createMethodExecStore(beanStore(), resource());
2211         return methodExecStore;
2212      }
2213
2214      /**
2215       * Specifies the method execution store for this class.
2216       *
2217       * <p>
2218       * Equivalent to calling:
2219       * <p class='bjava'>
2220       *    <jv>builder</jv>.methodExecStore().type(<jv>value</jv>);
2221       * </p>
2222       *
2223       * <h5 class='section'>See Also:</h5><ul>
2224       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
2225       *    <li class='jm'>{@link #methodExecStore()}
2226       * </ul>
2227       *
2228       * @param value The new value.
2229       *    <br>Cannot be <jk>null</jk>.
2230       * @return This object.
2231       */
2232      public Builder methodExecStore(Class<? extends MethodExecStore> value) {
2233         methodExecStore().type(assertArgNotNull("value", value));
2234         return this;
2235      }
2236
2237      /**
2238       * Specifies the method execution store for this class.
2239       *
2240       * <p>
2241       * Equivalent to calling:
2242       * <p class='bjava'>
2243       *    <jv>builder</jv>.methodExecStore().impl(<jv>value</jv>);
2244       * </p>
2245       *
2246       * <h5 class='section'>See Also:</h5><ul>
2247       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
2248       *    <li class='jm'>{@link #methodExecStore()}
2249       * </ul>
2250       *
2251       * @param value The new value.
2252       *    <br>Cannot be <jk>null</jk>.
2253       * @return This object.
2254       */
2255      public Builder methodExecStore(MethodExecStore value) {
2256         methodExecStore().impl(assertArgNotNull("value", value));
2257         return this;
2258      }
2259
2260      /**
2261       * <i><l>RestContext</l> configuration property:&emsp;</i>  Parser listener.
2262       *
2263       * <p>
2264       * Specifies the parser listener class to use for listening to non-fatal parsing errors.
2265       *
2266       * <h5 class='section'>See Also:</h5><ul>
2267       *    <li class='jm'>{@link org.apache.juneau.parser.Parser.Builder#listener(Class)}
2268       * </ul>
2269       *
2270       * @param value The new value for this setting.
2271       *    <br>Cannot be <jk>null</jk>.
2272       * @return This object.
2273       */
2274      public Builder parserListener(Class<? extends ParserListener> value) {
2275         if (isNotVoid(assertArgNotNull("value", value)))
2276            parsers.forEach(x -> x.listener(value));
2277         return this;
2278      }
2279
2280      /**
2281       * Returns the parser group sub-builder.
2282       *
2283       * <p>
2284       * Parsers are used to HTTP request bodies into POJOs based on the {@code Content-Type} header.
2285       *
2286       * <p>
2287       * The default parser set is empty.
2288       * It can be overridden via any of the following:
2289       * <ul class='spaced-list'>
2290       *    <li>Injected via bean store.
2291       *    <li>Class annotation: {@link Rest#parsers() @Rest(parsers)}
2292       *    <li>{@link RestInject @RestInject}-annotated method:
2293       *       <p class='bjava'>
2294       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] ParserSet myMethod(<i>&lt;args&gt;</i>) {...}
2295       *       </p>
2296       *       Args can be any injected bean including ParserSet.Builder, the default builder.
2297       * </ul>
2298       *
2299       * <h5 class='section'>See Also:</h5><ul>
2300       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
2301       * </ul>
2302       *
2303       * @return The parser group sub-builder.
2304       */
2305      public ParserSet.Builder parsers() {
2306         if (parsers == null)
2307            parsers = createParsers(beanStore(), resource());
2308         return parsers;
2309      }
2310
2311      /**
2312       * Adds one or more parsers to this class.
2313       *
2314       * <p>
2315       * Equivalent to calling:
2316       * <p class='bjava'>
2317       *    <jv>builder</jv>.parsers().add(<jv>value</jv>);
2318       * </p>
2319       *
2320       * <h5 class='section'>See Also:</h5><ul>
2321       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
2322       *    <li class='jm'>{@link #parsers()}
2323       * </ul>
2324       *
2325       * @param value The values to add.
2326       *    <br>Cannot contain <jk>null</jk> values.
2327       * @return This object.
2328       */
2329      @SafeVarargs
2330      public final Builder parsers(Class<? extends Parser>...value) {
2331         assertArgNoNulls("value", value);
2332         parsers().add(value);
2333         return this;
2334      }
2335
2336      /**
2337       * Adds one or more parsers to this class.
2338       *
2339       * <p>
2340       * Equivalent to calling:
2341       * <p class='bjava'>
2342       *    <jv>builder</jv>.parsers().add(<jv>value</jv>);
2343       * </p>
2344       *
2345       * <h5 class='section'>See Also:</h5><ul>
2346       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
2347       *    <li class='jm'>{@link #parsers()}
2348       * </ul>
2349       *
2350       * @param value The values to add.
2351       *    <br>Cannot contain <jk>null</jk> values.
2352       * @return This object.
2353       */
2354      public Builder parsers(Parser...value) {
2355         assertArgNoNulls("value", value);
2356         parsers().add(value);
2357         return this;
2358      }
2359
2360      /**
2361       * Returns the part parser sub-builder.
2362       *
2363       * <p>
2364       * The part parser is used for parsing HTTP parts such as request headers and query/form/path parameters.
2365       *
2366       * <p>
2367       * The default part parser is an {@link OpenApiParser}.
2368       * It can overridden via any of the following:
2369       * <ul class='spaced-list'>
2370       *    <li>Injected via bean store.
2371       *    <li>{@link RestInject @RestInject}-annotated method:
2372       *       <p class='bjava'>
2373       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] HttpPartParser myMethod(<i>&lt;args&gt;</i>) {...}
2374       *       </p>
2375       *       Args can be any injected bean including HttpPartParser.Builder, the default builder.
2376       * </ul>
2377       *
2378       * <h5 class='section'>See Also:</h5><ul>
2379       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
2380       * </ul>
2381       *
2382       * @return The part parser sub-builder.
2383       */
2384      public HttpPartParser.Creator partParser() {
2385         if (partParser == null)
2386            partParser = createPartParser(beanStore(), resource());
2387         return partParser;
2388      }
2389
2390      /**
2391       * Specifies the part parser to use for parsing HTTP parts for this class.
2392       *
2393       * <p>
2394       * Equivalent to calling:
2395       * <p class='bjava'>
2396       *    <jv>builder</jv>.partParser().type(<jv>value</jv>);
2397       * </p>
2398       *
2399       * <h5 class='section'>See Also:</h5><ul>
2400       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
2401       *    <li class='jm'>{@link #partParser()}
2402       * </ul>
2403       *
2404       * @param value The new value.
2405       *    <br>Cannot be <jk>null</jk>.
2406       * @return This object.
2407       */
2408      public Builder partParser(Class<? extends HttpPartParser> value) {
2409         partParser().type(assertArgNotNull("value", value));
2410         return this;
2411      }
2412
2413      /**
2414       * Specifies the part parser to use for parsing HTTP parts for this class.
2415       *
2416       * <p>
2417       * Equivalent to calling:
2418       * <p class='bjava'>
2419       *    <jv>builder</jv>.partParser().impl(<jv>value</jv>);
2420       * </p>
2421       *
2422       * <h5 class='section'>See Also:</h5><ul>
2423       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
2424       *    <li class='jm'>{@link #partParser()}
2425       * </ul>
2426       *
2427       * @param value The new value.
2428       *    <br>Cannot be <jk>null</jk>.
2429       * @return This object.
2430       */
2431      public Builder partParser(HttpPartParser value) {
2432         partParser().impl(assertArgNotNull("value", value));
2433         return this;
2434      }
2435
2436      /**
2437       * Returns the part serializer sub-builder.
2438       *
2439       * <p>
2440       * The part serializer is used for serializing HTTP parts such as response headers.
2441       *
2442       * <p>
2443       * The default part serializer is an {@link OpenApiSerializer}.
2444       * It can overridden via any of the following:
2445       * <ul class='spaced-list'>
2446       *    <li>Injected via bean store.
2447       *    <li>{@link RestInject @RestInject}-annotated method:
2448       *       <p class='bjava'>
2449       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] HttpPartSerializer myMethod(<i>&lt;args&gt;</i>) {...}
2450       *       </p>
2451       *       Args can be any injected bean including HttpPartSerializer.Builder, the default builder.
2452       * </ul>
2453       *
2454       * <h5 class='section'>See Also:</h5><ul>
2455       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
2456       * </ul>
2457       *
2458       * @return The part serializer sub-builder.
2459       */
2460      public HttpPartSerializer.Creator partSerializer() {
2461         if (partSerializer == null)
2462            partSerializer = createPartSerializer(beanStore(), resource());
2463         return partSerializer;
2464      }
2465
2466      /**
2467       * Specifies the part serializer to use for serializing HTTP parts for this class.
2468       *
2469       * <p>
2470       * Equivalent to calling:
2471       * <p class='bjava'>
2472       *    <jv>builder</jv>.partSerializer().type(<jv>value</jv>);
2473       * </p>
2474       *
2475       * <h5 class='section'>See Also:</h5><ul>
2476       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
2477       *    <li class='jm'>{@link #partSerializer()}
2478       * </ul>
2479       *
2480       * @param value The new value.
2481       *    <br>Cannot be <jk>null</jk>.
2482       * @return This object.
2483       */
2484      public Builder partSerializer(Class<? extends HttpPartSerializer> value) {
2485         partSerializer().type(assertArgNotNull("value", value));
2486         return this;
2487      }
2488
2489      /**
2490       * Specifies the part serializer to use for serializing HTTP parts for this class.
2491       *
2492       * <p>
2493       * Equivalent to calling:
2494       * <p class='bjava'>
2495       *    <jv>builder</jv>.partSerializer().impl(<jv>value</jv>);
2496       * </p>
2497       *
2498       * <h5 class='section'>See Also:</h5><ul>
2499       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
2500       *    <li class='jm'>{@link #partSerializer()}
2501       * </ul>
2502       *
2503       * @param value The new value.
2504       *    <br>Cannot be <jk>null</jk>.
2505       * @return This object.
2506       */
2507      public Builder partSerializer(HttpPartSerializer value) {
2508         partSerializer().impl(assertArgNotNull("value", value));
2509         return this;
2510      }
2511
2512      /**
2513       * Resource path.
2514       *
2515       * <p>
2516       * Identifies the URL subpath relative to the parent resource.
2517       *
2518       * <p>
2519       * This setting is critical for the routing of HTTP requests from ascendant to child resources.
2520       *
2521       * <h5 class='section'>Example:</h5>
2522       * <p class='bjava'>
2523       *    <jc>// Option #1 - Defined via annotation.</jc>
2524       *    <ja>@Rest</ja>(path=<js>"/myResource"</js>)
2525       *    <jk>public class</jk> MyResource {
2526       *
2527       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2528       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
2529       *
2530       *          <jc>// Using method on builder.</jc>
2531       *          <jv>builder</jv>.path(<js>"/myResource"</js>);
2532       *       }
2533       *
2534       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2535       *       <ja>@RestInit</ja>
2536       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
2537       *          <jv>builder</jv>.path(<js>"/myResource"</js>);
2538       *       }
2539       *    }
2540       * </p>
2541       *
2542       * <p>
2543       * <h5 class='section'>Notes:</h5><ul>
2544       *    <li class='note'>
2545       *       This annotation is ignored on top-level servlets (i.e. servlets defined in <c>web.xml</c> files).
2546       *       <br>Therefore, implementers can optionally specify a path value for documentation purposes.
2547       *    <li class='note'>
2548       *       Typically, this setting is only applicable to resources defined as children through the
2549       *       {@link Rest#children() @Rest(children)} annotation.
2550       *       <br>However, it may be used in other ways (e.g. defining paths for top-level resources in microservices).
2551       *    <li class='note'>
2552       *       Slashes are trimmed from the path ends.
2553       *       <br>As a convention, you may want to start your path with <js>'/'</js> simple because it make it easier to read.
2554       *    <li class='note'>
2555       *       This path is available through the following method:
2556       *       <ul>
2557       *          <li class='jm'>{@link RestContext#getPath() RestContext.getPath()}
2558       *       </ul>
2559       * </ul>
2560       *
2561       * <h5 class='section'>See Also:</h5><ul>
2562       *    <li class='ja'>{@link Rest#path}
2563       * </ul>
2564       *
2565       * @param value The new value for this setting.
2566       *    <br>Can be <jk>null</jk> or empty (path will not be set, defaults to empty string).
2567       * @return This object.
2568       */
2569      public Builder path(String value) {
2570         value = trimLeadingSlashes(value);
2571         if (ne(value))
2572            path = value;
2573         return this;
2574      }
2575
2576      /**
2577       * Returns the post-call method list.
2578       *
2579       * <p>
2580       * The list of methods that gets called immediately after the <ja>@RestOp</ja> annotated method gets called..
2581       *
2582       * @return The list of methods that gets called immediately after the <ja>@RestOp</ja> annotated method gets called..
2583       */
2584      public MethodList postCallMethods() {
2585         if (postCallMethods == null)
2586            postCallMethods = createPostCallMethods(beanStore(), resource());
2587         return postCallMethods;
2588      }
2589
2590      /**
2591       * Returns the post-init-child-first method list.
2592       *
2593       * @return The post-init-child-first method list.
2594       */
2595      public MethodList postInitChildFirstMethods() {
2596         if (postInitChildFirstMethods == null)
2597            postInitChildFirstMethods = createPostInitChildFirstMethods(beanStore(), resource());
2598         return postInitChildFirstMethods;
2599      }
2600
2601      /**
2602       * Returns the post-init method list.
2603       *
2604       * @return The post-init method list.
2605       */
2606      public MethodList postInitMethods() {
2607         if (postInitMethods == null)
2608            postInitMethods = createPostInitMethods(beanStore(), resource());
2609         return postInitMethods;
2610      }
2611
2612      /**
2613       * Returns the pre-call method list.
2614       *
2615       * <p>
2616       * The list of methods that gets called immediately before the <ja>@RestOp</ja> annotated method gets called.
2617       *
2618       * @return The pre-call method list.
2619       */
2620      public MethodList preCallMethods() {
2621         if (preCallMethods == null)
2622            preCallMethods = createPreCallMethods(beanStore(), resource());
2623         return preCallMethods;
2624      }
2625
2626      /**
2627       * Returns the media types produced by this resource if it's manually specified.
2628       *
2629       * @return The media types.
2630       */
2631      public Optional<List<MediaType>> produces() {
2632         return opt(produces);
2633      }
2634
2635      /**
2636       * Supported accept media types.
2637       *
2638       * <p>
2639       * Overrides the media types inferred from the serializers that identify what media types can be produced by the resource.
2640       * <br>An example where this might be useful if you have serializers registered that handle media types that you
2641       * don't want exposed in the Swagger documentation.
2642       *
2643       * <h5 class='section'>Example:</h5>
2644       * <p class='bjava'>
2645       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
2646       *    <ja>@Rest</ja>(produces={<js>"$C{REST/supportedProduces,application/json}"</js>})
2647       *    <jk>public class</jk> MyResource {
2648       *
2649       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2650       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
2651       *
2652       *          <jc>// Using method on builder.</jc>
2653       *          <jv>builder</jv>.produces(<jk>false</jk>, <js>"application/json"</js>)
2654       *       }
2655       *
2656       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2657       *       <ja>@RestInit</ja>
2658       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
2659       *          <jv>builder</jv>.produces(<jk>false</jk>, <js>"application/json"</js>);
2660       *       }
2661       *    }
2662       * </p>
2663       *
2664       * <p>
2665       * This affects the returned values from the following:
2666       * <ul class='javatree'>
2667       *    <li class='jm'>{@link RestContext#getProduces() RestContext.getProduces()}
2668       *    <li class='jm'>{@link SwaggerProvider#getSwagger(RestContext,Locale)} - Affects produces field.
2669       * </ul>
2670       *
2671       * <h5 class='section'>See Also:</h5><ul>
2672       *    <li class='ja'>{@link Rest#produces}
2673       *    <li class='ja'>{@link RestOp#produces}
2674       *    <li class='ja'>{@link RestGet#produces}
2675       *    <li class='ja'>{@link RestPut#produces}
2676       *    <li class='ja'>{@link RestPost#produces}
2677       * </ul>
2678       *
2679       * @param values The values to add to this setting.
2680       *    <br>Cannot contain <jk>null</jk> values.
2681       * @return This object.
2682       */
2683      public Builder produces(MediaType...values) {
2684         assertArgNoNulls("values", values);
2685         produces = addAll(produces, values);
2686         return this;
2687      }
2688
2689      /**
2690       * <i><l>RestContext</l> configuration property:&emsp;</i>  Render response stack traces in responses.
2691       *
2692       * <p>
2693       * Shortcut for calling <code>renderResponseStackTraces(<jk>true</jk>)</code>.
2694       *
2695       * @return This object.
2696       */
2697      public Builder renderResponseStackTraces() {
2698         renderResponseStackTraces = true;
2699         return this;
2700      }
2701
2702      /**
2703       * <i><l>RestContext</l> configuration property:&emsp;</i>  Render response stack traces in responses.
2704       *
2705       * <p>
2706       * Render stack traces in HTTP response bodies when errors occur.
2707       *
2708       * @param value
2709       *    The new value for this setting.
2710       *    <br>The default is <jk>false</jk>.
2711       * @return This object.
2712       */
2713      public Builder renderResponseStackTraces(boolean value) {
2714         renderResponseStackTraces = value;
2715         return this;
2716      }
2717
2718      /**
2719       * Returns the REST servlet/bean instance that this context is defined against.
2720       *
2721       * @return The REST servlet/bean instance that this context is defined against.
2722       */
2723      public Supplier<?> resource() {
2724         return Objects.requireNonNull(resource, "Resource not available. init(Object) has not been called.");
2725      }
2726
2727      /**
2728       * Returns the REST servlet/bean instance that this context is defined against if it's the specified type.
2729       *
2730       * @param <T> The expected type of the resource bean.
2731       * @param type The expected type of the resource bean.
2732       *    <br>Cannot be <jk>null</jk>.
2733       * @return The bean cast to that instance, or {@link Optional#empty()} if it's not the specified type.
2734       */
2735      public <T> Optional<T> resourceAs(Class<T> type) {
2736         var r = resource().get();
2737         return opt(assertArgNotNull("type", type).isInstance(r) ? type.cast(r) : null);
2738      }
2739
2740      /**
2741       * Returns the response processor list sub-builder.
2742       *
2743       * <p>
2744       * Specifies a list of {@link ResponseProcessor} classes that know how to convert POJOs returned by REST methods or
2745       * set via {@link RestResponse#setContent(Object)} into appropriate HTTP responses.
2746       *
2747       * <p>
2748       * By default, the following response handlers are provided in the specified order:
2749       * <ul class='javatreec'>
2750       *    <li class='jc'>{@link ReaderProcessor}
2751       *    <li class='jc'>{@link InputStreamProcessor}
2752       *    <li class='jc'>{@link ThrowableProcessor}
2753       *    <li class='jc'>{@link HttpResponseProcessor}
2754       *    <li class='jc'>{@link HttpResourceProcessor}
2755       *    <li class='jc'>{@link HttpEntityProcessor}
2756       *    <li class='jc'>{@link ResponseBeanProcessor}
2757       *    <li class='jc'>{@link PlainTextPojoProcessor}
2758       *    <li class='jc'>{@link SerializedPojoProcessor}
2759       * </ul>
2760       *
2761       * <h5 class='section'>Example:</h5>
2762       * <p class='bjava'>
2763       *    <jc>// Our custom response processor for Foo objects. </jc>
2764       *    <jk>public class</jk> MyResponseProcessor <jk>implements</jk> ResponseProcessor {
2765       *
2766       *       <ja>@Override</ja>
2767       *       <jk>public int</jk> process(RestOpSession <jv>opSession</jv>) <jk>throws</jk> IOException {
2768       *
2769       *             RestResponse <jv>res</jv> = <jv>opSession</jv>.getResponse();
2770       *             Foo <jv>foo</jv> = <jv>res</jv>.getOutput(Foo.<jk>class</jk>);
2771       *
2772       *             <jk>if</jk> (<jv>foo</jv> == <jk>null</jk>)
2773       *                <jk>return</jk> <jsf>NEXT</jsf>;  <jc>// Let the next processor handle it.</jc>
2774       *
2775       *             <jk>try</jk> (Writer <jv>writer</jv> = <jv>res</jv>.getNegotiatedWriter()) {
2776       *                <jc>//Pipe it to the writer ourselves.</jc>
2777       *             }
2778       *
2779       *             <jk>return</jk> <jsf>FINISHED</jsf>;  <jc>// We handled it.</jc>
2780       *       }
2781       *       }
2782       *    }
2783       *
2784       *    <jc>// Option #1 - Defined via annotation.</jc>
2785       *    <ja>@Rest</ja>(responseProcessors=MyResponseProcessor.<jk>class</jk>)
2786       *    <jk>public class</jk> MyResource {
2787       *
2788       *       <jc>// Option #2 - Defined via builder passed in through init method.</jc>
2789       *       <ja>@RestInit</ja>
2790       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
2791       *          <jv>builder</jv>.responseProcessors(MyResponseProcessors.<jk>class</jk>);
2792       *       }
2793       *
2794       *       <ja>@RestGet</ja>(...)
2795       *       <jk>public</jk> Object myMethod() {
2796       *          <jc>// Return a special object for our handler.</jc>
2797       *          <jk>return new</jk> MySpecialObject();
2798       *       }
2799       *    }
2800       * </p>
2801       *
2802       * <p>
2803       * The default response processors can overridden via any of the following:
2804       * <ul class='spaced-list'>
2805       *    <li>Injected via bean store.
2806       *    <li>Class annotation:  {@link Rest#responseProcessors() @Rest(responseProcessors)}
2807       *    <li>{@link RestInject @RestInject}-annotated method:
2808       *       <p class='bjava'>
2809       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] ResponseProcessorList myMethod(<i>&lt;args&gt;</i>) {...}
2810       *       </p>
2811       *       Args can be any injected bean including ResponseProcessorList.Builder, the default builder.
2812       * </ul>
2813       *
2814       * <h5 class='section'>Notes:</h5><ul>
2815       *    <li class='note'>
2816       *       Response processors are always inherited from ascendant resources.
2817       *    <li class='note'>
2818       *       When defined as a class, the implementation must have one of the following constructors:
2819       *       <ul>
2820       *          <li><code><jk>public</jk> T(RestContext)</code>
2821       *          <li><code><jk>public</jk> T()</code>
2822       *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
2823       *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
2824       *       </ul>
2825       *    <li class='note'>
2826       *       Inner classes of the REST resource class are allowed.
2827       * </ul>
2828       *
2829       * <h5 class='section'>See Also:</h5><ul>
2830       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ResponseProcessors">Response Processors</a>
2831       * </ul>
2832       *
2833       * @return The response processor list sub-builder.
2834       */
2835      public ResponseProcessorList.Builder responseProcessors() {
2836         if (responseProcessors == null)
2837            responseProcessors = createResponseProcessors(beanStore(), resource());
2838         return responseProcessors;
2839      }
2840
2841      /**
2842       * Adds one or more response processors to this class.
2843       *
2844       * <p>
2845       * Equivalent to calling:
2846       * <p class='bjava'>
2847       *    <jv>builder</jv>.responseProcessors().add(<jv>value</jv>);
2848       * </p>
2849       *
2850       * <h5 class='section'>See Also:</h5><ul>
2851       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ResponseProcessors">Response Processors</a>
2852       *    <li class='jm'>{@link #responseProcessors()}
2853       * </ul>
2854       *
2855       * @param value The values to add.
2856       *    <br>Cannot contain <jk>null</jk> values.
2857       * @return This object.
2858       */
2859      @SafeVarargs
2860      public final Builder responseProcessors(Class<? extends ResponseProcessor>...value) {
2861         assertArgNoNulls("value", value);
2862         responseProcessors().add(value);
2863         return this;
2864      }
2865
2866      /**
2867       * Adds one or more response processors to this class.
2868       *
2869       * <p>
2870       * Equivalent to calling:
2871       * <p class='bjava'>
2872       *    <jv>builder</jv>.responseProcessors().add(<jv>value</jv>);
2873       * </p>
2874       *
2875       * <h5 class='section'>See Also:</h5><ul>
2876       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ResponseProcessors">Response Processors</a>
2877       *    <li class='jm'>{@link #responseProcessors()}
2878       * </ul>
2879       *
2880       * @param value The values to add.
2881       *    <br>Cannot contain <jk>null</jk> values.
2882       * @return This object.
2883       */
2884      public Builder responseProcessors(ResponseProcessor...value) {
2885         assertArgNoNulls("value", value);
2886         responseProcessors().add(value);
2887         return this;
2888      }
2889
2890      /**
2891       * Returns the REST children list.
2892       *
2893       * @param restContext The rest context.
2894       *    <br>Can be <jk>null</jk> if the bean is a top-level resource.
2895       * @return The REST children list.
2896       * @throws Exception If a problem occurred instantiating one of the child rest contexts.
2897       */
2898      public RestChildren.Builder restChildren(RestContext restContext) throws Exception {
2899         if (restChildren == null)
2900            restChildren = createRestChildren(beanStore(), resource(), restContext);
2901         return restChildren;
2902      }
2903
2904      /**
2905       * REST children class.
2906       *
2907       * <p>
2908       * Allows you to extend the {@link RestChildren} class to modify how any of the methods are implemented.
2909       *
2910       * <p>
2911       * The subclass must have a public constructor that takes in any of the following arguments:
2912       * <ul>
2913       *    <li>{@link RestChildren.Builder} - The builder for the object.
2914       *    <li>Any beans found in the specified bean store.
2915       *    <li>Any {@link Optional} beans that may or may not be found in the specified bean store.
2916       * </ul>
2917       *
2918       * <h5 class='section'>Example:</h5>
2919       * <p class='bjava'>
2920       *    <jc>// Our extended context class</jc>
2921       *    <jk>public</jk> MyRestChildren <jk>extends</jk> RestChildren {
2922       *       <jk>public</jk> MyRestChildren(RestChildren.Builder <jv>builder</jv>, ARequiredSpringBean <jv>bean1</jv>, Optional&lt;AnOptionalSpringBean&gt; <jv>bean2</jv>) {
2923       *          <jk>super</jk>(<jv>builder</jv>);
2924       *       }
2925       *
2926       *       <jc>// Override any methods.</jc>
2927       *
2928       *       <ja>@Override</ja>
2929       *       <jk>public</jk> Optional&lt;RestChildMatch&gt; findMatch(RestCall <jv>call</jv>) {
2930       *          String <jv>path</jv> = <jv>call</jv>.getPathInfo();
2931       *          <jk>if</jk> (<jv>path</jv>.endsWith(<js>"/foo"</js>)) {
2932       *             <jc>// Do our own special handling.</jc>
2933       *          }
2934       *          <jk>return super</jk>.findMatch(<jv>call</jv>);
2935       *       }
2936       *    }
2937       * </p>
2938       * <p class='bjava'>
2939       *    <jc>// Option #1 - Defined via annotation.</jc>
2940       *    <ja>@Rest</ja>(restChildrenClass=MyRestChildren.<jk>class</jk>)
2941       *    <jk>public class</jk> MyResource {
2942       *       ...
2943       *
2944       *       <jc>// Option #2 - Defined via builder passed in through init method.</jc>
2945       *       <ja>@RestInit</ja>
2946       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
2947       *          <jv>builder</jv>.restChildrenClass(MyRestChildren.<jk>class</jk>);
2948       *       }
2949       *    }
2950       * </p>
2951       *
2952       * @param value The new value for this setting.
2953       *    <br>Cannot be <jk>null</jk>.
2954       * @return This object.
2955       */
2956      public Builder restChildrenClass(Class<? extends RestChildren> value) {
2957         childrenClass = assertArgNotNull("value", value);
2958         return this;
2959      }
2960
2961      /**
2962       * Returns the REST operation args sub-builder.
2963       *
2964       * @return The REST operation args sub-builder.
2965       */
2966      public RestOpArgList.Builder restOpArgs() {
2967         if (restOpArgs == null)
2968            restOpArgs = createRestOpArgs(beanStore(), resource());
2969         return restOpArgs;
2970      }
2971
2972      /**
2973       * Adds one or more REST operation args to this class.
2974       *
2975       * <p>
2976       * Equivalent to calling:
2977       * <p class='bjava'>
2978       *    <jv>builder</jv>.restOpArgs().add(<jv>value</jv>);
2979       * </p>
2980       *
2981       * @param value The new value.
2982       *    <br>Cannot contain <jk>null</jk> values.
2983       * @return This object.
2984       */
2985      @SafeVarargs
2986      public final Builder restOpArgs(Class<? extends RestOpArg>...value) {
2987         assertArgNoNulls("value", value);
2988         restOpArgs().add(value);
2989         return this;
2990      }
2991
2992      /**
2993       * REST operation context class.
2994       *
2995       * <p>
2996       * Allows you to extend the {@link RestOpContext} class to modify how any of the methods are implemented.
2997       *
2998       * <p>
2999       * The subclass must have a public constructor that takes in any of the following arguments:
3000       * <ul>
3001       *    <li>{@link RestOpContext.Builder} - The builder for the object.
3002       *    <li>Any beans found in the specified bean store.
3003       *    <li>Any {@link Optional} beans that may or may not be found in the specified bean store.
3004       * </ul>
3005       *
3006       * <h5 class='section'>Example:</h5>
3007       * <p class='bjava'>
3008       *    <jc>// Our extended context class that adds a request attribute to all requests.</jc>
3009       *    <jc>// The attribute value is provided by an injected spring bean.</jc>
3010       *    <jk>public</jk> MyRestOperationContext <jk>extends</jk> RestOpContext {
3011       *
3012       *       <jk>private final</jk> Optional&lt;? <jk>extends</jk> Supplier&lt;Object&gt;&gt; <jf>fooSupplier</jf>;
3013       *
3014       *       <jc>// Constructor that takes in builder and optional injected attribute provider.</jc>
3015       *       <jk>public</jk> MyRestOperationContext(RestOpContext.Builder <jv>builder</jv>, Optional&lt;AnInjectedFooSupplier&gt; <jv>fooSupplier</jv>) {
3016       *          <jk>super</jk>(<jv>builder</jv>);
3017       *          <jk>this</jk>.<jf>fooSupplier</jf> = <jv>fooSupplier</jv>.orElseGet(()-&gt;<jk>null</jk>);
3018       *       }
3019       *
3020       *       <jc>// Override the method used to create default request attributes.</jc>
3021       *       <ja>@Override</ja>
3022       *       <jk>protected</jk> NamedAttributeMap createDefaultRequestAttributes(Object <jv>resource</jv>, BeanStore <jv>beanStore</jv>, Method <jv>method</jv>, RestContext <jv>context</jv>) <jk>throws</jk> Exception {
3023       *          <jk>return super</jk>
3024       *             .createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanStore</jv>, <jv>method</jv>, <jv>context</jv>)
3025       *             .append(NamedAttribute.<jsm>of</jsm>(<js>"foo"</js>, ()-&gt;<jf>fooSupplier</jf>.get());
3026       *       }
3027       *    }
3028       * </p>
3029       * <p class='bjava'>
3030       *    <jc>// Option #1 - Defined via annotation.</jc>
3031       *    <ja>@Rest</ja>(restOpContextClass=MyRestOperationContext.<jk>class</jk>)
3032       *    <jk>public class</jk> MyResource {
3033       *       ...
3034       *
3035       *       <jc>// Option #2 - Defined via builder passed in through init method.</jc>
3036       *       <ja>@RestInit</ja>
3037       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3038       *          <jv>builder</jv>.methodContextClass(MyRestOperationContext.<jk>class</jk>);
3039       *       }
3040       *
3041       *       <ja>@RestGet</ja>
3042       *       <jk>public</jk> Object foo(RequestAttributes <jv>attributes</jv>) {
3043       *          <jk>return</jk> <jv>attributes</jv>.get(<js>"foo"</js>);
3044       *       }
3045       *    }
3046       * </p>
3047       *
3048       * @param value The new value for this setting.
3049       *    <br>Cannot be <jk>null</jk>.
3050       * @return This object.
3051       */
3052      public Builder restOpContextClass(Class<? extends RestOpContext> value) {
3053         opContextClass = assertArgNotNull("value", value);
3054         return this;
3055      }
3056
3057      /**
3058       * Returns the REST operations list.
3059       *
3060       * @param restContext The rest context.
3061       *    <br>Cannot be <jk>null</jk>.
3062       * @return The REST operations list.
3063       * @throws ServletException If a problem occurred instantiating one of the child rest contexts.
3064       */
3065      public RestOperations.Builder restOperations(RestContext restContext) throws ServletException {
3066         if (restOperations == null)
3067            restOperations = createRestOperations(beanStore(), resource(), assertArgNotNull("restContext", restContext));
3068         return restOperations;
3069      }
3070
3071      /**
3072       * Returns the root bean store.
3073       *
3074       * <p>
3075       * This is the bean store inherited from the parent resource and does not include
3076       * any beans added by this class.
3077       *
3078       * @return The root bean store.
3079       */
3080      public BeanStore rootBeanStore() {
3081         return rootBeanStore;
3082      }
3083
3084      /**
3085       * <i><l>RestContext</l> configuration property:&emsp;</i>  Serializer listener.
3086       *
3087       * <p>
3088       * Specifies the serializer listener class to use for listening to non-fatal serialization errors.
3089       *
3090       * <h5 class='section'>See Also:</h5><ul>
3091       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#listener(Class)}
3092       * </ul>
3093       *
3094       * @param value The new value for this setting.
3095       *    <br>Cannot be <jk>null</jk>.
3096       * @return This object.
3097       */
3098      public Builder serializerListener(Class<? extends SerializerListener> value) {
3099         if (isNotVoid(assertArgNotNull("value", value)))
3100            serializers.forEach(x -> x.listener(value));
3101         return this;
3102      }
3103
3104      /**
3105       * Returns the serializer group sub-builder.
3106       *
3107       * <p>
3108       * Serializers are used to convert POJOs to HTTP response bodies based on the {@code Accept} header.
3109       *
3110       * <p>
3111       * The default serializer set is empty.
3112       * It can be overridden via any of the following:
3113       * <ul class='spaced-list'>
3114       *    <li>Injected via bean store.
3115       *    <li>Class annotation: {@link Rest#serializers() @Rest(serializers)}
3116       *    <li>{@link RestInject @RestInject}-annotated method:
3117       *       <p class='bjava'>
3118       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] SerializerSet myMethod(<i>&lt;args&gt;</i>) {...}
3119       *       </p>
3120       *       Args can be any injected bean including SerializerSet.Builder, the default builder.
3121       * </ul>
3122       *
3123       * <h5 class='section'>See Also:</h5><ul>
3124       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
3125       * </ul>
3126       *
3127       * @return The serializer group sub-builder.
3128       */
3129      public SerializerSet.Builder serializers() {
3130         if (serializers == null)
3131            serializers = createSerializers(beanStore(), resource());
3132         return serializers;
3133      }
3134
3135      /**
3136       * Adds one or more serializers to this class.
3137       *
3138       * <p>
3139       * Equivalent to calling:
3140       * <p class='bjava'>
3141       *    <jv>builder</jv>.serializers().add(<jv>value</jv>);
3142       * </p>
3143       *
3144       * <h5 class='section'>See Also:</h5><ul>
3145       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
3146       *    <li class='jm'>{@link #serializers()}
3147       * </ul>
3148       *
3149       * @param value The values to add.
3150       *    <br>Cannot contain <jk>null</jk> values.
3151       * @return This object.
3152       */
3153      @SafeVarargs
3154      public final Builder serializers(Class<? extends Serializer>...value) {
3155         assertArgNoNulls("value", value);
3156         serializers().add(value);
3157         return this;
3158      }
3159
3160      /**
3161       * Adds one or more serializers to this class.
3162       *
3163       * <p>
3164       * Equivalent to calling:
3165       * <p class='bjava'>
3166       *    <jv>builder</jv>.serializers().add(<jv>value</jv>);
3167       * </p>
3168       *
3169       * <h5 class='section'>See Also:</h5><ul>
3170       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
3171       *    <li class='jm'>{@link #serializers()}
3172       * </ul>
3173       *
3174       * @param value The values to add.
3175       *    <br>Cannot contain <jk>null</jk> values.
3176       * @return This object.
3177       */
3178      public Builder serializers(Serializer...value) {
3179         assertArgNoNulls("value", value);
3180         serializers().add(value);
3181         return this;
3182      }
3183
3184      /**
3185       * Returns the start call method list.
3186       *
3187       * @return The start call method list.
3188       */
3189      public MethodList startCallMethods() {
3190         if (startCallMethods == null)
3191            startCallMethods = createStartCallMethods(beanStore(), resource());
3192         return startCallMethods;
3193      }
3194
3195      /**
3196       * Returns the static files bean creator.
3197       *
3198       * <p>
3199       * Used to retrieve localized files to be served up as static files through the REST API via the following
3200       * predefined methods:
3201       * <ul class='javatree'>
3202       *    <li class='jm'>{@link BasicRestObject#getHtdoc(String, Locale)}.
3203       *    <li class='jm'>{@link BasicRestServlet#getHtdoc(String, Locale)}.
3204       * </ul>
3205       *
3206       * <p>
3207       * The static file finder can be accessed through the following methods:
3208       * <ul class='javatree'>
3209       *    <li class='jm'>{@link RestContext#getStaticFiles()}
3210       *    <li class='jm'>{@link RestRequest#getStaticFiles()}
3211       * </ul>
3212       *
3213       * <p>
3214       * The default static files finder implementation class is {@link BasicStaticFiles}.  This can be overridden via the following:
3215       * <ul class='spaced-list'>
3216       *    <li>
3217       *       The {@link Rest#staticFiles() @Rest(staticFiles)} annotation.
3218       *    <li>
3219       *       Overridden {@link StaticFiles} implementation class name specified in {@link #defaultClasses()}.
3220       *    <li>
3221       *       Type specified via <c>{@link RestContext.Builder}.{@link #staticFiles() staticFiles()}.{@link org.apache.juneau.rest.staticfile.StaticFiles.Builder#type(Class) type(Class)}</c>.
3222       *    <li>
3223       *       Bean specified via <c>{@link RestContext.Builder}.{@link #staticFiles() staticFiles()}.{@link org.apache.juneau.rest.staticfile.StaticFiles.Builder#impl(Object) impl(Object)}</c>.
3224       * </ul>
3225       *
3226       * <h5 class='section'>Example:</h5>
3227       * <p class='bjava'>
3228       *    <jc>// Create a static file finder that looks for files in the /files working subdirectory, but
3229       *    // overrides the find() and resolve methods for special handling of special cases and adds a
3230       * // Foo header to all requests.</jc>
3231       *    <jk>public class</jk> MyStaticFiles <jk>extends</jk> BasicStaticFiles {
3232       *
3233       *       <jk>public</jk> MyStaticFiles() {
3234       *          <jk>super</jk>(
3235       *             StaticFiles
3236       *                .<jsm>create</jsm>()
3237       *                .dir(<js>"/files"</js>)
3238       *                .headers(BasicStringHeader.<jsm>of</jsm>(<js>"Foo"</js>, <js>"bar"</js>))
3239       *          );
3240       *       }
3241       *    }
3242       * </p>
3243       * <p class='bjava'>
3244       *    <ja>@Rest</ja>(staticFiles=MyStaticFiles.<jk>class</jk>)
3245       *    <jk>public class</jk> MyResource {...}
3246       * </p>
3247       *
3248       * <h5 class='section'>See Also:</h5><ul>
3249       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/StaticFiles">Static files</a>
3250       * </ul>
3251       *
3252       * @return The static files bean creator.
3253       */
3254      public BeanCreator<StaticFiles> staticFiles() {
3255         if (staticFiles == null)
3256            staticFiles = createStaticFiles(beanStore, resource);
3257         return staticFiles;
3258      }
3259
3260      /**
3261       * Specifies the static files resource finder for this class.
3262       *
3263       * <p>
3264       * Equivalent to calling:
3265       * <p class='bjava'>
3266       *    <jv>builder</jv>.staticFiles().type(<jv>value</jv>);
3267       * </p>
3268       *
3269       * <h5 class='section'>See Also:</h5><ul>
3270       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/StaticFiles">Static files</a>
3271       * </ul>
3272       *
3273       * @param value The new value.
3274       *    <br>Cannot be <jk>null</jk>.
3275       * @return This object.
3276       */
3277      public Builder staticFiles(Class<? extends StaticFiles> value) {
3278         staticFiles().type(assertArgNotNull("value", value));
3279         return this;
3280      }
3281
3282      /**
3283       * Specifies the static files resource finder for this class.
3284       *
3285       * <p>
3286       * Equivalent to calling:
3287       * <p class='bjava'>
3288       *    <jv>builder</jv>.staticFiles().impl(<jv>value</jv>);
3289       * </p>
3290       *
3291       * <h5 class='section'>See Also:</h5><ul>
3292       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/StaticFiles">Static files</a>
3293       * </ul>
3294       *
3295       * @param value The new value.
3296       *    <br>Cannot be <jk>null</jk>.
3297       * @return This object.
3298       */
3299      public Builder staticFiles(StaticFiles value) {
3300         staticFiles().impl(assertArgNotNull("value", value));
3301         return this;
3302      }
3303
3304      /**
3305       * Returns the swagger provider sub-builder.
3306       *
3307       * @return The swagger provider sub-builder.
3308       */
3309      public BeanCreator<SwaggerProvider> swaggerProvider() {
3310         if (swaggerProvider == null)
3311            swaggerProvider = createSwaggerProvider(beanStore, resource);
3312         return swaggerProvider;
3313      }
3314
3315      /**
3316       * Specifies the swagger provider for this class.
3317       *
3318       * <p>
3319       * Equivalent to calling:
3320       * <p class='bjava'>
3321       *    <jv>builder</jv>.swaggerProvider().type(<jv>value</jv>);
3322       * </p>
3323       *
3324       * @param value The new value.
3325       *    <br>Cannot be <jk>null</jk>.
3326       * @return This object.
3327       */
3328      public Builder swaggerProvider(Class<? extends SwaggerProvider> value) {
3329         swaggerProvider().type(assertArgNotNull("value", value));
3330         return this;
3331      }
3332
3333      /**
3334       * Specifies the swagger provider for this class.
3335       *
3336       * <p>
3337       * Equivalent to calling:
3338       * <p class='bjava'>
3339       *    <jv>builder</jv>.swaggerProvider().impl(<jv>value</jv>);
3340       * </p>
3341       *
3342       * @param value The new value.
3343       *    <br>Cannot be <jk>null</jk>.
3344       * @return This object.
3345       */
3346      public Builder swaggerProvider(SwaggerProvider value) {
3347         swaggerProvider().impl(assertArgNotNull("value", value));
3348         return this;
3349      }
3350
3351      /**
3352       * Returns the thrown-store sub-builder.
3353       *
3354       * <p>
3355       * The thrown store is an in-memory cache of thrown exceptions.
3356       * It is used to store thrown exceptions when {@link MethodExecStats#error(Throwable)} is called from the {@link MethodExecStore}
3357       * bean of this resource.  It can also be accessed directly via {@link RestContext#getThrownStore()} or passed in as a parameter
3358       * on a {@link RestOp}-annotated method.
3359       *
3360       * <p>
3361       * The default thrown store is inherited from the parent context and can be overridden via any of the following:
3362       * <ul class='spaced-list'>
3363       *    <li>Injected via bean store.
3364       *    <li>{@link RestInject @RestInject}-annotated method:
3365       *       <p class='bjava'>
3366       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] ThrownStore myMethod(<i>&lt;args&gt;</i>) {...}
3367       *       </p>
3368       *       Args can be any injected bean including ThrownStore.Builder, the default builder.
3369       * </ul>
3370       *
3371       * <h5 class='section'>See Also:</h5><ul>
3372       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
3373       * </ul>
3374       *
3375       * @return The builder for the {@link ThrownStore} object in the REST context.
3376       */
3377      public ThrownStore.Builder thrownStore() {
3378         if (thrownStore == null)
3379            thrownStore = createThrownStore(beanStore(), resource(), parentContext);
3380         return thrownStore;
3381      }
3382
3383      /**
3384       * Specifies the thrown store for this class.
3385       *
3386       * <p>
3387       * Equivalent to calling:
3388       * <p class='bjava'>
3389       *    <jv>builder</jv>.thrownStore().type(<jv>value</jv>);
3390       * </p>
3391       *
3392       * <h5 class='section'>See Also:</h5><ul>
3393       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
3394       *    <li class='jm'>{@link #thrownStore()}
3395       * </ul>
3396       *
3397       * @param value The new value.
3398       *    <br>Cannot be <jk>null</jk>.
3399       * @return This object.
3400       */
3401      public Builder thrownStore(Class<? extends ThrownStore> value) {
3402         thrownStore().type(assertArgNotNull("value", value));
3403         return this;
3404      }
3405
3406      /**
3407       * Specifies the thrown store for this class.
3408       *
3409       * <p>
3410       * Equivalent to calling:
3411       * <p class='bjava'>
3412       *    <jv>builder</jv>.thrownStore().impl(<jv>value</jv>);
3413       * </p>
3414       *
3415       * <h5 class='section'>See Also:</h5><ul>
3416       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
3417       *    <li class='jm'>{@link #thrownStore()}
3418       * </ul>
3419       *
3420       * @param value The new value.
3421       *    <br>Cannot be <jk>null</jk>.
3422       * @return This object.
3423       */
3424      public Builder thrownStore(ThrownStore value) {
3425         thrownStore().impl(assertArgNotNull("value", value));
3426         return this;
3427      }
3428
3429      @Override /* Overridden from Builder */
3430      public Builder type(Class<? extends org.apache.juneau.Context> value) {
3431         super.type(value);
3432         return this;
3433      }
3434
3435      /**
3436       * Resource authority path.
3437       *
3438       * <p>
3439       * Overrides the authority path value for this resource and any child resources.
3440       *
3441       * <p>
3442       * This setting is useful if you want to resolve relative URIs to absolute paths and want to explicitly specify the hostname/port.
3443       *
3444       * <p>
3445       * Affects the following methods:
3446       * <ul class='javatree'>
3447       *    <li class='jm'>{@link RestRequest#getAuthorityPath()}
3448       * </ul>
3449       *
3450       * <p>
3451       * If you do not specify the authority, it is automatically calculated via the following:
3452       *
3453       * <p class='bjava'>
3454       *    String <jv>scheme</jv> = <jv>request</jv>.getScheme();
3455       *    <jk>int</jk> <jv>port</jv> = <jv>request</jv>.getServerPort();
3456       *    StringBuilder <jv>sb</jv> = <jk>new</jk> StringBuilder(<jv>request</jv>.getScheme()).append(<js>"://"</js>).append(<jv>request</jv>.getServerName());
3457       *    <jk>if</jk> (! (<jv>port</jv> == 80 &amp;&amp; <js>"http"</js>.equals(<jv>scheme</jv>) || port == 443 &amp;&amp; <js>"https"</js>.equals(<jv>scheme</jv>)))
3458       *       <jv>sb</jv>.append(<js>':'</js>).append(<jv>port</jv>);
3459       *    <jv>authorityPath</jv> = <jv>sb</jv>.toString();
3460       * </p>
3461       *
3462       * <h5 class='section'>Example:</h5>
3463       * <p class='bjava'>
3464       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3465       *    <ja>@Rest</ja>(
3466       *       path=<js>"/servlet"</js>,
3467       *       uriAuthority=<js>"$C{REST/authorityPathOverride,http://localhost:10000}"</js>
3468       *    )
3469       *    <jk>public class</jk> MyResource {
3470       *
3471       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3472       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3473       *
3474       *          <jc>// Using method on builder.</jc>
3475       *          <jv>builder</jv>.uriAuthority(<js>"http://localhost:10000"</js>);
3476       *       }
3477       *
3478       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3479       *       <ja>@RestInit</ja>
3480       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3481       *          <jv>builder</jv>.uriAuthority(<js>"http://localhost:10000"</js>);
3482       *       }
3483       *    }
3484       * </p>
3485       *
3486       * <h5 class='section'>See Also:</h5><ul>
3487       *    <li class='ja'>{@link Rest#uriAuthority}
3488       * </ul>
3489       *
3490       * @param value
3491       *    The new value for this setting.
3492       *    <br>The default is the first value found:
3493       *    <ul>
3494       *       <li>System property <js>"RestContext.uriAuthority"
3495       *       <li>Environment variable <js>"RESTCONTEXT_URIAUTHORITY"
3496       *       <li><jk>null</jk>
3497       *    </ul>
3498       *    <br>Cannot be <jk>null</jk>.
3499       * @return This object.
3500       */
3501      public Builder uriAuthority(String value) {
3502         uriAuthority = assertArgNotNull("value", value);
3503         return this;
3504      }
3505
3506      /**
3507       * Resource context path.
3508       *
3509       * <p>
3510       * Overrides the context path value for this resource and any child resources.
3511       *
3512       * <p>
3513       * This setting is useful if you want to use <js>"context:/child/path"</js> URLs in child resource POJOs but
3514       * the context path is not actually specified on the servlet container.
3515       *
3516       * <p>
3517       * Affects the following methods:
3518       * <ul class='javatree'>
3519       *    <li class='jm'>{@link RestRequest#getContextPath()} - Returns the overridden context path for the resource.
3520       *    <li class='jm'>{@link RestRequest#getServletPath()} - Includes the overridden context path for the resource.
3521       * </ul>
3522       *
3523       * <h5 class='section'>Example:</h5>
3524       * <p class='bjava'>
3525       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3526       *    <ja>@Rest</ja>(
3527       *       path=<js>"/servlet"</js>,
3528       *       uriContext=<js>"$C{REST/contextPathOverride,/foo}"</js>
3529       *    )
3530       *    <jk>public class</jk> MyResource {
3531       *
3532       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3533       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3534       *
3535       *          <jc>// Using method on builder.</jc>
3536       *          <jv>builder</jv>.uriContext(<js>"/foo"</js>);
3537       *       }
3538       *
3539       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3540       *       <ja>@RestInit</ja>
3541       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3542       *          <jv>builder</jv>.uriContext(<js>"/foo"</js>);
3543       *       }
3544       *    }
3545       * </p>
3546       *
3547       * <h5 class='section'>See Also:</h5><ul>
3548       *    <li class='ja'>{@link Rest#uriContext}
3549       * </ul>
3550       *
3551       * @param value
3552       *    The new value for this setting.
3553       *    <br>The default is the first value found:
3554       *    <ul>
3555       *       <li>System property <js>"RestContext.uriContext"
3556       *       <li>Environment variable <js>"RESTCONTEXT_URICONTEXT"
3557       *       <li><jk>null</jk>
3558       *    </ul>
3559       *    <br>Cannot be <jk>null</jk>.
3560       * @return This object.
3561       */
3562      public Builder uriContext(String value) {
3563         uriContext = assertArgNotNull("value", value);
3564         return this;
3565      }
3566
3567      /**
3568       * URI resolution relativity.
3569       *
3570       * <p>
3571       * Specifies how relative URIs should be interpreted by serializers.
3572       *
3573       * <p>
3574       * See {@link UriResolution} for possible values.
3575       *
3576       * <p>
3577       * Affects the following methods:
3578       * <ul class='javatree'>
3579       *    <li class='jm'>{@link RestRequest#getUriResolver()}
3580       * </ul>
3581       *
3582       * <h5 class='section'>Example:</h5>
3583       * <p class='bjava'>
3584       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3585       *    <ja>@Rest</ja>(
3586       *       path=<js>"/servlet"</js>,
3587       *       uriRelativity=<js>"$C{REST/uriRelativity,PATH_INFO}"</js>
3588       *    )
3589       *    <jk>public class</jk> MyResource {
3590       *
3591       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3592       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3593       *
3594       *          <jc>// Using method on builder.</jc>
3595       *          <jv>builder</jv>.uriRelativity(<jsf>PATH_INFO</jsf>);
3596       *       }
3597       *
3598       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3599       *       <ja>@RestInit</ja>
3600       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3601       *          <jv>builder</jv>.uriRelativity(<jsf>PATH_INFO</jsf>);
3602       *       }
3603       *    }
3604       * </p>
3605       *
3606       * <h5 class='section'>See Also:</h5><ul>
3607       *    <li class='ja'>{@link Rest#uriRelativity}
3608       * </ul>
3609       *
3610       * @param value
3611       *    The new value for this setting.
3612       *    <br>The default is the first value found:
3613       *    <ul>
3614       *       <li>System property <js>"RestContext.uriRelativity"
3615       *       <li>Environment variable <js>"RESTCONTEXT_URIRELATIVITY"
3616       *       <li>{@link UriRelativity#RESOURCE}
3617       *    </ul>
3618       *    <br>Cannot be <jk>null</jk>.
3619       * @return This object.
3620       */
3621      public Builder uriRelativity(UriRelativity value) {
3622         uriRelativity = assertArgNotNull("value", value);
3623         return this;
3624      }
3625
3626      /**
3627       * URI resolution.
3628       *
3629       * <p>
3630       * Specifies how relative URIs should be interpreted by serializers.
3631       *
3632       * <p>
3633       * See {@link UriResolution} for possible values.
3634       *
3635       * <p>
3636       * Affects the following methods:
3637       * <ul class='javatree'>
3638       *    <li class='jm'>{@link RestRequest#getUriResolver()}
3639       * </ul>
3640       *
3641       * <h5 class='section'>Example:</h5>
3642       * <p class='bjava'>
3643       *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3644       *    <ja>@Rest</ja>(
3645       *       path=<js>"/servlet"</js>,
3646       *       uriResolution=<js>"$C{REST/uriResolution,ABSOLUTE}"</js>
3647       *    )
3648       *    <jk>public class</jk> MyResource {
3649       *
3650       *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3651       *       <jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3652       *
3653       *          <jc>// Using method on builder.</jc>
3654       *          <jv>builder</jv>.uriResolution(<jsf>ABSOLUTE</jsf>);
3655       *       }
3656       *
3657       *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3658       *       <ja>@RestInit</ja>
3659       *       <jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
3660       *          <jv>builder</jv>.uriResolution(<jsf>ABSOLUTE</jsf>);
3661       *       }
3662       *    }
3663       * </p>
3664       *
3665       * <h5 class='section'>See Also:</h5><ul>
3666       *    <li class='ja'>{@link Rest#uriResolution}
3667       * </ul>
3668       *
3669       * @param value
3670       *    The new value for this setting.
3671       *    <br>The default is the first value found:
3672       *    <ul>
3673       *       <li>System property <js>"RestContext.uriResolution"
3674       *       <li>Environment variable <js>"RESTCONTEXT_URIRESOLUTION"
3675       *       <li>{@link UriResolution#ROOT_RELATIVE}
3676       *    </ul>
3677       *    <br>Cannot be <jk>null</jk>.
3678       * @return This object.
3679       */
3680      public Builder uriResolution(UriResolution value) {
3681         uriResolution = assertArgNotNull("value", value);
3682         return this;
3683      }
3684
3685      /**
3686       * Returns the variable resolver sub-builder.
3687       *
3688       * <p>
3689       *    The variable resolver is used to resolve string variables of the form <js>"$X{...}"</js> in various places such as annotations on the REST class and methods.
3690       *
3691       * <p>
3692       *    Can be used to add more variables or context objects to the variable resolver.
3693       *    These variables affect the variable resolver returned by {@link RestRequest#getVarResolverSession()}.
3694       *
3695       * <p>
3696       * The var resolver is created by the constructor using the {@link #createVarResolver(BeanStore,Supplier,Class)} method and is initialized with the following variables:
3697       * <ul class='javatreec'>
3698       *    <li class='jc'>{@link ArgsVar}
3699       *    <li class='jc'>{@link CoalesceVar}
3700       *    <li class='jc'>{@link ConfigVar}
3701       *    <li class='jc'>{@link EnvVariablesVar}
3702       *    <li class='jc'>{@link FileVar}
3703       *    <li class='jc'>{@link HtmlWidgetVar}
3704       *    <li class='jc'>{@link IfVar}
3705       *    <li class='jc'>{@link LenVar}
3706       *    <li class='jc'>{@link LocalizationVar}
3707       *    <li class='jc'>{@link LowerCaseVar}
3708       *    <li class='jc'>{@link ManifestFileVar}
3709       *    <li class='jc'>{@link NotEmptyVar}
3710       *    <li class='jc'>{@link PatternExtractVar}
3711       *    <li class='jc'>{@link PatternMatchVar}
3712       *    <li class='jc'>{@link PatternReplaceVar}
3713       *    <li class='jc'>{@link RequestAttributeVar}
3714       *    <li class='jc'>{@link RequestFormDataVar}
3715       *    <li class='jc'>{@link RequestHeaderVar}
3716       *    <li class='jc'>{@link RequestPathVar}
3717       *    <li class='jc'>{@link RequestQueryVar}
3718       *    <li class='jc'>{@link RequestSwaggerVar}
3719       *    <li class='jc'>{@link RequestVar}
3720       *    <li class='jc'>{@link SerializedRequestAttrVar}
3721       *    <li class='jc'>{@link ServletInitParamVar}
3722       *    <li class='jc'>{@link SubstringVar}
3723       *    <li class='jc'>{@link SwaggerVar}
3724       *    <li class='jc'>{@link SwitchVar}
3725       *    <li class='jc'>{@link SystemPropertiesVar}
3726       *    <li class='jc'>{@link UpperCaseVar}
3727       *    <li class='jc'>{@link UrlEncodeVar}
3728       *    <li class='jc'>{@link UrlVar}
3729       * </ul>
3730       *
3731       * <p>
3732       * The default var resolver can be overridden via any of the following:
3733       * <ul class='spaced-list'>
3734       *    <li>Injected via bean store.
3735       *    <li>{@link RestInject @RestInject}-annotated methods:
3736       *       <p class='bjava'>
3737       *    <ja>@RestInject</ja> <jk>public</jk> [<jk>static</jk>] VarResolver myMethod(<i>&lt;args&gt;</i>) {...}
3738       *       </p>
3739       *       Args can be any injected bean including {@link org.apache.juneau.svl.VarResolver.Builder}, the default builder.
3740       * </ul>
3741       *
3742       * <h5 class='section'>See Also:</h5><ul>
3743       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">SVL Variables</a>
3744       * </ul>
3745       *
3746       * @return The variable resolver sub-builder.
3747       */
3748      public VarResolver.Builder varResolver() {
3749         return varResolver;
3750      }
3751
3752      /**
3753       * Adds one or more variables to the var resolver of this class.
3754       *
3755       * <p>
3756       * Equivalent to calling:
3757       * <p class='bjava'>
3758       *    <jv>builder</jv>.vars().add(<jv>value</jv>);
3759       * </p>
3760       *
3761       * <h5 class='section'>See Also:</h5><ul>
3762       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">SVL Variables</a>
3763       *    <li class='jm'>{@link #varResolver()}
3764       * </ul>
3765       *
3766       * @param value The values to add.
3767       *    <br>Cannot contain <jk>null</jk> values.
3768       * @return This object.
3769       */
3770      @SafeVarargs
3771      public final Builder vars(Class<? extends Var>...value) {
3772         assertArgNoNulls("value", value);
3773         varResolver.vars(value);
3774         return this;
3775      }
3776
3777      /**
3778       * Adds one or more variables to the var resolver of this class.
3779       *
3780       * <p>
3781       * Equivalent to calling:
3782       * <p class='bjava'>
3783       *    <jv>builder</jv>.vars().add(<jv>value</jv>);
3784       * </p>
3785       *
3786       * <h5 class='section'>See Also:</h5><ul>
3787       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">SVL Variables</a>
3788       *    <li class='jm'>{@link #varResolver()}
3789       * </ul>
3790       *
3791       * @param value The values to add.
3792       *    <br>Cannot contain <jk>null</jk> values.
3793       * @return This object.
3794       */
3795      public Builder vars(Var...value) {
3796         assertArgNoNulls("value", value);
3797         varResolver.vars(value);
3798         return this;
3799      }
3800
3801      private static void runInitHooks(BeanStore beanStore, Supplier<?> resource) throws ServletException {
3802
3803         var r = resource.get();
3804
3805         var map = CollectionUtils.<String,MethodInfo>map();
3806         // @formatter:off
3807         ClassInfo.ofProxy(r).getAllMethodsTopDown().stream()
3808            .filter(y -> y.hasAnnotation(RestInit.class) && ! y.hasParameter(RestOpContext.Builder.class))
3809            .forEach(y -> {
3810               var sig = y.getSignature();
3811               if (! map.containsKey(sig))
3812                  map.put(sig, y.accessible());
3813            }
3814         );
3815         // @formatter:on
3816
3817         for (var m : map.values()) {
3818            if (! beanStore.hasAllParams(m))
3819               throw servletException("Could not call @RestInit method {0}.{1}.  Could not find prerequisites: {2}.", cns(m.getDeclaringClass()), m.getSignature(), beanStore.getMissingParams(m));
3820            try {
3821               m.invoke(r, beanStore.getParams(m));
3822            } catch (Exception e) {
3823               throw servletException(e, "Exception thrown from @RestInit method {0}.{1}.", cns(m.getDeclaringClass()), m.getSignature());
3824            }
3825         }
3826      }
3827
3828      /**
3829       * Instantiates the bean context sub-builder.
3830       *
3831       * @param beanStore
3832       *    The factory used for creating beans and retrieving injected beans.
3833       * @param resource
3834       *    The REST servlet/bean instance that this context is defined against.
3835       * @return A new bean context sub-builder.
3836       */
3837      protected BeanContext.Builder createBeanContext(BeanStore beanStore, Supplier<?> resource) {
3838
3839         // Default value.
3840         Value<BeanContext.Builder> v = Value.of(BeanContext.create());
3841
3842         // Replace with builder from bean store.
3843         // @formatter:off
3844         beanStore
3845            .getBean(BeanContext.Builder.class)
3846            .map(BeanContext.Builder::copy)
3847            .ifPresent(x -> v.set(x));
3848         // @formatter:on
3849
3850         // Replace with bean from bean store.
3851         beanStore.getBean(BeanContext.class).ifPresent(x -> v.get().impl(x));
3852
3853         return v.get();
3854      }
3855
3856      /**
3857       * Creates the bean store in this builder.
3858       *
3859       * @param resource
3860       *    The REST servlet/bean instance that this context is defined against.
3861       * @return A new bean store builder.
3862       */
3863      protected BeanStore.Builder createBeanStore(Supplier<?> resource) {
3864
3865         // Default value.
3866         // @formatter:off
3867         var v = Value.of(
3868            BeanStore
3869               .create()
3870               .parent(rootBeanStore())
3871               .outer(resource.get())
3872            );
3873         // @formatter:on
3874
3875         // Apply @Rest(beanStore).
3876         rstream(AP.find(Rest.class, info(resourceClass))).map(x -> x.inner().beanStore()).filter(ClassUtils::isNotVoid).forEach(x -> v.get().type(x));
3877
3878         // Replace with bean from:  @RestInject public [static] BeanStore xxx(<args>)
3879         // @formatter:off
3880         v.get().build()
3881            .createMethodFinder(BeanStore.class)
3882            .find(Builder::isRestInjectMethod)
3883            .run(x -> v.get().impl(x));
3884         // @formatter:on
3885
3886         return v.get();
3887      }
3888
3889      /**
3890       * Instantiates the call logger sub-builder.
3891       *
3892       * <h5 class='section'>See Also:</h5><ul>
3893       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
3894       * </ul>
3895       *
3896       * @param beanStore
3897       *    The factory used for creating beans and retrieving injected beans.
3898       * @param resource
3899       *    The REST servlet/bean instance that this context is defined against.
3900       * @return A new call logger sub-builder.
3901       */
3902      protected BeanCreator<CallLogger> createCallLogger(BeanStore beanStore, Supplier<?> resource) {
3903
3904         var creator = beanStore.createBean(CallLogger.class).type(BasicCallLogger.class);
3905
3906         // Specify the bean type if its set as a default.
3907         defaultClasses().get(CallLogger.class).ifPresent(x -> creator.type(x));
3908
3909         beanStore.getBean(CallLogger.class).ifPresent(x -> creator.impl(x));
3910
3911         // Replace with bean from:  @RestInject public [static] CallLogger xxx(<args>)
3912         beanStore.createMethodFinder(CallLogger.class).find(Builder::isRestInjectMethod).run(x -> creator.impl(x));
3913
3914         return creator;
3915      }
3916
3917      /**
3918       * Creates the config for this builder.
3919       *
3920       * <h5 class='section'>See Also:</h5><ul>
3921       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ConfigurationFiles">Configuration Files</a>
3922       *    <li class='jm'>{@link #config()}
3923       * </ul>
3924       *
3925       * @param beanStore
3926       *    The factory used for creating beans and retrieving injected beans.
3927       * @param resource
3928       *    The REST servlet/bean instance that this context is defined against.
3929       * @param resourceClass
3930       *    The REST servlet/bean type that this context is defined against.
3931       * @return A new config.
3932       */
3933      protected Config createConfig(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
3934
3935         var v = Value.<Config>empty();
3936
3937         // Find our config file.  It's the last non-empty @RestResource(config).
3938         var vr = beanStore.getBean(VarResolver.class).orElseThrow(() -> new IllegalArgumentException("VarResolver not found."));
3939         var cfv = Value.<String>empty();
3940         rstream(AP.find(Rest.class, info(resourceClass))).map(x -> x.inner().config()).filter(Utils::ne).forEach(x -> cfv.set(vr.resolve(x)));
3941         var cf = cfv.orElse("");
3942
3943         // If not specified or value is set to SYSTEM_DEFAULT, use system default config.
3944         if (v.isEmpty() && "SYSTEM_DEFAULT".equals(cf))
3945            v.set(Config.getSystemDefault());
3946
3947         // Otherwise build one.
3948         if (v.isEmpty()) {
3949            Config.Builder cb = Config.create().varResolver(vr);
3950            if (! cf.isEmpty())
3951               cb.name(cf);
3952            v.set(cb.build());
3953         }
3954
3955         // Replace with bean from bean store.
3956         beanStore.getBean(Config.class).ifPresent(x -> v.set(x));
3957
3958         // Replace with bean from:  @RestInject public [static] Config xxx(<args>)
3959         beanStore.createMethodFinder(Config.class).addBean(Config.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.set(x));
3960
3961         return v.get();
3962      }
3963
3964      /**
3965       * Instantiates the debug enablement bean creator.
3966       *
3967       * @param beanStore
3968       *    The factory used for creating beans and retrieving injected beans.
3969       * @param resource
3970       *    The REST servlet/bean instance that this context is defined against.
3971       * @return A new debug enablement bean creator.
3972       */
3973      protected BeanCreator<DebugEnablement> createDebugEnablement(BeanStore beanStore, Supplier<?> resource) {
3974
3975         var creator = beanStore.createBean(DebugEnablement.class).type(BasicDebugEnablement.class);
3976
3977         // Specify the bean type if its set as a default.
3978         defaultClasses().get(DebugEnablement.class).ifPresent(x -> creator.type(x));
3979
3980         beanStore.getBean(DebugEnablement.class).ifPresent(x -> creator.impl(x));
3981
3982         // Replace with bean from:  @RestInject public [static] DebugEnablement xxx(<args>)
3983         beanStore.createMethodFinder(DebugEnablement.class).find(Builder::isRestInjectMethod).run(x -> creator.impl(x));
3984
3985         return creator;
3986      }
3987
3988      /**
3989       * Instantiates the default request attributes sub-builder.
3990       *
3991       * @param beanStore
3992       *    The factory used for creating beans and retrieving injected beans.
3993       * @param resource
3994       *    The REST servlet/bean instance that this context is defined against.
3995       * @return A new default request attributes sub-builder.
3996       */
3997      protected NamedAttributeMap createDefaultRequestAttributes(BeanStore beanStore, Supplier<?> resource) {
3998
3999         // Default value.
4000         var v = Value.of(NamedAttributeMap.create());
4001
4002         beanStore.getBean(NamedAttributeMap.class, "defaultRequestAttributes").ifPresent(x -> v.set(x));
4003
4004         // Replace with bean from:  @RestInject(name="defaultRequestAttributes") public [static] NamedAttributeMap xxx(<args>)
4005         beanStore.createMethodFinder(NamedAttributeMap.class).addBean(NamedAttributeMap.class, v.get()).find(x -> isRestInjectMethod(x, "defaultRequestAttributes")).run(x -> v.set(x));
4006
4007         return v.get();
4008      }
4009
4010      /**
4011       * Instantiates the default request headers sub-builder.
4012       *
4013       * @param beanStore
4014       *    The factory used for creating beans and retrieving injected beans.
4015       * @param resource
4016       *    The REST servlet/bean instance that this context is defined against.
4017       * @return A new default request headers sub-builder.
4018       */
4019      protected HeaderList createDefaultRequestHeaders(BeanStore beanStore, Supplier<?> resource) {
4020
4021         // Default value.
4022         var v = Value.of(HeaderList.create());
4023
4024         // Replace with bean from bean store.
4025         beanStore.getBean(HeaderList.class, "defaultRequestHeaders").ifPresent(x -> v.set(x));
4026
4027         // Replace with bean from:  @RestInject(name="defaultRequestHeaders") public [static] HeaderList xxx(<args>)
4028         beanStore.createMethodFinder(HeaderList.class).addBean(HeaderList.class, v.get()).find(x -> isRestInjectMethod(x, "defaultRequestHeaders")).run(x -> v.set(x));
4029
4030         return v.get();
4031      }
4032
4033      /**
4034       * Instantiates the default response headers sub-builder.
4035       *
4036       * @param beanStore
4037       *    The factory used for creating beans and retrieving injected beans.
4038       * @param resource
4039       *    The REST servlet/bean instance that this context is defined against.
4040       * @return A new default response headers sub-builder.
4041       */
4042      protected HeaderList createDefaultResponseHeaders(BeanStore beanStore, Supplier<?> resource) {
4043
4044         // Default value.
4045         var v = Value.of(HeaderList.create());
4046
4047         // Replace with bean from bean store.
4048         beanStore.getBean(HeaderList.class, "defaultResponseHeaders").ifPresent(x -> v.set(x));
4049
4050         // Replace with bean from:  @RestInject(name="defaultResponseHeaders") public [static] HeaderList xxx(<args>)
4051         beanStore.createMethodFinder(HeaderList.class).addBean(HeaderList.class, v.get()).find(x -> isRestInjectMethod(x, "defaultResponseHeaders")).run(x -> v.set(x));
4052
4053         return v.get();
4054      }
4055
4056      /**
4057       * Instantiates the destroy method list.
4058       *
4059       * @param beanStore
4060       *    The factory used for creating beans and retrieving injected beans.
4061       * @param resource
4062       *    The REST servlet/bean instance that this context is defined against.
4063       * @return A new destroy method list.
4064       */
4065      protected MethodList createDestroyMethods(BeanStore beanStore, Supplier<?> resource) {
4066
4067         // Default value.
4068         var v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestDestroy.class).collect(Collectors.toList())));
4069
4070         // Replace with bean from:  @RestInject(name="destroyMethods") public [static] MethodList xxx(<args>)
4071         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "destroyMethods")).run(x -> v.set(x));
4072
4073         return v.get();
4074      }
4075
4076      /**
4077       * Instantiates the encoder group sub-builder.
4078       *
4079       * <h5 class='section'>See Also:</h5><ul>
4080       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerEncoders">Encoders</a>
4081       *    <li class='jm'>{@link #encoders()}
4082       * </ul>
4083       *
4084       * @param resource
4085       *    The REST servlet/bean instance that this context is defined against.
4086       * @param beanStore
4087       *    The factory used for creating beans and retrieving injected beans.
4088       *    <br>Created by {@link RestContext.Builder#beanStore()}.
4089       * @return A new encoder group sub-builder.
4090       */
4091      protected EncoderSet.Builder createEncoders(BeanStore beanStore, Supplier<?> resource) {
4092
4093         // Default value.
4094         Value<EncoderSet.Builder> v = Value.of(EncoderSet.create(beanStore).add(IdentityEncoder.INSTANCE));
4095
4096         // Specify the implementation class if its set as a default.
4097         defaultClasses().get(EncoderSet.class).ifPresent(x -> v.get().type(x));
4098
4099         // Replace with bean from bean store.
4100         beanStore.getBean(EncoderSet.class).ifPresent(x -> v.get().impl(x));
4101
4102         // Replace with bean from:  @RestInject public [static] EncoderSet xxx(<args>)
4103         beanStore.createMethodFinder(EncoderSet.class).addBean(EncoderSet.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4104
4105         return v.get();
4106      }
4107
4108      /**
4109       * Instantiates the end call method list.
4110       *
4111       * @param beanStore
4112       *    The factory used for creating beans and retrieving injected beans.
4113       * @param resource
4114       *    The REST servlet/bean instance that this context is defined against.
4115       * @return A new end call method list.
4116       */
4117      protected MethodList createEndCallMethods(BeanStore beanStore, Supplier<?> resource) {
4118
4119         // Default value.
4120         Value<MethodList> v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestEndCall.class).collect(Collectors.toList())));
4121
4122         // Replace with bean from:  @RestInject(name="endCallMethods") public [static] MethodList xxx(<args>)
4123         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "endCallMethods")).run(x -> v.set(x));
4124
4125         return v.get();
4126      }
4127
4128      /**
4129       * Instantiates the JSON schema generator sub-builder.
4130       *
4131       * <h5 class='section'>See Also:</h5><ul>
4132       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
4133       * </ul>
4134       *
4135       * @param beanStore
4136       *    The factory used for creating beans and retrieving injected beans.
4137       * @param resource
4138       *    The REST servlet/bean instance that this context is defined against.
4139       * @return A new JSON schema generator sub-builder.
4140       */
4141      protected JsonSchemaGenerator.Builder createJsonSchemaGenerator(BeanStore beanStore, Supplier<?> resource) {
4142
4143         // Default value.
4144         var v = Value.of(JsonSchemaGenerator.create());
4145
4146         // Replace with builder from bean store.
4147         beanStore.getBean(JsonSchemaGenerator.Builder.class).map(JsonSchemaGenerator.Builder::copy).ifPresent(x -> v.set(x));
4148
4149         // Replace with bean from bean store.
4150         beanStore.getBean(JsonSchemaGenerator.class).ifPresent(x -> v.get().impl(x));
4151
4152         // Replace with bean from:  @RestInject public [static] JsonSchemaGenerator xxx(<args>)
4153         beanStore.createMethodFinder(JsonSchemaGenerator.class).addBean(JsonSchemaGenerator.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4154
4155         return v.get();
4156      }
4157
4158      /**
4159       * Instantiates the logger for this resource.
4160       *
4161       * <h5 class='section'>See Also:</h5><ul>
4162       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging / Debugging</a>
4163       *    <li class='jm'>{@link #logger()}
4164       * </ul>
4165       *
4166       * @param beanStore
4167       *    The factory used for creating beans and retrieving injected beans.
4168       * @param resource
4169       *    The REST servlet/bean instance that this context is defined against.
4170       * @param resourceClass
4171       *    The REST servlet/bean class that this context is defined against.
4172       * @return A new logger.
4173       */
4174      protected Logger createLogger(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
4175
4176         // Default value.
4177         Value<Logger> v = Value.of(Logger.getLogger(cn(resourceClass)));
4178
4179         // Replace with bean from bean store.
4180         beanStore.getBean(Logger.class).ifPresent(x -> v.set(x));
4181
4182         // Replace with bean from:  @RestInject public [static] Logger xxx(<args>)
4183         beanStore.createMethodFinder(Logger.class).addBean(Logger.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.set(x));
4184
4185         return v.get();
4186      }
4187
4188      /**
4189       * Instantiates the messages sub-builder.
4190       *
4191       * <h5 class='section'>See Also:</h5><ul>
4192       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/LocalizedMessages">Localized Messages</a>
4193       * </ul>
4194       *
4195       * @param beanStore
4196       *    The factory used for creating beans and retrieving injected beans.
4197       * @param resource
4198       *    The REST servlet/bean instance that this context is defined against.
4199       * @return A new messages sub-builder.
4200       */
4201      protected Messages.Builder createMessages(BeanStore beanStore, Supplier<?> resource) {
4202
4203         // Default value.
4204         Value<Messages.Builder> v = Value.of(Messages.create(resourceClass));
4205
4206         // Replace with bean from bean store.
4207         beanStore.getBean(Messages.class).ifPresent(x -> v.get().impl(x));
4208
4209         // Replace with bean from:  @RestInject public [static] Messages xxx(<args>)
4210         beanStore.createMethodFinder(Messages.class).addBean(Messages.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4211
4212         return v.get();
4213      }
4214
4215      /**
4216       * Instantiates the method execution statistics store sub-builder.
4217       *
4218       * <h5 class='section'>See Also:</h5><ul>
4219       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
4220       * </ul>
4221       *
4222       * @param beanStore
4223       *    The factory used for creating beans and retrieving injected beans.
4224       * @param resource
4225       *    The REST servlet/bean instance that this context is defined against.
4226       * @return A new method execution statistics store sub-builder.
4227       */
4228      protected MethodExecStore.Builder createMethodExecStore(BeanStore beanStore, Supplier<?> resource) {
4229
4230         // Default value.
4231         Value<MethodExecStore.Builder> v = Value.of(MethodExecStore.create(beanStore));
4232
4233         // Specify the implementation class if its set as a default.
4234         defaultClasses().get(MethodExecStore.class).ifPresent(x -> v.get().type(x));
4235
4236         // Replace with bean from bean store.
4237         beanStore.getBean(MethodExecStore.class).ifPresent(x -> v.get().impl(x));
4238
4239         // Replace with bean from:  @RestInject public [static] MethodExecStore xxx(<args>)
4240         beanStore.createMethodFinder(MethodExecStore.class).addBean(MethodExecStore.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4241
4242         return v.get();
4243      }
4244
4245      /**
4246       * Instantiates the parser group sub-builder.
4247       *
4248       * <h5 class='section'>See Also:</h5><ul>
4249       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
4250       * </ul>
4251       *
4252       * @param resource
4253       *    The REST servlet/bean instance that this context is defined against.
4254       * @param beanStore
4255       *    The factory used for creating beans and retrieving injected beans.
4256       *    <br>Created by {@link RestContext.Builder#beanStore()}.
4257       * @return A new parser group sub-builder.
4258       */
4259      protected ParserSet.Builder createParsers(BeanStore beanStore, Supplier<?> resource) {
4260
4261         // Default value.
4262         Value<ParserSet.Builder> v = Value.of(ParserSet.create(beanStore));
4263
4264         // Specify the implementation class if its set as a default.
4265         defaultClasses().get(ParserSet.class).ifPresent(x -> v.get().type(x));
4266
4267         // Replace with bean from bean store.
4268         beanStore.getBean(ParserSet.class).ifPresent(x -> v.get().impl(x));
4269
4270         // Replace with bean from:  @RestInject public [static] ParserSet xxx(<args>)
4271         beanStore.createMethodFinder(ParserSet.class).addBean(ParserSet.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4272
4273         return v.get();
4274      }
4275
4276      /**
4277       * Instantiates the part parser sub-builder.
4278       *
4279       * <h5 class='section'>See Also:</h5><ul>
4280       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
4281       * </ul>
4282       *
4283       * @param beanStore
4284       *    The factory used for creating beans and retrieving injected beans.
4285       * @param resource
4286       *    The REST servlet/bean instance that this context is defined against.
4287       * @return A new part parser sub-builder.
4288       */
4289      protected HttpPartParser.Creator createPartParser(BeanStore beanStore, Supplier<?> resource) {
4290
4291         // Default value.
4292         Value<HttpPartParser.Creator> v = Value.of(HttpPartParser.creator().type(OpenApiParser.class));
4293
4294         // Replace with builder from bean store.
4295         beanStore.getBean(HttpPartParser.Creator.class).map(HttpPartParser.Creator::copy).ifPresent(x -> v.set(x));
4296
4297         // Replace with bean from bean store.
4298         beanStore.getBean(HttpPartParser.class).ifPresent(x -> v.get().impl(x));
4299
4300         // Replace with this bean.
4301         resourceAs(HttpPartParser.class).ifPresent(x -> v.get().impl(x));
4302
4303         // Specify the bean type if its set as a default.
4304         defaultClasses().get(HttpPartParser.class).ifPresent(x -> v.get().type(x));
4305
4306         // Replace with bean from:  @RestInject public [static] HttpPartParser xxx(<args>)
4307         beanStore.createMethodFinder(HttpPartParser.class).addBean(HttpPartParser.Creator.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4308
4309         return v.get();
4310      }
4311
4312      /**
4313       * Instantiates the part serializer sub-builder.
4314       *
4315       * <h5 class='section'>See Also:</h5><ul>
4316       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HttpParts">HTTP Parts</a>
4317       * </ul>
4318       *
4319       * @param beanStore
4320       *    The factory used for creating beans and retrieving injected beans.
4321       * @param resource
4322       *    The REST servlet/bean instance that this context is defined against.
4323       * @return A new part serializer sub-builder.
4324       */
4325      protected HttpPartSerializer.Creator createPartSerializer(BeanStore beanStore, Supplier<?> resource) {
4326
4327         // Default value.
4328         Value<HttpPartSerializer.Creator> v = Value.of(HttpPartSerializer.creator().type(OpenApiSerializer.class));
4329
4330         // Replace with builder from bean store.
4331         beanStore.getBean(HttpPartSerializer.Creator.class).map(Creator::copy).ifPresent(x -> v.set(x));
4332
4333         // Replace with bean from bean store.
4334         beanStore.getBean(HttpPartSerializer.class).ifPresent(x -> v.get().impl(x));
4335
4336         // Replace with this bean.
4337         resourceAs(HttpPartSerializer.class).ifPresent(x -> v.get().impl(x));
4338
4339         // Specify the bean type if its set as a default.
4340         defaultClasses().get(HttpPartSerializer.class).ifPresent(x -> v.get().type(x));
4341
4342         // Replace with bean from:  @RestInject public [static] HttpPartSerializer xxx(<args>)
4343         beanStore.createMethodFinder(HttpPartSerializer.class).addBean(HttpPartSerializer.Creator.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4344
4345         return v.get();
4346      }
4347
4348      /**
4349       * Instantiates the post-call method list.
4350       *
4351       * @param beanStore
4352       *    The factory used for creating beans and retrieving injected beans.
4353       * @param resource
4354       *    The REST servlet/bean instance that this context is defined against.
4355       * @return A new post-call method list.
4356       */
4357      protected MethodList createPostCallMethods(BeanStore beanStore, Supplier<?> resource) {
4358
4359         // Default value.
4360         Value<MethodList> v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestPostCall.class).collect(Collectors.toList())));
4361
4362         // Replace with bean from:  @RestInject(name="postCallMethods") public [static] MethodList xxx(<args>)
4363         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "postCallMethods")).run(x -> v.set(x));
4364
4365         return v.get();
4366      }
4367
4368      /**
4369       * Instantiates the post-init-child-first method list.
4370       *
4371       * @param beanStore
4372       *    The factory used for creating beans and retrieving injected beans.
4373       * @param resource
4374       *    The REST servlet/bean instance that this context is defined against.
4375       * @return A new post-init-child-first method list.
4376       */
4377      protected MethodList createPostInitChildFirstMethods(BeanStore beanStore, Supplier<?> resource) {
4378
4379         // Default value.
4380         var ap = AP;
4381         Value<MethodList> v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestPostInit.class)
4382            .filter(m -> {
4383               var mi = MethodInfo.of(m);
4384               return rstream(ap.find(RestPostInit.class, mi))
4385                  .map(AnnotationInfo::inner)
4386                  .anyMatch(RestPostInit::childFirst);
4387            })
4388            .collect(Collectors.toList())));
4389
4390         // Replace with bean from:  @RestInject(name="postInitChildFirstMethods") public [static] MethodList xxx(<args>)
4391         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "postInitChildFirstMethods")).run(x -> v.set(x));
4392
4393         return v.get();
4394      }
4395
4396      /**
4397       * Instantiates the post-init method list.
4398       *
4399       * @param beanStore
4400       *    The factory used for creating beans and retrieving injected beans.
4401       * @param resource
4402       *    The REST servlet/bean instance that this context is defined against.
4403       * @return A new post-init method list.
4404       */
4405      protected MethodList createPostInitMethods(BeanStore beanStore, Supplier<?> resource) {
4406
4407         // Default value.
4408         var ap = AP;
4409         Value<MethodList> v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestPostInit.class)
4410            .filter(m -> {
4411               var mi = MethodInfo.of(m);
4412               return rstream(ap.find(RestPostInit.class, mi))
4413                  .map(AnnotationInfo::inner)
4414                  .anyMatch(x -> ! x.childFirst());
4415            })
4416            .collect(Collectors.toList())));
4417
4418         // Replace with bean from:  @RestInject(name="postInitMethods") public [static] MethodList xxx(<args>)
4419         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "postInitMethods")).run(x -> v.set(x));
4420
4421         return v.get();
4422      }
4423
4424      /**
4425       * Instantiates the pre-call method list.
4426       *
4427       * @param beanStore
4428       *    The factory used for creating beans and retrieving injected beans.
4429       * @param resource
4430       *    The REST servlet/bean instance that this context is defined against.
4431       * @return A new pre-call method list.
4432       */
4433      protected MethodList createPreCallMethods(BeanStore beanStore, Supplier<?> resource) {
4434
4435         // Default value.
4436         Value<MethodList> v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestPreCall.class).collect(Collectors.toList())));
4437
4438         // Replace with bean from:  @RestInject(name="preCallMethods") public [static] MethodList xxx(<args>)
4439         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "preCallMethods")).run(x -> v.set(x));
4440
4441         return v.get();
4442      }
4443
4444      /**
4445       * Instantiates the response processor list sub-builder.
4446       *
4447       * <h5 class='section'>See Also:</h5><ul>
4448       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ResponseProcessors">Response Processors</a>
4449       * </ul>
4450       *
4451       * @param beanStore
4452       *    The factory used for creating beans and retrieving injected beans.
4453       * @param resource
4454       *    The REST servlet/bean instance that this context is defined against.
4455       * @return A new response processor list sub-builder.
4456       */
4457      protected ResponseProcessorList.Builder createResponseProcessors(BeanStore beanStore, Supplier<?> resource) {
4458
4459         // Default value.
4460         // @formatter:off
4461         Value<ResponseProcessorList.Builder> v = Value.of(
4462             ResponseProcessorList
4463               .create(beanStore)
4464               .add(
4465                  ReaderProcessor.class,
4466                  InputStreamProcessor.class,
4467                  ThrowableProcessor.class,
4468                  HttpResponseProcessor.class,
4469                  HttpResourceProcessor.class,
4470                  HttpEntityProcessor.class,
4471                  ResponseBeanProcessor.class,
4472                  PlainTextPojoProcessor.class,
4473                  SerializedPojoProcessor.class
4474               )
4475         );
4476         // @formatter:on
4477
4478         // Replace with bean from bean store.
4479         beanStore.getBean(ResponseProcessorList.class).ifPresent(x -> v.get().impl(x));
4480
4481         // Replace with bean from:  @RestInject public [static] ResponseProcessorList xxx(<args>)
4482         beanStore.createMethodFinder(ResponseProcessorList.class).addBean(ResponseProcessorList.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4483
4484         return v.get();
4485      }
4486
4487      /**
4488       * Instantiates the REST children list.
4489       *
4490       * @param restContext The rest context.
4491       * @param beanStore
4492       *    The factory used for creating beans and retrieving injected beans.
4493       * @param resource
4494       *    The REST servlet/bean instance that this context is defined against.
4495       * @return A new REST children list.
4496       * @throws Exception If a problem occurred instantiating one of the child rest contexts.
4497       */
4498      protected RestChildren.Builder createRestChildren(BeanStore beanStore, Supplier<?> resource, RestContext restContext) throws Exception {
4499
4500         // Default value.
4501         Value<RestChildren.Builder> v = Value.of(RestChildren.create(beanStore).type(childrenClass));
4502
4503         // Initialize our child resources.
4504         for (var o : children) {
4505            var path = (String)null;
4506            Supplier<?> so;
4507
4508            if (o instanceof RestChild o2) {
4509               path = o2.path;
4510               var o3 = o2.resource;
4511               so = () -> o3;
4512            }
4513
4514            var cb = (Builder)null;
4515
4516            if (o instanceof Class<?> oc) {
4517               // Don't allow specifying yourself as a child.  Causes an infinite loop.
4518               if (oc == resourceClass)
4519                  continue;
4520               cb = RestContext.create(oc, restContext, inner);
4521               if (beanStore.getBean(oc).isPresent()) {
4522                  so = () -> beanStore.getBean(oc).get();  // If we resolved via injection, always get it this way.
4523               } else {
4524                  Object o2 = beanStore.createBean(oc).builder(RestContext.Builder.class, cb).run();
4525                  so = () -> o2;
4526               }
4527            } else {
4528               cb = RestContext.create(o.getClass(), restContext, inner);
4529               so = () -> o;
4530            }
4531
4532            if (nn(path))
4533               cb.path(path);
4534
4535            var cc = cb.init(so).build();
4536
4537            var mi = ClassInfo.of(so.get()).getMethod(x -> x.hasName("setContext") && x.hasParameterTypes(RestContext.class)).orElse(null);
4538            if (nn(mi))
4539               mi.accessible().invoke(so.get(), cc);
4540
4541            v.get().add(cc);
4542         }
4543
4544         // Replace with bean from:  @RestInject public [static] RestChildren xxx(<args>)
4545         beanStore.createMethodFinder(RestChildren.class).addBean(RestChildren.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4546
4547         return v.get();
4548      }
4549
4550      /**
4551       * Instantiates the REST operation args sub-builder.
4552       *
4553       * <p>
4554       * Instantiates based on the following logic:
4555       * <ul>
4556       *    <li>Looks for REST op args set via any of the following:
4557       *       <ul>
4558       *          <li>{@link RestContext.Builder#restOpArgs(Class...)}/{@link RestContext.Builder#restOpArgs(Class...)}
4559       *          <li>{@link Rest#restOpArgs()}.
4560       *       </ul>
4561       *    <li>Looks for a static or non-static <c>createRestParams()</c> method that returns <c>{@link Class}[]</c>.
4562       *    <li>Resolves it via the bean store registered in this context.
4563       *    <li>Instantiates a default set of parameters.
4564       * </ul>
4565       *
4566       * @param beanStore
4567       *    The factory used for creating beans and retrieving injected beans.
4568       * @param resource
4569       *    The REST servlet/bean instance that this context is defined against.
4570       * @return A new REST operation args sub-builder.
4571       */
4572      protected RestOpArgList.Builder createRestOpArgs(BeanStore beanStore, Supplier<?> resource) {
4573
4574         // Default value.
4575         Value<RestOpArgList.Builder> v = Value.of(RestOpArgList.create(beanStore).add(AttributeArg.class, ContentArg.class, FormDataArg.class, HasFormDataArg.class, HasQueryArg.class,
4576            HeaderArg.class, HttpServletRequestArgs.class, HttpServletResponseArgs.class, HttpSessionArgs.class, InputStreamParserArg.class, MethodArg.class, ParserArg.class, PathArg.class,
4577            PathRemainderArg.class, QueryArg.class, ReaderParserArg.class, RequestBeanArg.class, ResponseBeanArg.class, ResponseHeaderArg.class, ResponseCodeArg.class, RestContextArgs.class,
4578            RestSessionArgs.class, RestOpContextArgs.class, RestOpSessionArgs.class, RestRequestArgs.class, RestResponseArgs.class, DefaultArg.class));
4579
4580         // Replace with bean from bean store.
4581         beanStore.getBean(RestOpArgList.class).ifPresent(x -> v.get().impl(x));
4582
4583         // Replace with bean from:  @RestInject public [static] RestOpArgList xxx(<args>)
4584         beanStore.createMethodFinder(RestOpArgList.class).addBean(RestOpArgList.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4585
4586         return v.get();
4587      }
4588
4589      /**
4590       * Instantiates the REST operations list.
4591       *
4592       * <p>
4593       * The set of {@link RestOpContext} objects that represent the methods on this resource.
4594       *
4595       * @param restContext The rest context.
4596       * @param beanStore
4597       *    The factory used for creating beans and retrieving injected beans.
4598       * @param resource
4599       *    The REST servlet/bean instance that this context is defined against.
4600       * @return A new REST operations list.
4601       * @throws ServletException If a problem occurred instantiating one of the child rest contexts.
4602       */
4603      protected RestOperations.Builder createRestOperations(BeanStore beanStore, Supplier<?> resource, RestContext restContext) throws ServletException {
4604
4605         // Default value.
4606         Value<RestOperations.Builder> v = Value.of(RestOperations.create(beanStore));
4607         var ap = restContext.getBeanContext().getAnnotationProvider();
4608
4609         var rci = ClassInfo.of(resource.get());
4610
4611         var initMap = CollectionUtils.<String,MethodInfo>map();
4612         // @formatter:off
4613         ClassInfo.ofProxy(resource.get()).getAllMethodsTopDown().stream()
4614            .filter(y -> y.hasAnnotation(RestInit.class) && y.hasParameter(RestOpContext.Builder.class))
4615            .forEach(y -> {
4616               var sig = y.getSignature();
4617               if (! initMap.containsKey(sig))
4618                  initMap.put(sig, y.accessible());
4619            });
4620         // @formatter:on
4621
4622         for (var mi : rci.getPublicMethods()) {
4623            var al = rstream(ap.find(mi)).filter(REST_OP_GROUP).collect(Collectors.toList());
4624
4625            // Also include methods on @Rest-annotated interfaces.
4626            if (al.isEmpty()) {
4627               Predicate<MethodInfo> isRestAnnotatedInterface = x -> x.getDeclaringClass().isInterface()
4628                  && nn(x.getDeclaringClass().getAnnotations(Rest.class).findFirst().map(AnnotationInfo::inner).orElse(null));
4629               mi.getMatchingMethods().stream().filter(isRestAnnotatedInterface).forEach(x -> al.add(AnnotationInfo.of(x, RestOpAnnotation.DEFAULT)));
4630            }
4631
4632            if (al.size() > 0) {
4633               try {
4634                  if (mi.isNotPublic())
4635                     throw servletException("@RestOp method {0}.{1} must be defined as public.", rci.inner().getName(), mi.getSimpleName());
4636
4637                  RestOpContext.Builder rocb = RestOpContext.create(mi.inner(), restContext).beanStore(beanStore).type(opContextClass);
4638
4639                  beanStore = BeanStore.of(beanStore, resource.get()).addBean(RestOpContext.Builder.class, rocb);
4640                  for (var m : initMap.values()) {
4641                     if (! beanStore.hasAllParams(m)) {
4642                        throw servletException("Could not call @RestInit method {0}.{1}.  Could not find prerequisites: {2}.", cns(m.getDeclaringClass()), m.getSignature(),
4643                           beanStore.getMissingParams(m));
4644                     }
4645                     try {
4646                        m.invoke(resource.get(), beanStore.getParams(m));
4647                     } catch (Exception e) {
4648                        throw servletException(e, "Exception thrown from @RestInit method {0}.{1}.", cns(m.getDeclaringClass()), m.getSignature());
4649                     }
4650                  }
4651
4652                  var roc = rocb.build();
4653
4654                  String httpMethod = roc.getHttpMethod();
4655
4656                  // RRPC is a special case where a method returns an interface that we
4657                  // can perform REST calls against.
4658                  // We override the CallMethod.invoke() method to insert our logic.
4659                  if ("RRPC".equals(httpMethod)) {
4660
4661                     // @formatter:off
4662                     RestOpContext roc2 = RestOpContext
4663                        .create(mi.inner(), restContext)
4664                        .dotAll()
4665                        .beanStore(restContext.getRootBeanStore())
4666                        .type(RrpcRestOpContext.class)
4667                        .build();
4668                     v.get()
4669                        .add("GET", roc2)
4670                        .add("POST", roc2);
4671                     // @formatter:on
4672
4673                  } else {
4674                     v.get().add(roc);
4675                  }
4676               } catch (Throwable e) {
4677                  throw servletException(e, "Problem occurred trying to initialize methods on class {0}", rci.inner().getName());
4678               }
4679            }
4680         }
4681
4682         // Replace with bean from:  @RestInject public [static] RestOperations xxx(<args>)
4683         beanStore.createMethodFinder(RestOperations.class).addBean(RestOperations.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4684
4685         return v.get();
4686      }
4687
4688      /**
4689       * Instantiates the serializer group sub-builder.
4690       *
4691       * <h5 class='section'>See Also:</h5><ul>
4692       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
4693       * </ul>
4694       *
4695       * @param resource
4696       *    The REST servlet/bean instance that this context is defined against.
4697       * @param beanStore
4698       *    The factory used for creating beans and retrieving injected beans.
4699       *    <br>Created by {@link RestContext.Builder#beanStore()}.
4700       * @return A new serializer group sub-builder.
4701       */
4702      protected SerializerSet.Builder createSerializers(BeanStore beanStore, Supplier<?> resource) {
4703
4704         // Default value.
4705         Value<SerializerSet.Builder> v = Value.of(SerializerSet.create(beanStore));
4706
4707         // Specify the implementation class if its set as a default.
4708         defaultClasses().get(SerializerSet.class).ifPresent(x -> v.get().type(x));
4709
4710         // Replace with bean from bean store.
4711         beanStore.getBean(SerializerSet.class).ifPresent(x -> v.get().impl(x));
4712
4713         // Replace with bean from:  @RestInject public [static] SerializerSet xxx(<args>)
4714         beanStore.createMethodFinder(SerializerSet.class).addBean(SerializerSet.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4715
4716         return v.get();
4717      }
4718
4719      /**
4720       * Instantiates the start call method list.
4721       *
4722       * @param beanStore
4723       *    The factory used for creating beans and retrieving injected beans.
4724       * @param resource
4725       *    The REST servlet/bean instance that this context is defined against.
4726       * @return A new start call method list.
4727       */
4728      protected MethodList createStartCallMethods(BeanStore beanStore, Supplier<?> resource) {
4729
4730         // Default value.
4731         Value<MethodList> v = Value.of(MethodList.of(getAnnotatedMethods(resource, RestStartCall.class).collect(Collectors.toList())));
4732
4733         // Replace with bean from:  @RestInject(name="startCallMethods") public [static] MethodList xxx(<args>)
4734         beanStore.createMethodFinder(MethodList.class).addBean(MethodList.class, v.get()).find(x -> isRestInjectMethod(x, "startCallMethods")).run(x -> v.set(x));
4735
4736         return v.get();
4737      }
4738
4739      /**
4740       * Instantiates the static files bean creator.
4741       *
4742       * <h5 class='section'>See Also:</h5><ul>
4743       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/StaticFiles">Static files</a>
4744       * </ul>
4745       *
4746       * @param beanStore
4747       *    The factory used for creating beans and retrieving injected beans.
4748       * @param resource
4749       *    The REST servlet/bean instance that this context is defined against.
4750       * @return A new static files sub-builder.
4751       */
4752      protected BeanCreator<StaticFiles> createStaticFiles(BeanStore beanStore, Supplier<?> resource) {
4753
4754         var creator = beanStore.createBean(StaticFiles.class).type(BasicStaticFiles.class);
4755
4756         // Specify the bean type if its set as a default.
4757         defaultClasses().get(StaticFiles.class).ifPresent(x -> creator.type(x));
4758
4759         beanStore.getBean(StaticFiles.class).ifPresent(x -> creator.impl(x));
4760
4761         // Replace with bean from:  @RestInject public [static] StaticFiles xxx(<args>)
4762         beanStore.createMethodFinder(StaticFiles.class).find(Builder::isRestInjectMethod).run(x -> creator.impl(x));
4763
4764         return creator;
4765      }
4766
4767      /**
4768       * Instantiates the swagger provider sub-builder.
4769       *
4770       * <p>
4771       * Instantiates based on the following logic:
4772       * <ul>
4773       *    <li>Returns the resource class itself is an instance of {@link SwaggerProvider}.
4774       *    <li>Looks for swagger provider set via any of the following:
4775       *       <ul>
4776       *          <li>{@link RestContext.Builder#swaggerProvider(Class)}/{@link RestContext.Builder#swaggerProvider(SwaggerProvider)}
4777       *          <li>{@link Rest#swaggerProvider()}.
4778       *       </ul>
4779       *    <li>Looks for a static or non-static <c>createSwaggerProvider()</c> method that returns {@link SwaggerProvider} on the
4780       *       resource class with any of the following arguments:
4781       *       <ul>
4782       *          <li>{@link RestContext}
4783       *          <li>{@link BeanStore}
4784       *          <li>Any <a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestServerSpringbootBasics">juneau-rest-server-springboot Basics</a>.
4785       *       </ul>
4786       *    <li>Resolves it via the bean store registered in this context.
4787       *    <li>Instantiates a default {@link BasicSwaggerProvider}.
4788       * </ul>
4789       *
4790       * <h5 class='section'>See Also:</h5><ul>
4791       *    <li class='jm'>{@link RestContext.Builder#swaggerProvider(Class)}
4792       *    <li class='jm'>{@link RestContext.Builder#swaggerProvider(SwaggerProvider)}
4793       * </ul>
4794       *
4795       * @param beanStore
4796       *    The factory used for creating beans and retrieving injected beans.
4797       * @param resource
4798       *    The REST servlet/bean instance that this context is defined against.
4799       * @return A new swagger provider sub-builder.
4800       */
4801      protected BeanCreator<SwaggerProvider> createSwaggerProvider(BeanStore beanStore, Supplier<?> resource) {
4802
4803         var creator = beanStore.createBean(SwaggerProvider.class).type(BasicSwaggerProvider.class);
4804
4805         // Specify the bean type if its set as a default.
4806         defaultClasses().get(SwaggerProvider.class).ifPresent(x -> creator.type(x));
4807
4808         beanStore.getBean(SwaggerProvider.class).ifPresent(x -> creator.impl(x));
4809
4810         // Replace with bean from:  @RestInject public [static] SwaggerProvider xxx(<args>)
4811         beanStore.createMethodFinder(SwaggerProvider.class).find(Builder::isRestInjectMethod).run(x -> creator.impl(x));
4812
4813         return creator;
4814      }
4815
4816      /**
4817       * Instantiates the thrown-store sub-builder.
4818       *
4819       * <h5 class='section'>See Also:</h5><ul>
4820       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ExecutionStatistics">REST method execution statistics</a>
4821       * </ul>
4822       *
4823       * @param resource
4824       *    The REST servlet/bean instance that this context is defined against.
4825       * @param parent
4826       *    The parent context if the REST bean was registered via {@link Rest#children()}.
4827       *    <br>Will be <jk>null</jk> if the bean is a top-level resource.
4828       * @param beanStore
4829       *    The factory used for creating beans and retrieving injected beans.
4830       *    <br>Created by {@link RestContext.Builder#beanStore()}.
4831       * @return A new thrown-store sub-builder.
4832       */
4833      protected ThrownStore.Builder createThrownStore(BeanStore beanStore, Supplier<?> resource, RestContext parent) {
4834
4835         // Default value.
4836         Value<ThrownStore.Builder> v = Value.of(ThrownStore.create(beanStore).impl(parent == null ? null : parent.getThrownStore()));
4837
4838         // Specify the implementation class if its set as a default.
4839         defaultClasses().get(ThrownStore.class).ifPresent(x -> v.get().type(x));
4840
4841         // Replace with bean from bean store.
4842         beanStore.getBean(ThrownStore.class).ifPresent(x -> v.get().impl(x));
4843
4844         // Replace with bean from:  @RestInject public [static] ThrownStore xxx(<args>)
4845         beanStore.createMethodFinder(ThrownStore.class).addBean(ThrownStore.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4846
4847         return v.get();
4848      }
4849
4850      /**
4851       * Creates the variable resolver sub-builder.
4852       *
4853       * <h5 class='section'>See Also:</h5><ul>
4854       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">SVL Variables</a>
4855       * </ul>
4856       *
4857       * @param beanStore
4858       *    The factory used for creating beans and retrieving injected beans.
4859       * @param resource
4860       *    The REST servlet/bean instance that this context is defined against.
4861       * @param resourceClass
4862       *    The REST servlet/bean type that this context is defined against.
4863       * @return A new variable resolver sub-builder.
4864       */
4865      protected VarResolver.Builder createVarResolver(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
4866
4867         // Default value.
4868         // @formatter:off
4869         Value<VarResolver.Builder> v = Value.of(
4870            VarResolver
4871               .create()
4872               .defaultVars()
4873               .vars(
4874                  VarList.of(
4875                     ConfigVar.class,
4876                     FileVar.class,
4877                     LocalizationVar.class,
4878                     RequestAttributeVar.class,
4879                     RequestFormDataVar.class,
4880                     RequestHeaderVar.class,
4881                     RequestPathVar.class,
4882                     RequestQueryVar.class,
4883                     RequestVar.class,
4884                     RequestSwaggerVar.class,
4885                     SerializedRequestAttrVar.class,
4886                     ServletInitParamVar.class,
4887                     SwaggerVar.class,
4888                     UrlVar.class,
4889                     UrlEncodeVar.class,
4890                     HtmlWidgetVar.class
4891                  )
4892                  .addDefault()
4893               )
4894               .bean(FileFinder.class, FileFinder.create(beanStore).cp(resourceClass,null,true).build())
4895         );
4896         // @formatter:on
4897
4898         // Replace with bean from bean store.
4899         beanStore.getBean(VarResolver.class).ifPresent(x -> v.get().impl(x));
4900
4901         // Replace with bean from:  @RestInject public [static] VarResolver xxx(<args>)
4902         beanStore.createMethodFinder(VarResolver.class).addBean(VarResolver.Builder.class, v.get()).find(Builder::isRestInjectMethod).run(x -> v.get().impl(x));
4903
4904         return v.get();
4905      }
4906   }
4907
4908   private static final Map<Class<?>,RestContext> REGISTRY = new ConcurrentHashMap<>();
4909
4910   /**
4911    * Creates a new builder for this object.
4912    *
4913    * @param resourceClass
4914    *    The class annotated with <ja>@Rest</ja>.
4915    *    <br>Must not be <jk>null</jk>.
4916    * @param parentContext
4917    *    The parent context if the REST bean was registered via {@link Rest#children()}.
4918    *    <br>Can be <jk>null</jk> if the bean is a top-level resource.
4919    * @param servletConfig
4920    *    The servlet config passed into the servlet by the servlet container.
4921    *    <br>Can be <jk>null</jk> if not available.
4922    *    <br>If <jk>null</jk>, then some features (such as access to servlet init params) will not be available.
4923    *
4924    * @return A new builder object.
4925    * @throws ServletException Something bad happened.
4926    */
4927   public static Builder create(Class<?> resourceClass, RestContext parentContext, ServletConfig servletConfig) throws ServletException {
4928      return new Builder(resourceClass, parentContext, servletConfig);
4929   }
4930
4931   /**
4932    * Returns a registry of all created {@link RestContext} objects.
4933    *
4934    * @return An unmodifiable map of resource classes to {@link RestContext} objects.
4935    */
4936   public static final Map<Class<?>,RestContext> getGlobalRegistry() { return u(REGISTRY); }
4937
4938   static ServletException servletException(String msg, Object...args) {
4939      return new ServletException(f(msg, args));
4940   }
4941
4942   static ServletException servletException(Throwable t, String msg, Object...args) {
4943      return new ServletException(f(msg, args), t);
4944   }
4945
4946   protected final boolean allowContentParam;
4947   protected final boolean renderResponseStackTraces;
4948   protected final long maxInput;
4949   protected final AtomicBoolean initialized = new AtomicBoolean(false);
4950   protected final BasicHttpException initException;
4951   protected final BeanContext beanContext;
4952   protected final BeanStore beanStore;
4953   protected final BeanStore rootBeanStore;
4954   protected final Builder builder;
4955   protected final CallLogger callLogger;
4956   protected final Charset defaultCharset;
4957   protected final Class<?> resourceClass;
4958   protected final Class<? extends RestOpArg>[] restOpArgs;
4959   protected final ConcurrentHashMap<Locale,Swagger> swaggerCache = new ConcurrentHashMap<>();
4960   protected final Config config;
4961   protected final DebugEnablement debugEnablement;
4962   protected final DefaultClassList defaultClasses;
4963   protected final DefaultSettingsMap defaultSettings;
4964   protected final EncoderSet encoders;
4965   protected final HeaderList defaultRequestHeaders;
4966   protected final HeaderList defaultResponseHeaders;
4967   protected final HttpPartParser partParser;
4968   protected final HttpPartSerializer partSerializer;
4969   protected final Instant startTime;
4970   protected final JsonSchemaGenerator jsonSchemaGenerator;
4971   protected final List<MediaType> consumes;
4972   protected final List<MediaType> produces;
4973   protected final Logger logger;
4974   protected final Messages messages;
4975   protected final MethodExecStore methodExecStore;
4976   protected final NamedAttributeMap defaultRequestAttributes;
4977   protected final ParserSet parsers;
4978   protected final RestChildren restChildren;
4979   protected final RestContext parentContext;
4980   protected final RestOperations restOperations;
4981   protected final ResponseProcessor[] responseProcessors;
4982   protected final SerializerSet serializers;
4983   protected final Set<String> allowedHeaderParams;
4984   protected final Set<String> allowedMethodHeaders;
4985   protected final Set<String> allowedMethodParams;
4986   protected final StaticFiles staticFiles;
4987   protected final String clientVersionHeader;
4988   protected final String fullPath;
4989   protected final String path;
4990   protected final String uriAuthority;
4991   protected final String uriContext;
4992   protected final SwaggerProvider swaggerProvider;
4993   protected final ThrownStore thrownStore;
4994   protected final ThreadLocal<RestSession> localSession = new ThreadLocal<>();
4995   protected final UriRelativity uriRelativity;
4996   protected final UriResolution uriResolution;
4997   protected final UrlPathMatcher pathMatcher;
4998   protected final VarResolver varResolver;
4999   private final MethodInvoker[] destroyMethods;
5000   private final MethodInvoker[] endCallMethods;
5001   private final MethodInvoker[] postInitChildFirstMethods;
5002   private final MethodInvoker[] postInitMethods;
5003   private final MethodInvoker[] startCallMethods;
5004   private final MethodList postCallMethods;
5005   private final MethodList preCallMethods;
5006   private final Supplier<?> resource;
5007
5008   /**
5009    * Constructor.
5010    *
5011    * @param builder The builder containing the settings for this bean.
5012    * @throws Exception If any initialization problems were encountered.
5013    */
5014   public RestContext(Builder builder) throws Exception {
5015      super(builder);
5016
5017      startTime = Instant.now();
5018
5019      REGISTRY.put(builder.resourceClass, this);
5020
5021      BasicHttpException _initException = null;
5022
5023      try {
5024         this.builder = builder;
5025
5026         defaultClasses = builder.defaultClasses();
5027         defaultSettings = builder.defaultSettings();
5028         parentContext = builder.parentContext;
5029         resource = builder.resource;
5030         resourceClass = builder.resourceClass;
5031         rootBeanStore = builder.rootBeanStore();
5032
5033         BeanStore bs = beanStore = builder.beanStore();
5034         // @formatter:off
5035         beanStore
5036            .addBean(BeanStore.class, beanStore)
5037            .addBean(RestContext.class, this)
5038            .addBean(Object.class, resource.get())
5039            .addBean(DefaultSettingsMap.class, defaultSettings)
5040            .addBean(Builder.class, builder)
5041            .addBean(AnnotationWorkList.class, builder.getApplied());
5042         // @formatter:on
5043
5044         path = nn(builder.path) ? builder.path : "";
5045         fullPath = (parentContext == null ? "" : (parentContext.fullPath + '/')) + path;
5046         var p = path;
5047         if (! p.endsWith("/*"))
5048            p += "/*";
5049         pathMatcher = UrlPathMatcher.of(p);
5050
5051         allowContentParam = ! builder.disableContentParam;
5052         allowedHeaderParams = newCaseInsensitiveSet(opt(builder.allowedHeaderParams).map(x -> "NONE".equals(x) ? "" : x).orElse(""));
5053         allowedMethodHeaders = newCaseInsensitiveSet(opt(builder.allowedMethodHeaders).map(x -> "NONE".equals(x) ? "" : x).orElse(""));
5054         allowedMethodParams = newCaseInsensitiveSet(opt(builder.allowedMethodParams).map(x -> "NONE".equals(x) ? "" : x).orElse(""));
5055         clientVersionHeader = builder.clientVersionHeader;
5056         defaultCharset = builder.defaultCharset;
5057         maxInput = builder.maxInput;
5058         renderResponseStackTraces = builder.renderResponseStackTraces;
5059         uriAuthority = builder.uriAuthority;
5060         uriContext = builder.uriContext;
5061         uriRelativity = builder.uriRelativity;
5062         uriResolution = builder.uriResolution;
5063
5064         beanContext = bs.add(BeanContext.class, builder.beanContext().build());
5065         encoders = bs.add(EncoderSet.class, builder.encoders().build());
5066         serializers = bs.add(SerializerSet.class, builder.serializers().build());
5067         parsers = bs.add(ParserSet.class, builder.parsers().build());
5068         logger = bs.add(Logger.class, builder.logger());
5069         thrownStore = bs.add(ThrownStore.class, builder.thrownStore().build());
5070         methodExecStore = bs.add(MethodExecStore.class, builder.methodExecStore().thrownStoreOnce(thrownStore).build());
5071         messages = bs.add(Messages.class, builder.messages().build());
5072         varResolver = bs.add(VarResolver.class, builder.varResolver().bean(Messages.class, messages).build());
5073         config = bs.add(Config.class, builder.config().resolving(varResolver.createSession()));
5074         responseProcessors = bs.add(ResponseProcessor[].class, builder.responseProcessors().build().toArray());
5075         callLogger = bs.add(CallLogger.class, builder.callLogger().orElse(null));
5076         partSerializer = bs.add(HttpPartSerializer.class, builder.partSerializer().create());
5077         partParser = bs.add(HttpPartParser.class, builder.partParser().create());
5078         jsonSchemaGenerator = bs.add(JsonSchemaGenerator.class, builder.jsonSchemaGenerator().build());
5079         staticFiles = bs.add(StaticFiles.class, builder.staticFiles().orElse(null));
5080         bs.add(FileFinder.class, staticFiles);
5081         defaultRequestHeaders = bs.add(HeaderList.class, builder.defaultRequestHeaders(), "defaultRequestHeaders");
5082         defaultResponseHeaders = bs.add(HeaderList.class, builder.defaultResponseHeaders(), "defaultResponseHeaders");
5083         defaultRequestAttributes = bs.add(NamedAttributeMap.class, builder.defaultRequestAttributes(), "defaultRequestAttributes");
5084         restOpArgs = builder.restOpArgs().build().asArray();
5085         debugEnablement = bs.add(DebugEnablement.class, builder.debugEnablement().orElse(null));
5086         startCallMethods = builder.startCallMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
5087         endCallMethods = builder.endCallMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
5088         postInitMethods = builder.postInitMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
5089         postInitChildFirstMethods = builder.postInitChildFirstMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
5090         destroyMethods = builder.destroyMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
5091         preCallMethods = builder.preCallMethods();
5092         postCallMethods = builder.postCallMethods();
5093         restOperations = builder.restOperations(this).build();
5094         restChildren = builder.restChildren(this).build();
5095         swaggerProvider = bs.add(SwaggerProvider.class, builder.swaggerProvider().orElse(null));
5096
5097         var opContexts = restOperations.getOpContexts();
5098
5099         // @formatter:off
5100         produces = builder.produces().orElseGet(
5101            ()->{
5102               Set<MediaType> s = opContexts.isEmpty() ? emptySet() : toSet(opContexts.get(0).getSerializers().getSupportedMediaTypes());
5103               opContexts.forEach(x -> s.retainAll(x.getSerializers().getSupportedMediaTypes()));
5104               return u(toList(s));
5105            }
5106         );
5107         consumes = builder.consumes().orElseGet(
5108            ()->{
5109               Set<MediaType> s = opContexts.isEmpty() ? emptySet() : toSet(opContexts.get(0).getParsers().getSupportedMediaTypes());
5110               opContexts.forEach(x -> s.retainAll(x.getParsers().getSupportedMediaTypes()));
5111               return u(toList(s));
5112            }
5113         );
5114         // @formatter:on
5115
5116      } catch (BasicHttpException e) {
5117         _initException = e;
5118         throw e;
5119      } catch (Exception e) {
5120         _initException = new InternalServerError(e);
5121         throw e;
5122      } finally {
5123         initException = _initException;
5124      }
5125   }
5126
5127   @Override /* Overridden from Context */
5128   public RestSession.Builder createSession() {
5129      return RestSession.create(this);
5130   }
5131
5132   /**
5133    * Called during servlet destruction to invoke all {@link RestDestroy} methods.
5134    */
5135   public void destroy() {
5136      for (var x : destroyMethods) {
5137         try {
5138            x.invoke(beanStore, getResource());
5139         } catch (Exception e) {
5140            getLogger().log(Level.WARNING, unwrap(e), () -> f("Error occurred invoking servlet-destroy method ''{0}''.", x.getFullName()));
5141         }
5142      }
5143
5144      restChildren.destroy();
5145   }
5146
5147   /**
5148    * The main service method.
5149    *
5150    * <p>
5151    * Subclasses can optionally override this method if they want to tailor the behavior of requests.
5152    *
5153    * @param resource
5154    *    The REST servlet or bean that this context defines.
5155    *    <br>Note that this bean may not be the same bean used during initialization as it may have been replaced at runtime.
5156    * @param r1 The incoming HTTP servlet request object.
5157    * @param r2 The incoming HTTP servlet response object.
5158    * @throws ServletException General servlet exception.
5159    * @throws IOException Thrown by underlying stream.
5160    */
5161   public void execute(Object resource, HttpServletRequest r1, HttpServletResponse r2) throws ServletException, IOException {
5162
5163      // Must be careful not to bleed thread-locals.
5164      if (nn(localSession.get()))
5165         System.err.println("WARNING:  Thread-local call object was not cleaned up from previous request.  " + this + ", thread=[" + Thread.currentThread().getId() + "]");
5166
5167      RestSession.Builder sb = createSession().resource(resource).req(r1).res(r2).logger(getCallLogger());
5168
5169      try {
5170
5171         if (nn(initException))
5172            throw initException;
5173
5174         // If the resource path contains variables (e.g. @Rest(path="/f/{a}/{b}"), then we want to resolve
5175         // those variables and push the servletPath to include the resolved variables.  The new pathInfo will be
5176         // the remainder after the new servletPath.
5177         // Only do this for the top-level resource because the logic for child resources are processed next.
5178         if (pathMatcher.hasVars() && parentContext == null) {
5179            var sp = sb.req().getServletPath();
5180            var pi = sb.getPathInfoUndecoded();
5181            var upi2 = UrlPath.of(pi == null ? sp : sp + pi);
5182            var uppm = pathMatcher.match(upi2);
5183         if (nn(uppm) && ! uppm.hasEmptyVars()) {
5184            sb.pathVars(uppm.getVars());
5185            var pathInfo = opt(validatePathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))).orElse("\u0000");
5186            var servletPath = validateServletPath(uppm.getPrefix());
5187            sb.req(new HttpServletRequestWrapper(sb.req()) {
5188               @Override
5189               public String getPathInfo() {
5190                  return pathInfo.charAt(0) == (char)0 ? null : pathInfo;
5191               }
5192               @Override
5193               public String getServletPath() {
5194                  return servletPath;
5195               }
5196            });
5197         } else {
5198               var call = sb.build();
5199               call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
5200               return;
5201            }
5202         }
5203
5204         // If this resource has child resources, try to recursively call them.
5205         var childMatch = restChildren.findMatch(sb);
5206         if (childMatch.isPresent()) {
5207            var uppm = childMatch.get().getPathMatch();
5208            var rc = childMatch.get().getChildContext();
5209            if (! uppm.hasEmptyVars()) {
5210               sb.pathVars(uppm.getVars());
5211               var pathInfo = opt(validatePathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))).orElse("\u0000");
5212               var servletPath = validateServletPath(sb.req().getServletPath() + uppm.getPrefix());
5213               var childRequest = new HttpServletRequestWrapper(sb.req()) {
5214                  @Override
5215                  public String getPathInfo() {
5216                     return pathInfo.charAt(0) == (char)0 ? null : pathInfo;
5217                  }
5218                  @Override
5219                  public String getServletPath() {
5220                     return servletPath;
5221                  }
5222               };
5223               rc.execute(rc.getResource(), childRequest, sb.res());
5224            } else {
5225               var call = sb.build();
5226               call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
5227            }
5228            return;
5229         }
5230
5231      } catch (Throwable e) {
5232         handleError(sb.build(), convertThrowable(e));
5233      }
5234
5235      var s = sb.build();
5236
5237      try {
5238         localSession.set(s);
5239         s.debug(isDebug(s));
5240         startCall(s);
5241         s.run();
5242      } catch (Throwable e) {
5243         handleError(s, convertThrowable(e));
5244      } finally {
5245         try {
5246            s.finish();
5247            endCall(s);
5248         } finally {
5249            localSession.remove();
5250         }
5251      }
5252   }
5253
5254   /**
5255    * Allowed header URL parameters.
5256    *
5257    * <h5 class='section'>See Also:</h5><ul>
5258    *    <li class='ja'>{@link Rest#allowedHeaderParams}
5259    *    <li class='jm'>{@link RestContext.Builder#allowedHeaderParams(String)}
5260    * </ul>
5261    *
5262    * @return
5263    *    The header names allowed to be passed as URL parameters.
5264    *    <br>The set is case-insensitive ordered and unmodifiable.
5265    */
5266   public Set<String> getAllowedHeaderParams() { return allowedHeaderParams; }
5267
5268   /**
5269    * Allowed method headers.
5270    *
5271    * <h5 class='section'>See Also:</h5><ul>
5272    *    <li class='ja'>{@link Rest#allowedMethodHeaders}
5273    *    <li class='jm'>{@link RestContext.Builder#allowedMethodHeaders(String)}
5274    * </ul>
5275    *
5276    * @return
5277    *    The method names allowed to be passed as <c>X-Method</c> headers.
5278    *    <br>The set is case-insensitive ordered and unmodifiable.
5279    */
5280   public Set<String> getAllowedMethodHeaders() { return allowedMethodHeaders; }
5281
5282   /**
5283    * Allowed method URL parameters.
5284    *
5285    * <h5 class='section'>See Also:</h5><ul>
5286    *    <li class='ja'>{@link Rest#allowedMethodParams}
5287    *    <li class='jm'>{@link RestContext.Builder#allowedMethodParams(String)}
5288    * </ul>
5289    *
5290    * @return
5291    *    The method names allowed to be passed as <c>method</c> URL parameters.
5292    *    <br>The set is case-insensitive ordered and unmodifiable.
5293    */
5294   public Set<String> getAllowedMethodParams() { return allowedMethodParams; }
5295
5296   /**
5297    * Returns the annotations applied to this context.
5298    *
5299    * @return The annotations applied to this context.
5300    */
5301   public AnnotationWorkList getAnnotations() { return builder.getApplied(); }
5302
5303   /**
5304    * Returns the bean context associated with this context.
5305    *
5306    * @return The bean store associated with this context.
5307    */
5308   public BeanContext getBeanContext() { return beanContext; }
5309
5310   /**
5311    * Returns the bean store associated with this context.
5312    *
5313    * <p>
5314    * The bean store is used for instantiating child resource classes.
5315    *
5316    * @return The resource resolver associated with this context.
5317    */
5318   public BeanStore getBeanStore() { return beanStore; }
5319
5320   /**
5321    * Returns the builder that created this context.
5322    *
5323    * @return The builder that created this context.
5324    */
5325   public ServletConfig getBuilder() { return builder; }
5326
5327   /**
5328    * Returns the call logger to use for this resource.
5329    *
5330    * <h5 class='section'>See Also:</h5><ul>
5331    *    <li class='jm'>{@link RestContext.Builder#callLogger()}
5332    * </ul>
5333    *
5334    * @return
5335    *    The call logger to use for this resource.
5336    *    <br>Never <jk>null</jk>.
5337    */
5338   public CallLogger getCallLogger() { return callLogger; }
5339
5340   /**
5341    * Returns the name of the client version header name used by this resource.
5342    *
5343    * <h5 class='section'>See Also:</h5><ul>
5344    *    <li class='ja'>{@link Rest#clientVersionHeader}
5345    *    <li class='jm'>{@link RestContext.Builder#clientVersionHeader(String)}
5346    * </ul>
5347    *
5348    * @return
5349    *    The name of the client version header used by this resource.
5350    *    <br>Never <jk>null</jk>.
5351    */
5352   public String getClientVersionHeader() { return clientVersionHeader; }
5353
5354   /**
5355    * Returns the config file associated with this servlet.
5356    *
5357    * <p>
5358    * The config file is identified via one of the following:
5359    * <ul class='javatree'>
5360    *    <li class='ja'>{@link Rest#config()}
5361    *    <li class='jm'>{@link RestContext.Builder#config(Config)}
5362    * </ul>
5363    *
5364    * @return
5365    *    The resolving config file associated with this servlet.
5366    *    <br>Never <jk>null</jk>.
5367    */
5368   public Config getConfig() { return config; }
5369
5370   /**
5371    * Returns the explicit list of supported content types for this resource.
5372    *
5373    * <p>
5374    * Consists of the media types for consumption common to all operations on this class.
5375    *
5376    * <p>
5377    * Can be overridden by {@link RestContext.Builder#consumes(MediaType...)}.
5378    *
5379    * @return
5380    *    An unmodifiable list of supported <c>Content-Type</c> header values for this resource.
5381    *    <br>Never <jk>null</jk>.
5382    */
5383   public List<MediaType> getConsumes() { return consumes; }
5384
5385   /**
5386    * Returns the debug enablement bean for this context.
5387    *
5388    * @return The debug enablement bean for this context.
5389    */
5390   public DebugEnablement getDebugEnablement() { return debugEnablement; }
5391
5392   /**
5393    * Returns the default request attributes for this resource.
5394    *
5395    * <h5 class='section'>See Also:</h5><ul>
5396    *    <li class='jm'>{@link RestContext.Builder#defaultRequestAttributes(NamedAttribute...)}
5397    * </ul>
5398    *
5399    * @return
5400    *    The default request headers for this resource in an unmodifiable list.
5401    *    <br>Never <jk>null</jk>.
5402    */
5403   public NamedAttributeMap getDefaultRequestAttributes() { return defaultRequestAttributes; }
5404
5405   /**
5406    * Returns the default request headers for this resource.
5407    *
5408    * <h5 class='section'>See Also:</h5><ul>
5409    *    <li class='jm'>{@link RestContext.Builder#defaultRequestHeaders(org.apache.http.Header...)}
5410    * </ul>
5411    *
5412    * @return
5413    *    The default request headers for this resource in an unmodifiable list.
5414    *    <br>Never <jk>null</jk>.
5415    */
5416   public HeaderList getDefaultRequestHeaders() { return defaultRequestHeaders; }
5417
5418   /**
5419    * Returns the default response headers for this resource.
5420    *
5421    * <h5 class='section'>See Also:</h5><ul>
5422    *    <li class='jm'>{@link RestContext.Builder#defaultResponseHeaders(org.apache.http.Header...)}
5423    * </ul>
5424    *
5425    * @return
5426    *    The default response headers for this resource in an unmodifiable list.
5427    *    <br>Never <jk>null</jk>.
5428    */
5429   public HeaderList getDefaultResponseHeaders() { return defaultResponseHeaders; }
5430
5431   /**
5432    * Returns the encoders associated with this context.
5433    *
5434    * @return The encoders associated with this context.
5435    */
5436   public EncoderSet getEncoders() { return encoders; }
5437
5438   /**
5439    * Returns the path for this resource as defined by the {@link Rest#path() @Rest(path)} annotation or
5440    * {@link RestContext.Builder#path(String)} method concatenated with those on all parent classes.
5441    *
5442    * <p>
5443    * If path is not specified, returns <js>""</js>.
5444    *
5445    * <h5 class='section'>See Also:</h5><ul>
5446    *    <li class='jm'>{@link RestContext.Builder#path(String)}
5447    * </ul>
5448    *
5449    * @return The full path.
5450    */
5451   public String getFullPath() { return fullPath; }
5452
5453   /**
5454    * Returns the JSON-Schema generator associated with this resource.
5455    *
5456    * @return
5457    *    The HTTP-part serializer associated with this resource.
5458    *    <br>Never <jk>null</jk>.
5459    */
5460   public JsonSchemaGenerator getJsonSchemaGenerator() { return jsonSchemaGenerator; }
5461
5462   /**
5463    * Returns the HTTP call for the current request.
5464    *
5465    * @return The HTTP call for the current request, never <jk>null</jk>?
5466    * @throws InternalServerError If no active request exists on the current thread.
5467    */
5468   public RestSession getLocalSession() {
5469      var rc = localSession.get();
5470      if (rc == null)
5471         throw new InternalServerError("No active request on current thread.");
5472      return rc;
5473   }
5474
5475   /**
5476    * Returns the logger associated with this context.
5477    *
5478    * @return
5479    *    The logger for this resource.
5480    *    <br>Never <jk>null</jk>.
5481    */
5482   public Logger getLogger() { return logger; }
5483
5484   /**
5485    * Returns the resource bundle used by this resource.
5486    *
5487    * @return
5488    *    The resource bundle for this resource.
5489    *    <br>Never <jk>null</jk>.
5490    */
5491   public Messages getMessages() { return messages; }
5492
5493   /**
5494    * Returns the timing statistics on all method executions on this class.
5495    *
5496    * @return The timing statistics on all method executions on this class.
5497    */
5498   public MethodExecStore getMethodExecStore() { return methodExecStore; }
5499
5500   /**
5501    * Returns the parsers associated with this context.
5502    *
5503    * @return The parsers associated with this context.
5504    */
5505   public ParserSet getParsers() { return parsers; }
5506
5507   /**
5508    * Returns the HTTP-part parser associated with this resource.
5509    *
5510    * @return
5511    *    The HTTP-part parser associated with this resource.
5512    *    <br>Never <jk>null</jk>.
5513    */
5514   public HttpPartParser getPartParser() { return partParser; }
5515
5516   /**
5517    * Returns the HTTP-part serializer associated with this resource.
5518    *
5519    * @return
5520    *    The HTTP-part serializer associated with this resource.
5521    *    <br>Never <jk>null</jk>.
5522    */
5523   public HttpPartSerializer getPartSerializer() { return partSerializer; }
5524
5525   /**
5526    * Returns the path for this resource as defined by the {@link Rest#path() @Rest(path)} annotation or
5527    * {@link RestContext.Builder#path(String)} method.
5528    *
5529    * <p>
5530    * If path is not specified, returns <js>""</js>.
5531    *
5532    * <h5 class='section'>See Also:</h5><ul>
5533    *    <li class='jm'>{@link RestContext.Builder#path(String)}
5534    * </ul>
5535    *
5536    * @return The servlet path.
5537    */
5538   public String getPath() { return path; }
5539
5540   /**
5541    * Returns the path matcher for this context.
5542    *
5543    * @return The path matcher for this context.
5544    */
5545   public UrlPathMatcher getPathMatcher() { return pathMatcher; }
5546
5547   /**
5548    * Returns the explicit list of supported accept types for this resource.
5549    *
5550    * <p>
5551    * Consists of the media types for production common to all operations on this class.
5552    *
5553    * <p>
5554    * Can be overridden by {@link RestContext.Builder#produces(MediaType...)}.
5555    *
5556    * @return
5557    *    An unmodifiable list of supported <c>Accept</c> header values for this resource.
5558    *    <br>Never <jk>null</jk>.
5559    */
5560   public List<MediaType> getProduces() { return produces; }
5561
5562   /**
5563    * Returns the resource object.
5564    *
5565    * <p>
5566    * This is the instance of the class annotated with the {@link Rest @Rest} annotation, usually
5567    * an instance of {@link RestServlet}.
5568    *
5569    * @return
5570    *    The resource object.
5571    *    <br>Never <jk>null</jk>.
5572    */
5573   public Object getResource() { return resource.get(); }
5574
5575   /**
5576    * Returns the resource class type.
5577    *
5578    * @return The resource class type.
5579    */
5580   public Class<?> getResourceClass() { return resourceClass; }
5581
5582   /**
5583    * Returns the child resources associated with this servlet.
5584    *
5585    * @return
5586    *    An unmodifiable map of child resources.
5587    *    Keys are the {@link Rest#path() @Rest(path)} annotation defined on the child resource.
5588    */
5589   public RestChildren getRestChildren() { return restChildren; }
5590
5591   /**
5592    * Returns the REST Java methods defined in this resource.
5593    *
5594    * <p>
5595    * These are the methods annotated with the {@link RestOp @RestOp} annotation.
5596    *
5597    * @return
5598    *    An unmodifiable map of Java method names to call method objects.
5599    */
5600   public RestOperations getRestOperations() { return restOperations; }
5601
5602   /**
5603    * Returns the root bean store for this context.
5604    *
5605    * @return The root bean store for this context.
5606    */
5607   public BeanStore getRootBeanStore() { return rootBeanStore; }
5608
5609   /**
5610    * Returns the serializers associated with this context.
5611    *
5612    * @return The serializers associated with this context.
5613    */
5614   public SerializerSet getSerializers() { return serializers; }
5615
5616   /**
5617    * Returns the servlet init parameter returned by {@link ServletConfig#getInitParameter(String)}.
5618    *
5619    * @param name The init parameter name.
5620    * @return The servlet init parameter, or <jk>null</jk> if not found.
5621    */
5622   public String getServletInitParameter(String name) {
5623      return builder.getInitParameter(name);
5624   }
5625
5626   /**
5627    * Returns the static files associated with this context.
5628    *
5629    * @return
5630    *    The static files for this resource.
5631    *    <br>Never <jk>null</jk>.
5632    */
5633   public StaticFiles getStaticFiles() { return staticFiles; }
5634
5635   /**
5636    * Gives access to the internal statistics on this context.
5637    *
5638    * @return The context statistics.
5639    */
5640   public RestContextStats getStats() { return new RestContextStats(startTime, getMethodExecStore().getStatsByTotalTime()); }
5641
5642   /**
5643    * Returns the swagger for the REST resource.
5644    *
5645    * @param locale The locale of the swagger to return.
5646    * @return The swagger as an {@link Optional}.  Never <jk>null</jk>.
5647    */
5648   public Optional<Swagger> getSwagger(Locale locale) {
5649      Swagger s = swaggerCache.get(locale);
5650      if (s == null) {
5651         try {
5652            s = swaggerProvider.getSwagger(this, locale);
5653            if (nn(s))
5654               swaggerCache.put(locale, s);
5655         } catch (Exception e) {
5656            throw new InternalServerError(e);
5657         }
5658      }
5659      return opt(s);
5660   }
5661
5662   /**
5663    * Returns the Swagger provider used by this resource.
5664    *
5665    * <h5 class='section'>See Also:</h5><ul>
5666    *    <li class='jm'>{@link RestContext.Builder#swaggerProvider(Class)}
5667    *    <li class='jm'>{@link RestContext.Builder#swaggerProvider(SwaggerProvider)}
5668    * </ul>
5669    *
5670    * @return
5671    *    The information provider for this resource.
5672    *    <br>Never <jk>null</jk>.
5673    */
5674   public SwaggerProvider getSwaggerProvider() { return swaggerProvider; }
5675
5676   /**
5677    * Returns the stack trace database associated with this context.
5678    *
5679    * @return
5680    *    The stack trace database for this resource.
5681    *    <br>Never <jk>null</jk>.
5682    */
5683   public ThrownStore getThrownStore() { return thrownStore; }
5684
5685   /**
5686    * Returns the authority path of the resource.
5687    *
5688    * <h5 class='section'>See Also:</h5><ul>
5689    *    <li class='jm'>{@link RestContext.Builder#uriAuthority(String)}
5690    * </ul>
5691    *
5692    * @return
5693    *    The authority path of this resource.
5694    *    <br>If not specified, returns the context path of the ascendant resource.
5695    */
5696   public String getUriAuthority() {
5697      if (nn(uriAuthority))
5698         return uriAuthority;
5699      if (nn(parentContext))
5700         return parentContext.getUriAuthority();
5701      return null;
5702   }
5703
5704   /**
5705    * Returns the context path of the resource.
5706    *
5707    * <h5 class='section'>See Also:</h5><ul>
5708    *    <li class='jm'>{@link RestContext.Builder#uriContext(String)}
5709    * </ul>
5710    *
5711    * @return
5712    *    The context path of this resource.
5713    *    <br>If not specified, returns the context path of the ascendant resource.
5714    */
5715   public String getUriContext() {
5716      if (nn(uriContext))
5717         return uriContext;
5718      if (nn(parentContext))
5719         return parentContext.getUriContext();
5720      return null;
5721   }
5722
5723   /**
5724    * Returns the setting on how relative URIs should be interpreted as relative to.
5725    *
5726    * <h5 class='section'>See Also:</h5><ul>
5727    *    <li class='jm'>{@link RestContext.Builder#uriRelativity(UriRelativity)}
5728    * </ul>
5729    *
5730    * @return
5731    *    The URI-resolution relativity setting value.
5732    *    <br>Never <jk>null</jk>.
5733    */
5734   public UriRelativity getUriRelativity() { return uriRelativity; }
5735
5736   /**
5737    * Returns the setting on how relative URIs should be resolved.
5738    *
5739    * <h5 class='section'>See Also:</h5><ul>
5740    *    <li class='jm'>{@link RestContext.Builder#uriResolution(UriResolution)}
5741    * </ul>
5742    *
5743    * @return
5744    *    The URI-resolution setting value.
5745    *    <br>Never <jk>null</jk>.
5746    */
5747   public UriResolution getUriResolution() { return uriResolution; }
5748
5749   /**
5750    * Returns the variable resolver for this servlet.
5751    *
5752    * <p>
5753    * Variable resolvers are used to replace variables in property values.
5754    * They can be nested arbitrarily deep.
5755    * They can also return values that themselves contain other variables.
5756    *
5757    * <h5 class='figure'>Example:</h5>
5758    * <p class='bjava'>
5759    *    <ja>@Rest</ja>(
5760    *       messages=<js>"nls/Messages"</js>,
5761    *       properties={
5762    *          <ja>@Property</ja>(name=<js>"title"</js>,value=<js>"$L{title}"</js>),  <jc>// Localized variable in Messages.properties</jc>
5763    *          <ja>@Property</ja>(name=<js>"javaVendor"</js>,value=<js>"$S{java.vendor,Oracle}"</js>),  <jc>// System property with default value</jc>
5764    *          <ja>@Property</ja>(name=<js>"foo"</js>,value=<js>"bar"</js>),
5765    *          <ja>@Property</ja>(name=<js>"bar"</js>,value=<js>"baz"</js>),
5766    *          <ja>@Property</ja>(name=<js>"v1"</js>,value=<js>"$R{foo}"</js>),  <jc>// Request variable.  value="bar"</jc>
5767    *          <ja>@Property</ja>(name=<js>"v1"</js>,value=<js>"$R{foo,bar}"</js>),  <jc>// Request variable.  value="bar"</jc>
5768    *       }
5769    *    )
5770    *    <jk>public class</jk> MyRestResource <jk>extends</jk> BasicRestServlet {
5771    * </p>
5772    *
5773    * <p>
5774    * A typical usage pattern involves using variables inside the {@link HtmlDocConfig @HtmlDocConfig} annotation:
5775    * <p class='bjava'>
5776    *    <ja>@RestGet</ja>(<js>"/{name}/*"</js>)
5777    *    <ja>@HtmlDocConfig</ja>(
5778    *       navlinks={
5779    *          <js>"up: $R{requestParentURI}"</js>,
5780    *          <js>"api: servlet:/api"</js>,
5781    *          <js>"stats: servlet:/stats"</js>,
5782    *          <js>"editLevel: servlet:/editLevel?logger=$A{attribute.name, OFF}"</js>
5783    *       }
5784    *       header={
5785    *          <js>"&lt;h1&gt;$L{MyLocalizedPageTitle}&lt;/h1&gt;"</js>
5786    *       },
5787    *       aside={
5788    *          <js>"$F{resources/AsideText.html}"</js>
5789    *       }
5790    *    )
5791    *    <jk>public</jk> LoggerEntry getLogger(RestRequest <jv>req</jv>, <ja>@Path</ja> String <jv>name</jv>) <jk>throws</jk> Exception {
5792    * </p>
5793    *
5794    * <h5 class='section'>See Also:</h5><ul>
5795    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">SVL Variables</a>
5796    * </ul>
5797    *
5798    * @return The var resolver in use by this resource.
5799    */
5800   public VarResolver getVarResolver() { return varResolver; }
5801
5802   /**
5803    * Returns whether it's safe to pass the HTTP content as a <js>"content"</js> GET parameter.
5804    *
5805    * <h5 class='section'>See Also:</h5><ul>
5806    *    <li class='jm'>{@link RestContext.Builder#disableContentParam()}
5807    * </ul>
5808    *
5809    * @return <jk>true</jk> if setting is enabled.
5810    */
5811   public boolean isAllowContentParam() { return allowContentParam; }
5812
5813   /**
5814    * Returns whether it's safe to render stack traces in HTTP responses.
5815    *
5816    * @return <jk>true</jk> if setting is enabled.
5817    */
5818   public boolean isRenderResponseStackTraces() { return renderResponseStackTraces; }
5819
5820   /**
5821    * Called during servlet initialization to invoke all {@link RestPostInit} child-last methods.
5822    *
5823    * @return This object.
5824    * @throws ServletException Error occurred.
5825    */
5826   public synchronized RestContext postInit() throws ServletException {
5827      if (initialized.get())
5828         return this;
5829      var resource = getResource();
5830      var mi = ClassInfo.of(getResource()).getPublicMethod(x -> x.hasName("setContext") && x.hasParameterTypes(RestContext.class)).orElse(null);
5831      if (nn(mi)) {
5832         try {
5833            mi.accessible().invoke(resource, this);
5834         } catch (ExecutableException e) {
5835            throw new ServletException(e.unwrap());
5836         }
5837      }
5838      for (var x : postInitMethods) {
5839         try {
5840            x.invoke(beanStore, getResource());
5841         } catch (Exception e) {
5842            throw new ServletException(unwrap(e));
5843         }
5844      }
5845      restChildren.postInit();
5846      return this;
5847   }
5848
5849   /**
5850    * Called during servlet initialization to invoke all {@link RestPostInit} child-first methods.
5851    *
5852    * @return This object.
5853    * @throws ServletException Error occurred.
5854    */
5855   public RestContext postInitChildFirst() throws ServletException {
5856      if (initialized.get())
5857         return this;
5858      restChildren.postInitChildFirst();
5859      for (var x : postInitChildFirstMethods) {
5860         try {
5861            x.invoke(beanStore, getResource());
5862         } catch (Exception e) {
5863            throw new ServletException(unwrap(e));
5864         }
5865      }
5866      initialized.set(true);
5867      return this;
5868   }
5869
5870   private boolean isDebug(RestSession call) {
5871      return debugEnablement.isDebug(this, call.getRequest());
5872   }
5873
5874   private static Set<String> newCaseInsensitiveSet(String value) {
5875      var s = new TreeSet<>(String.CASE_INSENSITIVE_ORDER) {
5876         private static final long serialVersionUID = 1L;
5877
5878         @Override
5879         public boolean contains(Object v) {
5880            return v == null ? false : super.contains(v);
5881         }
5882      };
5883      StringUtils.split(value, x -> s.add(x));
5884      return u(s);
5885   }
5886
5887   private MethodInvoker toMethodInvoker(Method m) {
5888      return new MethodInvoker(m, getMethodExecStats(m));
5889   }
5890
5891   private static Throwable unwrap(Throwable t) {
5892      if (t instanceof InvocationTargetException t2)
5893         return t2.getTargetException();
5894      return t;
5895   }
5896
5897   /**
5898    * Method that can be subclassed to allow uncaught throwables to be treated as other types of throwables.
5899    *
5900    * <p>
5901    * The default implementation looks at the throwable class name to determine whether it can be converted to another type:
5902    *
5903    * <ul>
5904    *    <li><js>"*AccessDenied*"</js> - Converted to {@link Unauthorized}.
5905    *    <li><js>"*Empty*"</js>,<js>"*NotFound*"</js> - Converted to {@link NotFound}.
5906    * </ul>
5907    *
5908    * @param t The thrown object.
5909    * @return The converted thrown object.
5910    */
5911   protected Throwable convertThrowable(Throwable t) {
5912
5913      if (t instanceof InvocationTargetException t2)
5914         t = t2.getTargetException();
5915
5916      if (t instanceof ExecutableException t3)
5917         t = t3.getTargetException();
5918
5919      if (t instanceof BasicHttpException t2)
5920         return t2;
5921
5922      var ci = ClassInfo.of(t);
5923
5924      if (ci.hasAnnotation(Response.class))
5925         return t;
5926
5927      if (ci.isChildOf(ParseException.class) || ci.is(InvalidDataConversionException.class))
5928         return new BadRequest(t);
5929
5930      String n = cn(t);
5931
5932      if (co(n, "AccessDenied") || co(n, "Unauthorized"))
5933         return new Unauthorized(t);
5934
5935      if (co(n, "Empty") || co(n, "NotFound"))
5936         return new NotFound(t);
5937
5938      return t;
5939   }
5940
5941   /**
5942    * Called at the end of a request to invoke all {@link RestEndCall} methods.
5943    *
5944    * <p>
5945    * This is the very last method called in {@link #execute(Object, HttpServletRequest, HttpServletResponse)}.
5946    *
5947    * @param session The current request.
5948    */
5949   protected void endCall(RestSession session) {
5950      for (var x : endCallMethods) {
5951         try {
5952            x.invoke(session.getBeanStore(), session.getResource());
5953         } catch (Exception e) {
5954            getLogger().log(Level.WARNING, unwrap(e), () -> f("Error occurred invoking finish-call method ''{0}''.", x.getFullName()));
5955         }
5956      }
5957   }
5958
5959   /**
5960    * Finds the {@link RestOpArg} instances to handle resolving objects on the calls to the specified Java method.
5961    *
5962    * @param m The Java method being called.
5963    * @param beanStore
5964    *    The factory used for creating beans and retrieving injected beans.
5965    *    <br>Created by {@link RestContext.Builder#beanStore()}.
5966    * @return The array of resolvers.
5967    */
5968   protected RestOpArg[] findRestOperationArgs(Method m, BeanStore beanStore) {
5969
5970      var mi = MethodInfo.of(m);
5971      var params = mi.getParameters();
5972      var ra = new RestOpArg[params.size()];
5973
5974      beanStore = BeanStore.of(beanStore, getResource());
5975
5976      for (var i = 0; i < params.size(); i++) {
5977         var pi = params.get(i);
5978         beanStore.addBean(ParameterInfo.class, pi);
5979         for (var c : restOpArgs) {
5980            try {
5981               ra[i] = beanStore.createBean(RestOpArg.class).type(c).run();
5982               if (nn(ra[i]))
5983                  break;
5984            } catch (ExecutableException e) {
5985               throw new InternalServerError(e.unwrap(), "Could not resolve parameter {0} on method {1}.", i, mi.getFullName());
5986            }
5987         }
5988         if (ra[i] == null)
5989            throw new InternalServerError("Could not resolve parameter {0} on method {1}.", i, mi.getFullName());
5990      }
5991
5992      return ra;
5993   }
5994
5995   /**
5996    * Returns the time statistics gatherer for the specified method.
5997    *
5998    * @param m The method to get statistics for.
5999    * @return The cached time-stats object.
6000    */
6001   protected MethodExecStats getMethodExecStats(Method m) {
6002      return this.methodExecStore.getStats(m);
6003   }
6004
6005   /**
6006    * Returns the list of methods to invoke after the actual REST method is called.
6007    *
6008    * @return The list of methods to invoke after the actual REST method is called.
6009    */
6010   protected MethodList getPostCallMethods() { return postCallMethods; }
6011
6012   /**
6013    * Returns the list of methods to invoke before the actual REST method is called.
6014    *
6015    * @return The list of methods to invoke before the actual REST method is called.
6016    */
6017   protected MethodList getPreCallMethods() { return preCallMethods; }
6018
6019   /**
6020    * Method for handling response errors.
6021    *
6022    * <p>
6023    * Subclasses can override this method to provide their own custom error response handling.
6024    *
6025    * @param session The rest call.
6026    * @param e The exception that occurred.
6027    * @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
6028    */
6029   protected synchronized void handleError(RestSession session, Throwable e) throws IOException {
6030
6031      session.exception(e);
6032
6033      if (session.isDebug())
6034         e.printStackTrace();
6035
6036      int code = 500;
6037
6038      var ci = ClassInfo.of(e);
6039      var r = ci.getAnnotations(StatusCode.class).findFirst().map(AnnotationInfo::inner).orElse(null);
6040      if (nn(r))
6041         if (r.value().length > 0)
6042            code = r.value()[0];
6043
6044      var e2 = (e instanceof BasicHttpException e3 ? e3 : new BasicHttpException(code, e));
6045
6046      var req = session.getRequest();
6047      var res = session.getResponse();
6048
6049      Throwable t = e2.getRootCause();
6050      if (nn(t)) {
6051         Thrown t2 = thrown(t);
6052         res.setHeader(t2.getName(), t2.getValue());
6053      }
6054
6055      try {
6056         res.setContentType("text/plain");
6057         res.setHeader("Content-Encoding", "identity");
6058         var statusCode = e2.getStatusLine().getStatusCode();
6059         res.setStatus(statusCode);
6060
6061         var w = (PrintWriter)null;
6062         try {
6063            w = res.getWriter();
6064         } catch (@SuppressWarnings("unused") IllegalStateException x) {
6065            w = new PrintWriter(new OutputStreamWriter(res.getOutputStream(), UTF8));
6066         }
6067
6068         try (PrintWriter w2 = w) {
6069            var httpMessage = RestUtils.getHttpResponseText(statusCode);
6070            if (nn(httpMessage))
6071               w2.append("HTTP ").append(String.valueOf(statusCode)).append(": ").append(httpMessage).append("\n\n");
6072            if (isRenderResponseStackTraces())
6073               e.printStackTrace(w2);
6074            else
6075               w2.append(e2.getFullStackMessage(true));
6076         }
6077
6078      } catch (Exception e1) {
6079         req.setAttribute("Exception", e1);
6080      }
6081   }
6082
6083   /**
6084    * Handle the case where a matching method was not found.
6085    *
6086    * <p>
6087    * Subclasses can override this method to provide a 2nd-chance for specifying a response.
6088    * The default implementation will simply throw an exception with an appropriate message.
6089    *
6090    * @param session The HTTP call.
6091    * @throws Exception Any exception can be thrown.
6092    */
6093   protected void handleNotFound(RestSession session) throws Exception {
6094      var pathInfo = session.getPathInfo();
6095      var methodUC = session.getMethod();
6096      var rc = session.getStatus();
6097      var onPath = pathInfo == null ? " on no pathInfo" : String.format(" on path '%s'", pathInfo);
6098      if (rc == SC_NOT_FOUND)
6099         throw new NotFound("Method ''{0}'' not found on resource with matching pattern{1}.", methodUC, onPath);
6100      else if (rc == SC_PRECONDITION_FAILED)
6101         throw new PreconditionFailed("Method ''{0}'' not found on resource{1} with matching matcher.", methodUC, onPath);
6102      else if (rc == SC_METHOD_NOT_ALLOWED)
6103         throw new MethodNotAllowed("Method ''{0}'' not found on resource{1}.", methodUC, onPath);
6104      else
6105         throw new ServletException("Invalid method response: " + rc, session.getException());
6106   }
6107
6108   /**
6109       * Called during a request to invoke all {@link RestPostCall} methods.
6110       *
6111       * @param session The current request.
6112       * @throws Throwable If thrown from call methods.
6113       */
6114   protected void postCall(RestOpSession session) throws Throwable {
6115      for (var m : session.getContext().getPostCallMethods())
6116         m.invoke(session);
6117   }
6118
6119   /**
6120    * Called during a request to invoke all {@link RestPreCall} methods.
6121    *
6122    * @param session The current request.
6123    * @throws Throwable If thrown from call methods.
6124    */
6125   protected void preCall(RestOpSession session) throws Throwable {
6126      for (var m : session.getContext().getPreCallMethods())
6127         m.invoke(session);
6128   }
6129
6130   /**
6131    * The main method for serializing POJOs passed in through the {@link RestResponse#setContent(Object)} method or
6132    * returned by the Java method.
6133    *
6134    * <p>
6135    * Subclasses may override this method if they wish to modify the way the output is rendered or support other output
6136    * formats.
6137    *
6138    * <p>
6139    * The default implementation simply iterates through the response handlers on this resource
6140    * looking for the first one whose {@link ResponseProcessor#process(RestOpSession)} method returns
6141    * <jk>true</jk>.
6142    *
6143    * @param opSession The HTTP call.
6144    * @throws IOException Thrown by underlying stream.
6145    * @throws BasicHttpException Non-200 response.
6146    * @throws NotImplemented No registered response processors could handle the call.
6147    */
6148   protected void processResponse(RestOpSession opSession) throws IOException, BasicHttpException, NotImplemented {
6149
6150      // Loop until we find the correct processor for the POJO.
6151      int loops = 5;
6152      for (var i = 0; i < responseProcessors.length; i++) {
6153         var j = responseProcessors[i].process(opSession);
6154         if (j == FINISHED)
6155            return;
6156         if (j == RESTART) {
6157            if (loops-- < 0)
6158               throw new InternalServerError("Too many processing loops.");
6159            i = -1;  // Start over.
6160         }
6161      }
6162
6163      var output = opSession.getResponse().getContent().orElse(null);
6164      throw new NotImplemented("No response processors found to process output of type ''{0}''", cn(output));
6165   }
6166
6167   @Override /* Overridden from Context */
6168   protected FluentMap<String,Object> properties() {
6169      return super.properties()
6170         .a("allowContentParam", allowContentParam)
6171         .a("allowedHeaderParams", allowedHeaderParams)
6172         .a("allowedMethodHeader", allowedMethodHeaders)
6173         .a("allowedMethodParams", allowedMethodParams)
6174         .a("beanStore", beanStore)
6175         .a("clientVersionHeader", clientVersionHeader)
6176         .a("consumes", consumes)
6177         .a("defaultRequestHeaders", defaultRequestHeaders)
6178         .a("defaultResponseHeaders", defaultResponseHeaders)
6179         .a("partParser", partParser)
6180         .a("partSerializer", partSerializer)
6181         .a("produces", produces)
6182         .a("renderResponseStackTraces", renderResponseStackTraces)
6183         .a("responseProcessors", responseProcessors)
6184         .a("restOpArgs", restOpArgs)
6185         .a("staticFiles", staticFiles)
6186         .a("swaggerProvider", swaggerProvider)
6187         .a("uriAuthority", uriAuthority)
6188         .a("uriContext", uriContext)
6189         .a("uriRelativity", uriRelativity)
6190         .a("uriResolution", uriResolution);
6191   }
6192
6193   /**
6194    * Called at the start of a request to invoke all {@link RestStartCall} methods.
6195    *
6196    * @param session The current request.
6197    * @throws BasicHttpException If thrown from call methods.
6198    */
6199   protected void startCall(RestSession session) throws BasicHttpException {
6200      for (var x : startCallMethods) {
6201         try {
6202            x.invoke(session.getBeanStore(), session.getContext().getResource());
6203         } catch (IllegalAccessException | IllegalArgumentException e) {
6204            throw new InternalServerError(e, "Error occurred invoking start-call method ''{0}''.", x.getFullName());
6205         } catch (InvocationTargetException e) {
6206            var t = e.getTargetException();
6207            if (t instanceof BasicHttpException t2)
6208               throw t2;
6209            throw new InternalServerError(t);
6210         }
6211      }
6212   }
6213}