001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.jsp; 029 030import org.opencms.json.JSONArray; 031import org.opencms.json.JSONException; 032import org.opencms.json.JSONObject; 033import org.opencms.jsp.util.CmsJspJsonWrapper; 034 035import javax.servlet.jsp.JspException; 036import javax.servlet.jsp.JspTagException; 037import javax.servlet.jsp.PageContext; 038import javax.servlet.jsp.tagext.BodyTagSupport; 039 040/** 041 * Abstract superclass that handles the common behavior of the jsonarray/jsonobject/jsonvalue tags. 042 * 043 * <p>Each of these tags constructs a JSON value, adds it to the surrounding JSON context object if one exists, 044 * and optionally stores the result in a page context variable, either as a JSON object or as formatted JSON text, 045 * depending on the value of the mode attribute. 046 */ 047public abstract class A_CmsJspJsonTag extends BodyTagSupport { 048 049 /** JSON processing mode, decides what is stored in the variable given by var. */ 050 enum Mode { 051 /** Store result of tag as an object. */ 052 object, 053 /** Store result as wrapper object. */ 054 wrapper, 055 /** Store result of tag as formatted JSON (i.e. a string) . */ 056 text; 057 } 058 059 /** String describing request scope. */ 060 private static final String SCOPE_REQUEST = "request"; 061 062 /** String describing session scope. */ 063 private static final String SCOPE_SESSION = "session"; 064 065 /** String describing application scope. */ 066 private static final String SCOPE_APPLICATION = "application"; 067 068 /** Serial version id. */ 069 private static final long serialVersionUID = -4536413263964718943L; 070 071 /** The key attribute. */ 072 protected String m_key; 073 074 /** The mode attribute. */ 075 protected String m_mode; 076 077 /** The var attribute. */ 078 protected String m_var; 079 080 /** The target attribute. */ 081 protected Object m_target; 082 083 /** The scope attribute. */ 084 protected String m_scope; 085 086 /** 087 * Converts the given string description of a scope to the corresponding PageContext constant. 088 * 089 * @param scope String description of scope 090 * 091 * @return PageContext constant corresponding to given scope description 092 */ 093 protected static int getScope(String scope) { 094 095 int ret = PageContext.PAGE_SCOPE; // default 096 if (SCOPE_REQUEST.equalsIgnoreCase(scope)) { 097 ret = PageContext.REQUEST_SCOPE; 098 } else if (SCOPE_SESSION.equalsIgnoreCase(scope)) { 099 ret = PageContext.SESSION_SCOPE; 100 } else if (SCOPE_APPLICATION.equalsIgnoreCase(scope)) { 101 ret = PageContext.APPLICATION_SCOPE; 102 } 103 return ret; 104 } 105 106 /** 107 * @see javax.servlet.jsp.tagext.TagSupport#doEndTag() 108 */ 109 @Override 110 public int doEndTag() throws JspException { 111 112 if (m_var != null) { 113 // Export to a variable 114 String modeStr = m_mode; 115 Mode mode = Mode.wrapper; 116 int scopeValue = getScope(m_scope); 117 if (modeStr != null) { 118 try { 119 mode = Mode.valueOf(modeStr); 120 } catch (Exception e) { 121 throw new JspTagException("Unknown mode for json tag: " + modeStr); 122 } 123 } 124 Object val; 125 switch (mode) { 126 case object: 127 val = getJsonValue(); 128 break; 129 case text: 130 try { 131 val = JSONObject.valueToString(getJsonValue()); 132 } catch (JSONException e) { 133 throw new JspTagException("Could not format JSON", e); 134 } 135 break; 136 case wrapper: 137 default: 138 val = new CmsJspJsonWrapper(getJsonValue()); 139 break; 140 } 141 pageContext.setAttribute(m_var, val, scopeValue); 142 } else if (m_target != null) { 143 // Export to a specified JSON object 144 addToTarget(m_target, getJsonValue(), m_key); 145 } else { 146 I_CmsJspJsonContext context = (I_CmsJspJsonContext)findAncestorWithClass(this, I_CmsJspJsonContext.class); 147 if (context != null) { 148 context.addValue(m_key, getJsonValue()); 149 } 150 } 151 return EVAL_PAGE; 152 } 153 154 /** 155 * Returns the JSON value that should be added to the surrounding context and/or stored in the variable 156 * given by the var attribute. 157 * 158 * @return the value to add/store 159 * @throws JspTagException if getting the value fails 160 */ 161 public abstract Object getJsonValue() throws JspTagException; 162 163 /** 164 * Releases the resources used by this tag.<p> 165 */ 166 @Override 167 public void release() { 168 169 init(); 170 super.release(); 171 } 172 173 /** 174 * Sets the key attribute. 175 * 176 * @param key the key under which to store the value in the surrounding JSON object 177 */ 178 public void setKey(String key) { 179 180 m_key = key; 181 } 182 183 /** 184 * Sets the mode attribute. 185 * 186 * @param mode the mode 187 */ 188 public void setMode(String mode) { 189 190 m_mode = mode; 191 } 192 193 /** 194 * Sets the scope attribute. 195 * 196 * @param scope the variable scope 197 */ 198 public void setScope(String scope) { 199 200 m_scope = scope; 201 } 202 203 /** 204 * Sets the target attribute. 205 * 206 * @param target the target Object to store the JSON in. 207 * 208 * This must be another JSON object or a JSON wrapper. 209 */ 210 public void setTarget(Object target) { 211 212 m_target = target; 213 } 214 215 /** 216 * Sets the var attribute. 217 * 218 * @param var the name of the variable to store the result in 219 */ 220 public void setVar(String var) { 221 222 m_var = var; 223 } 224 225 /** 226 * Adds the specified value to the selected target.<p> 227 * 228 * @param target the target object 229 * @param val the value to set 230 * @param key the key to set the value, required in case the target is a JSONObject 231 * 232 * @throws JspException in case the value could not be added to the target 233 */ 234 protected void addToTarget(Object target, Object val, String key) throws JspException { 235 236 if (target instanceof JSONObject) { 237 if (key == null) { 238 throw new JspTagException("Can not add to JSONObject target with no key (val:" + val + ")"); 239 } 240 try { 241 JSONObject jsonObj = (JSONObject)target; 242 if (jsonObj.has(key)) { 243 jsonObj.append(key, val); 244 } else { 245 jsonObj.put(key, val); 246 } 247 } catch (JSONException e) { 248 throw new JspTagException("Could not add value to JSONObject target", e); 249 } 250 } else if (target instanceof JSONArray) { 251 ((JSONArray)target).put(val); 252 } else if (target instanceof CmsJspJsonWrapper) { 253 Object wrappedTaget = ((CmsJspJsonWrapper)target).getObject(); 254 addToTarget(wrappedTaget, val, key); 255 } else { 256 throw new JspTagException("Invalid target specified (target:" + val + ")"); 257 } 258 } 259 260 /** 261 * Initializes / resets the internal values.<p> 262 */ 263 protected void init() { 264 265 m_key = null; 266 m_var = null; 267 m_mode = null; 268 m_target = null; 269 m_scope = null; 270 } 271}