RequestContext.java
/*
* Copyright (c) 2013, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.tyrus.core;
import java.net.URI;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.glassfish.tyrus.spi.UpgradeRequest;
/**
* Implementation of all possible request interfaces. Should be the only point of truth.
*
* @author Pavel Bucek (pavel.bucek at oracle.com)
*/
public final class RequestContext extends UpgradeRequest {
private final URI requestURI;
private final String queryString;
private final Object httpSession;
private final boolean secure;
private final Principal userPrincipal;
private final Builder.IsUserInRoleDelegate isUserInRoleDelegate;
private final String remoteAddr;
private Map<String, List<String>> headers;
private Map<String, List<String>> parameterMap;
private RequestContext(URI requestURI, String queryString, Object httpSession, boolean secure, Principal
userPrincipal, Builder.IsUserInRoleDelegate IsUserInRoleDelegate, String remoteAddr, Map<String,
List<String>> parameterMap, Map<String, List<String>> headers) {
this.requestURI = requestURI;
this.queryString = queryString;
this.httpSession = httpSession;
this.secure = secure;
this.userPrincipal = userPrincipal;
this.isUserInRoleDelegate = IsUserInRoleDelegate;
this.remoteAddr = remoteAddr;
this.parameterMap = parameterMap;
this.headers = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
if (headers != null) {
this.headers.putAll(headers);
}
}
/**
* Get headers.
*
* @return headers map. List items are corresponding to header declaration in HTTP request.
*/
@Override
public Map<String, List<String>> getHeaders() {
return headers;
}
/**
* Returns the header value corresponding to the name.
*
* @param name header name.
* @return {@link List} of header values iff found, {@code null} otherwise.
*/
@Override
public String getHeader(String name) {
final List<String> stringList = headers.get(name);
if (stringList == null) {
return null;
} else {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (String s : stringList) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(s);
}
return sb.toString();
}
}
/**
* Make headers and parameter map read-only.
*/
public void lock() {
this.headers = Collections.unmodifiableMap(headers);
this.parameterMap = Collections.unmodifiableMap(parameterMap);
}
@Override
public Principal getUserPrincipal() {
return userPrincipal;
}
@Override
public URI getRequestURI() {
return requestURI;
}
@Override
public boolean isUserInRole(String role) {
if (isUserInRoleDelegate != null) {
return isUserInRoleDelegate.isUserInRole(role);
}
return false;
}
@Override
public Object getHttpSession() {
return httpSession;
}
@Override
public Map<String, List<String>> getParameterMap() {
return parameterMap;
}
@Override
public String getQueryString() {
return queryString;
}
@Override
public String getRequestUri() {
return requestURI.toString();
}
@Override
public boolean isSecure() {
return secure;
}
/**
* Get the Internet Protocol (IP) address of the client or last proxy that sent the request.
*
* @return a {@link String} containing the IP address of the client that sent the request or {@code null} when
* method is called on client-side.
*/
public String getRemoteAddr() {
return remoteAddr;
}
/**
* {@link RequestContext} builder.
*/
public static final class Builder {
private URI requestURI;
private String queryString;
private Object httpSession;
private boolean secure;
private Principal userPrincipal;
private Builder.IsUserInRoleDelegate isUserInRoleDelegate;
private Map<String, List<String>> parameterMap;
private String remoteAddr;
private Map<String, List<String>> headers;
/**
* Create empty builder.
*
* @return empty builder instance.
*/
public static Builder create() {
return new Builder();
}
/**
* Create builder instance based on provided {@link RequestContext}.
*
* @param requestContext request context.
* @return builder instance.
*/
public static Builder create(RequestContext requestContext) {
Builder builder = new Builder();
builder.requestURI = requestContext.requestURI;
builder.queryString = requestContext.queryString;
builder.httpSession = requestContext.httpSession;
builder.secure = requestContext.secure;
builder.userPrincipal = requestContext.userPrincipal;
builder.isUserInRoleDelegate = requestContext.isUserInRoleDelegate;
builder.parameterMap = requestContext.parameterMap;
builder.remoteAddr = requestContext.remoteAddr;
builder.headers = requestContext.headers;
return builder;
}
/**
* Set request URI.
*
* @param requestURI request URI to be set.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder requestURI(URI requestURI) {
this.requestURI = requestURI;
return this;
}
/**
* Set query string.
*
* @param queryString query string to be set.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder queryString(String queryString) {
this.queryString = queryString;
return this;
}
/**
* Set http session.
*
* @param httpSession {@code javax.servlet.http.HttpSession} session to be set.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder httpSession(Object httpSession) {
this.httpSession = httpSession;
return this;
}
/**
* Set secure state.
*
* @param secure secure state to be set.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder secure(boolean secure) {
this.secure = secure;
return this;
}
/**
* Set {@link Principal}.
*
* @param principal principal to be set.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder userPrincipal(Principal principal) {
this.userPrincipal = principal;
return this;
}
/**
* Set delegate for {@link RequestContext#isUserInRole(String)} method.
*
* @param isUserInRoleDelegate delegate for {@link RequestContext#isUserInRole(String)}.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder isUserInRoleDelegate(IsUserInRoleDelegate isUserInRoleDelegate) {
this.isUserInRoleDelegate = isUserInRoleDelegate;
return this;
}
/**
* Set parameter map.
*
* @param parameterMap parameter map. Takes map returned from ServletRequest#getParameterMap.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder parameterMap(Map<String, String[]> parameterMap) {
if (parameterMap != null) {
this.parameterMap = new HashMap<String, List<String>>();
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
this.parameterMap.put(entry.getKey(), Arrays.asList(entry.getValue()));
}
} else {
this.parameterMap = null;
}
return this;
}
/**
* Set remote address.
*
* @param remoteAddr remote address to be set.
* @return updated {@link RequestContext.Builder} instance.
*/
public Builder remoteAddr(String remoteAddr) {
this.remoteAddr = remoteAddr;
return this;
}
/**
* Build {@link RequestContext} from given properties.
*
* @return created {@link RequestContext}.
*/
public RequestContext build() {
return new RequestContext(requestURI, queryString, httpSession, secure, userPrincipal,
isUserInRoleDelegate, remoteAddr,
parameterMap != null ? parameterMap : new HashMap<String,
List<String>>(), headers);
}
/**
* Is user in role delegate.
* <p>
* Cannot easily query ServletContext or HttpServletRequest for this information, since it is stored only as
* object.
*/
public interface IsUserInRoleDelegate {
/**
* Returns a boolean indicating whether the authenticated user is included in the specified logical "role".
* Roles and role membership can be defined using deployment descriptors. If the user has not been
* authenticated, the method returns false.
*
* @param role a String specifying the name of the role.
* @return a boolean indicating whether the user making this request belongs to a given role; false if the
* user has not been authenticated.
*/
public boolean isUserInRole(String role);
}
}
}