View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.commons.test;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import javax.xml.parsers.DocumentBuilder;
28  import javax.xml.parsers.DocumentBuilderFactory;
29  
30  import junit.framework.TestCase;
31  import net.sf.maventaglib.checker.Tag;
32  import net.sf.maventaglib.checker.TagAttribute;
33  import net.sf.maventaglib.checker.Tld;
34  import net.sf.maventaglib.checker.TldParser;
35  
36  import org.apache.commons.beanutils.PropertyUtils;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  import org.w3c.dom.Document;
40  import org.xml.sax.EntityResolver;
41  import org.xml.sax.InputSource;
42  import org.xml.sax.SAXException;
43  
44  /**
45   * Insures the following ...
46   * <ul>
47   * <li> Tag handlers have setters for all tag attributes</li>
48   * <li> All tag handlers are in the classpath</li>
49   * <li> Tag handlers do not appear in the TLD more than once</li>
50   * <li> Tag handler attributes do not occur mare than once</li>
51   * </ul>
52   * 
53   * @author Dennis Byrne
54   * @see http://maven-taglib.sourceforge.net/ for dependency download
55   */
56  
57  public abstract class AbstractTagLibTestCase extends TestCase
58  {
59      private static Log log = LogFactory.getLog(AbstractTagLibTestCase.class);
60  
61      protected Tld[] tlds;
62  
63      protected String[] tldPaths;
64  
65      private ClassLoader classLoader = getClass().getClassLoader();
66  
67      /**
68       * Unmarshall TLDs to an object model. TLDs are supplied by a subclass.
69       */
70  
71      protected void setUp() throws Exception
72      {
73  
74          if (tldPaths == null)
75              throw new NullPointerException(
76                      "tldPaths cannot point to null before setUp() is called");
77  
78          int length = tldPaths.length;
79  
80          if (length == 0)
81              throw new IllegalStateException(
82                      "tldPaths should have at least one resource path");
83  
84          tlds = new Tld[length];
85  
86          for (int t = 0; t < length; t++)
87          {
88              String name = tldPaths[t];
89  
90              InputStream stream = classLoader.getResourceAsStream(name);
91  
92              if (stream == null)
93                  throw new NullPointerException(
94                          "couldn't get an input stream for " + name);
95  
96              tlds[t] = TldTestUtils.getTld(name, stream);
97              stream.close();
98          }
99      }
100 
101     public void testUniqueTagTestCase() throws Exception
102     {
103 
104         for (int lib = 0; lib < tlds.length; lib++)
105         {
106             Tld tld = tlds[lib];
107             List tagNames = new ArrayList();
108             Tag[] tags = tld.getTags();
109 
110             for (int t = 0; t < tags.length; t++)
111             {
112                 Tag tag = tags[t];
113 
114                 if (tag == null)
115                     throw new NullPointerException("tag");
116 
117                 String name = tag.getName();
118                 String msg = name + " found more than once in " + tldPaths[lib];
119                 assertFalse(msg, tagNames.contains(name));
120                 tagNames.add(name);
121             } // end t
122         } // end lib
123     }
124 
125     public void testUniqueTagAttributes() throws Exception
126     {
127 
128         for (int lib = 0; lib < tlds.length; lib++)
129         {
130             Tld tld = tlds[lib];
131             Tag[] tags = tld.getTags();
132 
133             for (int t = 0; t < tags.length; t++)
134             {
135 
136                 Tag tag = tags[t];
137                 assertUniqueTagAttributes(tag, tldPaths[lib]);
138 
139             } // end t
140         } // end lib
141     }
142 
143     private void assertUniqueTagAttributes(final Tag tag, final String path)
144     {
145 
146         List attributeNames = new ArrayList();
147         TagAttribute[] atts = tag.getAttributes();
148         String tagName = tag.getName();
149 
150         for (int a = 0; a < atts.length;)
151         {
152 
153             TagAttribute att = atts[a++];
154             String name = att.getAttributeName();
155             String msg = " @" + name + " of " + path + ":" + tagName
156                     + " is duplicated.";
157             assertFalse(msg, attributeNames.contains(name));
158             attributeNames.add(name);
159 
160         } // end a
161 
162     }
163 
164     /**
165      * Make sure the class exists. Make sure there is a setter for each
166      * attribute.
167      */
168 
169     public void testSetters() throws Exception
170     {
171 
172         for (int t = 0; t < tlds.length; t++)
173         {
174             Tld tld = tlds[t];
175             Tag[] tags = tld.getTags();
176 
177             for (int s = 0; s < tags.length; s++)
178             {
179                 Tag tag = tags[s];
180                 String filename = tld.getFilename();
181 
182                 Object object = TldTestUtils.makeTagClassInstance(tag,
183                         filename, classLoader);
184                 log.debug("filename = " + filename + " ; tag = "
185                         + tag.getName());
186                 assertSetters(tag, filename, object);
187 
188             } // end for tag
189         } // end for lib
190 
191     }
192 
193     private void assertSetters(final Tag tag, final String path,
194             final Object object)
195     {
196 
197         TagAttribute[] attributes = tag.getAttributes();
198         String tagName = tag.getName();
199 
200         for (int a = 0; a < attributes.length; a++)
201         {
202             TagAttribute attribute = attributes[a];
203             String name = attribute.getAttributeName();
204 
205             if (name == null || "".equals(name.trim()))
206                 throw new IllegalStateException(path + ":" + tagName
207                         + " has a nameless attribute ");
208 
209             String msg = path + ":" + tagName + "@" + name + " exists, but "
210                     + object.getClass().getName() + " has no setter.";
211 
212             assertTrue(msg, PropertyUtils.isWriteable(object, name));
213         } // end for attributes
214 
215     }
216     
217     private static class DelegateEntityResolver implements EntityResolver
218     {
219         private EntityResolver _delegate;
220 
221         public DelegateEntityResolver(EntityResolver delegate)
222         {
223             this._delegate = delegate;
224         }
225 
226         public InputSource resolveEntity(String publicId, String systemId)
227                 throws SAXException, IOException
228         {
229             if (publicId.equals("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"))
230             {
231                 return new InputSource(Thread.currentThread()
232                         .getContextClassLoader().getResourceAsStream(
233                                 "META-INF/dtd/web-jsptaglibrary_1_2.dtd"));
234             }
235             else
236             {
237                 return _delegate.resolveEntity(publicId, systemId);
238             }
239         }
240     }    
241 
242     private static class TldTestUtils
243     {
244         private static Log log = LogFactory.getLog(TldTestUtils.class);
245 
246         private static DocumentBuilderFactory dbf = DocumentBuilderFactory
247                 .newInstance();
248         static
249         {
250             dbf.setNamespaceAware(false);
251             dbf.setValidating(false);
252         }
253 
254         public static Tld getTld(String name, InputStream stream)
255                 throws Exception
256         {
257             if (stream == null)
258                 log.error(" input stream is null ");
259 
260             DocumentBuilder db = dbf.newDocumentBuilder();
261             db.setEntityResolver(new DelegateEntityResolver(null));
262             Document doc = db.parse(stream);
263 
264             return TldParser.parse(doc, name);
265         }
266 
267         public static Object makeTagClassInstance(Tag tag, String filename,
268                 ClassLoader classLoader) throws Exception
269         {
270 
271             String clazzName = tag.getTagClass();
272 
273             if (clazzName == null || "".equals(clazzName.trim()))
274                 throw new NullPointerException(tag.getName()
275                         + " is missing a tag class.");
276 
277             try
278             {
279 
280                 Class clazz = classLoader.loadClass(clazzName);
281                 return clazz.newInstance();
282 
283             }
284             catch (ClassNotFoundException e)
285             {
286                 throw new ClassNotFoundException(clazzName);
287             }
288             catch (IllegalAccessException ie)
289             {
290                 throw new IllegalAccessException(clazzName);
291             }
292             catch (InstantiationException iste)
293             {
294                 throw new InstantiationException(clazzName);
295             }
296         }
297     }
298 }