001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.net.http;
020
021import java.io.IOException;
022import java.io.OutputStream;
023import java.io.PrintWriter;
024import java.io.Serializable;
025import java.util.Locale;
026
027import javax.servlet.ServletOutputStream;
028import javax.servlet.http.Cookie;
029import javax.servlet.http.HttpServletResponse;
030import javax.servlet.http.HttpServletResponseWrapper;
031
032import lucee.commons.io.DevNullOutputStream;
033import lucee.commons.lang.Pair;
034import lucee.commons.net.URLEncoder;
035import lucee.runtime.op.Caster;
036import lucee.runtime.type.dt.DateTimeImpl;
037
038
039
040/**
041 * 
042 */
043public final class HttpServletResponseWrap extends HttpServletResponseWrapper implements HttpServletResponse,Serializable {
044        
045        private Cookie[] cookies=new Cookie[0];
046        private Pair[] headers=new Pair[0];
047        private int status=200;
048        private String statusCode="OK";
049        private String charset="ISO-8859-1";
050        private int contentLength=-1;
051        private String contentType=null;
052        private Locale locale=Locale.getDefault();
053        private int bufferSize=-1;
054        private boolean commited;
055        //private byte[] outputDatad;
056        private OutputStream out;//=new DevNullOutputStream();
057        private boolean outInit=false;
058        private PrintWriter writer;
059        private ServletOutputStreamDummy outputStream;
060        
061
062        private static ThreadLocal<Boolean> local=new ThreadLocal<Boolean>();
063
064
065        public static void set(boolean value) {
066                local.set(Caster.toBoolean(value));
067        }
068        public static boolean get() {
069                return Caster.toBooleanValue(local.get(),false);
070        }
071        public static void release() {
072                local.set(Boolean.FALSE);
073        }
074
075        /**
076         * Constructor of the class
077         */
078        public HttpServletResponseWrap(HttpServletResponse rsp) {
079                this(rsp,DevNullOutputStream.DEV_NULL_OUTPUT_STREAM);
080        }
081
082        public HttpServletResponseWrap(HttpServletResponse rsp,OutputStream out) {
083                super(rsp);
084                this.out=out;
085        }
086        
087        @Override
088        public void addCookie(Cookie cookie) {
089                Cookie[] tmp = new Cookie[cookies.length+1];
090                for(int i=0;i<cookies.length;i++) {
091                        tmp[i]=cookies[i];
092                }
093                tmp[cookies.length]=cookie;
094                cookies=tmp;
095        }
096        
097        @Override
098        public boolean containsHeader(String key) {
099                return ReqRspUtil.get(headers, key)!=null;
100        }
101        
102        @Override
103        public String encodeURL(String value) {
104                return URLEncoder.encode(value);
105        }
106        @Override
107        public String encodeRedirectURL(String url) {
108                return URLEncoder.encode(url);
109        }
110        @Override
111        public String encodeUrl(String value) {
112                return URLEncoder.encode(value);
113        }
114        @Override
115        public String encodeRedirectUrl(String value) {
116                return URLEncoder.encode(value);
117        }
118        
119        @Override
120        public void sendError(int code, String codeText) throws IOException {
121                // TODO impl
122        }
123        @Override
124        public void sendError(int code) throws IOException {
125                // TODO impl
126        }
127        
128        @Override
129        public void sendRedirect(String location) throws IOException {
130                addHeader("location",location);
131        }
132        @Override
133        public void setDateHeader(String key, long value) {
134                setHeader(key, new DateTimeImpl(value,false).castToString());
135        }
136        
137        @Override
138        public void addDateHeader(String key, long value) {
139                addHeader(key, new DateTimeImpl(value,false).castToString());
140        }
141        
142        @Override
143        public void setHeader(String key, String value) {
144                headers=ReqRspUtil.set(headers, key, value);
145        }
146        
147        @Override
148        public void addHeader(String key, String value) {
149                headers=ReqRspUtil.add(headers, key, value);
150        }
151        
152        @Override
153        public void setIntHeader(String key, int value) {
154                setHeader(key, String.valueOf(value));
155        }
156        
157        @Override
158        public void addIntHeader(String key, int value) {
159                addHeader(key, String.valueOf(value));
160        }
161        @Override
162        public void setStatus(int status) {
163                this.status=status; 
164        }
165        @Override
166        public void setStatus(int status, String statusCode) {
167                setStatus(status);
168                this.statusCode=statusCode;  
169        }
170        
171        @Override
172        public String getCharacterEncoding() {
173                return charset;
174        }
175        
176        public void setCharacterEncoding(String charset) {
177                this.charset = charset;
178        }
179        
180        @Override
181        public ServletOutputStream getOutputStream() throws IOException {
182                //if(writer!=null) throw new IOException("output already initallised as Writer");
183                if(outputStream!=null) return outputStream;
184                return outputStream=new ServletOutputStreamDummy(out);
185        }
186        
187        public ServletOutputStream getExistingOutputStream()  {
188                return outputStream;
189        }
190        
191        @Override
192        public PrintWriter getWriter() throws IOException {
193                //if(outputStream!=null) throw new IOException("output already initallised as OutputStream");
194                if(writer!=null) return writer;
195                return writer= new PrintWriter(getOutputStream());
196                
197        }
198        
199        public PrintWriter getExistingWriter() {
200                return writer;
201        }
202        
203        
204        
205        
206        @Override
207        public void setContentLength(int contentLength) {
208                this.contentLength=contentLength;
209        }
210        @Override
211        public void setContentType(String contentType) {
212                this.contentType=contentType;
213        }
214        @Override
215        public void setBufferSize(int size) {
216                this.bufferSize=size;
217        }
218        @Override
219        public int getBufferSize() {
220                return bufferSize;
221        }
222        @Override
223        public void flushBuffer() throws IOException {
224                if(writer!=null)writer.flush();
225                else if(outputStream!=null)outputStream.flush();
226                commited = true;
227        }
228        @Override
229        public void resetBuffer() {
230                commited = true;
231        }
232        @Override
233        public boolean isCommitted() {
234                return commited;
235        }
236        @Override
237        public void reset() {
238                commited = true;
239        }
240        @Override
241        public void setLocale(Locale locale) {
242                this.locale=locale;
243        }
244        @Override
245        public Locale getLocale() {
246                return locale;
247        }
248
249        /**
250         * @return the charset
251         */
252        public String getCharsetEncoding() {
253                return charset;
254        }
255
256        /**
257         * @return the commited
258         */
259        public boolean isCommited() {
260                return commited;
261        }
262
263        /**
264         * @return the contentLength
265         */
266        public int getContentLength() {
267                return contentLength;
268        }
269
270        /**
271         * @return the contentType
272         */
273        public String getContentType() {
274                return contentType;
275        }
276
277        /**
278         * @return the cookies
279         */
280        public Cookie[] getCookies() {
281                return cookies;
282        }
283
284        /**
285         * @return the headers
286         */
287        public Pair[] getHeaders() {
288                return headers;
289        }
290
291        /* *
292         * @return the outputData
293         * /
294        public byte[] getOutputData() {
295                return outputData;
296        }
297
298        public void setOutputData(byte[] outputData) {
299                this.outputData=outputData;
300        }*/
301
302        /**
303         * @return the status
304         */
305        public int getStatus() {
306                return status;
307        }
308
309        /**
310         * @return the statusCode
311         */
312        public String getStatusCode() {
313                return statusCode;
314        }
315
316        
317        
318}