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