You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ti...@apache.org on 2019/02/20 09:16:04 UTC

svn commit: r1853936 - in /felix/trunk/converter/converter/src/main/java/org/osgi/util/converter: ConvertingImpl.java DTOUtil.java Util.java

Author: timothyjward
Date: Wed Feb 20 09:16:04 2019
New Revision: 1853936

URL: http://svn.apache.org/viewvc?rev=1853936&view=rev
Log:
FELIX-6063 Avoid using getDeclaredXXX() in the converter

Modified:
    felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java
    felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/DTOUtil.java
    felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/Util.java

Modified: felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java?rev=1853936&r1=1853935&r2=1853936&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java Wed Feb 20 09:16:04 2019
@@ -385,28 +385,24 @@ class ConvertingImpl extends AbstractSpe
 
 				Field f = null;
 				try {
-					f = targetAsCls.getDeclaredField(fieldName);
+					f = targetAsCls.getField(fieldName);
 				} catch (NoSuchFieldException e) {
-					try {
-						f = targetAsCls.getField(fieldName);
-					} catch (NoSuchFieldException | NullPointerException e1) {
-						// There is no field with this name
-						if (keysIgnoreCase) {
-							// If enabled, try again but now ignore case
-							for (Field fs : targetAsCls.getDeclaredFields()) {
-								if (fs.getName().equalsIgnoreCase(fieldName)) {
-									f = fs;
-									break;
-								}
+					// There is no field with this name
+					if (keysIgnoreCase) {
+						// If enabled, try again but now ignore case
+						for (Field fs : targetAsCls.getFields()) {
+							if (fs.getName().equalsIgnoreCase(fieldName)) {
+								f = fs;
+								break;
 							}
+						}
 
-							if (f == null) {
-								for (Field fs : targetAsCls.getFields()) {
-									if (fs.getName()
-											.equalsIgnoreCase(fieldName)) {
-										f = fs;
-										break;
-									}
+						if (f == null) {
+							for (Field fs : targetAsCls.getFields()) {
+								if (fs.getName()
+										.equalsIgnoreCase(fieldName)) {
+									f = fs;
+									break;
 								}
 							}
 						}
@@ -523,12 +519,10 @@ class ConvertingImpl extends AbstractSpe
 
 	private List<String> getNames(Class< ? > cls) {
 		List<String> names = new ArrayList<>();
-		for (Field field : cls.getDeclaredFields()) {
+		for (Field field : cls.getFields()) {
 			int modifiers = field.getModifiers();
 			if (Modifier.isStatic(modifiers))
 				continue;
-			if (!Modifier.isPublic(modifiers))
-				continue;
 
 			String name = field.getName();
 			if (!names.contains(name))
@@ -930,17 +924,11 @@ class ConvertingImpl extends AbstractSpe
 		return null;
 	}
 
-	private boolean isMarkerAnnotation(Class< ? > annClass) {
-		for (Method m : annClass.getDeclaredMethods()) {
-			try {
-				if (Annotation.class
-						.getMethod(m.getName(), m.getParameterTypes())
-						.getReturnType()
-						.equals(m.getReturnType()))
-					// this is a base annotation method
-					continue;
-			} catch (Exception ex) {
-				// Method not found, not a marker annotation
+	private static boolean isMarkerAnnotation(Class< ? > annClass) {
+		for (Method m : annClass.getMethods()) {
+			if (m.getDeclaringClass() != annClass) {
+				// this is a base annotation or object method
+				continue;
 			}
 			return false;
 		}
@@ -950,8 +938,9 @@ class ConvertingImpl extends AbstractSpe
 	@SuppressWarnings("unchecked")
 	private <T> T tryStandardMethods() {
 		try {
-			Method m = targetAsClass.getDeclaredMethod("valueOf", String.class);
-			if (m != null) {
+			// Section 707.4.2.3 and 707.4.2.5 require valueOf to be public and static
+			Method m = targetAsClass.getMethod("valueOf", String.class);
+			if (m != null && Modifier.isStatic(m.getModifiers())) {
 				return (T) m.invoke(null, object.toString());
 			}
 		} catch (Exception e) {
@@ -1009,7 +998,8 @@ class ConvertingImpl extends AbstractSpe
 		Set<String> invokedMethods = new HashSet<>();
 
 		Map result = new HashMap();
-		for (Method md : sourceCls.getDeclaredMethods()) {
+		// Bean accessors must be public
+		for (Method md : sourceCls.getMethods()) {
 			handleBeanMethod(obj, md, invokedMethods, result);
 		}
 
@@ -1021,28 +1011,31 @@ class ConvertingImpl extends AbstractSpe
 		Set<String> handledFields = new HashSet<>();
 
 		Map result = new HashMap();
-		// Do we need 'declaredfields'? We only need to look at the public
-		// ones...
-		for (Field f : obj.getClass().getDeclaredFields()) {
-			handleDTOField(obj, f, handledFields, result, ic);
-		}
+		// We only use public fields for mapping a DTO
 		for (Field f : obj.getClass().getFields()) {
 			handleDTOField(obj, f, handledFields, result, ic);
 		}
 		return result;
 	}
 
-	@SuppressWarnings("rawtypes")
+	@SuppressWarnings({"unchecked","rawtypes"})
 	private static Map createMapFromInterface(Object obj, Class< ? > srcCls) {
 		Map result = new HashMap();
 
-		for (Class i : getInterfaces(srcCls)) {
-			for (Method md : i.getMethods()) {
-				handleInterfaceMethod(obj, i, md, new HashSet<String>(),
-						result);
+		if(Annotation.class.isAssignableFrom(srcCls) && isMarkerAnnotation(((Annotation)obj).annotationType())) {
+			// We special case this if the source is a marker annotation because we will end up with no
+			// interface methods otherwise
+			result.put(Util.getMarkerAnnotationKey(((Annotation)obj).annotationType(), obj), Boolean.TRUE);
+			return result;
+		} else {
+			for (Class i : getInterfaces(srcCls)) {
+				for (Method md : i.getMethods()) {
+					handleInterfaceMethod(obj, i, md, new HashSet<String>(),
+							result);
+				}
+				if (result.size() > 0)
+					return result;
 			}
-			if (result.size() > 0)
-				return result;
 		}
 		throw new ConversionException("Cannot be converted to map: " + obj);
 	}
@@ -1099,10 +1092,14 @@ class ConvertingImpl extends AbstractSpe
 			return Collections.emptySet();
 
 		Set<Class< ? >> interfaces = getInterfaces0(cls);
-		for (Iterator<Class< ? >> it = interfaces.iterator(); it.hasNext();) {
+		outer: for (Iterator<Class< ? >> it = interfaces.iterator(); it.hasNext();) {
 			Class< ? > intf = it.next();
-			if (intf.getDeclaredMethods().length == 0)
-				it.remove();
+			for (Method method : intf.getMethods()) {
+				if(method.getDeclaringClass() == intf) {
+					continue outer;
+				}
+			}
+			it.remove();
 		}
 
 		interfaces.removeAll(NO_MAP_VIEW_TYPES);
@@ -1217,9 +1214,8 @@ class ConvertingImpl extends AbstractSpe
 
 	private boolean hasGetProperties(Class< ? > cls) {
 		try {
-			Method m = cls.getDeclaredMethod("getProperties");
-			if (m == null)
-				m = cls.getMethod("getProperties");
+			// Section 707.4.4.4.8 says getProperties must be public
+			Method m = cls.getMethod("getProperties");
 			return m != null;
 		} catch (Exception e) {
 			return false;
@@ -1228,9 +1224,8 @@ class ConvertingImpl extends AbstractSpe
 
 	private Map< ? , ? > getPropertiesDelegate(Object obj, Class< ? > cls) {
 		try {
-			Method m = cls.getDeclaredMethod("getProperties");
-			if (m == null)
-				m = cls.getMethod("getProperties");
+			// Section 707.4.4.4.8 says getProperties must be public
+			Method m = cls.getMethod("getProperties");
 
 			return converter.convert(m.invoke(obj)).to(Map.class);
 		} catch (Exception e) {
@@ -1262,7 +1257,7 @@ class ConvertingImpl extends AbstractSpe
 		Set<Method> setters = new HashSet<>();
 		while (!Object.class.equals(cls)) {
 			Set<Method> methods = new HashSet<>();
-			methods.addAll(Arrays.asList(cls.getDeclaredMethods()));
+			// Only public methods can be Java Bean setters
 			methods.addAll(Arrays.asList(cls.getMethods()));
 			for (Method md : methods) {
 				if (md.getParameterTypes().length != 1)

Modified: felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/DTOUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/DTOUtil.java?rev=1853936&r1=1853935&r2=1853936&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/DTOUtil.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/DTOUtil.java Wed Feb 20 09:16:04 2019
@@ -30,14 +30,9 @@ class DTOUtil {
 
 	static boolean isDTOType(Class< ? > cls) {
 		try {
-			cls.getDeclaredConstructor();
+			cls.getConstructor();
 		} catch (NoSuchMethodException | SecurityException e) {
-			// No zero-arg constructor, not a DTO
-			return false;
-		}
-
-		if (cls.getDeclaredMethods().length > 0) {
-			// should not have any methods
+			// No public zero-arg constructor, not a DTO
 			return false;
 		}
 

Modified: felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/Util.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/Util.java?rev=1853936&r1=1853935&r2=1853936&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/Util.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/Util.java Wed Feb 20 09:16:04 2019
@@ -81,7 +81,8 @@ class Util {
 
 	static Map<String,Method> getBeanKeys(Class< ? > beanClass) {
 		Map<String,Method> keys = new LinkedHashMap<>();
-		for (Method md : beanClass.getDeclaredMethods()) {
+		// Bean methods must be public and can be on parent classes
+		for (Method md : beanClass.getMethods()) {
 			String key = getBeanKey(md);
 			if (key != null && !keys.containsKey(key)) {
 				keys.put(key, md);
@@ -202,7 +203,13 @@ class Util {
 			return null;
 
 		boolean valueFound = false;
-		for (Method md : ann.getDeclaredMethods()) {
+		// All annotation methods must be public
+		for (Method md : ann.getMethods()) {
+			if(md.getDeclaringClass() != ann) {
+				// Ignore Object methods and Annotation methods
+				continue;
+			}
+			
 			if ("value".equals(md.getName())) {
 				valueFound = true;
 				continue;
@@ -317,10 +324,20 @@ class Util {
 
 	static String getPrefix(Class< ? > cls) {
 		try {
-			Field prefixField = cls.getDeclaredField("PREFIX_");
-			if (prefixField.getType().equals(String.class)) {
-				if ((prefixField.getModifiers() & (Modifier.PUBLIC
-						| Modifier.FINAL | Modifier.STATIC)) > 0) {
+			// We can use getField as the PREFIX must be public (see spec erratum)
+			Field prefixField = cls.getField("PREFIX_");
+			if (prefixField.getDeclaringClass() == cls &&
+					prefixField.getType().equals(String.class)) {
+				int modifiers = prefixField.getModifiers();
+				// We need to be final *and* static
+				if (Modifier.isFinal(modifiers) &&
+					Modifier.isStatic(modifiers)) {
+					
+					if(!prefixField.isAccessible()) {
+						// Should we log that we have to do this?
+						prefixField.setAccessible(true);
+					}
+					
 					return (String) prefixField.get(null);
 				}
 			}