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