http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/07843d64/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
new file mode 100644
index 0000000..8e10182
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
@@ -0,0 +1,1153 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.internal.ArrayUtils.*;
+import static org.apache.juneau.serializer.SerializerContext.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.activation.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.encoders.*;
+import org.apache.juneau.encoders.Encoder;
+import org.apache.juneau.ini.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.response.*;
+import org.apache.juneau.rest.vars.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
+import org.apache.juneau.svl.vars.*;
+
+/**
+ * Defines the initial configuration of a <code>RestServlet</code> or 
<code>@RestResource</code> annotated object.
+ * <p>
+ * An extension of the {@link ServletConfig} object used during servlet 
initialization.
+ * <p>
+ * Provides access to the following initialized resources:
+ * <ul>
+ *     <li>{@link #getConfigFile()} - The external configuration file for this 
resource.
+ *     <li>{@link #getProperties()} - The modifiable configuration properties 
for this resource.
+ *     <li>{@link #getVarResolverBuilder()} - The variable resolver for this 
resource.
+ * </ul>
+ * <p>
+ * Methods are provided for overriding or augmenting the information provided 
by the <ja>@RestResource</ja> annotation.
+ * In general, most information provided in the <ja>@RestResource</ja> 
annotation can be specified programmatically
+ * through calls on this object.
+ * <p>
+ * To interact with this object, simply implement the following init method in 
your resource class:
+ * <p class='bcode'>
+ *     <jk>public synchronized void</jk> init(RestConfig config) 
<jk>throws</jk> Exception {
+ *             
config.addPojoSwaps(CalendarSwap.<jsf>RFC2822DTZ</jsf>.<jk>class</jk>);
+ *             config.setProperty(<jsf>PARSER_debug</jsf>, <jk>true</jk>);
+ *             <jk>super</jk>.init(config); <jc>// Make sure this is the last 
line! (or just leave it out entirely)</jc>
+ *     }
+ * </p>
+ * <p>
+ * Note that this method is identical to {@link 
HttpServlet#init(ServletConfig)} except you get access to
+ * this object instead.  Also, this method can throw any exception, not just a 
{@link ServletException}.
+ * <p>
+ * The parent <code>init(RestServletConfig)</code> method will construct a 
read-only {@link RestContext} object
+ * that contains a snapshot of these settings.  If you call 
<code><jk>super</jk>.init(RestServletConfig)<code> before
+ * you modify this config object, you won't see the changes!
+ */
+@SuppressWarnings("hiding")
+public class RestConfig implements ServletConfig {
+
+       final ServletConfig inner;
+
+       
//---------------------------------------------------------------------------
+       // The following fields are meant to be modifiable.
+       // They should not be declared final.
+       // Read-only snapshots of these will be made in RestServletContext.
+       
//---------------------------------------------------------------------------
+
+       ObjectMap properties;
+       ConfigFile configFile;
+       VarResolverBuilder varResolverBuilder;
+
+       List<Class<?>>
+               beanFilters = new ArrayList<Class<?>>(),
+               pojoSwaps = new ArrayList<Class<?>>();
+       SerializerGroupBuilder serializers = new SerializerGroupBuilder();
+       ParserGroupBuilder parsers = new ParserGroupBuilder();
+       EncoderGroupBuilder encoders = new 
EncoderGroupBuilder().append(IdentityEncoder.INSTANCE);
+       List<Object> converters = new ArrayList<Object>();
+       List<Object> guards = new ArrayList<Object>();
+       MimetypesFileTypeMap mimeTypes = new MimetypesFileTypeMap();
+       Map<String,String> defaultRequestHeaders = new 
TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
+       Map<String,Object> defaultResponseHeaders = new 
LinkedHashMap<String,Object>();
+       List<Object> responseHandlers = new ArrayList<Object>();
+       List<Object> childResources = new ArrayList<Object>();
+       List<MediaType> supportedContentTypes, supportedAcceptTypes;
+       List<Object> styleSheets;
+       Object favIcon;
+       List<Object> staticFiles;
+       RestContext parentContext;
+       String path;
+       String clientVersionHeader = "X-Client-Version";
+
+       Object resourceResolver = RestResourceResolver.class;
+       Object logger = RestLogger.Normal.class;
+       Object callHandler = RestCallHandler.class;
+       Object infoProvider = RestInfoProvider.class;
+
+       /**
+        * Constructor.
+        * @param config The servlet config passed into the servlet by the 
servlet container.
+        * @param resource The class annotated with <ja>@RestResource</ja>.
+        * @throws ServletException Something bad happened.
+        */
+       RestConfig(ServletConfig config, Class<?> resourceClass, RestContext 
parentContext) throws ServletException {
+               this.inner = config;
+               this.parentContext = parentContext;
+               try {
+
+                       properties = new ObjectMap();
+                       configFile = ConfigMgr.DEFAULT.create();
+                       varResolverBuilder = new VarResolverBuilder()
+                               .vars(
+                                       SystemPropertiesVar.class,
+                                       EnvVariablesVar.class,
+                                       ConfigFileVar.class,
+                                       IfVar.class,
+                                       SwitchVar.class
+                               );
+
+                       VarResolver vr = varResolverBuilder.build();
+
+                       Map<Class<?>,RestResource> 
restResourceAnnotationsParentFirst = 
ReflectionUtils.findAnnotationsMapParentFirst(RestResource.class, 
resourceClass);
+
+                       // Find our config file.  It's the last non-empty 
@RestResource.config().
+                       String configPath = "";
+                       for (RestResource r : 
restResourceAnnotationsParentFirst.values())
+                               if (! r.config().isEmpty())
+                                       configPath = r.config();
+                       String cf = vr.resolve(configPath);
+                       if (! cf.isEmpty())
+                               configFile = ConfigMgr.DEFAULT.get(cf);
+                       configFile = configFile.getResolving(vr);
+
+                       // Add our config file to the variable resolver.
+                       
varResolverBuilder.contextObject(ConfigFileVar.SESSION_config, configFile);
+                       vr = varResolverBuilder.build();
+
+                       // Add our servlet URI to our properties.
+                       ServletContext ctx = config.getServletContext();
+                       String ctxPath = ctx.getContextPath();
+                       // Workaround for bug in Jetty that causes context path 
to always end in "null".
+                       if (ctxPath.endsWith("null"))
+                               ctxPath = ctxPath.substring(0, 
ctxPath.length()-4);
+                       properties.put(SERIALIZER_relativeUriBase, ctxPath);
+
+                       // Add the servlet init parameters to our properties.
+                       for (Enumeration<String> ep = 
config.getInitParameterNames(); ep.hasMoreElements();) {
+                               String p = ep.nextElement();
+                               String initParam = config.getInitParameter(p);
+                               properties.put(vr.resolve(p), 
vr.resolve(initParam));
+                       }
+
+                       // Load stuff from parent-to-child order.
+                       // This allows child settings to overwrite parent 
settings.
+                       for (Map.Entry<Class<?>,RestResource> e : 
restResourceAnnotationsParentFirst.entrySet()) {
+                               Class<?> c = e.getKey();
+                               RestResource r = e.getValue();
+                               for (Property p : r.properties())
+                                       properties.append(vr.resolve(p.name()), 
vr.resolve(p.value()));
+                               addSerializers(reverse(r.serializers()));  // 
TODO - why reverse?
+                               addParsers(reverse(r.parsers()));  // TODO - 
why reverse?
+                               addEncoders(reverse(r.encoders()));  // TODO - 
why reverse?
+                               
addDefaultRequestHeaders(r.defaultRequestHeaders());
+                               
addDefaultResponseHeaders(r.defaultResponseHeaders());
+                               addResponseHandlers(r.responseHandlers());
+                               addConverters(r.converters());
+                               addGuards(reverse(r.guards()));
+                               addChildResources(r.children());
+                               addBeanFilters(r.beanFilters());
+                               addPojoSwaps(r.pojoSwaps());
+                               if (! r.stylesheet().isEmpty())
+                                       setStyleSheet(c, r.stylesheet());
+                               if (! r.favicon().isEmpty())
+                                       setFavIcon(c, r.favicon());
+                               if (! r.staticFiles().isEmpty())
+                                       addStaticFiles(c, r.staticFiles());
+                               if (! r.path().isEmpty())
+                                       setPath(r.path());
+                               if (! r.clientVersionHeader().isEmpty())
+                                       
setClientVersionHeader(r.clientVersionHeader());
+                               if (r.resourceResolver() != 
RestResourceResolver.class)
+                                       
setResourceResolver(r.resourceResolver());
+                               if (r.logger() != RestLogger.Normal.class)
+                                       setLogger(r.logger());
+                               if (r.callHandler() != RestCallHandler.class)
+                                       setCallHandler(r.callHandler());
+                               if (r.infoProvider() != RestInfoProvider.class)
+                                       setInfoProvider(r.infoProvider());
+                       }
+
+                       addResponseHandlers(
+                               StreamableHandler.class,
+                               WritableHandler.class,
+                               ReaderHandler.class,
+                               InputStreamHandler.class,
+                               RedirectHandler.class,
+                               DefaultHandler.class
+                       );
+
+                       addMimeTypes(
+                               "text/css css CSS",
+                               "text/html html htm HTML",
+                               "text/plain txt text TXT",
+                               "application/javascript js",
+                               "image/png png",
+                               "image/gif gif",
+                               "application/xml xml XML",
+                               "application/json json JSON"
+                       );
+               } catch (Exception e) {
+                       throw new ServletException(e);
+               }
+       }
+
+       /**
+        * Adds the specified {@link Var} classes to this config.
+        * <p>
+        * These variables affect the variable resolver returned by {@link 
RestRequest#getVarResolverSession()} which is
+        * used to resolve string variables of the form <js>"$X{...}"</js>.
+        * <p>
+        * By default, this config includes the following variables:
+        * <ul class='spaced-list'>
+        *      <li>{@link SystemPropertiesVar}
+        *      <li>{@link EnvVariablesVar}
+        *      <li>{@link ConfigFileVar}
+        *      <li>{@link IfVar}
+        *      <li>{@link SwitchVar}
+        * </ul>
+        * <p>
+        * Later during the construction of {@link RestContext}, we add the 
following variables:
+        * <ul>
+        *      <li>{@link LocalizationVar}
+        *      <li>{@link RequestVar}
+        *      <li>{@link SerializedRequestAttrVar}
+        *      <li>{@link ServletInitParamVar}
+        *      <li>{@link UrlEncodeVar}
+        * </ul>
+        *
+        * @param vars The {@link Var} classes to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addVars(Class<?>...vars) {
+               this.varResolverBuilder.vars(vars);
+               return this;
+       }
+
+       /**
+        * Adds a var context object to this config.
+        * <p>
+        * Var context objects are read-only objects associated with the 
variable resolver for
+        * vars that require external information.
+        * <p>
+        * For example, the {@link ConfigFileVar} needs access to this 
resource's {@link ConfigFile} through the {@link ConfigFileVar#SESSION_config}
+        * object that can be specified as either a session object (temporary) 
or context object (permanent).
+        * In this case, we call the following code to add it to the context 
map:
+        * <p class='bcode'>
+        *      config.addVarContextObject(<jsf>SESSION_config</jsf>, 
configFile);
+        * </p>
+        *
+        * @param name The context object key (i.e. the name that the Var class 
looks for).
+        * @param object The context object.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addVarContextObject(String name, Object object) {
+               this.varResolverBuilder.contextObject(name, object);
+               return this;
+       }
+
+       /**
+        * Overwrites the default config file with a custom config file.
+        * <p>
+        * By default, the config file is determined using the {@link 
RestResource#config() @RestResource.config()} annotation.
+        * This method allows you to programmatically override it with your own 
custom config file.
+        *
+        * @param configFile The new config file.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setConfigFile(ConfigFile configFile) {
+               this.configFile = configFile;
+               return this;
+       }
+
+       /**
+        * Sets a property on this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#properties()} annotation.
+        *
+        * @param key The property name.
+        * @param value The property value.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setProperty(String key, Object value) {
+               this.properties.put(key, value);
+               return this;
+       }
+
+       /**
+        * Sets multiple properties on this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#properties() @RestResource.properties()} annotation.
+        * <p>
+        * Values in the map are added to the existing properties and are 
overwritten if duplicates are found.
+        *
+        * @param properties The new properties to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setProperties(Map<String,Object> properties) {
+               this.properties.putAll(properties);
+               return this;
+       }
+
+       /**
+        * Adds class-level bean filters to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#beanFilters() @RestResource.beanFilters()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param beanFilters The bean filters to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addBeanFilters(Class<?>...beanFilters) {
+               this.beanFilters.addAll(Arrays.asList(beanFilters));
+               return this;
+       }
+
+       /**
+        * Adds class-level pojo swaps to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#pojoSwaps() @RestResource.pojoSwaps()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param pojoSwaps The pojo swaps to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addPojoSwaps(Class<?>...pojoSwaps) {
+               this.pojoSwaps.addAll(Arrays.asList(pojoSwaps));
+               return this;
+       }
+
+       /**
+        * Adds class-level serializers to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#serializers() @RestResource.serializers()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param serializers The serializer classes to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addSerializers(Class<?>...serializers) {
+               this.serializers.append(serializers);
+               return this;
+       }
+
+       /**
+        * Adds class-level serializers to this resource.
+        * <p>
+        * Same as {@link #addSerializers(Class...)} except allows you to pass 
in serializer instances.
+        * The actual serializer ends up being the result of this operation 
using the bean filters, pojo swaps, and properties on this config:
+        * <p class='bcode'>
+        *      serializer = 
serializer.builder().beanFilters(beanFilters).pojoSwaps(pojoSwaps).properties(properties).build();
+        * </p>
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param serializers The serializers to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addSerializers(Serializer...serializers) {
+               this.serializers.append(serializers);
+               return this;
+       }
+
+       /**
+        * Adds class-level parsers to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#parsers() @RestResource.parsers()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param parsers The parser classes to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addParsers(Class<?>...parsers) {
+               this.parsers.append(parsers);
+               return this;
+       }
+
+       /**
+        * Adds class-level parsers to this resource.
+        * <p>
+        * Same as {@link #addParsers(Class...)} except allows you to pass in 
parser instances.
+        * The actual parser ends up being the result of this operation using 
the bean filters, pojo swaps, and properties on this config:
+        * <p class='bcode'>
+        *      parser = 
parser.builder().beanFilters(beanFilters).pojoSwaps(pojoSwaps).properties(properties).build();
+        * </p>
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param parsers The parsers to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addParsers(Parser...parsers) {
+               this.parsers.append(parsers);
+               return this;
+       }
+
+       /**
+        * Adds class-level encoders to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#encoders() @RestResource.encoders()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        * <p>
+        * By default, only the {@link IdentityEncoder} is included in this 
list.
+        *
+        * @param encoders The parser classes to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addEncoders(Class<?>...encoders) {
+               this.encoders.append(encoders);
+               return this;
+       }
+
+       /**
+        * Adds class-level encoders to this resource.
+        * <p>
+        * Same as {@link #addEncoders(Class...)} except allows you to pass in 
encoder instances.
+        *
+        * @param encoders The encoders to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addEncoders(Encoder...encoders) {
+               this.encoders.append(encoders);
+               return this;
+       }
+
+       /**
+        * Adds class-level converters to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#converters() @RestResource.converters()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        * <p>
+        * By default, this config includes the following converters:
+        * <ul class='spaced-list'>
+        *      <li>{@link StreamableHandler}
+        *      <li>{@link WritableHandler}
+        *      <li>{@link ReaderHandler}
+        *      <li>{@link InputStreamHandler}
+        *      <li>{@link RedirectHandler}
+        *      <li>{@link DefaultHandler}
+        * </ul>
+        *
+        * @param converters The converter classes to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addConverters(Class<?>...converters) {
+               this.converters.addAll(Arrays.asList(converters));
+               return this;
+       }
+
+       /**
+        * Adds class-level encoders to this resource.
+        * <p>
+        * Same as {@link #addConverters(Class...)} except allows you to pass 
in converter instances.
+        *
+        * @param converters The converters to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addConverters(RestConverter...converters) {
+               this.converters.addAll(Arrays.asList(converters));
+               return this;
+       }
+
+       /**
+        * Adds class-level guards to this resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#guards() @RestResource.guards()} annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param guards The guard classes to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addGuards(Class<?>...guards) {
+               this.guards.addAll(Arrays.asList(guards));
+               return this;
+       }
+
+       /**
+        * Adds class-level guards to this resource.
+        * <p>
+        * Same as {@link #addGuards(Class...)} except allows you to pass in 
guard instances.
+        *
+        * @param guards The guards to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addGuards(RestGuard...guards) {
+               this.guards.addAll(Arrays.asList(guards));
+               return this;
+       }
+
+       /**
+        * Adds MIME-type definitions.
+        * <p>
+        * These definitions are used in the following locations for setting 
the media type on responses:
+        * <ul>
+        *      <li>{@link RestRequest#getReaderResource(String)}
+        *      <li>Static files resolved through {@link 
RestResource#staticFiles()}
+        * </ul>
+        * <p>
+        * Refer to {@link MimetypesFileTypeMap#addMimeTypes(String)} for an 
explanation of the format.
+        * <p>
+        * By default, this config includes the following mime-type definitions:
+        * <ul class='spaced-list'>
+        *      <li><js>"text/css css CSS"</js>
+        *      <li><js>"text/html html htm HTML"</js>
+        *      <li><js>"text/plain txt text TXT"</js>
+        *      <li><js>"application/javascript js"</js>
+        *      <li><js>"image/png png"</js>
+        *      <li><js>"image/gif gif"</js>
+        *      <li><js>"application/xml xml XML"</js>
+        *      <li><js>"application/json json JSON"</js>
+        * </ul>
+        *
+        * @param mimeTypes The MIME-types to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addMimeTypes(String...mimeTypes) {
+               for (String mimeType : mimeTypes)
+                       this.mimeTypes.addMimeTypes(mimeType);
+               return this;
+       }
+
+       /**
+        * Adds class-level default HTTP request headers to this resource.
+        * <p>
+        * Default request headers are default values for when HTTP requests do 
not specify a header value.
+        * For example, you can specify a default value for <code>Accept</code> 
if a request does not specify that header value.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#defaultRequestHeaders() @RestResource.defaultRequestHeaders()} 
annotation.
+        *
+        * @param name The HTTP header name.
+        * @param value The HTTP header value.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addDefaultRequestHeader(String name, Object value) {
+               this.defaultRequestHeaders.put(name, 
StringUtils.toString(value));
+               return this;
+       }
+
+       /**
+        * Adds class-level default HTTP request headers to this resource.
+        * <p>
+        * Default request headers are default values for when HTTP requests do 
not specify a header value.
+        * For example, you can specify a default value for <code>Accept</code> 
if a request does not specify that header value.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#defaultRequestHeaders() @RestResource.defaultRequestHeaders()} 
annotation.
+        *
+        * @param headers HTTP headers of the form <js>"Name: Value"</js>.
+        * @return This object (for method chaining).
+        * @throws RestServletException If header string is not correctly 
formatted.
+        */
+       public RestConfig addDefaultRequestHeaders(String...headers) throws 
RestServletException {
+               for (String header : headers) {
+                       String[] h = RestUtils.parseHeader(header);
+                       if (h == null)
+                               throw new RestServletException("Invalid default 
request header specified: ''{0}''.  Must be in the format: ''Header-Name: 
header-value''", header);
+                       addDefaultRequestHeader(h[0], h[1]);
+               }
+               return this;
+       }
+
+       /**
+        * Adds class-level default HTTP response headers to this resource.
+        * <p>
+        * Default response headers are headers that will be appended to all 
responses if those headers have not already been
+        *      set on the response object.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#defaultResponseHeaders() @RestResource.defaultResponseHeaders()} 
annotation.
+        * <p>
+        * Values are added AFTER those found in the annotation and therefore 
take precedence over those defined via the annotation.
+        *
+        * @param name The HTTP header name.
+        * @param value The HTTP header value.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addDefaultResponseHeader(String name, Object value) {
+               this.defaultResponseHeaders.put(name, value);
+               return this;
+       }
+
+       /**
+        * Adds class-level default HTTP response headers to this resource.
+        * <p>
+        * Default response headers are headers that will be appended to all 
responses if those headers have not already been
+        *      set on the response object.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#defaultResponseHeaders() @RestResource.defaultResponseHeaders()} 
annotation.
+        *
+        * @param headers HTTP headers of the form <js>"Name: Value"</js>.
+        * @return This object (for method chaining).
+        * @throws RestServletException If header string is not correctly 
formatted.
+        */
+       public RestConfig addDefaultResponseHeaders(String...headers) throws 
RestServletException {
+               for (String header : headers) {
+                       String[] h = RestUtils.parseHeader(header);
+                       if (h == null)
+                               throw new RestServletException("Invalid default 
response header specified: ''{0}''.  Must be in the format: ''Header-Name: 
header-value''", header);
+                       addDefaultResponseHeader(h[0], h[1]);
+               }
+               return this;
+       }
+
+       /**
+        * Adds class-level response handler classes to this resource.
+        * <p>
+        * Response handlers are responsible for converting various POJOs 
returned by REST methods into actual HTTP responses.
+        * <p>
+        * By default, this config includes the following response handlers:
+        * <ul class='spaced-list'>
+        *      <li>{@link StreamableHandler}
+        *      <li>{@link WritableHandler}
+        *      <li>{@link ReaderHandler}
+        *      <li>{@link InputStreamHandler}
+        *      <li>{@link RedirectHandler}
+        *      <li>{@link DefaultHandler}
+        * </ul>
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#responseHandlers() @RestResource.responseHandlers()} annotation.
+        *
+        * @param responseHandlers The response handlers to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addResponseHandlers(Class<?>...responseHandlers) {
+               this.responseHandlers.addAll(Arrays.asList(responseHandlers));
+               return this;
+       }
+
+       /**
+        * Adds class-level response handlers to this resource.
+        * <p>
+        * Same as {@link #addResponseHandlers(Class...)} except allows you to 
pass in response handler instances.
+        *
+        * @param responseHandlers The response handlers to add to this config.
+        * @return This object (for method chaining).
+        */
+       public RestConfig 
addResponseHandlers(ResponseHandler...responseHandlers) {
+               this.responseHandlers.addAll(Arrays.asList(responseHandlers));
+               return this;
+       }
+
+       /**
+        * Adds a child resource to this resource.
+        * <p>
+        * Child resources are resources that are accessed under the path of 
the parent resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#children() @RestResource.children()} annotation.
+        *
+        * @param path The child path of the resource.  Must conform to {@link 
RestResource#path()} format.
+        * @param child The child resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addChildResource(String path, Object child) {
+               this.childResources.add(new Pair<String,Object>(path, child));
+               return this;
+       }
+
+       /**
+        * Add child resources to this resource.
+        * <p>
+        * Child resources are resources that are accessed under the path of 
the parent resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#children() @RestResource.children()} annotation.
+        *
+        * @param children The child resources to add to this resource.
+        * Children must be annotated with {@link RestResource#path()} to 
identify the child path.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addChildResources(Object...children) {
+               this.childResources.addAll(Arrays.asList(children));
+               return this;
+       }
+
+       /**
+        * Add child resources to this resource.
+        * <p>
+        * Child resources are resources that are accessed under the path of 
the parent resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#children() @RestResource.children()} annotation.
+        *
+        * @param children The child resources to add to this resource.
+        * Children must be annotated with {@link RestResource#path()} to 
identify the child path.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addChildResources(Class<?>...children) {
+               this.childResources.addAll(Arrays.asList(children));
+               return this;
+       }
+
+       /**
+        * Specifies the list of supported <code>Accept</code> media types for 
this resource.
+        * <p>
+        * This overrides the media types inferred from the parsers on this 
resource.
+        * <p>
+        * There is no annotation equivalent to this method call.
+        *
+        * @param mediaTypes The new list of media types supported by this 
resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setSupportedAcceptTypes(String...mediaTypes) {
+               supportedAcceptTypes = new ArrayList<MediaType>();
+               for (String mediaType : mediaTypes)
+                       
supportedAcceptTypes.add(MediaType.forString(mediaType));
+               return this;
+       }
+
+       /**
+        * Specifies the list of supported <code>Accept</code> media types for 
this resource.
+        * <p>
+        * This overrides the media types inferred from the parsers on this 
resource.
+        * <p>
+        * There is no annotation equivalent to this method call.
+        *
+        * @param mediaTypes The new list of media types supported by this 
resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setSupportedAcceptTypes(MediaType...mediaTypes) {
+               supportedAcceptTypes = Arrays.asList(mediaTypes);
+               return this;
+       }
+
+       /**
+        * Specifies the list of supported <code>Content-Type</code> media 
types for this resource.
+        * <p>
+        * This overrides the media types inferred from the serializers on this 
resource.
+        * <p>
+        * There is no annotation equivalent to this method call.
+        *
+        * @param mediaTypes The new list of media types supported by this 
resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setSupportedContentTypes(String...mediaTypes) {
+               supportedContentTypes = new ArrayList<MediaType>();
+               for (String mediaType : mediaTypes)
+                       
supportedContentTypes.add(MediaType.forString(mediaType));
+               return this;
+       }
+
+       /**
+        * Specifies the list of supported <code>Content-Type</code> media 
types for this resource.
+        * <p>
+        * This overrides the media types inferred from the serializers on this 
resource.
+        * <p>
+        * There is no annotation equivalent to this method call.
+        *
+        * @param mediaTypes The new list of media types supported by this 
resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setSupportedContentTypes(MediaType...mediaTypes) {
+               supportedContentTypes = Arrays.asList(mediaTypes);
+               return this;
+       }
+
+       /**
+        * Specifies the stylesheets that make up the contents of the page 
<js>"/resource-path/styles.css"</js>.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#stylesheet() @RestResource.stylesheet()} annotation.
+        * <p>
+        * The object types can be any of the following:
+        * <ul>
+        *      <li>{@link InputStream}
+        *      <li>{@link Reader}
+        *      <li>{@link File}
+        *      <li>{@link CharSequence}
+        *      <li><code><jk>byte</jk>[]</code>
+        * </ul>
+        * The contents of all these stylesheets will be aggregated into a 
single page in the order they are specified in this list.
+        *
+        * @param styleSheets The new list of style sheets that make up the 
<code>styles.css</code> page.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setStyleSheet(Object...styleSheets) {
+               this.styleSheets = new 
ArrayList<Object>(Arrays.asList(styleSheets));
+               return this;
+       }
+
+       /**
+        * Specifies the stylesheet that make up the contents of the page 
<js>"/resource-path/styles.css"</js>.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#stylesheet() @RestResource.stylesheet()} annotation.
+        * <p>
+        * Use this method to specify a resource located in the classpath.
+        * This call uses the {@link Class#getResourceAsStream(String)} method 
to retrieve the stylesheet contents.
+        *
+        * @param resourceClass The resource class used to resolve the resource 
stream.
+        * @param resourcePath The path passed to the {@link 
Class#getResourceAsStream(String)} method.
+        * Can also be a path starting with <js>"file://"</js> denoting a 
location to pull from the file system.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setStyleSheet(Class<?> resourceClass, String 
resourcePath) {
+               this.styleSheets = new ArrayList<Object>();
+               this.styleSheets.add(new Pair<Class<?>,String>(resourceClass, 
resourcePath));
+               return this;
+       }
+
+       /**
+        * Adds to the stylesheet that make up the contents of the page 
<js>"/resource-path/styles.css"</js>.
+        * <p>
+        * Same as {@link #setStyleSheet(Object...)} except appends to the 
existing list instead of replacing.
+        *
+        * @param styleSheets The list of style sheets to add that make up the 
<code>styles.css</code> page.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addStyleSheet(Object...styleSheets) {
+               if (this.styleSheets == null)
+                       this.styleSheets = new ArrayList<Object>();
+               this.styleSheets.addAll(Arrays.asList(styleSheets));
+               return this;
+       }
+
+       /**
+        * Adds to the stylesheet that make up the contents of the page 
<js>"/resource-path/styles.css"</js>.
+        * <p>
+        * Same as {@link #setStyleSheet(Class,String)} except appends to the 
existing list instead of replacing.
+        *
+        * @param resourceClass The resource class used to resolve the resource 
stream.
+        * @param resourcePath The path passed to the {@link 
Class#getResourceAsStream(String)} method.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addStyleSheet(Class<?> resourceClass, String 
resourcePath) {
+               if (this.styleSheets == null)
+                       this.styleSheets = new ArrayList<Object>();
+               this.styleSheets.add(new Pair<Class<?>,String>(resourceClass, 
resourcePath));
+               return this;
+       }
+
+       /**
+        * Specifies the icon contents that make up the contents of the page 
<js>"/resource-path/favicon.ico"</js>.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#favicon() @RestResource.favicon()} annotation.
+        * <p>
+        * The object type can be any of the following:
+        * <ul>
+        *      <li>{@link InputStream}
+        *      <li>{@link File}
+        *      <li><code><jk>byte</jk>[]</code>
+        * </ul>
+        *
+        * @param favIcon The contents that make up the 
<code>favicon.ico</code> page.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setFavIcon(Object favIcon) {
+               this.favIcon = favIcon;
+               return this;
+       }
+
+       /**
+        * Specifies the icon contents that make up the contents of the page 
<js>"/resource-path/favicon.ico"</js>.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#favicon() @RestResource.favicon()} annotation.
+        * <p>
+        * Use this method to specify a resource located in the classpath.
+        * This call uses the {@link Class#getResourceAsStream(String)} method 
to retrieve the stylesheet contents.
+        *
+        * @param resourceClass The resource class used to resolve the resource 
stream.
+        * @param resourcePath The path passed to the {@link 
Class#getResourceAsStream(String)} method.
+        * Can also be a path starting with <js>"file://"</js> denoting a 
location to pull from the file system.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setFavIcon(Class<?> resourceClass, String 
resourcePath) {
+               this.favIcon = new Pair<Class<?>,String>(resourceClass, 
resourcePath);
+               return this;
+       }
+
+       /**
+        * Appends to the static files resource map.
+        * <p>
+        * Use this method to specify resources located in the classpath to be 
served up as static files.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#staticFiles() @RestResource.staticFiles()} annotation.
+        *
+        * @param resourceClass The resource class used to resolve the resource 
streams.
+        * @param staticFilesString A JSON string denoting a map of child URLs 
to classpath subdirectories.
+        * For example, if this string is <js>"{htdocs:'docs'}"</js> with class 
<code>com.foo.MyResource</code>,
+        * then URLs of the form <js>"/resource-path/htdocs/..."</js> will 
resolve to files located in the <code>com.foo.docs</code> package.
+        * @return This object (for method chaining).
+        */
+       public RestConfig addStaticFiles(Class<?> resourceClass, String 
staticFilesString) {
+               if (staticFiles == null)
+                       staticFiles = new ArrayList<Object>();
+               staticFiles.add(new Pair<Class<?>,Object>(resourceClass, 
staticFilesString));
+               return this;
+       }
+
+       /**
+        * Overrides the default REST resource resolver.
+        * <p>
+        * The resource resolver is used to resolve instances from {@link 
Class} objects defined in the {@link RestResource#children()} annotation.
+        * The default value is the base class {@link RestResourceResolver}.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#resourceResolver() @RestResource.resourceResolver()} annotation.
+        *
+        * @param resourceResolver The new resource resolver.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setResourceResolver(Class<? extends 
RestResourceResolver> resourceResolver) {
+               this.resourceResolver = resourceResolver;
+               return this;
+       }
+
+       /**
+        * Overrides the default REST resource resolver.
+        * <p>
+        * Same as {@link #setResourceResolver(Class)} except allows you to 
specify an instance instead of a class.
+        *
+        * @param resourceResolver The new resource resolver.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setResourceResolver(RestResourceResolver 
resourceResolver) {
+               this.resourceResolver = resourceResolver;
+               return this;
+       }
+
+       /**
+        * Sets the URL path of the resource <js>"/foobar"</js>.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#path() @RestResource.path()} annotation.
+        *
+        * @param path The URL path of this resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setPath(String path) {
+               if (StringUtils.startsWith(path, '/'))
+                       path = path.substring(1);
+               this.path = path;
+               return this;
+       }
+
+       /**
+        * Sets name of the header used to denote the client version on HTTP 
requests.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#clientVersionHeader() @RestResource.clientVersionHeader()} 
annotation.
+        *
+        * @param clientVersionHeader The name of the HTTP header that denotes 
the client version.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setClientVersionHeader(String clientVersionHeader) {
+               this.clientVersionHeader = clientVersionHeader;
+               return this;
+       }
+
+       /**
+        * Overrides the logger for the resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#logger() @RestResource.logger()} annotation.
+        *
+        * @param logger The new logger for this resource.  Can be 
<jk>null</jk> to disable logging.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setLogger(Class<? extends RestLogger> logger) {
+               this.logger = logger;
+               return this;
+       }
+
+       /**
+        * Overrides the logger for the resource.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#logger() @RestResource.logger()} annotation.
+        *
+        * @param logger The new logger for this resource.  Can be 
<jk>null</jk> to disable logging.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setLogger(RestLogger logger) {
+               this.logger = logger;
+               return this;
+       }
+
+       /**
+        * Overrides the call handler for the resource.
+        * <p>
+        * The call handler is the object that handles execution of REST HTTP 
calls.
+        * Subclasses can be created that customize the behavior of how REST 
calls are handled.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#callHandler() @RestResource.callHandler()} annotation.
+        *
+        * @param restHandler The new call handler for this resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setCallHandler(Class<? extends RestCallHandler> 
restHandler) {
+               this.callHandler = restHandler;
+               return this;
+       }
+
+       /**
+        * Overrides the call handler for the resource.
+        * <p>
+        * The call handler is the object that handles execution of REST HTTP 
calls.
+        * Subclasses can be created that customize the behavior of how REST 
calls are handled.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#callHandler() @RestResource.callHandler()} annotation.
+        *
+        * @param restHandler The new call handler for this resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setCallHandler(RestCallHandler restHandler) {
+               this.callHandler = restHandler;
+               return this;
+       }
+
+       /**
+        * Overrides the info provider for the resource.
+        * <p>
+        * The info provider provides all the various information about a 
resource such as the Swagger documentation.
+        * Subclasses can be created that customize the information.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#infoProvider() @RestResource.infoProvider()} annotation.
+        *
+        * @param infoProvider The new info provider for this resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setInfoProvider(Class<? extends RestInfoProvider> 
infoProvider) {
+               this.infoProvider = infoProvider;
+               return this;
+       }
+
+       /**
+        * Overrides the info provider for the resource.
+        * <p>
+        * The info provider provides all the various information about a 
resource such as the Swagger documentation.
+        * Subclasses can be created that customize the information.
+        * <p>
+        * This is the programmatic equivalent to the {@link 
RestResource#infoProvider() @RestResource.infoProvider()} annotation.
+        *
+        * @param infoProvider The new info provider for this resource.
+        * @return This object (for method chaining).
+        */
+       public RestConfig setInfoProvider(RestInfoProvider infoProvider) {
+               this.infoProvider = infoProvider;
+               return this;
+       }
+
+       /**
+        * Creates a new {@link PropertyStore} object initialized with the 
properties defined in this config.
+        * @return A new property store.
+        */
+       protected PropertyStore createPropertyStore() {
+               return PropertyStore.create().addProperties(properties);
+       }
+
+
+       
//----------------------------------------------------------------------------------------------------
+       // Methods that give access to the config file, var resolver, and 
properties.
+       
//----------------------------------------------------------------------------------------------------
+
+       /**
+        * Returns the external configuration file for this resource.
+        * <p>
+        * The configuration file location is determined via the {@link 
RestResource#config() @RestResource.config()} annotation on the resource.
+        * <p>
+        * The config file can be programmatically overridden by adding the 
following method to your resource:
+        * <p class='bcode'>
+        *      <jk>public</jk> ConfigFile createConfigFile(ServletConfig 
servletConfig) <jk>throws</jk> ServletException;
+        * </p>
+        * <p>
+        * If a config file is not set up, then an empty config file will be 
returned that is not backed by any file.
+        *
+        * @return The external config file for this resource.  Never 
<jk>null</jk>.
+        */
+       public ConfigFile getConfigFile() {
+               return configFile;
+       }
+
+       /**
+        * Returns the configuration properties for this resource.
+        * <p>
+        * The configuration properties are determined via the {@link 
RestResource#properties()} annotation on the resource.
+        * <p>
+        * The configuration properties can be augmented programmatically by 
adding the following method to your resource:
+        * <p class='bcode'>
+        *      <jk>public</jk> ObjectMap createProperties(ServletConfig 
servletConfig) <jk>throws</jk> ServletException;
+        * </p>
+        * <p>
+        * These properties can be modified during servlet initialization.
+        * However, any modifications made after {@link 
RestServlet#init(RestConfig)} has been called will have no effect.
+        *
+        * @return The configuration properties for this resource.  Never 
<jk>null</jk>.
+        */
+       public ObjectMap getProperties() {
+               return properties;
+       }
+
+       /**
+        * Creates the variable resolver for this resource.
+        * <p>
+        * The variable resolver returned by this method can resolve the 
following variables:
+        * <ul>
+        *      <li>{@link SystemPropertiesVar}
+        *      <li>{@link EnvVariablesVar}
+        *      <li>{@link ConfigFileVar}
+        *      <li>{@link IfVar}
+        *      <li>{@link SwitchVar}
+        * </ul>
+        * <p>
+        * Note that the variables supported here are only a subset of those 
returned by {@link RestRequest#getVarResolverSession()}.
+        *
+        * @return The variable resolver for this resource.  Never 
<jk>null</jk>.
+        */
+       public VarResolverBuilder getVarResolverBuilder() {
+               return varResolverBuilder;
+       }
+
+
+       
//----------------------------------------------------------------------------------------------------
+       // Methods inherited from ServletConfig
+       
//----------------------------------------------------------------------------------------------------
+
+       @Override /* ServletConfig */
+       public String getInitParameter(String name) {
+               return inner.getInitParameter(name);
+       }
+
+       @Override /* ServletConfig */
+       public Enumeration<String> getInitParameterNames() {
+               return inner.getInitParameterNames();
+       }
+
+       @Override /* ServletConfig */
+       public ServletContext getServletContext() {
+               return inner.getServletContext();
+       }
+
+       @Override /* ServletConfig */
+       public String getServletName() {
+               return inner.getServletName();
+       }
+}


Reply via email to