001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.messaging.amf.io.util;
022
023 import java.beans.BeanInfo;
024 import java.beans.Introspector;
025 import java.beans.PropertyDescriptor;
026 import java.lang.reflect.Field;
027 import java.lang.reflect.Modifier;
028 import java.util.ArrayList;
029 import java.util.HashSet;
030 import java.util.Hashtable;
031 import java.util.List;
032 import java.util.Map;
033 import java.util.Set;
034
035 /**
036 * @author Franck WOLFF
037 */
038 public class DefaultGroovyClassDescriptor extends JavaClassDescriptor {
039
040 public DefaultGroovyClassDescriptor(Class<?> type) {
041 super(type);
042 }
043
044 @Override
045 protected List<Property> introspectProperties() {
046 List<Property> properties = null;
047 Class<?> type = getType();
048
049 if (!isExternalizable() && !Map.class.isAssignableFrom(type) && !Hashtable.class.isAssignableFrom(type)) {
050 properties = new ArrayList<Property>();
051
052 try {
053 Set<String> propertyNames = new HashSet<String>();
054
055 // Add read/write properties (ie: public getter/setter).
056 Introspector.flushFromCaches(type); // Ensure that we don't get a cached reference, the Groovy class could have been modified
057 BeanInfo info = Introspector.getBeanInfo(type);
058 for (PropertyDescriptor property : info.getPropertyDescriptors()) {
059 String propertyName = property.getName();
060 if (property.getWriteMethod() != null && property.getReadMethod() != null) {
061 properties.add(new MethodProperty(converters, propertyName, property.getWriteMethod(), property.getReadMethod()));
062 propertyNames.add(propertyName);
063 }
064 }
065
066 // Add other public fields.
067 Field[] fields = type.getFields();
068 for (Field field : fields) {
069 String propertyName = field.getName();
070 if (!propertyNames.contains(propertyName) &&
071 !Modifier.isStatic(field.getModifiers()) &&
072 !Modifier.isTransient(field.getModifiers())) {
073 properties.add(new FieldProperty(converters, field));
074 propertyNames.add(propertyName);
075 }
076 }
077 }
078 catch (RuntimeException e) {
079 throw e;
080 }
081 catch (Exception e) {
082 throw new RuntimeException(e);
083 }
084 }
085
086 return properties;
087 }
088 }