/**
* 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.cxf.transport.websocket.jetty;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ReadListener;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.transport.websocket.InvalidPathException;
import org.apache.cxf.transport.websocket.WebSocketUtils;
/**
*
*/
public class WebSocketVirtualServletRequest implements HttpServletRequest {
private static final Logger LOG = LogUtils.getL7dLogger(WebSocketVirtualServletRequest.class);
private WebSocketServletHolder webSocketHolder;
private InputStream in;
private Map<String, String> requestHeaders;
private Map<String, Object> attributes;
public WebSocketVirtualServletRequest(WebSocketServletHolder websocket, InputStream in)
throws IOException {
this.webSocketHolder = websocket;
this.in = in;
this.requestHeaders = WebSocketUtils.readHeaders(in);
String path = requestHeaders.get(WebSocketUtils.URI_KEY);
String origin = websocket.getRequestURI();
if (!path.startsWith(origin)) {
LOG.log(Level.WARNING, "invalid path: {0} not within {1}", new Object[]{path, origin});
throw new InvalidPathException();
}
this.attributes = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
Object v = websocket.getAttribute("org.apache.cxf.transport.endpoint.address");
if (v != null) {
attributes.put("org.apache.cxf.transport.endpoint.address", v);
}
}
@Override
public AsyncContext getAsyncContext() {
return null;
}
@Override
public Object getAttribute(String name) {
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "getAttribute({0}) -> {1}", new Object[] {name, attributes.get(name)});
}
return attributes.get(name);
}
@Override
public Enumeration<String> getAttributeNames() {
LOG.log(Level.FINE, "getAttributeNames()");
return Collections.enumeration(attributes.keySet());
}
@Override
public String getCharacterEncoding() {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "getCharacterEncoding()");
return null;
}
@Override
public int getContentLength() {
LOG.log(Level.FINE, "getContentLength()");
return 0;
}
@Override
public String getContentType() {
LOG.log(Level.FINE, "getContentType()");
return requestHeaders.get("Content-Type");
}
@Override
public DispatcherType getDispatcherType() {
LOG.log(Level.FINE, "getDispatcherType()");
return webSocketHolder.getDispatcherType();
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream() {
@Override
public int read() throws IOException {
return in.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return in.read(b, off, len);
}
@Override
public boolean isFinished() {
throw new UnsupportedOperationException();
}
@Override
public boolean isReady() {
throw new UnsupportedOperationException();
}
@Override
public void setReadListener(ReadListener arg0) {
throw new UnsupportedOperationException();
}
};
}
@Override
public String getLocalAddr() {
LOG.log(Level.FINE, "getLocalAddr()");
return webSocketHolder.getLocalAddr();
}
@Override
public String getLocalName() {
LOG.log(Level.FINE, "getLocalName()");
return webSocketHolder.getLocalName();
}
@Override
public int getLocalPort() {
LOG.log(Level.FINE, "getLocalPort()");
return webSocketHolder.getLocalPort();
}
@Override
public Locale getLocale() {
LOG.log(Level.FINE, "getLocale()");
return webSocketHolder.getLocale();
}
@Override
public Enumeration<Locale> getLocales() {
LOG.log(Level.FINE, "getLocales()");
return webSocketHolder.getLocales();
}
@Override
public String getParameter(String name) {
// TODO Auto-generated method stub
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "getParameter({0})", name);
}
return null;
}
@Override
public Map<String, String[]> getParameterMap() {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "getParameterMap()");
return null;
}
@Override
public Enumeration<String> getParameterNames() {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "getParameterNames()");
return null;
}
@Override
public String[] getParameterValues(String name) {
// TODO Auto-generated method stub
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "getParameterValues({0})", name);
}
return null;
}
@Override
public String getProtocol() {
LOG.log(Level.FINE, "getProtocol");
return webSocketHolder.getProtocol();
}
@Override
public BufferedReader getReader() throws IOException {
LOG.log(Level.FINE, "getReader");
return new BufferedReader(new InputStreamReader(in, "utf-8"));
}
@Override
public String getRealPath(String path) {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "getRealPath");
return null;
}
@Override
public String getRemoteAddr() {
LOG.log(Level.FINE, "getRemoteAddr");
return webSocketHolder.getRemoteAddr();
}
@Override
public String getRemoteHost() {
LOG.log(Level.FINE, "getRemoteHost");
return webSocketHolder.getRemoteHost();
}
@Override
public int getRemotePort() {
LOG.log(Level.FINE, "getRemotePort");
return webSocketHolder.getRemotePort();
}
@Override
public RequestDispatcher getRequestDispatcher(String path) {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "getRequestDispatcher");
return null;
}
@Override
public String getScheme() {
LOG.log(Level.FINE, "getScheme");
return webSocketHolder.getScheme();
}
@Override
public String getServerName() {
return webSocketHolder.getServerName();
}
@Override
public int getServerPort() {
LOG.log(Level.FINE, "getServerPort");
return webSocketHolder.getServerPort();
}
@Override
public ServletContext getServletContext() {
LOG.log(Level.FINE, "getServletContext");
return webSocketHolder.getServletContext();
}
@Override
public boolean isAsyncStarted() {
LOG.log(Level.FINE, "isAsyncStarted");
return false;
}
@Override
public boolean isAsyncSupported() {
LOG.log(Level.FINE, "isAsyncSupported");
return false;
}
@Override
public boolean isSecure() {
LOG.log(Level.FINE, "isSecure");
return webSocketHolder.isSecure();
}
@Override
public void removeAttribute(String name) {
LOG.log(Level.FINE, "removeAttribute");
attributes.remove(name);
}
@Override
public void setAttribute(String name, Object o) {
LOG.log(Level.FINE, "setAttribute");
attributes.put(name, o);
}
@Override
public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
LOG.log(Level.FINE, "setCharacterEncoding");
// ignore as we stick to utf-8.
}
@Override
public AsyncContext startAsync() {
LOG.log(Level.FINE, "startAsync");
return null;
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "startAsync");
return null;
}
@Override
public boolean authenticate(HttpServletResponse servletResponse) throws IOException, ServletException {
// TODO Auto-generated method stub
LOG.log(Level.FINE, "authenticate");
return false;
}
@Override
public String getAuthType() {
LOG.log(Level.FINE, "getAuthType");
return webSocketHolder.getAuthType();
}
@Override
public String getContextPath() {
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "getContextPath -> " + webSocketHolder.getContextPath());
}
return webSocketHolder.getContextPath();
}
@Override
public Cookie[] getCookies() {
LOG.log(Level.FINE, "getCookies");
return null;
}
@Override
public long getDateHeader(String name) {
LOG.log(Level.FINE, "getDateHeader");
return 0;
}
@Override
public String getHeader(String name) {
LOG.log(Level.FINE, "getHeader");
return requestHeaders.get(name);
}
@Override
public Enumeration<String> getHeaderNames() {
LOG.log(Level.FINE, "getHeaderNames");
return Collections.enumeration(requestHeaders.keySet());
}
@Override
public Enumeration<String> getHeaders(String name) {
LOG.log(Level.FINE, "getHeaders");
// our protocol assumes no multiple headers
return Collections.enumeration(Arrays.asList(requestHeaders.get(name)));
}
@Override
public int getIntHeader(String name) {
LOG.log(Level.FINE, "getIntHeader");
String v = requestHeaders.get(name);
return v == null ? -1 : Integer.parseInt(v);
}
@Override
public String getMethod() {
LOG.log(Level.FINE, "getMethod");
return requestHeaders.get(WebSocketUtils.METHOD_KEY);
}
@Override
public Part getPart(String name) throws IOException, ServletException {
LOG.log(Level.FINE, "getPart");
return null;
}
@Override
public Collection<Part> getParts() throws IOException, ServletException {
LOG.log(Level.FINE, "getParts");
return null;
}
@Override
public String getPathInfo() {
String uri = requestHeaders.get(WebSocketUtils.URI_KEY);
String servletpath = webSocketHolder.getServletPath();
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "getPathInfo " + servletpath + " " + uri);
}
//TODO remove the query string part
//REVISIT may cache this value in requstHeaders?
return uri.substring(servletpath.length());
}
@Override
public String getPathTranslated() {
String path = getPathInfo();
String opathtrans = webSocketHolder.getPathTranslated();
// some container may choose not to return this value
if (opathtrans == null) {
return null;
}
String opathinfo = webSocketHolder.getPathInfo();
LOG.log(Level.FINE, "getPathTranslated " + path + " " + opathinfo);
int pos = opathtrans.indexOf(opathinfo);
//REVISIT may cache this value in requstHeaders?
return new StringBuilder().append(opathtrans.substring(0, pos)).append(path).toString();
}
@Override
public String getQueryString() {
LOG.log(Level.FINE, "getQueryString");
return null;
}
@Override
public String getRemoteUser() {
LOG.log(Level.FINE, "getRemoteUser");
return null;
}
@Override
public String getRequestURI() {
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "getRequestURI " + requestHeaders.get(WebSocketUtils.URI_KEY));
}
return requestHeaders.get(WebSocketUtils.URI_KEY);
}
@Override
public StringBuffer getRequestURL() {
StringBuffer sb = webSocketHolder.getRequestURL();
String ouri = webSocketHolder.getRequestURI();
String uri = getRequestURI();
sb.append(uri.substring(ouri.length()));
LOG.log(Level.FINE, "getRequestURL " + uri);
return sb;
}
@Override
public String getRequestedSessionId() {
LOG.log(Level.FINE, "getRequestedSessionId");
return null;
}
@Override
public String getServletPath() {
LOG.log(Level.FINE, "getServletPath " + webSocketHolder.getServletPath());
return webSocketHolder.getServletPath();
}
@Override
public HttpSession getSession() {
LOG.log(Level.FINE, "getSession");
return null;
}
@Override
public HttpSession getSession(boolean create) {
LOG.log(Level.FINE, "getSession");
return null;
}
@Override
public Principal getUserPrincipal() {
LOG.log(Level.FINE, "getUserPrincipal");
return webSocketHolder.getUserPrincipal();
}
@Override
public boolean isRequestedSessionIdFromCookie() {
LOG.log(Level.FINE, "isRequestedSessionIdFromCookie");
return false;
}
@Override
public boolean isRequestedSessionIdFromURL() {
LOG.log(Level.FINE, "isRequestedSessionIdFromURL");
return false;
}
@Override
public boolean isRequestedSessionIdFromUrl() {
LOG.log(Level.FINE, "isRequestedSessionIdFromUrl");
return false;
}
@Override
public boolean isRequestedSessionIdValid() {
LOG.log(Level.FINE, "isRequestedSessionIdValid");
return false;
}
@Override
public boolean isUserInRole(String role) {
LOG.log(Level.FINE, "isUserInRole");
return false;
}
@Override
public void login(String username, String password) throws ServletException {
LOG.log(Level.FINE, "login");
}
@Override
public void logout() throws ServletException {
LOG.log(Level.FINE, "logout");
}
@Override
public long getContentLengthLong() {
throw new UnsupportedOperationException();
}
@Override
public String changeSessionId() {
throw new UnsupportedOperationException();
}
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> arg0) throws IOException, ServletException {
throw new UnsupportedOperationException();
}
}