001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.jcs3.jcache.extras.web;
020
021import java.io.IOException;
022import java.io.OutputStream;
023import java.io.OutputStreamWriter;
024import java.io.PrintWriter;
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.LinkedList;
029import java.util.List;
030import java.util.Map;
031import java.util.TreeMap;
032import java.util.concurrent.CopyOnWriteArraySet;
033import javax.servlet.ServletOutputStream;
034import javax.servlet.http.Cookie;
035import javax.servlet.http.HttpServletResponse;
036import javax.servlet.http.HttpServletResponseWrapper;
037
038public class InMemoryResponse extends HttpServletResponseWrapper implements Serializable
039{
040    private final OutputStream buffer;
041
042    private final Collection<Cookie> cookies = new CopyOnWriteArraySet<>();
043    private final Map<String, List<Serializable>> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
044    private int status = SC_OK;
045    private String contentType;
046    private PrintWriter writer;
047    private int contentLength;
048
049    public InMemoryResponse(final HttpServletResponse response, final OutputStream baos)
050    {
051        super(response);
052        this.buffer = baos;
053    }
054
055    private List<Serializable> ensureHeaderExists(final String s)
056    {
057        return headers.computeIfAbsent(s, k -> new LinkedList<>());
058    }
059
060    @Override
061    public void addCookie(final Cookie cookie)
062    {
063        super.addCookie(cookie);
064        cookies.add(cookie);
065    }
066
067    @Override
068    public void addDateHeader(final String s, final long l)
069    {
070        super.addDateHeader(s, l);
071        ensureHeaderExists(s).add(l);
072    }
073
074    @Override
075    public void addHeader(final String s, final String s2)
076    {
077        super.addHeader(s, s2);
078        ensureHeaderExists(s).add(s2);
079    }
080
081    @Override
082    public void addIntHeader(final String s, final int i)
083    {
084        super.addIntHeader(s, i);
085        ensureHeaderExists(s).add(i);
086    }
087
088    @Override
089    public boolean containsHeader(final String s)
090    {
091        return headers.containsKey(s);
092    }
093
094    @Override
095    public String getHeader(final String s)
096    {
097        final List<Serializable> serializables = headers.get(s);
098        if (serializables.isEmpty())
099        {
100            return null;
101        }
102        return serializables.iterator().next().toString();
103    }
104
105    @Override
106    public Collection<String> getHeaderNames()
107    {
108        return headers.keySet();
109    }
110
111    @Override
112    public Collection<String> getHeaders(final String s)
113    {
114        final List<Serializable> serializables = headers.get(s);
115        final Collection<String> strings = new ArrayList<>(serializables.size());
116        for (final Serializable ser : serializables)
117        {
118            strings.add(ser.toString());
119        }
120        return strings;
121    }
122
123    @Override
124    public int getStatus()
125    {
126        return status;
127    }
128
129    @Override
130    public void sendError(final int i) throws IOException
131    {
132        status = i;
133        super.sendError(i);
134    }
135
136    @Override
137    public void sendError(final int i, final String s) throws IOException
138    {
139        status = i;
140        super.sendError(i, s);
141    }
142
143    @Override
144    public void sendRedirect(final String s) throws IOException
145    {
146        status = SC_MOVED_TEMPORARILY;
147        super.sendRedirect(s);
148    }
149
150    @Override
151    public void setDateHeader(final String s, final long l)
152    {
153        super.setDateHeader(s, l);
154        final List<Serializable> serializables = ensureHeaderExists(s);
155        serializables.clear();
156        serializables.add(l);
157    }
158
159    @Override
160    public void setHeader(final String s, final String s2)
161    {
162        super.setHeader(s, s2);
163        final List<Serializable> serializables = ensureHeaderExists(s);
164        serializables.clear();
165        serializables.add(s2);
166    }
167
168    @Override
169    public void setIntHeader(final String s, final int i)
170    {
171        super.setIntHeader(s, i);
172        final List<Serializable> serializables = ensureHeaderExists(s);
173        serializables.clear();
174        serializables.add(i);
175    }
176
177    @Override
178    public void setStatus(final int i)
179    {
180        status = i;
181        super.setStatus(i);
182    }
183
184    @Override
185    public void setStatus(final int i, final String s)
186    {
187        status = i;
188        super.setStatus(i, s);
189    }
190
191    @Override
192    public String getContentType()
193    {
194        return contentType;
195    }
196
197    @Override
198    public ServletOutputStream getOutputStream() throws IOException
199    {
200        return new ServletOutputStream()
201        {
202            @Override
203            public void write(final int b) throws IOException
204            {
205                buffer.write(b);
206            }
207        };
208    }
209
210    @Override
211    public PrintWriter getWriter() throws IOException
212    {
213        if (writer == null) {
214            writer = new PrintWriter(new OutputStreamWriter(buffer, getCharacterEncoding()), true);
215        }
216        return writer;
217    }
218
219    @Override
220    public void reset()
221    {
222        super.reset();
223        status = SC_OK;
224        headers.clear();
225        cookies.clear();
226        contentType = null;
227        contentLength = 0;
228    }
229
230    @Override
231    public void setContentLength(final int i)
232    {
233        super.setContentLength(i);
234        contentLength = i;
235    }
236
237    @Override
238    public void setContentType(final String s)
239    {
240        contentType = s;
241        super.setContentType(s);
242    }
243
244    @Override
245    public void flushBuffer() throws IOException
246    {
247        if (writer != null)
248        {
249            writer.flush();
250        }
251        else
252        {
253            buffer.flush();
254        }
255    }
256
257    public int getContentLength()
258    {
259        return contentLength;
260    }
261
262    public Collection<Cookie> getCookies()
263    {
264        return cookies;
265    }
266
267    public Map<String, List<Serializable>> getHeaders()
268    {
269        return headers;
270    }
271}