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.commons.io;
020import javax.servlet.jsp.JspWriter;
021import javax.servlet.jsp.tagext.BodyContent;
022
023import lucee.runtime.writer.BodyContentImpl;
024import lucee.runtime.writer.CFMLWriter;
025import lucee.runtime.writer.DevNullBodyContent;
026
027/**
028 * Stack for the Body Content Objects
029 */
030public final class BodyContentStack {
031
032    private CFMLWriter base;
033    
034    private final DevNullBodyContent nirvana=new DevNullBodyContent();
035    private Entry current;
036    private final Entry root;
037    
038    
039    /**
040     * Default Constructor
041     */
042    public BodyContentStack() {
043        current=new Entry(null,null);
044        root=current;
045    }
046
047    /**
048     * initialize the BodyContentStack
049     * @param rsp
050     */
051    public void init(CFMLWriter writer) {
052        this.base=writer;
053    }
054
055    /**
056     * release the BodyContentStack
057     */
058    public void release() {
059        this.base=null;
060        current=root;
061        current.body=null;
062        current.after=null;
063        current.before=null;
064    }
065    
066
067    /**
068     * push a new BodyContent to Stack
069     * @return new BodyContent
070     */
071    public BodyContent push() {
072        if(current.after==null) {
073            current.after=new Entry(current,new BodyContentImpl(current.body==null?(JspWriter)base:current.body));
074        }
075        else {
076            current.after.doDevNull=false;
077            current.after.body.init(current.body==null?(JspWriter)base:current.body);
078        }
079        current=current.after;
080        return current.body;
081    }
082    
083    /**
084     * pop a BodyContent from Stack
085     * @return BodyContent poped
086     */
087    public JspWriter pop() {
088        if(current.before!=null) current=current.before;
089        return getWriter();
090    }
091    
092    /**
093     * set if actuell BodyContent is DevNull or not
094     * @param doDevNull
095     */
096    public void setDevNull(boolean doDevNull) {
097        current.doDevNull=doDevNull;
098    }
099    
100    /**
101     * @return returns actuell writer
102     */
103    public JspWriter getWriter() {
104        if(!current.doDevNull) {
105            if(current.body!=null) return current.body;
106            return base;
107        }
108        return nirvana;
109    }
110    
111    
112    class Entry {
113        private Entry before;
114        private Entry after;
115        private boolean doDevNull=false;
116        private BodyContentImpl body;
117        private Entry(Entry before, BodyContentImpl body) {
118            this.before=before;
119            this.body=body;
120        }
121        
122    }
123
124    /**
125     * @return returns DevNull Object
126     */
127    public boolean getDevNull() {
128        return current.doDevNull;
129    }
130
131    /**
132     * @return returns DevNull Object
133     */
134    public DevNullBodyContent getDevNullBodyContent() {
135        return nirvana;
136    }
137
138    /**
139     * @return Returns the base.
140     */
141    public CFMLWriter getBase() {
142        return base;
143    }
144
145}