View Javadoc
1   /*
2    * MIT License
3    *
4    * Copyright (c) 2010-2024 The Waffle Project Contributors: https://github.com/Waffle/waffle/graphs/contributors
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy
7    * of this software and associated documentation files (the "Software"), to deal
8    * in the Software without restriction, including without limitation the rights
9    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   * copies of the Software, and to permit persons to whom the Software is
11   * furnished to do so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  package waffle.mock.http;
25  
26  import java.io.ByteArrayOutputStream;
27  import java.io.IOException;
28  import java.io.OutputStreamWriter;
29  import java.io.PrintWriter;
30  import java.nio.charset.StandardCharsets;
31  import java.util.ArrayList;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  import javax.servlet.ServletOutputStream;
37  import javax.servlet.WriteListener;
38  import javax.servlet.http.HttpServletResponse;
39  import javax.servlet.http.HttpServletResponseWrapper;
40  
41  import org.mockito.Mockito;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  /**
46   * The Class SimpleHttpResponse.
47   */
48  public class SimpleHttpResponse extends HttpServletResponseWrapper {
49  
50      /** The Constant LOGGER. */
51      private static final Logger LOGGER = LoggerFactory.getLogger(SimpleHttpResponse.class);
52  
53      /** The status. */
54      private int status = 500;
55  
56      /** The headers. */
57      private final Map<String, List<String>> headers = new HashMap<>();
58  
59      /** The bytes. */
60      final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
61  
62      /** The out. */
63      private final ServletOutputStream out = new ServletOutputStream() {
64          @Override
65          public void write(final int b) throws IOException {
66              SimpleHttpResponse.this.bytes.write(b);
67          }
68  
69          @Override
70          public boolean isReady() {
71              return false;
72          }
73  
74          @Override
75          public void setWriteListener(final WriteListener writeListener) {
76              // Not used
77          }
78      };
79  
80      /** The writer. */
81      private final PrintWriter writer = new PrintWriter(new OutputStreamWriter(this.bytes, StandardCharsets.UTF_8),
82              true);
83  
84      /**
85       * Instantiates a new simple http response.
86       */
87      public SimpleHttpResponse() {
88          super(Mockito.mock(HttpServletResponse.class));
89      }
90  
91      /**
92       * Gets the status.
93       *
94       * @return the status
95       */
96      @Override
97      public int getStatus() {
98          return this.status;
99      }
100 
101     @Override
102     public void addHeader(final String headerName, final String headerValue) {
103         List<String> current = this.headers.get(headerName);
104         if (current == null) {
105             current = new ArrayList<>();
106         }
107         current.add(headerValue);
108         this.headers.put(headerName, current);
109     }
110 
111     @Override
112     public void setHeader(final String headerName, final String headerValue) {
113         List<String> current = this.headers.get(headerName);
114         if (current == null) {
115             current = new ArrayList<>();
116         } else {
117             current.clear();
118         }
119         current.add(headerValue);
120         this.headers.put(headerName, current);
121     }
122 
123     @Override
124     public void setStatus(final int value) {
125         this.status = value;
126     }
127 
128     /**
129      * Gets the status string.
130      *
131      * @return the status string
132      */
133     public String getStatusString() {
134         if (this.status == 401) {
135             return "Unauthorized";
136         }
137         return "Unknown";
138     }
139 
140     @Override
141     public void flushBuffer() {
142         SimpleHttpResponse.LOGGER.info("{}: {}", Integer.valueOf(this.status), this.getStatusString());
143         for (final Map.Entry<String, List<String>> header : this.headers.entrySet()) {
144             for (final String headerValue : header.getValue()) {
145                 SimpleHttpResponse.LOGGER.info("{}: {}", header, headerValue);
146             }
147         }
148     }
149 
150     /**
151      * Use this for testing the number of headers.
152      *
153      * @return int header name size.
154      */
155     public int getHeaderNamesSize() {
156         return this.headers.size();
157     }
158 
159     /**
160      * Gets the header values.
161      *
162      * @param headerName
163      *            the header name
164      *
165      * @return the header values
166      */
167     public String[] getHeaderValues(final String headerName) {
168         final List<String> headerValues = this.headers.get(headerName);
169         return headerValues == null ? null : headerValues.toArray(new String[0]);
170     }
171 
172     /**
173      * Gets the header.
174      *
175      * @param headerName
176      *            the header name
177      *
178      * @return the header
179      */
180     @Override
181     public String getHeader(final String headerName) {
182         final List<String> headerValues = this.headers.get(headerName);
183         return headerValues == null ? null : String.join(", ", headerValues);
184     }
185 
186     @Override
187     public void sendError(final int rc, final String message) {
188         this.status = rc;
189     }
190 
191     @Override
192     public void sendError(final int rc) {
193         this.status = rc;
194     }
195 
196     @Override
197     public PrintWriter getWriter() {
198         return this.writer;
199     }
200 
201     @Override
202     public ServletOutputStream getOutputStream() throws IOException {
203         return this.out;
204     }
205 
206     /**
207      * Gets the output text.
208      *
209      * @return the output text
210      */
211     public String getOutputText() {
212         this.writer.flush();
213         return this.bytes.toString(StandardCharsets.UTF_8);
214     }
215 }