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