001    package railo.runtime.writer;
002    
003    import java.io.IOException;
004    import java.io.OutputStream;
005    import java.io.Writer;
006    
007    import javax.servlet.ServletOutputStream;
008    import javax.servlet.http.HttpServletResponse;
009    
010    import railo.commons.io.IOUtil;
011    import railo.commons.lang.ByteBuffer;
012    import railo.runtime.net.http.ReqRspUtil;
013    
014    /**
015     * Implementation of a JSpWriter
016     */
017    public class JspWriterImplByteBuffer extends CFMLWriter { 
018         
019            private static final int BUFFER_SIZE = 1024; 
020        
021        private ServletOutputStream out;
022    
023        private HttpServletResponse response;
024    
025        private boolean flushed;
026        
027        private String headData;
028        
029        private ByteBuffer buffer;
030        
031        private boolean closed=false;
032    
033            private String charset;
034        
035        /**
036         * constructor of the class
037         * @param response Response Object
038         * @param bufferSize buffer Size
039         * @param autoFlush do auto flush Content
040         */
041        public JspWriterImplByteBuffer(HttpServletResponse response, int bufferSize, boolean autoFlush) {
042            super(bufferSize, autoFlush);
043            this.response=response;
044            this.autoFlush=autoFlush;
045            this.bufferSize=bufferSize;
046            charset = response.getCharacterEncoding();
047            buffer=new ByteBuffer(charset,BUFFER_SIZE);
048            //initBuffer(response.getCharacterEncoding());
049        }
050    
051        /**
052         * constructor of the class
053         * @param response Response Object
054         */
055        public JspWriterImplByteBuffer(HttpServletResponse response) {
056            this(response, BUFFER_SIZE, false);
057        }
058        
059        private void _check() throws IOException {
060            if(autoFlush && buffer.size()>bufferSize)  {
061                _flush();
062            }
063        }
064    
065        /**
066         * @throws IOException
067         */
068        protected void initOut() throws IOException {
069            if (out == null) {
070                out=response.getOutputStream();
071            }
072        }
073    
074            /*public void splitForCacheTo(Resource res) throws IOException {
075                    initOut();
076                    out=new CacheWriter(out,res);
077            } 
078            
079            public void clearCacheSplit() {
080                    if(out instanceof CacheWriter) {
081                            CacheWriter cw = (CacheWriter)out;
082                            out=cw.getOut();
083                            if(cw.getCacheFile().exists())cw.getCacheFile().delete();
084                    }
085            } */
086        
087    
088        /**
089         * @see javax.servlet.jsp.JspWriter#print(char[]) 
090         */ 
091        public void print(char[] arg) throws IOException { 
092            buffer.append(arg);
093            _check();
094        }
095        
096        /**
097         * reset configuration of buffer
098         * @param bufferSize size of the buffer
099         * @param autoFlush does the buffer autoflush
100         * @throws IOException
101         */
102        public void setBufferConfig(int bufferSize, boolean autoFlush) throws IOException {
103            this.bufferSize=bufferSize;
104            this.autoFlush=autoFlush;
105            _check();
106        }
107        
108        /**
109         * 
110         * @param headData
111         * @throws IOException
112         */
113        public void appendHTMLHead(String headData) throws IOException {
114            if(!flushed) {
115                if(this.headData==null)this.headData=headData;
116                else this.headData+=headData;
117            }
118            else throw new IOException("page already flushed");
119        }
120        
121        /**
122         * @see railo.runtime.writer.CFMLWriter#writeHTMLHead(java.lang.String)
123         */
124        public void writeHTMLHead(String headData) throws IOException {
125            if(!flushed) {
126                    this.headData=headData;
127            }
128            else throw new IOException("page already flushed");
129        }
130        
131    
132        
133        /** 
134         * @see railo.runtime.writer.CFMLWriter#getHTMLHead()
135         */
136        public String getHTMLHead() throws IOException {
137            if(flushed) throw new IOException("page already flushed");
138            return headData==null?"":headData;
139        }
140        
141        /** 
142         * @see railo.runtime.writer.CFMLWriter#resetHTMLHead()
143         */
144        public void resetHTMLHead() throws IOException {
145            if(flushed) throw new IOException("page already flushed");
146            headData=null;
147        }
148        
149        /**
150         * just a wrapper function for ACF
151         * @throws IOException 
152         */
153        public void initHeaderBuffer() throws IOException{
154            resetHTMLHead();
155        }
156    
157        /** 
158         * @see java.io.Writer#write(char[], int, int) 
159         */ 
160        public void write(char[] cbuf, int off, int len) throws IOException { 
161            buffer.append(cbuf,off,len);
162            _check();
163        }
164    
165        /** 
166         * @see javax.servlet.jsp.JspWriter#clear() 
167         */ 
168        public void clear() throws IOException { 
169            if (flushed)  throw new IOException("jsp writer is already flushed");
170            clearBuffer();
171        } 
172    
173        /** 
174         * @see javax.servlet.jsp.JspWriter#clearBuffer() 
175         */ 
176        public void clearBuffer() {
177            buffer=new ByteBuffer(charset,BUFFER_SIZE);
178        } 
179    
180        /** 
181         * @see java.io.Writer#flush() 
182         */ 
183        public void flush() throws IOException { 
184            flushBuffer();
185            // weil flushbuffer das out erstellt muss ich nicht mehr checken
186            out.flush();
187        } 
188        /** 
189         * @see java.io.Writer#flush() 
190         */ 
191        private void _flush() throws IOException { 
192            flushBuffer();
193            // weil flushbuffer das out erstellt muss ich nicht mehr checken
194            out.flush();
195        } 
196    
197        /**
198         * Flush the output buffer to the underlying character stream, without
199         * flushing the stream itself.  This method is non-private only so that it
200         * may be invoked by PrintStream.
201         * @throws IOException
202         */
203        protected final void flushBuffer() throws IOException {
204            flushed = true;
205            initOut();
206            _writeOut(out,false);
207            clearBuffer();
208        } 
209        
210        private void _writeOut(OutputStream os,boolean writeLength) throws IOException {
211            if(headData==null) {
212                    if(writeLength)ReqRspUtil.setContentLength(response,buffer.size());
213                buffer.writeOut(os);
214                return;
215                //return buffer.toString();
216            }
217            if(writeLength)ReqRspUtil.setContentLength(response,buffer.size()+headData.getBytes(charset).length);
218            
219            String str=buffer.toString();
220            Writer writer = IOUtil.getWriter(os, charset);
221            int index=str.indexOf("</head>");
222            if(index==-1) {
223                str= headData.concat(str);
224                headData=null;
225                
226                writer.write(str);
227                writer.flush();
228                return;
229                //return str;
230            }
231            str= str.substring(0,index).concat(headData).concat(str.substring(index));
232            headData=null;
233            writer.write(str);
234            writer.flush();
235            //return str;
236        }
237        
238        
239    
240        /** 
241         * @see java.io.Writer#close() 
242         */ 
243        public void close() throws IOException { 
244            if (response == null || closed) return;
245            if(out==null) { 
246                    //response.setContentLength(buffer.size());
247                    initOut();
248                    _writeOut(out,!flushed);
249                
250                    
251                //byte[] barr = _toString().getBytes(response.getCharacterEncoding());
252                //response.setContentLength(barr.length);
253                //ServletOutputStream os = response.getOutputStream();
254                //os.write(barr);
255                out.flush();
256                out.close();
257            }
258            else {
259                    flush();
260                out.close();
261                out = null;
262            }
263            closed = true;
264        } 
265    
266        /** 
267         * @see javax.servlet.jsp.JspWriter#getRemaining() 
268         */ 
269        public int getRemaining() { 
270            return bufferSize - buffer.size();
271        }
272    
273        /** 
274         * @see javax.servlet.jsp.JspWriter#newLine() 
275         */ 
276        public void newLine() throws IOException { 
277            println();
278        } 
279    
280        /** 
281         * @see javax.servlet.jsp.JspWriter#print(boolean) 
282         */ 
283        public void print(boolean arg) throws IOException { 
284            print(arg?new char[]{'t','r','u','e'}:new char[]{'f','a','l','s','e'}); 
285        }
286    
287        /** 
288         * @see javax.servlet.jsp.JspWriter#print(char) 
289         */ 
290        public void print(char arg) throws IOException { 
291            buffer.append(arg);
292            _check();
293        } 
294    
295        /** 
296         * @see javax.servlet.jsp.JspWriter#print(int) 
297         */ 
298        public void print(int arg) throws IOException { 
299            _print(String.valueOf(arg)); 
300        } 
301    
302        /** 
303         * @see javax.servlet.jsp.JspWriter#print(long) 
304         */ 
305        public void print(long arg) throws IOException { 
306            _print(String.valueOf(arg)); 
307    
308        } 
309    
310        /** 
311         * @see javax.servlet.jsp.JspWriter#print(float) 
312         */ 
313        public void print(float arg) throws IOException { 
314            _print(String.valueOf(arg)); 
315        } 
316    
317        /** 
318         * @see javax.servlet.jsp.JspWriter#print(double) 
319         */ 
320        public void print(double arg) throws IOException { 
321            _print(String.valueOf(arg)); 
322        } 
323    
324        /** 
325         * @see javax.servlet.jsp.JspWriter#print(java.lang.String) 
326         */ 
327        public void print(String arg) throws IOException { 
328            buffer.append(arg);
329            _check();
330        } 
331    
332        /** 
333         * @see javax.servlet.jsp.JspWriter#print(java.lang.Object) 
334         */ 
335        public void print(Object arg) throws IOException { 
336            _print(String.valueOf(arg)); 
337        } 
338    
339        /** 
340         * @see javax.servlet.jsp.JspWriter#println() 
341         */ 
342        public void println() throws IOException { 
343            _print("\n"); 
344    
345        } 
346    
347        /** 
348         * @see javax.servlet.jsp.JspWriter#println(boolean) 
349         */ 
350        public void println(boolean arg) throws IOException { 
351            print(arg?new char[]{'t','r','u','e','\n'}:new char[]{'f','a','l','s','e','\n'}); 
352        } 
353    
354        /** 
355         * @see javax.servlet.jsp.JspWriter#println(char) 
356         */ 
357        public void println(char arg) throws IOException { 
358            print(new char[]{arg,'\n'}); 
359        } 
360    
361        /** 
362         * @see javax.servlet.jsp.JspWriter#println(int) 
363         */ 
364        public void println(int arg) throws IOException { 
365            print(arg); 
366            println(); 
367        } 
368    
369        /** 
370         * @see javax.servlet.jsp.JspWriter#println(long) 
371         */ 
372        public void println(long arg) throws IOException { 
373            print(arg); 
374            println(); 
375        } 
376    
377        /** 
378         * @see javax.servlet.jsp.JspWriter#println(float) 
379         */ 
380        public void println(float arg) throws IOException { 
381            print(arg); 
382            println(); 
383        } 
384    
385        /** 
386         * @see javax.servlet.jsp.JspWriter#println(double) 
387         */ 
388        public void println(double arg) throws IOException { 
389            print(arg); 
390            println(); 
391        } 
392    
393        /** 
394         * @see javax.servlet.jsp.JspWriter#println(char[]) 
395         */ 
396        public void println(char[] arg) throws IOException { 
397            print(arg); 
398            println(); 
399        } 
400    
401        /** 
402         * @see javax.servlet.jsp.JspWriter#println(java.lang.String) 
403         */ 
404        public void println(String arg) throws IOException { 
405            _print(arg); 
406            println(); 
407        } 
408    
409        /** 
410         * @see javax.servlet.jsp.JspWriter#println(java.lang.Object) 
411         */ 
412        public void println(Object arg) throws IOException { 
413            print(arg); 
414            println(); 
415        }
416        
417        /** 
418         * @see java.io.Writer#write(char[]) 
419         */ 
420        public void write(char[] cbuf) throws IOException { 
421            print(cbuf); 
422        } 
423    
424        /** 
425         * @see java.io.Writer#write(int) 
426         */ 
427        public void write(int c) throws IOException { 
428            print(c); 
429        } 
430    
431        /** 
432         * @see java.io.Writer#write(java.lang.String, int, int) 
433         */ 
434        public void write(String str, int off, int len) throws IOException { 
435            write(str.toCharArray(),off,len);
436        } 
437    
438        /** 
439         * @see java.io.Writer#write(java.lang.String) 
440         */ 
441        public void write(String str) throws IOException { 
442            _print(str);
443        }
444    
445        /**
446         * @return Returns the flushed.
447         */
448        public boolean isFlushed() {
449            return flushed;
450        }
451    
452        public void setClosed(boolean closed) {
453            this.closed=closed;
454        }
455    
456        private void _print(String arg) throws IOException { 
457            buffer.append(arg);
458            _check();
459        }
460    
461        /**
462             * @see railo.runtime.writer.CFMLWriter#getResponseStream()
463             */
464            public OutputStream getResponseStream() throws IOException {
465                    initOut();
466                    return out;
467            }
468        
469        /**
470             * @see railo.runtime.writer.CFMLWriter#writeRaw(java.lang.String)
471             */
472            public void writeRaw(String str) throws IOException {
473                    write(str);
474            }
475    
476    }