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