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