diff --git a/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseGenerator.java b/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseGenerator.java index 1d11fdd..61efa8e 100644 --- a/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseGenerator.java +++ b/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseGenerator.java @@ -15,11 +15,11 @@ */ package com.rometools.modules.base.io; -import java.beans.PropertyDescriptor; import java.net.URL; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.jdom2.Element; @@ -40,6 +40,7 @@ import com.rometools.modules.base.types.ShippingType; import com.rometools.modules.base.types.ShortDate; import com.rometools.modules.base.types.Size; import com.rometools.modules.base.types.YearType; +import com.rometools.rome.feed.impl.PropertyDescriptor; import com.rometools.rome.feed.module.Module; import com.rometools.rome.io.ModuleGenerator; @@ -68,7 +69,7 @@ public class GoogleBaseGenerator implements ModuleGenerator { public void generate(final Module module, final Element element) { final GoogleBaseImpl mod = (GoogleBaseImpl) module; final HashMap props2tags = new HashMap(GoogleBaseParser.PROPS2TAGS); - final PropertyDescriptor[] pds = GoogleBaseParser.pds; + final List pds = GoogleBaseParser.pds; for (final PropertyDescriptor pd : pds) { final String tagName = (String) props2tags.get(pd.getName()); diff --git a/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseParser.java b/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseParser.java index c6cfa63..f7c5e8e 100644 --- a/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseParser.java +++ b/rome-modules/src/main/java/com/rometools/modules/base/io/GoogleBaseParser.java @@ -15,9 +15,6 @@ */ package com.rometools.modules.base.io; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; import java.io.IOException; import java.lang.reflect.Array; import java.net.URL; @@ -46,6 +43,8 @@ import com.rometools.modules.base.types.PriceTypeEnumeration; import com.rometools.modules.base.types.ShippingType; import com.rometools.modules.base.types.Size; import com.rometools.modules.base.types.YearType; +import com.rometools.rome.feed.impl.BeanIntrospector; +import com.rometools.rome.feed.impl.PropertyDescriptor; import com.rometools.rome.feed.module.Module; import com.rometools.rome.io.ModuleParser; @@ -59,16 +58,19 @@ public class GoogleBaseParser implements ModuleParser { public static final SimpleDateFormat LONG_DT_FMT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); static final Namespace NS = Namespace.getNamespace(GoogleBase.URI); static final Properties PROPS2TAGS = new Properties(); - static PropertyDescriptor[] pds = null; + static List pds = null; static { try { - pds = Introspector.getBeanInfo(GoogleBaseImpl.class).getPropertyDescriptors(); + pds = BeanIntrospector.getPropertyDescriptorsWithGetters(GoogleBaseImpl.class); + } catch (final IllegalArgumentException e) { + LOG.error("Failed to get property descriptors for GoogleBaseImpl", e); + } + + try { PROPS2TAGS.load(GoogleBaseParser.class.getResourceAsStream("/com/rometools/modules/base/io/tags.properties")); } catch (final IOException e) { LOG.error("Unable to read properties file for Google Base tags!", e); - } catch (final IntrospectionException e) { - LOG.error("Unable to get property descriptors for GoogleBaseImpl!", e); } } diff --git a/rome-modules/src/test/java/com/rometools/modules/AbstractTestCase.java b/rome-modules/src/test/java/com/rometools/modules/AbstractTestCase.java index 699b5bd..7351743 100644 --- a/rome-modules/src/test/java/com/rometools/modules/AbstractTestCase.java +++ b/rome-modules/src/test/java/com/rometools/modules/AbstractTestCase.java @@ -15,11 +15,7 @@ */ package com.rometools.modules; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; import java.io.File; -import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import junit.framework.TestCase; @@ -50,73 +46,6 @@ public abstract class AbstractTestCase extends TestCase { } } - /** - * This method takes a JavaBean and generates a standard toString() type result for it. - * - * @param o JavaBean object to stringinate - * @return STRINGIATION! Stringingating the countryside. Stringinating all the peasants. - */ - public static String beanToString(final Object o, final boolean showNulls) { - final StringBuffer result = new StringBuffer(); - - if (o == null) { - return "--- null"; - } - - result.append("--- begin"); - result.append(o.getClass().getName()); - result.append(" hash: "); - result.append(o.hashCode()); - result.append("\r\n"); - - try { - final PropertyDescriptor[] pds = Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors(); - - for (final PropertyDescriptor pd : pds) { - String out = ""; - - try { - final Object value = pd.getReadMethod().invoke(o, (Object[]) null); - - if (value != null && value.getClass().isArray()) { - final Object[] values = (Object[]) value; - - for (final Object value2 : values) { - out += value2 + " "; - } - } else { - out += value; - } - - if (!out.equals("null") || showNulls) { - result.append("Property: " + pd.getName() + " Value: " + out); - } - } catch (final IllegalAccessException iae) { - result.append("Property: " + pd.getName() + " (Illegal Access to Value) "); - } catch (final InvocationTargetException iae) { - result.append("Property: " + pd.getName() + " (InvocationTargetException) " + iae.toString()); - } catch (final Exception e) { - result.append("Property: " + pd.getName() + " (Other Exception )" + e.toString()); - } - - if (!out.equals("null") || showNulls) { - result.append("\r\n"); - } - } - } catch (final IntrospectionException ie) { - result.append("Introspection Exception: " + ie.toString()); - result.append("\r\n"); - } - - result.append("--- end "); - result.append(o.getClass().getName()); - result.append(" hash: "); - result.append(o.hashCode()); - result.append("\n"); - - return result.toString(); - } - public boolean assertEquals(final String message, final Object[] control, final Object[] test) { if (control == null && test == null) { return true; diff --git a/rome-modules/src/test/java/com/rometools/modules/base/io/GoogleBaseParserTest.java b/rome-modules/src/test/java/com/rometools/modules/base/io/GoogleBaseParserTest.java index 29be8e4..ea67d47 100644 --- a/rome-modules/src/test/java/com/rometools/modules/base/io/GoogleBaseParserTest.java +++ b/rome-modules/src/test/java/com/rometools/modules/base/io/GoogleBaseParserTest.java @@ -71,45 +71,6 @@ public class GoogleBaseParserTest extends AbstractTestCase { return suite; } - /** - * Test of parse method, of class com.totsp.xml.syndication.base.io.GoogleBaseParser. - */ - public void testQuickParse() throws Exception { - try { - LOG.debug("testParse"); - final SyndFeedInput input = new SyndFeedInput(); - final File testDir = new File(super.getTestFile("xml")); - final File[] testFiles = testDir.listFiles(); - for (int h = 0; h < testFiles.length; h++) { - if (!testFiles[h].getName().endsWith(".xml")) { - continue; - } - SyndFeed feed = null; - try { - feed = input.build(testFiles[h]); - } catch (final Exception e) { - throw new RuntimeException(testFiles[h].getAbsolutePath(), e); - } - final List entries = feed.getEntries(); - for (int i = 0; i < entries.size(); i++) { - final SyndEntry entry = entries.get(i); - LOG.debug("{}", entry.getModules().size()); - for (int j = 0; j < entry.getModules().size(); j++) { - LOG.debug("{}", entry.getModules().get(j).getClass()); - if (entry.getModules().get(j) instanceof GoogleBase) { - final GoogleBase base = (GoogleBase) entry.getModules().get(j); - LOG.debug(testFiles[h].getName()); - LOG.debug(super.beanToString(base, false)); - } - } - } - } - } catch (final Exception e) { - e.printStackTrace(); - throw e; - } - } - /** * Test of parse method, of class com.totsp.xml.syndication.base.io.GoogleBaseParser. */ diff --git a/rome-modules/src/test/java/com/rometools/modules/yahooweather/io/WeatherModuleParserTest.java b/rome-modules/src/test/java/com/rometools/modules/yahooweather/io/WeatherModuleParserTest.java index 42335bb..a4bb743 100644 --- a/rome-modules/src/test/java/com/rometools/modules/yahooweather/io/WeatherModuleParserTest.java +++ b/rome-modules/src/test/java/com/rometools/modules/yahooweather/io/WeatherModuleParserTest.java @@ -80,7 +80,6 @@ public class WeatherModuleParserTest extends AbstractTestCase { final YWeatherModule base = (YWeatherModule) entry.getModules().get(j); assertTrue(((YWeatherEntryModule) base).getForecasts().length > 0); LOG.debug(testFiles[h].getName()); - LOG.debug(super.beanToString(base, false)); final YWeatherEntryModule module2 = new YWeatherModuleImpl(); module2.copyFrom(base); diff --git a/rome/src/main/java/com/rometools/rome/feed/impl/BeanIntrospector.java b/rome/src/main/java/com/rometools/rome/feed/impl/BeanIntrospector.java index 774d080..4ac1b0e 100644 --- a/rome/src/main/java/com/rometools/rome/feed/impl/BeanIntrospector.java +++ b/rome/src/main/java/com/rometools/rome/feed/impl/BeanIntrospector.java @@ -16,9 +16,6 @@ */ package com.rometools.rome.feed.impl; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -50,10 +47,8 @@ public class BeanIntrospector { * @param clazz The class to extract the desired {@link PropertyDescriptor}s from * @return All {@link PropertyDescriptor} for properties with getters and setters for the given * class. - * @throws IntrospectionException When the extraction of the desired {@link PropertyDescriptor}s - * failed */ - private static synchronized PropertyDescriptor[] getPropertyDescriptors(final Class clazz) throws IntrospectionException { + private static synchronized PropertyDescriptor[] getPropertyDescriptors(final Class clazz) { PropertyDescriptor[] descriptors = introspected.get(clazz); if (descriptors == null) { descriptors = getPDs(clazz); @@ -69,10 +64,8 @@ public class BeanIntrospector { * @param clazz The class to extract the desired {@link PropertyDescriptor}s from * @return All {@link PropertyDescriptor}s for properties with a getter that does not come from * {@link Object} and does not accept parameters. - * @throws IntrospectionException When the extraction of the desired {@link PropertyDescriptor}s - * failed */ - public static List getPropertyDescriptorsWithGetters(final Class clazz) throws IntrospectionException { + public static List getPropertyDescriptorsWithGetters(final Class clazz) { final List relevantDescriptors = new ArrayList(); @@ -108,10 +101,8 @@ public class BeanIntrospector { * @param clazz The class to extract the desired {@link PropertyDescriptor}s from * @return All {@link PropertyDescriptor}s for properties with a getter (that does not come from * {@link Object} and does not accept parameters) and a setter. - * @throws IntrospectionException When the extraction of the desired {@link PropertyDescriptor}s - * failed */ - public static List getPropertyDescriptorsWithGettersAndSetters(final Class clazz) throws IntrospectionException { + public static List getPropertyDescriptorsWithGettersAndSetters(final Class clazz) { final List relevantDescriptors = new ArrayList(); @@ -131,7 +122,7 @@ public class BeanIntrospector { } - private static PropertyDescriptor[] getPDs(final Class clazz) throws IntrospectionException { + private static PropertyDescriptor[] getPDs(final Class clazz) { final Method[] methods = clazz.getMethods(); final Map getters = getPDs(methods, false); final Map setters = getPDs(methods, true); @@ -139,7 +130,7 @@ public class BeanIntrospector { return propertyDescriptors.toArray(new PropertyDescriptor[propertyDescriptors.size()]); } - private static Map getPDs(final Method[] methods, final boolean setters) throws IntrospectionException { + private static Map getPDs(final Method[] methods, final boolean setters) { final Map pds = new HashMap(); @@ -157,15 +148,15 @@ public class BeanIntrospector { if (setters) { if (methodName.startsWith(SETTER) && returnType == void.class && nrOfParameters == 1) { - propertyName = Introspector.decapitalize(methodName.substring(3)); + propertyName = decapitalize(methodName.substring(3)); propertyDescriptor = new PropertyDescriptor(propertyName, null, method); } } else { if (methodName.startsWith(GETTER) && returnType != void.class && nrOfParameters == 0) { - propertyName = Introspector.decapitalize(methodName.substring(3)); + propertyName = decapitalize(methodName.substring(3)); propertyDescriptor = new PropertyDescriptor(propertyName, method, null); } else if (methodName.startsWith(BOOLEAN_GETTER) && returnType == boolean.class && nrOfParameters == 0) { - propertyName = Introspector.decapitalize(methodName.substring(2)); + propertyName = decapitalize(methodName.substring(2)); propertyDescriptor = new PropertyDescriptor(propertyName, method, null); } } @@ -181,8 +172,7 @@ public class BeanIntrospector { } - private static List merge(final Map getters, final Map setters) - throws IntrospectionException { + private static List merge(final Map getters, final Map setters) { final List props = new ArrayList(); final Set processedProps = new HashSet(); @@ -210,4 +200,16 @@ public class BeanIntrospector { return props; } + /** + * Make first character lower case unless the second character is upper case. + */ + private static String decapitalize(String name) { + if (name.isEmpty() || (name.length() > 1 && Character.isUpperCase(name.charAt(1)))) { + return name; + } + + char[] chars = name.toCharArray(); + chars[0] = Character.toLowerCase(chars[0]); + return new String(chars); + } } diff --git a/rome/src/main/java/com/rometools/rome/feed/impl/CloneableBean.java b/rome/src/main/java/com/rometools/rome/feed/impl/CloneableBean.java index 27e35bb..e20ab42 100644 --- a/rome/src/main/java/com/rometools/rome/feed/impl/CloneableBean.java +++ b/rome/src/main/java/com/rometools/rome/feed/impl/CloneableBean.java @@ -16,7 +16,6 @@ */ package com.rometools.rome.feed.impl; -import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Method; diff --git a/rome/src/main/java/com/rometools/rome/feed/impl/CopyFromHelper.java b/rome/src/main/java/com/rometools/rome/feed/impl/CopyFromHelper.java index bbc8c9e..e44e070 100644 --- a/rome/src/main/java/com/rometools/rome/feed/impl/CopyFromHelper.java +++ b/rome/src/main/java/com/rometools/rome/feed/impl/CopyFromHelper.java @@ -16,7 +16,6 @@ */ package com.rometools.rome.feed.impl; -import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.ArrayList; diff --git a/rome/src/main/java/com/rometools/rome/feed/impl/EqualsBean.java b/rome/src/main/java/com/rometools/rome/feed/impl/EqualsBean.java index b301b15..14f95b5 100644 --- a/rome/src/main/java/com/rometools/rome/feed/impl/EqualsBean.java +++ b/rome/src/main/java/com/rometools/rome/feed/impl/EqualsBean.java @@ -16,7 +16,6 @@ */ package com.rometools.rome.feed.impl; -import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Method; diff --git a/rome/src/main/java/com/rometools/rome/feed/impl/PropertyDescriptor.java b/rome/src/main/java/com/rometools/rome/feed/impl/PropertyDescriptor.java new file mode 100644 index 0000000..8debcb8 --- /dev/null +++ b/rome/src/main/java/com/rometools/rome/feed/impl/PropertyDescriptor.java @@ -0,0 +1,105 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This class was copied from OpenBeans (Apache Harmony) and modified to + * avoid using java.beans package, because it is not available on some + * platforms (Android in particular). + */ + +package com.rometools.rome.feed.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class PropertyDescriptor { + + private final String name; + private final Method getter; + private final Method setter; + + public PropertyDescriptor(String name, Method getter, Method setter) { + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException("Bad property name"); + } + + this.name = name; + this.getter = checkGetter(getter); + this.setter = checkSetter(setter); + } + + public String getName() { + return name; + } + + public Method getReadMethod() { + return getter; + } + + public Method getWriteMethod() { + return setter; + } + + public Class getPropertyType() { + if (getter != null) { + return getter.getReturnType(); + } else if (setter != null) { + Class[] parameterTypes = setter.getParameterTypes(); + return parameterTypes[0]; + } else { + return null; + } + } + + private Method checkGetter(Method method) { + if (method != null) { + int modifiers = method.getModifiers(); + if (!Modifier.isPublic(modifiers)) { + throw new IllegalArgumentException("Modifier for getter method should be public"); + } + Class[] parameterTypes = method.getParameterTypes(); + if (parameterTypes.length != 0) { + throw new IllegalArgumentException("Number of parameters in getter method is not equal to 0"); + } + Class returnType = method.getReturnType(); + if (returnType.equals(Void.TYPE)) { + throw new IllegalArgumentException("Getter has return type void"); + } + Class propertyType = getPropertyType(); + if (propertyType != null && !returnType.equals(propertyType)) { + throw new IllegalArgumentException("Parameter type in getter does not correspond to setter"); + } + } + return method; + } + + private Method checkSetter(Method method) { + if (method != null) { + int modifiers = method.getModifiers(); + if (!Modifier.isPublic(modifiers)) { + throw new IllegalArgumentException("Modifier for setter method should be public"); + } + Class[] parameterTypes = method.getParameterTypes(); + if (parameterTypes.length != 1) { + throw new IllegalArgumentException("Number of parameters in setter method is not equal to 1"); + } + Class parameterType = parameterTypes[0]; + Class propertyType = getPropertyType(); + if (propertyType != null && !propertyType.equals(parameterType)) { + throw new IllegalArgumentException("Parameter type in setter does not correspond to getter"); + } + } + return method; + } +} diff --git a/rome/src/main/java/com/rometools/rome/feed/impl/ToStringBean.java b/rome/src/main/java/com/rometools/rome/feed/impl/ToStringBean.java index d1ec50d..4ff9bce 100644 --- a/rome/src/main/java/com/rometools/rome/feed/impl/ToStringBean.java +++ b/rome/src/main/java/com/rometools/rome/feed/impl/ToStringBean.java @@ -16,7 +16,6 @@ */ package com.rometools.rome.feed.impl; -import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Method;