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