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