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