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.tag;
020
021import java.io.IOException;
022import java.util.Map;
023import java.util.TreeMap;
024
025import lucee.commons.lang.StringUtil;
026import lucee.runtime.exp.ApplicationException;
027import lucee.runtime.exp.PageException;
028import lucee.runtime.ext.tag.BodyTagTryCatchFinallyImpl;
029import lucee.runtime.op.Caster;
030
031/**
032 * base class for both cfhtmlhead and cfhtmlbody
033 */
034public abstract class HtmlHeadBodyBase extends BodyTagTryCatchFinallyImpl {
035
036        private final static String REQUEST_ATTRIBUTE_PREFIX = "REQUEST_ATTRIBUTE_IDMAP_";
037
038        /**
039         * The text to add to the 'head' area of an HTML page. Everything inside the quotation marks is placed in the 'head' section
040         */
041        protected String text = null;
042        protected String variable = null;
043
044        private String action = null;
045        private String id = null;
046
047        @Override
048        public void release() {
049                super.release();
050                text = null;
051                variable = null;
052                action = null;
053                id = null;
054        }
055
056        public abstract String getTagName();
057        public abstract void actionAppend() throws IOException, ApplicationException;
058        public abstract void actionFlush() throws IOException;
059        public abstract void actionRead() throws IOException, PageException;
060        public abstract void actionReset() throws IOException;
061        public abstract void actionWrite() throws IOException, ApplicationException;
062
063        /**
064         * @param variable the variable to set
065         */
066        public void setVariable(String variable) {
067                this.variable = variable;
068        }
069
070        /**
071         * @param action the action to set
072         */
073        public void setAction(String action) {
074                if (!StringUtil.isEmpty(action, true))
075                        this.action = action.trim().toLowerCase();
076        }
077
078
079        /**
080         * set the value text
081         * The text to add to the 'head' area of an HTML page. Everything inside the quotation marks is
082         * placed in the 'head' section
083         *
084         * @param text value to set
085         */
086        public void setText(String text) {
087                this.text = text;
088        }
089
090        public void setId(String id) {
091                this.id = id;
092        }
093
094        @Override
095        public int doStartTag() throws PageException {
096
097                return EVAL_BODY_BUFFERED;
098        }
099
100
101        @Override
102        public int doEndTag() throws PageException {
103
104                processTag();
105
106                return SKIP_BODY;
107        }
108
109        public int doAfterBody() throws PageException {
110                if (StringUtil.isEmpty(text) && bodyContent != null) {
111                        text = bodyContent.getString();
112                }
113                if(bodyContent!=null)bodyContent.clearBody();
114
115                return SKIP_BODY;
116        }
117
118        protected void processTag() throws PageException {
119
120                try {
121
122                        if (StringUtil.isEmpty(action, true) || action.equals("append")) {
123
124                                required(getTagName(), "text", text);
125                                if (isValid())
126                                        actionAppend();
127                        }
128                        else if (action.equals("reset")) {
129
130                                resetIdMap();
131                                actionReset();
132                        }
133                        else if (action.equals("write")) {
134
135                                required(getTagName(), "text", text);
136                                resetIdMap();
137                                if (isValid())          // call isValid() to register the id if set
138                                        actionWrite();
139                        }
140                        else if (action.equals("read")) actionRead();
141                        else if (action.equals("flush")) actionFlush();
142                        else
143                                throw new ApplicationException("invalid value [" + action + "] for attribute action", "values for attribute action are: [append], flush, read, reset, write");
144                } catch (IOException e) {
145                        throw Caster.toPageException(e);
146                }
147        }
148
149        /**
150         *
151         * @return - true if the id was not set or was set and was not used yet in the request. if it was not set -- register it for future calls of the tag
152         */
153        protected boolean isValid() {
154
155                if (StringUtil.isEmpty(id))
156                        return true;
157
158                Map m = getIdMap();
159
160        if (m.containsKey(id))
161            return false;
162
163        m.put(id, Boolean.TRUE);
164        return true;
165        }
166
167        protected Map getIdMap() {
168
169                String reqAttr = REQUEST_ATTRIBUTE_PREFIX + getTagName();
170
171                Map result = (Map)pageContext.getRequest().getAttribute(reqAttr);
172
173                if (result == null) {
174
175                        result = new TreeMap(String.CASE_INSENSITIVE_ORDER);
176                        pageContext.getRequest().setAttribute(reqAttr, result);
177                }
178
179                return result;
180        }
181
182        protected void resetIdMap() {
183
184                String reqAttr = REQUEST_ATTRIBUTE_PREFIX + getTagName();
185
186                pageContext.getRequest().setAttribute(reqAttr, null);
187        }
188}