1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.beanutils.bugs; 18 19 import junit.framework.TestCase; 20 import org.apache.commons.beanutils.PropertyUtils; 21 22 import java.beans.PropertyDescriptor; 23 24 25 /** 26 * jdk's beans class do not work with covariant returns & generics. 27 * <p> 28 * See https://issues.apache.org/jira/browse/BEANUTILS-340 29 * See http://bugs.sun.com/view_bug.do?bug_id=6528714 30 * </p> 31 */ 32 public class Jira340TestCase extends TestCase { 33 34 public void testStub() {} 35 36 /* these tests require java 5+ language level to compile and execute 37 38 public void testCovariantReturnPropertyUtils() throws Throwable { 39 assertEquals(InnerBean.class, PropertyUtils.getPropertyType(new Bean(), "innerBean")); 40 final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new Bean(), "innerBean"); 41 assertEquals(InnerBean.class, d.getPropertyType()); 42 assertEquals(InnerBean.class, d.getReadMethod().getReturnType()); 43 } 44 45 //this method will fail due to a java Introspector api bug 46 public void failing_testCovariantReturnIntrospector() throws Throwable { 47 java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(Bean.class); 48 final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors(); 49 for (int i = 0; i < descriptors.length; i ++) { 50 if ("innerBean".equals(descriptors[i].getName())) { 51 assertEquals(InnerBean.class, descriptors[i].getPropertyType()); 52 assertEquals(InnerBean.class, descriptors[i].getReadMethod().getReturnType()); 53 } 54 } 55 } 56 57 public void testGenericReadWritePropertyUtils() throws Throwable { 58 assertEquals(String.class, PropertyUtils.getPropertyType(new ReadWriteNamedBean(), "name")); 59 60 final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new ReadWriteNamedBean(), "name"); 61 assertEquals(String.class, d.getPropertyType()); 62 assertEquals(String.class, d.getReadMethod().getReturnType()); 63 assertEquals(String.class, d.getWriteMethod().getParameterTypes()[0]); 64 } 65 66 //this method will fail due to a java Introspector api bug 67 public void failing_testGenericReadWriteIntrospector() throws Throwable { 68 java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(ReadWriteNamedBean.class); 69 final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors(); 70 for (int i = 0; i < descriptors.length; i ++) { 71 if ("name".equals(descriptors[i].getName())) { 72 assertEquals(String.class, descriptors[i].getPropertyType()); 73 assertEquals(String.class, descriptors[i].getReadMethod().getReturnType()); 74 assertEquals(String.class, descriptors[i].getWriteMethod().getParameterTypes()[0]); 75 } 76 } 77 } 78 79 public void testGenericWritePropertyUtils() throws Throwable { 80 assertEquals(String.class, PropertyUtils.getPropertyType(new WriteNamedBean(), "name")); 81 82 final PropertyDescriptor d = PropertyUtils.getPropertyDescriptor(new WriteNamedBean(), "name"); 83 assertEquals(String.class, d.getPropertyType()); 84 assertEquals(String.class, d.getWriteMethod().getParameterTypes()[0]); 85 } 86 87 //this method will fail due to a java Introspector api bug 88 public void failing_testGenericWriteIntrospector() throws Throwable { 89 java.beans.BeanInfo bi = java.beans.Introspector.getBeanInfo(WriteNamedBean.class); 90 final PropertyDescriptor[] descriptors = bi.getPropertyDescriptors(); 91 for (int i = 0; i < descriptors.length; i ++) { 92 if ("name".equals(descriptors[i].getName())) { 93 assertEquals(String.class, descriptors[i].getPropertyType()); 94 assertEquals(String.class, descriptors[i].getWriteMethod().getParameterTypes()[0]); 95 } 96 } 97 } 98 99 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 */ 260 }