1 /* 2 * $Id: InsertAttributeModel.java 1305937 2012-03-27 18:15:15Z nlebas $ 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 package org.apache.tiles.template; 23 24 import java.io.IOException; 25 import java.util.Deque; 26 27 import org.apache.tiles.Attribute; 28 import org.apache.tiles.TilesContainer; 29 import org.apache.tiles.access.TilesAccess; 30 import org.apache.tiles.autotag.core.runtime.ModelBody; 31 import org.apache.tiles.request.Request; 32 import org.slf4j.Logger; 33 import org.slf4j.LoggerFactory; 34 35 /** 36 * <p> 37 * <strong>Inserts the value of an attribute into the page.</strong> 38 * </p> 39 * <p> 40 * This tag can be flexibly used to insert the value of an attribute into a 41 * page. As in other usages in Tiles, every attribute can be determined to have 42 * a "type", either set explicitly when it was defined, or "computed". If the 43 * type is not explicit, then if the attribute value is a valid definition, it 44 * will be inserted as such. Otherwise, if it begins with a "/" character, it 45 * will be treated as a "template". Finally, if it has not otherwise been 46 * assigned a type, it will be treated as a String and included without any 47 * special handling. 48 * </p> 49 * 50 * <p> 51 * <strong>Example : </strong> 52 * </p> 53 * 54 * <pre> 55 * <code> 56 * <tiles:insertAttribute name="body" /> 57 * </code> 58 * </pre> 59 * 60 * @version $Rev: 1305937 $ $Date: 2012-03-28 05:15:15 +1100 (Wed, 28 Mar 2012) $ 61 * @since 2.2.0 62 */ 63 public class InsertAttributeModel { 64 65 /** 66 * The logging object. 67 */ 68 private Logger log = LoggerFactory.getLogger(getClass()); 69 70 /** 71 * The attribute resolver to use. 72 */ 73 private AttributeResolver attributeResolver; 74 75 /** 76 * Constructor that uses the defaut attribute resolver. 77 * 78 * @since 3.0.0 79 */ 80 public InsertAttributeModel() { 81 this(new DefaultAttributeResolver()); 82 } 83 84 /** 85 * Constructor. 86 * 87 * @param attributeResolver The attribute resolver to use. 88 * @since 2.2.0 89 */ 90 public InsertAttributeModel(AttributeResolver attributeResolver) { 91 this.attributeResolver = attributeResolver; 92 } 93 94 /** 95 * Executes the operation. 96 * @param ignore If <code>true</code>, if an exception happens during 97 * rendering, of if the attribute is null, the problem will be ignored. 98 * @param preparer The preparer to invoke before rendering the attribute. 99 * @param role A comma-separated list of roles. If present, the attribute 100 * will be rendered only if the current user belongs to one of the roles. 101 * @param defaultValue The default value of the attribute. To use only if 102 * the attribute was not computed. 103 * @param defaultValueRole The default comma-separated list of roles. To use 104 * only if the attribute was not computed. 105 * @param defaultValueType The default type of the attribute. To use only if 106 * the attribute was not computed. 107 * @param name The name of the attribute. 108 * @param value The attribute to use immediately, if not null. 109 * @param flush If <code>true</code>, the response will be flushed after the insert. 110 * @param request The request. 111 * @param modelBody The body. 112 * @throws IOException If an I/O error happens during rendering. 113 * @since 2.2.0 114 */ 115 public void execute(boolean ignore, String preparer, 116 String role, Object defaultValue, String defaultValueRole, 117 String defaultValueType, String name, Attribute value, 118 boolean flush, Request request, ModelBody modelBody) throws IOException { 119 TilesContainer container = TilesAccess.getCurrentContainer(request); 120 Deque<Object> composeStack = ComposeStackUtil.getComposeStack(request); 121 Attribute attribute = resolveAttribute(container, ignore, preparer, 122 role, defaultValue, defaultValueRole, defaultValueType, name, 123 value, request); 124 if (attribute != null) { 125 composeStack.push(attribute); 126 } 127 modelBody.evaluateWithoutWriting(); 128 container = TilesAccess.getCurrentContainer(request); 129 if (attribute != null) { 130 attribute = (Attribute) composeStack.pop(); 131 } 132 renderAttribute(container, ignore, attribute, request); 133 if (flush) { 134 request.getWriter().flush(); 135 } 136 } 137 138 /** 139 * Resolves the attribute. and starts the context. 140 * 141 * @param container The Tiles container to use. 142 * @param ignore If <code>true</code>, if an exception happens during 143 * rendering, of if the attribute is null, the problem will be ignored. 144 * @param preparer The preparer to invoke before rendering the attribute. 145 * @param role A comma-separated list of roles. If present, the attribute 146 * will be rendered only if the current user belongs to one of the roles. 147 * @param defaultValue The default value of the attribute. To use only if 148 * the attribute was not computed. 149 * @param defaultValueRole The default comma-separated list of roles. To use 150 * only if the attribute was not computed. 151 * @param defaultValueType The default type of the attribute. To use only if 152 * the attribute was not computed. 153 * @param name The name of the attribute. 154 * @param value The attribute to use immediately, if not null. 155 * @param request The request. 156 * @return The resolved attribute. 157 */ 158 private Attribute resolveAttribute(TilesContainer container, 159 boolean ignore, String preparer, String role, Object defaultValue, 160 String defaultValueRole, String defaultValueType, String name, 161 Attribute value, Request request) { 162 if (preparer != null) { 163 container.prepare(preparer, request); 164 } 165 Attribute attribute = attributeResolver.computeAttribute(container, 166 value, name, role, ignore, defaultValue, defaultValueRole, 167 defaultValueType, request); 168 container.startContext(request); 169 return attribute; 170 } 171 172 /** 173 * Renders the attribute as a string. 174 * @param container The Tiles container to use. 175 * @param ignore If <code>true</code>, if an exception happens during 176 * rendering, of if the attribute is null, the problem will be ignored. 177 * @param attribute The attribute to use, previously resolved. 178 * @param request The request. 179 * 180 * @throws IOException If an I/O error happens during rendering. 181 */ 182 private void renderAttribute(TilesContainer container, boolean ignore, 183 Attribute attribute, Request request) throws IOException { 184 try { 185 if (attribute == null && ignore) { 186 return; 187 } 188 container.render(attribute, request); 189 } catch (IOException e) { 190 if (!ignore) { 191 throw e; 192 } else if (log.isDebugEnabled()) { 193 log.debug("Ignoring exception", e); 194 } 195 } catch (RuntimeException e) { 196 if (!ignore) { 197 throw e; 198 } else if (log.isDebugEnabled()) { 199 log.debug("Ignoring exception", e); 200 } 201 } finally { 202 container.endContext(request); 203 } 204 } 205 }