1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jelly.tags.define;
18
19 import java.lang.reflect.Method;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.apache.commons.jelly.JellyTagException;
24 import org.apache.commons.jelly.MissingAttributeException;
25 import org.apache.commons.jelly.Tag;
26 import org.apache.commons.jelly.XMLOutput;
27 import org.apache.commons.jelly.impl.Attribute;
28 import org.apache.commons.jelly.impl.DynamicBeanTag;
29 import org.apache.commons.jelly.impl.TagFactory;
30 import org.apache.commons.jelly.util.ClassLoaderUtils;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import org.xml.sax.Attributes;
36
37 /***
38 * Binds a Java bean to the given named Jelly tag so that the attributes of
39 * the tag set the bean properties..
40 *
41 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
42 * @version $Revision: 155420 $
43 */
44 public class BeanTag extends DefineTagSupport {
45
46 /*** The Log to which logging calls will be made. */
47 private static final Log log = LogFactory.getLog(BeanTag.class);
48
49 /*** An empty Map as I think Collections.EMPTY_MAP is only JDK 1.3 onwards */
50 private static final Map EMPTY_MAP = new HashMap();
51
52 /*** the name of the tag to create */
53 private String name;
54
55 /*** the Java class name to use for the tag */
56 private String className;
57
58 /*** the ClassLoader used to load beans */
59 private ClassLoader classLoader;
60
61 /*** the name of the attribute used for the variable name */
62 private String varAttribute = "var";
63
64 /*** the attribute definitions for this dynamic tag */
65 private Map attributes;
66
67 /***
68 * Adds a new attribute definition to this dynamic tag
69 */
70 public void addAttribute(Attribute attribute) {
71 if ( attributes == null ) {
72 attributes = new HashMap();
73 }
74 attributes.put( attribute.getName(), attribute );
75 }
76
77
78
79 public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException {
80 invokeBody(output);
81
82 if (name == null) {
83 throw new MissingAttributeException("name");
84 }
85 if (className == null) {
86 throw new MissingAttributeException("className");
87 }
88
89 Class theClass = null;
90 try {
91 ClassLoader classLoader = getClassLoader();
92 theClass = ClassLoaderUtils.loadClass(className, getClassLoader(), getContext().getUseContextClassLoader(), getClass());
93 }
94 catch (ClassNotFoundException e) {
95 log.error( "Could not load class: " + className + " exception: " + e, e );
96 throw new JellyTagException(
97 "Could not find class: "
98 + className
99 + " using ClassLoader: "
100 + classLoader);
101 }
102
103 final Class beanClass = theClass;
104 final Method invokeMethod = getInvokeMethod( theClass );
105 final Map beanAttributes = (attributes != null) ? attributes : EMPTY_MAP;
106
107 TagFactory factory = new TagFactory() {
108 public Tag createTag(String name, Attributes attributes) {
109 return new DynamicBeanTag(beanClass, beanAttributes, varAttribute, invokeMethod);
110 }
111 };
112
113 getTagLibrary().registerBeanTag(name, factory);
114
115
116 attributes = null;
117 }
118
119
120
121
122
123 /***
124 * Sets the name of the tag to create
125 */
126 public void setName(String name) {
127 this.name = name;
128 }
129
130 /***
131 * Sets the Java class name to use for the tag
132 */
133 public void setClassName(String className) {
134 this.className = className;
135 }
136
137 /***
138 * Sets the ClassLoader to use to load the class.
139 * If no value is set then the current threads context class
140 * loader is used.
141 */
142 public void setClassLoader(ClassLoader classLoader) {
143 this.classLoader = classLoader;
144 }
145
146 /***
147 * @return the ClassLoader to use to load classes specified by this object,
148 * the thread context loader if the context flag is set, or the class used to load this class.
149 */
150 public ClassLoader getClassLoader() {
151 return ClassLoaderUtils.getClassLoader(classLoader, getContext().getUseContextClassLoader(), getClass());
152 }
153
154 /***
155 * Sets the name of the attribute used to define the bean variable that this dynamic
156 * tag will output its results as. This defaults to 'var' though this property
157 * can be used to change this if it conflicts with a bean property called 'var'.
158 */
159 public void setVarAttribute(String varAttribute) {
160 this.varAttribute = varAttribute;
161 }
162
163
164
165
166
167 /***
168 * Extracts the invoke method for the class if one is used.
169 */
170 protected Method getInvokeMethod( Class theClass ) {
171 return null;
172 }
173 }