1 /*
2  * Copyright 2008-2019 by Emeric Vernat
3  *
4  *     This file is part of Java Melody.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package net.bull.javamelody.internal.web;
19
20 import java.io.IOException;
21 import java.io.OutputStreamWriter;
22 import java.io.PrintWriter;
23
24 import javax.servlet.ServletOutputStream;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.servlet.http.HttpServletResponseWrapper;
27
28 /**
29  * Implémentation de {@link HttpServletResponseWrapper} permettant d'encapsuler l'outputStream,
30  * par exemple pour calculer la taille du flux ou pour le compresser.
31  * @author Emeric Vernat
32  */

33 abstract class FilterServletResponseWrapper extends HttpServletResponseWrapper {
34     private ServletOutputStream stream;
35     private PrintWriter writer;
36     private int status = HttpServletResponse.SC_OK;
37
38     /**
39      * Constructeur.
40      * @param response HttpServletResponse
41      */

42     FilterServletResponseWrapper(HttpServletResponse response) {
43         super(response);
44         assert response != null;
45     }
46
47     HttpServletResponse getHttpServletResponse() {
48         return (HttpServletResponse) getResponse();
49     }
50
51     /**
52      * @return ServletOutputStream
53      */

54     ServletOutputStream getStream() {
55         return stream;
56     }
57
58     /** {@inheritDoc} */
59     @Override
60     public void reset() {
61         super.reset();
62         status = 0;
63         stream = null;
64         writer = null;
65     }
66
67     /**
68      * Retourne le status définit par setStatus ou sendError.
69      * @return int
70      */

71     public int getCurrentStatus() {
72         // cette méthode s'appele getCurrentStatus pour ne pas interférer avec getStatus
73         // dans servlet api 3.0, tout en restant compatible avec servlet api 2.5
74         return status;
75     }
76
77     /** {@inheritDoc} */
78     @Override
79     public void setStatus(int status) {
80         super.setStatus(status);
81         this.status = status;
82     }
83
84     /** {@inheritDoc} */
85     @Override
86     public void sendError(int error) throws IOException {
87         super.sendError(error);
88         this.status = error;
89     }
90
91     /** {@inheritDoc} */
92     @Override
93     public void sendError(int error, String message) throws IOException {
94         super.sendError(error, message);
95         this.status = error;
96     }
97
98     /**
99      * Crée et retourne un ServletOutputStream pour écrire le contenu dans la response associée.
100      * @return ServletOutputStream
101      * @throws IOException   Erreur d'entrée/sortie
102      */

103     protected abstract ServletOutputStream createOutputStream() throws IOException;
104
105     /** {@inheritDoc} */
106     @Override
107     public ServletOutputStream getOutputStream() throws IOException {
108         if (writer != null) {
109             throw new IllegalStateException(
110                     "getWriter() has already been called for this response");
111         }
112
113         if (stream == null) {
114             stream = createOutputStream();
115             assert stream != null;
116         }
117         return stream;
118     }
119
120     /** {@inheritDoc} */
121     @Override
122     public PrintWriter getWriter() throws IOException {
123         if (writer == null) {
124             if (stream != null) {
125                 throw new IllegalStateException(
126                         "getOutputStream() has already been called for this response");
127             }
128
129             try {
130                 getOutputStream();
131             } catch (final IllegalStateException e) {
132                 // issue 488: if a filter has called getWriter() before the MonitoringFilter, we can't call getOutputStream()
133                 writer = super.getWriter();
134                 return writer;
135             }
136
137             final ServletOutputStream outputStream = getOutputStream();
138             final String charEnc = getHttpServletResponse().getCharacterEncoding();
139             // HttpServletResponse.getCharacterEncoding() shouldn't return null
140             // according the spec, so feel free to remove that "if"
141             final PrintWriter result;
142             if (charEnc == null) {
143                 result = new PrintWriter(outputStream);
144             } else {
145                 result = new PrintWriter(new OutputStreamWriter(outputStream, charEnc));
146             }
147             writer = result;
148         }
149         return writer;
150     }
151
152     /** {@inheritDoc} */
153     @Override
154     public void flushBuffer() throws IOException {
155         if (writer != null) {
156             writer.flush();
157         } else if (stream != null) {
158             stream.flush();
159         } else {
160             // writes status code and headers when no content (issue #836)
161             super.flushBuffer();
162         }
163     }
164
165     public void flushStream() throws IOException {
166         if (writer != null) {
167             writer.flush();
168         } else if (stream != null) {
169             stream.flush();
170         }
171     }
172
173     /**
174      * Ferme le flux.
175      * @throws IOException e
176      */

177     public void close() throws IOException {
178         if (writer != null) {
179             writer.close();
180         } else if (stream != null) {
181             stream.close();
182         }
183     }
184 }
185