/** * 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.jooby.servlet; import static java.util.Objects.requireNonNull; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.Executor; import java.util.function.Function; import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.jooby.Cookie; import org.jooby.MediaType; import org.jooby.spi.NativeRequest; import org.jooby.spi.NativeUpload; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; public class ServletServletRequest implements NativeRequest { private HttpServletRequest req; private String tmpdir; private boolean multipart; private String path; private ServletUpgrade upgrade = noupgrade(); public ServletServletRequest(final HttpServletRequest req, final String tmpdir, final boolean multipart) throws IOException { this.req = requireNonNull(req, "HTTP req is required."); this.tmpdir = requireNonNull(tmpdir, "A tmpdir is required."); this.multipart = multipart; String pathInfo = req.getPathInfo(); if (pathInfo == null) { pathInfo = "/"; } this.path = req.getContextPath() + URLDecoder.decode(pathInfo, "UTF-8"); } public HttpServletRequest servletRequest() { return req; } public ServletServletRequest(final HttpServletRequest req, final String tmpdir) throws IOException { this(req, tmpdir, multipart(req)); } public ServletServletRequest with(final ServletUpgrade upgrade) { this.upgrade = requireNonNull(upgrade, "An upgrade provider is required."); return this; } @Override public String method() { return req.getMethod(); } @Override public Optional<String> queryString() { return Optional.ofNullable(Strings.emptyToNull(req.getQueryString())); } @Override public String path() { return path; } @Override public String rawPath() { return req.getRequestURI(); } @Override public List<String> paramNames() { return toList(req.getParameterNames()); } private <T> List<T> toList(final Enumeration<T> enumeration) { Builder<T> result = ImmutableList.builder(); while (enumeration.hasMoreElements()) { result.add(enumeration.nextElement()); } return result.build(); } @Override public List<String> params(final String name) throws Exception { String[] values = req.getParameterValues(name); if (values == null) { return Collections.emptyList(); } return Arrays.asList(values); } @Override public Map<String, Object> attributes() { final Enumeration<String> attributeNames = req.getAttributeNames(); if (!attributeNames.hasMoreElements()) { return Collections.emptyMap(); } return Collections.list(attributeNames).stream() .collect(Collectors.toMap(Function.identity(), req::getAttribute)); } @Override public List<String> headers(final String name) { return toList(req.getHeaders(name)); } @Override public Optional<String> header(final String name) { return Optional.ofNullable(req.getHeader(name)); } @Override public List<String> headerNames() { return toList(req.getHeaderNames()); } @Override public List<Cookie> cookies() { javax.servlet.http.Cookie[] cookies = req.getCookies(); if (cookies == null) { return ImmutableList.of(); } return Arrays.stream(cookies) .map(c -> { Cookie.Definition cookie = new Cookie.Definition(c.getName(), c.getValue()); Optional.ofNullable(c.getComment()).ifPresent(cookie::comment); Optional.ofNullable(c.getDomain()).ifPresent(cookie::domain); Optional.ofNullable(c.getPath()).ifPresent(cookie::path); return cookie.toCookie(); }) .collect(Collectors.toList()); } @Override public List<NativeUpload> files(final String name) throws IOException { try { if (multipart) { return req.getParts().stream() .filter(part -> part.getSubmittedFileName() != null && part.getName().equals(name)) .map(part -> new ServletUpload(part, tmpdir)) .collect(Collectors.toList()); } return Collections.emptyList(); } catch (ServletException ex) { throw new IOException("File not found: " + name, ex); } } @Override public InputStream in() throws IOException { return req.getInputStream(); } @Override public String ip() { return req.getRemoteAddr(); } @Override public String protocol() { return req.getProtocol(); } @Override public boolean secure() { return req.isSecure(); } @Override public <T> T upgrade(final Class<T> type) throws Exception { return upgrade.upgrade(type); } @Override public void startAsync(final Executor executor, final Runnable runnable) { req.startAsync(); executor.execute(runnable); } private static boolean multipart(final HttpServletRequest req) { String contentType = req.getContentType(); return contentType != null && contentType.toLowerCase().startsWith(MediaType.multipart.name()); } private static ServletUpgrade noupgrade() { return new ServletUpgrade() { @Override public <T> T upgrade(final Class<T> type) throws Exception { throw new UnsupportedOperationException(""); } }; } }