Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 6f84e45

Browse files
FABJ-480: Fix maxInboundMessageSize yaml reading (#148)
Signed-off-by: vasili pispanen <vpispanen@gmail.com> Coauthored-by: Mark S. Lewis <mark_lewis@uk.ibm.com> Co-authored-by: Vasili Pispanen <vpispanen@gmail.com>
1 parent adf7fce commit 6f84e45

File tree

3 files changed

+179
-17
lines changed

3 files changed

+179
-17
lines changed

src/main/java/org/hyperledger/fabric/sdk/Endpoint.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.io.IOException;
2121
import java.io.InputStream;
2222
import java.lang.reflect.InvocationTargetException;
23-
import java.lang.reflect.Method;
2423
import java.nio.file.Files;
2524
import java.nio.file.Paths;
2625
import java.security.PrivateKey;
@@ -56,6 +55,7 @@
5655
import org.bouncycastle.crypto.digests.SHA256Digest;
5756
import org.hyperledger.fabric.sdk.exception.CryptoException;
5857
import org.hyperledger.fabric.sdk.helper.Config;
58+
import org.hyperledger.fabric.sdk.helper.Utils;
5959
import org.hyperledger.fabric.sdk.security.CryptoPrimitives;
6060

6161
import static java.lang.String.format;
@@ -348,23 +348,15 @@ private void addNettyBuilderProps(NettyChannelBuilder channelBuilder, Properties
348348

349349
}
350350
if (null == methodName || "forAddress".equals(methodName) || "build".equals(methodName)) {
351-
352351
continue;
353352
}
354353

355354
Object parmsArrayO = es.getValue();
356-
Object[] parmsArray;
357-
if (!(parmsArrayO instanceof Object[])) {
358-
parmsArray = new Object[] {parmsArrayO};
359-
360-
} else {
361-
parmsArray = (Object[]) parmsArrayO;
362-
}
355+
Object[] parmsArray = !(parmsArrayO instanceof Object[]) ? new Object[] {parmsArrayO} : (Object[]) parmsArrayO;
363356

364357
Class<?>[] classParms = new Class<?>[parmsArray.length];
365-
int i = -1;
366-
for (Object oparm : parmsArray) {
367-
++i;
358+
for (int i = 0; i < parmsArray.length; i++) {
359+
Object oparm = parmsArray[i];
368360

369361
if (null == oparm) {
370362
classParms[i] = Object.class;
@@ -375,7 +367,6 @@ private void addNettyBuilderProps(NettyChannelBuilder channelBuilder, Properties
375367
if (null != unwrapped) {
376368
classParms[i] = unwrapped;
377369
} else {
378-
379370
Class<?> clz = oparm.getClass();
380371

381372
Class<?> ecz = clz.getEnclosingClass();
@@ -387,13 +378,11 @@ private void addNettyBuilderProps(NettyChannelBuilder channelBuilder, Properties
387378
}
388379
}
389380

390-
final Method method = channelBuilder.getClass().getMethod(methodName, classParms);
391-
392-
method.invoke(channelBuilder, parmsArray);
381+
Utils.invokeMethod(channelBuilder, methodName, classParms, parmsArray);
393382

394383
if (logger.isTraceEnabled()) {
395384
logger.trace(format("Endpoint with url: %s set managed channel builder method %s (%s) ", url,
396-
method, Arrays.toString(parmsArray)));
385+
methodName, Arrays.toString(parmsArray)));
397386

398387
}
399388

src/main/java/org/hyperledger/fabric/sdk/helper/Utils.java

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import java.io.FileInputStream;
2020
import java.io.IOException;
2121
import java.io.InputStream;
22+
import java.lang.reflect.InvocationTargetException;
23+
import java.lang.reflect.Method;
24+
import java.math.BigDecimal;
25+
import java.math.BigInteger;
2226
import java.net.URI;
2327
import java.nio.file.FileVisitOption;
2428
import java.nio.file.Files;
@@ -29,11 +33,15 @@
2933
import java.util.Collection;
3034
import java.util.Comparator;
3135
import java.util.List;
36+
import java.util.Map;
3237
import java.util.Properties;
3338
import java.util.UUID;
39+
import java.util.function.Function;
3440
import java.util.regex.Matcher;
3541
import java.util.regex.Pattern;
42+
import java.util.stream.Collectors;
3643

44+
import com.google.common.collect.ImmutableMap;
3745
import com.google.protobuf.ByteString;
3846
import com.google.protobuf.Timestamp;
3947
import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -60,6 +68,26 @@ public final class Utils {
6068
private static final Config config = Config.getConfig();
6169
private static final int MAX_LOG_STRING_LENGTH = config.maxLogStringLength();
6270

71+
private static final Map<Class<?>, Function<String, ?>> STRING_CONVERSIONS_BY_TYPE =
72+
new ImmutableMap.Builder<Class<?>, Function<String, ?>>()
73+
.put(Byte.class, Byte::valueOf)
74+
.put(byte.class, Byte::valueOf)
75+
.put(Short.class, Short::valueOf)
76+
.put(short.class, Short::valueOf)
77+
.put(Integer.class, Integer::valueOf)
78+
.put(int.class, Integer::valueOf)
79+
.put(Long.class, Long::valueOf)
80+
.put(long.class, Long::valueOf)
81+
.put(Float.class, Float::valueOf)
82+
.put(float.class, Float::valueOf)
83+
.put(Double.class, Double::valueOf)
84+
.put(double.class, Double::valueOf)
85+
.put(Boolean.class, Boolean::valueOf)
86+
.put(boolean.class, Boolean::valueOf)
87+
.put(BigInteger.class, BigInteger::new)
88+
.put(BigDecimal.class, BigDecimal::new)
89+
.build();
90+
6391
/**
6492
* Generate parameter hash for the given chaincode path,func and args
6593
*
@@ -408,6 +436,76 @@ public static String toHexString(String bytes) {
408436

409437
}
410438

439+
/**
440+
* Lookup method by name and params
441+
* If there are no strict matches - trying to convert args to appropriate type
442+
* Useful for building network configs from yaml files
443+
* */
444+
public static Object invokeMethod(final Object target, final String methodName, final Class<?>[] parameterTypes, final Object[] args) throws InvocationTargetException,
445+
IllegalAccessException, NoSuchMethodException {
446+
if (parameterTypes.length != args.length) {
447+
throw new IllegalArgumentException("Parameters types " + java.util.Arrays.toString(parameterTypes) +
448+
" do not match arguments " + java.util.Arrays.toString(args));
449+
}
450+
451+
Method method = lookupMethod(target.getClass(), methodName, parameterTypes);
452+
453+
//convert args to founded method param's types
454+
Object[] coercedArgs = new Object[args.length];
455+
Class<?>[] methodParameterTypes = method.getParameterTypes();
456+
for (int i = 0; i < args.length; i++) {
457+
coercedArgs[i] = convertArgumentToType(args[i], methodParameterTypes[i]);
458+
}
459+
460+
return method.invoke(target, coercedArgs);
461+
}
462+
463+
private static Method lookupMethod(final Class<?> cls, final String name, final Class<?>[] parameterTypes) throws NoSuchMethodException {
464+
try {
465+
return cls.getMethod(name, parameterTypes);
466+
} catch (NoSuchMethodException originalException) {
467+
//trying to find method with same name and parameters count
468+
List<Method> candidates = java.util.Arrays.stream(cls.getMethods())
469+
.filter(it -> it.getName().equals(name))
470+
.filter(it -> it.getParameterCount() == parameterTypes.length)
471+
.collect(Collectors.toList());
472+
473+
if (candidates.isEmpty()) {
474+
throw originalException;
475+
}
476+
477+
//if there is only one candidate - return it
478+
if (candidates.size() == 1) {
479+
return candidates.get(0);
480+
}
481+
482+
//else, it could be same method declared in hierarchy (override). They must be with equal parameter types
483+
for (int i = 0; i < candidates.size() - 1; i++) {
484+
Class<?>[] types1 = candidates.get(i).getParameterTypes();
485+
Class<?>[] types2 = candidates.get(i + 1).getParameterTypes();
486+
//otherwise - we found methods with different params and can't choose one
487+
if (!java.util.Arrays.equals(types1, types2)) {
488+
throw originalException;
489+
}
490+
}
491+
492+
return candidates.get(0);
493+
}
494+
}
495+
496+
private static Object convertArgumentToType(final Object arg, final Class<?> type) {
497+
if (arg.getClass().equals(type) || !(arg instanceof String)) {
498+
return arg;
499+
}
500+
501+
Function<String, ?> convert = STRING_CONVERSIONS_BY_TYPE.get(type);
502+
if (null == convert) {
503+
throw new IllegalArgumentException("Unable to convert \"" + arg + "\" to " + type.getTypeName());
504+
}
505+
506+
return convert.apply((String) arg);
507+
}
508+
411509
/**
412510
* Private constructor to prevent instantiation.
413511
*/

src/test/java/org/hyperledger/fabric/sdk/helper/UtilsTest.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.junit.Rule;
3232
import org.junit.Test;
3333
import org.junit.rules.TemporaryFolder;
34+
import org.mockito.Mockito;
3435

3536
import static java.nio.charset.StandardCharsets.UTF_8;
3637
import static org.hyperledger.fabric.sdk.testutils.TestUtils.assertArrayListEquals;
@@ -43,6 +44,16 @@ public class UtilsTest {
4344
@Rule
4445
public final TemporaryFolder tempFolder = new TemporaryFolder();
4546

47+
public static class InvocationStub {
48+
public InvocationStub intParameter(int i) {
49+
return this;
50+
}
51+
52+
public InvocationStub complexParameter(InvocationStub that) {
53+
return this;
54+
}
55+
}
56+
4657
@Test
4758
public void testGenerateParameterHash() {
4859
List<String> args = new ArrayList<>();
@@ -379,6 +390,70 @@ public void testToHexStringNull() {
379390
Assert.assertNull(Utils.toHexString((ByteString) null));
380391
}
381392

393+
@Test
394+
public void testInvokeMethodMismatchedTypesAndArgs() {
395+
Assert.assertThrows(IllegalArgumentException.class, () -> {
396+
Utils.invokeMethod(new InvocationStub(), "intParameter", new Class<?>[] {int.class}, new Object[0]);
397+
});
398+
}
399+
400+
@Test
401+
public void testInvokeMethodInvalidParameterType() {
402+
Assert.assertThrows(IllegalArgumentException.class, () -> {
403+
Utils.invokeMethod(new InvocationStub(), "complexParameter", new Class<?>[] {InvocationStub.class}, new Object[] {"wrong"});
404+
});
405+
}
406+
407+
@Test
408+
public void testInvokeMethodWithCorrectArgs() throws Exception {
409+
InvocationStub testObject = Mockito.spy(new InvocationStub());
410+
411+
Object result = Utils.invokeMethod(testObject, "intParameter", new Class<?>[] {int.class}, new Object[] {1024});
412+
413+
Mockito.verify(testObject, Mockito.atLeastOnce()).intParameter(1024);
414+
Assert.assertEquals(testObject, result);
415+
}
416+
417+
@Test
418+
public void testInvokeMethodWithCoercedArgs() throws Exception {
419+
InvocationStub testObject = Mockito.spy(new InvocationStub());
420+
421+
Object result = Utils.invokeMethod(testObject, "intParameter", new Class<?>[] {int.class}, new Object[] {"1024"});
422+
423+
Mockito.verify(testObject, Mockito.atLeastOnce()).intParameter(1024);
424+
Assert.assertEquals(testObject, result);
425+
}
426+
427+
@Test
428+
public void testInvokeMethodWithAlternativeTypedArgs() throws Exception {
429+
InvocationStub testObject = Mockito.spy(new InvocationStub());
430+
431+
Object result = Utils.invokeMethod(testObject, "intParameter", new Class<?>[] {Integer.class}, new Object[] {"1024"});
432+
433+
Mockito.verify(testObject, Mockito.atLeastOnce()).intParameter(1024);
434+
Assert.assertEquals(testObject, result);
435+
}
436+
437+
@Test
438+
public void testInvokeMethodWithCoercedArgsAndParameters() throws Exception {
439+
InvocationStub testObject = Mockito.spy(new InvocationStub());
440+
441+
Object result = Utils.invokeMethod(testObject, "intParameter", new Class<?>[] {String.class}, new Object[] {"1024"});
442+
443+
Mockito.verify(testObject, Mockito.atLeastOnce()).intParameter(1024);
444+
Assert.assertEquals(testObject, result);
445+
}
446+
447+
@Test
448+
public void testInvokeMethodWithComplexArgs() throws Exception {
449+
InvocationStub testObject = Mockito.spy(new InvocationStub());
450+
451+
Object result = Utils.invokeMethod(testObject, "complexParameter", new Class<?>[] {InvocationStub.class}, new Object[] {testObject});
452+
453+
Mockito.verify(testObject, Mockito.atLeastOnce()).complexParameter(testObject);
454+
Assert.assertEquals(testObject, result);
455+
}
456+
382457
// ==========================================================================================
383458
// Helper methods
384459
// ==========================================================================================

0 commit comments

Comments
 (0)