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.tobago.internal.taglib.component;
21  
22  import net.sf.maventaglib.checker.TagAttribute;
23  import net.sf.maventaglib.checker.Tld;
24  import net.sf.maventaglib.checker.TldParser;
25  import org.apache.commons.beanutils.PropertyUtils;
26  import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
27  import org.apache.myfaces.tobago.internal.mock.servlet.MockPageContext;
28  import org.junit.Assert;
29  import org.junit.Before;
30  import org.junit.Test;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  import org.w3c.dom.Document;
34  import org.xml.sax.EntityResolver;
35  import org.xml.sax.InputSource;
36  import org.xml.sax.SAXException;
37  
38  import javax.servlet.jsp.tagext.Tag;
39  import javax.xml.parsers.DocumentBuilder;
40  import javax.xml.parsers.DocumentBuilderFactory;
41  import java.beans.PropertyDescriptor;
42  import java.io.IOException;
43  import java.io.InputStream;
44  import java.lang.reflect.InvocationTargetException;
45  import java.util.HashMap;
46  
47  public abstract class GenericTestBase extends AbstractTobagoTestBase {
48  
49    private static final Logger LOG = LoggerFactory.getLogger(GenericTestBase.class);
50  
51    private Tld[] tlds;
52    private String[] tldPaths;
53  
54    @Before
55    public void setUp() throws Exception {
56      super.setUp();
57      tlds = new Tld[tldPaths.length];
58      for (int i = 0; i < tldPaths.length; i++) {
59        final InputStream stream = getClass().getClassLoader().getResourceAsStream(tldPaths[i]);
60        tlds[i] = getTld(tldPaths[i], stream);
61        stream.close();
62      }
63    }
64  
65    @Test
66    public void testRelease() throws IllegalAccessException,
67        NoSuchMethodException, InvocationTargetException, IOException,
68        SAXException, ClassNotFoundException, InstantiationException {
69      for (final Tld tld : tlds) {
70        for (final net.sf.maventaglib.checker.Tag tag : tld.getTags()) {
71          final Tag tagInstance = getTagInstance(tag);
72          checkRelease(tagInstance);
73        }
74      }
75    }
76  
77    @Test
78    public void testSetterExist() throws NoSuchMethodException,
79        IllegalAccessException, InvocationTargetException, IOException,
80        SAXException, ClassNotFoundException, InstantiationException {
81  
82      for (final Tld tld : tlds) {
83        for (final net.sf.maventaglib.checker.Tag tag : tld.getTags()) {
84          final Tag tagInstance = getTagInstance(tag);
85          final TagAttribute[] attributes = tag.getAttributes();
86          for (final TagAttribute attribute : attributes) {
87            final String name = attribute.getName();
88            checkSetter(tagInstance, name);
89          }
90        }
91      }
92    }
93  
94    protected Tag getTagInstance(final net.sf.maventaglib.checker.Tag tag)
95        throws ClassNotFoundException, InstantiationException, IllegalAccessException {
96      final String className = tag.getTagClass();
97      final Class tagClass = Class.forName(className);
98      return (Tag) tagClass.newInstance();
99    }
100 
101   private void checkSetter(final javax.servlet.jsp.tagext.Tag tagObject, final String name)
102       throws IllegalAccessException, InstantiationException,
103       NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
104     final PropertyDescriptor propertyDescriptor
105         = PropertyUtils.getPropertyDescriptor(tagObject, name);
106     Assert.assertNotNull("setter '" + name + "' of class " + tagObject.getClass().getName() + " has "
107         + "property descriptor.", propertyDescriptor);
108   }
109 
110   public void setTlds(final Tld[] tlds) {
111     this.tlds = tlds;
112   }
113 
114   public void setTldPaths(final String[] tldPaths) {
115     this.tldPaths = tldPaths;
116   }
117 
118   private void checkRelease(final javax.servlet.jsp.tagext.Tag tag) throws NoSuchMethodException,
119       IllegalAccessException, InvocationTargetException, IOException,
120       SAXException {
121     tag.setPageContext(new MockPageContext());
122 
123     final HashMap<String, Object> initialValues = new HashMap<String, Object>();
124     final PropertyDescriptor[] descriptors =
125         PropertyUtils.getPropertyDescriptors(tag);
126 
127     // store initial values
128     for (final PropertyDescriptor descriptor : descriptors) {
129       if (isTagProperty(descriptor)) {
130         final String name = descriptor.getName();
131         final Object value = PropertyUtils.getSimpleProperty(tag, name);
132         initialValues.put(name, value);
133       }
134     }
135 
136     // set new values
137     for (final PropertyDescriptor descriptor : descriptors) {
138       if (isTagProperty(descriptor)) {
139         final String name = descriptor.getName();
140         final Class propertyType = descriptor.getPropertyType();
141         Object value = null;
142         if (propertyType == String.class) {
143           value = new String("bla");
144         } else if (propertyType == Integer.TYPE) {
145           value = new Integer(42);
146         } else if (propertyType == Boolean.TYPE) {
147           value = Boolean.TRUE;
148         } else {
149           LOG.debug("Unsupported property type '" + propertyType
150               + "' for property '" + name + "'");
151         }
152         PropertyUtils.setSimpleProperty(tag, name, value);
153       }
154     }
155 
156     tag.release();
157 
158     // check released values
159     for (final PropertyDescriptor descriptor : descriptors) {
160       if (isTagProperty(descriptor)) {
161         final String name = descriptor.getName();
162         // XXX: who releases id?
163         if (name.equals("id")) {
164           continue;
165         }
166         try {
167           final Object newValue = PropertyUtils.getSimpleProperty(tag, name);
168           final Object oldValue = initialValues.get(name);
169           final String msg = "release of property '" + name + "' for tag '"
170               + tag.getClass().getName() + "' failed.";
171           Assert.assertEquals(msg, oldValue, newValue);
172           // XXX: first error stops loop
173           // if (newValue != null && !newValue.equals(oldValue)) {
174         } catch (final NoSuchMethodException e1) {
175           LOG.error("", e1);
176         }
177       }
178     }
179   }
180 
181   private boolean isTagProperty(final PropertyDescriptor descriptor) {
182     if ("parent".equals(descriptor.getName())) {
183       return false;
184     } else {
185       return descriptor.getReadMethod() != null
186           && descriptor.getWriteMethod() != null;
187     }
188   }
189 
190   private Tld getTld(final String name, final InputStream stream) throws Exception {
191     final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
192     final DocumentBuilder db = dbf.newDocumentBuilder();
193     db.setEntityResolver(new Resolver());
194     final Document doc = db.parse(stream);
195     return TldParser.parse(doc, name);
196   }
197 
198   private static class Resolver implements EntityResolver {
199     public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
200       final InputSource inputSource =
201           new InputSource(GenericTestBase.class.getResourceAsStream("/web-jsptaglibrary_1_2.dtd"));
202       inputSource.setSystemId(systemId);
203       return inputSource;
204     }
205   }
206 }