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