/* * COMSAT * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.comsat.webactors.servlet; import co.paralleluniverse.actors.ActorRef; import co.paralleluniverse.comsat.webactors.Cookie; import static co.paralleluniverse.comsat.webactors.Cookie.*; import co.paralleluniverse.comsat.webactors.HttpRequest; import co.paralleluniverse.comsat.webactors.HttpResponse; import co.paralleluniverse.comsat.webactors.WebMessage; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.io.ByteStreams; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.util.Collection; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Wraps a {@link HttpServletRequest} as a {@link HttpRequest} */ public final class ServletHttpRequest extends HttpRequest { final HttpServletRequest request; final HttpServletResponse response; private ListMultimap<String, String> headers; private Multimap<String, String> params; private Map<String, Object> attrs; private final ActorRef<? super HttpResponse> sender; private String strBody; private byte[] binBody; private Collection<Cookie> cookies; /** * Constructs a {@code HttpRequestWrapper} message * * @param sender this message's sender * @param request the {@link HttpServletRequest} * @param response the {@link HttpServletResponse} */ public ServletHttpRequest(ActorRef<? super HttpResponse> sender, HttpServletRequest request, HttpServletResponse response) { this.sender = sender; this.request = request; this.response = response; } public HttpServletRequest getServletRequest() { return request; } public HttpServletResponse getServletResponse() { return response; } @Override public final String getSourceHost() { return request.getRemoteHost(); } @Override public final int getSourcePort() { return request.getRemotePort(); } // @Override // public String getRequestURL() { // return request.getRequestURL().toString(); // } @Override public final String getStringBody() { if (strBody == null) { if (binBody != null) return null; final byte[] ba = readBody(); final String enc = request.getCharacterEncoding(); try { this.strBody = enc!=null ? new String(ba, enc) : new String(ba); } catch (final UnsupportedEncodingException e) { throw new UnsupportedCharsetException(enc); } } return strBody; } @Override public final ByteBuffer getByteBufferBody() { if (binBody == null) { if (strBody != null) return null; this.binBody = readBody(); } return ByteBuffer.wrap(binBody).asReadOnlyBuffer(); } private byte[] readBody() { try { final ServletInputStream is = request.getInputStream(); final int length = request.getContentLength(); final byte[] ba; if (length < 0) ba = ByteStreams.toByteArray(is); else { ba = new byte[length]; ByteStreams.readFully(is, ba); } return ba; } catch (final IOException ex) { throw new RuntimeException(ex); } } @Override public final ListMultimap<String, String> getHeaders() { if (headers == null) { final ImmutableListMultimap.Builder<String, String> mm = ImmutableListMultimap.builder();// LinkedHashMultimap.create(); for (final Enumeration<String> hs = request.getHeaderNames(); hs.hasMoreElements();) { final String h = hs.nextElement(); for (final Enumeration<String> hv = request.getHeaders(h); hv.hasMoreElements();) // Normalize header names by their conversion to lower case mm.put(h.toLowerCase(Locale.ENGLISH), hv.nextElement()); } this.headers = mm.build(); } return headers; } @Override public final Multimap<String, String> getParameters() { if (params == null) { final ImmutableListMultimap.Builder<String, String> mm = ImmutableListMultimap.builder(); for (final Enumeration<String> ps = request.getParameterNames(); ps.hasMoreElements();) { final String p = ps.nextElement(); final String[] pvs = request.getParameterValues(p); if (pvs != null) { for (final String pv : pvs) mm.put(p, pv); } } this.params = mm.build(); } return params; } @Override public final Map<String, Object> getAttributes() { if (attrs == null) { final ImmutableMap.Builder<String, Object> m = ImmutableMap.builder(); for (final Enumeration<String> as = request.getAttributeNames(); as.hasMoreElements();) { final String a = as.nextElement(); final Object v = request.getAttribute(a); m.put(a, v); } this.attrs = m.build(); } return attrs; } @Override public final Collection<Cookie> getCookies() { if (cookies == null) { final javax.servlet.http.Cookie[] cs = request.getCookies(); final ImmutableCollection.Builder<Cookie> collb = ImmutableList.builder(); if (cs != null) { for (final javax.servlet.http.Cookie c : cs) { collb.add(cookie(c.getName(), c.getValue()) .setComment(c.getComment()) .setDomain(c.getDomain()) .setMaxAge(c.getMaxAge()) .setHttpOnly(c.isHttpOnly()) .setPath(c.getPath()) .setSecure(c.getSecure()) .setVersion(c.getVersion()) .build()); } } this.cookies = collb.build(); } return cookies; } @Override public final long getDateHeader(String name) { return request.getDateHeader(name); } @Override public final String getMethod() { return request.getMethod(); } @Override public final String getScheme() { return request.getScheme(); } @Override public final String getQueryString() { return request.getQueryString(); } @Override public final String getServerName() { return request.getServerName(); } @Override public final int getServerPort() { return request.getServerPort(); } @Override public final String getContextPath() { return request.getContextPath(); } @Override public final String getRequestURI() { return request.getRequestURI(); } @Override public final int getContentLength() { return request.getContentLength(); } @Override public final String getContentType() { return request.getContentType(); } @Override public final String getPathInfo() { return request.getPathInfo(); } @Override public final Charset getCharacterEncoding() { return request.getCharacterEncoding() != null ? Charset.forName(request.getCharacterEncoding()) : null; } @Override public final ActorRef<WebMessage> getFrom() { //noinspection unchecked return (ActorRef<WebMessage>) sender; } }