http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2c3a7cb5/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestConverter.java ---------------------------------------------------------------------- diff --git a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestConverter.java b/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestConverter.java deleted file mode 100755 index 0c1c9ec..0000000 --- a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestConverter.java +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************************************************************** - * 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.server; - -import org.apache.juneau.*; -import org.apache.juneau.serializer.*; -import org.apache.juneau.server.annotation.*; -import org.apache.juneau.server.converters.*; - -/** - * REST method response converter. - * <p> - * Implements a filter mechanism for REST method calls that allows response objects to be - * converted to some other POJO after invocation of the REST method. - * <p> - * Converters are associated with REST methods through the {@link RestMethod#converters()} annotation. - * <h6 class='topic'>Example</h6> - * <p class='bcode'> - * <jk>public class</jk> RequestEchoResource <jk>extends</jk> RestServlet { - * - * <jc>// GET request handler</jc> - * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>, converters={Queryable.<jk>class</jk>,Traversable.<jk>class</jk>}) - * <jk>public</jk> HttpServletRequest doGet(RestRequest req) { - * res.setTitle(<js>"Contents of HttpServletRequest object"</js>); - * <jk>return</jk> req; - * } - * } - * </p> - * <p> - * Converters can also be associated at the servlet level using the {@link RestResource#converters()} annotation. - * Applying converters at the resource level is equivalent to applying converters to each resource method individually. - * - * <h6 class='topic'>How to implement</h6> - * <p> - * Implementers should simply implement the {@link #convert(RestRequest, Object, ClassMeta)} and - * return back a 'converted' object. - * It's up to the implementer to decide what this means. - * <p> - * Converters must implement a no-args constructor. - * - * <h6 class='topic'>Predefined converters</h6> - * <p> - * The following converters are available by default. - * <ul class='spaced-list'> - * <li>{@link Traversable} - Allows URL additional path info to address individual elements in a POJO tree. - * <li>{@link Queryable} - Allows query/view/sort functions to be performed on POJOs. - * <li>{@link Introspectable} - Allows Java public methods to be invoked on the returned POJOs. - * </ul> - */ -public interface RestConverter { - - /** - * Performs post-call conversion on the specified response object. - * - * @param req The servlet request. - * @param res The response object set by the REST method through the {@link RestResponse#setOutput(Object)} method. - * @param cm The {@link ClassMeta} on the object from the bean context of the servlet. - * Can be used to check if the object has any filters. - * @return The converted object. - * @throws RestException Thrown if any errors occur during conversion. - * @throws SerializeException - */ - public Object convert(RestRequest req, Object res, ClassMeta<?> cm) throws RestException, SerializeException; -}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2c3a7cb5/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestException.java ---------------------------------------------------------------------- diff --git a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestException.java b/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestException.java deleted file mode 100755 index 62ea6ae..0000000 --- a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestException.java +++ /dev/null @@ -1,137 +0,0 @@ -/*************************************************************************************************************************** - * 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.server; - -import java.text.*; - -/** - * Exception thrown to trigger an error HTTP status. - * <p> - * REST methods on subclasses of {@link RestServlet} can throw - * this exception to trigger an HTTP status other than the automatically-generated - * <code>404</code>, <code>405</code>, and <code>500</code> statuses. - * - * @author James Bognar ([email protected]) - */ -public class RestException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - private int status; - private int occurrence; - - /** - * Constructor. - * - * @param status The HTTP status code. - * @param msg The status message. - * @param args Optional string format arguments. - */ - public RestException(int status, String msg, Object...args) { - super(args.length == 0 ? msg : MessageFormat.format(msg, args)); - this.status = status; - } - - /** - * Constructor. - * - * @param status The HTTP status code. - * @param cause The root exception. - */ - public RestException(int status, Throwable cause) { - this(status, cause.getLocalizedMessage()); - initCause(cause); - } - - - /** - * Sets the inner cause for this exception. - * - * @param cause The inner cause. - * @return This object (for method chaining). - */ - @Override /* Throwable */ - public synchronized RestException initCause(Throwable cause) { - super.initCause(cause); - return this; - } - - - /** - * Returns all error messages from all errors in this stack. - * <p> - * Typically useful if you want to render all the error messages in the stack, but don't - * want to render all the stack traces too. - * - * @param scrubForXssVulnerabilities If <jk>true</jk>, replaces <js>'<'</js>, <js>'>'</js>, and <js>'&'</js> characters with spaces. - * @return All error messages from all errors in this stack. - */ - public String getFullStackMessage(boolean scrubForXssVulnerabilities) { - String msg = getMessage(); - StringBuilder sb = new StringBuilder(); - if (msg != null) { - if (scrubForXssVulnerabilities) - msg = msg.replace('<', ' ').replace('>', ' ').replace('&', ' '); - sb.append(msg); - } - Throwable e = getCause(); - while (e != null) { - msg = e.getMessage(); - if (msg != null && scrubForXssVulnerabilities) - msg = msg.replace('<', ' ').replace('>', ' ').replace('&', ' '); - String cls = e.getClass().getSimpleName(); - if (msg == null) - sb.append(MessageFormat.format("\nCaused by ({0})", cls)); - else - sb.append(MessageFormat.format("\nCaused by ({0}): {1}", cls, msg)); - e = e.getCause(); - } - return sb.toString(); - } - - @Override /* Object */ - public int hashCode() { - int i = 0; - Throwable t = this; - while (t != null) { - for (StackTraceElement e : t.getStackTrace()) - i ^= e.hashCode(); - t = t.getCause(); - } - return i; - } - - void setOccurrence(int occurrence) { - this.occurrence = occurrence; - } - - /** - * Returns the number of times this exception occurred on this servlet. - * <p> - * This only gets set if {@link RestServletContext#REST_useStackTraceHashes} is enabled on the servlet. - * - * @return The occurrence number if {@link RestServletContext#REST_useStackTraceHashes} is enabled, or <code>0</code> otherwise. - */ - public int getOccurrence() { - return occurrence; - } - - /** - * Returns the HTTP status code. - * - * @return The HTTP status code. - */ - public int getStatus() { - return status; - } -} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2c3a7cb5/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestGuard.java ---------------------------------------------------------------------- diff --git a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestGuard.java b/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestGuard.java deleted file mode 100755 index 46475ce..0000000 --- a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestGuard.java +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************************************************************** - * 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.server; - -import static javax.servlet.http.HttpServletResponse.*; - -import org.apache.juneau.server.annotation.*; - -/** - * REST method guard. - * - * - * <h6 class='topic'>Description</h6> - * <p> - * Implements a guard mechanism for REST method calls that allows requests to be - * rejected before invocation of the REST method. - * For example, guards can be used to ensure that only administrators can call certain methods. - * <p> - * Guards are applied to REST methods declaratively through the {@link RestResource#guards()} or {@link RestMethod#guards()} annotations. - * <p> - * If multiple guards are specified, ALL guards must pass in order for the request to proceed. - * - * - * <h6 class='topic'>How to implement</h6> - * <p> - * Typically, guards will be used for permissions checking on the user making the request, - * but it can also be used for other purposes like pre-call validation of a request. - * <p> - * Implementers should simply throw a {@link RestException} from the {@link #guard(RestRequest, RestResponse)} - * method to abort processing on the current request. - * <p> - * Guards must implement a no-args constructor. - * - * - * <h6 class='topic'>Example usage</h6> - * <p class='bcode'> - * <jk>public</jk> MyResource <jk>extends</jk> RestServlet { - * - * <jc>// Delete method with guard that only allows Billy to call it.</jc> - * <ja>@RestMethod</ja>(name=<js>"DELETE"</js>, guards=BillyGuard.<jk>class</jk>) - * <jk>public</jk> doDelete(RestRequest req, RestResponse res) <jk>throws</jk> Exception {...} - * } - * </p> - * - * - * <h6 class='topic'>Example implementation</h6> - * <p class='bcode'> - * <jc>// Define a guard that only lets Billy make a request</jc> - * <jk>public</jk> BillyGuard <jk>extends</jk> RestGuard { - * - * <ja>@Override</ja> - * <jk>public boolean</jk> isRequestAllowed(RestRequest req) { - * return req.getUserPrincipal().getName().contains(<js>"Billy"</js>); - * } - * } - * </p> - */ -public abstract class RestGuard { - - /** - * Checks the current HTTP request and throws a {@link RestException} if the guard - * does not permit the request. - * <p> - * By default, throws an <jsf>SC_FORBIDDEN</jsf> exception if {@link #isRequestAllowed(RestRequest)} - * returns <jk>false</jk>. - * <p> - * Subclasses are free to override this method to tailor the behavior of how to handle unauthorized - * requests. - * - * @param req The servlet request. - * @param res The servlet response. - * @throws RestException Thrown to abort processing on current request. - * @return <jk>true</jk> if request can proceed. - * Specify <jk>false</jk> if you're doing something like a redirection to a login page. - */ - public boolean guard(RestRequest req, RestResponse res) throws RestException { - if (! isRequestAllowed(req)) - throw new RestException(SC_FORBIDDEN, "Access denied by guard"); - return true; - } - - /** - * Returns <jk>true</jk> if the specified request can pass through this guard. - * - * @param req The servlet request. - * @return <jk>true</jk> if the specified request can pass through this guard. - */ - public abstract boolean isRequestAllowed(RestRequest req); -} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2c3a7cb5/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcher.java ---------------------------------------------------------------------- diff --git a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcher.java b/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcher.java deleted file mode 100755 index c2513f7..0000000 --- a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcher.java +++ /dev/null @@ -1,76 +0,0 @@ -/*************************************************************************************************************************** - * 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.server; - -import org.apache.juneau.server.annotation.*; - -/** - * Class used for defining method-level matchers using the {@link RestMethod#matchers()} annotation. - * <p> - * Matchers are used to allow multiple Java methods to handle requests assigned to the same - * URL path pattern, but differing based on some request attribute, such as a specific header value. - * For example, matchers can be used to provide two different methods for handling requests - * from two different client versions. - * <p> - * Java methods with matchers associated with them are always attempted before Java methods - * without matchers. - * This allows a 'default' method to be defined to handle requests where no matchers match. - * <p> - * When multiple matchers are specified on a method, only one matcher is required to match. - * This is opposite from the {@link RestMethod#guards()} annotation, where all guards - * are required to match in order to execute the method. - * - * <h6 class='topic'>Example</h6> - * <p class='bcode'> - * <jk>public class</jk> MyResource <jk>extends</jk> RestServlet { - * - * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>, matchers=IsDNT.<jk>class</jk>) - * <jk>public</jk> Object doGetWithDNT() { - * <jc>// Handle request with Do-Not-Track specified</jc> - * } - * - * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>) - * <jk>public</jk> Object doGetWithoutDNT() { - * <jc>// Handle request without Do-Not-Track specified</jc> - * } - * } - * - * <jk>public class</jk> IsDNT <jk>extends</jk> RestMatcher { - * <ja>@Override</ja> - * <jk>public boolean</jk> matches(RestRequest req) { - * <jk>return</jk> req.getHeader(<jk>int</jk>.<jk>class</jk>, <js>"DNT"</js>, 0) == 1; - * } - * } - * </p> - */ -public abstract class RestMatcher { - - /** - * Returns <jk>true</jk> if the specified request matches this matcher. - * - * @param req The servlet request. - * @return <jk>true</jk> if the specified request matches this matcher. - */ - public abstract boolean matches(RestRequest req); - - /** - * Returns <jk>true</jk> if this matcher is required to match in order for the method to be invoked. - * <p> - * If <jk>false</jk>, then only one of the matchers must match. - * - * @return <jk>true</jk> if this matcher is required to match in order for the method to be invoked. - */ - public boolean mustMatch() { - return false; - } -} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2c3a7cb5/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcherReflecting.java ---------------------------------------------------------------------- diff --git a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcherReflecting.java b/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcherReflecting.java deleted file mode 100644 index 3140559..0000000 --- a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestMatcherReflecting.java +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************************************************************** - * 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.server; - -import java.lang.reflect.*; - -/** - * Subclass of {@link RestMatcher} that gives access to the servlet and Java method it's applied to. - * <p> - * Essentially the same as {@link RestMatcher} except has a constructor where the - * Java method is passed in so that you can access annotations defined on it to tailor - * the behavior of the matcher. - * - * @author James Bognar ([email protected]) - */ -public abstract class RestMatcherReflecting extends RestMatcher { - - /** - * Constructor. - * - * @param servlet The REST servlet. - * @param javaMethod The Java method that this rest matcher is defined on. - */ - protected RestMatcherReflecting(RestServlet servlet, Method javaMethod) {} -} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2c3a7cb5/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestRequest.java ---------------------------------------------------------------------- diff --git a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestRequest.java b/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestRequest.java deleted file mode 100755 index 29ce04d..0000000 --- a/com.ibm.team.juno.server/src/main/java/org/apache/juneau/server/RestRequest.java +++ /dev/null @@ -1,1764 +0,0 @@ -/*************************************************************************************************************************** - * 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.server; - -import static java.util.Collections.*; -import static java.util.logging.Level.*; -import static javax.servlet.http.HttpServletResponse.*; - -import java.io.*; -import java.lang.reflect.*; -import java.net.*; -import java.text.*; -import java.util.*; -import java.util.logging.*; - -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.parser.ParseException; -import org.apache.juneau.serializer.*; -import org.apache.juneau.server.labels.*; -import org.apache.juneau.server.labels.Var; -import org.apache.juneau.svl.*; -import org.apache.juneau.urlencoding.*; -import org.apache.juneau.utils.*; - -/** - * Represents an HTTP request for a REST resource. - * <p> - * Equivalent to {@link HttpServletRequest} except with some additional convenience methods. - * </p> - * <p> - * For reference, given the URL <js>"http://localhost:9080/contextRoot/servletPath/foo?bar=baz#qux"</js>, the - * following methods return the following values.... - * </p> - * <table class='styled'> - * <tr><th>Method</th><th>Value</th></tr> - * <tr><td>{@code getContextPath()}</td><td>{@code /contextRoot}</td></tr> - * <tr><td>{@code getPathInfo()}</td><td>{@code /foo}</td></tr> - * <tr><td>{@code getPathTranslated()}</td><td>{@code path-to-deployed-war-on-filesystem/foo}</td></tr> - * <tr><td>{@code getQueryString()}</td><td>{@code bar=baz}</td></tr> - * <tr><td>{@code getRequestURI()}</td><td>{@code /contextRoot/servletPath/foo}</td></tr> - * <tr><td>{@code getRequestURL()}</td><td>{@code http://localhost:9080/contextRoot/servletPath/foo}</td></tr> - * <tr><td>{@code getServletPath()}</td><td>{@code /servletPath}</td></tr> - * </table> - * <p> - * Refer to <a class='doclink' href='package-summary.html#TOC'>REST Servlet API</a> for information about using this class. - * </p> - * - * @author jbognar - */ -@SuppressWarnings("unchecked") -public final class RestRequest extends HttpServletRequestWrapper { - - private final RestServlet servlet; - private String method, pathRemainder, content; - Method javaMethod; - private ObjectMap properties; - private SerializerGroup serializerGroup; - private ParserGroup parserGroup; - private Encoder encoder; - private int contentLength; - private final boolean debug; - private UrlEncodingParser urlEncodingParser; // The parser used to parse URL attributes and parameters (beanContext also used to parse headers) - private BeanContext beanContext; - private VarResolverSession varSession; - private Map<String,String[]> queryParams; - private Map<String,String> defaultServletHeaders, defaultMethodHeaders, overriddenHeaders, overriddenParams; - private boolean isPost; - private String servletURI, relativeServletURI; - private String charset, defaultCharset; - private ObjectMap headers; - private ConfigFile cf; - - /** - * Constructor. - */ - RestRequest(RestServlet servlet, HttpServletRequest req) throws ServletException { - super(req); - - try { - this.servlet = servlet; - isPost = req.getMethod().equalsIgnoreCase("POST"); - - // If this is a POST, we want to parse the query parameters ourselves to prevent - // the servlet code from processing the HTTP body as URL-Encoded parameters. - if (isPost) - queryParams = servlet.getUrlEncodingParser().parseIntoSimpleMap(getQueryString()); - else { - queryParams = req.getParameterMap(); - } - - // Get the HTTP method. - // Can be overridden through a "method" GET attribute. - method = super.getMethod(); - - String m = getQueryParameter("method"); - if (! StringUtils.isEmpty(m) && (servlet.context.allowMethodParams.contains(m) || servlet.context.allowMethodParams.contains("*"))) - method = m; - - if (servlet.context.allowContentParam) - content = getQueryParameter("content"); - - defaultServletHeaders = servlet.getDefaultRequestHeaders(); - - debug = "true".equals(getQueryParameter("debug", "false")); - - if (debug) { - servlet.log(Level.INFO, toString()); - } - - } catch (RestException e) { - throw e; - } catch (Exception e) { - throw new ServletException(e); - } - } - - /* - * Called from RestServlet after a match has been made but before the guard or method invocation. - */ - @SuppressWarnings("hiding") - final void init(Method javaMethod, String pathRemainder, ObjectMap properties, Map<String,String> mDefaultRequestHeaders, String defaultCharset, SerializerGroup mSerializers, ParserGroup mParsers, UrlEncodingParser mUrlEncodingParser) { - this.javaMethod = javaMethod; - this.pathRemainder = pathRemainder; - this.properties = properties; - this.defaultMethodHeaders = mDefaultRequestHeaders; - this.serializerGroup = mSerializers; - this.parserGroup = mParsers; - this.urlEncodingParser = mUrlEncodingParser; - this.beanContext = urlEncodingParser.getBeanContext(); - this.defaultCharset = defaultCharset; - } - - /** - * Returns <jk>true</jk> if the request contains any of the specified parameters. - * - * @param params The list of parameters to check for. - * @return <jk>true</jk> if the request contains any of the specified parameters. - */ - public boolean hasAnyQueryParameters(String...params) { - for (String p : params) - if (hasQueryParameter(p)) - return true; - return false; - } - - /** - * Returns a string of the form <js>"HTTP method-name full-url"</js> - * - * @return A description of the request. - */ - public String getDescription() { - String qs = getQueryString(); - return "HTTP " + getMethod() + " " + getRequestURI() + (qs == null ? "" : "?" + qs); - } - - /** - * Servlet calls this method to initialize the properties. - */ - RestRequest setProperties(ObjectMap properties) { - this.properties = properties; - return this; - } - - /** - * Retrieve the properties active for this request. - * These properties can be modified by the request. - * - * @return The properties active for this request. - */ - public ObjectMap getProperties() { - return this.properties; - } - - /** - * Returns the <code>Content-Type</code> header value on the request, stripped - * of any parameters such as <js>";charset=X"</js>. - * <p> - * Example: <js>"text/json"</js>. - * <p> - * If the content type is not specified, and the content is specified via a - * <code>&content</code> query parameter, the content type is assumed to be - * <js>"text/uon"</js>. Otherwise, the - * content type is assumed to be <js>"text/json"</js>. - * - * @return The <code>Accept</code> media-type header values on the request. - */ - public String getMediaType() { - String cm = getHeader("Content-Type"); - if (cm == null) { - if (content != null) - return "text/uon"; - return "text/json"; - } - int j = cm.indexOf(';'); - if (j != -1) - cm = cm.substring(0, j); - return cm; - } - - /** - * Returns the media types that are valid for <code>Content-Type</code> headers on the request. - * - * @return The set of media types registered in the parser group of this request. - */ - public List<String> getSupportedMediaTypes() { - return parserGroup.getSupportedMediaTypes(); - } - - /** - * Returns the charset specified on the <code>Content-Type</code> header, or - * <js>"UTF-8"</js> if not specified. - */ - @Override /* ServletRequest */ - public String getCharacterEncoding() { - if (charset == null) { - // Determine charset - // NOTE: Don't use super.getCharacterEncoding() because the spec is implemented inconsistently. - // Jetty returns the default charset instead of null if the character is not specified on the request. - String h = getHeader("Content-Type"); - if (h != null) { - int i = h.indexOf(";charset="); - if (i > 0) - charset = h.substring(i+9).trim(); - } - if (charset == null) - charset = defaultCharset; - if (! RestServlet.availableCharsets.containsKey(charset)) - throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported charset in header ''Content-Type'': ''{0}''", h); - } - return charset; - } - - /** - * Sets the charset to expect on the request body. - */ - @Override /* ServletRequest */ - public void setCharacterEncoding(String charset) { - this.charset = charset; - } - - /** - * Returns the specified header value, or <jk>null</jk> if the header value isn't present. - * <p> - * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks - * for {@code &HeaderName=x} in the URL query string. - */ - @Override /* ServletRequest */ - public String getHeader(String name) { - return getHeader(name, (String)null); - } - - /** - * Returns all the request headers as an {@link ObjectMap}. - * <p> - * Altering entries in this map does not alter headers in the underlying request. - * - * @return The request headers. Never <jk>null</jk>. - */ - public ObjectMap getHeaders() { - if (headers == null) { - headers = new ObjectMap(); - for (Enumeration<String> e = getHeaderNames(); e.hasMoreElements();) { - String key = e.nextElement(); - headers.put(key, getHeader(key)); - } - } - return headers; - } - - /** - * Set the request header to the specified value. - * - * @param name The header name. - * @param value The header value. - */ - public void setHeader(String name, String value) { - if (overriddenHeaders == null) - overriddenHeaders = new TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER); - overriddenHeaders.put(name, value); - } - - /** - * Set the request parameter to the specified value. - * - * @param name The parameter name. - * @param value The parameter value. - */ - public void setParameter(String name, Object value) { - if (overriddenParams == null) - overriddenParams = new TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER); - overriddenParams.put(name, value == null ? null : value.toString()); - } - - /** - * Returns the specified header value, or the specified default value if the - * header value isn't present. - * <p> - * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks - * for {@code &HeaderName=x} in the URL query string. - * - * @param name The HTTP header name. - * @param def The default value to return if the header value isn't found. - * @return The header value, or the default value if the header isn't present. - */ - public String getHeader(String name, String def) { - String h = getOverriddenHeader(name); - if (h != null) - return h; - h = super.getHeader(name); - if (h != null && ! h.isEmpty()) - return h; - if (defaultMethodHeaders != null) { - h = defaultMethodHeaders.get(name); - if (h != null) - return h; - } - h = defaultServletHeaders.get(name); - if (h != null) - return h; - return def; - } - - @Override /* ServletRequest */ - public Enumeration<String> getHeaders(String name) { - String h = getOverriddenHeader(name); - if (h != null) - return enumeration(singleton(h)); - return super.getHeaders(name); - } - - /* - * Returns header value from URL-parameters or set via setHeader() meant - * to override actual header values on the request. - */ - private String getOverriddenHeader(String name) { - String h = null; - if (servlet.context.allowHeaderParams) - h = getQueryParameter(name); - if (h != null) - return h; - if (overriddenHeaders != null) { - h = overriddenHeaders.get(name); - if (h != null) - return h; - } - return h; - } - - @Override /* ServletRequest */ - public Locale getLocale() { - String h = getOverriddenHeader("Accept-Language"); - if (h != null) { - MediaRange[] mr = MediaRange.parse(h); - if (mr.length > 0) - return toLocale(mr[0].getType()); - } - return super.getLocale(); - } - - @Override /* ServletRequest */ - public Enumeration<Locale> getLocales() { - String h = getOverriddenHeader("Accept-Language"); - if (h != null) { - MediaRange[] mr = MediaRange.parse(h); - if (mr.length > 0) { - List<Locale> l = new ArrayList<Locale>(mr.length); - for (MediaRange r : mr) - l.add(toLocale(r.getType())); - return enumeration(l); - } - } - return super.getLocales(); - } - - /** - * Converts an Accept-Header value entry to a Locale. - */ - private Locale toLocale(String lang) { - String country = ""; - int i = lang.indexOf('-'); - if (i > -1) { - country = lang.substring(i+1).trim(); - lang = lang.substring(0,i).trim(); - } - return new Locale(lang, country); - } - - /** - * Returns the serializers associated with this request. - * - * @return The serializers associated with this request. - */ - public SerializerGroup getSerializerGroup() { - return serializerGroup; - } - - /** - * Returns the parsers associated with this request. - * - * @return The parsers associated with this request. - */ - public ParserGroup getParserGroup() { - return parserGroup; - } - - /** - * Returns the method of this request. - * <p> - * If <code>allowHeaderParams</code> init parameter is <jk>true</jk>, then first looks - * for <code>&method=xxx</code> in the URL query string. - */ - @Override /* ServletRequest */ - public String getMethod() { - return method; - } - - /** - * Returns the parameter with the specified name. - * <p> - * Returns <jk>null</jk> for parameters with no value (e.g. <js>"&foo"</js>). - * This is consistent with WAS, but differs from Tomcat behavior. - * The presence of parameter <js>"&foo"</js> in this case can be determined using {@link #hasParameter(String)}. - * <p> - * Parameter lookup is case-insensitive (consistent with WAS, but differs from Tomcat). - * <p> - * <i>Note:</i> Calling this method on URL-Encoded FORM posts causes the body content to be loaded and parsed by - * the underlying servlet API. - * <p> - * <i>Note:</i> This method returns the raw unparsed value, and differs from calling <code>getParameter(name, String.<jk>class</js>)</code> - * which will convert the value from UON notation: - * <ul> - * <li><js>"\u0000"</js> => <jk>null</jk> - * <li><js>"$s(foo)"</js> => <js>"foo"</js> - * <li><js>"(foo)"</js> => <js>"foo"</js> - * </ul> - */ - @Override /* ServletRequest */ - public String getParameter(String name) { - String s = null; - if (overriddenParams != null) - s = overriddenParams.get(name); - if (s != null) - return s; - - String val = super.getParameter(name); - - // Fix for behavior difference between Tomcat and WAS. - // getParameter("foo") on "&foo" in Tomcat returns "". - // getParameter("foo") on "&foo" in WAS returns null. - if (val != null && val.isEmpty()) - if (queryParams.containsKey(name)) - val = null; - - return val; - } - - /** - * Same as {@link #getParameter(String)} except returns the default value - * if <jk>null</jk> or empty. - * - * @param name The query parameter name. - * @param def The default value. - * @return The parameter value, or the default value if <jk>null</jk> or empty. - */ - public String getParameter(String name, String def) { - String val = getParameter(name); - if (val == null || val.isEmpty()) - return def; - return val; - } - - /** - * Returns the specified URL parameter value parsed to the specified class type using the - * {@link UrlEncodingParser} registered with this servlet. - * <p> - * <i>Note:</i> Calling this method on URL-Encoded FORM posts causes the body content to be loaded and parsed by - * the underlying servlet API. - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @param def The default value if the parameter was not specified or is <jk>null</jk>. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameter(String name, Class<T> c, T def) throws ParseException { - return getParameter(name, beanContext.getClassMeta(c), def); - } - - /** - * Returns the specified URL parameter value parsed to the specified class type using the - * {@link UrlEncodingParser} registered with this servlet. - * <p> - * <i>Note:</i> Calling this method on URL-Encoded FORM posts causes the body content to be loaded and parsed by - * the underlying servlet API. - * <p> - * Unlike {@link #getParameter(String, Class, Object)}, this method can be used to parse parameters - * of complex types involving JCF classes. - * <p class='bcode'> - * ClassMeta<Map<String,Integer>> cm = request.getBeanContext().getMapClassMeta(TreeMap.<jk>class</jk>, String.<jk>class</jk>, Integer.<jk>class</jk>); - * Map<String,Integer> m = request.getParameter(<js>"myParameter"</js>, cm, <jk>new</jk> TreeMap<String,Integer>()); - * </p> - * - * @param name The parameter name. - * @param cm The class type to convert the parameter value to. - * @param def The default value if the parameter was not specified or is <jk>null</jk>. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameter(String name, ClassMeta<T> cm, T def) throws ParseException { - String val = getParameter(name); - if (val == null) - return def; - return parseParameter(val, cm); - } - - /** - * Returns the specified URL parameter value parsed to the specified class type using the - * {@link UrlEncodingParser} registered with this servlet. - * <p> - * <i>Note:</i> Calling this method on URL-Encoded FORM posts causes the body content to be loaded and parsed by - * the underlying servlet API. - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameter(String name, Class<T> c) throws ParseException { - return getParameter(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getParameter(String, Class)} except for use on multi-part parameters - * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>) - * <p> - * This method must only be called when parsing into classes of type Collection or array. - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameters(String name, Class<T> c) throws ParseException { - return getParameters(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getParameter(String, Class)} except works on parameterized - * types such as those returned by {@link Method#getGenericParameterTypes()} - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameter(String name, Type c) throws ParseException { - return (T)getParameter(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getParameter(String, Class)} except for use on multi-part parameters - * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>) - * <p> - * This method must only be called when parsing into classes of type Collection or array. - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameters(String name, Type c) throws ParseException { - return (T)getParameters(name, beanContext.getClassMeta(c)); - } - - /** - * Returns the specified URL parameter value parsed to the specified class type using the - * {@link UrlEncodingParser} registered with this servlet. - * <p> - * <i>Note:</i> Calling this method on URL-Encoded FORM posts causes the body content to be loaded and parsed by - * the underlying servlet API. - * <p> - * Unlike {@link #getParameter(String, Class)}, this method can be used to parse parameters - * of complex types involving JCF classes. - * <p class='bcode'> - * ClassMeta<Map<String,Integer>> cm = request.getBeanContext().getMapClassMeta(TreeMap.<jk>class</jk>, String.<jk>class</jk>, Integer.<jk>class</jk>); - * Map<String,Integer> m = request.getParameter(<js>"myParameter"</js>, cm); - * </p> - * - * @param name The parameter name. - * @param cm The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getParameter(String name, ClassMeta<T> cm) throws ParseException { - - String val = getParameter(name); - - if (cm.isPrimitive() && (val == null || val.isEmpty())) - return cm.getPrimitiveDefault(); - - return parseParameter(val, cm); - } - - /** - * Same as {@link #getParameter(String, ClassMeta)} except for use on multi-part parameters - * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>) - * <p> - * This method must only be called when parsing into classes of type Collection or array. - * - * @param name The parameter name. - * @param cm The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - @SuppressWarnings("rawtypes") - public <T> T getParameters(String name, ClassMeta<T> cm) throws ParseException { - String[] p = getParameterValues(name); - if (p == null) - return null; - if (cm.isArray()) { - List c = new ArrayList(); - for (int i = 0; i < p.length; i++) - c.add(parseParameter(p[i], cm.getElementType())); - return (T)ArrayUtils.toArray(c, cm.getElementType().getInnerClass()); - } else if (cm.isCollection()) { - try { - Collection c = (Collection)(cm.canCreateNewInstance() ? cm.newInstance() : new ObjectList()); - for (int i = 0; i < p.length; i++) - c.add(parseParameter(p[i], cm.getElementType())); - return (T)c; - } catch (ParseException e) { - throw e; - } catch (Exception e) { - // Typically an instantiation exception. - throw new ParseException(e); - } - } - throw new ParseException("Invalid call to getParameters(String, ClassMeta). Class type must be a Collection or array."); - } - - /** - * Returns <jk>true</jk> if the URL parameters on this request contains the specified entry. - * <p> - * Note that this returns <jk>true</jk> even if the value is set to null (e.g. <js>"?key"</js>). - * - * @param name The URL parameter name. - * @return <jk>true</jk> if the URL parameters on this request contains the specified entry. - */ - public boolean hasParameter(String name) { - return getParameterMap().containsKey(name); - } - - /** - * Same as {@link #getParameter(String)} except only looks in the URL string, - * not parameters from URL-Encoded FORM posts. - * <p> - * This method can be used to retrieve a parameter without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name The URL parameter name. - * @return The parameter value, or <jk>null</jk> if parameter not specified or has no value (e.g. <js>"&foo"</js>. - */ - public String getQueryParameter(String name) { - String s = null; - if (overriddenParams != null) - s = overriddenParams.get(name); - if (s != null) - return s; - String[] v = queryParams.get(name); - if (v == null || v.length == 0) - return null; - if (v.length == 1 && v[0] != null && v[0].isEmpty()) { - // Fix for behavior difference between Tomcat and WAS. - // getParameter("foo") on "&foo" in Tomcat returns "". - // getParameter("foo") on "&foo" in WAS returns null. - if (queryParams.containsKey(name)) - return null; - } - - return v[0]; - } - - /** - * Same as {@link #getQueryParameter(String)} but returns the specified default - * value if the query parameter was not specified. - * - * @param name The URL parameter name. - * @param def The default value. - * @return The parameter value, or the default value if parameter not specified or has no value (e.g. <js>"&foo"</js>. - */ - public String getQueryParameter(String name, String def) { - String s = getQueryParameter(name); - return s == null ? def : s; - } - - /** - * Same as {@link #getParameter(String, Class, Object)} except only looks in the URL string, - * not parameters from URL-Encoded FORM posts. - * <p> - * This method can be used to retrieve a parameter without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @param def The default value if the parameter was not specified or is <jk>null</jk>. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameter(String name, Class<T> c, T def) throws ParseException { - return getQueryParameter(name, beanContext.getClassMeta(c), def); - } - - /** - * Same as {@link #getParameter(String, ClassMeta, Object)} except only looks in the URL string, - * not parameters from URL-Encoded FORM posts. - * <p> - * This method can be used to retrieve a parameter without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name The parameter name. - * @param cm The class type to convert the parameter value to. - * @param def The default value if the parameter was not specified or is <jk>null</jk>. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameter(String name, ClassMeta<T> cm, T def) throws ParseException { - String val = getQueryParameter(name); - if (val == null) - return def; - return parseParameter(val, cm); - } - - /** - * Same as {@link #getParameter(String, ClassMeta, Object)} except only looks in the URL string, - * not parameters from URL-Encoded FORM posts. - * <p> - * This method can be used to retrieve a parameter without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name The parameter name. - * @param c The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameter(String name, Class<T> c) throws ParseException { - return getQueryParameter(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getQueryParameter(String, Class)} except for use on multi-part parameters - * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>). - * <p> - * This method must only be called when parsing into classes of type Collection or array. - * - * @param name The query parameter name. - * @param c The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The query parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameters(String name, Class<T> c) throws ParseException { - return getQueryParameters(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getQueryParameter(String, Class)} except works on parameterized - * types such as those returned by {@link Method#getGenericParameterTypes()} - * - * @param name The query parameter name. - * @param c The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The query parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameter(String name, Type c) throws ParseException { - return (T)getQueryParameter(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getQueryParameter(String, Type)} except for use on multi-part parameters - * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>). - * <p> - * This method must only be called when parsing into classes of type Collection or array. - * - * @param name The query parameter name. - * @param c The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The query parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameters(String name, Type c) throws ParseException { - return (T)getQueryParameters(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getParameter(String, ClassMeta)} except only looks in the URL string, - * not parameters from URL-Encoded FORM posts. - * <p> - * This method can be used to retrieve a parameter without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name The parameter name. - * @param cm The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - public <T> T getQueryParameter(String name, ClassMeta<T> cm) throws ParseException { - - String val = getQueryParameter(name); - - if (cm.isPrimitive() && (val == null || val.isEmpty())) - return cm.getPrimitiveDefault(); - return parseParameter(val, cm); - } - - /** - * Same as {@link #getQueryParameter(String, ClassMeta)} except for use on multi-part parameters - * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>). - * <p> - * This method must only be called when parsing into classes of type Collection or array. - * - * @param name The parameter name. - * @param cm The class type to convert the parameter value to. - * @param <T> The class type to convert the parameter value to. - * @return The parameter value converted to the specified class type. - * @throws ParseException - */ - @SuppressWarnings("rawtypes") - public <T> T getQueryParameters(String name, ClassMeta<T> cm) throws ParseException { - String[] p = getQueryParameters(name); - if (p == null) - return null; - if (cm.isArray()) { - List c = new ArrayList(); - for (int i = 0; i < p.length; i++) - c.add(parseParameter(p[i], cm.getElementType())); - return (T)ArrayUtils.toArray(c, cm.getElementType().getInnerClass()); - } else if (cm.isCollection()) { - try { - Collection c = (Collection)(cm.canCreateNewInstance() ? cm.newInstance() : new ObjectList()); - for (int i = 0; i < p.length; i++) - c.add(parseParameter(p[i], cm.getElementType())); - return (T)c; - } catch (ParseException e) { - throw e; - } catch (Exception e) { - // Typically an instantiation exception. - throw new ParseException(e); - } - } - throw new ParseException("Invalid call to getQueryParameters(String, ClassMeta). Class type must be a Collection or array."); - } - - /** - * Returns the list of all query parameters with the specified name. - * Same as {@link #getParameterValues(String)} except only looks in the URL string, - * not parameters from URL-Encoded FORM posts. - * <p> - * This method can be used to retrieve parameters without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name - * @return the list of query parameters, or <jk>null</jk> if the parameter does not exist. - */ - public String[] getQueryParameters(String name) { - return queryParams.get(name); - } - - /** - * Returns <jk>true</jk> if the URL parameters on this request contains the specified entry. - * <p> - * Note that this returns <jk>true</jk> even if the value is set to null (e.g. <js>"?key"</js>). - * <p> - * This method can be used to check the existence of a parameter without triggering the underlying - * servlet API to load and parse the request body. - * - * @param name The URL parameter name. - * @return <jk>true</jk> if the URL parameters on this request contains the specified entry. - */ - public boolean hasQueryParameter(String name) { - return queryParams.containsKey(name); - } - - /** - * Equivalent to {@link #getParameterMap()}, but only looks for query parameters in the URL, not form posts. - * <p> - * This method can be used to retrieve query parameters without triggering the underlying - * servlet API to load and parse the request body. - * <p> - * This object is modifiable. - * - * @return The query parameters as a modifiable map. - */ - public Map<String,String[]> getQueryParameterMap() { - return queryParams; - } - - /** - * Equivalent to {@link #getParameterNames()}, but only looks for query parameters in the URL, not form posts. - * <p> - * This method can be used to retrieve query parameters without triggering the underlying - * servlet API to load and parse the request body. - * <p> - * This object is modifiable. - * - * @return An iterator of query parameter names. - */ - public Iterator<String> getQueryParameterNames() { - return queryParams.keySet().iterator(); - } - - private <T> T parseParameter(String val, ClassMeta<T> c) throws ParseException { - if (val == null) - return null; - // Shortcut - If we're returning a string and the value doesn't start with '$' or '(', then - // just return the string since it's a plain value. - if (c.getInnerClass() == String.class && val.length() > 0) { - char x = val.charAt(0); - if (x != '(' && x != '$' && x != '\u0000' && val.indexOf('~') == -1) - return (T)val; - } - return urlEncodingParser.parseParameter(val, c); - } - - /** - * Shortcut for calling <code>getHeaders().get(c, name, def);</code> - * <p> - * The type can be any POJO type convertable from a <code>String</code> (See <a class='doclink' href='package-summary.html#PojosConvertableFromString'>POJOs Convertable From Strings</a>). - * - * @param name The HTTP header name. - * @param c The class type to convert the header value to. - * @param def The default value if the header was not specified or is <jk>null</jk>. - * @param <T> The class type to convert the header value to. - * @return The parameter value converted to the specified class type. - */ - public <T> T getHeader(String name, Class<T> c, T def) { - String h = getHeader(name); - if (h == null) - return def; - return beanContext.convertToType(h, c); - } - - /** - * Shortcut for calling <code>getHeaders().get(c, name);</code> - * <p> - * The type can be any POJO type convertable from a <code>String</code> (See <a class='doclink' href='package-summary.html#PojosConvertableFromString'>POJOs Convertable From Strings</a>). - * - * @param name The HTTP header name. - * @param c The class type to convert the header value to. - * @param <T> The class type to convert the header value to. - * @return The parameter value converted to the specified class type. - */ - public <T> T getHeader(String name, Class<T> c) { - String h = getHeader(name); - return beanContext.convertToType(h, c); - } - - /** - * Same as {@link #getHeader(String, Class)} except works on parameterized - * types such as those returned by {@link Method#getGenericParameterTypes()} - * - * @param name The HTTP header name. - * @param c The class type to convert the header value to. - * @param <T> The class type to convert the header value to. - * @return The parameter value converted to the specified class type. - */ - public <T> T getHeader(String name, Type c) { - String h = getHeader(name); - return (T)beanContext.convertToType(null, h, beanContext.getClassMeta(c)); - } - - /** - * Returns the specified request attribute converted to the specified class type. - * <p> - * The type can be any POJO type convertable from a <code>String</code> (See <a class='doclink' href='package-summary.html#PojosConvertableFromString'>POJOs Convertable From Strings</a>). - * - * @param name The attribute name. - * @param c The class type to convert the attribute value to. - * @param <T> The class type to convert the attribute value to. - * @return The attribute value converted to the specified class type. - * @throws ParseException - */ - public <T> T getAttribute(String name, Class<T> c) throws ParseException { - return getAttribute(name, beanContext.getClassMeta(c)); - } - - /** - * Same as {@link #getAttribute(String, Class)} except works on parameterized - * types such as those returned by {@link Method#getGenericParameterTypes()} - * - * @param name The attribute name. - * @param c The class type to convert the attribute value to. - * @param <T> The class type to convert the attribute value to. - * @return The attribute value converted to the specified class type. - * @throws ParseException - */ - public <T> T getAttribute(String name, Type c) throws ParseException { - return (T)getAttribute(name, beanContext.getClassMeta(c)); - } - - /** - * Returns the specified request attribute converted to the specified class type. - * <p> - * The type can be any POJO type convertable from a <code>String</code> (See <a class='doclink' href='package-summary.html#PojosConvertableFromString'>POJOs Convertable From Strings</a>). - * - * @param name The attribute name. - * @param cm The class type to convert the attribute value to. - * @param <T> The class type to convert the attribute value to. - * @return The attribute value converted to the specified class type. - * @throws ParseException - */ - public <T> T getAttribute(String name, ClassMeta<T> cm) throws ParseException { - Object attr = getAttribute(name); - T t = null; - if (attr != null) - t = urlEncodingParser.parseParameter(attr.toString(), cm); - if (t == null && cm.isPrimitive()) - return cm.getPrimitiveDefault(); - return t; - } - - /** - * Same as {@link HttpServletRequest#getPathInfo()} except returns the path undecoded. - * - * @return The undecoded portion of the URL after the resource URL path pattern match. - */ - public String getPathInfoUndecoded() { - return RestUtils.getPathInfoUndecoded(this); - } - - /** - * Returns the value {@link #getPathInfo()} split on the <js>'/'</js> character. - * <p> - * If path info is <jk>null</jk>, returns an empty list. - * <p> - * URL-encoded characters in segments are automatically decoded by this method. - * - * @return The decoded segments, or an empty list if path info is <jk>null</jk>. - */ - public String[] getPathInfoParts() { - String s = getPathInfoUndecoded(); - if (s == null || s.isEmpty() || s.equals("/")) - return new String[0]; - s = s.substring(1); - if (s.endsWith("/")) - s = s.substring(0, s.length()-1); - boolean needsDecode = (s.indexOf('%') != -1 || s.indexOf('+') != -1); - String[] l = s.split("/", Integer.MAX_VALUE); - try { - if (needsDecode) - for (int i = 0; i < l.length; i++) - l[i] = URLDecoder.decode(l[i], "UTF-8"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); // Won't happen. - } - return l; - } - - /** - * Same as {@link #getInput(ClassMeta)}, except a shortcut for passing in regular {@link Class} objects - * instead of having to look up {@link ClassMeta} objects. - * - * @param type The class type to instantiate. - * @param <T> The class type to instantiate. - * @return The input parsed to a POJO. - * @throws IOException If a problem occurred trying to read from the reader. - * @throws ParseException If the input contains a syntax error or is malformed for the requested {@code Accept} header or is not valid for the specified type. - */ - public <T> T getInput(Class<T> type) throws IOException, ParseException { - return getInput(beanContext.getClassMeta(type)); - } - - /** - * Same as {@link #getInput(Class)} except works on parameterized - * types such as those returned by {@link Method#getGenericParameterTypes()} - * - * @param type The class type to instantiate. - * @param <T> The class type to instantiate. - * @return The input parsed to a POJO. - */ - public <T> T getInput(Type type) { - return (T)getInput(beanContext.getClassMeta(type)); - } - - /** - * Reads the input from the HTTP request as JSON, XML, or HTML and converts the input to the specified class type. - * <p> - * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks - * for {@code &content=xxx} in the URL query string. - * <p> - * If type is <jk>null</jk> or <code>Object.<jk>class</jk></code>, then the actual type will be determined automatically based on the - * following input: - * <table class='styled'> - * <tr><th>Type</th><th>JSON input</th><th>XML input</th><th>Return type</th></tr> - * <tr> - * <td>object</td> - * <td><js>"{...}"</js></td> - * <td><code><xt><object></xt>...<xt></object></xt></code><br><code><xt><x</xt> <xa>type</xa>=<xs>'object'</xs><xt>></xt>...<xt></x></xt></code></td> - * <td>{@link ObjectMap}</td> - * </tr> - * <tr> - * <td>array</td> - * <td><js>"[...]"</js></td> - * <td><code><xt><array></xt>...<xt></array></xt></code><br><code><xt><x</xt> <xa>type</xa>=<xs>'array'</xs><xt>></xt>...<xt></x></xt></code></td> - * <td>{@link ObjectList}</td> - * </tr> - * <tr> - * <td>string</td> - * <td><js>"'...'"</js></td> - * <td><code><xt><string></xt>...<xt></string></xt></code><br><code><xt><x</xt> <xa>type</xa>=<xs>'string'</xs><xt>></xt>...<xt></x></xt></code></td> - * <td>{@link String}</td> - * </tr> - * <tr> - * <td>number</td> - * <td><code>123</code></td> - * <td><code><xt><number></xt>123<xt></number></xt></code><br><code><xt><x</xt> <xa>type</xa>=<xs>'number'</xs><xt>></xt>...<xt></x></xt></code></td> - * <td>{@link Number}</td> - * </tr> - * <tr> - * <td>boolean</td> - * <td><jk>true</jk></td> - * <td><code><xt><boolean></xt>true<xt></boolean></xt></code><br><code><xt><x</xt> <xa>type</xa>=<xs>'boolean'</xs><xt>></xt>...<xt></x></xt></code></td> - * <td>{@link Boolean}</td> - * </tr> - * <tr> - * <td>null</td> - * <td><jk>null</jk> or blank</td> - * <td><code><xt><null/></xt></code> or blank<br><code><xt><x</xt> <xa>type</xa>=<xs>'null'</xs><xt>/></xt></code></td> - * <td><jk>null</jk></td> - * </tr> - * </table> - * <p> - * Refer to <a href='../core/package-summary.html#PojoCategories' class='doclink'>POJO Categories</a> for a complete definition of supported POJOs. - * - * @param type The class type to instantiate. - * @param <T> The class type to instantiate. - * @return The input parsed to a POJO. - * @throws RestException If a problem occurred trying to read the input. - */ - public <T> T getInput(ClassMeta<T> type) throws RestException { - - try { - if (type.isReader()) - return (T)getReader(); - - if (type.isInputStream()) - return (T)getInputStream(); - - String mediaType = getMediaType(); - Parser p = getParser(); - - if (p != null) { - try { - properties.append("mediaType", mediaType).append("characterEncoding", getCharacterEncoding()); - if (! p.isReaderParser()) { - InputStreamParser p2 = (InputStreamParser)p; - ParserSession session = p2.createSession(getInputStream(), properties, getJavaMethod(), getServlet()); - return p2.parse(session, type); - } - ReaderParser p2 = (ReaderParser)p; - ParserSession session = p2.createSession(getUnbufferedReader(), properties, getJavaMethod(), getServlet()); - return p2.parse(session, type); - } catch (ParseException e) { - throw new RestException(SC_BAD_REQUEST, - "Could not convert request body content to class type ''{0}'' using parser ''{1}''.", - type, p.getClass().getName() - ).initCause(e); - } - } - - throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE, - "Unsupported media-type in request header ''Content-Type'': ''{0}''\n\tSupported media-types: {1}", - getHeader("Content-Type"), parserGroup.getSupportedMediaTypes() - ); - - } catch (IOException e) { - throw new RestException(SC_INTERNAL_SERVER_ERROR, - "I/O exception occurred while attempting to handle request ''{0}''.", - getDescription() - ).initCause(e); - } - } - - /** - * Returns the parser matching the request <code>Accept</code> header. - * - * @return The parser matching the request <code>Accept</code> header, or <jk>null</jk> - * if no matching parser was found. - */ - public Parser getParser() { - String mediaType = getMediaType(); - Parser p = parserGroup.getParser(mediaType); - - // If no patching parser for URL-encoding, use the one defined on the servlet. - if (p == null && mediaType.equals("application/x-www-form-urlencoded")) - p = urlEncodingParser; - - return p; - } - - /** - * Returns the reader parser matching the request <code>Accept</code> header. - * - * @return The reader parser matching the request <code>Accept</code> header, or <jk>null</jk> - * if no matching reader parser was found, or the matching parser was an input stream parser. - */ - public ReaderParser getReaderParser() { - Parser p = getParser(); - if (p.isReaderParser()) - return (ReaderParser)p; - return null; - } - - /** - * Returns the HTTP body content as a plain string. - * <p> - * If {@code allowHeaderParams} init parameter is true, then first looks - * for {@code &content=xxx} in the URL query string. - * - * @return The incoming input from the connection as a plain string. - * @throws IOException If a problem occurred trying to read from the reader. - */ - public String getInputAsString() throws IOException { - if (content != null) - return content; - content = IOUtils.read(getReader()).toString(); - return content; - } - - /** - * Returns a resolved URL. - * <p> - * <ul class='spaced-list'> - * <li>Fully-qualified absolute URLs (e.g. <js>"http://..."</js>, <js>"https://"</js>) are simply converted to a URL. - * <li>Absolute URLs (e.g. <js>"/foo/..."</js>) are interpreted as relative to the server hostname. - * <li>Relative URLs (e.g. <js>"foo/..."</js>) are interpreted as relative to this servlet path. - * </ul> - * - * @param path The URL path to resolve. - * @return The resolved URL. - * @throws MalformedURLException If path is not a valid URL component. - */ - public URL getURL(String path) throws MalformedURLException { - if (path.startsWith("http://") || path.startsWith("https://")) - return new URL(path); - if (StringUtils.startsWith(path, '/')) - return new URL(getScheme(), getLocalName(), getLocalPort(), path); - return new URL(getScheme(), getLocalName(), getLocalPort(), getContextPath() + getServletPath() + (StringUtils.isEmpty(path) ? "" : ('/' + path))); - } - - /** - * Returns the HTTP body content as a {@link Reader}. - * <p> - * If {@code allowHeaderParams} init parameter is true, then first looks - * for {@code &content=xxx} in the URL query string. - * <p> - * Automatically handles GZipped input streams. - */ - @Override /* ServletRequest */ - public BufferedReader getReader() throws IOException { - Reader r = getUnbufferedReader(); - if (r instanceof BufferedReader) - return (BufferedReader)r; - int len = getContentLength(); - int buffSize = len <= 0 ? 8192 : Math.max(len, 8192); - return new BufferedReader(r, buffSize); - } - - /** - * Same as {@link #getReader()}, but doesn't encapsulate the result in a {@link BufferedReader}; - * - * @return An unbuffered reader. - * @throws IOException - */ - protected Reader getUnbufferedReader() throws IOException { - if (content != null) - return new CharSequenceReader(content); - return new InputStreamReader(getInputStream(), getCharacterEncoding()); - } - - /** - * Returns the HTTP body content as an {@link InputStream}. - * <p> - * Automatically handles GZipped input streams. - * - * @return The negotiated input stream. - * @throws IOException If any error occurred while trying to get the input stream or wrap it - * in the GZIP wrapper. - */ - @Override /* ServletRequest */ - public ServletInputStream getInputStream() throws IOException { - - Encoder enc = getEncoder(); - - ServletInputStream is = super.getInputStream(); - if (enc != null) { - final InputStream is2 = enc.getInputStream(is); - return new ServletInputStream() { - @Override /* InputStream */ - public final int read() throws IOException { - return is2.read(); - } - @Override /* InputStream */ - public final void close() throws IOException { - is2.close(); - } - }; - } - return is; - } - - private Encoder getEncoder() { - if (encoder == null) { - String ce = getHeader("content-encoding"); - if (! (ce == null || ce.isEmpty())) { - ce = ce.trim(); - encoder = servlet.getEncoders().getEncoder(ce); - if (encoder == null) - throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE, - "Unsupported encoding in request header ''Content-Encoding'': ''{0}''\n\tSupported codings: {1}", - getHeader("content-encoding"), servlet.getEncoders().getSupportedEncodings() - ); - } - - if (encoder != null) - contentLength = -1; - } - // Note that if this is the identity encoder, we want to return null - // so that we don't needlessly wrap the input stream. - if (encoder == IdentityEncoder.INSTANCE) - return null; - return encoder; - } - - @Override /* ServletRequest */ - public int getContentLength() { - return contentLength == 0 ? super.getContentLength() : contentLength; - } - - /** - * Returns <jk>true</jk> if <code>&plainText=true</code> was specified as a URL parameter. - * <p> - * This indicates that the <code>Content-Type</code> of the output should always be set to <js>"text/plain"</js> - * to make it easy to render in a browser. - * <p> - * This feature is useful for debugging. - * - * @return <jk>true</jk> if {@code &plainText=true} was specified as a URL parameter - */ - public boolean isPlainText() { - return "true".equals(getQueryParameter("plainText", "false")); - } - - /** - * Returns the decoded remainder of the URL following any path pattern matches. - * <p> - * The behavior of path remainder is shown below given the path pattern "/foo/*": - * <p> - * <table class='styled'> - * <tr> - * <th>URL</th> - * <th>Path Remainder</th> - * </tr> - * <tr> - * <th><code>/foo</code></th> - * <th><jk>null</jk></th> - * </tr> - * <tr> - * <th><code>/foo/</code></th> - * <th><js>""</js></th> - * </tr> - * <tr> - * <th><code>/foo//</code></th> - * <th><js>"/"</js></th> - * </tr> - * <tr> - * <th><code>/foo///</code></th> - * <th><js>"//"</js></th> - * </tr> - * <tr> - * <th><code>/foo/a/b</code></th> - * <th><js>"a/b"</js></th> - * </tr> - * <tr> - * <th><code>/foo//a/b/</code></th> - * <th><js>"/a/b/"</js></th> - * </tr> - * <tr> - * <th><code>/foo/a%2Fb</code></th> - * <th><js>"a/b"</js></th> - * </tr> - * </table> - * - * <dl> - * <dt>Example:</dt> - * <dd> - * <p class='bcode'> - * <jc>// REST method</jc> - * <ja>@RestMethod</ja>(name=<js>"GET"</js>,path=<js>"/foo/{bar}/*"</js>) - * <jk>public</jk> doGetById(RestServlet res, RestResponse res, <jk>int</jk> bar) { - * System.<jsm>err</jsm>.println(res.getRemainder()); - * } - * - * <jc>// Prints "path/remainder"</jc> - * <jk>new</jk> RestCall(servletPath + <js>"/foo/123/path/remainder"</js>).connect(); - * </p> - * </dd> - * </dl> - * - * @return The path remainder string. - */ - public String getPathRemainder() { - return RestUtils.decode(pathRemainder); - } - - /** - * Same as {@link #getPathRemainder()} but doesn't decode characters. - * - * @return The undecoded path remainder. - */ - public String getPathRemainderUndecoded() { - return pathRemainder; - } - - /** - * Shortcut method for calling {@link RestServlet#getMessage(Locale, String, Object...)} based - * on the request locale. - * - * @param key The message key. - * @param args Optional {@link MessageFormat} variable values in the value. - * @return The localized message. - */ - public String getMessage(String key, Object...args) { - return servlet.getMessage(getLocale(), key, args); - } - - /** - * Shortcut method for calling {@link RestServlet#getMethodDescriptions(RestRequest)} based - * on the request locale. - * - * @return The localized method descriptions. - * @throws RestServletException - */ - public Collection<MethodDescription> getMethodDescriptions() throws RestServletException { - return servlet.getMethodDescriptions(this); - } - - /** - * Returns the resource bundle for the request locale. - * - * @return The resource bundle. Never <jk>null</jk>. - */ - public MessageBundle getResourceBundle() { - return servlet.getMessages(getLocale()); - } - - /** - * Returns the servlet handling the request. - * <p> - * Can be used to access servlet-init parameters or annotations during requests, - * such as in calls to {@link RestGuard#guard(RestRequest, RestResponse)}.. - * - * @return The servlet handling the request. - */ - public RestServlet getServlet() { - return servlet; - } - - /** - * Returns the java method handling the request. - * <p> - * Can be used to access the method name or method annotations during requests, such - * as in calls to {@link RestGuard#guard(RestRequest, RestResponse)}. - * <p> - * Note: This returns null when evaluating servlet-level guards since the method - * has not been resolved at that point of execution. - * - * @return The Java method handling the request, or <code>null</code> if the method - * has not yet been resolved. - */ - public Method getJavaMethod() { - return javaMethod; - } - - /** - * Returns the URI of the parent resource. - * <p> - * Trailing slashes in the path are ignored by this method. - * <p> - * The behavior is shown below: - * <table class='styled'> - * <tr> - * <th>getRequestURI</th> - * <th>getRequestParentURI</th> - * </tr> - * <tr> - * <th><code>/foo/bar</code></th> - * <th><code>/foo</code></th> - * </tr> - * <tr> - * <th><code>/foo/bar?baz=bing</code></th> - * <th><code>/foo</code></th> - * </tr> - * <tr> - * <th><code>/foo/bar/</code></th> - * <th><code>/foo</code></th> - * </tr> - * <tr> - * <th><code>/foo/bar//</code></th> - * <th><code>/foo</code></th> - * </tr> - * <tr> - * <th><code>/foo//bar//</code></th> - * <th><code>/foo/</code></th> - * </tr> - * <tr> - * <th><code>/foo</code></th> - * <th>/</th> - * </tr> - * </table> - * - * @return The request parent URI. - */ - public String getRequestParentURI() { - String uri = getRequestURI(); - while (StringUtils.endsWith(uri, '/')) - uri = uri.substring(0, uri.length()-1); - int i = uri.lastIndexOf('/'); - if (i <= 0) - return "/"; - return uri.substring(0, i); - } - - /** - * Same as {@link #getRequestURI()} but trims trailing slashes from the result. - * - * @return The trimmed request URI. - */ - public String getTrimmedRequestURI() { - return RestUtils.trimTrailingSlashes(getRequestURI()); - } - - /** - * Same as {@link #getRequestURL()} but trims trailing slashes from the result. - * - * @return The trimmed request URL. - */ - public StringBuffer getTrimmedRequestURL() { - return RestUtils.trimTrailingSlashes(getRequestURL()); - } - - /** - * Gets the URI of the servlet (e.g. <js>"https://localhost:9080/contextPath/servletPath"</js>). - * - * @return The servlet URI. - */ - public String getServletURI() { - if (servletURI == null) { - // Note that we can't use getPathInfo() to calculate this since it replaces - // URL-encoded chars (e.g. %2F) which throws off the length calculation - // because getRequestURL() does not replace those chars. - servletURI = getServletURIBuilder().toString(); - } - return servletURI; - } - - /** - * Gets the path-absolute relative URI of the servlet (e.g. <js>"/contextPath/servletPath"</js>). - * - * @return The relative servlet URI. - */ - public String getRelativeServletURI() { - if (relativeServletURI == null) - relativeServletURI = getContextPath() + getServletPath(); - return relativeServletURI; - } - - /** - * Returns a <code>StringBuffer</code> prefilled with the string <code><js>"/[contextPath]/[servletPath]"</js></code>. - * - * @return The servlet URI string builder. - */ - public StringBuffer getServletURIBuilder() { - return RestUtils.trimPathInfo(getRequestURL(), getContextPath(), getServletPath()); - } - - /** - * Returns the {@link BeanContext} associated with this request. - * - * @return The request bean context. - */ - public BeanContext getBeanContext() { - return beanContext; - } - - /** - * Returns the localized servlet label. - * Equivalent to calling {@link RestServlet#getLabel(RestRequest)} with this object. - * - * @return The localized servlet label. - */ - public String getServletLabel() { - return servlet.getLabel(this); - } - - /** - * Returns the localized servlet description. - * Equivalent to calling {@link RestServlet#getDescription(RestRequest)} with this object. - * - * @return The localized servlet description. - */ - public String getServletDescription() { - return servlet.getDescription(this); - } - - /** - * Returns the localized method description. - * Equivalent to calling {@link RestServlet#getMethodDescription(String, RestRequest)} with this object. - * - * @return The localized method description. - */ - public String getMethodDescription() { - return servlet.getMethodDescription(javaMethod.getName(), this); - } - - /** - * Returns the variable resolver session for this request using session objects created by {@link RestServlet#getSessionObjects(RestRequest)}. - * - * @return The variable resolver for this request. - */ - public VarResolverSession getVarResolverSession() { - if (varSession == null) - varSession = servlet.getVarResolver().createSession(servlet.getSessionObjects(this)); - return varSession; - } - - /** - * Shortcut for calling <code>getVarResolverSession().resolve(input)</code>. - * - * @param input The input string to resolve variables in. - * @return The string with variables resolved, or <jk>null</jk> if input is null. - */ - public String resolveVars(String input) { - return getVarResolverSession().resolve(input); - } - - /** - * Returns an instance of a {@link ReaderResource} that represents the contents of a resource text file from the classpath. - * <p> - * - * @param name The name of the resource (i.e. the value normally passed to {@link Class#getResourceAsStream(String)}. - * @param resolveVars If <jk>true</jk>, any {@link Var} variables will be resolved by the variable resolver returned - * by {@link #getVarResolverSession()}. - * @param contentType The value to set as the <js>"Content-Type"</js> header for this object. - * @return A new reader resource, or <jk>null</jk> if resource could not be found. - * @throws IOException - */ - public ReaderResource getReaderResource(String name, boolean resolveVars, String contentType) throws IOException { - String s = servlet.getResourceAsString(name); - if (s == null) - return null; - ReaderResource rr = new ReaderResource(s, contentType); - if (resolveVars) - rr.setVarSession(getVarResolverSession()); - return rr; - } - - /** - * Same as {@link #getReaderResource(String, boolean, String)} except uses {@link RestServlet#getMimetypesFileTypeMap()} - * to determine the media type. - * - * @param name The name of the resource (i.e. the value normally passed to {@link Class#getResourceAsStream(String)}. - * @param resolveVars If <jk>true</jk>, any {@link Var} variables will be resolved by the variable resolver returned - * by {@link #getVarResolverSession()}. - * @return A new reader resource, or <jk>null</jk> if resource could not be found. - * @throws IOException - */ - public ReaderResource getReaderResource(String name, boolean resolveVars) throws IOException { - return getReaderResource(name, resolveVars, servlet.getMimetypesFileTypeMap().getContentType(name)); - } - - /** - * Same as {@link #getReaderResource(String, boolean)} with <code>resolveVars == <jk>false</jk></code> - * - * @param name The name of the resource (i.e. the value normally passed to {@link Class#getResourceAsStream(String)}. - * @return A new reader resource, or <jk>null</jk> if resource could not be found. - * @throws IOException - */ - public ReaderResource getReaderResource(String name) throws IOException { - return getReaderResource(name, false, servlet.getMimetypesFileTypeMap().getContentType(name)); - } - - /** - * Returns the config file associated with the servlet. - * - * @return The config file associated with the servlet, or <jk>null</jk> if servlet does not have a config file associated with it. - */ - public ConfigFile getConfig() { - if (cf == null) - cf = servlet.getConfig().getResolving(getVarResolverSession()); - return cf; - } - - @Override /* Object */ - public String toString() { - StringBuilder sb = new StringBuilder("\n").append(getDescription()).append("\n"); - sb.append("---Headers---\n"); - for (Enumeration<String> e = getHeaderNames(); e.hasMoreElements();) { - String h = e.nextElement(); - sb.append("\t").append(h).append(": ").append(getHeader(h)).append("\n"); - } - sb.append("---Default Servlet Headers---\n"); - for (Map.Entry<String,String> e : defaultServletHeaders.entrySet()) { - sb.append("\t").append(e.getKey()).append(": ").append(e.getValue()).append("\n"); - } - if (method.equals("PUT") || method.equals("POST")) { - sb.append("---Content---\n"); - try { - sb.append(getInputAsString()).append("\n"); - } catch (Exception e1) { - sb.append(e1.getLocalizedMessage()); - servlet.log(WARNING, e1, "Error occurred while trying to read debug input."); - } - } - return sb.toString(); - } - - /** - * Returns the URI of the parent of this servlet. - * - * @return The URI of the parent of this servlet. - */ - public String getServletParentURI() { - String s = getServletURI(); - return s.substring(0, s.lastIndexOf('/')); - } -} \ No newline at end of file
