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 javax.servlet.http.HttpServletResponse.*;
016import static org.apache.juneau.internal.CollectionUtils.*;
017import static org.apache.juneau.internal.ObjectUtils.*;
018import static org.apache.juneau.internal.IOUtils.*;
019import static org.apache.juneau.internal.StringUtils.*;
020import static org.apache.juneau.rest.util.RestUtils.*;
021import static org.apache.juneau.rest.Enablement.*;
022import static org.apache.juneau.rest.HttpRuntimeException.*;
023import static org.apache.juneau.BasicIllegalArgumentException.*;
024
025import java.io.*;
026import java.lang.reflect.*;
027import java.lang.reflect.Method;
028import java.nio.charset.*;
029import java.time.*;
030import java.util.*;
031import java.util.concurrent.*;
032import java.util.concurrent.atomic.*;
033import java.util.stream.*;
034
035import javax.activation.*;
036import javax.servlet.*;
037import javax.servlet.http.*;
038
039import org.apache.juneau.*;
040import org.apache.juneau.annotation.*;
041import org.apache.juneau.collections.*;
042import org.apache.juneau.config.*;
043import org.apache.juneau.cp.*;
044import org.apache.juneau.cp.Messages;
045import org.apache.juneau.encoders.*;
046import org.apache.juneau.html.*;
047import org.apache.juneau.html.annotation.*;
048import org.apache.juneau.http.*;
049import org.apache.juneau.http.annotation.*;
050import org.apache.juneau.http.annotation.Body;
051import org.apache.juneau.http.annotation.FormData;
052import org.apache.juneau.http.annotation.HasFormData;
053import org.apache.juneau.http.annotation.HasQuery;
054import org.apache.juneau.http.annotation.Header;
055import org.apache.juneau.http.annotation.Path;
056import org.apache.juneau.http.annotation.Query;
057import org.apache.juneau.http.annotation.Response;
058import org.apache.juneau.httppart.*;
059import org.apache.juneau.httppart.bean.*;
060import org.apache.juneau.json.*;
061import org.apache.juneau.jsonschema.*;
062import org.apache.juneau.msgpack.*;
063import org.apache.juneau.mstat.*;
064import org.apache.juneau.oapi.*;
065import org.apache.juneau.parser.*;
066import org.apache.juneau.plaintext.*;
067import org.apache.juneau.reflect.*;
068import org.apache.juneau.rest.annotation.*;
069import org.apache.juneau.rest.converters.*;
070import org.apache.juneau.http.exception.*;
071import org.apache.juneau.http.remote.*;
072import org.apache.juneau.rest.reshandlers.*;
073import org.apache.juneau.rest.util.*;
074import org.apache.juneau.rest.vars.*;
075import org.apache.juneau.serializer.*;
076import org.apache.juneau.soap.*;
077import org.apache.juneau.svl.*;
078import org.apache.juneau.uon.*;
079import org.apache.juneau.urlencoding.*;
080import org.apache.juneau.utils.*;
081import org.apache.juneau.xml.*;
082
083/**
084 * Contains all the configuration on a REST resource and the entry points for handling REST calls.
085 *
086 * <ul class='seealso'>
087 *    <li class='link'>{@doc RestContext}
088 * </ul>
089 */
090@ConfigurableContext(nocache=true)
091public class RestContext extends BeanContext {
092
093   /** Represents a null value for the {@link Rest#context()} annotation.*/
094   @SuppressWarnings("javadoc")
095   public static final class Null extends RestContext {
096      public Null(RestContextBuilder builder) throws Exception {
097         super(builder);
098      }
099   }
100
101   //-------------------------------------------------------------------------------------------------------------------
102   // Configurable properties
103   //-------------------------------------------------------------------------------------------------------------------
104
105   static final String PREFIX = "RestContext";
106
107   /**
108    * Configuration property:  Allow body URL parameter.
109    *
110    * <h5 class='section'>Property:</h5>
111    * <ul class='spaced-list'>
112    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_allowBodyParam REST_allowBodyParam}
113    *    <li><b>Name:</b>  <js>"RestContext.allowBodyParam.b"</js>
114    *    <li><b>Data type:</b>  <jk>boolean</jk>
115    *    <li><b>System property:</b>  <c>RestContext.allowBodyParam</c>
116    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_ALLOWBODYPARAM</c>
117    *    <li><b>Default:</b>  <jk>true</jk>
118    *    <li><b>Session property:</b>  <jk>false</jk>
119    *    <li><b>Annotations:</b>
120    *       <ul>
121    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#allowBodyParam()}
122    *       </ul>
123    *    <li><b>Methods:</b>
124    *       <ul>
125    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#allowBodyParam(boolean)}
126    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#dontAllowBodyParam()}
127    *       </ul>
128    * </ul>
129    *
130    * <h5 class='section'>Description:</h5>
131    * <p>
132    * When enabled, the HTTP body content on PUT and POST requests can be passed in as text using the <js>"body"</js>
133    * URL parameter.
134    * <br>
135    * For example:
136    * <p class='bcode w800'>
137    *  ?body=(name='John%20Smith',age=45)
138    * </p>
139    *
140    * <h5 class='section'>Example:</h5>
141    * <p class='bcode w800'>
142    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
143    *    <ja>@Rest</ja>(allowBodyParam=<js>"$C{REST/allowBodyParam,false}"</js>)
144    *    <jk>public class</jk> MyResource {
145    *
146    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
147    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
148    *
149    *          <jc>// Using method on builder.</jc>
150    *          builder.allowBodyParam(<jk>false</jk>);
151    *
152    *          <jc>// Same, but using property.</jc>
153    *          builder.set(<jsf>REST_allowBodyParam</jsf>, <jk>false</jk>);
154    *       }
155    *
156    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
157    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
158    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
159    *          builder.allowBodyParam(<jk>false</jk>);
160    *       }
161    *    }
162    * </p>
163    *
164    * <ul class='notes'>
165    *    <li>
166    *       <js>'body'</js> parameter name is case-insensitive.
167    *    <li>
168    *       Useful for debugging PUT and POST methods using only a browser.
169    * </ul>
170    */
171   public static final String REST_allowBodyParam = PREFIX + ".allowBodyParam.b";
172
173   /**
174    * Configuration property:  Allowed header URL parameters.
175    *
176    * <h5 class='section'>Property:</h5>
177    * <ul class='spaced-list'>
178    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_allowedHeaderParams REST_allowedHeaderParams}
179    *    <li><b>Name:</b>  <js>"RestContext.allowedHeaderParams.s"</js>
180    *    <li><b>Data type:</b>  <c>String</c> (comma-delimited)
181    *    <li><b>System property:</b>  <c>RestContext.allowedHeaderParams</c>
182    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_ALLOWHEADERPARAMS</c>
183    *    <li><b>Default:</b>  <js>"Accept,Content-Type"</js>
184    *    <li><b>Session property:</b>  <jk>false</jk>
185    *    <li><b>Annotations:</b>
186    *       <ul>
187    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#allowedHeaderParams()}
188    *       </ul>
189    *    <li><b>Methods:</b>
190    *       <ul>
191    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#allowedHeaderParams(String)}
192    *       </ul>
193    * </ul>
194    *
195    * <h5 class='section'>Description:</h5>
196    * <p>
197    * When specified, allows headers such as <js>"Accept"</js> and <js>"Content-Type"</js> to be passed in as URL query
198    * parameters.
199    * <br>
200    * For example:
201    * <p class='bcode w800'>
202    *  ?Accept=text/json&amp;Content-Type=text/json
203    * </p>
204    *
205    * <h5 class='section'>Example:</h5>
206    * <p class='bcode w800'>
207    *    <jc>// Option #1 - Defined via annotation.</jc>
208    *    <ja>@Rest</ja>(allowedHeaderParams=<js>"Accept,Content-Type"</js>)
209    *    <jk>public class</jk> MyResource {
210    *
211    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
212    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
213    *
214    *          <jc>// Using method on builder.</jc>
215    *          builder.allowedHeaderParams(<js>"Accept,Content-Type"</js>);
216    *
217    *          <jc>// Same, but using property.</jc>
218    *          builder.set(<jsf>REST_allowedHeaderParams</jsf>, <js>"Accept,Content-Type"</js>);
219    *       }
220    *
221    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
222    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
223    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
224    *          builder.allowedHeaderParams(<js>"Accept,Content-Type"</js>);
225    *       }
226    *    }
227    * </p>
228    *
229    * <ul class='notes'>
230    *    <li>
231    *       Useful for debugging REST interface using only a browser so that you can quickly simulate header values
232    *       in the URL bar.
233    *    <li>
234    *       Header names are case-insensitive.
235    *    <li>
236    *       Use <js>"*"</js> to allow any headers to be specified as URL parameters.
237    *    <li>
238    *       Use <js>"NONE"</js> (case insensitive) to suppress inheriting a value from a parent class.
239    * </ul>
240    */
241   public static final String REST_allowedHeaderParams = PREFIX + ".allowedHeaderParams.s";
242
243   /**
244    * Configuration property:  Allowed method headers.
245    *
246    * <h5 class='section'>Property:</h5>
247    * <ul class='spaced-list'>
248    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_allowedMethodHeaders REST_allowedMethodHeaders}
249    *    <li><b>Name:</b>  <js>"RestContext.allowedMethodHeaders.s"</js>
250    *    <li><b>Data type:</b>  <c>String</c> (comma-delimited)
251    *    <li><b>System property:</b>  <c>RestContext.allowedMethodHeaders</c>
252    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_ALLOWEDMETHODHEADERS</c>
253    *    <li><b>Default:</b>  empty string
254    *    <li><b>Session property:</b>  <jk>false</jk>
255    *    <li><b>Annotations:</b>
256    *       <ul>
257    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#allowedMethodHeaders()}
258    *       </ul>
259    *    <li><b>Methods:</b>
260    *       <ul>
261    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#allowedMethodHeaders(String)}
262    *       </ul>
263    * </ul>
264    *
265    * <h5 class='section'>Description:</h5>
266    * <p>
267    * A comma-delimited list of HTTP method names that are allowed to be passed as values in an <c>X-Method</c> HTTP header
268    * to override the real HTTP method name.
269    * <p>
270    * Allows you to override the actual HTTP method with a simulated method.
271    * <br>For example, if an HTTP Client API doesn't support <c>PATCH</c> but does support <c>POST</c> (because
272    * <c>PATCH</c> is not part of the original HTTP spec), you can add a <c>X-Method: PATCH</c> header on a normal
273    * <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.
274    *
275    * <h5 class='section'>Example:</h5>
276    * <p class='bcode w800'>
277    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
278    *    <ja>@Rest</ja>(allowedMethodHeaders=<js>"PATCH"</js>)
279    *    <jk>public class</jk> MyResource {
280    *
281    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
282    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
283    *
284    *          <jc>// Using method on builder.</jc>
285    *          builder.allowedMethodHeaders(<js>"PATCH"</js>);
286    *
287    *          <jc>// Same, but using property.</jc>
288    *          builder.set(<jsf>REST_allowedMethodHeaders</jsf>, <js>"PATCH"</js>);
289    *       }
290    *
291    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
292    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
293    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
294    *          builder.allowedMethodHeaders(<js>"PATCH"</js>);
295    *       }
296    *    }
297    * </p>
298    *
299    * <ul class='notes'>
300    *    <li>
301    *       Method names are case-insensitive.
302    *    <li>
303    *       Use <js>"*"</js> to represent all methods.
304    *    <li>
305    *       Use <js>"NONE"</js> (case insensitive) to suppress inheriting a value from a parent class.
306    * </ul>
307    */
308   public static final String REST_allowedMethodHeaders = PREFIX + ".allowedMethodHeaders.s";
309
310   /**
311    * Configuration property:  Allowed method URL parameters.
312    *
313    * <h5 class='section'>Property:</h5>
314    * <ul class='spaced-list'>
315    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_allowedMethodParams REST_allowedMethodParams}
316    *    <li><b>Name:</b>  <js>"RestContext.allowedMethodParams.s"</js>
317    *    <li><b>Data type:</b>  <c>String</c> (comma-delimited)
318    *    <li><b>System property:</b>  <c>RestContext.allowedMethodParams</c>
319    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_ALLOWEDMETHODPARAMS</c>
320    *    <li><b>Default:</b>  <js>"HEAD,OPTIONS"</js>
321    *    <li><b>Session property:</b>  <jk>false</jk>
322    *    <li><b>Annotations:</b>
323    *       <ul>
324    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#allowedMethodParams()}
325    *       </ul>
326    *    <li><b>Methods:</b>
327    *       <ul>
328    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#allowedMethodParams(String)}
329    *       </ul>
330    * </ul>
331    *
332    * <h5 class='section'>Description:</h5>
333    * <p>
334    * When specified, the HTTP method can be overridden by passing in a <js>"method"</js> (case-insensitive) URL parameter on a regular
335    * GET request.
336    * <br>
337    * For example:
338    * <p class='bcode w800'>
339    *  /myservlet/myendpoint?method=OPTIONS
340    * </p>
341    * <p>
342    *    Useful in cases where you want to simulate a non-GET request in a browser by simply adding a parameter.
343    *    <br>Also useful if you want to construct hyperlinks to non-GET REST endpoints such as links to <c>OPTIONS</c>
344    * pages.
345    *
346    * <p>
347    * Note that per the {@doc ExtRFC2616.section9 HTTP specification}, special care should
348    * be taken when allowing non-safe (<c>POST</c>, <c>PUT</c>, <c>DELETE</c>) methods to be invoked through GET requests.
349    *
350    *
351    * <h5 class='section'>Example:</h5>
352    * <p class='bcode w800'>
353    *    <jc>// Option #1 - Defined via annotation.</jc>
354    *    <ja>@Rest</ja>(allowedMethodParams=<js>"HEAD,OPTIONS,PUT"</js>)
355    *    <jk>public class</jk> MyResource {
356    *
357    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
358    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
359    *
360    *          <jc>// Using method on builder.</jc>
361    *          builder.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
362    *
363    *          <jc>// Same, but using property.</jc>
364    *          builder.set(<jsf>REST_allowedMethodParams</jsf>, <js>"HEAD,OPTIONS,PUT"</js>);
365    *       }
366    *
367    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
368    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
369    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
370    *          builder.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
371    *       }
372    *    }
373    * </p>
374    *
375    * <ul class='notes'>
376    *    <li>
377    *       Format is a comma-delimited list of HTTP method names that can be passed in as a method parameter.
378    *    <li>
379    *       <js>'method'</js> parameter name is case-insensitive.
380    *    <li>
381    *       Use <js>"*"</js> to represent all methods.
382    *    <li>
383    *       Use <js>"NONE"</js> (case insensitive) to suppress inheriting a value from a parent class.
384    * </ul>
385    */
386   public static final String REST_allowedMethodParams = PREFIX + ".allowedMethodParams.s";
387
388   /**
389    * Configuration property:  Allow header URL parameters.
390    *
391    * <div class='warn'>
392    *    <b>Deprecated</b> - Use {@link #REST_allowedHeaderParams}
393    * </div>
394    */
395   @Deprecated
396   public static final String REST_allowHeaderParams = PREFIX + ".allowHeaderParams.b";
397
398   /**
399    * Configuration property:  REST call handler.
400    *
401    * <div class='warn'>
402    *    <b>Deprecated</b> - Use {@link RestContext#REST_context} and override methods.
403    * </div>
404    */
405   @Deprecated
406   public static final String REST_callHandler = PREFIX + ".callHandler.o";
407
408   /**
409    * Configuration property:  REST call logger.
410    *
411    * <h5 class='section'>Property:</h5>
412    * <ul class='spaced-list'>
413    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_callLogger REST_callLogger}
414    *    <li><b>Name:</b>  <js>"RestContext.callLogger.o"</js>
415    *    <li><b>Data type:</b>
416    *       <ul>
417    *          <li>{@link org.apache.juneau.rest.RestCallLogger}
418    *          <li><c>Class&lt;{@link org.apache.juneau.rest.RestCallLogger}&gt;</c>
419    *       </ul>
420    *    <li><b>Default:</b>  {@link org.apache.juneau.rest.BasicRestCallLogger}
421    *    <li><b>Session property:</b>  <jk>false</jk>
422    *    <li><b>Annotations:</b>
423    *       <ul>
424    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#callLogger()}
425    *       </ul>
426    *    <li><b>Methods:</b>
427    *       <ul>
428    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#callLogger(Class)}
429    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#callLogger(RestCallLogger)}
430    *       </ul>
431    * </ul>
432    *
433    * <h5 class='section'>Description:</h5>
434    * <p>
435    * Specifies the logger to use for logging of HTTP requests and responses.
436    *
437    * <h5 class='section'>Example:</h5>
438    * <p class='bcode w800'>
439    *    <jc>// Our customized logger.</jc>
440    *    <jk>public class</jk> MyLogger <jk>extends</jk> BasicRestCallLogger {
441    *
442    *       <ja>@Override</ja>
443    *       <jk>public void</jk> log(RestCallLoggerConfig config, HttpServletRequest req, HttpServletResponse res) {
444    *          <jc>// Handle logging ourselves.</jc>
445    *       }
446    *    }
447    *
448    *    <jc>// Option #1 - Registered via annotation resolving to a config file setting with default value.</jc>
449    *    <ja>@Rest</ja>(callLogger=MyLogger.<jk>class</jk>)
450    *    <jk>public class</jk> MyResource {
451    *
452    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
453    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
454    *
455    *          <jc>// Using method on builder.</jc>
456    *          builder.callLogger(MyLogger.<jk>class</jk>);
457    *
458    *          <jc>// Same, but using property.</jc>
459    *          builder.set(<jsf>REST_callLogger</jsf>, MyLogger.<jk>class</jk>);
460    *       }
461    *
462    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
463    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
464    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
465    *          builder.callLogger(MyLogger.<jk>class</jk>);
466    *       }
467    *    }
468    * </p>
469    *
470    * <ul class='notes'>
471    *    <li>
472    *       The default call logger if not specified is {@link BasicRestCallLogger}.
473    *    <li>
474    *       The resource class itself will be used if it implements the {@link RestCallLogger} interface and not
475    *       explicitly overridden via this annotation.
476    *    <li>
477    *       The {@link RestServlet} and {@link BasicRest} classes implement the {@link RestCallLogger} interface with the same
478    *       that gets used if not overridden by this annotation.
479    *       <br>Subclasses can also alter the behavior by overriding these methods.
480    *    <li>
481    *       When defined as a class, the implementation must have one of the following constructors:
482    *       <ul>
483    *          <li><code><jk>public</jk> T(RestContext)</code>
484    *          <li><code><jk>public</jk> T()</code>
485    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
486    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
487    *       </ul>
488    *    <li>
489    *       Inner classes of the REST resource class are allowed.
490    * </ul>
491    *
492    * <ul class='seealso'>
493    *    <li class='link'>{@doc RestLoggingAndDebugging}
494    * </ul>
495    */
496   public static final String REST_callLogger = PREFIX + ".callLogger.o";
497
498   /**
499    * Configuration property:  REST call logging rules.
500    *
501    * <h5 class='section'>Property:</h5>
502    * <ul class='spaced-list'>
503    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_callLoggerConfig REST_callLoggerConfig}
504    *    <li><b>Name:</b>  <js>"RestContext.callLoggerConfig.o"</js>
505    *    <li><b>Data type:</b>  {@link org.apache.juneau.rest.RestCallLoggerConfig}
506    *    <li><b>Default:</b>  {@link org.apache.juneau.rest.RestCallLoggerConfig#DEFAULT_NOOP}
507    *    <li><b>Session property:</b>  <jk>false</jk>
508    *    <li><b>Annotations:</b>
509    *       <ul>
510    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#logging()}
511    *       </ul>
512    *    <li><b>Methods:</b>
513    *       <ul>
514    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#callLoggerConfig(RestCallLoggerConfig)}
515    *       </ul>
516    * </ul>
517    *
518    * <h5 class='section'>Description:</h5>
519    * <p>
520    * Specifies rules on how to handle logging of HTTP requests/responses.
521    *
522    * <h5 class='section'>Example:</h5>
523    * <p class='bcode w800'>
524    *    <jc>// Option #1 - Registered via annotation.</jc>
525    *    <ja>@Rest</ja>(
526    *       logging=<ja>@Logging</ja>(
527    *          level=<js>"INFO"</js>,
528    *          rules={
529    *             <ja>@LoggingRule</ja>(codes=<js>"400-499"</js>, level=<js>"WARNING"</js>, req=<js>"SHORT"</js>, res=<js>"MEDIUM"</js>),
530    *             <ja>@LoggingRule</ja>(codes=<js>">=500"</js>, level=<js>"SEVERE"</js>, req=<js>"LONG"</js>, res=<js>"LONG"</js>)
531    *          }
532    *       }
533    *    )
534    *    <jk>public class</jk> MyResource {
535    *
536    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
537    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
538    *
539    *          <jc>// Using method on builder.</jc>
540    *          builder.callLoggerConfig(
541    *             RestCallLoggerConfig
542    *                .<jsm>create</jsm>()
543    *                .level(Level.<jsf>INFO</jsf>)
544    *                .rules(
545    *                   RestCallLoggingRule
546    *                      .<jsm>create</jsm>()
547    *                      .codes(<js>"400-499"</js>)
548    *                      .level(<jsf>WARNING</jsf>)
549    *                      .req(<jsf>SHORT</jsf>)
550    *                      .res(<jsf>MEDIUM</jsf>)
551    *                      .build(),
552    *                   RestCallLoggingRule
553    *                      .<jsm>create</jsm>()
554    *                      .codes(<js>">=500"</js>)
555    *                      .level(<jsf>SEVERE</jsf>)
556    *                      .req(<jsf>LONG</jsf>)
557    *                      .res(<jsf>LONG</jsf>)
558    *                      .build()
559    *                )
560    *                .build()
561    *          );
562    *
563    *          <jc>// Same, but using property with JSON value.</jc>
564    *          builder.set(<jsf>REST_callLoggerConfig</jsf>, <js>"{level:'INFO',rules:[{codes:'400-499',level:'WARNING',...},...]}"</js>);
565    *       }
566    *    }
567    * </p>
568    *
569    * <ul class='seealso'>
570    *    <li class='link'>{@doc RestLoggingAndDebugging}
571    * </ul>
572    */
573   public static final String REST_callLoggerConfig = PREFIX + ".callLoggerConfig.o";
574
575   /**
576    * Configuration property:  Children.
577    *
578    * <h5 class='section'>Property:</h5>
579    * <ul class='spaced-list'>
580    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_children REST_children}
581    *    <li><b>Name:</b>  <js>"RestContext.children.lo"</js>
582    *    <li><b>Data type:</b>  <c>List&lt;Class|Object|{@link org.apache.juneau.rest.RestChild}&gt;</c>
583    *    <li><b>Default:</b>  empty list
584    *    <li><b>Session property:</b>  <jk>false</jk>
585    *    <li><b>Annotations:</b>
586    *       <ul>
587    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#children()}
588    *       </ul>
589    *    <li><b>Methods:</b>
590    *       <ul>
591    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#child(String,Object)}
592    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#children(Class...)}
593    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#children(Object...)}
594    *       </ul>
595    * </ul>
596    *
597    * <h5 class='section'>Description:</h5>
598    * <p>
599    * Defines children of this resource.
600    *
601    * <p>
602    * A REST child resource is simply another servlet or object that is initialized as part of the ascendant resource and has a
603    * servlet path directly under the ascendant resource object path.
604    * <br>The main advantage to defining servlets as REST children is that you do not need to define them in the
605    * <c>web.xml</c> file of the web application.
606    * <br>This can cut down on the number of entries that show up in the <c>web.xml</c> file if you are defining
607    * large numbers of servlets.
608    *
609    * <p>
610    * Child resources must specify a value for {@link Rest#path() @Rest(path)} that identifies the subpath of the child resource
611    * relative to the ascendant path UNLESS you use the {@link RestContextBuilder#child(String, Object)} method to register it.
612    *
613    * <p>
614    * Child resources can be nested arbitrarily deep using this technique (i.e. children can also have children).
615    *
616    * <dl>
617    *    <dt>Servlet initialization:</dt>
618    *    <dd>
619    *       <p>
620    *          A child resource will be initialized immediately after the ascendant servlet/resource is initialized.
621    *          <br>The child resource receives the same servlet config as the ascendant servlet/resource.
622    *          <br>This allows configuration information such as servlet initialization parameters to filter to child
623    *          resources.
624    *       </p>
625    *    </dd>
626    *    <dt>Runtime behavior:</dt>
627    *    <dd>
628    *       <p>
629    *          As a rule, methods defined on the <c>HttpServletRequest</c> object will behave as if the child
630    *          servlet were deployed as a top-level resource under the child's servlet path.
631    *          <br>For example, the <c>getServletPath()</c> and <c>getPathInfo()</c> methods on the
632    *          <c>HttpServletRequest</c> object will behave as if the child resource were deployed using the
633    *          child's servlet path.
634    *          <br>Therefore, the runtime behavior should be equivalent to deploying the child servlet in the
635    *          <c>web.xml</c> file of the web application.
636    *       </p>
637    *    </dd>
638    * </dl>
639    *
640    * <h5 class='section'>Example:</h5>
641    * <p class='bcode w800'>
642    *    <jc>// Our child resource.</jc>
643    *    <ja>@Rest</ja>(path=<js>"/child"</js>)
644    *    <jk>public class</jk> MyChildResource {...}
645    *
646    *    <jc>// Option #1 - Registered via annotation.</jc>
647    *    <ja>@Rest</ja>(children={MyChildResource.<jk>class</jk>})
648    *    <jk>public class</jk> MyResource {
649    *
650    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
651    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
652    *
653    *          <jc>// Using method on builder.</jc>
654    *          builder.children(MyChildResource.<jk>class</jk>);
655    *
656    *          <jc>// Same, but using property.</jc>
657    *          builder.addTo(<jsf>REST_children</jsf>, MyChildResource.<jk>class</jk>));
658    *
659    *          <jc>// Use a pre-instantiated object instead.</jc>
660    *          builder.child(<js>"/child"</js>, <jk>new</jk> MyChildResource());
661    *       }
662    *
663    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
664    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
665    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
666    *          builder.children(MyChildResource.<jk>class</jk>);
667    *       }
668    *    }
669    * </p>
670    *
671    * <ul class='notes'>
672    *    <li>
673    *       When defined as classes, instances are resolved using the registered {@link #REST_resourceResolver} which
674    *       by default is {@link BasicRestResourceResolver} which requires the class have one of the following
675    *       constructors:
676    *       <ul>
677    *          <li><code><jk>public</jk> T(RestContextBuilder)</code>
678    *          <li><code><jk>public</jk> T()</code>
679    *       </ul>
680    * </ul>
681    *
682    * <ul class='seealso'>
683    *    <li class='link'>{@doc RestChildren}
684    * </ul>
685    */
686   public static final String REST_children = PREFIX + ".children.lo";
687
688   /**
689    * Configuration property:  Classpath resource finder.
690    *
691    * <h5 class='section'>Property:</h5>
692    * <ul class='spaced-list'>
693    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_classpathResourceFinder REST_classpathResourceFinder}
694    *    <li><b>Name:</b>  <js>"RestContext.classpathResourceFinder.o"</js>
695    *    <li><b>Data type:</b>  {@link org.apache.juneau.cp.ResourceFinder}
696    *    <li><b>Default:</b>  {@link org.apache.juneau.cp.BasicResourceFinder}
697    *    <li><b>Session property:</b>  <jk>false</jk>
698    *    <li><b>Annotations:</b>
699    *       <ul>
700    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#classpathResourceFinder()}
701    *       </ul>
702    *    <li><b>Methods:</b>
703    *       <ul>
704    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#classpathResourceFinder(Class)}
705    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#classpathResourceFinder(ResourceFinder)}
706    *       </ul>
707    * </ul>
708    *
709    * <h5 class='section'>Description:</h5>
710    * <p>
711    * Used to retrieve localized files from the classpath.
712    *
713    * <p>
714    * Used by the following methods:
715    * <ul class='javatree'>
716    *    <li class='jc'>{@link RestContext}
717    *    <ul>
718    *       <li class='jm'>{@link #getClasspathResource(String,Locale) getClasspathResource(String,Locale)}
719    *       <li class='jm'>{@link #getClasspathResource(Class,MediaType,String,Locale) getClasspathResource(Class,MediaType,String,Locale)}
720    *       <li class='jm'>{@link #getClasspathResourceAsString(String,Locale) getClasspathResourceAsString(String,Locale)}
721    *       <li class='jm'>{@link #getStaticFile(String) resolveStaticFile(String)}
722    *    </ul>
723    *    <li class='jc'>{@link RestRequest}
724    *    <ul>
725    *       <li class='jm'>{@link RestRequest#getClasspathHttpResource(String) getClasspathHttpResource(String)}
726    *       <li class='jm'>{@link RestRequest#getClasspathHttpResource(String,boolean) getClasspathHttpResource(String,boolean)}
727    *       <li class='jm'>{@link RestRequest#getClasspathHttpResource(String,boolean,MediaType,boolean) getClasspathHttpResource(String,boolean,MediaType,boolean)}
728    *    </ul>
729    * </ul>
730    *
731    * <p>
732    * It also affects the behavior of the {@link #REST_staticFiles} property.
733    *
734    * <h5 class='section'>Example:</h5>
735    * <p class='bcode w800'>
736    *    <jc>// Our customized classpath resource finder.</jc>
737    *    <jk>public class</jk> MyClasspathResourceFinder <jk>extends</jk> ClasspathResourceFinderBasic {
738    *       <ja>@Override</ja>
739    *       <jk>public</jk> InputStream findResource(Class&lt;?&gt; baseClass, String name, Locale locale) <jk>throws</jk> IOException {
740    *          <jc>// Do your own resolution.</jc>
741    *       }
742    *    }
743    *
744    *    <jc>// Option #1 - Registered via annotation.</jc>
745    *    <ja>@Rest</ja>(classpathResourceFinder=MyClasspathResourceFinder.<jk>class</jk>)
746    *    <jk>public class</jk> MyResource {
747    *
748    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
749    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
750    *
751    *          <jc>// Using method on builder.</jc>
752    *          builder.classpathResourceFinder(MyClasspathResourceFinder.<jk>class</jk>);
753    *
754    *          <jc>// Same, but using property.</jc>
755    *          builder.set(<jsf>REST_classpathResourceFinder</jsf>, MyClasspathResourceFinder.<jk>class</jk>));
756    *
757    *          <jc>// Use a pre-instantiated object instead.</jc>
758    *          builder.classpathResourceFinder(<jk>new</jk> MyClasspathResourceFinder());
759    *       }
760    *
761    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
762    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
763    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
764    *          builder.classpathResourceFinder(MyClasspathResourceFinder.<jk>class</jk>);
765    *       }
766    *    }
767    * </p>
768    *
769    * <ul class='notes'>
770    *    <li>
771    *       The default value is {@link BasicResourceFinder} which provides basic support for finding localized
772    *       resources on the classpath and JVM working directory.
773    *       <br>The {@link RecursiveResourceFinder} is another option that also recursively searches for resources
774    *       up the class-hierarchy.
775    *       <br>Each of these classes can be extended to provide customized handling of resource retrieval.
776    *    <li>
777    *       The resource class itself will be used if it implements the {@link ResourceFinder} interface and not
778    *       explicitly overridden via this annotation.
779    *    <li>
780    *       The {@link RestServlet} and {@link BasicRest} classes implement the {@link ResourceFinder} interface with the same
781    *       functionality as {@link BasicResourceFinder} that gets used if not overridden by this annotation.
782    *       <br>Subclasses can also alter the behavior by overriding these methods.
783    *    <li>
784    *       When defined as a class, the implementation must have one of the following constructors:
785    *       <ul>
786    *          <li><code><jk>public</jk> T(RestContext)</code>
787    *          <li><code><jk>public</jk> T()</code>
788    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
789    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
790    *       </ul>
791    *    <li>
792    *       Inner classes of the REST resource class are allowed.
793    * </ul>
794    */
795   public static final String REST_classpathResourceFinder = PREFIX + ".classpathResourceFinder.o";
796
797   /**
798    * Configuration property:  Client version header.
799    *
800    * <h5 class='section'>Property:</h5>
801    * <ul class='spaced-list'>
802    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_clientVersionHeader REST_clientVersionHeader}
803    *    <li><b>Name:</b>  <js>"RestContext.clientVersionHeader.s"</js>
804    *    <li><b>Data type:</b>  <c>String</c>
805    *    <li><b>System property:</b>  <c>RestContext.clientVersionHeader</c>
806    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_CLIENTVERSIONHEADER</c>
807    *    <li><b>Default:</b>  <js>"X-Client-Version"</js>
808    *    <li><b>Session property:</b>  <jk>false</jk>
809    *    <li><b>Annotations:</b>
810    *       <ul>
811    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#clientVersionHeader()}
812    *       </ul>
813    *    <li><b>Methods:</b>
814    *       <ul>
815    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#clientVersionHeader(String)}
816    *       </ul>
817    * </ul>
818    *
819    * <h5 class='section'>Description:</h5>
820    * <p>
821    * Specifies the name of the header used to denote the client version on HTTP requests.
822    *
823    * <p>
824    * The client version is used to support backwards compatibility for breaking REST interface changes.
825    * <br>Used in conjunction with {@link RestMethod#clientVersion() @RestMethod(clientVersion)} annotation.
826    *
827    * <h5 class='section'>Example:</h5>
828    * <p class='bcode w800'>
829    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
830    *    <ja>@Rest</ja>(clientVersionHeader=<js>"$C{REST/clientVersionHeader,Client-Version}"</js>)
831    *    <jk>public class</jk> MyResource {
832    *
833    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
834    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
835    *
836    *          <jc>// Using method on builder.</jc>
837    *          builder.clientVersionHeader(<js>"Client-Version"</js>);
838    *
839    *          <jc>// Same, but using property.</jc>
840    *          builder.set(<jsf>REST_clientVersionHeader</jsf>, <js>"Client-Version"</js>);
841    *       }
842    *
843    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
844    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
845    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
846    *          builder.clientVersionHeader(<js>"Client-Version"</js>);
847    *       }
848    *    }
849    * </p>
850    * <p class='bcode w800'>
851    *    <jc>// Call this method if Client-Version is at least 2.0.
852    *    // Note that this also matches 2.0.1.</jc>
853    *    <ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"2.0"</js>)
854    *    <jk>public</jk> Object method1() {
855    *       ...
856    *    }
857    *
858    *    <jc>// Call this method if Client-Version is at least 1.1, but less than 2.0.</jc>
859    *    <ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"[1.1,2.0)"</js>)
860    *    <jk>public</jk> Object method2() {
861    *       ...
862    *    }
863    *
864    *    <jc>// Call this method if Client-Version is less than 1.1.</jc>
865    *    <ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"[0,1.1)"</js>)
866    *    <jk>public</jk> Object method3() {
867    *       ...
868    *    }
869    * </p>
870    */
871   public static final String REST_clientVersionHeader = PREFIX + ".clientVersionHeader.s";
872
873   /**
874    * Configuration property:  Class-level response converters.
875    *
876    * <h5 class='section'>Property:</h5>
877    * <ul class='spaced-list'>
878    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_converters REST_converters}
879    *    <li><b>Name:</b>  <js>"RestContext.converters.lo"</js>
880    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.rest.RestConverter}|Class&lt;{@link org.apache.juneau.rest.RestConverter}&gt;&gt;</c>
881    *    <li><b>Default:</b>  empty list
882    *    <li><b>Session property:</b>  <jk>false</jk>
883    *    <li><b>Annotations:</b>
884    *       <ul>
885    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#converters()}
886    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#converters()}
887    *       </ul>
888    *    <li><b>Methods:</b>
889    *       <ul>
890    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#converters(Class...)}
891    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#converters(RestConverter...)}
892    *       </ul>
893    * </ul>
894    *
895    * <h5 class='section'>Description:</h5>
896    * <p>
897    * Associates one or more {@link RestConverter converters} with a resource class.
898    * <br>These converters get called immediately after execution of the REST method in the same order specified in the
899    * annotation.
900    * <br>The object passed into this converter is the object returned from the Java method or passed into
901    * the {@link RestResponse#setOutput(Object)} method.
902    *
903    * <p>
904    * Can be used for performing post-processing on the response object before serialization.
905    *
906    * <p>
907    *    When multiple converters are specified, they're executed in the order they're specified in the annotation
908    *    (e.g. first the results will be traversed, then the resulting node will be searched/sorted).
909    *
910    * <h5 class='section'>Example:</h5>
911    * <p class='bcode w800'>
912    *    <jc>// Our converter.</jc>
913    *    <jk>public class</jk> MyConverter <jk>implements</jk> RestConverter {
914    *       <ja>@Override</ja>
915    *       <jk>public</jk> Object convert(RestRequest req, Object o) {
916    *          <jc>// Do something with object and return another object.</jc>
917    *          <jc>// Or just return the same object for a no-op.</jc>
918    *       }
919    *    }
920    *
921    *    <jc>// Option #1 - Registered via annotation resolving to a config file setting with default value.</jc>
922    *    <ja>@Rest</ja>(converters={MyConverter.<jk>class</jk>})
923    *    <jk>public class</jk> MyResource {
924    *
925    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
926    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
927    *
928    *          <jc>// Using method on builder.</jc>
929    *          builder.converters(MyConverter.<jk>class</jk>);
930    *
931    *          <jc>// Same, but using property.</jc>
932    *          builder.set(<jsf>REST_converters</jsf>, MyConverter.<jk>class</jk>);
933    *
934    *          <jc>// Pass in an instance instead.</jc>
935    *          builder.converters(<jk>new</jk> MyConverter());
936    *       }
937    *
938    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
939    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
940    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
941    *          builder.converters(MyConverter.<jk>class</jk>);
942    *       }
943    *    }
944    * </p>
945    *
946    * <ul class='seealso'>
947    *    <li class='jc'>{@link Traversable} - Allows URL additional path info to address individual elements in a POJO tree.
948    *    <li class='jc'>{@link Queryable} - Allows query/view/sort functions to be performed on POJOs.
949    *    <li class='jc'>{@link Introspectable} - Allows Java public methods to be invoked on the returned POJOs.
950    *    <li class='link'>{@doc RestConverters}
951    * </ul>
952    *
953    * <ul class='notes'>
954    *    <li>
955    *       When defined as a class, the implementation must have one of the following constructors:
956    *       <ul>
957    *          <li><code><jk>public</jk> T(BeanContext)</code>
958    *          <li><code><jk>public</jk> T()</code>
959    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
960    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
961    *       </ul>
962    *    <li>
963    *       Inner classes of the REST resource class are allowed.
964    * </ul>
965    */
966   public static final String REST_converters = PREFIX + ".converters.lo";
967
968   /**
969    * Configuration property:  Debug mode.
970    *
971    * <h5 class='section'>Property:</h5>
972    * <ul class='spaced-list'>
973    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_debug REST_debug}
974    *    <li><b>Name:</b>  <js>"RestContext.debug.s"</js>
975    *    <li><b>Data type:</b>  {@link org.apache.juneau.rest.Enablement}
976    *    <li><b>System property:</b>  <c>RestContext.debug</c>
977    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_DEBUG</c>
978    *    <li><b>Default:</b>  {@link org.apache.juneau.rest.Enablement#FALSE}
979    *    <li><b>Session property:</b>  <jk>false</jk>
980    *    <li><b>Annotations:</b>
981    *       <ul>
982    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#debug()}
983    *       </ul>
984    *    <li><b>Methods:</b>
985    *       <ul>
986    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#debug()}
987    *       </ul>
988    * </ul>
989    *
990    * <h5 class='section'>Description:</h5>
991    * <p>
992    * Enables the following:
993    * <ul class='spaced-list'>
994    *    <li>
995    *       HTTP request/response bodies are cached in memory for logging purposes.
996    *    <li>
997    *       Request/response messages are automatically logged always or per request.
998    * </ul>
999    */
1000   public static final String REST_debug = PREFIX + ".debug.s";
1001
1002   /**
1003    * Configuration property:  Debug mode on specified classes/methods.
1004    *
1005    * <h5 class='section'>Property:</h5>
1006    * <ul class='spaced-list'>
1007    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_debugOn REST_debugOn}
1008    *    <li><b>Name:</b>  <js>"RestContext.debugOn.s"</js>
1009    *    <li><b>Data type:</b>  <c>String</c> (comma-delimited)
1010    *    <li><b>System property:</b>  <c>RestContext.debugOn</c>
1011    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_DEBUGON</c>
1012    *    <li><b>Default:</b>  Empty string
1013    *    <li><b>Session property:</b>  <jk>false</jk>
1014    *    <li><b>Annotations:</b>
1015    *       <ul>
1016    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#debugOn()}
1017    *       </ul>
1018    *    <li><b>Methods:</b>
1019    *       <ul>
1020    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#debugOn(String)}
1021    *       </ul>
1022    * </ul>
1023    *
1024    * <h5 class='section'>Description:</h5>
1025    * <p>
1026    * Enables the following:
1027    * <ul class='spaced-list'>
1028    *    <li>
1029    *       HTTP request/response bodies are cached in memory for logging purposes.
1030    *    <li>
1031    *       Request/response messages are automatically logged always or per request.
1032    * </ul>
1033    */
1034   public static final String REST_debugOn = PREFIX + ".debugOn.s";
1035
1036   /**
1037    * Configuration property:  Default character encoding.
1038    *
1039    * <h5 class='section'>Property:</h5>
1040    * <ul class='spaced-list'>
1041    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_defaultCharset REST_defaultCharset}
1042    *    <li><b>Name:</b>  <js>"RestContext.defaultCharset.s"</js>
1043    *    <li><b>Data type:</b>  <c>String</c>
1044    *    <li><b>System property:</b>  <c>RestContext.defaultCharset</c>
1045    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_DEFAULTCHARSET</c>
1046    *    <li><b>Default:</b>  <js>"utf-8"</js>
1047    *    <li><b>Session property:</b>  <jk>false</jk>
1048    *    <li><b>Annotations:</b>
1049    *       <ul>
1050    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#defaultCharset()}
1051    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#defaultCharset()}
1052    *       </ul>
1053    *    <li><b>Methods:</b>
1054    *       <ul>
1055    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#defaultCharset(String)}
1056    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#defaultCharset(Charset)}
1057    *       </ul>
1058    * </ul>
1059    *
1060    * <h5 class='section'>Description:</h5>
1061    * <p>
1062    * The default character encoding for the request and response if not specified on the request.
1063    *
1064    * <h5 class='section'>Example:</h5>
1065    * <p class='bcode w800'>
1066    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1067    *    <ja>@Rest</ja>(defaultCharset=<js>"$C{REST/defaultCharset,US-ASCII}"</js>)
1068    *    <jk>public class</jk> MyResource {
1069    *
1070    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1071    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1072    *
1073    *          <jc>// Using method on builder.</jc>
1074    *          builder.defaultCharset(<js>"US-ASCII"</js>);
1075    *
1076    *          <jc>// Same, but using property.</jc>
1077    *          builder.set(<jsf>REST_defaultCharset</jsf>, <js>"US-ASCII"</js>);
1078    *       }
1079    *
1080    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1081    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1082    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1083    *          builder.defaultCharset(<js>"US-ASCII"</js>);
1084    *       }
1085    *
1086    *       <jc>// Override at the method level.</jc>
1087    *       <ja>@RestMethod</ja>(defaultCharset=<js>"UTF-16"</js>)
1088    *       public Object myMethod() {...}
1089    *    }
1090    * </p>
1091    */
1092   public static final String REST_defaultCharset = PREFIX + ".defaultCharset.s";
1093
1094   /**
1095    * Configuration property:  Default request attributes.
1096    *
1097    * <div class='warn'>
1098    *    <b>Deprecated</b> - Use {@link #REST_reqAttrs}
1099    * </div>
1100    */
1101   @Deprecated
1102   public static final String REST_attrs = PREFIX + ".reqAttrs.smo";
1103
1104   /**
1105    * Configuration property:  Default request headers.
1106    *
1107    * <div class='warn'>
1108    *    <b>Deprecated</b> - Use {@link #REST_reqHeaders}
1109    * </div>
1110    */
1111   @Deprecated
1112   public static final String REST_defaultRequestHeaders = PREFIX + ".reqHeaders.smo";
1113
1114   /**
1115    * Configuration property:  Default response headers.
1116    *
1117    * <div class='warn'>
1118    *    <b>Deprecated</b> - Use {@link #REST_resHeaders}
1119    * </div>
1120    */
1121   @Deprecated
1122   public static final String REST_defaultResponseHeaders = PREFIX + ".resHeaders.omo";
1123
1124   /**
1125    * Configuration property:  Compression encoders.
1126    *
1127    * <h5 class='section'>Property:</h5>
1128    * <ul class='spaced-list'>
1129    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_encoders REST_encoders}
1130    *    <li><b>Name:</b>  <js>"RestContext.encoders.o"</js>
1131    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.encoders.Encoder}|Class&lt;{@link org.apache.juneau.encoders.Encoder}&gt;&gt;</c>
1132    *    <li><b>Default:</b>  empty list
1133    *    <li><b>Session property:</b>  <jk>false</jk>
1134    *    <li><b>Annotations:</b>
1135    *       <ul>
1136    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#encoders()}
1137    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#encoders()}
1138    *       </ul>
1139    *    <li><b>Methods:</b>
1140    *       <ul>
1141    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#encoders(Class...)}
1142    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#encoders(Encoder...)}
1143    *       </ul>
1144    * </ul>
1145    *
1146    * <h5 class='section'>Description:</h5>
1147    * <p>
1148    * These can be used to enable various kinds of compression (e.g. <js>"gzip"</js>) on requests and responses.
1149    *
1150    * <h5 class='section'>Example:</h5>
1151    * <p class='bcode w800'>
1152    *    <jc>// Option #1 - Registered via annotation.</jc>
1153    *    <ja>@Rest</ja>(encoders={GzipEncoder.<jk>class</jk>})
1154    *    <jk>public class</jk> MyResource {
1155    *
1156    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
1157    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1158    *
1159    *          <jc>// Using method on builder.</jc>
1160    *          builder.encoders(GzipEncoder.<jk>class</jk>);
1161    *
1162    *          <jc>// Same, but using property.</jc>
1163    *          builder.addTo(<jsf>REST_encoders</jsf>, GzipEncoder.<jk>class</jk>);
1164    *       }
1165    *
1166    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
1167    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1168    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1169    *          builder.encoders(GzipEncoder.<jk>class</jk>);
1170    *       }
1171    *
1172    *       <jc>// Override at the method level.</jc>
1173    *       <ja>@RestMethod</ja>(encoders={MySpecialEncoder.<jk>class</jk>}, inherit={<js>"ENCODERS"</js>})
1174    *       public Object myMethod() {...}
1175    *    }
1176    * </p>
1177    *
1178    * <ul class='notes'>
1179    *    <li>
1180    *       When defined as a class, the implementation must have one of the following constructors:
1181    *       <ul>
1182    *          <li><code><jk>public</jk> T(BeanContext)</code>
1183    *          <li><code><jk>public</jk> T()</code>
1184    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
1185    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
1186    *       </ul>
1187    *    <li>
1188    *       Inner classes of the REST resource class are allowed.
1189    * </ul>
1190    *
1191    * <ul class='seealso'>
1192    *    <li class='link'>{@doc RestEncoders}
1193    * </ul>
1194    */
1195   public static final String REST_encoders = PREFIX + ".encoders.lo";
1196
1197   /**
1198    * Configuration property:  Class-level guards.
1199    *
1200    * <h5 class='section'>Property:</h5>
1201    * <ul class='spaced-list'>
1202    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_guards REST_guards}
1203    *    <li><b>Name:</b>  <js>"RestContext.guards.lo"</js>
1204    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.rest.RestGuard}|Class&lt;{@link org.apache.juneau.rest.RestGuard}&gt;&gt;</c>
1205    *    <li><b>Default:</b>  empty list
1206    *    <li><b>Session property:</b>  <jk>false</jk>
1207    *    <li><b>Annotations:</b>
1208    *       <ul>
1209    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#guards()}
1210    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#guards()}
1211    *       </ul>
1212    *    <li><b>Methods:</b>
1213    *       <ul>
1214    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#guards(Class...)}
1215    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#guards(RestGuard...)}
1216    *       </ul>
1217    * </ul>
1218    *
1219    * <h5 class='section'>Description:</h5>
1220    * <p>
1221    * Associates one or more {@link RestGuard RestGuards} with all REST methods defined in this class.
1222    * <br>These guards get called immediately before execution of any REST method in this class.
1223    *
1224    * <p>
1225    * If multiple guards are specified, <b>ALL</b> guards must pass.
1226    * <br>Note that this is different than matchers where only ONE matcher needs to pass.
1227    *
1228    * <h5 class='section'>Example:</h5>
1229    * <p class='bcode w800'>
1230    *    <jc>// Define a guard that only lets Billy make a request.</jc>
1231    *    <jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
1232    *       <ja>@Override</ja>
1233    *       <jk>public boolean</jk> isRequestAllowed(RestRequest req) {
1234    *          <jk>return</jk> req.getUserPrincipal().getName().equals(<js>"Billy"</js>);
1235    *       }
1236    *    }
1237    *
1238    *    <jc>// Option #1 - Registered via annotation.</jc>
1239    *    <ja>@Rest</ja>(guards={BillyGuard.<jk>class</jk>})
1240    *    <jk>public class</jk> MyResource {
1241    *
1242    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
1243    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1244    *
1245    *          <jc>// Using method on builder.</jc>
1246    *          builder.guards(BillyGuard.<jk>class</jk>);
1247    *
1248    *          <jc>// Same, but using property.</jc>
1249    *          builder.addTo(<jsf>REST_guards</jsf>, BillyGuard.<jk>class</jk>);
1250    *       }
1251    *
1252    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
1253    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1254    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1255    *          builder.guards(BillyGuard.<jk>class</jk>);
1256    *       }
1257    *
1258    *       <jc>// Override at the method level.</jc>
1259    *       <ja>@RestMethod</ja>(guards={SomeOtherGuard.<jk>class</jk>})
1260    *       public Object myMethod() {...}
1261    *    }
1262    * </p>
1263    *
1264    * <ul class='notes'>
1265    *    <li>
1266    *       When defined as a class, the implementation must have one of the following constructors:
1267    *       <ul>
1268    *          <li><code><jk>public</jk> T(RestContext)</code>
1269    *          <li><code><jk>public</jk> T()</code>
1270    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
1271    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
1272    *       </ul>
1273    *    <li>
1274    *       Inner classes of the REST resource class are allowed.
1275    * </ul>
1276    *
1277    * <ul class='seealso'>
1278    *    <li class='link'>{@doc RestGuards}
1279    * </ul>
1280    */
1281   public static final String REST_guards = PREFIX + ".guards.lo";
1282
1283   /**
1284    * Configuration property:  REST info provider.
1285    *
1286    * <h5 class='section'>Property:</h5>
1287    * <ul class='spaced-list'>
1288    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_infoProvider REST_infoProvider}
1289    *    <li><b>Name:</b>  <js>"RestContext.infoProvider.o"</js>
1290    *    <li><b>Data type:</b>
1291    *       <ul>
1292    *          <li>{@link org.apache.juneau.rest.RestInfoProvider}
1293    *          <li><c>Class&lt;{@link org.apache.juneau.rest.RestInfoProvider}&gt;</c>
1294    *       </ul>
1295    *    <li><b>Default:</b>  {@link org.apache.juneau.rest.BasicRestInfoProvider}
1296    *    <li><b>Session property:</b>  <jk>false</jk>
1297    *    <li><b>Annotations:</b>
1298    *       <ul>
1299    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#infoProvider()}
1300    *       </ul>
1301    *    <li><b>Methods:</b>
1302    *       <ul>
1303    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#infoProvider(Class)}
1304    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#infoProvider(RestInfoProvider)}
1305    *       </ul>
1306    * </ul>
1307    *
1308    * <h5 class='section'>Description:</h5>
1309    * <p>
1310    * Class used to retrieve title/description/swagger information about a resource.
1311    *
1312    * <h5 class='section'>Example:</h5>
1313    * <p class='bcode w800'>
1314    *    <jc>// Our customized info provider.</jc>
1315    *    <jc>// Extend from the default implementation and selectively override values.</jc>
1316    *    <jk>public class</jk> MyRestInfoProvider <jk>extends</jk> BasicRestInfoProvider {
1317    *
1318    *       <jc>// Must provide this constructor!</jc>
1319    *       <jk>public</jk> MyRestInfoProvider(RestContext context) {
1320    *          <jk>super</jk>(context);
1321    *       }
1322    *
1323    *       <ja>@Override</ja>
1324    *       <jk>public</jk> Swagger getSwaggerFromFile(RestRequest req) <jk>throws</jk> RestException {
1325    *          <jc>// Provide our own method of retrieving swagger from file system.</jc>
1326    *       }
1327    *
1328    *       <ja>@Override</ja>
1329    *       <jk>public</jk> Swagger getSwagger(RestRequest req) <jk>throws</jk> RestException {
1330    *          Swagger s = <jk>super</jk>.getSwagger(req);
1331    *          <jc>// Made inline modifications to generated swagger.</jc>
1332    *          <jk>return</jk> s;
1333    *       }
1334    *
1335    *       <ja>@Override</ja>
1336    *       <jk>public</jk> String getSiteName(RestRequest req) {
1337    *          <jc>// Override the site name.</jc>
1338    *       }
1339    *    }
1340    *
1341    *    <jc>// Option #1 - Registered via annotation resolving to a config file setting with default value.</jc>
1342    *    <ja>@Rest</ja>(infoProvider=MyRestInfoProvider.<jk>class</jk>)
1343    *    <jk>public class</jk> MyResource {
1344    *
1345    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
1346    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1347    *
1348    *          <jc>// Using method on builder.</jc>
1349    *          builder.infoProvider(MyRestInfoProvider.<jk>class</jk>);
1350    *
1351    *          <jc>// Same, but using property.</jc>
1352    *          builder.set(<jsf>REST_infoProvider</jsf>, MyRestInfoProvider.<jk>class</jk>);
1353    *       }
1354    *
1355    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
1356    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1357    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1358    *          builder.infoProvider(MyRestInfoProvider.<jk>class</jk>);
1359    *       }
1360    *    }
1361    * </p>
1362    *
1363    * <ul class='notes'>
1364    *    <li>
1365    *       The default info provider if not specified is {@link BasicRestInfoProvider}.
1366    *    <li>
1367    *       The resource class itself will be used if it implements the {@link RestInfoProvider} interface and not
1368    *       explicitly overridden via this annotation.
1369    *    <li>
1370    *       The{@link RestServlet} and {@link BasicRest} classes implement the {@link RestInfoProvider} interface with the same
1371    *       functionality as {@link BasicRestInfoProvider} that gets used if not overridden by this annotation.
1372    *       <br>Subclasses can also alter the behavior by overriding these methods.
1373    *    <li>
1374    *       When defined as a class, the implementation must have one of the following constructors:
1375    *       <ul>
1376    *          <li><code><jk>public</jk> T(RestContext)</code>
1377    *          <li><code><jk>public</jk> T()</code>
1378    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
1379    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
1380    *       </ul>
1381    *    <li>
1382    *       Inner classes of the REST resource class are allowed.
1383    * </ul>
1384    */
1385   public static final String REST_infoProvider = PREFIX + ".infoProvider.o";
1386
1387   /**
1388    * Configuration property:  REST logger.
1389    *
1390    * <div class='warn'>
1391    *    <b>Deprecated</b> - Use {@link #REST_callLogger}
1392    * </div>
1393    */
1394   @Deprecated
1395   public static final String REST_logger = PREFIX + ".logger.o";
1396
1397   /**
1398    * Configuration property:  The maximum allowed input size (in bytes) on HTTP requests.
1399    *
1400    * <h5 class='section'>Property:</h5>
1401    * <ul class='spaced-list'>
1402    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_maxInput REST_maxInput}
1403    *    <li><b>Name:</b>  <js>"RestContext.maxInput.s"</js>
1404    *    <li><b>Data type:</b>  <c>String</c>
1405    *    <li><b>System property:</b>  <c>RestContext.maxInput</c>
1406    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_MAXINPUT</c>
1407    *    <li><b>Default:</b>  <js>"100M"</js>
1408    *    <li><b>Session property:</b>  <jk>false</jk>
1409    *    <li><b>Annotations:</b>
1410    *       <ul>
1411    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#maxInput()}
1412    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#maxInput()}
1413    *       </ul>
1414    *    <li><b>Methods:</b>
1415    *       <ul>
1416    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#maxInput(String)}
1417    *       </ul>
1418    * </ul>
1419    *
1420    * <h5 class='section'>Description:</h5>
1421    * <p>
1422    * Useful for alleviating DoS attacks by throwing an exception when too much input is received instead of resulting
1423    * in out-of-memory errors which could affect system stability.
1424    *
1425    * <h5 class='section'>Example:</h5>
1426    * <p class='bcode w800'>
1427    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
1428    *    <ja>@Rest</ja>(maxInput=<js>"$C{REST/maxInput,10M}"</js>)
1429    *    <jk>public class</jk> MyResource {
1430    *
1431    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1432    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1433    *
1434    *          <jc>// Using method on builder.</jc>
1435    *          builder.maxInput(<js>"10M"</js>);
1436    *
1437    *          <jc>// Same, but using property.</jc>
1438    *          builder.set(<jsf>REST_maxInput</jsf>, <js>"10M"</js>);
1439    *       }
1440    *
1441    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1442    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1443    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1444    *          builder.maxInput(<js>"10M"</js>);
1445    *       }
1446    *
1447    *       <jc>// Override at the method level.</jc>
1448    *       <ja>@RestMethod</ja>(maxInput=<js>"10M"</js>)
1449    *       public Object myMethod() {...}
1450    *    }
1451    * </p>
1452    *
1453    * <ul class='notes'>
1454    *    <li>
1455    *       String value that gets resolved to a <jk>long</jk>.
1456    *    <li>
1457    *       Can be suffixed with any of the following representing kilobytes, megabytes, and gigabytes:
1458    *       <js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
1459    *    <li>
1460    *       A value of <js>"-1"</js> can be used to represent no limit.
1461    * </ul>
1462    */
1463   public static final String REST_maxInput = PREFIX + ".maxInput.s";
1464
1465   /**
1466    * Configuration property:  Messages.
1467    *
1468    * <h5 class='section'>Property:</h5>
1469    * <ul class='spaced-list'>
1470    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_messages REST_messages}
1471    *    <li><b>Name:</b>  <js>"RestContext.messages.lo"</js>
1472    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.utils.Tuple2}&lt;Class,String&gt;&gt;</c>
1473    *    <li><b>Default:</b>  <jk>null</jk>
1474    *    <li><b>Session property:</b>  <jk>false</jk>
1475    *    <li><b>Annotations:</b>
1476    *       <ul>
1477    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#messages()}
1478    *       </ul>
1479    *    <li><b>Methods:</b>
1480    *       <ul>
1481    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#messages(String)},
1482    *       </ul>
1483    * </ul>
1484    *
1485    * <h5 class='section'>Description:</h5>
1486    * <p>
1487    * Identifies the location of the resource bundle for this class if it's different from the class name.
1488    *
1489    * <p>
1490    * By default, the resource bundle name is assumed to match the class name.  For example, given the class
1491    * <c>MyClass.java</c>, the resource bundle is assumed to be <c>MyClass.properties</c>.  This property
1492    * allows you to override this setting to specify a different location such as <c>MyMessages.properties</c> by
1493    * specifying a value of <js>"MyMessages"</js>.
1494    *
1495    * <p>
1496    *    Resource bundles are searched using the following base name patterns:
1497    *    <ul>
1498    *       <li><js>"{package}.{name}"</js>
1499    *       <li><js>"{package}.i18n.{name}"</js>
1500    *       <li><js>"{package}.nls.{name}"</js>
1501    *       <li><js>"{package}.messages.{name}"</js>
1502    *    </ul>
1503    *
1504    * <p>
1505    * This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following methods:
1506    * <ul class='javatree'>
1507    *    <li class='jm'>{@link RestRequest#getMessage(String, Object...)}
1508    *    <li class='jm'>{@link RestContext#getMessages() RestContext.getMessages()}
1509    * </ul>
1510    *
1511    * <p>
1512    * Request-localized messages are also available by passing either of the following parameter types into your Java method:
1513    * <ul class='javatree'>
1514    *    <li class='jc'>{@link ResourceBundle} - Basic Java resource bundle.
1515    *    <li class='jc'>{@link Messages} - Extended resource bundle with several convenience methods.
1516    * </ul>
1517    *
1518    * The value can be a relative path like <js>"nls/Messages"</js>, indicating to look for the resource bundle
1519    * <js>"com.foo.sample.nls.Messages"</js> if the resource class is in <js>"com.foo.sample"</js>, or it can be an
1520    * absolute path like <js>"com.foo.sample.nls.Messages"</js>
1521    *
1522    * <h5 class='section'>Examples:</h5>
1523    * <p class='bcode w800'>
1524    *    <cc># Contents of org/apache/foo/nls/MyMessages.properties</cc>
1525    *
1526    *    <ck>HelloMessage</ck> = <cv>Hello {0}!</cv>
1527    * </p>
1528    * <p class='bcode w800'>
1529    *    <jc>// Contents of org/apache/foo/MyResource.java</jc>
1530    *
1531    *    <ja>@Rest</ja>(messages=<js>"nls/MyMessages"</js>)
1532    *    <jk>public class</jk> MyResource {...}
1533    *
1534    *       <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/hello/{you}"</js>)
1535    *       <jk>public</jk> Object helloYou(RestRequest <jv>req</jv>, Messages <jv>messages</jv>, <ja>@Path</ja>(<js>"name"</js>) String <jv>you</jv>) {
1536    *          String <jv>s</jv>;
1537    *
1538    *          <jc>// Get it from the RestRequest object.</jc>
1539    *          <jv>s</jv> = <jv>req</jv>.getMessage(<js>"HelloMessage"</js>, <jv>you</jv>);
1540    *
1541    *          <jc>// Or get it from the method parameter.</jc>
1542    *          <jv>s</jv> = <jv>messages</jv>.getString(<js>"HelloMessage"</js>, <jv>you</jv>);
1543    *
1544    *          <jc>// Or get the message in a locale different from the request.</jc>
1545    *          <jv>s</jv> = <jv>messages</jv>.forLocale(Locale.<jsf>UK</jsf>).getString(<js>"HelloMessage"</js>, <jv>you</jv>);
1546    *
1547    *          <jk>return</jk> <jv>s</jv>;
1548    *       }
1549    *    }
1550    * </p>
1551    *
1552    * <ul class='notes'>
1553    *    <li>Mappings are cumulative from super classes.
1554    *       <br>Therefore, you can find and retrieve messages up the class-hierarchy chain.
1555    * </ul>
1556    *
1557    * <ul class='seealso'>
1558    *    <li class='jc'>{@link Messages}
1559    *    <li class='link'>{@doc RestMessages}
1560    * </ul>
1561    */
1562   public static final String REST_messages = PREFIX + ".messages.lo";
1563
1564   /**
1565    * Configuration property:  MIME types.
1566    *
1567    * <h5 class='section'>Property:</h5>
1568    * <ul class='spaced-list'>
1569    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_mimeTypes REST_mimeTypes}
1570    *    <li><b>Name:</b>  <js>"RestContext.mimeTypes.ss"</js>
1571    *    <li><b>Data type:</b>  <c>Set&lt;String&gt;</c>
1572    *    <li><b>System property:</b>  <c>RestContext.mimeTypes</c>
1573    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_MIMETYPES</c>
1574    *    <li><b>Default:</b>  empty list
1575    *    <li><b>Session property:</b>  <jk>false</jk>
1576    *    <li><b>Annotations:</b>
1577    *       <ul>
1578    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#mimeTypes()}
1579    *       </ul>
1580    *    <li><b>Methods:</b>
1581    *       <ul>
1582    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#mimeTypes(String...)}
1583    *       </ul>
1584    * </ul>
1585    *
1586    * <h5 class='section'>Description:</h5>
1587    * <p>
1588    * Defines MIME-type file type mappings.
1589    *
1590    * <p>
1591    * Used for specifying the content type on file resources retrieved through the following methods:
1592    * <ul class='javatree'>
1593    *    <li class='jm'>{@link RestContext#getStaticFile(String) RestContext.resolveStaticFile(String)}
1594    *    <li class='jm'>{@link RestRequest#getClasspathHttpResource(String,boolean,MediaType,boolean)}
1595    *    <li class='jm'>{@link RestRequest#getClasspathHttpResource(String,boolean)}
1596    *    <li class='jm'>{@link RestRequest#getClasspathHttpResource(String)}
1597    * </ul>
1598    *
1599    * <p>
1600    * This list appends to the existing list provided by {@link ExtendedMimetypesFileTypeMap}.
1601    *
1602    * <h5 class='section'>Example:</h5>
1603    * <p class='bcode w800'>
1604    *    <jc>// Option #1 - Defined via annotation.</jc>
1605    *    <ja>@Rest</ja>(mimeTypes={<js>"text/plain txt text TXT"</js>})
1606    *    <jk>public class</jk> MyResource {
1607    *
1608    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1609    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1610    *
1611    *          <jc>// Using method on builder.</jc>
1612    *          builder.mimeTypes(<js>"text/plain txt text TXT"</js>);
1613    *
1614    *          <jc>// Same, but using property.</jc>
1615    *          builder.addTo(<jsf>REST_mimeTypes</jsf>, <js>"text/plain txt text TXT"</js>);
1616    *       }
1617    *
1618    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1619    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1620    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1621    *          builder.mimeTypes(<js>"text/plain txt text TXT"</js>);
1622    *       }
1623    *    }
1624    * </p>
1625    *
1626    * <ul class='notes'>
1627    *    <li>
1628    *       Values are .mime.types formatted entry string.
1629    *       <br>Example: <js>"image/svg+xml svg"</js>
1630    * </ul>
1631    */
1632   public static final String REST_mimeTypes = PREFIX + ".mimeTypes.ss";
1633
1634   /**
1635    * Configuration property:  Java method parameter resolvers.
1636    *
1637    * <h5 class='section'>Property:</h5>
1638    * <ul class='spaced-list'>
1639    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_paramResolvers REST_paramResolvers}
1640    *    <li><b>Name:</b>  <js>"RestContext.paramResolvers.lo"</js>
1641    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.rest.RestMethodParam}|Class&lt;{@link org.apache.juneau.rest.RestMethodParam}&gt;&gt;</c>
1642    *    <li><b>Default:</b>  empty list
1643    *    <li><b>Session property:</b>  <jk>false</jk>
1644    *    <li><b>Annotations:</b>
1645    *       <ul>
1646    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#paramResolvers()}
1647    *       </ul>
1648    *    <li><b>Methods:</b>
1649    *       <ul>
1650    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#paramResolvers(Class...)}
1651    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#paramResolvers(RestMethodParam...)}
1652    *       </ul>
1653    * </ul>
1654    *
1655    * <h5 class='section'>Description:</h5>
1656    * <p>
1657    * By default, the Juneau framework will automatically Java method parameters of various types (e.g.
1658    * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).
1659    * This setting allows you to provide your own resolvers for your own class types that you want resolved.
1660    *
1661    * <p>
1662    * For example, if you want to pass in instances of <c>MySpecialObject</c> to your Java method, define
1663    * the following resolver:
1664    * <p class='bcode w800'>
1665    *    <jc>// Define a parameter resolver for resolving MySpecialObject objects.</jc>
1666    *    <jk>public class</jk> MyRestParam <jk>extends</jk> RestMethodParam {
1667    *
1668    *       <jc>// Must have no-arg constructor!</jc>
1669    *       <jk>public</jk> MyRestParam() {
1670    *          <jc>// First two parameters help with Swagger doc generation.</jc>
1671    *          <jk>super</jk>(<jsf>QUERY</jsf>, <js>"myparam"</js>, MySpecialObject.<jk>class</jk>);
1672    *       }
1673    *
1674    *       <jc>// The method that creates our object.
1675    *       // In this case, we're taking in a query parameter and converting it to our object.</jc>
1676    *       <jk>public</jk> Object resolve(RestRequest req, RestResponse res) <jk>throws</jk> Exception {
1677    *          <jk>return new</jk> MySpecialObject(req.getQuery().get(<js>"myparam"</js>));
1678    *       }
1679    *    }
1680    *
1681    *    <jc>// Option #1 - Registered via annotation.</jc>
1682    *    <ja>@Rest</ja>(paramResolvers=MyRestParam.<jk>class</jk>)
1683    *    <jk>public class</jk> MyResource {
1684    *
1685    *       <jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>
1686    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1687    *
1688    *          <jc>// Using method on builder.</jc>
1689    *          builder.paramResolvers(MyRestParam.<jk>class</jk>);
1690    *
1691    *          <jc>// Same, but using property.</jc>
1692    *          builder.addTo(<jsf>REST_paramResolver</jsf>, MyRestParam.<jk>class</jk>);
1693    *       }
1694    *
1695    *       <jc>// Option #3 - Registered via builder passed in through init method.</jc>
1696    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1697    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1698    *          builder.paramResolvers(MyRestParam.<jk>class</jk>);
1699    *       }
1700    *
1701    *       <jc>// Now pass it into your method.</jc>
1702    *       <ja>@RestMethod</ja>(...)
1703    *       <jk>public</jk> Object doMyMethod(MySpecialObject mySpeciaObject) {
1704    *          <jc>// Do something with it.</jc>
1705    *       }
1706    *    }
1707    * </p>
1708    *
1709    * <ul class='notes'>
1710    *    <li>
1711    *       When defined as a class, the implementation must have one of the following constructors:
1712    *       <ul>
1713    *          <li><code><jk>public</jk> T(BeanContext)</code>
1714    *          <li><code><jk>public</jk> T()</code>
1715    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
1716    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
1717    *       </ul>
1718    *    <li>
1719    *       Inner classes of the REST resource class are allowed.
1720    *    <li>
1721    *       Refer to {@link RestMethodParam} for the list of predefined parameter resolvers.
1722    * </ul>
1723    */
1724   public static final String REST_paramResolvers = PREFIX + ".paramResolvers.lo";
1725
1726   /**
1727    * Configuration property:  Parsers.
1728    *
1729    * <h5 class='section'>Property:</h5>
1730    * <ul class='spaced-list'>
1731    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_parsers REST_parsers}
1732    *    <li><b>Name:</b>  <js>"RestContext.parsers.lo"</js>
1733    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.parser.Parser}|Class&lt;{@link org.apache.juneau.parser.Parser}&gt;&gt;</c>
1734    *    <li><b>Default:</b>  empty list
1735    *    <li><b>Session property:</b>  <jk>false</jk>
1736    *    <li><b>Annotations:</b>
1737    *       <ul>
1738    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#parsers()}
1739    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#parsers()}
1740    *       </ul>
1741    *    <li><b>Methods:</b>
1742    *       <ul>
1743    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#parsers(Object...)}
1744    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#parsers(Class...)}
1745    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#parsersReplace(Object...)}
1746    *       </ul>
1747    * </ul>
1748    *
1749    * <h5 class='section'>Description:</h5>
1750    * <p>
1751    * Adds class-level parsers to this resource.
1752    *
1753    * <p>
1754    * Parsers are used to convert the body of HTTP requests into POJOs.
1755    * <br>Any of the Juneau framework parsers can be used in this setting.
1756    * <br>The parser selected is based on the request <c>Content-Type</c> header matched against the values returned by the following method
1757    * using a best-match algorithm:
1758    * <ul class='javatree'>
1759    *    <li class='jm'>{@link Parser#getMediaTypes()}
1760    * </ul>
1761    *
1762    * <h5 class='section'>Example:</h5>
1763    * <p class='bcode w800'>
1764    *    <jc>// Option #1 - Defined via annotation.</jc>
1765    *    <ja>@Rest</ja>(parsers={JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>})
1766    *    <jk>public class</jk> MyResource {
1767    *
1768    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1769    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1770    *
1771    *          <jc>// Using method on builder.</jc>
1772    *          builder.parsers(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
1773    *
1774    *          <jc>// Same, but use pre-instantiated parsers.</jc>
1775    *          builder.parsers(JsonParser.<jsf>DEFAULT</jsf>, XmlParser.<jsf>DEFAULT</jsf>);
1776    *
1777    *          <jc>// Same, but using property.</jc>
1778    *          builder.set(<jsf>REST_parsers</jsf>, JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
1779    *       }
1780    *
1781    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1782    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1783    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1784    *          builder.parsers(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
1785    *       }
1786    *
1787    *       <jc>// Override at the method level.</jc>
1788    *       <ja>@RestMethod</ja>(parsers={HtmlParser.<jk>class</jk>})
1789    *       <jk>public</jk> Object myMethod(<ja>@Body</ja> MyPojo myPojo) {
1790    *          <jc>// Do something with your parsed POJO.</jc>
1791    *       }
1792    *    }
1793    * </p>
1794    *
1795    * <ul class='notes'>
1796    *    <li>
1797    *       When defined as a class, properties/transforms defined on the resource/method are inherited.
1798    *    <li>
1799    *       When defined as an instance, properties/transforms defined on the resource/method are NOT inherited.
1800    *    <li>
1801    *       Typically, you'll want your resource to extend directly from {@link BasicRestServlet} which comes
1802    *       preconfigured with the following parsers:
1803    *       <ul>
1804    *          <li class='jc'>{@link JsonParser}
1805    *          <li class='jc'>{@link XmlParser}
1806    *          <li class='jc'>{@link HtmlParser}
1807    *          <li class='jc'>{@link UonParser}
1808    *          <li class='jc'>{@link UrlEncodingParser}
1809    *          <li class='jc'>{@link MsgPackParser}
1810    *          <li class='jc'>{@link PlainTextParser}
1811    *       </ul>
1812    * </ul>
1813    *
1814    * <ul class='seealso'>
1815    *    <li class='link'>{@doc RestParsers}
1816    * </ul>
1817    */
1818   public static final String REST_parsers = PREFIX + ".parsers.lo";
1819
1820   /**
1821    * Configuration property:  HTTP part parser.
1822    *
1823    * <h5 class='section'>Property:</h5>
1824    * <ul class='spaced-list'>
1825    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_partParser REST_partParser}
1826    *    <li><b>Name:</b>  <js>"RestContext.partParser.o"</js>
1827    *    <li><b>Data type:</b>  <c>{@link org.apache.juneau.httppart.HttpPartParser}|Class&lt;{@link org.apache.juneau.httppart.HttpPartParser}&gt;</c>
1828    *    <li><b>Default:</b>  {@link org.apache.juneau.oapi.OpenApiParser}
1829    *    <li><b>Session property:</b>  <jk>false</jk>
1830    *    <li><b>Annotations:</b>
1831    *       <ul>
1832    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#partParser()}
1833    *       </ul>
1834    *    <li><b>Methods:</b>
1835    *       <ul>
1836    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#partParser(Class)}
1837    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#partParser(HttpPartParser)}
1838    *       </ul>
1839    * </ul>
1840    *
1841    * <h5 class='section'>Description:</h5>
1842    * <p>
1843    * Specifies the {@link HttpPartParser} to use for parsing headers, query/form parameters, and URI parts.
1844    *
1845    * <p>
1846    * The default value is {@link OpenApiParser} which allows for both plain-text and URL-Encoded-Object-Notation values.
1847    * <br>If your parts contain text that can be confused with UON (e.g. <js>"(foo)"</js>), you can switch to
1848    * {@link SimplePartParser} which treats everything as plain text.
1849    *
1850    * <h5 class='section'>Example:</h5>
1851    * <p class='bcode w800'>
1852    *    <jc>// Option #1 - Defined via annotation.</jc>
1853    *    <ja>@Rest</ja>(partParser=SimplePartParser.<jk>class</jk>)
1854    *    <jk>public class</jk> MyResource {
1855    *
1856    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1857    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1858    *
1859    *          <jc>// Using method on builder.</jc>
1860    *          builder.partParser(SimplePartParser.<jk>class</jk>);
1861    *
1862    *          <jc>// Same, but using property.</jc>
1863    *          builder.set(<jsf>REST_partParser</jsf>, SimplePartParser.<jk>class</jk>);
1864    *       }
1865    *
1866    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1867    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1868    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1869    *          builder.partParser(SimplePartParser.<jk>class</jk>);
1870    *       }
1871    *
1872    *       <ja>@RestMethod</ja>(...)
1873    *       <jk>public</jk> Object myMethod(<ja>@Header</ja>(<js>"My-Header"</js>) MyParsedHeader h, <ja>@Query</ja>(<js>"myquery"</js>) MyParsedQuery q) {
1874    *          <jc>// Do something with your parsed parts.</jc>
1875    *       }
1876    *    }
1877    * </p>
1878    *
1879    * <ul class='notes'>
1880    *    <li>
1881    *       When defined as a class, properties/transforms defined on the resource/method are inherited.
1882    *    <li>
1883    *       When defined as an instance, properties/transforms defined on the resource/method are NOT inherited.
1884    * </ul>
1885    */
1886   public static final String REST_partParser = PREFIX + ".partParser.o";
1887
1888   /**
1889    * Configuration property:  HTTP part serializer.
1890    *
1891    * <h5 class='section'>Property:</h5>
1892    * <ul class='spaced-list'>
1893    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_partSerializer REST_partSerializer}
1894    *    <li><b>Name:</b>  <js>"RestContext.partSerializer.o"</js>
1895    *    <li><b>Data type:</b>
1896    *       <ul>
1897    *          <li>{@link org.apache.juneau.httppart.HttpPartSerializer}
1898    *          <li><c>Class&lt;{@link org.apache.juneau.httppart.HttpPartSerializer}&gt;</c>
1899    *       </ul>
1900    *    <li><b>Default:</b>  {@link org.apache.juneau.oapi.OpenApiSerializer}
1901    *    <li><b>Session property:</b>  <jk>false</jk>
1902    *    <li><b>Annotations:</b>
1903    *       <ul>
1904    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#partSerializer()}
1905    *       </ul>
1906    *    <li><b>Methods:</b>
1907    *       <ul>
1908    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#partSerializer(Class)}
1909    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#partSerializer(HttpPartSerializer)}
1910    *       </ul>
1911    * </ul>
1912    *
1913    * <h5 class='section'>Description:</h5>
1914    * <p>
1915    * Specifies the {@link HttpPartSerializer} to use for serializing headers, query/form parameters, and URI parts.
1916    *
1917    * <p>
1918    * The default value is {@link OpenApiSerializer} which serializes based on OpenAPI rules, but defaults to UON notation for beans and maps, and
1919    * plain text for everything else.
1920    * <br>Other options include:
1921    * <ul>
1922    *    <li class='jc'>{@link SimplePartSerializer} - Always serializes to plain text.
1923    *    <li class='jc'>{@link UonSerializer} - Always serializers to UON.
1924    * </ul>
1925    *
1926    * <h5 class='section'>Example:</h5>
1927    * <p class='bcode w800'>
1928    *    <jc>// Option #1 - Defined via annotation.</jc>
1929    *    <ja>@Rest</ja>(partSerializer=SimplePartSerializer.<jk>class</jk>)
1930    *    <jk>public class</jk> MyResource {
1931    *
1932    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
1933    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
1934    *
1935    *          <jc>// Using method on builder.</jc>
1936    *          builder.partSerializer(SimplePartSerializer.<jk>class</jk>);
1937    *
1938    *          <jc>// Same, but using property.</jc>
1939    *          builder.set(<jsf>REST_partSerializer</jsf>, SimplePartSerializer.<jk>class</jk>);
1940    *       }
1941    *
1942    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
1943    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
1944    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
1945    *          builder.partSerializer(SimplePartSerializer.<jk>class</jk>);
1946    *       }
1947    *
1948    *       <ja>@RestMethod</ja>(...)
1949    *       <jk>public</jk> Object myMethod(RestResponse res) {
1950    *          <jc>// Set a header to a POJO.</jc>
1951    *          res.setHeader(<js>"My-Header"</js>, <jk>new</jk> MyPojo());
1952    *       }
1953    *    }
1954    * </p>
1955    *
1956    * <ul class='notes'>
1957    *    <li>
1958    *       When defined as a class, properties/transforms defined on the resource/method are inherited.
1959    *    <li>
1960    *       When defined as an instance, properties/transforms defined on the resource/method are NOT inherited.
1961    * </ul>
1962    */
1963   public static final String REST_partSerializer = PREFIX + ".partSerializer.o";
1964
1965   /**
1966    * Configuration property:  Resource path.
1967    *
1968    * <h5 class='section'>Property:</h5>
1969    * <ul class='spaced-list'>
1970    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_path REST_path}
1971    *    <li><b>Name:</b>  <js>"RestContext.path.s"</js>
1972    *    <li><b>Data type:</b>  <c>String</c>
1973    *    <li><b>System property:</b>  <c>RestContext.path.</c>
1974    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_PATH</c>
1975    *    <li><b>Default:</b>  <jk>null</jk>
1976    *    <li><b>Session property:</b>  <jk>false</jk>
1977    *    <li><b>Annotations:</b>
1978    *       <ul>
1979    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#path()}
1980    *       </ul>
1981    *    <li><b>Methods:</b>
1982    *       <ul>
1983    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#path(String)}
1984    *       </ul>
1985    * </ul>
1986    *
1987    * <h5 class='section'>Description:</h5>
1988    * <p>
1989    * Identifies the URL subpath relative to the ascendant resource.
1990    *
1991    * <p>
1992    * This setting is critical for the routing of HTTP requests from ascendant to child resources.
1993    *
1994    * <h5 class='section'>Example:</h5>
1995    * <p class='bcode w800'>
1996    *    <jc>// Option #1 - Defined via annotation.</jc>
1997    *    <ja>@Rest</ja>(path=<js>"/myResource"</js>)
1998    *    <jk>public class</jk> MyResource {
1999    *
2000    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2001    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2002    *
2003    *          <jc>// Using method on builder.</jc>
2004    *          builder.path(<js>"/myResource"</js>);
2005    *
2006    *          <jc>// Same, but using property.</jc>
2007    *          builder.set(<jsf>REST_path</jsf>, <js>"/myResource"</js>);
2008    *       }
2009    *
2010    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2011    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2012    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2013    *          builder.path(<js>"/myResource"</js>);
2014    *       }
2015    *    }
2016    * </p>
2017    *
2018    * <p>
2019    * <ul class='notes'>
2020    *    <li>
2021    *       This annotation is ignored on top-level servlets (i.e. servlets defined in <c>web.xml</c> files).
2022    *       <br>Therefore, implementers can optionally specify a path value for documentation purposes.
2023    *    <li>
2024    *       Typically, this setting is only applicable to resources defined as children through the
2025    *       {@link Rest#children() @Rest(children)} annotation.
2026    *       <br>However, it may be used in other ways (e.g. defining paths for top-level resources in microservices).
2027    *    <li>
2028    *       Slashes are trimmed from the path ends.
2029    *       <br>As a convention, you may want to start your path with <js>'/'</js> simple because it make it easier to read.
2030    *    <li>
2031    *       This path is available through the following method:
2032    *       <ul>
2033    *          <li class='jm'>{@link RestContext#getPath() RestContext.getPath()}
2034    *       </ul>
2035    * </ul>
2036    */
2037   public static final String REST_path = PREFIX + ".path.s";
2038
2039   /**
2040    * Configuration property:  Render response stack traces in responses.
2041    *
2042    * <h5 class='section'>Property:</h5>
2043    * <ul class='spaced-list'>
2044    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_renderResponseStackTraces REST_renderResponseStackTraces}
2045    *    <li><b>Name:</b>  <js>"RestContext.renderResponseStackTraces.b"</js>
2046    *    <li><b>Data type:</b>  <jk>boolean</jk>
2047    *    <li><b>System property:</b>  <c>RestContext.renderResponseStackTraces</c>
2048    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_RENDERRESPONSESTACKTRACES</c>
2049    *    <li><b>Default:</b>  <jk>false</jk>
2050    *    <li><b>Session property:</b>  <jk>false</jk>
2051    *    <li><b>Annotations:</b>
2052    *       <ul>
2053    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#renderResponseStackTraces()}
2054    *       </ul>
2055    *    <li><b>Methods:</b>
2056    *       <ul>
2057    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#renderResponseStackTraces(boolean)}
2058    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#renderResponseStackTraces()}
2059    *       </ul>
2060    * </ul>
2061    *
2062    * <h5 class='section'>Description:</h5>
2063    * <p>
2064    * Render stack traces in HTTP response bodies when errors occur.
2065    *
2066    * <h5 class='section'>Example:</h5>
2067    * <p class='bcode w800'>
2068    *    <jc>// Option #1 - Defined via annotation.</jc>
2069    *    <ja>@Rest</ja>(renderResponseStackTraces=<jk>true</jk>)
2070    *    <jk>public class</jk> MyResource {
2071    *
2072    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2073    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2074    *
2075    *          <jc>// Using method on builder.</jc>
2076    *          builder.renderResponseStackTraces();
2077    *
2078    *          <jc>// Same, but using property.</jc>
2079    *          builder.set(<jsf>REST_renderResponseStackTraces</jsf>, <jk>true</jk>);
2080    *       }
2081    *
2082    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2083    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2084    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2085    *          builder.renderResponseStackTraces();
2086    *       }
2087    *    }
2088    * </p>
2089    *
2090    * <ul class='notes'>
2091    *    <li>
2092    *       Useful for debugging, although allowing stack traces to be rendered may cause security concerns so use
2093    *       caution when enabling.
2094    *    <li>
2095    *       This setting is available through the following method:
2096    *       <ul>
2097    *          <li class='jm'>{@link RestContext#isRenderResponseStackTraces() RestContext.isRenderResponseStackTraces()}
2098    *       </ul>
2099    *       That method is used by {@link #handleError(RestCall, Throwable)}.
2100    * </ul>
2101    */
2102   public static final String REST_renderResponseStackTraces = PREFIX + ".renderResponseStackTraces.b";
2103
2104   /**
2105    * Configuration property:  Default request attributes.
2106    *
2107    * <h5 class='section'>Property:</h5>
2108    * <ul class='spaced-list'>
2109    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_reqAttrs REST_reqAttrs}
2110    *    <li><b>Name:</b>  <js>"RestContext.reqAttrs.smo"</js>
2111    *    <li><b>Data type:</b>  <c>Map&lt;String,Object&gt;</c>
2112    *    <li><b>System property:</b>  <c>RestContext.reqAttrs</c>
2113    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_REQATTRS</c>
2114    *    <li><b>Default:</b>  empty map
2115    *    <li><b>Session property:</b>  <jk>false</jk>
2116    *    <li><b>Annotations:</b>
2117    *       <ul>
2118    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#reqAttrs()}
2119    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#reqAttrs()}
2120    *       </ul>
2121    *    <li><b>Methods:</b>
2122    *       <ul>
2123    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#reqAttrs(String...)}
2124    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#reqAttr(String,Object)}
2125    *       </ul>
2126    * </ul>
2127    *
2128    * <h5 class='section'>Description:</h5>
2129    * <p>
2130    * Specifies default values for request attributes if they're not already set on the request.
2131    *
2132    * <ul class='notes'>
2133    *    <li>
2134    *       Strings are in the format <js>"Name: value"</js>.
2135    *    <li>
2136    *       Affects values returned by the following methods:
2137    *       <ul>
2138    *          <li class='jm'>{@link RestRequest#getAttribute(String)}.
2139    *          <li class='jm'>{@link RestRequest#getAttributes()}.
2140    *       </ul>
2141    * </ul>
2142    *
2143    * <h5 class='section'>Example:</h5>
2144    * <p class='bcode w800'>
2145    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
2146    *    <ja>@Rest</ja>(reqAttrs={<js>"Foo: bar"</js>, <js>"Baz: $C{REST/myAttributeValue}"</js>})
2147    *    <jk>public class</jk> MyResource {
2148    *
2149    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2150    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2151    *
2152    *          <jc>// Using method on builder.</jc>
2153    *          builder
2154    *             .attr(<js>"Foo"</js>, <js>"bar"</js>);
2155    *             .attr(<js>"Baz: true"</js>);
2156    *
2157    *          <jc>// Same, but using property.</jc>
2158    *          builder.addTo(<jsf>REST_reqAttrs</jsf>, <js>"Foo"</js>, <js>"bar"</js>);
2159    *       }
2160    *
2161    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2162    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2163    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2164    *          builder.reqAttr(<js>"Foo"</js>, <js>"bar"</js>);
2165    *       }
2166    *
2167    *       <jc>// Override at the method level.</jc>
2168    *       <ja>@RestMethod</ja>(reqAttrs={<js>"Foo: bar"</js>})
2169    *       public Object myMethod() {...}
2170    *    }
2171    * </p>
2172    */
2173   public static final String REST_reqAttrs = PREFIX + ".reqAttrs.smo";
2174
2175   /**
2176    * Configuration property:  Default request headers.
2177    *
2178    * <h5 class='section'>Property:</h5>
2179    * <ul class='spaced-list'>
2180    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_reqHeaders REST_reqHeaders}
2181    *    <li><b>Name:</b>  <js>"RestContext.reqHeaders.smo"</js>
2182    *    <li><b>Data type:</b>  <c>Map&lt;String,String&gt;</c>
2183    *    <li><b>System property:</b>  <c>RestContext.reqHeaders</c>
2184    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_REQHEADERS</c>
2185    *    <li><b>Default:</b>  empty map
2186    *    <li><b>Session property:</b>  <jk>false</jk>
2187    *    <li><b>Annotations:</b>
2188    *       <ul>
2189    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#reqHeaders()}
2190    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#reqHeaders()}
2191    *       </ul>
2192    *    <li><b>Methods:</b>
2193    *       <ul>
2194    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#reqHeader(String,Object)}
2195    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#reqHeaders(String...)}
2196    *       </ul>
2197    * </ul>
2198    *
2199    * <h5 class='section'>Description:</h5>
2200    * <p>
2201    * Specifies default values for request headers if they're not passed in through the request.
2202    *
2203    * <ul class='notes'>
2204    *    <li>
2205    *       Strings are in the format <js>"Header-Name: header-value"</js>.
2206    *    <li>
2207    *       Affects values returned by {@link RestRequest#getHeader(String)} when the header is not present on the request.
2208    *    <li>
2209    *       The most useful reason for this annotation is to provide a default <c>Accept</c> header when one is not
2210    *       specified so that a particular default {@link Serializer} is picked.
2211    * </ul>
2212    *
2213    * <h5 class='section'>Example:</h5>
2214    * <p class='bcode w800'>
2215    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
2216    *    <ja>@Rest</ja>(reqHeaders={<js>"Accept: application/json"</js>, <js>"My-Header: $C{REST/myHeaderValue}"</js>})
2217    *    <jk>public class</jk> MyResource {
2218    *
2219    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2220    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2221    *
2222    *          <jc>// Using method on builder.</jc>
2223    *          builder
2224    *             .reqHeader(<js>"Accept"</js>, <js>"application/json"</js>);
2225    *             .reqHeaders(<js>"My-Header: foo"</js>);
2226    *
2227    *          <jc>// Same, but using property.</jc>
2228    *          builder.addTo(<jsf>REST_reqHeaders</jsf>, <js>"Accept"</js>, <js>"application/json"</js>);
2229    *       }
2230    *
2231    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2232    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2233    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2234    *          builder.reqHeader(<js>"Accept"</js>, <js>"application/json"</js>);
2235    *       }
2236    *
2237    *       <jc>// Override at the method level.</jc>
2238    *       <ja>@RestMethod</ja>(reqHeaders={<js>"Accept: text/xml"</js>})
2239    *       public Object myMethod() {...}
2240    *    }
2241    * </p>
2242    */
2243   public static final String REST_reqHeaders = PREFIX + ".reqHeaders.smo";
2244
2245   /**
2246    * Configuration property:  Default response headers.
2247    *
2248    * <h5 class='section'>Property:</h5>
2249    * <ul class='spaced-list'>
2250    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_resHeaders REST_resHeaders}
2251    *    <li><b>Name:</b>  <js>"RestContext.resHeaders.omo"</js>
2252    *    <li><b>Data type:</b>  <c>Map&lt;String,String&gt;</c>
2253    *    <li><b>System property:</b>  <c>RestContext.resHeaders</c>
2254    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_RESHEADERS</c>
2255    *    <li><b>Default:</b>  empty map
2256    *    <li><b>Session property:</b>  <jk>false</jk>
2257    *    <li><b>Annotations:</b>
2258    *       <ul>
2259    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#resHeaders()}
2260    *       </ul>
2261    *    <li><b>Methods:</b>
2262    *       <ul>
2263    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#resHeader(String,Object)}
2264    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#resHeaders(String...)}
2265    *       </ul>
2266    * </ul>
2267    *
2268    * <h5 class='section'>Description:</h5>
2269    * <p>
2270    * Specifies default values for response headers if they're not set after the Java REST method is called.
2271    *
2272    * <ul class='notes'>
2273    *    <li>
2274    *       Strings are in the format <js>"Header-Name: header-value"</js>.
2275    *    <li>
2276    *       This is equivalent to calling {@link RestResponse#setHeader(String, String)} programmatically in each of
2277    *       the Java methods.
2278    *    <li>
2279    *       The header value will not be set if the header value has already been specified (hence the 'default' in the name).
2280    * </ul>
2281    *
2282    * <h5 class='section'>Example:</h5>
2283    * <p class='bcode w800'>
2284    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
2285    *    <ja>@Rest</ja>(resHeaders={<js>"Content-Type: $C{REST/defaultContentType,text/plain}"</js>,<js>"My-Header: $C{REST/myHeaderValue}"</js>})
2286    *    <jk>public class</jk> MyResource {
2287    *
2288    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2289    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2290    *
2291    *          <jc>// Using method on builder.</jc>
2292    *          builder
2293    *             .resHeader(<js>"Content-Type"</js>, <js>"text/plain"</js>);
2294    *             .resHeaders(<js>"My-Header: foo"</js>);
2295    *
2296    *          <jc>// Same, but using property.</jc>
2297    *          builder
2298    *             .addTo(<jsf>REST_resHeaders</jsf>, <js>"Accept"</js>, <js>"application/json"</js>);
2299    *             .addTo(<jsf>REST_resHeaders</jsf>, <js>"My-Header"</js>, <js>"foo"</js>);
2300    *       }
2301    *
2302    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2303    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2304    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2305    *          builder.resHeader(<js>"Content-Type"</js>, <js>"text/plain"</js>);
2306    *       }
2307    *    }
2308    * </p>
2309    */
2310   public static final String REST_resHeaders = PREFIX + ".resHeaders.omo";
2311
2312   /**
2313    * Configuration property:  REST resource resolver.
2314    *
2315    * <h5 class='section'>Property:</h5>
2316    * <ul class='spaced-list'>
2317    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_resourceResolver REST_resourceResolver}
2318    *    <li><b>Name:</b>  <js>"RestContext.resourceResolver.o"</js>
2319    *    <li><b>Data type:</b>
2320    *       <ul>
2321    *          <li>{@link org.apache.juneau.rest.RestResourceResolver}
2322    *          <li><c>Class&lt;{@link org.apache.juneau.rest.RestResourceResolver}&gt;</c>
2323    *       </ul>
2324    *    <li><b>Default:</b>  {@link org.apache.juneau.rest.BasicRestResourceResolver}
2325    *    <li><b>Session property:</b>  <jk>false</jk>
2326    *    <li><b>Annotations:</b>
2327    *       <ul>
2328    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#resourceResolver()}
2329    *       </ul>
2330    *    <li><b>Methods:</b>
2331    *       <ul>
2332    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#resourceResolver(Class)}
2333    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#resourceResolver(RestResourceResolver)}
2334    *       </ul>
2335    * </ul>
2336    *
2337    * <h5 class='section'>Description:</h5>
2338    * <p>
2339    * The resolver used for resolving instances of child resources.
2340    *
2341    * <p>
2342    * Can be used to provide customized resolution of REST resource class instances (e.g. resources retrieve from Spring).
2343    *
2344    * <h5 class='section'>Example:</h5>
2345    * <p class='bcode w800'>
2346    *    <jc>// Our custom resource resolver. </jc>
2347    *    <jk>public class</jk> MyResourceResolver <jk>extends</jk> RestResourceResolverSimple {
2348    *
2349    *       <ja>@Override</ja>
2350    *       <jk>public</jk> Object resolve(Class&lt;?&gt; resourceType, RestContextBuilder builder) <jk>throws</jk> Exception {
2351    *          Object resource = <jsm>findOurResourceSomehow</jsm>(resourceType);
2352    *
2353    *          <jc>// If we can't resolve it, use default resolution.</jc>
2354    *          <jk>if</jk> (resource == <jk>null</jk>)
2355    *             resource = <jk>super</jk>.resolve(resourceType, builder);
2356    *
2357    *          <jk>return</jk> resource;
2358    *       }
2359    *    }
2360    *
2361    *    <jc>// Option #1 - Defined via annotation.</jc>
2362    *    <ja>@Rest</ja>(resourceResolver=MyResourceResolver.<jk>class</jk>)
2363    *    <jk>public class</jk> MyResource {
2364    *
2365    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2366    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2367    *
2368    *          <jc>// Using method on builder.</jc>
2369    *          builder.resourceResolver(MyResourceResolver.<jk>class</jk>);
2370    *
2371    *          <jc>// Same, but using property.</jc>
2372    *          builder.set(<jsf>REST_resourceResolver</jsf>, MyResourceResolver.<jk>class</jk>);
2373    *       }
2374    *
2375    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2376    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2377    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2378    *          builder.resourceResolver(MyResourceResolver.<jk>class</jk>);
2379    *       }
2380    *    }
2381    * </p>
2382    *
2383    * <ul class='notes'>
2384    *    <li>
2385    *       Unless overridden, resource resolvers are inherited from ascendant resources.
2386    *    <li>
2387    *       The resource class itself will be used if it implements the {@link RestResourceResolver} interface and not
2388    *       explicitly overridden via this annotation.
2389    *    <li>
2390    *       The {@link RestServlet} and {@link BasicRest} classes implement the {@link RestResourceResolver} interface with the same
2391    *       functionality as {@link BasicRestResourceResolver} that gets used if not overridden by this annotation.
2392    *       <br>Subclasses can also alter the behavior by overriding these methods.
2393    *    <li>
2394    *       When defined as a class, the implementation must have one of the following constructors:
2395    *       <ul>
2396    *          <li><code><jk>public</jk> T(RestContext)</code>
2397    *          <li><code><jk>public</jk> T()</code>
2398    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
2399    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
2400    *       </ul>
2401    *    <li>
2402    *       Inner classes of the REST resource class are allowed.
2403    * </ul>
2404    *
2405    * <ul class='seealso'>
2406    *    <li class='link'>{@doc RestResourceResolvers}
2407    *    <li class='link'>{@doc RestInjection}
2408    * </ul>
2409    */
2410   public static final String REST_resourceResolver = PREFIX + ".resourceResolver.o";
2411
2412   /**
2413    * Configuration property:  Response handlers.
2414    *
2415    * <h5 class='section'>Property:</h5>
2416    * <ul class='spaced-list'>
2417    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_responseHandlers REST_responseHandlers}
2418    *    <li><b>Name:</b>  <js>"RestContext.responseHandlers.lo"</js>
2419    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.rest.ResponseHandler}|Class&lt;{@link org.apache.juneau.rest.ResponseHandler}&gt;&gt;</c>
2420    *    <li><b>Default:</b>  empty list
2421    *    <li><b>Session property:</b>  <jk>false</jk>
2422    *    <li><b>Annotations:</b>
2423    *       <ul>
2424    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#responseHandlers()}
2425    *       </ul>
2426    *    <li><b>Methods:</b>
2427    *       <ul>
2428    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#responseHandlers(Class...)}
2429    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#responseHandlers(ResponseHandler...)}
2430    *       </ul>
2431    * </ul>
2432    *
2433    * <h5 class='section'>Description:</h5>
2434    * <p>
2435    * Specifies a list of {@link ResponseHandler} classes that know how to convert POJOs returned by REST methods or
2436    * set via {@link RestResponse#setOutput(Object)} into appropriate HTTP responses.
2437    *
2438    * <p>
2439    * By default, the following response handlers are provided out-of-the-box:
2440    * <ul>
2441    *    <li class='jc'>{@link ReaderHandler} - {@link Reader} objects.
2442    *    <li class='jc'>{@link InputStreamHandler} - {@link InputStream} objects.
2443    *    <li class='jc'>{@link DefaultHandler} - All other POJOs.
2444    * </ul>
2445    *
2446    * <h5 class='section'>Example:</h5>
2447    * <p class='bcode w800'>
2448    *    <jc>// Our custom response handler for MySpecialObject objects. </jc>
2449    *    <jk>public class</jk> MyResponseHandler <jk>implements</jk> ResponseHandler {
2450    *
2451    *       <ja>@Override</ja>
2452    *       <jk>public boolean</jk> handle(RestRequest req, RestResponse res, Object output) <jk>throws</jk> IOException, RestException {
2453    *          <jk>if</jk> (output <jk>instanceof</jk> MySpecialObject) {
2454    *             <jk>try</jk> (Writer w = res.getNegotiatedWriter()) {
2455    *                <jc>//Pipe it to the writer ourselves.</jc>
2456    *             }
2457    *             <jk>return true</jk>;  <jc>// We handled it.</jc>
2458    *          }
2459    *          <jk>return false</jk>; <jc>// We didn't handle it.</jc>
2460    *       }
2461    *    }
2462    *
2463    *    <jc>// Option #1 - Defined via annotation.</jc>
2464    *    <ja>@Rest</ja>(responseHandlers=MyResponseHandler.<jk>class</jk>)
2465    *    <jk>public class</jk> MyResource {
2466    *
2467    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2468    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2469    *
2470    *          <jc>// Using method on builder.</jc>
2471    *          builder.responseHandlers(MyResponseHandler.<jk>class</jk>);
2472    *
2473    *          <jc>// Same, but using property.</jc>
2474    *          builder.addTo(<jsf>REST_responseHandlers</jsf>, MyResponseHandler.<jk>class</jk>);
2475    *       }
2476    *
2477    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2478    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2479    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2480    *          builder.responseHandlers(MyResponseHandler.<jk>class</jk>);
2481    *       }
2482    *
2483    *       <ja>@RestMethod</ja>(...)
2484    *       <jk>public</jk> Object myMethod() {
2485    *          <jc>// Return a special object for our handler.</jc>
2486    *          <jk>return new</jk> MySpecialObject();
2487    *       }
2488    *    }
2489    * </p>
2490    *
2491    * <ul class='notes'>
2492    *    <li>
2493    *       Response handlers resolvers are always inherited from ascendant resources.
2494    *    <li>
2495    *       When defined as a class, the implementation must have one of the following constructors:
2496    *       <ul>
2497    *          <li><code><jk>public</jk> T(RestContext)</code>
2498    *          <li><code><jk>public</jk> T()</code>
2499    *          <li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>
2500    *          <li><code><jk>public static</jk> T <jsm>create</jsm>()</code>
2501    *       </ul>
2502    *    <li>
2503    *       Inner classes of the REST resource class are allowed.
2504    * </ul>
2505    */
2506   public static final String REST_responseHandlers = PREFIX + ".responseHandlers.lo";
2507
2508   /**
2509    * Configuration property:  Declared roles.
2510    *
2511    * <h5 class='section'>Property:</h5>
2512    * <ul class='spaced-list'>
2513    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_rolesDeclared REST_rolesDeclared}
2514    *    <li><b>Name:</b>  <js>"RestContext.rolesDeclared.ss"</js>
2515    *    <li><b>Data type:</b>  <c>Set&lt;String&gt;</c>
2516    *    <li><b>System property:</b>  <c>RestContext.rolesDeclared</c>
2517    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_ROLESDECLARED</c>
2518    *    <li><b>Default:</b>  empty list
2519    *    <li><b>Session property:</b>  <jk>false</jk>
2520    *    <li><b>Annotations:</b>
2521    *       <ul>
2522    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#rolesDeclared()}
2523    *       </ul>
2524    *    <li><b>Methods:</b>
2525    *       <ul>
2526    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#rolesDeclared(String...)}
2527    *       </ul>
2528    * </ul>
2529    *
2530    *
2531    * <h5 class='section'>Description:</h5>
2532    * <p>
2533    * A comma-delimited list of all possible user roles.
2534    *
2535    * <p>
2536    * Used in conjunction with {@link RestContextBuilder#roleGuard(String)} is used with patterns.
2537    *
2538    * <h5 class='section'>Example:</h5>
2539    * <p class='bcode w800'>
2540    *    <ja>@Rest</ja>(
2541    *       rolesDeclared=<js>"ROLE_ADMIN,ROLE_READ_WRITE,ROLE_READ_ONLY,ROLE_SPECIAL"</js>,
2542    *       roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE &amp;&amp; ROLE_SPECIAL)"</js>
2543    *    )
2544    *    <jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
2545    *       ...
2546    *    }
2547    * </p>
2548    *
2549    * <ul class='seealso'>
2550    *    <li class='jf'>{@link RestContext#REST_rolesDeclared}
2551    * </ul>
2552    */
2553   public static final String REST_rolesDeclared = PREFIX + ".rolesDeclared.ss";
2554
2555   /**
2556    * Configuration property:  Role guard.
2557    *
2558    * <h5 class='section'>Property:</h5>
2559    * <ul class='spaced-list'>
2560    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_roleGuard REST_roleGuard}
2561    *    <li><b>Name:</b>  <js>"RestContext.roleGuard.ss"</js>
2562    *    <li><b>Data type:</b>  <c>Set&lt;String&gt;</c>
2563    *    <li><b>System property:</b>  <c>RestContext.roleGuard</c>
2564    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_ROLEGUARD</c>
2565    *    <li><b>Default:</b>  empty set
2566    *    <li><b>Session property:</b>  <jk>false</jk>
2567    *    <li><b>Annotations:</b>
2568    *       <ul>
2569    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#roleGuard()}
2570    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#roleGuard()}
2571    *       </ul>
2572    *    <li><b>Methods:</b>
2573    *       <ul>
2574    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#roleGuard(String)}
2575    *       </ul>
2576    * </ul>
2577    *
2578    * <h5 class='section'>Description:</h5>
2579    * <p>
2580    * An expression defining if a user with the specified roles are allowed to access methods on this class.
2581    *
2582    * <h5 class='section'>Example:</h5>
2583    * <p class='bcode w800'>
2584    *    <ja>@Rest</ja>(
2585    *       path=<js>"/foo"</js>,
2586    *       roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE &amp;&amp; ROLE_SPECIAL)"</js>
2587    *    )
2588    *    <jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
2589    *       ...
2590    *    }
2591    * </p>
2592    *
2593    * <ul class='notes'>
2594    *    <li>
2595    *       Supports any of the following expression constructs:
2596    *       <ul>
2597    *          <li><js>"foo"</js> - Single arguments.
2598    *          <li><js>"foo,bar,baz"</js> - Multiple OR'ed arguments.
2599    *          <li><js>"foo | bar | bqz"</js> - Multiple OR'ed arguments, pipe syntax.
2600    *          <li><js>"foo || bar || bqz"</js> - Multiple OR'ed arguments, Java-OR syntax.
2601    *          <li><js>"fo*"</js> - Patterns including <js>'*'</js> and <js>'?'</js>.
2602    *          <li><js>"fo* &amp; *oo"</js> - Multiple AND'ed arguments, ampersand syntax.
2603    *          <li><js>"fo* &amp;&amp; *oo"</js> - Multiple AND'ed arguments, Java-AND syntax.
2604    *          <li><js>"fo* || (*oo || bar)"</js> - Parenthesis.
2605    *       </ul>
2606    *    <li>
2607    *       AND operations take precedence over OR operations (as expected).
2608    *    <li>
2609    *       Whitespace is ignored.
2610    *    <li>
2611    *       <jk>null</jk> or empty expressions always match as <jk>false</jk>.
2612    *    <li>
2613    *       If patterns are used, you must specify the list of declared roles using {@link Rest#rolesDeclared()} or {@link RestContext#REST_rolesDeclared}.
2614    *    <li>
2615    *       Supports {@doc RestSvlVariables}
2616    *       (e.g. <js>"$L{my.localized.variable}"</js>).
2617    *    <li>
2618    *       Role guards defined at both the class and method level must both pass.
2619    * </ul>
2620    *
2621    * <ul class='seealso'>
2622    *    <li class='jf'>{@link RestContext#REST_roleGuard}
2623    * </ul>
2624    */
2625   public static final String REST_roleGuard = PREFIX + ".roleGuard.ss";
2626
2627   /**
2628    * Configuration property:  Serializers.
2629    *
2630    * <h5 class='section'>Property:</h5>
2631    * <ul class='spaced-list'>
2632    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_serializers REST_serializers}
2633    *    <li><b>Name:</b>  <js>"RestContext.serializers.lo"</js>
2634    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.serializer.Serializer}|Class&lt;{@link org.apache.juneau.serializer.Serializer}&gt;&gt;</c>
2635    *    <li><b>Default:</b>  empty list
2636    *    <li><b>Session property:</b>  <jk>false</jk>
2637    *    <li><b>Annotations:</b>
2638    *       <ul>
2639    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#serializers()}
2640    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#serializers()}
2641    *       </ul>
2642    *    <li><b>Methods:</b>
2643    *       <ul>
2644    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#serializers(Object...)}
2645    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#serializers(Class...)}
2646    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#serializersReplace(Object...)}
2647    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#serializersReplace(Class...)}
2648    *       </ul>
2649    * </ul>
2650    *
2651    * <h5 class='section'>Description:</h5>
2652    * <p>
2653    * Adds class-level serializers to this resource.
2654    *
2655    * <p>
2656    * Serializer are used to convert POJOs to HTTP response bodies.
2657    * <br>Any of the Juneau framework serializers can be used in this setting.
2658    * <br>The serializer selected is based on the request <c>Accept</c> header matched against the values returned by the following method
2659    * using a best-match algorithm:
2660    * <ul class='javatree'>
2661    *    <li class='jm'>{@link Serializer#getMediaTypeRanges()}
2662    * </ul>
2663    *
2664    * <h5 class='section'>Example:</h5>
2665    * <p class='bcode w800'>
2666    *    <jc>// Option #1 - Defined via annotation.</jc>
2667    *    <ja>@Rest</ja>(serializers={JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>})
2668    *    <jk>public class</jk> MyResource {
2669    *
2670    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2671    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2672    *
2673    *          <jc>// Using method on builder.</jc>
2674    *          builder.serializers(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>);
2675    *
2676    *          <jc>// Same, but use pre-instantiated parsers.</jc>
2677    *          builder.serializers(JsonSerializer.<jsf>DEFAULT</jsf>, XmlSerializer.<jsf>DEFAULT</jsf>);
2678    *
2679    *          <jc>// Same, but using property.</jc>
2680    *          builder.set(<jsf>REST_serializers</jsf>, JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>);
2681    *       }
2682    *
2683    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2684    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2685    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2686    *          builder.serializers(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>);
2687    *       }
2688    *
2689    *       <jc>// Override at the method level.</jc>
2690    *       <ja>@RestMethod</ja>(serializers={HtmlSerializer.<jk>class</jk>})
2691    *       <jk>public</jk> MyPojo myMethod() {
2692    *          <jc>// Return a POJO to be serialized.</jc>
2693    *          <jk>return new</jk> MyPojo();
2694    *       }
2695    *    }
2696    * </p>
2697    *
2698    * <ul class='notes'>
2699    *    <li>
2700    *       When defined as a class, properties/transforms defined on the resource/method are inherited.
2701    *    <li>
2702    *       When defined as an instance, properties/transforms defined on the resource/method are NOT inherited.
2703    *    <li>
2704    *       Typically, you'll want your resource to extend directly from {@link BasicRestServlet} which comes
2705    *       preconfigured with the following serializers:
2706    *       <ul>
2707    *          <li class='jc'>{@link HtmlDocSerializer}
2708    *          <li class='jc'>{@link HtmlStrippedDocSerializer}
2709    *          <li class='jc'>{@link HtmlSchemaDocSerializer}
2710    *          <li class='jc'>{@link JsonSerializer}
2711    *          <li class='jc'>{@link SimpleJsonSerializer}
2712    *          <li class='jc'>{@link JsonSchemaSerializer}
2713    *          <li class='jc'>{@link XmlDocSerializer}
2714    *          <li class='jc'>{@link UonSerializer}
2715    *          <li class='jc'>{@link UrlEncodingSerializer}
2716    *          <li class='jc'>{@link MsgPackSerializer}
2717    *          <li class='jc'>{@link SoapXmlSerializer}
2718    *          <li class='jc'>{@link PlainTextSerializer}
2719    *       </ul>
2720    * </ul>
2721    *
2722    * <ul class='seealso'>
2723    *    <li class='link'>{@doc RestSerializers}
2724    * </ul>
2725    * <p>
2726    */
2727   public static final String REST_serializers = PREFIX + ".serializers.lo";
2728
2729   /**
2730    * Configuration property:  Static file response headers.
2731    *
2732    * <h5 class='section'>Property:</h5>
2733    * <ul class='spaced-list'>
2734    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_staticFileResponseHeaders REST_staticFileResponseHeaders}
2735    *    <li><b>Name:</b>  <js>"RestContext.staticFileResponseHeaders.omo"</js>
2736    *    <li><b>Data type:</b>  <c>Map&lt;String,String&gt;</c>
2737    *    <li><b>System property:</b>  <c>RestContext.staticFileResponseHeaders</c>
2738    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_STATICFILERESPONSEHEADERS</c>
2739    *    <li><b>Default:</b>  <code>{<js>'Cache-Control'</js>: <js>'max-age=86400, public</js>}</code>
2740    *    <li><b>Session property:</b>  <jk>false</jk>
2741    *    <li><b>Annotations:</b>
2742    *       <ul>
2743    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#staticFileResponseHeaders()}
2744    *       </ul>
2745    *    <li><b>Methods:</b>
2746    *       <ul>
2747    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFileResponseHeaders(Map)}
2748    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFileResponseHeaders(String...)}
2749    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFileResponseHeader(String,String)}
2750    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFileResponseHeadersReplace(Map)}
2751    *       </ul>
2752    * </ul>
2753    *
2754    * <h5 class='section'>Description:</h5>
2755    * <p>
2756    * Used to customize the headers on responses returned for statically-served files.
2757    *
2758    * <h5 class='section'>Example:</h5>
2759    * <p class='bcode w800'>
2760    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
2761    *    <ja>@Rest</ja>(
2762    *       staticFileResponseHeaders={
2763    *          <js>"Cache-Control: $C{REST/cacheControl,nocache}"</js>,
2764    *          <js>"My-Header: $C{REST/myHeaderValue}"</js>
2765    *       }
2766    *    )
2767    *    <jk>public class</jk> MyResource {
2768    *
2769    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2770    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2771    *
2772    *          <jc>// Using method on builder.</jc>
2773    *          builder
2774    *             .staticFileResponseHeader(<js>"Cache-Control"</js>, <js>"nocache"</js>);
2775    *             .staticFileResponseHeaders(<js>"My-Header: foo"</js>);
2776    *
2777    *          <jc>// Same, but using property.</jc>
2778    *          builder
2779    *             .addTo(<jsf>REST_staticFileResponseHeaders</jsf>, <js>"Cache-Control"</js>, <js>"nocache"</js>);
2780    *             .addTo(<jsf>REST_staticFileResponseHeaders</jsf>, <js>"My-Header"</js>, <js>"foo"</js>);
2781    *       }
2782    *
2783    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2784    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2785    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2786    *          builder.staticFileResponseHeader(<js>"Cache-Control"</js>, <js>"nocache"</js>);
2787    *       }
2788    *    }
2789    * </p>
2790    *
2791    * <p>
2792    * Note that headers can also be specified per path-mapping via the {@link Rest#staticFiles() @Rest(staticFiles)} annotation.
2793    * <p class='bcode w800'>
2794    *    <ja>@Rest</ja>(
2795    *       staticFiles={
2796    *          <js>"htdocs:docs:{'Cache-Control':'max-age=86400, public'}"</js>
2797    *       }
2798    *    )
2799    * </p>
2800    *
2801    * <ul class='seealso'>
2802    *    <li class='jf'>{@link #REST_staticFiles} for information about statically-served files.
2803    * </ul>
2804    */
2805   public static final String REST_staticFileResponseHeaders = PREFIX + ".staticFileResponseHeaders.omo";
2806
2807   /**
2808    * Configuration property:  Static file mappings.
2809    *
2810    * <h5 class='section'>Property:</h5>
2811    * <ul class='spaced-list'>
2812    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_staticFiles REST_staticFiles}
2813    *    <li><b>Name:</b>  <js>"RestContext.staticFiles.lo"</js>
2814    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.rest.StaticFileMapping}&gt;</c>
2815    *    <li><b>Default:</b>  <jk>null</jk>
2816    *    <li><b>Session property:</b>  <jk>false</jk>
2817    *    <li><b>Annotations:</b>
2818    *       <ul>
2819    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#staticFiles()}
2820    *       </ul>
2821    *    <li><b>Methods:</b>
2822    *       <ul>
2823    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFiles(String)},
2824    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFiles(Class,String)}
2825    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFiles(String,String)}
2826    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFiles(Class,String,String)}
2827    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#staticFiles(StaticFileMapping...)}
2828    *       </ul>
2829    * </ul>
2830    *
2831    * <h5 class='section'>Description:</h5>
2832    * <p>
2833    * Used to define paths and locations of statically-served files such as images or HTML documents
2834    * from the classpath or file system.
2835    *
2836    * <p>
2837    * The format of the value is one of the following:
2838    * <ol class='spaced-list'>
2839    *    <li><js>"path:location"</js>
2840    *    <li><js>"path:location:headers"</js>
2841    * </ol>
2842    *
2843    * <p>
2844    * An example where this class is used is in the {@link Rest#staticFiles} annotation:
2845    * <p class='bcode w800'>
2846    *    <jk>package</jk> com.foo.mypackage;
2847    *
2848    *    <ja>@Rest</ja>(
2849    *       path=<js>"/myresource"</js>,
2850    *       staticFiles={
2851    *          <js>"htdocs:docs"</js>,
2852    *          <js>"styles:styles"</js>
2853    *       }
2854    *    )
2855    *    <jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet {...}
2856    * </p>
2857    *
2858    * <p>
2859    * In the example above, given a GET request to the following URL...
2860    * <p class='bcode w800'>
2861    *    /myresource/htdocs/foobar.html
2862    * </p>
2863    * <br>...the servlet will attempt to find the <c>foobar.html</c> file in the following location:
2864    * <ol class='spaced-list'>
2865    *    <li><c>com.foo.mypackage.docs</c> package.
2866    * </ol>
2867    *
2868    * <p>
2869    * The location is interpreted as an absolute path if it starts with <js>'/'</js>.
2870    * <p class='bcode w800'>
2871    *    <ja>@Rest</ja>(
2872    *       staticFiles={
2873    *          <js>"htdocs:/docs"</js>
2874    *       }
2875    *    )
2876    * </p>
2877    * <p>
2878    * In the example above, given a GET request to the following URL...
2879    * <p class='bcode w800'>
2880    *    /myresource/htdocs/foobar.html
2881    * </p>
2882    * <br>...the servlet will attempt to find the <c>foobar.html</c> file in the following location:
2883    * <ol class='spaced-list'>
2884    *    <li><c>docs</c> package (typically under <c>src/main/resources/docs</c> in your workspace).
2885    *    <li><c>[working-dir]/docs</c> directory at runtime.
2886    * </ol>
2887    *
2888    * <p>
2889    * Response headers can be specified for served files by adding a 3rd section that consists of a {@doc SimplifiedJson} object.
2890    * <p class='bcode w800'>
2891    *    <ja>@Rest</ja>(
2892    *       staticFiles={
2893    *          <js>"htdocs:docs:{'Cache-Control':'max-age=86400, public'}"</js>
2894    *       }
2895    *    )
2896    * </p>
2897    *
2898    * <p>
2899    * The same path can map to multiple locations.  Files are searched in the order
2900    * <p class='bcode w800'>
2901    *    <ja>@Rest</ja>(
2902    *       staticFiles={
2903    *          <jc>// Search in absolute location '/htdocs/folder' before location 'htdocs.package' relative to servlet package.</jc>
2904    *          <js>"htdocs:/htdocs/folder,htdocs:htdocs.package"</js>
2905    *       }
2906    *    )
2907    * </p>
2908    *
2909    * <ul class='seealso'>
2910    *    <li class='jf'>{@link #REST_classpathResourceFinder} for configuring how classpath resources are located and retrieved.
2911    *    <li class='jf'>{@link #REST_mimeTypes} for configuring the media types based on file extension.
2912    *    <li class='jf'>{@link #REST_staticFileResponseHeaders} for configuring response headers on statically served files.
2913    *    <li class='jf'>{@link #REST_useClasspathResourceCaching} for configuring static file caching.
2914    *    <li class='jm'>{@link RestContext#getClasspathResource(String,Locale)} for retrieving static files.
2915    * </ul>
2916    *
2917    * <ul class='notes'>
2918    *    <li>
2919    *       Mappings are cumulative from super classes.
2920    *    <li>
2921    *       Child resources can override mappings made on parent class resources.
2922    *       <br>When both parent and child resources map against the same path, files will be search in the child location
2923    *       and then the parent location.
2924    * </ul>
2925    */
2926   public static final String REST_staticFiles = PREFIX + ".staticFiles.lo";
2927
2928   /**
2929    * Configuration property:  Supported accept media types.
2930    *
2931    * <h5 class='section'>Property:</h5>
2932    * <ul class='spaced-list'>
2933    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_produces REST_produces}
2934    *    <li><b>Name:</b>  <js>"RestContext.produces.ls"</js>
2935    *    <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
2936    *    <li><b>System property:</b>  <c>RestContext.produces</c>
2937    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_PRODUCES</c>
2938    *    <li><b>Default:</b>  empty list
2939    *    <li><b>Session property:</b>  <jk>false</jk>
2940    *    <li><b>Annotations:</b>
2941    *       <ul>
2942    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#produces()}
2943    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#produces()}
2944    *       </ul>
2945    *    <li><b>Methods:</b>
2946    *       <ul>
2947    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#produces(String...)}
2948    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#produces(MediaType...)}
2949    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#producesReplace(String...)}
2950    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#producesReplace(MediaType...)}
2951    *       </ul>
2952    * </ul>
2953    *
2954    * <h5 class='section'>Description:</h5>
2955    * <p>
2956    * Overrides the media types inferred from the serializers that identify what media types can be produced by the resource.
2957    * <br>An example where this might be useful if you have serializers registered that handle media types that you
2958    * don't want exposed in the Swagger documentation.
2959    *
2960    * <h5 class='section'>Example:</h5>
2961    * <p class='bcode w800'>
2962    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
2963    *    <ja>@Rest</ja>(produces={<js>"$C{REST/supportedProduces,application/json}"</js>})
2964    *    <jk>public class</jk> MyResource {
2965    *
2966    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
2967    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
2968    *
2969    *          <jc>// Using method on builder.</jc>
2970    *          builder.produces(<jk>false</jk>, <js>"application/json"</js>)
2971    *
2972    *          <jc>// Same, but using property.</jc>
2973    *          builder.set(<jsf>REST_produces</jsf>, <js>"application/json"</js>);
2974    *       }
2975    *
2976    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
2977    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
2978    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
2979    *          builder.produces(<jk>false</jk>, <js>"application/json"</js>);
2980    *       }
2981    *    }
2982    * </p>
2983    *
2984    * <p>
2985    * This affects the returned values from the following:
2986    * <ul class='javatree'>
2987    *    <li class='jm'>{@link RestContext#getProduces() RestContext.getProduces()}
2988    *    <li class='jm'>{@link RestRequest#getProduces()}
2989    *    <li class='jm'>{@link RestInfoProvider#getSwagger(RestRequest)} - Affects produces field.
2990    * </ul>
2991    */
2992   public static final String REST_produces = PREFIX + ".produces.ls";
2993
2994   /**
2995    * Configuration property:  Properties.
2996    *
2997    * <h5 class='section'>Property:</h5>
2998    * <ul class='spaced-list'>
2999    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_properties REST_properties}
3000    *    <li><b>Name:</b>  <js>"RestContext.properties.sms"</js>
3001    *    <li><b>Data type:</b>  <c>Map&lt;String,String&gt;</c>
3002    *    <li><b>System property:</b>  <c>RestContext.properties</c>
3003    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_PROPERTIES</c>
3004    *    <li><b>Default:</b>  empty map
3005    *    <li><b>Session property:</b>  <jk>false</jk>
3006    *    <li><b>Annotations:</b>
3007    *       <ul>
3008    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#properties()}
3009    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#flags()}
3010    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#properties()}
3011    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#flags()}
3012    *       </ul>
3013    *    <li><b>Methods:</b>
3014    *       <ul>
3015    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#property(String,Object)}
3016    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#properties(Map)}
3017    *       </ul>
3018    * </ul>
3019    *
3020    * <h5 class='section'>Description:</h5>
3021    * <p>
3022    * Shortcut to add properties to the bean contexts of all serializers and parsers on all methods in the class.
3023    *
3024    * <p>
3025    * Any of the properties defined on {@link RestContext} or any of the serializers and parsers can be specified.
3026    *
3027    * <p>
3028    * Property values will be converted to the appropriate type.
3029    *
3030    * <ul class='notes'>
3031    *    <li>
3032    *       Supports {@doc RestSvlVariables}
3033    *       (e.g. <js>"$L{my.localized.variable}"</js>).
3034    * </ul>
3035    *
3036    * <ul class='seealso'>
3037    *    <li class='jm'>{@link RestContextBuilder#set(String,Object)}
3038    *    <li class='jm'>{@link RestContextBuilder#set(java.util.Map)}
3039    * </ul>
3040    */
3041   public static final String REST_properties = PREFIX + ".properties.sms";
3042
3043   /**
3044    * Configuration property:  Supported content media types.
3045    *
3046    * <h5 class='section'>Property:</h5>
3047    * <ul class='spaced-list'>
3048    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_consumes REST_consumes}
3049    *    <li><b>Name:</b>  <js>"RestContext.consumes.ls"</js>
3050    *    <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
3051    *    <li><b>System property:</b>  <c>RestContext.consumes</c>
3052    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_CONSUMES</c>
3053    *    <li><b>Default:</b>  empty list
3054    *    <li><b>Session property:</b>  <jk>false</jk>
3055    *    <li><b>Annotations:</b>
3056    *       <ul>
3057    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#consumes()}
3058    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#consumes()}
3059    *       </ul>
3060    *    <li><b>Methods:</b>
3061    *       <ul>
3062    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#consumes(String...)}
3063    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#consumes(MediaType...)}
3064    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#consumesReplace(String...)}
3065    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#consumesReplace(MediaType...)}
3066    *       </ul>
3067    * </ul>
3068    *
3069    * <h5 class='section'>Description:</h5>
3070    * <p>
3071    * Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource.
3072    * <br>An example where this might be useful if you have parsers registered that handle media types that you
3073    * don't want exposed in the Swagger documentation.
3074    *
3075    * <h5 class='section'>Example:</h5>
3076    * <p class='bcode w800'>
3077    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3078    *    <ja>@Rest</ja>(consumes={<js>"$C{REST/supportedConsumes,application/json}"</js>})
3079    *    <jk>public class</jk> MyResource {
3080    *
3081    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3082    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
3083    *
3084    *          <jc>// Using method on builder.</jc>
3085    *          builder.consumes(<jk>false</jk>, <js>"application/json"</js>)
3086    *
3087    *          <jc>// Same, but using property.</jc>
3088    *          builder.set(<jsf>REST_consumes</jsf>, <js>"application/json"</js>);
3089    *       }
3090    *
3091    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3092    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3093    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
3094    *          builder.consumes(<jk>false</jk>, <js>"application/json"</js>);
3095    *       }
3096    *    }
3097    * </p>
3098    *
3099    * <p>
3100    * This affects the returned values from the following:
3101    * <ul class='javatree'>
3102    *    <li class='jm'>{@link RestContext#getConsumes() RestContext.getConsumes()}
3103    *    <li class='jm'>{@link RestRequest#getConsumes()}
3104    *    <li class='jm'>{@link RestInfoProvider#getSwagger(RestRequest)} - Affects consumes field.
3105    * </ul>
3106    */
3107   public static final String REST_consumes = PREFIX + ".consumes.ls";
3108
3109   /**
3110    * Configuration property:  REST context class.
3111    *
3112    * <review>NEEDS REVIEW</review>
3113    *
3114    * <h5 class='section'>Property:</h5>
3115    * <ul class='spaced-list'>
3116    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_context REST_context}
3117    *    <li><b>Name:</b>  <js>"RestContext.context.c"</js>
3118    *    <li><b>Data type:</b>  <c>Class&lt;? extends {@link org.apache.juneau.rest.RestContext}&gt;</c>
3119    *    <li><b>Default:</b>  {@link org.apache.juneau.rest.RestContext}
3120    *    <li><b>Session property:</b>  <jk>false</jk>
3121    *    <li><b>Annotations:</b>
3122    *       <ul>
3123    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#context()}
3124    *       </ul>
3125    *    <li><b>Methods:</b>
3126    *       <ul>
3127    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#context(Class)}
3128    *       </ul>
3129    * </ul>
3130    *
3131    * <h5 class='section'>Description:</h5>
3132    * <p>
3133    * Allows you to extend the {@link RestContext} class to modify how any of the methods are implemented.
3134    *
3135    * <p>
3136    * The subclass must provide the following:
3137    * <ul>
3138    *    <li>A public constructor that takes in one parameter that should be passed to the super constructor:  {@link RestContextBuilder}.
3139    * </ul>
3140    *
3141    * <h5 class='section'>Example:</h5>
3142    * <p class='bcode w800'>
3143    *    <jc>// Our extended context class</jc>
3144    *    <jk>public</jk> MyRestContext <jk>extends</jk> RestContext {
3145    *       <jk>public</jk> MyRestContext(RestContextBuilder <jv>builder</jv>) {
3146    *          <jk>super</jk>(<jv>builder</jv>);
3147    *       }
3148    *
3149    *       <jc>// Override any methods.</jc>
3150    *    }
3151    * </p>
3152    * <p class='bcode w800'>
3153    *    <jc>// Option #1 - Defined via annotation.</jc>
3154    *    <ja>@Rest</ja>(context=MyRestContext.<jk>class</jk>)
3155    *    <jk>public class</jk> MyResource {
3156    *       ...
3157    *
3158    *       <jc>// Option #2 - Defined via builder passed in through init method.</jc>
3159    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3160    *       <jk>public void</jk> init(RestContextBuilder <jv>builder</jv>) <jk>throws</jk> Exception {
3161    *          <jv>builder</jv>.context(MyRestContext.<jk>class</jk>);
3162    *       }
3163    *    }
3164    * </p>
3165    */
3166   public static final String REST_context = PREFIX + ".context.c";
3167
3168   /**
3169    * Configuration property:  Use classpath resource caching.
3170    *
3171    * <h5 class='section'>Property:</h5>
3172    * <ul class='spaced-list'>
3173    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_useClasspathResourceCaching REST_useClasspathResourceCaching}
3174    *    <li><b>Name:</b>  <js>"RestContext.useClasspathResourceCaching.b"</js>
3175    *    <li><b>Data type:</b>  <jk>boolean</jk>
3176    *    <li><b>System property:</b>  <c>RestContext.useClasspathResourceCaching</c>
3177    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_USECLASSPATHRESOURCECACHING</c>
3178    *    <li><b>Default:</b>  <jk>true</jk>
3179    *    <li><b>Session property:</b>  <jk>false</jk>
3180    *    <li><b>Annotations:</b>
3181    *       <ul>
3182    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#useClasspathResourceCaching()}
3183    *       </ul>
3184    *    <li><b>Methods:</b>
3185    *       <ul>
3186    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#useClasspathResourceCaching(boolean)}
3187    *       </ul>
3188    * </ul>
3189    *
3190    * <h5 class='section'>Description:</h5>
3191    * <p>
3192    * When enabled, resources retrieved via {@link RestContext#getClasspathResource(String, Locale)} (and related
3193    * methods) will be cached in memory to speed subsequent lookups.
3194    *
3195    * <h5 class='section'>Example:</h5>
3196    * <p class='bcode w800'>
3197    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3198    *    <ja>@Rest</ja>(useClasspathResourceCaching=<js>"$C{REST/useClasspathResourceCaching,false}"</js>)
3199    *    <jk>public class</jk> MyResource {
3200    *
3201    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3202    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
3203    *
3204    *          <jc>// Using method on builder.</jc>
3205    *          builder.useClasspathResourceCaching(<jk>false</jk>)
3206    *
3207    *          <jc>// Same, but using property.</jc>
3208    *          builder.set(<jsf>REST_useClasspathResourceCaching</jsf>, <jk>false</jk>);
3209    *       }
3210    *
3211    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3212    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3213    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
3214    *          builder.useClasspathResourceCaching(<jk>false</jk>)
3215    *       }
3216    *    }
3217    * </p>
3218    *
3219    * <ul class='seealso'>
3220    *    <li class='jf'>{@link #REST_staticFiles} for information about static files.
3221    * </ul>
3222    */
3223   public static final String REST_useClasspathResourceCaching = PREFIX + ".useClasspathResourceCaching.b";
3224
3225   /**
3226    * Configuration property:  Use stack trace hashes.
3227    *
3228    * <div class='warn'>
3229    *    <b>Deprecated</b> - Use {@link Logging#useStackTraceHashing}
3230    * </div>
3231    */
3232   @Deprecated
3233   public static final String REST_useStackTraceHashes = PREFIX + ".useStackTraceHashes.b";
3234
3235   /**
3236    * Configuration property:  Resource URI authority path.
3237    *
3238    * <h5 class='section'>Property:</h5>
3239    * <ul class='spaced-list'>
3240    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_uriAuthority REST_uriAuthority}
3241    *    <li><b>Name:</b>  <js>"RestContext.uriAuthority.s"</js>
3242    *    <li><b>Data type:</b>  <c>String</c>
3243    *    <li><b>System property:</b>  <c>RestContext.uriAuthority</c>
3244    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_URIAUTHORITY</c>
3245    *    <li><b>Default:</b>  <jk>null</jk>
3246    *    <li><b>Session property:</b>  <jk>false</jk>
3247    *    <li><b>Annotations:</b>
3248    *       <ul>
3249    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#uriAuthority()}
3250    *       </ul>
3251    *    <li><b>Methods:</b>
3252    *       <ul>
3253    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#uriAuthority(String)}
3254    *       </ul>
3255    * </ul>
3256    *
3257    * <h5 class='section'>Description:</h5>
3258    * <p>
3259    * Overrides the authority path value for this resource and any child resources.
3260    *
3261    * <p>
3262    * Affects the following methods:
3263    * <ul class='javatree'>
3264    *    <li class='jm'>{@link RestRequest#getAuthorityPath()}
3265    * </ul>
3266    *
3267    * <p>
3268    * If you do not specify the authority, it is automatically calculated via the following:
3269    *
3270    * <p class='bcode w800'>
3271    *    String scheme = request.getScheme();
3272    *    <jk>int</jk> port = request.getServerPort();
3273    *    StringBuilder sb = <jk>new</jk> StringBuilder(request.getScheme()).append(<js>"://"</js>).append(request.getServerName());
3274    *    <jk>if</jk> (! (port == 80 &amp;&amp; <js>"http"</js>.equals(scheme) || port == 443 &amp;&amp; <js>"https"</js>.equals(scheme)))
3275    *       sb.append(<js>':'</js>).append(port);
3276    *    authorityPath = sb.toString();
3277    * </p>
3278    *
3279    * <h5 class='section'>Example:</h5>
3280    * <p class='bcode w800'>
3281    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3282    *    <ja>@Rest</ja>(
3283    *       path=<js>"/servlet"</js>,
3284    *       uriAuthority=<js>"$C{REST/authorityPathOverride,http://localhost:10000}"</js>
3285    *    )
3286    *    <jk>public class</jk> MyResource {
3287    *
3288    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3289    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
3290    *
3291    *          <jc>// Using method on builder.</jc>
3292    *          builder.uriAuthority(<js>"http://localhost:10000"</js>);
3293    *
3294    *          <jc>// Same, but using property.</jc>
3295    *          builder.set(<jsf>REST_uriAuthority</jsf>, <js>"http://localhost:10000"</js>);
3296    *       }
3297    *
3298    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3299    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3300    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
3301    *          builder.uriAuthority(<js>"http://localhost:10000"</js>);
3302    *       }
3303    *    }
3304    * </p>
3305    */
3306   public static final String REST_uriAuthority = PREFIX + ".uriAuthority.s";
3307
3308   /**
3309    * Configuration property:  Resource URI context path.
3310    *
3311    * <h5 class='section'>Property:</h5>
3312    * <ul class='spaced-list'>
3313    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_uriContext REST_uriContext}
3314    *    <li><b>Name:</b>  <js>"RestContext.uriContext.s"</js>
3315    *    <li><b>Data type:</b>  <c>String</c>
3316    *    <li><b>System property:</b>  <c>RestContext.uriContext</c>
3317    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_URICONTEXT</c>
3318    *    <li><b>Default:</b>  <jk>null</jk>
3319    *    <li><b>Session property:</b>  <jk>false</jk>
3320    *    <li><b>Annotations:</b>
3321    *       <ul>
3322    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#uriContext()}
3323    *       </ul>
3324    *    <li><b>Methods:</b>
3325    *       <ul>
3326    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#uriContext(String)}
3327    *       </ul>
3328    * </ul>
3329    *
3330    * <h5 class='section'>Description:</h5>
3331    * <p>
3332    * Overrides the context path value for this resource and any child resources.
3333    *
3334    * <p>
3335    * This setting is useful if you want to use <js>"context:/child/path"</js> URLs in child resource POJOs but
3336    * the context path is not actually specified on the servlet container.
3337    *
3338    * <p>
3339    * Affects the following methods:
3340    * <ul class='javatree'>
3341    *    <li class='jm'>{@link RestRequest#getContextPath()} - Returns the overridden context path for the resource.
3342    *    <li class='jm'>{@link RestRequest#getServletPath()} - Includes the overridden context path for the resource.
3343    * </ul>
3344    *
3345    * <h5 class='section'>Example:</h5>
3346    * <p class='bcode w800'>
3347    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3348    *    <ja>@Rest</ja>(
3349    *       path=<js>"/servlet"</js>,
3350    *       uriContext=<js>"$C{REST/contextPathOverride,/foo}"</js>
3351    *    )
3352    *    <jk>public class</jk> MyResource {
3353    *
3354    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3355    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
3356    *
3357    *          <jc>// Using method on builder.</jc>
3358    *          builder.uriContext(<js>"/foo"</js>);
3359    *
3360    *          <jc>// Same, but using property.</jc>
3361    *          builder.set(<jsf>REST_uriContext</jsf>, <js>"/foo"</js>);
3362    *       }
3363    *
3364    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3365    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3366    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
3367    *          builder.uriContext(<js>"/foo"</js>);
3368    *       }
3369    *    }
3370    * </p>
3371    */
3372   public static final String REST_uriContext = PREFIX + ".uriContext.s";
3373
3374   /**
3375    * Configuration property:  URI resolution relativity.
3376    *
3377    * <h5 class='section'>Property:</h5>
3378    * <ul class='spaced-list'>
3379    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_uriRelativity REST_uriRelativity}
3380    *    <li><b>Name:</b>  <js>"RestContext.uriRelativity.s"</js>
3381    *    <li><b>Data type:</b>  <c>String</c>
3382    *    <li><b>System property:</b>  <c>RestContext.uriRelativity</c>
3383    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_URIRELATIVITY</c>
3384    *    <li><b>Default:</b>  <js>"RESOURCE"</js>
3385    *    <li><b>Session property:</b>  <jk>false</jk>
3386    *    <li><b>Annotations:</b>
3387    *       <ul>
3388    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#uriRelativity()}
3389    *       </ul>
3390    *    <li><b>Methods:</b>
3391    *       <ul>
3392    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#uriRelativity(String)}
3393    *       </ul>
3394    * </ul>
3395    *
3396    * <h5 class='section'>Description:</h5>
3397    * <p>
3398    * Specifies how relative URIs should be interpreted by serializers.
3399    *
3400    * <p>
3401    * See {@link UriResolution} for possible values.
3402    *
3403    * <p>
3404    * Affects the following methods:
3405    * <ul class='javatree'>
3406    *    <li class='jm'>{@link RestRequest#getUriResolver()}
3407    * </ul>
3408    *
3409    * <h5 class='section'>Example:</h5>
3410    * <p class='bcode w800'>
3411    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3412    *    <ja>@Rest</ja>(
3413    *       path=<js>"/servlet"</js>,
3414    *       uriRelativity=<js>"$C{REST/uriRelativity,PATH_INFO}"</js>
3415    *    )
3416    *    <jk>public class</jk> MyResource {
3417    *
3418    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3419    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
3420    *
3421    *          <jc>// Using method on builder.</jc>
3422    *          builder.uriRelativity(<js>"PATH_INFO"</js>);
3423    *
3424    *          <jc>// Same, but using property.</jc>
3425    *          builder.set(<jsf>REST_uriRelativity</jsf>, <js>"PATH_INFO"</js>);
3426    *       }
3427    *
3428    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3429    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3430    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
3431    *          builder.uriRelativity(<js>"PATH_INFO"</js>);
3432    *       }
3433    *    }
3434    * </p>
3435    */
3436   public static final String REST_uriRelativity = PREFIX + ".uriRelativity.s";
3437
3438   /**
3439    * Configuration property:  URI resolution.
3440    *
3441    * <h5 class='section'>Property:</h5>
3442    * <ul class='spaced-list'>
3443    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_uriResolution REST_uriResolution}
3444    *    <li><b>Name:</b>  <js>"RestContext.uriResolution.s"</js>
3445    *    <li><b>Data type:</b>  <c>String</c>
3446    *    <li><b>System property:</b>  <c>RestContext.uriResolution</c>
3447    *    <li><b>Environment variable:</b>  <c>RESTCONTEXT_URIRESOLUTION</c>
3448    *    <li><b>Default:</b>  <js>"ROOT_RELATIVE"</js>
3449    *    <li><b>Session property:</b>  <jk>false</jk>
3450    *    <li><b>Annotations:</b>
3451    *       <ul>
3452    *          <li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#uriResolution()}
3453    *       </ul>
3454    *    <li><b>Methods:</b>
3455    *       <ul>
3456    *          <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#uriResolution(String)}
3457    *       </ul>
3458    * </ul>
3459    *
3460    * <h5 class='section'>Description:</h5>
3461    * <p>
3462    * Specifies how relative URIs should be interpreted by serializers.
3463    *
3464    * <p>
3465    * See {@link UriResolution} for possible values.
3466    *
3467    * <p>
3468    * Affects the following methods:
3469    * <ul class='javatree'>
3470    *    <li class='jm'>{@link RestRequest#getUriResolver()}
3471    * </ul>
3472    *
3473    * <h5 class='section'>Example:</h5>
3474    * <p class='bcode w800'>
3475    *    <jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
3476    *    <ja>@Rest</ja>(
3477    *       path=<js>"/servlet"</js>,
3478    *       uriResolution=<js>"$C{REST/uriResolution,ABSOLUTE}"</js>
3479    *    )
3480    *    <jk>public class</jk> MyResource {
3481    *
3482    *       <jc>// Option #2 - Defined via builder passed in through resource constructor.</jc>
3483    *       <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
3484    *
3485    *          <jc>// Using method on builder.</jc>
3486    *          builder.uriResolution(<js>"ABSOLUTE"</js>);
3487    *
3488    *          <jc>// Same, but using property.</jc>
3489    *          builder.set(<jsf>REST_uriResolution</jsf>, <js>"ABSOLUTE"</js>);
3490    *       }
3491    *
3492    *       <jc>// Option #3 - Defined via builder passed in through init method.</jc>
3493    *       <ja>@RestHook</ja>(<jsf>INIT</jsf>)
3494    *       <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
3495    *          builder.uriResolution(<js>"ABSOLUTE"</js>);
3496    *       }
3497    *    }
3498    * </p>
3499    */
3500   public static final String REST_uriResolution = PREFIX + ".uriResolution.s";
3501
3502   /**
3503    * Configuration property:  HTML Widgets.
3504    *
3505    * <div class='warn'>
3506    *    <b>Deprecated</b> - Use {@link HtmlDocSerializer#HTMLDOC_widgets}
3507    * </div>
3508    */
3509   @Deprecated
3510   public static final String REST_widgets = PREFIX + ".widgets.lo";
3511
3512
3513   //-------------------------------------------------------------------------------------------------------------------
3514   // Static
3515   //-------------------------------------------------------------------------------------------------------------------
3516
3517   private static final Map<Class<?>, RestContext> REGISTRY = new ConcurrentHashMap<>();
3518
3519   /**
3520    * Returns a registry of all created {@link RestContext} objects.
3521    *
3522    * @return An unmodifiable map of resource classes to {@link RestContext} objects.
3523    */
3524   public static final Map<Class<?>, RestContext> getGlobalRegistry() {
3525      return Collections.unmodifiableMap(REGISTRY);
3526   }
3527
3528// public static final Set<MethodExecStats> getGlobalExecStats() {
3529//    Set<MethodExecStats> s = new TreeSet<>();
3530//    for (RestContext rc : REGISTRY.values())
3531//       s.addAll(rc.getMethodExecStats());
3532//    return s;
3533// }
3534//
3535////  public static final Set<ExceptionStats> getGlobalExceptions() {
3536////     Set<ExceptionStats> s = new TreeSet<>();
3537////     for (RestContext rc : REGISTRY.values())
3538////        s.addAll(rc.getStackTraceDb().getClonedStackTraceInfos());
3539////     return s;
3540////  }
3541//
3542// public static final Set<StatusStats> getGlobalStatusStats() {
3543//    Set<StatusStats> s = new TreeSet<>();
3544//    for (RestContext rc : REGISTRY.values()) {
3545//       StatusStats ss = StatusStats.create(rc.getResource().getClass());
3546//       s.add(ss);
3547//       for (RestMethodContext rmc : rc.getCallMethods().values()) {
3548//          StatusStats.Method ssm = ss.getMethod(rmc.method);
3549//          for (Map.Entry<Integer,Integer> e : rmc.getStatusCodes().entrySet()) {
3550//             ssm.status(e.getKey(), e.getValue());
3551//          }
3552//       }
3553//    }
3554//    return s;
3555// }
3556
3557   //-------------------------------------------------------------------------------------------------------------------
3558   // Instance
3559   //-------------------------------------------------------------------------------------------------------------------
3560
3561   private final Object resource;
3562   final RestContextBuilder builder;
3563   private final boolean
3564      allowBodyParam,
3565      renderResponseStackTraces,
3566      useClasspathResourceCaching;
3567   private final Enablement debug;
3568   @Deprecated private final boolean
3569      useStackTraceHashes;
3570   private final String
3571      clientVersionHeader,
3572      uriAuthority,
3573      uriContext;
3574   final String fullPath;
3575   final UrlPathPattern pathPattern;
3576
3577   private final Set<String> allowedMethodParams, allowedHeaderParams, allowedMethodHeaders;
3578
3579   private final RestContextProperties properties;
3580   private final Map<Class<?>,RestMethodParam> paramResolvers;
3581   private final SerializerGroup serializers;
3582   private final ParserGroup parsers;
3583   private final HttpPartSerializer partSerializer;
3584   private final HttpPartParser partParser;
3585   private final JsonSchemaGenerator jsonSchemaGenerator;
3586   private final List<MediaType>
3587      consumes,
3588      produces;
3589   private final Map<String,Object>
3590      reqHeaders,
3591      resHeaders,
3592      staticFileResponseHeaders;
3593   private final OMap reqAttrs;
3594   private final ResponseHandler[] responseHandlers;
3595   private final MimetypesFileTypeMap mimetypesFileTypeMap;
3596   private final StaticFiles[] staticFiles;
3597   private final String[] staticFilesPaths;
3598   private final Messages msgs;
3599   private final Config config;
3600   private final VarResolver varResolver;
3601   private final Map<String,List<RestMethodContext>> methodMap;
3602   private final List<RestMethodContext> methods;
3603   private final Map<String,RestContext> childResources;
3604   @SuppressWarnings("deprecation") private final RestLogger logger;
3605   private final RestCallLogger callLogger;
3606   private final RestCallLoggerConfig callLoggerConfig;
3607   private final StackTraceDatabase stackTraceDb;
3608   private final RestInfoProvider infoProvider;
3609   private final HttpException initException;
3610   private final RestContext parentContext;
3611   private final RestResourceResolver resourceResolver;
3612   private final UriResolution uriResolution;
3613   private final UriRelativity uriRelativity;
3614   private final ConcurrentHashMap<String,MethodExecStats> methodExecStats = new ConcurrentHashMap<>();
3615   private final Instant startTime;
3616   private final Map<Class<?>,ResponseBeanMeta> responseBeanMetas = new ConcurrentHashMap<>();
3617
3618   // Lifecycle methods
3619   private final MethodInvoker[]
3620      postInitMethods,
3621      postInitChildFirstMethods,
3622      preCallMethods,
3623      postCallMethods,
3624      startCallMethods,
3625      endCallMethods,
3626      destroyMethods;
3627   private final RestMethodParam[][]
3628      preCallMethodParams,
3629      postCallMethodParams;
3630   private final Class<?>[][]
3631      postInitMethodParams,
3632      postInitChildFirstMethodParams,
3633      startCallMethodParams,
3634      endCallMethodParams,
3635      destroyMethodParams;
3636
3637   // In-memory cache of images and stylesheets in the org.apache.juneau.rest.htdocs package.
3638   private final Map<String,StaticFile> staticFilesCache = new ConcurrentHashMap<>();
3639
3640   private final ResourceManager staticResourceManager;
3641   @Deprecated private final ConcurrentHashMap<Integer,AtomicInteger> stackTraceHashes = new ConcurrentHashMap<>();
3642
3643   private final ThreadLocal<RestCall> call = new ThreadLocal<>();
3644
3645   private final ReflectionMap<Enablement> debugEnablement;
3646
3647   /**
3648    * Constructor.
3649    *
3650    * @param resource The resource annotated with <ja>@Rest</ja>.
3651    * @return A new builder object.
3652    * @throws ServletException Something bad happened.
3653    */
3654   public static RestContextBuilder create(Object resource) throws ServletException {
3655      return new RestContextBuilder(null, resource.getClass(), null).init(resource);
3656   }
3657
3658   /**
3659    * Constructor.
3660    *
3661    * @param servletConfig The servlet config passed into the servlet by the servlet container.
3662    * @param resourceClass The class annotated with <ja>@Rest</ja>.
3663    * @param parentContext The parent context, or <jk>null</jk> if there is no parent context.
3664    * @return A new builder object.
3665    * @throws ServletException Something bad happened.
3666    */
3667   static RestContextBuilder create(ServletConfig servletConfig, Class<?> resourceClass, RestContext parentContext) throws ServletException {
3668      return new RestContextBuilder(servletConfig, resourceClass, parentContext);
3669   }
3670
3671   /**
3672    * Constructor.
3673    *
3674    * @param builder The servlet configuration object.
3675    * @throws Exception If any initialization problems were encountered.
3676    */
3677   @SuppressWarnings("deprecation")
3678   public RestContext(RestContextBuilder builder) throws Exception {
3679      super(builder.getPropertyStore());
3680
3681      startTime = Instant.now();
3682
3683      REGISTRY.put(builder.resourceClass, this);
3684
3685      HttpException _initException = null;
3686
3687      try {
3688         ServletContext servletContext = builder.servletContext;
3689
3690         this.resource = builder.resource;
3691         this.builder = builder;
3692         this.parentContext = builder.parentContext;
3693
3694         Object defaultResourceResolver = parentContext == null ? (resource instanceof RestResourceResolver ? resource : BasicRestResourceResolver.class) : parentContext.resourceResolver;
3695         resourceResolver = getInstanceProperty(REST_resourceResolver, resource, RestResourceResolver.class, defaultResourceResolver, ResourceResolver.FUZZY, this);
3696
3697         varResolver = builder.varResolverBuilder
3698            .vars(
3699               FileVar.class,
3700               LocalizationVar.class,
3701               RequestAttributeVar.class,
3702               RequestFormDataVar.class,
3703               RequestHeaderVar.class,
3704               RequestPathVar.class,
3705               RequestQueryVar.class,
3706               RequestVar.class,
3707               RestInfoVar.class,
3708               SerializedRequestAttrVar.class,
3709               ServletInitParamVar.class,
3710               SwaggerVar.class,
3711               UrlVar.class,
3712               UrlEncodeVar.class,
3713               WidgetVar.class
3714            )
3715            .build()
3716         ;
3717
3718         VarResolverSession vrs = this.varResolver.createSession();
3719         config = builder.config.resolving(vrs);
3720
3721         ClassInfo rci = ClassInfo.of(resource).resolved();
3722
3723         PropertyStore ps = getPropertyStore();
3724
3725         uriContext = nullIfEmpty(getStringProperty(REST_uriContext, null));
3726         uriAuthority = nullIfEmpty(getStringProperty(REST_uriAuthority, null));
3727         uriResolution = getProperty(REST_uriResolution, UriResolution.class, UriResolution.ROOT_RELATIVE);
3728         uriRelativity = getProperty(REST_uriRelativity, UriRelativity.class, UriRelativity.RESOURCE);
3729
3730         allowBodyParam = getBooleanProperty(REST_allowBodyParam, true);
3731         allowedHeaderParams = newUnmodifiableSortedCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedHeaderParams, "Accept,Content-Type"));
3732         allowedMethodParams = newUnmodifiableSortedCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedMethodParams, "HEAD,OPTIONS"));
3733         allowedMethodHeaders = newUnmodifiableSortedCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedMethodHeaders, ""));
3734         renderResponseStackTraces = getBooleanProperty(REST_renderResponseStackTraces, false);
3735         useStackTraceHashes = getBooleanProperty(REST_useStackTraceHashes, true);
3736         clientVersionHeader = getStringProperty(REST_clientVersionHeader, "X-Client-Version");
3737
3738         ReflectionMap.Builder<Enablement> deb = ReflectionMap.create(Enablement.class);
3739         for (String s : split(getStringProperty(REST_debugOn, ""))) {
3740            s = s.trim();
3741            if (! s.isEmpty()) {
3742               int i = s.indexOf('=');
3743               if (i == -1)
3744                  deb.append(s.trim(), Enablement.TRUE);
3745               else
3746                  deb.append(s.substring(0, i).trim(), Enablement.fromString(s.substring(i+1).trim()));
3747            }
3748         }
3749
3750         boolean debug = isDebug();
3751
3752         Enablement de = getInstanceProperty(REST_debug, Enablement.class, debug ? Enablement.TRUE : Enablement.FALSE);
3753         if (de != null)
3754            deb.append(rci.getFullName(), de);
3755         for (MethodInfo mi : rci.getPublicMethods())
3756            for (RestMethod a : mi.getAnnotations(RestMethod.class))
3757               if (a != null && ! a.debug().isEmpty())
3758                  deb.append(mi.getFullName(), Enablement.fromString(a.debug()));
3759
3760         this.debugEnablement = deb.build();
3761
3762         this.debug = debugEnablement.find(rci.inner(), Enablement.class).orElse(Enablement.FALSE);
3763
3764         responseHandlers = getInstanceArrayProperty(REST_responseHandlers, resource, ResponseHandler.class, new ResponseHandler[0], resourceResolver, this);
3765
3766         AMap<Class<?>,RestMethodParam> _paramResolvers = AMap.of();
3767         for (RestMethodParam rp : getInstanceArrayProperty(REST_paramResolvers, RestMethodParam.class, new RestMethodParam[0], resourceResolver, this))
3768            _paramResolvers.put(rp.forClass(), rp);
3769         paramResolvers = _paramResolvers.unmodifiable();
3770
3771         Map<String,Object> _reqHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
3772         _reqHeaders.putAll(getMapProperty(REST_reqHeaders, String.class));
3773         reqHeaders = AMap.unmodifiable(_reqHeaders);
3774
3775         reqAttrs = new OMap(getMapProperty(REST_reqAttrs, Object.class)).unmodifiable();
3776         resHeaders = getMapProperty(REST_resHeaders, Object.class);
3777         staticFileResponseHeaders = getMapProperty(REST_staticFileResponseHeaders, Object.class);
3778
3779         logger = getInstanceProperty(REST_logger, resource, RestLogger.class, NoOpRestLogger.class, resourceResolver, this);
3780
3781         Object clc = getProperty(REST_callLoggerConfig);
3782         if (this.debug == TRUE)
3783            this.callLoggerConfig = RestCallLoggerConfig.DEFAULT_DEBUG;
3784         else if (clc instanceof RestCallLoggerConfig)
3785            this.callLoggerConfig = (RestCallLoggerConfig)clc;
3786         else if (clc instanceof OMap)
3787            this.callLoggerConfig = RestCallLoggerConfig.create().apply((OMap)clc).build();
3788         else
3789            this.callLoggerConfig = RestCallLoggerConfig.DEFAULT_NOOP;
3790
3791         this.stackTraceDb = new StackTraceDatabase(callLoggerConfig.getStackTraceHashingTimeout(), RestMethodContext.class);
3792
3793         Object defaultRestCallLogger = resource instanceof RestCallLogger ? resource : BasicRestCallLogger.class;
3794         callLogger = getInstanceProperty(REST_callLogger, resource, RestCallLogger.class, defaultRestCallLogger, resourceResolver, this);
3795
3796         properties = builder.properties;
3797         serializers =
3798            SerializerGroup
3799            .create()
3800            .append(getInstanceArrayProperty(REST_serializers, Serializer.class, new Serializer[0], resourceResolver, resource, ps))
3801            .build();
3802         parsers =
3803            ParserGroup
3804            .create()
3805            .append(getInstanceArrayProperty(REST_parsers, Parser.class, new Parser[0], resourceResolver, resource, ps))
3806            .build();
3807         partSerializer = getInstanceProperty(REST_partSerializer, HttpPartSerializer.class, OpenApiSerializer.class, resourceResolver, resource, ps);
3808         partParser = getInstanceProperty(REST_partParser, HttpPartParser.class, OpenApiParser.class, resourceResolver, resource, ps);
3809         jsonSchemaGenerator =
3810            JsonSchemaGenerator
3811            .create()
3812            .apply(ps)
3813            .build();
3814
3815         mimetypesFileTypeMap = new ExtendedMimetypesFileTypeMap();
3816         for (String mimeType : getArrayProperty(REST_mimeTypes, String.class))
3817            mimetypesFileTypeMap.addMimeTypes(mimeType);
3818
3819         Object defaultResourceFinder = resource instanceof ResourceFinder ? resource : BasicResourceFinder.class;
3820         ResourceFinder rf = getInstanceProperty(REST_classpathResourceFinder, ResourceFinder.class, defaultResourceFinder, resourceResolver, this);
3821
3822         useClasspathResourceCaching = getProperty(REST_useClasspathResourceCaching, boolean.class, true);
3823         staticResourceManager = new ResourceManager(rci.inner(), rf, useClasspathResourceCaching);
3824
3825         consumes = getListProperty(REST_consumes, MediaType.class, parsers.getSupportedMediaTypes());
3826         produces = getListProperty(REST_produces, MediaType.class, serializers.getSupportedMediaTypes());
3827
3828         StaticFileMapping[] staticFileMappings = getArrayProperty(REST_staticFiles, StaticFileMapping.class, new StaticFileMapping[0]);
3829         staticFiles = new StaticFiles[staticFileMappings.length];
3830         for (int i = 0; i < staticFiles.length; i++)
3831            staticFiles[i] = new StaticFiles(staticFileMappings[i], staticResourceManager, mimetypesFileTypeMap, staticFileResponseHeaders);
3832
3833         Set<String> s = new TreeSet<>();
3834         for (StaticFiles sf : staticFiles)
3835            s.add(sf.getPath());
3836         staticFilesPaths = s.toArray(new String[s.size()]);
3837
3838         Tuple2<Class<?>,String>[] mbl = getInstanceArrayProperty(REST_messages, Tuple2.class, new Tuple2[0]);
3839         Messages msgs = null;
3840         for (int i = mbl.length-1; i >= 0; i--)
3841            msgs = Messages.create(firstNonNull(mbl[i].getA(), rci.inner())).name(mbl[i].getB()).parent(msgs).build();
3842         this.msgs = msgs;
3843
3844         this.fullPath = (builder.parentContext == null ? "" : (builder.parentContext.fullPath + '/')) + builder.getPath();
3845
3846         String p = builder.getPath();
3847         if (! p.endsWith("/*"))
3848            p += "/*";
3849         this.pathPattern = new UrlPathPattern(p);
3850
3851         this.childResources = Collections.synchronizedMap(new LinkedHashMap<String,RestContext>());  // Not unmodifiable on purpose so that children can be replaced.
3852
3853         //----------------------------------------------------------------------------------------------------
3854         // Initialize the child resources.
3855         // Done after initializing fields above since we pass this object to the child resources.
3856         //----------------------------------------------------------------------------------------------------
3857         List<String> methodsFound = new LinkedList<>();   // Temporary to help debug transient duplicate method issue.
3858         MethodMapBuilder methodMapBuilder = new MethodMapBuilder();
3859         AMap<String,Method>
3860            _startCallMethods = AMap.of(),
3861            _preCallMethods = AMap.of(),
3862            _postCallMethods = AMap.of(),
3863            _endCallMethods = AMap.of(),
3864            _postInitMethods = AMap.of(),
3865            _postInitChildFirstMethods = AMap.of(),
3866            _destroyMethods = AMap.of();
3867         AList<RestMethodParam[]>
3868            _preCallMethodParams = AList.of(),
3869            _postCallMethodParams = AList.of();
3870         AList<Class<?>[]>
3871            _startCallMethodParams = AList.of(),
3872            _endCallMethodParams = AList.of(),
3873            _postInitMethodParams = AList.of(),
3874            _postInitChildFirstMethodParams = AList.of(),
3875            _destroyMethodParams = AList.of();
3876
3877         for (MethodInfo mi : rci.getPublicMethods()) {
3878            RestMethod a = mi.getLastAnnotation(RestMethod.class);
3879
3880            // Also include methods on @Rest-annotated interfaces.
3881            if (a == null) {
3882               for (Method mi2 : mi.getMatching()) {
3883                  Class<?> ci2 = mi2.getDeclaringClass();
3884                  if (ci2.isInterface() && ci2.getAnnotation(Rest.class) != null) {
3885                     a = new RestMethodAnnotation();
3886                  }
3887               }
3888            }
3889            if (a != null) {
3890               methodsFound.add(mi.getSimpleName() + "," + emptyIfNull(firstNonEmpty(a.name(), a.method())) + "," + fixMethodPath(a.path()));
3891               try {
3892                  if (mi.isNotPublic())
3893                     throw new RestServletException("@RestMethod method {0}.{1} must be defined as public.", rci.inner().getName(), mi.getSimpleName());
3894
3895                  RestMethodContextBuilder rmcb = new RestMethodContextBuilder(resource, mi.inner(), this);
3896                  RestMethodContext sm = new RestMethodContext(rmcb);
3897                  String httpMethod = sm.getHttpMethod();
3898
3899                  // RRPC is a special case where a method returns an interface that we
3900                  // can perform REST calls against.
3901                  // We override the CallMethod.invoke() method to insert our logic.
3902                  if ("RRPC".equals(httpMethod)) {
3903
3904                     final ClassMeta<?> interfaceClass = getClassMeta(mi.inner().getGenericReturnType());
3905                     final RrpcInterfaceMeta rim = new RrpcInterfaceMeta(interfaceClass.getInnerClass(), null);
3906                     if (rim.getMethodsByPath().isEmpty())
3907                        throw new RestException(SC_INTERNAL_SERVER_ERROR, "Method {0} returns an interface {1} that doesn't define any remote methods.", mi.getSignature(), interfaceClass.getFullName());
3908
3909                     RestMethodContextBuilder smb = new RestMethodContextBuilder(resource, mi.inner(), this);
3910                     smb.dotAll();
3911                     sm = new RestMethodContext(smb) {
3912
3913                        @Override
3914                        void invoke(RestCall call) throws Throwable {
3915
3916                           super.invoke(call);
3917
3918                           final Object o = call.getOutput();
3919
3920                           if ("GET".equals(call.getMethod())) {
3921                              call.output(rim.getMethodsByPath().keySet());
3922                              return;
3923
3924                           } else if ("POST".equals(call.getMethod())) {
3925                              String pip = call.getUrlPathInfo().getPath();
3926                              if (pip.indexOf('/') != -1)
3927                                 pip = pip.substring(pip.lastIndexOf('/')+1);
3928                              pip = urlDecode(pip);
3929                              RrpcInterfaceMethodMeta rmm = rim.getMethodMetaByPath(pip);
3930                              if (rmm != null) {
3931                                 Method m = rmm.getJavaMethod();
3932                                 try {
3933                                    RestRequest req = call.getRestRequest();
3934                                    // Parse the args and invoke the method.
3935                                    Parser p = req.getBody().getParser();
3936                                    Object[] args = null;
3937                                    if (m.getGenericParameterTypes().length == 0)
3938                                       args = new Object[0];
3939                                    else {
3940                                       try (Closeable in = p.isReaderParser() ? req.getReader() : req.getInputStream()) {
3941                                          args = p.parseArgs(in, m.getGenericParameterTypes());
3942                                       }
3943                                    }
3944                                    Object output = m.invoke(o, args);
3945                                    call.output(output);
3946                                    return;
3947                                 } catch (Exception e) {
3948                                    throw toHttpException(e, InternalServerError.class);
3949                                 }
3950                              }
3951                           }
3952                           throw new NotFound();
3953                        }
3954                     };
3955
3956                     methodMapBuilder.add("GET", sm).add("POST", sm);
3957
3958                  } else {
3959                     methodMapBuilder.add(httpMethod, sm);
3960                  }
3961               } catch (Throwable e) {
3962                  throw new RestServletException(e, "Problem occurred trying to initialize methods on class {0}, methods={1}", rci.inner().getName(), SimpleJsonSerializer.DEFAULT.serialize(methodsFound));
3963               }
3964            }
3965         }
3966
3967         for (MethodInfo m : rci.getAllMethodsParentFirst()) {
3968            if (m.isPublic() && m.hasAnnotation(RestHook.class)) {
3969               HookEvent he = m.getLastAnnotation(RestHook.class).value();
3970               String sig = m.getSignature();
3971               switch(he) {
3972                  case PRE_CALL: {
3973                     if (! _preCallMethods.containsKey(sig)) {
3974                        m.setAccessible();
3975                        _preCallMethods.put(sig, m.inner());
3976                        _preCallMethodParams.add(findParams(m, true, null));
3977                     }
3978                     break;
3979                  }
3980                  case POST_CALL: {
3981                     if (! _postCallMethods.containsKey(sig)) {
3982                        m.setAccessible();
3983                        _postCallMethods.put(sig, m.inner());
3984                        _postCallMethodParams.add(findParams(m, true, null));
3985                     }
3986                     break;
3987                  }
3988                  case START_CALL: {
3989                     if (! _startCallMethods.containsKey(sig)) {
3990                        m.setAccessible();
3991                        _startCallMethods.put(sig, m.inner());
3992                        _startCallMethodParams.add((Class<?>[])m.getRawParamTypes().toArray());
3993                        assertArgsOnlyOfType(m, HttpServletRequest.class, HttpServletResponse.class);
3994                     }
3995                     break;
3996                  }
3997                  case END_CALL: {
3998                     if (! _endCallMethods.containsKey(sig)) {
3999                        m.setAccessible();
4000                        _endCallMethods.put(sig, m.inner());
4001                        _endCallMethodParams.add((Class<?>[])m.getRawParamTypes().toArray());
4002                        assertArgsOnlyOfType(m, HttpServletRequest.class, HttpServletResponse.class);
4003                     }
4004                     break;
4005                  }
4006                  case POST_INIT: {
4007                     if (! _postInitMethods.containsKey(sig)) {
4008                        m.setAccessible();
4009                        _postInitMethods.put(sig, m.inner());
4010                        _postInitMethodParams.add((Class<?>[])m.getRawParamTypes().toArray());
4011                        assertArgsOnlyOfType(m, RestContext.class);
4012                     }
4013                     break;
4014                  }
4015                  case POST_INIT_CHILD_FIRST: {
4016                     if (! _postInitChildFirstMethods.containsKey(sig)) {
4017                        m.setAccessible();
4018                        _postInitChildFirstMethods.put(sig, m.inner());
4019                        _postInitChildFirstMethodParams.add((Class<?>[])m.getRawParamTypes().toArray());
4020                        assertArgsOnlyOfType(m, RestContext.class);
4021                     }
4022                     break;
4023                  }
4024                  case DESTROY: {
4025                     if (! _destroyMethods.containsKey(sig)) {
4026                        m.setAccessible();
4027                        _destroyMethods.put(sig, m.inner());
4028                        _destroyMethodParams.add((Class<?>[])m.getRawParamTypes().toArray());
4029                        assertArgsOnlyOfType(m, RestContext.class);
4030                     }
4031                     break;
4032                  }
4033                  default: // Ignore INIT
4034               }
4035            }
4036         }
4037
4038         this.preCallMethods = _preCallMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_preCallMethods.size()]);
4039         this.postCallMethods = _postCallMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_postCallMethods.size()]);
4040         this.startCallMethods = _startCallMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_startCallMethods.size()]);
4041         this.endCallMethods = _endCallMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_endCallMethods.size()]);
4042         this.postInitMethods = _postInitMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_postInitMethods.size()]);
4043         this.postInitChildFirstMethods = _postInitChildFirstMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_postInitChildFirstMethods.size()]);
4044         this.destroyMethods = _destroyMethods.values().stream().map(x->new MethodInvoker(x, getMethodExecStats(x))).collect(Collectors.toList()).toArray(new MethodInvoker[_destroyMethods.size()]);
4045         this.preCallMethodParams = _preCallMethodParams.toArray(new RestMethodParam[_preCallMethodParams.size()][]);
4046         this.postCallMethodParams = _postCallMethodParams.toArray(new RestMethodParam[_postCallMethodParams.size()][]);
4047         this.startCallMethodParams = _startCallMethodParams.toArray(new Class[_startCallMethodParams.size()][]);
4048         this.endCallMethodParams = _endCallMethodParams.toArray(new Class[_endCallMethodParams.size()][]);
4049         this.postInitMethodParams = _postInitMethodParams.toArray(new Class[_postInitMethodParams.size()][]);
4050         this.postInitChildFirstMethodParams = _postInitChildFirstMethodParams.toArray(new Class[_postInitChildFirstMethodParams.size()][]);
4051         this.destroyMethodParams = _destroyMethodParams.toArray(new Class[_destroyMethodParams.size()][]);
4052
4053         this.methodMap = methodMapBuilder.getMap();
4054         this.methods = methodMapBuilder.getList();
4055
4056         // Initialize our child resources.
4057         for (Object o : getArrayProperty(REST_children, Object.class)) {
4058            String path = null;
4059            Object r = null;
4060            if (o instanceof RestChild) {
4061               RestChild rc = (RestChild)o;
4062               path = rc.path;
4063               r = rc.resource;
4064            } else if (o instanceof Class<?>) {
4065               Class<?> c = (Class<?>)o;
4066               // Don't allow specifying yourself as a child.  Causes an infinite loop.
4067               if (c == builder.resourceClass)
4068                  continue;
4069               r = c;
4070            } else {
4071               r = o;
4072            }
4073
4074            RestContextBuilder childBuilder = null;
4075
4076            if (o instanceof Class) {
4077               Class<?> oc = (Class<?>)o;
4078               childBuilder = RestContext.create(builder.inner, oc, this);
4079               r = resourceResolver.resolve(resource, oc, childBuilder);
4080            } else {
4081               r = o;
4082               childBuilder = RestContext.create(builder.inner, o.getClass(), this);
4083            }
4084
4085            childBuilder.init(r);
4086            if (r instanceof RestServlet)
4087               ((RestServlet)r).innerInit(childBuilder);
4088            childBuilder.servletContext(servletContext);
4089            RestContext rc2 = childBuilder.build();
4090            if (r instanceof RestServlet)
4091               ((RestServlet)r).setContext(rc2);
4092            path = childBuilder.getPath();
4093            childResources.put(path, rc2);
4094         }
4095
4096         Object defaultRestInfoProvider = resource instanceof RestInfoProvider ? resource : BasicRestInfoProvider.class;
4097         infoProvider = getInstanceProperty(REST_infoProvider, resource, RestInfoProvider.class, defaultRestInfoProvider, resourceResolver, this);
4098
4099      } catch (HttpException e) {
4100         _initException = e;
4101         throw e;
4102      } catch (Exception e) {
4103         _initException = new InternalServerError(e);
4104         throw e;
4105      } finally {
4106         initException = _initException;
4107      }
4108   }
4109
4110   /**
4111    * Returns the resource resolver associated with this context.
4112    *
4113    * <p>
4114    * The resource resolver is used for instantiating child resource classes.
4115    *
4116    * <ul class='seealso'>
4117    *    <li class='jf'>{@link #REST_resourceResolver}
4118    * </ul>
4119    *
4120    * @return The resource resolver associated with this context.
4121    */
4122   protected RestResourceResolver getResourceResolver() {
4123      return resourceResolver;
4124   }
4125
4126   /**
4127    * Returns the time statistics gatherer for the specified method.
4128    *
4129    * @param m The method to get statistics for.
4130    * @return The cached time-stats object.
4131    */
4132   protected MethodExecStats getMethodExecStats(Method m) {
4133      String n = MethodInfo.of(m).getSimpleName();
4134      MethodExecStats ts = methodExecStats.get(n);
4135      if (ts == null) {
4136         methodExecStats.putIfAbsent(n, new MethodExecStats(m));
4137         ts = methodExecStats.get(n);
4138      }
4139      return ts;
4140   }
4141
4142   /**
4143    * Returns the variable resolver for this servlet.
4144    *
4145    * <p>
4146    * Variable resolvers are used to replace variables in property values.
4147    * They can be nested arbitrarily deep.
4148    * They can also return values that themselves contain other variables.
4149    *
4150    * <h5 class='figure'>Example:</h5>
4151    * <p class='bcode w800'>
4152    *    <ja>@Rest</ja>(
4153    *       messages=<js>"nls/Messages"</js>,
4154    *       properties={
4155    *          <ja>@Property</ja>(name=<js>"title"</js>,value=<js>"$L{title}"</js>),  <jc>// Localized variable in Messages.properties</jc>
4156    *          <ja>@Property</ja>(name=<js>"javaVendor"</js>,value=<js>"$S{java.vendor,Oracle}"</js>),  <jc>// System property with default value</jc>
4157    *          <ja>@Property</ja>(name=<js>"foo"</js>,value=<js>"bar"</js>),
4158    *          <ja>@Property</ja>(name=<js>"bar"</js>,value=<js>"baz"</js>),
4159    *          <ja>@Property</ja>(name=<js>"v1"</js>,value=<js>"$R{foo}"</js>),  <jc>// Request variable.  value="bar"</jc>
4160    *          <ja>@Property</ja>(name=<js>"v1"</js>,value=<js>"$R{foo,bar}"</js>),  <jc>// Request variable.  value="bar"</jc>
4161    *       }
4162    *    )
4163    *    <jk>public class</jk> MyRestResource <jk>extends</jk> BasicRestServlet {
4164    * </p>
4165    *
4166    * <p>
4167    * A typical usage pattern involves using variables inside the {@link HtmlDocConfig @HtmlDocConfig} annotation:
4168    * <p class='bcode w800'>
4169    *    <ja>@RestMethod</ja>(
4170    *       name=<jsf>GET</jsf>, path=<js>"/{name}/*"</js>
4171    *    )
4172    *    <ja>@HtmlDocConfig</ja>(
4173    *       navlinks={
4174    *          <js>"up: $R{requestParentURI}"</js>,
4175    *          <js>"options: servlet:/?method=OPTIONS"</js>,
4176    *          <js>"stats: servlet:/stats"</js>,
4177    *          <js>"editLevel: servlet:/editLevel?logger=$A{attribute.name, OFF}"</js>
4178    *       }
4179    *       header={
4180    *          <js>"&lt;h1&gt;$L{MyLocalizedPageTitle}&lt;/h1&gt;"</js>
4181    *       },
4182    *       aside={
4183    *          <js>"$F{resources/AsideText.html}"</js>
4184    *       }
4185    *    )
4186    *    <jk>public</jk> LoggerEntry getLogger(RestRequest req, <ja>@Path</ja> String name) <jk>throws</jk> Exception {
4187    * </p>
4188    *
4189    * <ul class='seealso'>
4190    *    <li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#vars(Class...)} - For adding custom vars.
4191    *    <li class='link'>{@doc RestSvlVariables}
4192    *    <li class='link'>{@doc RestSvlVariables}
4193    * </ul>
4194    *
4195    * @return The var resolver in use by this resource.
4196    */
4197   public VarResolver getVarResolver() {
4198      return varResolver;
4199   }
4200
4201   /**
4202    * Returns the config file associated with this servlet.
4203    *
4204    * <p>
4205    * The config file is identified via one of the following:
4206    * <ul class='javatree'>
4207    *    <li class='ja'>{@link Rest#config()}
4208    *    <li class='jm'>{@link RestContextBuilder#config(Config)}
4209    * </ul>
4210    *
4211    * @return
4212    *    The resolving config file associated with this servlet.
4213    *    <br>Never <jk>null</jk>.
4214    */
4215   public Config getConfig() {
4216      return config;
4217   }
4218
4219   /**
4220    * Resolve a static resource file.
4221    *
4222    * <p>
4223    * The location of static resources are defined via:
4224    * <ul class='javatree'>
4225    *    <li class='jf'>{@link RestContext#REST_staticFiles RestContext.REST_staticFiles}
4226    * </ul>
4227    *
4228    * @param pathInfo The unencoded path info.
4229    * @return The wrapped resource, never <jk>null</jk>.
4230    * @throws NotFound Invalid path.
4231    * @throws IOException Thrown by underlying stream.
4232    */
4233   protected StaticFile getStaticFile(String pathInfo) throws NotFound, IOException {
4234      if (! staticFilesCache.containsKey(pathInfo)) {
4235         String p = urlDecode(trimSlashes(pathInfo));
4236         if (p.indexOf("..") != -1)
4237            throw new NotFound("Invalid path");
4238         StaticFile sf = null;
4239         for (StaticFiles sfs : staticFiles) {
4240            sf = sfs.resolve(p);
4241            if (sf != null)
4242               break;
4243         }
4244         if (sf == null)
4245            sf = new StaticFile(null,null,null);
4246         if (useClasspathResourceCaching) {
4247            if (staticFilesCache.size() > 100)
4248               staticFilesCache.clear();
4249            staticFilesCache.put(pathInfo, sf);
4250         }
4251         return sf;
4252      }
4253      return staticFilesCache.get(pathInfo);
4254   }
4255
4256   /**
4257    * Same as {@link Class#getResourceAsStream(String)} except if it doesn't find the resource on this class, searches
4258    * up the parent hierarchy chain.
4259    *
4260    * <p>
4261    * If the resource cannot be found in the classpath, then an attempt is made to look in the JVM working directory.
4262    *
4263    * <p>
4264    * If the <c>locale</c> is specified, then we look for resources whose name matches that locale.
4265    * <br>For example, if looking for the resource <js>"MyResource.txt"</js> for the Japanese locale, we will look for
4266    * files in the following order:
4267    * <ol>
4268    *    <li><js>"MyResource_ja_JP.txt"</js>
4269    *    <li><js>"MyResource_ja.txt"</js>
4270    *    <li><js>"MyResource.txt"</js>
4271    * </ol>
4272    *
4273    * <h5 class='section'>Example:</h5>
4274    * <p class='bcode w800'>
4275    *    <jc>// A rest method that (unsafely!) returns the contents of a localized file </jc>
4276    * <jc>// from the classpath.</jc>
4277    *    <ja>@RestMethod</ja>(path=<js>"/foo"</js>)
4278    *    <jk>public</jk> Object myMethod(RestRequest req, <ja>@Query</ja>(<js>"file"</js>) String file) {
4279    *       <jk>return</jk> getContext().getClasspathResource(file, req.getLocale());
4280    *    }
4281    * </p>
4282    *
4283    * <ul class='seealso'>
4284    *    <li class='jf'>{@link #REST_classpathResourceFinder}
4285    * </ul>
4286    *
4287    * @param name The resource name.
4288    * @param locale
4289    *    Optional locale.
4290    *    <br>If <jk>null</jk>, won't look for localized file names.
4291    * @return An input stream of the resource, or <jk>null</jk> if the resource could not be found.
4292    * @throws IOException Thrown by underlying stream.
4293    */
4294   public InputStream getClasspathResource(String name, Locale locale) throws IOException {
4295      return staticResourceManager.getStream(name, locale);
4296   }
4297
4298   /**
4299    * Reads the input stream from {@link #getClasspathResource(String, Locale)} into a String.
4300    *
4301    * <h5 class='section'>Example:</h5>
4302    * <p class='bcode w800'>
4303    *    <jc>// A rest method that (unsafely!) returns the contents of a localized file </jc>
4304    * <jc>// from the classpath.</jc>
4305    *    <ja>@RestMethod</ja>(path=<js>"/foo"</js>)
4306    *    <jk>public</jk> String myMethod(RestRequest req, <ja>@Query</ja>(<js>"file"</js>) String file) {
4307    *       <jk>return</jk> getContext().getClasspathResourceAsString(file, req.getLocale());
4308    *    }
4309    * </p>
4310    *
4311    * <ul class='seealso'>
4312    *    <li class='jf'>{@link #REST_classpathResourceFinder}
4313    * </ul>
4314    *
4315    * @param name The resource name.
4316    * @param locale
4317    *    Optional locale.
4318    *    <br>If <jk>null</jk>, won't look for localized file names.
4319    * @return The contents of the stream as a string, or <jk>null</jk> if the resource could not be found.
4320    * @throws IOException If resource could not be found.
4321    */
4322   public String getClasspathResourceAsString(String name, Locale locale) throws IOException {
4323      return staticResourceManager.getString(name, locale);
4324   }
4325
4326
4327   /**
4328    * Reads the input stream from {@link #getClasspathResource(String, Locale)} and parses it into a POJO using the parser
4329    * matched by the specified media type.
4330    *
4331    * <p>
4332    * Useful if you want to load predefined POJOs from JSON files in your classpath.
4333    *
4334    * <h5 class='section'>Example:</h5>
4335    * <p class='bcode w800'>
4336    *    <jc>// A rest method that (unsafely!) returns the contents of a localized file </jc>
4337    * <jc>// from the classpath parsed as an array of beans.</jc>
4338    *    <ja>@RestMethod</ja>(path=<js>"/foo"</js>)
4339    *    <jk>public</jk> MyBean[] myMethod(RestRequest req, <ja>@Query</ja>(<js>"file"</js>) String file) {
4340    *       <jk>return</jk> getContext().getClasspathResource(MyBean[].<jk>class</jk>, <jsf>JSON</jsf>, file, req.getLocale());
4341    *    }
4342    * </p>
4343    *
4344    * <ul class='seealso'>
4345    *    <li class='jf'>{@link #REST_classpathResourceFinder}
4346    * </ul>
4347    *
4348    * @param c The class type of the POJO to create.
4349    * @param mediaType The media type of the data in the stream (e.g. <js>"text/json"</js>)
4350    * @param name The resource name (e.g. "htdocs/styles.css").
4351    * @param locale
4352    *    Optional locale.
4353    *    <br>If <jk>null</jk>, won't look for localized file names.
4354    * @return The parsed resource, or <jk>null</jk> if the resource could not be found.
4355    * @throws IOException Thrown by underlying stream.
4356    * @throws ServletException If the media type was unknown or the input could not be parsed into a POJO.
4357    */
4358   public <T> T getClasspathResource(Class<T> c, MediaType mediaType, String name, Locale locale) throws IOException, ServletException {
4359      InputStream is = getClasspathResource(name, locale);
4360      if (is == null)
4361         return null;
4362      try {
4363         Parser p = parsers.getParser(mediaType);
4364         if (p == null) {
4365            if (mediaType == MediaType.JSON)
4366               p = JsonParser.DEFAULT;
4367            if (mediaType == MediaType.XML)
4368               p = XmlParser.DEFAULT;
4369            if (mediaType == MediaType.HTML)
4370               p = HtmlParser.DEFAULT;
4371            if (mediaType == MediaType.UON)
4372               p = UonParser.DEFAULT;
4373            if (mediaType == MediaType.URLENCODING)
4374               p = UrlEncodingParser.DEFAULT;
4375            if (mediaType == MediaType.MSGPACK)
4376               p = MsgPackParser.DEFAULT;
4377         }
4378         if (p != null) {
4379            try {
4380               try (Closeable in = p.isReaderParser() ? new InputStreamReader(is, UTF8) : is) {
4381                  return p.parse(in, c);
4382               }
4383            } catch (ParseException e) {
4384               throw new ServletException("Could not parse resource '"+name+" as media type '"+mediaType+"'.", e);
4385            }
4386         }
4387         throw new ServletException("Unknown media type '"+mediaType+"'");
4388      } catch (Exception e) {
4389         throw new ServletException("Could not parse resource with name '"+name+"'", e);
4390      }
4391   }
4392
4393   /**
4394    * Returns the path for this resource as defined by the {@link Rest#path() @Rest(path)} annotation or
4395    * {@link RestContextBuilder#path(String)} method concatenated with those on all parent classes.
4396    *
4397    * <p>
4398    * If path is not specified, returns <js>""</js>.
4399    *
4400    * <ul class='seealso'>
4401    *    <li class='jf'>{@link #REST_path}
4402    * </ul>
4403    *
4404    * @return The servlet path.
4405    */
4406   public String getPath() {
4407      return fullPath;
4408   }
4409
4410   /**
4411    * Returns the logger to use for this resource.
4412    *
4413    * <div class='warn'>
4414    *    <b>Deprecated</b> - Use {@link #getCallLogger()}
4415    * </div>
4416    *
4417    * <ul class='seealso'>
4418    *    <li class='jf'>{@link #REST_logger}
4419    * </ul>
4420    *
4421    * @return
4422    *    The logger to use for this resource.
4423    *    <br>Never <jk>null</jk>.
4424    */
4425   @Deprecated
4426   public RestLogger getLogger() {
4427      return logger;
4428   }
4429
4430   /**
4431    * Returns the call logger to use for this resource.
4432    *
4433    * <ul class='seealso'>
4434    *    <li class='jf'>{@link #REST_callLogger}
4435    * </ul>
4436    *
4437    * @return
4438    *    The call logger to use for this resource.
4439    *    <br>Never <jk>null</jk>.
4440    */
4441   public RestCallLogger getCallLogger() {
4442      return callLogger;
4443   }
4444
4445   /**
4446    * Returns the call logger config to use for this resource.
4447    *
4448    * <ul class='seealso'>
4449    *    <li class='jf'>{@link #REST_callLoggerConfig}
4450    * </ul>
4451    *
4452    * @return
4453    *    The call logger config to use for this resource.
4454    *    <br>Never <jk>null</jk>.
4455    */
4456   public RestCallLoggerConfig getCallLoggerConfig() {
4457      return callLoggerConfig;
4458   }
4459
4460   /**
4461    * Returns the resource bundle used by this resource.
4462    *
4463    * <ul class='seealso'>
4464    *    <li class='jf'>{@link #REST_messages}
4465    * </ul>
4466    *
4467    * @return
4468    *    The resource bundle for this resource.
4469    *    <br>Never <jk>null</jk>.
4470    */
4471   public Messages getMessages() {
4472      return msgs;
4473   }
4474
4475   /**
4476    * Returns the REST information provider used by this resource.
4477    *
4478    * <ul class='seealso'>
4479    *    <li class='jf'>{@link RestContext#REST_infoProvider}
4480    * </ul>
4481    *
4482    * @return
4483    *    The information provider for this resource.
4484    *    <br>Never <jk>null</jk>.
4485    */
4486   public RestInfoProvider getInfoProvider() {
4487      return infoProvider;
4488   }
4489
4490   /**
4491    * Returns the resource object.
4492    *
4493    * <p>
4494    * This is the instance of the class annotated with the {@link Rest @Rest} annotation, usually
4495    * an instance of {@link RestServlet}.
4496    *
4497    * @return
4498    *    The resource object.
4499    *    <br>Never <jk>null</jk>.
4500    */
4501   public Object getResource() {
4502      return resource;
4503   }
4504
4505   /**
4506    * Returns the resource object as a {@link RestServlet}.
4507    *
4508    * @return
4509    *    The resource object cast to {@link RestServlet}, or <jk>null</jk> if the resource doesn't subclass from
4510    *    {@link RestServlet}.
4511    */
4512   public RestServlet getRestServlet() {
4513      return resource instanceof RestServlet ? (RestServlet)resource : null;
4514   }
4515
4516   /**
4517    * Throws a {@link HttpException} if an exception occurred in the constructor of this object.
4518    *
4519    * @throws HttpException The initialization exception wrapped in a {@link HttpException}.
4520    */
4521   protected void checkForInitException() throws HttpException {
4522      if (initException != null)
4523         throw initException;
4524   }
4525
4526   /**
4527    * Returns the parent resource context (if this resource was initialized from a parent).
4528    *
4529    * <p>
4530    * From this object, you can get access to the parent resource class itself using {@link #getResource()} or
4531    * {@link #getRestServlet()}
4532    *
4533    * @return The parent resource context, or <jk>null</jk> if there is no parent context.
4534    */
4535   public RestContext getParentContext() {
4536      return parentContext;
4537   }
4538
4539   /**
4540    * Returns the class-level properties associated with this servlet.
4541    *
4542    * <p>
4543    * Properties at the class level are defined via the following:
4544    * <ul class='javatree'>
4545    *    <li class='ja'>{@link Rest#properties()}
4546    *    <li class='jm'>{@link RestContextBuilder#set(String, Object)}
4547    *    <li class='jm'>{@link RestContextBuilder#set(Map)}
4548    * </ul>
4549    *
4550    * <ul class='notes'>
4551    *    <li>
4552    *       The returned {@code Map} is mutable.
4553    *       <br>Therefore, subclasses are free to override or set additional initialization parameters in their {@code init()} method.
4554    * </ul>
4555    *
4556    * @return The resource properties as a {@link RestContextProperties}.
4557    */
4558   public RestContextProperties getProperties() {
4559      return properties;
4560   }
4561
4562   /**
4563    * Returns the servlet init parameter returned by {@link ServletConfig#getInitParameter(String)}.
4564    *
4565    * @param name The init parameter name.
4566    * @return The servlet init parameter, or <jk>null</jk> if not found.
4567    */
4568   public String getServletInitParameter(String name) {
4569      return builder.getInitParameter(name);
4570   }
4571
4572   /**
4573    * Returns the child resources associated with this servlet.
4574    *
4575    * @return
4576    *    An unmodifiable map of child resources.
4577    *    Keys are the {@link Rest#path() @Rest(path)} annotation defined on the child resource.
4578    */
4579   public Map<String,RestContext> getChildResources() {
4580      return Collections.unmodifiableMap(childResources);
4581   }
4582
4583   /**
4584    * Returns the number of times this exception was thrown based on a hash of its stacktrace.
4585    *
4586    * <div class='warn'>
4587    *    <b>Deprecated</b> - Not used by new logging API.
4588    * </div>
4589    *
4590    * <ul class='seealso'>
4591    *    <li class='jf'>{@link RestContext#REST_useStackTraceHashes}
4592    * </ul>
4593    *
4594    * @param e The exception to check.
4595    * @return
4596    *    The number of times this exception was thrown, or <c>0</c> if {@link #REST_useStackTraceHashes}
4597    *    setting is not enabled.
4598    */
4599   @Deprecated
4600   public int getStackTraceOccurrence(Throwable e) {
4601      if (! useStackTraceHashes)
4602         return 0;
4603      int h = e.hashCode();
4604      stackTraceHashes.putIfAbsent(h, new AtomicInteger());
4605      return stackTraceHashes.get(h).incrementAndGet();
4606   }
4607
4608   /**
4609    * Returns whether it's safe to render stack traces in HTTP responses.
4610    *
4611    * <ul class='seealso'>
4612    *    <li class='jf'>{@link RestContext#REST_useStackTraceHashes}
4613    * </ul>
4614    *
4615    * @return <jk>true</jk> if setting is enabled.
4616    */
4617   public boolean isRenderResponseStackTraces() {
4618      return renderResponseStackTraces;
4619   }
4620
4621   /**
4622    * Returns whether it's safe to pass the HTTP body as a <js>"body"</js> GET parameter.
4623    *
4624    * <ul class='seealso'>
4625    *    <li class='jf'>{@link RestContext#REST_allowBodyParam}
4626    * </ul>
4627    *
4628    * @return <jk>true</jk> if setting is enabled.
4629    */
4630   public boolean isAllowBodyParam() {
4631      return allowBodyParam;
4632   }
4633
4634   /**
4635    * Allowed header URL parameters.
4636    *
4637    * <ul class='seealso'>
4638    *    <li class='jf'>{@link RestContext#REST_allowedHeaderParams}
4639    * </ul>
4640    *
4641    * @return
4642    *    The header names allowed to be passed as URL parameters.
4643    *    <br>The set is case-insensitive ordered.
4644    */
4645   public Set<String> getAllowedHeaderParams() {
4646      return allowedHeaderParams;
4647   }
4648
4649   /**
4650    * Allowed method headers.
4651    *
4652    * <ul class='seealso'>
4653    *    <li class='jf'>{@link RestContext#REST_allowedMethodHeaders}
4654    * </ul>
4655    *
4656    * @return
4657    *    The method names allowed to be passed as <c>X-Method</c> headers.
4658    *    <br>The set is case-insensitive ordered.
4659    */
4660   public Set<String> getAllowedMethodHeaders() {
4661      return allowedMethodHeaders;
4662   }
4663
4664   /**
4665    * Allowed method URL parameters.
4666    *
4667    * <ul class='seealso'>
4668    *    <li class='jf'>{@link RestContext#REST_allowedMethodParams}
4669    * </ul>
4670    *
4671    * @return
4672    *    The method names allowed to be passed as <c>method</c> URL parameters.
4673    *    <br>The set is case-insensitive ordered.
4674    */
4675   public Set<String> getAllowedMethodParams() {
4676      return allowedMethodParams;
4677   }
4678
4679   /**
4680    * Returns the debug setting on this context for the specified method.
4681    *
4682    * @param method The java method.
4683    * @return The debug setting on this context or the debug value of the servlet context if not specified for this method.
4684    */
4685   public Enablement getDebug(Method method) {
4686      if (method == null)
4687         return null;
4688      return debugEnablement.find(method).orElse(debug);
4689   }
4690
4691   /**
4692    * Returns the name of the client version header name used by this resource.
4693    *
4694    * <ul class='seealso'>
4695    *    <li class='jf'>{@link RestContext#REST_clientVersionHeader}
4696    * </ul>
4697    *
4698    * @return
4699    *    The name of the client version header used by this resource.
4700    *    <br>Never <jk>null</jk>.
4701    */
4702   public String getClientVersionHeader() {
4703      return clientVersionHeader;
4704   }
4705
4706   /**
4707    * Returns the HTTP-part parser associated with this resource.
4708    *
4709    * <ul class='seealso'>
4710    *    <li class='jf'>{@link RestContext#REST_partParser}
4711    * </ul>
4712    *
4713    * @return
4714    *    The HTTP-part parser associated with this resource.
4715    *    <br>Never <jk>null</jk>.
4716    */
4717   public HttpPartParser getPartParser() {
4718      return partParser;
4719   }
4720
4721   /**
4722    * Returns the HTTP-part serializer associated with this resource.
4723    *
4724    * <ul class='seealso'>
4725    *    <li class='jf'>{@link RestContext#REST_partSerializer}
4726    * </ul>
4727    *
4728    * @return
4729    *    The HTTP-part serializer associated with this resource.
4730    *    <br>Never <jk>null</jk>.
4731    */
4732   public HttpPartSerializer getPartSerializer() {
4733      return partSerializer;
4734   }
4735
4736   /**
4737    * Returns the JSON-Schema generator associated with this resource.
4738    *
4739    * @return
4740    *    The HTTP-part serializer associated with this resource.
4741    *    <br>Never <jk>null</jk>.
4742    */
4743   public JsonSchemaGenerator getJsonSchemaGenerator() {
4744      return jsonSchemaGenerator;
4745   }
4746
4747   /**
4748    * Returns the explicit list of supported accept types for this resource.
4749    *
4750    * <ul class='seealso'>
4751    *    <li class='jf'>{@link RestContext#REST_serializers}
4752    *    <li class='jf'>{@link RestContext#REST_produces}
4753    * </ul>
4754    *
4755    * @return
4756    *    The supported <c>Accept</c> header values for this resource.
4757    *    <br>Never <jk>null</jk>.
4758    */
4759   public List<MediaType> getProduces() {
4760      return produces;
4761   }
4762
4763   /**
4764    * Returns the explicit list of supported content types for this resource.
4765    *
4766    * <ul class='seealso'>
4767    *    <li class='jf'>{@link RestContext#REST_parsers}
4768    *    <li class='jf'>{@link RestContext#REST_consumes}
4769    * </ul>
4770    *
4771    * @return
4772    *    The supported <c>Content-Type</c> header values for this resource.
4773    *    <br>Never <jk>null</jk>.
4774    */
4775   public List<MediaType> getConsumes() {
4776      return consumes;
4777   }
4778
4779   /**
4780    * Returns the default request headers for this resource.
4781    *
4782    * <ul class='seealso'>
4783    *    <li class='jf'>{@link RestContext#REST_reqHeaders}
4784    * </ul>
4785    *
4786    * @return
4787    *    The default request headers for this resource.
4788    *    <br>Never <jk>null</jk>.
4789    */
4790   public Map<String,Object> getReqHeaders() {
4791      return reqHeaders;
4792   }
4793
4794   /**
4795    * Returns the default request attributes for this resource.
4796    *
4797    * <ul class='seealso'>
4798    *    <li class='jf'>{@link RestContext#REST_reqAttrs}
4799    * </ul>
4800    *
4801    * @return
4802    *    The default request headers for this resource.
4803    *    <br>Never <jk>null</jk>.
4804    */
4805   public OMap getReqAttrs() {
4806      return reqAttrs;
4807   }
4808
4809   /**
4810    * Returns the default response headers for this resource.
4811    *
4812    * <ul class='seealso'>
4813    *    <li class='jf'>{@link RestContext#REST_resHeaders}
4814    * </ul>
4815    *
4816    * @return
4817    *    The default response headers for this resource.
4818    *    <br>Never <jk>null</jk>.
4819    */
4820   public Map<String,Object> getResHeaders() {
4821      return resHeaders;
4822   }
4823
4824   /**
4825    * Returns the response handlers associated with this resource.
4826    *
4827    * <ul class='seealso'>
4828    *    <li class='jf'>{@link RestContext#REST_responseHandlers}
4829    * </ul>
4830    *
4831    * @return
4832    *    The response handlers associated with this resource.
4833    *    <br>Never <jk>null</jk>.
4834    */
4835   protected ResponseHandler[] getResponseHandlers() {
4836      return responseHandlers;
4837   }
4838
4839   /**
4840    * Returns the authority path of the resource.
4841    *
4842    * <ul class='seealso'>
4843    *    <li class='jf'>{@link RestContext#REST_uriAuthority}
4844    * </ul>
4845    *
4846    * @return
4847    *    The authority path of this resource.
4848    *    <br>If not specified, returns the context path of the ascendant resource.
4849    */
4850   public String getUriAuthority() {
4851      if (uriAuthority != null)
4852         return uriAuthority;
4853      if (parentContext != null)
4854         return parentContext.getUriAuthority();
4855      return null;
4856   }
4857
4858   /**
4859    * Returns the context path of the resource.
4860    *
4861    * <ul class='seealso'>
4862    *    <li class='jf'>{@link RestContext#REST_uriContext}
4863    * </ul>
4864    *
4865    * @return
4866    *    The context path of this resource.
4867    *    <br>If not specified, returns the context path of the ascendant resource.
4868    */
4869   public String getUriContext() {
4870      if (uriContext != null)
4871         return uriContext;
4872      if (parentContext != null)
4873         return parentContext.getUriContext();
4874      return null;
4875   }
4876
4877   /**
4878    * Returns the setting on how relative URIs should be interpreted as relative to.
4879    *
4880    * <ul class='seealso'>
4881    *    <li class='jf'>{@link RestContext#REST_uriRelativity}
4882    * </ul>
4883    *
4884    * @return
4885    *    The URI-resolution relativity setting value.
4886    *    <br>Never <jk>null</jk>.
4887    */
4888   public UriRelativity getUriRelativity() {
4889      return uriRelativity;
4890   }
4891
4892   /**
4893    * Returns the setting on how relative URIs should be resolved.
4894    *
4895    * <ul class='seealso'>
4896    *    <li class='jf'>{@link RestContext#REST_uriResolution}
4897    * </ul>
4898    *
4899    * @return
4900    *    The URI-resolution setting value.
4901    *    <br>Never <jk>null</jk>.
4902    */
4903   public UriResolution getUriResolution() {
4904      return uriResolution;
4905   }
4906
4907   /**
4908    * Returns the media type for the specified file name.
4909    *
4910    * <ul class='seealso'>
4911    *    <li class='jf'>{@link RestContext#REST_mimeTypes}
4912    * </ul>
4913    *
4914    * @param name The file name.
4915    * @return The MIME-type, or <jk>null</jk> if it could not be determined.
4916    */
4917   public String getMediaTypeForName(String name) {
4918      return mimetypesFileTypeMap.getContentType(name);
4919   }
4920
4921   /**
4922    * Returns <jk>true</jk> if the specified path refers to a static file.
4923    *
4924    * <p>
4925    * Static files are files pulled from the classpath and served up directly to the browser.
4926    *
4927    * <ul class='seealso'>
4928    *    <li class='jf'>{@link RestContext#REST_staticFiles}
4929    * </ul>
4930    *
4931    * @param p The URL path remainder after the servlet match.
4932    * @return <jk>true</jk> if the specified path refers to a static file.
4933    */
4934   public boolean isStaticFile(String p) {
4935      return pathStartsWith(p, staticFilesPaths);
4936   }
4937
4938   /**
4939    * Returns the REST Java methods defined in this resource.
4940    *
4941    * <p>
4942    * These are the methods annotated with the {@link RestMethod @RestMethod} annotation.
4943    *
4944    * @return
4945    *    An unmodifiable map of Java method names to call method objects.
4946    */
4947   public List<RestMethodContext> getMethodContexts() {
4948      return methods;
4949   }
4950
4951   /**
4952    * Gives access to the internal stack trace database.
4953    *
4954    * @return The stack trace database.
4955    */
4956   public StackTraceDatabase getStackTraceDb() {
4957      return stackTraceDb;
4958   }
4959
4960   /**
4961    * Returns timing information on all method executions on this class.
4962    *
4963    * <p>
4964    * Timing information is maintained for any <ja>@RestResource</ja>-annotated and hook methods.
4965    *
4966    * @return A list of timing statistics ordered by average execution time descending.
4967    */
4968   public List<MethodExecStats> getMethodExecStats() {
4969      return methodExecStats.values().stream().sorted().collect(Collectors.toList());
4970   }
4971
4972   /**
4973    * Gives access to the internal stack trace database.
4974    *
4975    * @return The stack trace database.
4976    */
4977   public RestContextStats getStats() {
4978      return new RestContextStats(startTime, getMethodExecStats());
4979   }
4980
4981   /**
4982    * Returns the timing information returned by {@link #getMethodExecStats()} in a readable format.
4983    *
4984    * @return A report of all method execution times ordered by .
4985    */
4986   public String getMethodExecStatsReport() {
4987      StringBuilder sb = new StringBuilder()
4988         .append(" Method                         Runs      Running   Errors   Avg          Total     \n")
4989         .append("------------------------------ --------- --------- -------- ------------ -----------\n");
4990      getMethodExecStats()
4991         .stream()
4992         .sorted(Comparator.comparingDouble(MethodExecStats::getTotalTime).reversed())
4993         .forEach(x -> sb.append(String.format("%30s %9d %9d %9d %10dms %10dms\n", x.getMethod(), x.getRuns(), x.getRunning(), x.getErrors(), x.getAvgTime(), x.getTotalTime())));
4994      return sb.toString();
4995   }
4996
4997   /**
4998    * Finds the {@link RestMethodParam} instances to handle resolving objects on the calls to the specified Java method.
4999    *
5000    * @param mi The Java method being called.
5001    * @param isPreOrPost Whether this is a {@link HookEvent#PRE_CALL} or {@link HookEvent#POST_CALL}.
5002    * @param pathPattern The path pattern to match against.
5003    * @return The array of resolvers.
5004    * @throws ServletException If an annotation usage error was detected.
5005    */
5006   protected RestMethodParam[] findParams(MethodInfo mi, boolean isPreOrPost, UrlPathPattern pathPattern) throws ServletException {
5007
5008      List<ClassInfo> pt = mi.getParamTypes();
5009      RestMethodParam[] rp = new RestMethodParam[pt.size()];
5010      PropertyStore ps = getPropertyStore();
5011
5012      for (int i = 0; i < pt.size(); i++) {
5013
5014         ClassInfo t = pt.get(i);
5015         if (t.inner() != null) {
5016            Class<?> c = t.inner();
5017            rp[i] = paramResolvers.get(c);
5018            if (rp[i] == null)
5019               rp[i] = RestParamDefaults.STANDARD_RESOLVERS.get(c);
5020         }
5021
5022         ParamInfo mpi = mi.getParam(i);
5023
5024         if (mpi.hasAnnotation(Header.class)) {
5025            rp[i] = new RestParamDefaults.HeaderObject(mpi, ps);
5026         } else if (mpi.hasAnnotation(Attr.class)) {
5027            rp[i] = new RestParamDefaults.AttributeObject(mpi, ps);
5028         } else if (mpi.hasAnnotation(Query.class)) {
5029            rp[i] = new RestParamDefaults.QueryObject(mpi, ps);
5030         } else if (mpi.hasAnnotation(FormData.class)) {
5031            rp[i] = new RestParamDefaults.FormDataObject(mpi, ps);
5032         } else if (mpi.hasAnnotation(Path.class)) {
5033            rp[i] = new RestParamDefaults.PathObject(mpi, ps, pathPattern);
5034         } else if (mpi.hasAnnotation(Body.class)) {
5035            rp[i] = new RestParamDefaults.BodyObject(mpi, ps);
5036         } else if (mpi.hasAnnotation(Request.class)) {
5037            rp[i] = new RestParamDefaults.RequestObject(mpi, ps);
5038         } else if (mpi.hasAnnotation(Response.class)) {
5039            rp[i] = new RestParamDefaults.ResponseObject(mpi, ps);
5040         } else if (mpi.hasAnnotation(ResponseHeader.class)) {
5041            rp[i] = new RestParamDefaults.ResponseHeaderObject(mpi, ps);
5042         } else if (mpi.hasAnnotation(ResponseStatus.class)) {
5043            rp[i] = new RestParamDefaults.ResponseStatusObject(t);
5044         } else if (mpi.hasAnnotation(HasFormData.class)) {
5045            rp[i] = new RestParamDefaults.HasFormDataObject(mpi);
5046         } else if (mpi.hasAnnotation(HasQuery.class)) {
5047            rp[i] = new RestParamDefaults.HasQueryObject(mpi);
5048         } else if (mpi.hasAnnotation(org.apache.juneau.rest.annotation.Method.class)) {
5049            rp[i] = new RestParamDefaults.MethodObject(mi, t, mpi);
5050         }
5051
5052         if (rp[i] == null && ! isPreOrPost)
5053            throw new RestServletException("Invalid parameter specified for method ''{0}'' at index position {1}", mi.inner(), i);
5054      }
5055
5056      return rp;
5057   }
5058
5059
5060   //------------------------------------------------------------------------------------------------------------------
5061   // Call handling
5062   //------------------------------------------------------------------------------------------------------------------
5063
5064   /**
5065    * Wraps an incoming servlet request/response pair into a single {@link RestCall} object.
5066    *
5067    * <p>
5068    * This is the first method called by {@link #execute(HttpServletRequest, HttpServletResponse)}.
5069    *
5070    * @param req The rest request.
5071    * @param res The rest response.
5072    * @return The wrapped request/response pair.
5073    */
5074   protected RestCall createCall(HttpServletRequest req, HttpServletResponse res) {
5075      return new RestCall(this, req, res).logger(getCallLogger()).loggerConfig(getCallLoggerConfig());
5076   }
5077
5078   /**
5079    * Creates a {@link RestRequest} object based on the specified incoming {@link HttpServletRequest} object.
5080    *
5081    * <p>
5082    * This method is called immediately after {@link #startCall(RestCall)} has been called.
5083    *
5084    * @param call The current REST call.
5085    * @return The wrapped request object.
5086    * @throws ServletException If any errors occur trying to interpret the request.
5087    */
5088   public RestRequest createRequest(RestCall call) throws ServletException {
5089      return new RestRequest(call);
5090   }
5091
5092   /**
5093    * Creates a {@link RestResponse} object based on the specified incoming {@link HttpServletResponse} object
5094    * and the request returned by {@link #createRequest(RestCall)}.
5095    *
5096    * @param call The current REST call.
5097    * @return The wrapped response object.
5098    * @throws ServletException If any errors occur trying to interpret the request or response.
5099    */
5100   public RestResponse createResponse(RestCall call) throws ServletException {
5101      return new RestResponse(call);
5102   }
5103
5104   /**
5105    * The main service method.
5106    *
5107    * <p>
5108    * Subclasses can optionally override this method if they want to tailor the behavior of requests.
5109    *
5110    * @param r1 The incoming HTTP servlet request object.
5111    * @param r2 The incoming HTTP servlet response object.
5112    * @throws ServletException General servlet exception.
5113    * @throws IOException Thrown by underlying stream.
5114    */
5115   public void execute(HttpServletRequest r1, HttpServletResponse r2) throws ServletException, IOException {
5116
5117      RestCall call = createCall(r1, r2);
5118
5119      // Must be careful not to bleed thread-locals.
5120      if (this.call.get() != null)
5121         System.err.println("WARNING:  Thread-local call object was not cleaned up from previous request.  " + this + ", thread=["+Thread.currentThread().getId()+"]");
5122      this.call.set(call);
5123
5124      try {
5125         checkForInitException();
5126
5127         // If the resource path contains variables (e.g. @Rest(path="/f/{a}/{b}"), then we want to resolve
5128         // those variables and push the servletPath to include the resolved variables.  The new pathInfo will be
5129         // the remainder after the new servletPath.
5130         // Only do this for the top-level resource because the logic for child resources are processed next.
5131         if (pathPattern.hasVars() && getParentContext() == null) {
5132            String sp = call.getServletPath();
5133            String pi = call.getPathInfoUndecoded();
5134            UrlPathInfo upi2 = new UrlPathInfo(pi == null ? sp : sp + pi);
5135            UrlPathPatternMatch uppm = pathPattern.match(upi2);
5136            if (uppm != null && ! uppm.hasEmptyVars()) {
5137               call.addPathVars(uppm.getVars());
5138               call.request(
5139                  new OverrideableHttpServletRequest(call.getRequest())
5140                     .pathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))
5141                     .servletPath(uppm.getPrefix())
5142               );
5143            } else {
5144               call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
5145               return;
5146            }
5147         }
5148
5149         // If this resource has child resources, try to recursively call them.
5150         String pi = call.getPathInfoUndecoded();
5151         if ((! childResources.isEmpty()) && pi != null && ! pi.equals("/")) {
5152            for (RestContext rc : getChildResources().values()) {
5153               UrlPathPattern upp = rc.pathPattern;
5154               UrlPathPatternMatch uppm = upp.match(call.getUrlPathInfo());
5155               if (uppm != null) {
5156                  if (! uppm.hasEmptyVars()) {
5157                     call.addPathVars(uppm.getVars());
5158                     HttpServletRequest childRequest = new OverrideableHttpServletRequest(call.getRequest())
5159                        .pathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))
5160                        .servletPath(call.getServletPath() + uppm.getPrefix());
5161                     rc.execute(childRequest, call.getResponse());
5162                  } else {
5163                     call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
5164                  }
5165                  return;
5166               }
5167            }
5168         }
5169
5170         if (isDebug(call))
5171            call.debug(true);
5172
5173         startCall(call);
5174
5175         createRequest(call);
5176         createResponse(call);
5177
5178         StaticFile r = null;
5179         if (call.getPathInfoUndecoded() != null) {
5180            String p = call.getPathInfoUndecoded().substring(1);
5181            if (isStaticFile(p)) {
5182               r = getStaticFile(p);
5183               if (! r.exists()) {
5184                  call.output(null);
5185                  r = null;
5186               }
5187            } else if (p.equals("favicon.ico")) {
5188               call.output(null);
5189            }
5190         }
5191
5192         if (r != null) {
5193            call.status(SC_OK);
5194            call.output(r);
5195         } else {
5196
5197            // If the specified method has been defined in a subclass, invoke it.
5198            try {
5199               findMethod(call).invoke(call);
5200            } catch (NotFound e) {
5201               if (call.getStatus() == 0)
5202                  call.status(404);
5203               handleNotFound(call);
5204            }
5205         }
5206
5207         if (call.hasOutput()) {
5208            // Now serialize the output if there was any.
5209            // Some subclasses may write to the OutputStream or Writer directly.
5210            handleResponse(call);
5211         }
5212
5213
5214      } catch (Throwable e) {
5215         handleError(call, convertThrowable(e));
5216      } finally {
5217         clearState();
5218      }
5219
5220      call.finish();
5221      finishCall(call);
5222   }
5223
5224   private RestMethodContext findMethod(RestCall call) throws Throwable {
5225      String m = call.getMethod();
5226
5227      int rc = 0;
5228      if (methodMap.containsKey(m)) {
5229         for (RestMethodContext mc : methodMap.get(m)) {
5230            int mrc = mc.match(call);
5231            if (mrc == 2)
5232               return mc;
5233            rc = Math.max(rc, mrc);
5234         }
5235      }
5236
5237      if (methodMap.containsKey("*")) {
5238         for (RestMethodContext mc : methodMap.get("*")) {
5239            int mrc = mc.match(call);
5240            if (mrc == 2)
5241               return mc;
5242            rc = Math.max(rc, mrc);
5243         }
5244      }
5245
5246      // If no paths matched, see if the path matches any other methods.
5247      // Note that we don't want to match against "/*" patterns such as getOptions().
5248      if (rc == 0) {
5249         for (RestMethodContext mc : methods) {
5250            if (! mc.getPathPattern().endsWith("/*")) {
5251               int mrc = mc.match(call);
5252               if (mrc == 2)
5253                  throw new MethodNotAllowed();
5254            }
5255         }
5256      }
5257
5258      if (rc == 1)
5259         throw new PreconditionFailed("Method ''{0}'' not found on resource on path ''{1}'' with matching matcher.", m, call.getPathInfo());
5260
5261      throw new NotFound();
5262   }
5263
5264   private boolean isDebug(RestCall call) {
5265      Enablement e = null;
5266      RestMethodContext mc = call.getRestMethodContext();
5267      if (mc != null)
5268         e = mc.getDebug();
5269      if (e == null)
5270         e = getDebug();
5271      if (e == TRUE)
5272         return true;
5273      if (e == FALSE)
5274         return false;
5275      if (e == PER_REQUEST)
5276         return "true".equalsIgnoreCase(call.getRequest().getHeader("X-Debug"));
5277      return false;
5278   }
5279
5280   /**
5281    * The main method for serializing POJOs passed in through the {@link RestResponse#setOutput(Object)} method or
5282    * returned by the Java method.
5283    *
5284    * <p>
5285    * Subclasses may override this method if they wish to modify the way the output is rendered or support other output
5286    * formats.
5287    *
5288    * <p>
5289    * The default implementation simply iterates through the response handlers on this resource
5290    * looking for the first one whose {@link ResponseHandler#handle(RestRequest,RestResponse)} method returns
5291    * <jk>true</jk>.
5292    *
5293    * @param call The HTTP call.
5294    * @throws IOException Thrown by underlying stream.
5295    * @throws HttpException Non-200 response.
5296    * @throws NotImplemented No registered response handlers could handle the call.
5297    */
5298   public void handleResponse(RestCall call) throws IOException, HttpException, NotImplemented {
5299
5300      RestRequest req = call.getRestRequest();
5301      RestResponse res = call.getRestResponse();
5302
5303      // Loop until we find the correct handler for the POJO.
5304      for (ResponseHandler h : getResponseHandlers())
5305         if (h.handle(req, res))
5306            return;
5307
5308      Object output = res.getOutput();
5309      throw new NotImplemented("No response handlers found to process output of type '"+(output == null ? null : output.getClass().getName())+"'");
5310   }
5311
5312   /**
5313    * Method that can be subclassed to allow uncaught throwables to be treated as other types of throwables.
5314    *
5315    * <p>
5316    * The default implementation looks at the throwable class name to determine whether it can be converted to another type:
5317    *
5318    * <ul>
5319    *    <li><js>"*AccessDenied*"</js> - Converted to {@link Unauthorized}.
5320    *    <li><js>"*Empty*"</js>,<js>"*NotFound*"</js> - Converted to {@link NotFound}.
5321    * </ul>
5322    *
5323    * @param t The thrown object.
5324    * @return The converted thrown object.
5325    */
5326   @SuppressWarnings("deprecation")
5327   public Throwable convertThrowable(Throwable t) {
5328
5329      ClassInfo ci = ClassInfo.ofc(t);
5330      if (ci.is(InvocationTargetException.class)) {
5331         t = ((InvocationTargetException)t).getTargetException();
5332         ci = ClassInfo.ofc(t);
5333      }
5334
5335      if (ci.is(HttpRuntimeException.class)) {
5336         t = ((HttpRuntimeException)t).getInner();
5337         ci = ClassInfo.ofc(t);
5338      }
5339
5340      if (ci.isChildOf(RestException.class) || ci.hasAnnotation(Response.class))
5341         return t;
5342
5343      if (t instanceof ParseException || t instanceof InvalidDataConversionException)
5344         return new BadRequest(t);
5345
5346      String n = t.getClass().getName();
5347
5348      if (n.contains("AccessDenied") || n.contains("Unauthorized"))
5349         return new Unauthorized(t);
5350
5351      if (n.contains("Empty") || n.contains("NotFound"))
5352         return new NotFound(t);
5353
5354      return t;
5355   }
5356
5357   /**
5358    * Handle the case where a matching method was not found.
5359    *
5360    * <p>
5361    * Subclasses can override this method to provide a 2nd-chance for specifying a response.
5362    * The default implementation will simply throw an exception with an appropriate message.
5363    *
5364    * @param call The HTTP call.
5365    * @throws Exception Any exception can be thrown.
5366    */
5367   public void handleNotFound(RestCall call) throws Exception {
5368      String pathInfo = call.getPathInfo();
5369      String methodUC = call.getMethod();
5370      int rc = call.getStatus();
5371      String onPath = pathInfo == null ? " on no pathInfo"  : String.format(" on path '%s'", pathInfo);
5372      if (rc == SC_NOT_FOUND)
5373         throw new NotFound("Method ''{0}'' not found on resource with matching pattern{1}.", methodUC, onPath);
5374      else if (rc == SC_PRECONDITION_FAILED)
5375         throw new PreconditionFailed("Method ''{0}'' not found on resource{1} with matching matcher.", methodUC, onPath);
5376      else if (rc == SC_METHOD_NOT_ALLOWED)
5377         throw new MethodNotAllowed("Method ''{0}'' not found on resource{1}.", methodUC, onPath);
5378      else
5379         throw new ServletException("Invalid method response: " + rc);
5380   }
5381
5382   /**
5383    * Method for handling response errors.
5384    *
5385    * <p>
5386    * Subclasses can override this method to provide their own custom error response handling.
5387    *
5388    * @param call The rest call.
5389    * @param e The exception that occurred.
5390    * @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
5391    */
5392   @SuppressWarnings("deprecation")
5393   public synchronized void handleError(RestCall call, Throwable e) throws IOException {
5394
5395      call.exception(e);
5396
5397      if (call.isDebug())
5398         e.printStackTrace();
5399
5400      int occurrence = getStackTraceOccurrence(e);
5401
5402      int code = 500;
5403
5404      ClassInfo ci = ClassInfo.ofc(e);
5405      Response r = ci.getLastAnnotation(Response.class);
5406      if (r != null)
5407         if (r.code().length > 0)
5408            code = r.code()[0];
5409
5410      RestException e2 = (e instanceof RestException ? (RestException)e : new RestException(e, code)).setOccurrence(occurrence);
5411
5412      HttpServletRequest req = call.getRequest();
5413      HttpServletResponse res = call.getResponse();
5414
5415      Throwable t = null;
5416      if (e instanceof HttpRuntimeException)
5417         t = ((HttpRuntimeException)e).getInner();
5418      if (t == null)
5419         t = e2.getRootCause();
5420      if (t != null) {
5421         res.setHeader("Exception-Name", stripInvalidHttpHeaderChars(t.getClass().getName()));
5422         res.setHeader("Exception-Message", stripInvalidHttpHeaderChars(t.getMessage()));
5423      }
5424
5425      try {
5426         res.setContentType("text/plain");
5427         res.setHeader("Content-Encoding", "identity");
5428         res.setStatus(e2.getStatus());
5429
5430         PrintWriter w = null;
5431         try {
5432            w = res.getWriter();
5433         } catch (IllegalStateException x) {
5434            w = new PrintWriter(new OutputStreamWriter(res.getOutputStream(), UTF8));
5435         }
5436
5437         try (PrintWriter w2 = w) {
5438            String httpMessage = RestUtils.getHttpResponseText(e2.getStatus());
5439            if (httpMessage != null)
5440               w2.append("HTTP ").append(String.valueOf(e2.getStatus())).append(": ").append(httpMessage).append("\n\n");
5441            if (isRenderResponseStackTraces())
5442               e.printStackTrace(w2);
5443            else
5444               w2.append(e2.getFullStackMessage(true));
5445         }
5446
5447      } catch (Exception e1) {
5448         req.setAttribute("Exception", e1);
5449      }
5450   }
5451
5452   /**
5453    * Returns the session objects for the specified request.
5454    *
5455    * <p>
5456    * The default implementation simply returns a single map containing <c>{'req':req,'res',res}</c>.
5457    *
5458    * @param call The current REST call.
5459    * @return The session objects for that request.
5460    */
5461   public Map<String,Object> getSessionObjects(RestCall call) {
5462      Map<String,Object> m = new HashMap<>();
5463      m.put("req", call.getRequest());
5464      m.put("res", call.getResponse());
5465      return m;
5466   }
5467
5468   /**
5469    * Called at the start of a request to invoke all {@link HookEvent#START_CALL} methods.
5470    *
5471    * @param call The current request.
5472    */
5473   protected void startCall(RestCall call) {
5474      for (int i = 0; i < startCallMethods.length; i++)
5475         startOrFinish(resource, startCallMethods[i], startCallMethodParams[i], call.getRequest(), call.getResponse());
5476   }
5477
5478   /**
5479    * Called during a request to invoke all {@link HookEvent#PRE_CALL} methods.
5480    *
5481    * @param call The current request.
5482    * @throws HttpException If thrown from call methods.
5483    */
5484   protected void preCall(RestCall call) throws HttpException {
5485      for (int i = 0; i < preCallMethods.length; i++)
5486         preOrPost(resource, preCallMethods[i], preCallMethodParams[i], call);
5487   }
5488
5489   /**
5490    * Called during a request to invoke all {@link HookEvent#POST_CALL} methods.
5491    *
5492    * @param call The current request.
5493    * @throws HttpException If thrown from call methods.
5494    */
5495   protected void postCall(RestCall call) throws HttpException {
5496      for (int i = 0; i < postCallMethods.length; i++)
5497         preOrPost(resource, postCallMethods[i], postCallMethodParams[i], call);
5498   }
5499
5500   private static void preOrPost(Object resource, MethodInvoker m, RestMethodParam[] mp, RestCall call) throws HttpException {
5501      if (m != null) {
5502         Object[] args = new Object[mp.length];
5503         for (int i = 0; i < mp.length; i++) {
5504            try {
5505               args[i] = mp[i].resolve(call.getRestRequest(), call.getRestResponse());
5506            } catch (Exception e) {
5507               throw toHttpException(e, BadRequest.class, "Invalid data conversion.  Could not convert {0} ''{1}'' to type ''{2}'' on method ''{3}.{4}''.", mp[i].getParamType().name(), mp[i].getName(), mp[i].getType(), m.getDeclaringClass().getName(), m.getName());
5508            }
5509         }
5510         try {
5511            m.invoke(resource, args);
5512         } catch (Exception e) {
5513            throw toHttpException(e, InternalServerError.class);
5514         }
5515      }
5516   }
5517
5518   /**
5519    * Called at the end of a request to invoke all {@link HookEvent#END_CALL} methods.
5520    *
5521    * <p>
5522    * This is the very last method called in {@link #execute(HttpServletRequest, HttpServletResponse)}.
5523    *
5524    * @param call The current request.
5525    */
5526   protected void finishCall(RestCall call) {
5527      for (int i = 0; i < endCallMethods.length; i++)
5528         startOrFinish(resource, endCallMethods[i], endCallMethodParams[i], call.getRequest(), call.getResponse());
5529   }
5530
5531   private static void startOrFinish(Object resource, MethodInvoker m, Class<?>[] p, HttpServletRequest req, HttpServletResponse res) throws HttpException, InternalServerError {
5532      if (m != null) {
5533         Object[] args = new Object[p.length];
5534         for (int i = 0; i < p.length; i++) {
5535            if (p[i] == HttpServletRequest.class)
5536               args[i] = req;
5537            else if (p[i] == HttpServletResponse.class)
5538               args[i] = res;
5539         }
5540         try {
5541            m.invoke(resource, args);
5542         } catch (Exception e) {
5543            throw toHttpException(e, InternalServerError.class);
5544         }
5545      }
5546   }
5547
5548   /**
5549    * Called during servlet initialization to invoke all {@link HookEvent#POST_INIT} methods.
5550    *
5551    * @return This object (for method chaining).
5552    * @throws ServletException Error occurred.
5553    */
5554   public RestContext postInit() throws ServletException {
5555      for (int i = 0; i < postInitMethods.length; i++)
5556         postInitOrDestroy(resource, postInitMethods[i], postInitMethodParams[i]);
5557      for (RestContext childContext : this.childResources.values())
5558         childContext.postInit();
5559      return this;
5560   }
5561
5562   /**
5563    * Called during servlet initialization to invoke all {@link HookEvent#POST_INIT_CHILD_FIRST} methods.
5564    *
5565    * @return This object (for method chaining).
5566    * @throws ServletException Error occurred.
5567    */
5568   public RestContext postInitChildFirst() throws ServletException {
5569      for (RestContext childContext : this.childResources.values())
5570         childContext.postInitChildFirst();
5571      for (int i = 0; i < postInitChildFirstMethods.length; i++)
5572         postInitOrDestroy(resource, postInitChildFirstMethods[i], postInitChildFirstMethodParams[i]);
5573      return this;
5574   }
5575
5576   private void postInitOrDestroy(Object r, MethodInvoker m, Class<?>[] p) {
5577      if (m != null) {
5578         Object[] args = new Object[p.length];
5579         for (int i = 0; i < p.length; i++) {
5580            if (p[i] == RestContext.class)
5581               args[i] = this;
5582            else if (p[i] == RestContextBuilder.class)
5583               args[i] = this.builder;
5584            else if (p[i] == ServletConfig.class)
5585               args[i] = this.builder.inner;
5586         }
5587         try {
5588            m.invoke(r, args);
5589         } catch (Exception e) {
5590            if (e instanceof RuntimeException && ClassInfo.of(e).hasAnnotation(Response.class))
5591               throw (RuntimeException)e;
5592            throw new InternalServerError(e);
5593         }
5594      }
5595   }
5596
5597   /**
5598    * Called during servlet initialization to invoke all {@link HookEvent#DESTROY} methods.
5599    */
5600   protected void destroy() {
5601      for (int i = 0; i < destroyMethods.length; i++) {
5602         try {
5603            postInitOrDestroy(resource, destroyMethods[i], destroyMethodParams[i]);
5604         } catch (Exception e) {
5605            e.printStackTrace();
5606         }
5607      }
5608
5609      for (RestContext r : childResources.values()) {
5610         r.destroy();
5611         if (r.resource instanceof Servlet)
5612            ((Servlet)r.resource).destroy();
5613      }
5614   }
5615
5616   /**
5617    * Returns the HTTP request object for the current request.
5618    *
5619    * @return The HTTP request object, or <jk>null</jk> if it hasn't been created.
5620    */
5621   public RestRequest getRequest() {
5622      RestCall rc = call.get();
5623      return rc == null ? null : rc.getRestRequest();
5624   }
5625
5626   /**
5627    * Returns the HTTP response object for the current request.
5628    *
5629    * @return The HTTP response object, or <jk>null</jk> if it hasn't been created.
5630    */
5631   public RestResponse getResponse() {
5632      RestCall rc = call.get();
5633      return rc == null ? null : rc.getRestResponse();
5634   }
5635
5636   /**
5637    * If the specified object is annotated with {@link Response}, this returns the response metadata about that object.
5638    *
5639    * @param o The object to check.
5640    * @return The response metadata, or <jk>null</jk> if it wasn't annotated with {@link Response}.
5641    */
5642   public ResponseBeanMeta getResponseBeanMeta(Object o) {
5643      if (o == null)
5644         return null;
5645      Class<?> c = o.getClass();
5646      ResponseBeanMeta rbm = responseBeanMetas.get(c);
5647      if (rbm == null) {
5648         rbm = ResponseBeanMeta.create(c, serializers.getPropertyStore());
5649         if (rbm == null)
5650            rbm = ResponseBeanMeta.NULL;
5651         responseBeanMetas.put(c, rbm);
5652      }
5653      if (rbm == ResponseBeanMeta.NULL)
5654         return null;
5655      return rbm;
5656   }
5657
5658   Enablement getDebug() {
5659      return debug;
5660   }
5661
5662   /**
5663    * Clear any request state information on this context.
5664    * This should always be called in a finally block in the RestServlet.
5665    */
5666   void clearState() {
5667      call.remove();
5668   }
5669
5670   //-----------------------------------------------------------------------------------------------------------------
5671   // Other methods.
5672   //-----------------------------------------------------------------------------------------------------------------
5673
5674   @Override /* Context */
5675   public OMap toMap() {
5676      return super.toMap()
5677         .a("RestContext", new DefaultFilteringOMap()
5678            .a("allowBodyParam", allowBodyParam)
5679            .a("allowedMethodHeader", allowedMethodHeaders)
5680            .a("allowedMethodParams", allowedMethodParams)
5681            .a("allowedHeaderParams", allowedHeaderParams)
5682            .a("clientVersionHeader", clientVersionHeader)
5683            .a("consumes", consumes)
5684            .a("infoProvider", infoProvider)
5685            .a("logger", logger)
5686            .a("paramResolvers", paramResolvers)
5687            .a("parsers", parsers)
5688            .a("partParser", partParser)
5689            .a("partSerializer", partSerializer)
5690            .a("produces", produces)
5691            .a("properties", properties)
5692            .a("renderResponseStackTraces", renderResponseStackTraces)
5693            .a("reqHeaders", reqHeaders)
5694            .a("resHeaders", resHeaders)
5695            .a("resourceResolver", resourceResolver)
5696            .a("responseHandlers", responseHandlers)
5697            .a("serializers", serializers)
5698            .a("staticFileResponseHeaders", staticFileResponseHeaders)
5699            .a("staticFiles", staticFiles)
5700            .a("uriAuthority", uriAuthority)
5701            .a("uriContext", uriContext)
5702            .a("uriRelativity", uriRelativity)
5703            .a("uriResolution", uriResolution)
5704            .a("useClasspathResourceCaching", useClasspathResourceCaching)
5705         );
5706   }
5707
5708   //-----------------------------------------------------------------------------------------------------------------
5709   // Helpers.
5710   //-----------------------------------------------------------------------------------------------------------------
5711
5712   static class MethodMapBuilder  {
5713      TreeMap<String,TreeSet<RestMethodContext>> map = new TreeMap<>();
5714      Set<RestMethodContext> set = ASet.of();
5715
5716
5717      MethodMapBuilder add(String httpMethodName, RestMethodContext mc) {
5718         httpMethodName = httpMethodName.toUpperCase();
5719         if (! map.containsKey(httpMethodName))
5720            map.put(httpMethodName, new TreeSet<>());
5721         map.get(httpMethodName).add(mc);
5722         set.add(mc);
5723         return this;
5724      }
5725
5726      Map<String,List<RestMethodContext>> getMap() {
5727         AMap<String,List<RestMethodContext>> m = AMap.of();
5728         for (Map.Entry<String,TreeSet<RestMethodContext>> e : map.entrySet())
5729            m.put(e.getKey(), AList.of(e.getValue()));
5730         return m.unmodifiable();
5731      }
5732
5733      List<RestMethodContext> getList() {
5734         return AList.of(set).unmodifiable();
5735      }
5736   }
5737}