View Javadoc
1 /* 2 * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/impl/BeanTagScript.java,v 1.15 2002/08/13 08:04:38 jstrachan Exp $ 3 * $Revision: 1.15 $ 4 * $Date: 2002/08/13 08:04:38 $ 5 * 6 * ==================================================================== 7 * 8 * The Apache Software License, Version 1.1 9 * 10 * Copyright (c) 1999-2002 The Apache Software Foundation. All rights 11 * reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. The end-user documentation included with the redistribution, if 26 * any, must include the following acknowlegement: 27 * "This product includes software developed by the 28 * Apache Software Foundation (http://www.apache.org/)." 29 * Alternately, this acknowlegement may appear in the software itself, 30 * if and wherever such third-party acknowlegements normally appear. 31 * 32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software 33 * Foundation" must not be used to endorse or promote products derived 34 * from this software without prior written permission. For written 35 * permission, please contact apache@apache.org. 36 * 37 * 5. Products derived from this software may not be called "Apache" 38 * nor may "Apache" appear in their names without prior written 39 * permission of the Apache Group. 40 * 41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This software consists of voluntary contributions made by many 56 * individuals on behalf of the Apache Software Foundation. For more 57 * information on the Apache Software Foundation, please see 58 * <http://www.apache.org/>;. 59 * 60 * $Id: BeanTagScript.java,v 1.15 2002/08/13 08:04:38 jstrachan Exp $ 61 */ 62 63 package org.apache.commons.jelly.impl; 64 65 import java.beans.BeanInfo; 66 import java.beans.Introspector; 67 import java.beans.PropertyDescriptor; 68 import java.lang.reflect.Method; 69 import java.io.Writer; 70 import java.util.ArrayList; 71 import java.util.HashMap; 72 import java.util.HashSet; 73 import java.util.Iterator; 74 import java.util.List; 75 import java.util.Map; 76 import java.util.Set; 77 78 import org.apache.commons.beanutils.ConvertUtils; 79 80 import org.apache.commons.jelly.CompilableTag; 81 import org.apache.commons.jelly.JellyContext; 82 import org.apache.commons.jelly.JellyException; 83 import org.apache.commons.jelly.Script; 84 import org.apache.commons.jelly.Tag; 85 import org.apache.commons.jelly.XMLOutput; 86 import org.apache.commons.jelly.expression.Expression; 87 88 import org.apache.commons.logging.Log; 89 import org.apache.commons.logging.LogFactory; 90 91 /*** <p><code>TagScript</code> evaluates a custom tag.</p> 92 * 93 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> 94 * @version $Revision: 1.15 $ 95 */ 96 97 public class BeanTagScript extends TagScript { 98 99 /*** The Log to which logging calls will be made. */ 100 private static final Log log = LogFactory.getLog(BeanTagScript.class); 101 102 103 // this state must be shared & thread safe... 104 105 /*** The cached Tag Class information */ 106 private Class tagClass; 107 108 /*** Expressions for each attribute */ 109 private Expression[] expressions = { 110 }; 111 112 /*** Write Methods for each attribute */ 113 private Method[] methods = { 114 }; 115 116 /*** Types of each attribute */ 117 private Class[] types = { 118 }; 119 120 public BeanTagScript() { 121 } 122 123 public BeanTagScript(TagFactory tagFactory) { 124 super(tagFactory); 125 } 126 127 // Script interface 128 //------------------------------------------------------------------------- 129 130 /*** Evaluates the body of a tag */ 131 public void run(JellyContext context, XMLOutput output) throws Exception { 132 if ( ! context.isCacheTags() ) { 133 clearTag(); 134 } 135 Tag tag = getTag(); 136 if ( tag == null ) { 137 return; 138 } 139 tag.setContext(context); 140 141 // initialize all the properties of the tag before its used 142 // if there is a problem abort this tag 143 for (int i = 0, size = expressions.length; i < size; i++) { 144 Expression expression = expressions[i]; 145 Method method = methods[i]; 146 Class type = types[i]; 147 148 // some types are Expression objects so let the tag 149 // evaluate them 150 Object value = null; 151 if (type.isAssignableFrom(Expression.class) && !type.isAssignableFrom(Object.class)) { 152 value = expression; 153 } 154 else { 155 value = expression.evaluate(context); 156 } 157 // convert value to correct type 158 if (value != null) { 159 value = convertType(value, type); 160 } 161 Object[] arguments = { value }; 162 try { 163 method.invoke(tag, arguments); 164 } 165 catch (Exception e) { 166 String valueTypeName = (value != null ) ? value.getClass().getName() : "null"; 167 log.warn( 168 "Cannot call method: " + method.getName() + " as I cannot convert: " 169 + value + " of type: " + valueTypeName + " into type: " + type.getName() 170 ); 171 throw createJellyException( 172 "Cannot call method: " + method.getName() + " on tag of type: " 173 + tag.getClass().getName() + " with value: " + value + " of type: " 174 + valueTypeName + ". Exception: " + e, e 175 ); 176 } 177 } 178 179 try { 180 tag.doTag(output); 181 } 182 catch (JellyException e) { 183 handleException(e); 184 } 185 catch (Exception e) { 186 handleException(e); 187 } 188 } 189 190 191 // Implementation methods 192 //------------------------------------------------------------------------- 193 194 /*** 195 * Compiles a newly created tag if required, sets its parent and body. 196 */ 197 protected void configureTag(Tag tag) throws Exception { 198 super.configureTag(tag); 199 Class aClass = tag.getClass(); 200 if ( tagClass == null || ! tagClass.equals( aClass ) ) { 201 tagClass = aClass; 202 compileClass(); 203 } 204 } 205 206 207 /*** Compiles the given tag class caching the property descriptors etc. 208 */ 209 protected void compileClass() throws Exception { 210 List typeList = new ArrayList(); 211 List methodList = new ArrayList(); 212 List expressionList = new ArrayList(); 213 BeanInfo info = Introspector.getBeanInfo(tagClass); 214 PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); 215 Set attributeSet = new HashSet(); 216 if (descriptors != null) { 217 for (int i = 0, size = descriptors.length; i < size; i++) { 218 PropertyDescriptor descriptor = descriptors[i]; 219 String name = descriptor.getName(); 220 Expression expression = (Expression) attributes.get(name); 221 if (expression != null) { 222 attributeSet.add( name ); 223 Method writeMethod = descriptor.getWriteMethod(); 224 if (writeMethod != null) { 225 Class type = descriptor.getPropertyType(); 226 expressionList.add(expression); 227 methodList.add(writeMethod); 228 typeList.add(type); 229 if (log.isDebugEnabled()) { 230 log.debug( 231 "Adding tag property name: " 232 + name 233 + " type: " 234 + type.getName() 235 + " expression: " 236 + expression); 237 } 238 } 239 } 240 } 241 } 242 243 // System.err.println( "BeanTagScript::compile() " + this ); 244 245 // now create the arrays to avoid object allocation & casting when 246 // running the script 247 int size = expressionList.size(); 248 expressions = new Expression[size]; 249 methods = new Method[size]; 250 types = new Class[size]; 251 expressionList.toArray(expressions); 252 methodList.toArray(methods); 253 typeList.toArray(types); 254 255 // now lets check for any attributes that are not used 256 for ( Iterator iter = attributes.keySet().iterator(); iter.hasNext(); ) { 257 String name = (String) iter.next(); 258 if ( ! attributeSet.contains( name ) ) { 259 throw createJellyException( 260 "This tag does not understand the attribute '" + name + "'" 261 ); 262 } 263 } 264 } 265 266 }

This page was automatically generated by Maven