View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2015 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.caravan.io.http.impl.servletclient;
21  
22  import java.io.BufferedReader;
23  import java.io.ByteArrayInputStream;
24  import java.io.IOException;
25  import java.io.InputStreamReader;
26  import java.io.UnsupportedEncodingException;
27  import java.net.URI;
28  import java.net.URISyntaxException;
29  import java.net.URLDecoder;
30  import java.security.Principal;
31  import java.util.Collection;
32  import java.util.Collections;
33  import java.util.Enumeration;
34  import java.util.List;
35  import java.util.Locale;
36  import java.util.Map;
37  
38  import javax.servlet.AsyncContext;
39  import javax.servlet.DispatcherType;
40  import javax.servlet.RequestDispatcher;
41  import javax.servlet.ServletContext;
42  import javax.servlet.ServletException;
43  import javax.servlet.ServletInputStream;
44  import javax.servlet.ServletRequest;
45  import javax.servlet.ServletResponse;
46  import javax.servlet.http.Cookie;
47  import javax.servlet.http.HttpServletRequest;
48  import javax.servlet.http.HttpServletResponse;
49  import javax.servlet.http.HttpSession;
50  import javax.servlet.http.Part;
51  
52  import org.apache.commons.lang3.ArrayUtils;
53  import org.apache.http.NameValuePair;
54  import org.apache.http.client.utils.URLEncodedUtils;
55  import org.slf4j.Logger;
56  import org.slf4j.LoggerFactory;
57  
58  import com.google.common.base.Charsets;
59  import com.google.common.collect.ImmutableMap;
60  import com.google.common.collect.ImmutableMap.Builder;
61  import com.google.common.collect.Maps;
62  
63  import io.wcm.caravan.io.http.request.CaravanHttpRequest;
64  import rx.Observable;
65  
66  /**
67   * Mapper from {@link CaravanHttpRequest} to {@link HttpServletRequest}.
68   */
69  public class HttpServletRequestMapper implements HttpServletRequest {
70  
71    private static final Logger LOG = LoggerFactory.getLogger(HttpServletRequestMapper.class);
72  
73    private final CaravanHttpRequest request;
74    private final URI uri;
75    private final String serviceId;
76    private final Map<String, Object> attributes = Maps.newHashMap();
77  
78    /**
79     * @param request Request
80     */
81    public HttpServletRequestMapper(CaravanHttpRequest request) throws NotSupportedByRequestMapperException {
82      this.request = request;
83      try {
84        uri = new URI(request.getUrl());
85        serviceId = URLDecoder.decode(request.getServiceId(), Charsets.UTF_8.toString());
86      }
87      catch (URISyntaxException | UnsupportedEncodingException ex) {
88        throw new NotSupportedByRequestMapperException();
89      }
90    }
91  
92    @Override
93    public Object getAttribute(String name) {
94      return attributes.get(name);
95    }
96  
97    @Override
98    public Enumeration<String> getAttributeNames() {
99      return Collections.enumeration(attributes.keySet());
100   }
101 
102   @Override
103   public String getCharacterEncoding() {
104     return request.getCharset().toString();
105   }
106 
107   @Override
108   public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
109     // do nothing
110   }
111 
112   @Override
113   public int getContentLength() {
114     return request.getBody().length;
115   }
116 
117   @Override
118   public String getContentType() {
119     return null;
120   }
121 
122   @Override
123   public ServletInputStream getInputStream() throws IOException {
124     return new ServletInputStream() {
125 
126       private int index;
127 
128       @Override
129       public int read() throws IOException {
130         return index < request.getBody().length ? -1 : request.getBody()[index++];
131       }
132 
133     };
134 
135   }
136 
137   @Override
138   public String getParameter(String name) {
139     String[] values = getParameterValues(name);
140     return ArrayUtils.isEmpty(values) ? null : values[0];
141   }
142 
143   @Override
144   public Enumeration<String> getParameterNames() {
145     return Collections.enumeration(getParameterMap().keySet());
146   }
147 
148   @Override
149   public String[] getParameterValues(String name) {
150     return getParameterMap().get(name);
151   }
152 
153   @Override
154   public Map<String, String[]> getParameterMap() {
155     try {
156       List<NameValuePair> pairs = URLEncodedUtils.parse(new URI(request.getUrl()), Charsets.UTF_8.toString());
157       Map<String, Collection<String>> multiMap = Observable.from(pairs).toMultimap(NameValuePair::getName, NameValuePair::getValue).toBlocking().single();
158       Builder<String, String[]> builder = ImmutableMap.builder();
159       multiMap.entrySet().stream().forEach(entry -> {
160         String[] arrayValue = entry.getValue().toArray(new String[entry.getValue().size()]);
161         builder.put(entry.getKey(), arrayValue);
162       });
163       return builder.build();
164     }
165     catch (URISyntaxException ex) {
166       LOG.debug("Error parsing {}", request.getUrl(), ex);
167     }
168     return null;
169   }
170 
171   @Override
172   public String getProtocol() {
173     return "HTTP/1.1";
174   }
175 
176   @Override
177   public String getScheme() {
178     return "http";
179   }
180 
181   @Override
182   public String getServerName() {
183     return "localhost";
184   }
185 
186   @Override
187   public int getServerPort() {
188     return 8080;
189   }
190 
191   @Override
192   public BufferedReader getReader() throws IOException {
193     return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(request.getBody())));
194   }
195 
196   @Override
197   public String getRemoteAddr() {
198     return "localhost";
199   }
200 
201   @Override
202   public String getRemoteHost() {
203     return "localhost";
204   }
205 
206   @Override
207   public void setAttribute(String name, Object o) {
208     attributes.put(name, o);
209   }
210 
211   @Override
212   public void removeAttribute(String name) {
213     attributes.remove(name);
214   }
215 
216   @Override
217   public Locale getLocale() {
218     return Locale.getDefault();
219   }
220 
221   @Override
222   public Enumeration<Locale> getLocales() {
223     return Collections.enumeration(Collections.singletonList(getLocale()));
224   }
225 
226   @Override
227   public boolean isSecure() {
228     return false;
229   }
230 
231   @Override
232   public RequestDispatcher getRequestDispatcher(String path) {
233     return getServletContext().getRequestDispatcher(path);
234   }
235 
236   @Override
237   public String getRealPath(String path) {
238     throw new NotSupportedByRequestMapperException();
239   }
240 
241   @Override
242   public int getRemotePort() {
243     return 0;
244   }
245 
246   @Override
247   public String getLocalName() {
248     return "localhost";
249   }
250 
251   @Override
252   public String getLocalAddr() {
253     return "localhost";
254   }
255 
256   @Override
257   public int getLocalPort() {
258     return 8080;
259   }
260 
261   @Override
262   public ServletContext getServletContext() {
263     throw new NotSupportedByRequestMapperException();
264   }
265 
266   @Override
267   public AsyncContext startAsync() {
268     return startAsync(this, null);
269   }
270 
271   @Override
272   public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
273     throw new NotSupportedByRequestMapperException();
274 
275   }
276 
277   @Override
278   public boolean isAsyncStarted() {
279     return false;
280   }
281 
282   @Override
283   public boolean isAsyncSupported() {
284     return false;
285   }
286 
287   @Override
288   public AsyncContext getAsyncContext() {
289     throw new NotSupportedByRequestMapperException();
290   }
291 
292   @Override
293   public DispatcherType getDispatcherType() {
294     return DispatcherType.REQUEST;
295   }
296 
297   @Override
298   public String getAuthType() {
299     return null;
300   }
301 
302   @Override
303   public Cookie[] getCookies() {
304     return new Cookie[0];
305   }
306 
307   @Override
308   public long getDateHeader(String name) {
309     String value = getHeader(name);
310     return value == null ? -1 : Long.parseLong(value);
311   }
312 
313   @Override
314   public String getHeader(String name) {
315     Collection<String> values = request.getHeaders().get(name);
316     return values.isEmpty() ? null : values.iterator().next();
317   }
318 
319   @Override
320   public Enumeration<String> getHeaders(String name) {
321     return Collections.enumeration(request.getHeaders().get(name));
322   }
323 
324   @Override
325   public Enumeration<String> getHeaderNames() {
326     return Collections.enumeration(request.getHeaders().keySet());
327   }
328 
329   @Override
330   public int getIntHeader(String name) {
331     String value = getHeader(name);
332     return value == null ? -1 : Integer.parseInt(value);
333   }
334 
335   @Override
336   public String getMethod() {
337     return request.getMethod();
338   }
339 
340   @Override
341   public String getPathInfo() {
342     return uri.getPath().substring(serviceId.length());
343   }
344 
345   @Override
346   public String getPathTranslated() {
347     return null;
348   }
349 
350   @Override
351   public String getContextPath() {
352     return "";
353   }
354 
355   @Override
356   public String getQueryString() {
357     return uri.getRawQuery();
358   }
359 
360   @Override
361   public String getRemoteUser() {
362     return null;
363   }
364 
365   @Override
366   public boolean isUserInRole(String role) {
367     return false;
368   }
369 
370   @Override
371   public Principal getUserPrincipal() {
372     return null;
373   }
374 
375   @Override
376   public String getRequestedSessionId() {
377     return null;
378   }
379 
380   @Override
381   public String getRequestURI() {
382     return uri.getRawPath();
383   }
384 
385   @Override
386   public StringBuffer getRequestURL() {
387     return new StringBuffer("http://localhost:8080").append(getRequestURI());
388   }
389 
390   @Override
391   public String getServletPath() {
392     return serviceId;
393   }
394 
395   @Override
396   public HttpSession getSession(boolean create) {
397     throw new NotSupportedByRequestMapperException();
398   }
399 
400   @Override
401   public HttpSession getSession() {
402     return getSession(true);
403   }
404 
405   @Override
406   public boolean isRequestedSessionIdValid() {
407     return true;
408   }
409 
410   @Override
411   public boolean isRequestedSessionIdFromCookie() {
412     return false;
413   }
414 
415   @Override
416   public boolean isRequestedSessionIdFromURL() {
417     return false;
418   }
419 
420   @Override
421   public boolean isRequestedSessionIdFromUrl() {
422     return false;
423   }
424 
425   @Override
426   public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
427     throw new NotSupportedByRequestMapperException();
428   }
429 
430   @Override
431   public void login(String username, String password) throws ServletException {
432     throw new NotSupportedByRequestMapperException();
433   }
434 
435   @Override
436   public void logout() throws ServletException {
437     // nothing to do
438   }
439 
440   @Override
441   public Collection<Part> getParts() throws IOException, ServletException {
442     return Collections.emptyList();
443   }
444 
445   @Override
446   public Part getPart(String name) throws IOException, ServletException {
447     return null;
448   }
449 
450 }