Replaced System.arraycopy with reflective array access.

This solves ArrayStoreExceptions that would otherwise occur with a primitive array.
This commit is contained in:
Ruben Dijkstra 2014-04-12 01:00:50 +02:00
parent 3ff199fe61
commit 92b978bda9
3 changed files with 59 additions and 31 deletions

View File

@ -166,13 +166,19 @@ public class ConstructorUtils {
private static class VarArgsTransformer extends ConstructorArgumentTransformer {
private Class<?>[] paramtypes;
private final Class<?>[] paramTypes;
private final Class<?> componentType;
private VarArgsTransformer(Constructor<?> constructor) {
super(constructor);
paramtypes = constructor.getParameterTypes();
paramTypes = constructor.getParameterTypes();
if (paramTypes.length > 0) {
componentType = paramTypes[paramTypes.length - 1].getComponentType();
} else {
componentType = null;
}
}
@Override
@ -182,16 +188,23 @@ public class ConstructorUtils {
@Override
public Object[] apply(Object[] args) {
Class<?>[] paramTypes = constructor.getParameterTypes();
Iterator<Object> iterator = Arrays
.asList(args)
.iterator();
// constructor args
Object[] cargs = new Object[paramTypes.length];
System.arraycopy(args, 0, cargs, 0, cargs.length - 1);
for (int i = 0; i < cargs.length - 1; i++) {
Array.set(cargs, i, iterator.next());
}
// array with vargs
int size = args.length - cargs.length + 1;
Object[] array = (Object[]) Array.newInstance(
paramTypes[paramTypes.length - 1].getComponentType(), size);
cargs[cargs.length - 1] = array;
System.arraycopy(args, cargs.length - 1, array, 0, size);
Object vargs = Array.newInstance(
componentType, size);
cargs[cargs.length - 1] = vargs;
for (int i = 0; i < Array.getLength(vargs); i++) {
Array.set(vargs, i, iterator.next());
}
return cargs;
}

View File

@ -13,12 +13,12 @@
*/
package com.mysema.query.types;
public class ProjectionExample{
public class ProjectionExample {
public Long id;
public String text;
public ProjectionExample() {
}
@ -43,4 +43,9 @@ public class ProjectionExample{
}
}
public ProjectionExample(Long id, char... characters) {
this.id = id;
this.text = String.copyValueOf(characters);
}
}

View File

@ -23,41 +23,41 @@ import com.mysema.query.types.path.PathBuilder;
public class ProjectionsTest {
public static class VarArgs {
String[] args;
public VarArgs(String... strs) {
args = strs;
}
}
public static class VarArgs2 {
String arg;
String[] args;
public VarArgs2(String s, String... strs) {
arg = s;
args = strs;
}
}
@SuppressWarnings("unchecked")
@Test
public void Array() {
FactoryExpression<String[]> expr = Projections.array(String[].class,
FactoryExpression<String[]> expr = Projections.array(String[].class,
new PathImpl(String.class, "p1"), new PathImpl(String.class, "p2"));
assertEquals(String[].class, expr.newInstance("1","2").getClass());
assertEquals(String[].class, expr.newInstance("1", "2").getClass());
}
@Test
public void BeanClassOfTExpressionOfQArray() {
PathBuilder<Entity> entity = new PathBuilder<Entity>(Entity.class, "entity");
QBean<Entity> beanProjection = Projections.bean(Entity.class,
entity.getNumber("cId",Integer.class),
entity.getNumber("cId", Integer.class),
entity.getNumber("eId", Integer.class));
assertEquals(Entity.class, beanProjection.newInstance(1,2).getClass());
assertEquals(Entity.class, beanProjection.newInstance(1, 2).getClass());
}
@Test
@ -65,33 +65,43 @@ public class ProjectionsTest {
Expression<Long> longVal = ConstantImpl.create(1l);
Expression<String> stringVal = ConstantImpl.create("");
assertEquals(ProjectionExample.class, Projections.constructor(ProjectionExample.class, longVal, stringVal)
.newInstance(0l,"").getClass());
.newInstance(0l, "").getClass());
}
@Test
public void Constructor_VarArgs() {
Expression<String> stringVal = ConstantImpl.create("");
VarArgs instance = Projections.constructor(VarArgs.class, stringVal).newInstance("X", "Y");
assertArrayEquals(new String[]{"X", "Y"}, instance.args);
VarArgs instance = Projections.constructor(VarArgs.class, stringVal, stringVal).newInstance("X", "Y");
assertArrayEquals(new String[]{"X", "Y"}, instance.args);
}
@Test
public void Constructor_VarArgs2() {
Expression<String> stringVal = ConstantImpl.create("");
VarArgs2 instance = Projections.constructor(VarArgs2.class, stringVal, stringVal, stringVal).newInstance("X", "Y", "Z");
assertEquals("X", instance.arg);
assertArrayEquals(new String[]{"Y", "Z"}, instance.args);
assertArrayEquals(new String[]{"Y", "Z"}, instance.args);
}
@Test
public void Constructor_VarArgs3() {
Constant<Long> longVal = ConstantImpl.create(1L);
Constant<Character> charVal = ConstantImpl.create('\0');
ProjectionExample instance = Projections
.constructor(ProjectionExample.class, longVal, charVal, charVal, charVal, charVal, charVal, charVal)
.newInstance(1L, 'm', 'y', 's', 'e', 'm', 'a');
assertEquals(1L, (long) instance.id);
assertEquals("mysema", instance.text);
}
@Test
public void FieldsClassOfTExpressionOfQArray() {
PathBuilder<Entity> entity = new PathBuilder<Entity>(Entity.class, "entity");
QBean<Entity> beanProjection = Projections.fields(Entity.class,
entity.getNumber("cId",Integer.class),
entity.getNumber("cId", Integer.class),
entity.getNumber("eId", Integer.class));
assertEquals(Entity.class, beanProjection.newInstance(1,2).getClass());
assertEquals(Entity.class, beanProjection.newInstance(1, 2).getClass());
}
}