001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.beanutils.bugs;
018    
019    import junit.framework.TestCase;
020    import org.apache.commons.beanutils.PropertyUtils;
021    
022    import java.beans.PropertyDescriptor;
023    
024    
025    /*
026     * jdk's beans class do not work with covariant returns & generics.
027     * <p>
028     * See https://issues.apache.org/jira/browse/BEANUTILS-340
029     * See http://bugs.sun.com/view_bug.do?bug_id=6528714
030     * </p>
031     */
032    public class Jira340TestCase extends TestCase {
033    
034        public void testStub() {}
035    
036        /* these tests require java 5+ language level to compile and execute */
037    
038        public void testCovariantReturnPropertyUtils() throws Throwable {
039            assertEquals(InnerBean.class, PropertyUtils.getPropertyType(new Bean(), "innerBean"));
040            final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new Bean(), "innerBean");
041            assertEquals(InnerBean.class, d.getPropertyType());
042            assertEquals(InnerBean.class, d.getReadMethod().getReturnType());
043        }
044    
045        //this method will fail due to a java Introspector api bug
046        public void failing_testCovariantReturnIntrospector() throws Throwable {
047            java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(Bean.class);
048            final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors();
049            for (int i = 0; i < descriptors.length; i ++) {
050                if ("innerBean".equals(descriptors[i].getName())) {
051                    assertEquals(InnerBean.class, descriptors[i].getPropertyType());
052                    assertEquals(InnerBean.class, descriptors[i].getReadMethod().getReturnType());
053                }
054            }
055        }
056    
057        public void testGenericReadWritePropertyUtils() throws Throwable {
058            assertEquals(String.class, PropertyUtils.getPropertyType(new ReadWriteNamedBean(), "name"));
059    
060            final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new ReadWriteNamedBean(), "name");
061            assertEquals(String.class, d.getPropertyType());
062            assertEquals(String.class, d.getReadMethod().getReturnType());
063            assertEquals(String.class, d.getWriteMethod().getParameterTypes()[0]);
064        }
065    
066        //this method will fail due to a java Introspector api bug
067        public void failing_testGenericReadWriteIntrospector() throws Throwable {
068            java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(ReadWriteNamedBean.class);
069            final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors();
070            for (int i = 0; i < descriptors.length; i ++) {
071                if ("name".equals(descriptors[i].getName())) {
072                    assertEquals(String.class, descriptors[i].getPropertyType());
073                    assertEquals(String.class, descriptors[i].getReadMethod().getReturnType());
074                    assertEquals(String.class, descriptors[i].getWriteMethod().getParameterTypes()[0]);
075                }
076            }
077        }
078    
079        public void testGenericWritePropertyUtils() throws Throwable {
080            assertEquals(String.class, PropertyUtils.getPropertyType(new WriteNamedBean(), "name"));
081    
082            final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new WriteNamedBean(), "name");
083            assertEquals(String.class, d.getPropertyType());
084            assertEquals(String.class, d.getWriteMethod().getParameterTypes()[0]);
085        }
086    
087        //this method will fail due to a java Introspector api bug
088        public void failing_testGenericWriteIntrospector() throws Throwable {
089            java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(WriteNamedBean.class);
090            final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors();
091            for (int i = 0; i < descriptors.length; i ++) {
092                if ("name".equals(descriptors[i].getName())) {
093                    assertEquals(String.class, descriptors[i].getPropertyType());
094                    assertEquals(String.class, descriptors[i].getWriteMethod().getParameterTypes()[0]);
095                }
096            }
097        }
098    
099        public void testGenericReadPropertyUtils() throws Throwable {
100            assertEquals(String.class, PropertyUtils.getPropertyType(new ReadNamedBean(), "name"));
101    
102            final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new ReadNamedBean(), "name");
103            assertEquals(String.class, d.getPropertyType());
104            assertEquals(String.class, d.getReadMethod().getReturnType());
105        }
106    
107        //this method will fail due to a java Introspector api bug
108        public void failing_testGenericReadIntrospector() throws Throwable {
109            java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(WriteNamedBean.class);
110            final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors();
111            for (int i = 0; i < descriptors.length; i ++) {
112                if ("name".equals(descriptors[i].getName())) {
113                    assertEquals(String.class, descriptors[i].getPropertyType());
114                    assertEquals(String.class, descriptors[i].getReadMethod().getReturnType());
115                }
116            }
117        }
118    
119        public void testGenericWriteOverloadInheritPropertyUtils() throws Throwable {
120            //can't really assert a specific type b/c it's non-deterministic - just want to make sure things don't blow up
121            assertNotNull(PropertyUtils.getPropertyType(new WriteOverloadNamedBeanInherit(), "name"));
122    
123            final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new WriteOverloadNamedBeanInherit(), "name");
124            assertNotNull(d.getPropertyType());
125            assertNotNull(d.getWriteMethod().getParameterTypes()[0]);
126        }
127    
128        //this method will fail due to a java Introspector api bug
129        public void testGenericWriteOverloadInheritIntrospector() throws Throwable {
130            //can't really assert a specific type b/c it's non-deterministic - just want to make sure things don't blow up
131            java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(WriteOverloadNamedBeanInherit.class);
132            final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors();
133            for (int i = 0; i < descriptors.length; i ++) {
134                if ("name".equals(descriptors[i].getName())) {
135                    assertNotNull(descriptors[i].getPropertyType());
136                    assertNotNull(descriptors[i].getWriteMethod().getParameterTypes()[0]);
137                }
138            }
139        }
140    
141        public void testGenericWriteOverloadNonInheritPropertyUtils() throws Throwable {
142            //can't really assert a specific type b/c it's non-deterministic - just want to make sure things don't blow up
143            assertNotNull(PropertyUtils.getPropertyType(new WriteOverloadNamedBeanNonInherit(), "name"));
144    
145            final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new WriteOverloadNamedBeanNonInherit(), "name");
146            assertNotNull(d.getPropertyType());
147            assertNotNull(d.getWriteMethod().getParameterTypes()[0]);
148        }
149    
150        //this method will fail due to a java Introspector api bug
151        public void testGenericWriteOverloadNonInheritIntrospector() throws Throwable {
152            //can't really assert a specific type b/c it's non-deterministic - just want to make sure things don't blow up
153            java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(WriteOverloadNamedBeanNonInherit.class);
154            final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors();
155            for (int i = 0; i < descriptors.length; i ++) {
156                if ("name".equals(descriptors[i].getName())) {
157                    assertNotNull(descriptors[i].getPropertyType());
158                    assertNotNull(descriptors[i].getWriteMethod().getParameterTypes()[0]);
159                }
160            }
161        }
162    
163        public void testVisibilityBridge() throws Throwable {
164            assertEquals(String.class, PropertyUtils.getPropertyType(new PublicClass(), "foo"));
165        }
166    
167        //example 1 start
168        static class Bean implements Beanable {
169            private InnerBean innerBean = new InnerBean();
170    
171            public InnerBean getInnerBean() {
172                return innerBean;
173            }
174        }
175    
176        static interface Beanable {
177            InnerBeanable getInnerBean();
178        }
179    
180        static class InnerBean implements InnerBeanable {
181        }
182    
183        static interface InnerBeanable {
184        }
185        //example 1 end
186    
187        //example 2/3/4 start
188        static interface ReadNamed<T> {
189            T getName();
190        }
191    
192        static interface WriteNamed<T> {
193            void setName(T t);
194        }
195    
196        static class ReadWriteNamedBean implements ReadNamed<String>, WriteNamed<String> {
197            private String myName;
198    
199            public String getName() {
200                return myName;
201            }
202    
203            public void setName(String name) {
204                myName = name;
205            }
206        }
207    
208        static class WriteNamedBean implements WriteNamed<String> {
209            private String myName;
210            public void setName(String name) {
211                myName = name;
212            }
213        }
214    
215        static class ReadNamedBean implements ReadNamed<String> {
216            private final String myName = "foo";
217            public String getName() {
218                return myName;
219            }
220        }
221        //example 2/3/4 end
222    
223    
224        //example 5 start
225        //not using covariant return but still generating a bridge method on later java versions
226        static class PackagePrivateClass {
227            public String getFoo() { return null; }
228        }
229        public static class PublicClass extends PackagePrivateClass { }
230        //example 5 end
231    
232        //example 6 start
233        static class WriteOverloadNamedBeanInherit implements WriteNamed<String> {
234            private String myName;
235    
236            public void setName(String s) {
237                myName = s;
238            }
239    
240            public void setName(CharSequence s) {
241                myName = s.toString();
242            }
243        }
244        //example 6 end
245    
246        //example 7 start
247        static class WriteOverloadNamedBeanNonInherit implements WriteNamed<String> {
248            private String myName;
249    
250            public void setName(String s) {
251                myName = s;
252            }
253    
254            public void setName(Number s) {
255                myName = s.toString();
256            }
257        }
258        //example 7 end
259    }