KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > displaytag > tld > TldTest


1 package org.displaytag.tld;
2
3 import java.io.File JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.net.URL JavaDoc;
6 import java.util.ArrayList JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.List JavaDoc;
9
10 import javax.servlet.jsp.tagext.TagSupport JavaDoc;
11 import javax.xml.parsers.DocumentBuilder JavaDoc;
12 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
13
14 import junit.framework.TestCase;
15
16 import org.apache.commons.beanutils.PropertyUtils;
17 import org.apache.commons.lang.builder.ToStringBuilder;
18 import org.apache.commons.lang.builder.ToStringStyle;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.w3c.dom.Document JavaDoc;
22 import org.w3c.dom.Node JavaDoc;
23 import org.w3c.dom.NodeList JavaDoc;
24 import org.xml.sax.EntityResolver JavaDoc;
25 import org.xml.sax.InputSource JavaDoc;
26
27
28 /**
29  * Reads tlds and check tag classes for declared attributes. This simple reports missing/invalid setters in tag classes.
30  * Basic tests only, other tests are performed by the maven-taglib plugin.
31  * @author Fabrizio Giustina
32  * @version $Revision: 833 $ ($Author: fgiust $)
33  */

34 public class TldTest extends TestCase
35 {
36
37     /**
38      * logger.
39      */

40     private static Log log = LogFactory.getLog(TldTest.class);
41
42     /**
43      * @see junit.framework.TestCase#getName()
44      */

45     public String JavaDoc getName()
46     {
47         return getClass().getName() + "." + super.getName();
48     }
49
50     /**
51      * Check displaytag 1.2 dtd.
52      * @throws Exception any Exception generated during test.
53      */

54     public void testStandardTld() throws Exception JavaDoc
55     {
56         checkTld("/src/main/resources/META-INF/displaytag.tld");
57     }
58
59     /**
60      * Check displaytag EL dtd.
61      * @throws Exception any Exception generated during test.
62      */

63     public void testELTld() throws Exception JavaDoc
64     {
65         checkTld("/src/main/resources/META-INF/displaytag-el.tld");
66     }
67
68     /**
69      * Check the given tld. Assure then:
70      * <ul>
71      * <li>Any tag class is loadable</li>
72      * <li>the tag class has a setter for any of the declared attribute</li>
73      * <li>the type declared in the dtd for an attribute (if any) matches the type accepted by the getter</li>
74      * </ul>
75      * @param checkedTld path for the tld to check, relative to basedir.
76      * @throws Exception any Exception generated during test.
77      */

78     public void checkTld(String JavaDoc checkedTld) throws Exception JavaDoc
79     {
80
81         List JavaDoc tagsAttributes = getTagAttributeList(checkedTld);
82
83         List JavaDoc errors = new ArrayList JavaDoc();
84         Iterator JavaDoc iterator = tagsAttributes.iterator();
85         while (iterator.hasNext())
86         {
87             TagAttribute attribute = (TagAttribute) iterator.next();
88
89             if (log.isDebugEnabled())
90             {
91                 log.debug("testing " + attribute);
92             }
93             String JavaDoc className = attribute.getTagClass();
94             Class JavaDoc tagClass = null;
95             try
96             {
97                 tagClass = Class.forName(className);
98             }
99             catch (ClassNotFoundException JavaDoc e)
100             {
101                 errors.add("unable to find declared tag class [" + className + "]");
102                 continue;
103             }
104
105             if (!TagSupport JavaDoc.class.isAssignableFrom(tagClass))
106             {
107                 errors.add("Declared class [" + className + "] doesn't extend TagSupport");
108                 continue;
109             }
110
111             // load it
112
Object JavaDoc tagObject = null;
113             try
114             {
115                 tagObject = tagClass.newInstance();
116             }
117             catch (Throwable JavaDoc e)
118             {
119                 errors.add("unable to instantiate declared tag class [" + className + "]");
120                 continue;
121             }
122
123             if (!PropertyUtils.isWriteable(tagObject, attribute.getAttributeName()))
124             {
125                 errors.add("Setter for attribute [" + attribute.getAttributeName() + "] not found in " + className);
126                 continue;
127             }
128
129             Class JavaDoc propertyType = PropertyUtils.getPropertyType(tagObject, attribute.getAttributeName());
130
131             String JavaDoc tldType = attribute.getAttributeType();
132             if (tldType != null)
133             {
134                 Class JavaDoc tldTypeClass = getClassFromName(tldType);
135
136                 if (!propertyType.isAssignableFrom(tldTypeClass))
137                 {
138                     errors.add("Tag attribute ["
139                         + attribute.getAttributeName()
140                         + "] declared in tld as ["
141                         + tldType
142                         + "], class declare ["
143                         + propertyType.getName()
144                         + "]");
145                     continue;
146                 }
147
148             }
149
150         }
151
152         if (errors.size() > 0)
153         {
154             if (log.isInfoEnabled())
155             {
156                 log.info(errors.size() + " errors found in tag classes: " + errors);
157             }
158             fail(errors.size() + " errors found in tag classes: " + errors);
159         }
160     }
161
162     /**
163      * returns a class from its name, handling primitives.
164      * @param className clss name
165      * @return Class istantiated using Class.forName or the matching primitive.
166      */

167     private Class JavaDoc getClassFromName(String JavaDoc className)
168     {
169
170         Class JavaDoc tldTypeClass = null;
171
172         if ("int".equals(className))
173         {
174             tldTypeClass = int.class;
175         }
176         else if ("long".equals(className))
177         {
178             tldTypeClass = long.class;
179         }
180         else if ("double".equals(className))
181         {
182             tldTypeClass = double.class;
183         }
184         else if ("boolean".equals(className))
185         {
186             tldTypeClass = boolean.class;
187         }
188         else if ("char".equals(className))
189         {
190             tldTypeClass = char.class;
191         }
192         else if ("byte".equals(className))
193         {
194             tldTypeClass = byte.class;
195         }
196
197         if (tldTypeClass == null)
198         {
199             // not a primitive type
200
try
201             {
202                 tldTypeClass = Class.forName(className);
203             }
204             catch (ClassNotFoundException JavaDoc e)
205             {
206                 fail("unable to find class [" + className + "] declared in 'type' attribute");
207             }
208         }
209         return tldTypeClass;
210     }
211
212     /**
213      * Extract a list of attributes from tld.
214      * @param checkedTld path for the checked tld, relative to basedir.
215      * @return List of TagAttribute
216      * @throws Exception any Exception thrown during test
217      */

218     private List JavaDoc getTagAttributeList(String JavaDoc checkedTld) throws Exception JavaDoc
219     {
220
221         URL JavaDoc classDir = TldTest.class.getResource("TldTest.class");
222         String JavaDoc tldPath = classDir.getPath();
223
224         String JavaDoc baseWebappDir = tldPath.substring(0, tldPath.indexOf("target") - 1);
225         tldPath = baseWebappDir + checkedTld;
226         log.debug("tld found: " + tldPath);
227
228         File JavaDoc tldFile = new File JavaDoc(tldPath);
229         DocumentBuilder JavaDoc builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
230         builder.setEntityResolver(new ClasspathEntityResolver());
231         Document JavaDoc webXmlDoc = builder.parse(tldFile);
232
233         NodeList JavaDoc tagList = webXmlDoc.getElementsByTagName("tag");
234         List JavaDoc tagsAttributes = new ArrayList JavaDoc();
235
236         for (int i = 0; i < tagList.getLength(); i++)
237         {
238             Node JavaDoc tag = tagList.item(i);
239
240             // String tagclass = tag.getAttributes().getNamedItem("tag-class").getNodeValue();
241

242             NodeList JavaDoc tagAttributes = tag.getChildNodes();
243
244             String JavaDoc tagclass = null;
245             for (int k = 0; k < tagAttributes.getLength(); k++)
246             {
247                 Node JavaDoc tagAttribute = tagAttributes.item(k);
248
249                 // only handle 1.0 tlds
250
if ("tag-class".equals(tagAttribute.getNodeName()))
251                 {
252                     tagclass = tagAttribute.getChildNodes().item(0).getNodeValue();
253                     break;
254                 }
255
256             }
257
258             tagAttributes = tag.getChildNodes();
259             for (int k = 0; k < tagAttributes.getLength(); k++)
260             {
261                 Node JavaDoc tagAttribute = tagAttributes.item(k);
262                 if ("attribute".equals(tagAttribute.getNodeName()))
263                 {
264                     NodeList JavaDoc initParams = tagAttribute.getChildNodes();
265                     String JavaDoc attributeName = null;
266                     String JavaDoc attributeType = null;
267                     for (int z = 0; z < initParams.getLength(); z++)
268                     {
269                         Node JavaDoc initParam = initParams.item(z);
270                         if (initParam.getNodeType() != Node.TEXT_NODE && initParam.hasChildNodes())
271                         {
272                             if (initParam.getNodeName().equals("name"))
273                             {
274                                 attributeName = initParam.getFirstChild().getNodeValue();
275                             }
276                             else if (initParam.getNodeName().equals("type"))
277                             {
278                                 attributeType = initParam.getFirstChild().getNodeValue();
279                             }
280                         }
281                     }
282                     TagAttribute attribute = new TagAttribute();
283                     attribute.setTagClass(tagclass);
284                     attribute.setAttributeName(attributeName);
285                     attribute.setAttributeType(attributeType);
286                     tagsAttributes.add(attribute);
287                     if (log.isDebugEnabled())
288                     {
289                         log.debug(attribute);
290                     }
291                 }
292             }
293         }
294
295         return tagsAttributes;
296     }
297
298     /**
299      * Simple Entity resolver which looks in the classpath for dtds.
300      * @author Fabrizio Giustina
301      * @version $Revision: 833 $ ($Author: fgiust $)
302      */

303     public static class ClasspathEntityResolver implements EntityResolver JavaDoc
304     {
305
306         /**
307          * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String)
308          */

309         public InputSource JavaDoc resolveEntity(String JavaDoc publicID, String JavaDoc systemID)
310         {
311             if (systemID != null)
312             {
313                 String JavaDoc systemFileName = systemID;
314
315                 if (systemFileName.indexOf("/") > 0)
316                 {
317                     systemFileName = systemFileName.substring(systemFileName.lastIndexOf("/") + 1, systemFileName
318                         .length());
319                 }
320
321                 ClassLoader JavaDoc classLoader = getClass().getClassLoader();
322
323                 URL JavaDoc dtdURL = classLoader.getResource("javax/servlet/jsp/resources/" + systemFileName);
324
325                 if (dtdURL == null)
326                 {
327                     return null;
328                 }
329
330                 // Return local copy of the dtd
331
try
332                 {
333                     return new InputSource JavaDoc(dtdURL.openStream());
334                 }
335                 catch (IOException JavaDoc e)
336                 {
337                     // return null
338
}
339             }
340
341             // If no match, returning null makes process continue normally
342
return null;
343         }
344     }
345
346     /**
347      * Javabean representing a tag attribute.
348      * @author Fabrizio Giustina
349      * @version $Revision: 833 $ ($Author: fgiust $)
350      */

351     public static class TagAttribute
352     {
353
354         /**
355          * Tag class.
356          */

357         private String JavaDoc tagClass;
358
359         /**
360          * Attribute name.
361          */

362         private String JavaDoc attributeName;
363
364         /**
365          * Atttribute type (can be null).
366          */

367         private String JavaDoc attributeType;
368
369         /**
370          * @return Returns the attribute name.
371          */

372         public String JavaDoc getAttributeName()
373         {
374             return this.attributeName;
375         }
376
377         /**
378          * @param name attribute name.
379          */

380         public void setAttributeName(String JavaDoc name)
381         {
382             this.attributeName = name;
383         }
384
385         /**
386          * @return Returns the attributeType.
387          */

388         public String JavaDoc getAttributeType()
389         {
390             return this.attributeType;
391         }
392
393         /**
394          * @param type The attributeType to set.
395          */

396         public void setAttributeType(String JavaDoc type)
397         {
398             this.attributeType = type;
399         }
400
401         /**
402          * @return Returns the tagClass.
403          */

404         public String JavaDoc getTagClass()
405         {
406             return this.tagClass;
407         }
408
409         /**
410          * @param tagClassName name of the tag class
411          */

412         public void setTagClass(String JavaDoc tagClassName)
413         {
414             this.tagClass = tagClassName;
415         }
416
417         /**
418          * @see java.lang.Object#toString()
419          */

420         public String JavaDoc toString()
421         {
422             return new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).append("tagClass", this.tagClass).append(
423                 "attributeName",
424                 this.attributeName).append("attributeType", this.attributeType).toString();
425         }
426     }
427 }
Popular Tags