Coverage report

  %line %branch
org.apache.commons.jelly.impl.DynamicBeanTag
0% 
0% 

 1  
 /*
 2  
  * Copyright 2002,2004 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.commons.jelly.impl;
 17  
 
 18  
 import java.lang.reflect.InvocationTargetException;
 19  
 import java.lang.reflect.Method;
 20  
 import java.util.HashSet;
 21  
 import java.util.Iterator;
 22  
 import java.util.Map;
 23  
 import java.util.Set;
 24  
 
 25  
 import org.apache.commons.beanutils.ConvertingWrapDynaBean;
 26  
 import org.apache.commons.collections.BeanMap;
 27  
 import org.apache.commons.jelly.DynaBeanTagSupport;
 28  
 import org.apache.commons.jelly.JellyTagException;
 29  
 import org.apache.commons.jelly.MissingAttributeException;
 30  
 import org.apache.commons.jelly.Tag;
 31  
 import org.apache.commons.jelly.XMLOutput;
 32  
 import org.apache.commons.jelly.expression.Expression;
 33  
 import org.apache.commons.logging.Log;
 34  
 import org.apache.commons.logging.LogFactory;
 35  
 
 36  
 /**
 37  
  * This tag is bound onto a Java Bean class. When the tag is invoked a bean will be created
 38  
  * using the tags attributes.
 39  
  * The bean may also have an invoke method called invoke(), run(), execute() or some such method
 40  
  * which will be invoked after the bean has been configured.</p>
 41  
  *
 42  
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 43  
  * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
 44  
  * @version $Revision: 1.7 $
 45  
  */
 46  0
 public class DynamicBeanTag extends DynaBeanTagSupport implements BeanSource {
 47  
 
 48  
     /** The Log to which logging calls will be made. */
 49  0
     private static final Log log = LogFactory.getLog(DynamicBeanTag.class);
 50  
 
 51  
     /** Empty arguments for Method.invoke() */
 52  0
     private static final Object[] emptyArgs = {};
 53  
 
 54  
     /** the bean class */
 55  
     private Class beanClass;
 56  
 
 57  
     /** the current bean instance */
 58  
     private Object bean;
 59  
 
 60  
     /** the method to invoke on the bean */
 61  
     private Method method;
 62  
 
 63  
     /**
 64  
      * the tag attribute name that is used to declare the name
 65  
      * of the variable to export after running this tag
 66  
      */
 67  
     private String variableNameAttribute;
 68  
 
 69  
     /** the current variable name that the bean should be exported as */
 70  
     private String var;
 71  
 
 72  
     /** the set of attribute names we've already set */
 73  0
     private Set setAttributesSet = new HashSet();
 74  
 
 75  
     /** the attribute definitions */
 76  
     private Map attributes;
 77  
 
 78  
     /**
 79  
      *
 80  
      * @param beanClass Class of the bean that will receive the setter events
 81  
      * @param attributes
 82  
      * @param variableNameAttribute
 83  
      * @param method method of the Bean to invoke after the attributes have been set.  Can be null.
 84  
      */
 85  0
     public DynamicBeanTag(Class beanClass, Map attributes, String variableNameAttribute, Method method) {
 86  0
         this.beanClass = beanClass;
 87  0
         this.method = method;
 88  0
         this.attributes = attributes;
 89  0
         this.variableNameAttribute = variableNameAttribute;
 90  0
     }
 91  
 
 92  
     public void beforeSetAttributes() throws JellyTagException {
 93  
         // create a new dynabean before the attributes are set
 94  
         try {
 95  0
             bean = beanClass.newInstance();
 96  0
             setDynaBean( new ConvertingWrapDynaBean( bean ) );
 97  0
         } catch (InstantiationException e) {
 98  0
             throw new JellyTagException("Could not instantiate dynabean",e);
 99  
         } catch (IllegalAccessException e) {
 100  0
             throw new JellyTagException("Could not instantiate dynabean",e);
 101  
         }
 102  
 
 103  0
         setAttributesSet.clear();
 104  0
     }
 105  
 
 106  
     public void setAttribute(String name, Object value) throws JellyTagException {
 107  0
         boolean isVariableName = false;
 108  0
         if (variableNameAttribute != null ) {
 109  0
             if ( variableNameAttribute.equals( name ) ) {
 110  0
                 if (value == null) {
 111  0
                     var = null;
 112  
                 }
 113  
                 else {
 114  0
                     var = value.toString();
 115  
                 }
 116  0
                 isVariableName = true;
 117  
             }
 118  
         }
 119  0
         if (! isVariableName) {
 120  
 
 121  
             // #### strictly speaking we could
 122  
             // know what attributes are specified at compile time
 123  
             // so this dynamic set is unnecessary
 124  0
             setAttributesSet.add(name);
 125  
 
 126  
             // we could maybe implement attribute specific validation here
 127  
 
 128  0
             super.setAttribute(name, value);
 129  
         }
 130  0
     }
 131  
 
 132  
     // Tag interface
 133  
     //-------------------------------------------------------------------------
 134  
     public void doTag(XMLOutput output) throws JellyTagException {
 135  
 
 136  
         // lets find any attributes that are not set and
 137  0
         for ( Iterator iter = attributes.values().iterator(); iter.hasNext(); ) {
 138  0
             Attribute attribute = (Attribute) iter.next();
 139  0
             String name = attribute.getName();
 140  0
             if ( ! setAttributesSet.contains( name ) ) {
 141  0
                 if ( attribute.isRequired() ) {
 142  0
                     throw new MissingAttributeException(name);
 143  
                 }
 144  
                 // lets get the default value
 145  0
                 Object value = null;
 146  0
                 Expression expression = attribute.getDefaultValue();
 147  0
                 if ( expression != null ) {
 148  0
                     value = expression.evaluate(context);
 149  
                 }
 150  
 
 151  
                 // only set non-null values?
 152  0
                 if ( value != null ) {
 153  0
                     super.setAttribute(name, value);
 154  
                 }
 155  
             }
 156  
         }
 157  
 
 158  
         // If the dynamic bean is itself a tag, let it execute itself
 159  0
         if (bean instanceof Tag)
 160  
         {
 161  0
             Tag tag = (Tag) bean;
 162  0
             tag.setBody(getBody());
 163  0
             tag.setContext(getContext());
 164  0
             tag.setParent(getParent());
 165  0
             ((Tag) bean).doTag(output);
 166  
 
 167  0
             return;
 168  
         }
 169  
 
 170  0
         invokeBody(output);
 171  
 
 172  
         // export the bean if required
 173  0
         if ( var != null ) {
 174  0
             context.setVariable(var, bean);
 175  
         }
 176  
 
 177  
         // now, I may invoke the 'execute' method if I have one
 178  0
         if ( method != null ) {
 179  
             try {
 180  0
                 method.invoke( bean, emptyArgs );
 181  0
             }
 182  
             catch (IllegalAccessException e) {
 183  0
                 methodInvocationException(bean, method, e);
 184  0
             }
 185  
             catch (IllegalArgumentException e) {
 186  0
                 methodInvocationException(bean, method, e);
 187  0
             }
 188  
             catch (InvocationTargetException e) {
 189  
                 // methodInvocationError(bean, method, e);
 190  
 
 191  0
                 Throwable inner = e.getTargetException();
 192  
 
 193  0
                 throw new JellyTagException(inner);
 194  
 
 195  
             }
 196  
         }
 197  0
     }
 198  
 
 199  
     /**
 200  
      * Report the state of the bean when method invocation fails
 201  
      * so that the user can determine any problems that might
 202  
      * be occuring while using dynamic jelly beans.
 203  
      *
 204  
      * @param bean Bean on which <code>method</code was invoked
 205  
      * @param method Method that was invoked
 206  
      * @param e Exception throw when <code>method</code> was invoked
 207  
      */
 208  
     private void methodInvocationException(Object bean, Method method, Exception e) throws JellyTagException {
 209  0
         log.error("Could not invoke " + method, e);
 210  0
         BeanMap beanMap = new BeanMap(bean);
 211  
 
 212  0
         log.error("Bean properties:");
 213  0
         for (Iterator i = beanMap.keySet().iterator(); i.hasNext();) {
 214  0
             String property = (String) i.next();
 215  0
             Object value = beanMap.get(property);
 216  0
             log.error(property + " -> " + value);
 217  
         }
 218  
 
 219  0
         log.error(beanMap);
 220  0
         throw new JellyTagException(e);
 221  
     }
 222  
 
 223  
     // Properties
 224  
     //-------------------------------------------------------------------------
 225  
     /**
 226  
      * @return the bean that has just been created
 227  
      */
 228  
     public Object getBean() {
 229  0
         return bean;
 230  
     }
 231  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.