Skip to content

Commit

Permalink
FELIX-6064 Be lenient when converting from a DTO type with no public …
Browse files Browse the repository at this point in the history
…no-args constructor

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1853957 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
timothyjward committed Feb 20, 2019
1 parent 6c6b97d commit 44f2db3
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ private <T> T convertToDTO(Class< ? > sourceCls, Class< ? > targetAsCls) {

if (f != null) {
Object val = entry.getValue();
if (sourceAsDTO && DTOUtil.isDTOType(f.getType()))
if (sourceAsDTO && DTOUtil.isDTOType(f.getType(), false))
val = converter.convert(val).sourceAsDTO().to(
f.getType());
else {
Expand Down Expand Up @@ -573,8 +573,8 @@ Object convertCollectionValue(Object element) {
if (isCopyRequiredType(cls)) {
cls = getConstructableType(cls);
}

if (sourceAsDTO || DTOUtil.isDTOType(cls))
// Either force source as DTO, or lenient DTO type
if (sourceAsDTO || DTOUtil.isDTOType(cls, true))
element = converter.convert(element).sourceAsDTO().to(cls);
else
element = converter.convert(element).to(cls);
Expand Down Expand Up @@ -605,8 +605,8 @@ private Object convertMapElement(Object element, int typeIdx) {
if (isCopyRequiredType(cls)) {
cls = getConstructableType(cls);
}

if (sourceAsDTO || DTOUtil.isDTOType(cls))
// Either force source as DTO, or DTO type
if (sourceAsDTO || DTOUtil.isDTOType(cls, false))
element = converter.convert(element).sourceAsDTO().to(cls);
else
element = converter.convert(element).to(cls);
Expand All @@ -623,7 +623,7 @@ private Map convertToMapDelegate() {
return MapDelegate.forMap((Map) object, this);
} else if (Dictionary.class.isAssignableFrom(sourceClass)) {
return MapDelegate.forDictionary((Dictionary) object, this);
} else if (DTOUtil.isDTOType(sourceClass) || sourceAsDTO) {
} else if (DTOUtil.isDTOType(sourceClass, true) || sourceAsDTO) {
return MapDelegate.forDTO(object, sourceClass, this);
} else if (sourceAsJavaBean) {
return MapDelegate.forBean(object, sourceClass, this);
Expand Down Expand Up @@ -657,7 +657,7 @@ private Object convertToMapType() {
return convertToMap();
else if (Dictionary.class.isAssignableFrom(targetAsClass))
return convertToDictionary();
else if (targetAsDTO || DTOUtil.isDTOType(targetAsClass))
else if (targetAsDTO || DTOUtil.isDTOType(targetAsClass, false))
return convertToDTO(sourceClass, targetAsClass);
else if (targetAsClass.isInterface())
return convertToInterface(sourceClass, targetAsClass);
Expand Down Expand Up @@ -836,7 +836,7 @@ private static boolean isMapType(Class< ? > cls, boolean asJavaBean,
return true;
else if (getInterfaces(cls).size() > 0)
return true;
else if (DTOUtil.isDTOType(cls))
else if (DTOUtil.isDTOType(cls, true))
return true;
else if (asJavaBean && isWriteableJavaBean(cls))
return true;
Expand Down Expand Up @@ -1195,12 +1195,12 @@ private static void handleInterfaceMethod(Object obj, Class< ? > intf,
private Map< ? , ? > mapView(Object obj, Class< ? > sourceCls,
InternalConverter ic) {
if (Map.class.isAssignableFrom(sourceCls)
|| (DTOUtil.isDTOType(sourceCls) && obj instanceof Map))
|| (DTOUtil.isDTOType(sourceCls, true) && obj instanceof Map))
return (Map< ? , ? >) obj;
else if (Dictionary.class.isAssignableFrom(sourceCls))
return MapDelegate.forDictionary((Dictionary< ? , ? >) object,
this);
else if (DTOUtil.isDTOType(sourceCls) || sourceAsDTO)
else if (DTOUtil.isDTOType(sourceCls, true) || sourceAsDTO)
return createMapFromDTO(obj, ic);
else if (sourceAsJavaBean) {
Map< ? , ? > m = createMapFromBeanAccessors(obj, sourceCls);
Expand Down Expand Up @@ -1238,7 +1238,7 @@ private static boolean isCopyRequiredType(Class< ? > cls) {
return false;
return Map.class.isAssignableFrom(cls)
|| Collection.class.isAssignableFrom(cls)
|| DTOUtil.isDTOType(cls) || cls.isArray();
|| DTOUtil.isDTOType(cls, true) || cls.isArray();
}

private static boolean isWriteableJavaBean(Class< ? > cls) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ private DTOUtil() {
// Do not instantiate. This is a utility class.
}

static boolean isDTOType(Class< ? > cls) {
try {
cls.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
// No public zero-arg constructor, not a DTO
return false;
static boolean isDTOType(Class< ? > cls, boolean ignorePublicNoArgsCtor) {
if(!ignorePublicNoArgsCtor) {
try {
cls.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
// No public zero-arg constructor, not a DTO
return false;
}
}

for (Method m : cls.getMethods()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,17 @@ public void testDTO2Map3() {
assertEquals(Alpha.A, e2.alpha);
}

@Test
public void testDTO2Map4() {
MyDefaultCtorDTOAlike dto = new MyDefaultCtorDTOAlike();
dto.myProp = "myValue";

@SuppressWarnings("rawtypes")
Map m = converter.convert(dto).to(Map.class);
assertEquals(1, m.size());
assertEquals("myValue", m.get("myProp"));
}

@Test @SuppressWarnings({ "rawtypes", "unchecked" })
public void testDTOFieldShadowing() {
MySubDTO dto = new MySubDTO();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.osgi.util.converter;

public class MyDefaultCtorDTOAlike {

MyDefaultCtorDTOAlike() {
// Deliberately default visibiilty
}

public String myProp;
}

0 comments on commit 44f2db3

Please sign in to comment.