| /* |
| * Copyright 2004-2005 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.taglib.tiles; |
| |
| import java.lang.reflect.InvocationTargetException; |
| |
| import javax.servlet.jsp.JspException; |
| import javax.servlet.jsp.tagext.BodyTagSupport; |
| |
| import org.apache.commons.beanutils.PropertyUtils; |
| import org.apache.taglib.tiles.util.TagUtils; |
| import org.apache.tiles.AttributeDefinition; |
| import org.apache.tiles.DefinitionNameAttribute; |
| import org.apache.tiles.DirectStringAttribute; |
| import org.apache.tiles.PathAttribute; |
| |
| /** |
| * Put an attribute in enclosing attribute container tag. |
| * Enclosing attribute container tag can be : <insert> or <definition>. |
| * Exception is thrown if no appropriate tag can be found. |
| * Put tag can have following atributes : |
| * <li> |
| * <ul>name : Name of the attribute</ul> |
| * <ul>value | content : value to put as attribute</ul> |
| * <ul>type : value type. Only valid if value is a String and is set by |
| * value="something" or by a bean. |
| * Possible type are : string (value is used as direct string), |
| * page | template (value is used as a page url to insert), |
| * definition (value is used as a definition name to insert)</ul> |
| * <ul>direct : Specify if value is to be used as a direct string or as a |
| * page url to insert. This is another way to specify the type. It only apply |
| * if value is set as a string, and type is not present.</ul> |
| * <ul>beanName : Name of a bean used for setting value. Only valid if value is not set. |
| * If property is specified, value come from bean's property. Otherwise, bean |
| * itself is used for value.</ul> |
| * <ul>beanProperty : Name of the property used for retrieving value.</ul> |
| * <ul>beanScope : Scope containing bean. </ul> |
| * <ul>role : Role to check when 'insert' will be called. If enclosing tag is |
| * <insert>, role is checked immediately. If enclosing tag is |
| * <definition>, role will be checked when this definition will be |
| * inserted.</ul> |
| * </li> |
| * Value can also come from tag body. Tag body is taken into account only if |
| * value is not set by one of the tag attributes. In this case Attribute type is |
| * "string", unless tag body define another type. |
| * |
| * @author Cedric Dumoulin |
| * @author David Geary |
| */ |
| public class PutTag extends BodyTagSupport implements ComponentConstants { |
| |
| /* JSP Tag attributes */ |
| |
| /** |
| * Name of attribute to put in component context. |
| */ |
| protected String attributeName = null; |
| |
| /** |
| * Associated attribute value. |
| */ |
| private Object value = null; |
| |
| /** |
| * JSP Template compatibility. |
| */ |
| private String direct = null; |
| |
| /** |
| * Requested type for the value. |
| */ |
| private String valueType = null; |
| |
| /** |
| * Bean name attribute. |
| */ |
| private String beanName = null; |
| |
| /** |
| * Bean property attribute. |
| */ |
| private String beanProperty = null; |
| |
| /** |
| * Bean scope attribute. |
| */ |
| private String beanScope = null; |
| |
| /** |
| * Role attribute. |
| */ |
| private String role = null; |
| |
| /* Internal properties */ |
| |
| /** |
| * Cached real value computed from tag attributes. |
| */ |
| protected Object realValue = null; |
| |
| /** |
| * Default constructor. |
| */ |
| public PutTag() { |
| super(); |
| } |
| |
| /** |
| * Release all allocated resources. |
| */ |
| public void release() { |
| |
| super.release(); |
| |
| attributeName = null; |
| valueType = null; |
| direct = null; |
| value = null; |
| beanName = null; |
| beanProperty = null; |
| beanScope = null; |
| role = null; |
| } |
| |
| /** |
| * Release internal properties. |
| */ |
| protected void releaseInternal() { |
| realValue = null; |
| } |
| |
| /** |
| * Set name. |
| */ |
| public void setName(String value) { |
| this.attributeName = value; |
| } |
| |
| /** |
| * Get name. |
| */ |
| public String getName() { |
| return attributeName; |
| } |
| |
| /** |
| * Set value. |
| * Method added to satisfy Tomcat (bug ?). |
| */ |
| public void setValue(String value) { |
| this.value = value; |
| } |
| |
| /** |
| * Get value. |
| * Method added to satisfy Tomcat (bug ?). |
| */ |
| public String getValue() { |
| return (String) this.value; |
| } |
| |
| /** |
| * Set value. |
| */ |
| public void setValue(Object value) { |
| this.value = value; |
| } |
| |
| /** |
| * Set property value as an object. |
| * Added because some web containers react badly to value as <code>Object</code>. |
| */ |
| public void setObjectValue(Object value) { |
| this.value = value; |
| } |
| |
| /** |
| * Set content. |
| * Method added to satisfy Tomcat (bug ?). |
| */ |
| public void setContent(String value) { |
| this.value = value; |
| } |
| |
| /** |
| * Get content. |
| * Method added to satisfy Tomcat (bug ?). |
| */ |
| public String getContent() { |
| return (String) value; |
| } |
| |
| /** |
| * Set content. |
| */ |
| public void setContent(Object value) { |
| this.value = value; |
| } |
| |
| /** |
| * Set direct. |
| * Method added for compatibility with JSP1.1. |
| */ |
| public void setDirect(String isDirect) { |
| this.direct = isDirect; |
| } |
| |
| /** |
| * Set type. |
| */ |
| public void setType(String value) { |
| this.valueType = value; |
| } |
| |
| /** |
| * Get type. |
| */ |
| public String getType() { |
| return this.valueType; |
| } |
| |
| /** |
| * Set bean name. |
| */ |
| public void setBeanName(String value) { |
| this.beanName = value; |
| } |
| |
| /** |
| * Get bean name. |
| */ |
| public String getBeanName() { |
| return beanName; |
| } |
| |
| /** |
| * Set bean property. |
| */ |
| public void setBeanProperty(String value) { |
| this.beanProperty = value; |
| } |
| |
| /** |
| * Get bean property. |
| */ |
| public String getBeanProperty() { |
| return beanProperty; |
| } |
| |
| /** |
| * Set bean scope. |
| */ |
| public void setBeanScope(String value) { |
| this.beanScope = value; |
| } |
| |
| /** |
| * Get bean scope. |
| */ |
| public String getBeanScope() { |
| return beanScope; |
| } |
| |
| /** |
| * Set role attribute. |
| * @param role The role the user must be in to store content. |
| */ |
| public void setRole(String role) { |
| this.role = role; |
| } |
| |
| /** |
| * Get role attribute |
| * @return The role defined in the tag or <code>null</code>. |
| */ |
| public String getRole() { |
| return role; |
| } |
| |
| /** |
| * Get real value according to tag attribute. |
| * Real value is the value computed after attribute processing. |
| * @return Real value. |
| * @throws JspException If something goes wrong while getting value from bean. |
| */ |
| public Object getRealValue() throws JspException { |
| if (realValue == null) { |
| computeRealValue(); |
| } |
| |
| return realValue; |
| } |
| |
| /** |
| * Compute real value according to tag attributes. |
| * @throws JspException If something goes wrong while getting value from bean. |
| */ |
| protected void computeRealValue() throws JspException { |
| // Compute real value from attributes set. |
| realValue = value; |
| |
| // If realValue is not set, value must come from body |
| if (value == null && beanName == null) { |
| // Test body content in case of empty body. |
| if (bodyContent != null) { |
| realValue = bodyContent.getString(); |
| } else { |
| realValue = ""; |
| } |
| } |
| |
| // Does value comes from a bean ? |
| if (realValue == null && beanName != null) { |
| getRealValueFromBean(); |
| return; |
| } |
| |
| // Is there a type set ? |
| // First check direct attribute, and translate it to a valueType. |
| // Then, evaluate valueType, and create requested typed attribute. |
| // If valueType is not set, use the value "as is". |
| if (valueType == null && direct != null) { |
| if (Boolean.valueOf(direct).booleanValue() == true) { |
| valueType = "string"; |
| } else { |
| valueType = "path"; |
| } |
| } |
| |
| if (realValue != null |
| && valueType != null |
| && !(value instanceof AttributeDefinition)) { |
| |
| String strValue = realValue.toString(); |
| if (valueType.equalsIgnoreCase("string")) { |
| realValue = new DirectStringAttribute(strValue); |
| |
| } else if (valueType.equalsIgnoreCase("page")) { |
| realValue = new PathAttribute(strValue); |
| |
| } else if (valueType.equalsIgnoreCase("template")) { |
| realValue = new PathAttribute(strValue); |
| |
| } else if (valueType.equalsIgnoreCase("instance")) { |
| realValue = new DefinitionNameAttribute(strValue); |
| |
| } else if (valueType.equalsIgnoreCase("definition")) { |
| realValue = new DefinitionNameAttribute(strValue); |
| |
| } else { // bad type |
| throw new JspException( |
| "Warning - Tag put : Bad type '" + valueType + "'."); |
| } |
| } |
| |
| } |
| |
| /** |
| * Extract real value from specified bean. |
| * @throws JspException If something goes wrong while getting value from bean. |
| */ |
| protected void getRealValueFromBean() throws JspException { |
| try { |
| Object bean = TagUtils.retrieveBean(beanName, beanScope, pageContext); |
| if (bean != null && beanProperty != null) { |
| realValue = PropertyUtils.getProperty(bean, beanProperty); |
| } else { |
| realValue = bean; // value can be null |
| } |
| |
| } catch (NoSuchMethodException ex) { |
| throw new JspException( |
| "Error - component.PutAttributeTag : Error while retrieving value from bean '" |
| + beanName |
| + "' with property '" |
| + beanProperty |
| + "' in scope '" |
| + beanScope |
| + "'. (exception : " |
| + ex.getMessage()); |
| |
| } catch (InvocationTargetException ex) { |
| throw new JspException( |
| "Error - component.PutAttributeTag : Error while retrieving value from bean '" |
| + beanName |
| + "' with property '" |
| + beanProperty |
| + "' in scope '" |
| + beanScope |
| + "'. (exception : " |
| + ex.getMessage()); |
| |
| } catch (IllegalAccessException ex) { |
| throw new JspException( |
| "Error - component.PutAttributeTag : Error while retrieving value from bean '" |
| + beanName |
| + "' with property '" |
| + beanProperty |
| + "' in scope '" |
| + beanScope |
| + "'. (exception : " |
| + ex.getMessage()); |
| } |
| } |
| |
| /** |
| * Do start tag. |
| */ |
| public int doStartTag() throws JspException { |
| // Do we need to evaluate body ? |
| if (value == null && beanName == null) { |
| return EVAL_BODY_TAG; |
| } |
| |
| // Value is set, don't evaluate body. |
| return SKIP_BODY; |
| } |
| |
| /** |
| * Do end tag. |
| */ |
| public int doEndTag() throws JspException { |
| // Call parent tag which in turn does what it want |
| callParent(); |
| |
| // clean up tag handler for reuse. |
| releaseInternal(); |
| |
| return EVAL_PAGE; |
| } |
| |
| /** |
| * Find parent tag which must implement AttributeContainer. |
| * @throws JspException If we can't find an appropriate enclosing tag. |
| */ |
| protected void callParent() throws JspException { |
| // Get enclosing parent |
| PutTagParent enclosingParent = findEnclosingPutTagParent(); |
| enclosingParent.processNestedTag(this); |
| } |
| |
| /** |
| * Find parent tag which must implement AttributeContainer. |
| * @throws JspException If we can't find an appropriate enclosing tag. |
| */ |
| protected PutTagParent findEnclosingPutTagParent() throws JspException { |
| try { |
| PutTagParent parent = |
| (PutTagParent) findAncestorWithClass(this, PutTagParent.class); |
| |
| if (parent == null) { |
| throw new JspException("Error - tag put : enclosing tag doesn't accept 'put' tag."); |
| } |
| |
| return parent; |
| |
| } catch (ClassCastException ex) { |
| throw new JspException("Error - tag put : enclosing tag doesn't accept 'put' tag."); |
| } |
| } |
| |
| } |