Skip to content

Commit

Permalink
Merge pull request #809 from serso/my-android
Browse files Browse the repository at this point in the history
Pull request for #769
  • Loading branch information
snazha-blkio authored Dec 7, 2018
2 parents 213a9da + ddbe2cc commit 2270186
Show file tree
Hide file tree
Showing 59 changed files with 319 additions and 97 deletions.
3 changes: 3 additions & 0 deletions abi/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@
description 'Ethereum Application Binary Interface (ABI) for working with smart contracts'

dependencies {
compile project(':compat')
compile project(':utils')
}

useReducedJdk(project)
6 changes: 2 additions & 4 deletions abi/src/main/java/org/web3j/abi/EventEncoder.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package org.web3j.abi;

import java.util.List;
import java.util.stream.Collectors;

import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.Type;
import org.web3j.crypto.Hash;
import org.web3j.utils.Collection;
import org.web3j.utils.Numeric;

/**
Expand Down Expand Up @@ -33,9 +33,7 @@ static <T extends Type> String buildMethodSignature(
StringBuilder result = new StringBuilder();
result.append(methodName);
result.append("(");
String params = parameters.stream()
.map(p -> Utils.getTypeName(p))
.collect(Collectors.joining(","));
final String params = Collection.join(parameters, ",", Utils::getTypeName);
result.append(params);
result.append(")");
return result.toString();
Expand Down
7 changes: 3 additions & 4 deletions abi/src/main/java/org/web3j/abi/FunctionEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;

import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.StaticArray;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Uint;
import org.web3j.crypto.Hash;
import org.web3j.utils.Collection;
import org.web3j.utils.Numeric;

/**
Expand Down Expand Up @@ -75,9 +75,8 @@ static String buildMethodSignature(String methodName, List<Type> parameters) {
StringBuilder result = new StringBuilder();
result.append(methodName);
result.append("(");
String params = parameters.stream()
.map(Type::getTypeAsString)
.collect(Collectors.joining(","));

final String params = Collection.join(parameters, ",", Type::getTypeAsString);
result.append(params);
result.append(")");
return result.toString();
Expand Down
13 changes: 7 additions & 6 deletions abi/src/main/java/org/web3j/abi/TypeDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;

import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Array;
Expand All @@ -25,6 +23,8 @@
import org.web3j.abi.datatypes.Uint;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.generated.Uint160;
import org.web3j.compat.BiFunction;
import org.web3j.compat.Compat;
import org.web3j.utils.Numeric;

/**
Expand Down Expand Up @@ -192,7 +192,7 @@ static Utf8String decodeUtf8String(String input, int offset) {
DynamicBytes dynamicBytesResult = decodeDynamicBytes(input, offset);
byte[] bytes = dynamicBytesResult.getValue();

return new Utf8String(new String(bytes, StandardCharsets.UTF_8));
return new Utf8String(new String(bytes, Compat.UTF_8));
}

/**
Expand All @@ -219,7 +219,8 @@ private static <T extends Type> T instantiateStaticArray(
try {
Class<List> listClass = List.class;
return typeReference.getClassType().getConstructor(listClass).newInstance(elements);
} catch (ReflectiveOperationException e) {
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException
| InvocationTargetException | NoSuchMethodException e) {
//noinspection unchecked
return (T) new StaticArray<>(elements);
}
Expand Down Expand Up @@ -271,8 +272,8 @@ private static <T extends Type> T decodeArrayElements(
}
} catch (ClassNotFoundException e) {
throw new UnsupportedOperationException(
"Unable to access parameterized type " + typeReference.getType().getTypeName(),
e);
"Unable to access parameterized type "
+ Compat.getTypeName(typeReference.getType()), e);
}
}
}
4 changes: 2 additions & 2 deletions abi/src/main/java/org/web3j/abi/TypeEncoder.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.web3j.abi;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Array;
Expand All @@ -16,6 +15,7 @@
import org.web3j.abi.datatypes.Ufixed;
import org.web3j.abi.datatypes.Uint;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.compat.Compat;
import org.web3j.utils.Numeric;

import static org.web3j.abi.datatypes.Type.MAX_BIT_LENGTH;
Expand Down Expand Up @@ -141,7 +141,7 @@ static String encodeDynamicBytes(DynamicBytes dynamicBytes) {
}

static String encodeString(Utf8String string) {
byte[] utfEncoded = string.getValue().getBytes(StandardCharsets.UTF_8);
byte[] utfEncoded = string.getValue().getBytes(Compat.UTF_8);
return encodeDynamicBytes(new DynamicBytes(utfEncoded));
}

Expand Down
6 changes: 4 additions & 2 deletions abi/src/main/java/org/web3j/abi/TypeReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.web3j.compat.Compat;

/**
* Type wrapper to get around limitations of Java's type erasure.
* This is so that we can pass around Typed {@link org.web3j.abi.datatypes.Array} types.
Expand Down Expand Up @@ -58,10 +60,10 @@ public boolean isIndexed() {
public Class<T> getClassType() throws ClassNotFoundException {
Type clsType = getType();

if (getType() instanceof ParameterizedType) {
if (clsType instanceof ParameterizedType) {
return (Class<T>) ((ParameterizedType) clsType).getRawType();
} else {
return (Class<T>) Class.forName(clsType.getTypeName());
return (Class<T>) Class.forName(Compat.getTypeName(clsType));
}
}

Expand Down
12 changes: 6 additions & 6 deletions abi/src/main/java/org/web3j/abi/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.DynamicBytes;
Expand All @@ -16,6 +15,7 @@
import org.web3j.abi.datatypes.Ufixed;
import org.web3j.abi.datatypes.Uint;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.compat.Compat;

/**
* Utility functions.
Expand All @@ -32,7 +32,7 @@ static <T extends Type> String getTypeName(TypeReference<T> typeReference) {
type = (Class<?>) ((ParameterizedType) reflectedType).getRawType();
return getParameterizedTypeName(typeReference, type);
} else {
type = Class.forName(reflectedType.getTypeName());
type = Class.forName(Compat.getTypeName(reflectedType));
return getSimpleTypeName(type);
}
} catch (ClassNotFoundException e) {
Expand Down Expand Up @@ -86,16 +86,16 @@ static <T extends Type> Class<T> getParameterizedTypeFromArray(
java.lang.reflect.Type[] typeArguments =
((ParameterizedType) type).getActualTypeArguments();

String parameterizedTypeName = typeArguments[0].getTypeName();
String parameterizedTypeName = Compat.getTypeName(typeArguments[0]);
return (Class<T>) Class.forName(parameterizedTypeName);
}

@SuppressWarnings("unchecked")
public static List<TypeReference<Type>> convert(List<TypeReference<?>> input) {
List<TypeReference<Type>> result = new ArrayList<>(input.size());
result.addAll(input.stream()
.map(typeReference -> (TypeReference<Type>) typeReference)
.collect(Collectors.toList()));
for (TypeReference<?> ref : input) {
result.add((TypeReference<Type>) ref);
}
return result;
}

Expand Down
22 changes: 15 additions & 7 deletions abi/src/main/java/org/web3j/abi/datatypes/Event.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.web3j.abi.datatypes;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.web3j.abi.TypeReference;

Expand All @@ -28,14 +28,22 @@ public List<TypeReference<Type>> getParameters() {
}

public List<TypeReference<Type>> getIndexedParameters() {
return parameters.stream()
.filter(TypeReference::isIndexed)
.collect(Collectors.toList());
final List<TypeReference<Type>> result = new ArrayList<>(parameters.size());
for (TypeReference<Type> parameter : parameters) {
if (parameter.isIndexed()) {
result.add(parameter);
}
}
return result;
}

public List<TypeReference<Type>> getNonIndexedParameters() {
return parameters.stream()
.filter(p -> !p.isIndexed())
.collect(Collectors.toList());
final List<TypeReference<Type>> result = new ArrayList<>(parameters.size());
for (TypeReference<Type> parameter : parameters) {
if (!parameter.isIndexed()) {
result.add(parameter);
}
}
return result;
}
}
18 changes: 18 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ buildscript {
ext.slf4jVersion = '1.7.25'
ext.javaWebSocketVersion = '1.3.8'
ext.picocliVersion = '3.0.0'
ext.streamsupportVersion = '1.7.0'

// test dependencies
ext.equalsverifierVersion = '2.1.7'
Expand Down Expand Up @@ -344,3 +345,20 @@ configure(subprojects.findAll { it.name != 'integration-tests' }) {
}
}
}

// Makes a submodule to be compiled against a reduced JDK, currently an Android JDK.
ext.useReducedJdk = { Project project ->
// Use Android JDK instead of normal JDK in order to limit language APIs allowed in the project
project.tasks.withType(JavaCompile) { Task task ->
// As tests are run on a local Java VM they don't have to be compatible with Android JDK.
if (task.name.contains("compileTest")) return
options.bootstrapClasspath = files(
// Contains lambda-related classes such as java.lang.invoke.LambdaMetafactory.
// Copied from [android-sdk]/build-tools/27.0.3
"$rootDir/compat/libs/core-lambda-stubs.jar",
// Android JDK. Copied from [android-sdk]/platforms/android-15. All Android specific
// packages were stripped. The only kept packages are:
// java.*, javax.*, org.w3c.* and org.xml.*
"$rootDir/compat/libs/android.jar")
}
}
7 changes: 7 additions & 0 deletions compat/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

description 'Android compatibility module'

dependencies {
}

useReducedJdk(project)
Binary file added compat/libs/android.jar
Binary file not shown.
Binary file added compat/libs/core-lambda-stubs.jar
Binary file not shown.
13 changes: 13 additions & 0 deletions compat/src/main/java/java/lang/SafeVarargs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package java.lang;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* This class won't be loaded at runtime as it "overrides" a bootstrap class from JDK.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {}
9 changes: 9 additions & 0 deletions compat/src/main/java/org/web3j/compat/BiFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.web3j.compat;

/**
* Ports {@link java.util.function.BiFunction}.
*/
public interface BiFunction<T, U, R> {

R apply(T t, U u);
}
91 changes: 91 additions & 0 deletions compat/src/main/java/org/web3j/compat/Compat.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.web3j.compat;

import java.lang.reflect.Type;
import java.math.BigInteger;
import java.nio.charset.Charset;

/**
* Provides compatibility methods to substitute those methods from Java SDK that
* are not supported on Android.
*/
public final class Compat {

/**
* Ports {@link java.nio.charset.StandardCharsets#UTF_8}.
*/
public static final Charset UTF_8 = Charset.forName("UTF-8");

private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE);

private Compat() {
}

/**
* Ports {@link String#join(CharSequence, CharSequence...)}.
*/
public static String join(CharSequence delimiter, CharSequence... elements) {
if (elements.length == 0) {
return "";
}
final StringBuilder sb = new StringBuilder(7 * elements.length);
sb.append(elements[0]);
for (int i = 1; i < elements.length; i++) {
sb.append(delimiter);
sb.append(elements[i]);

}
return sb.toString();
}

/**
* Ports {@link BigInteger#longValueExact()}.
*/
public static long longValueExact(BigInteger value) {
if (value.compareTo(LONG_MIN) >= 0 && value.compareTo(LONG_MAX) <= 0) {
return value.longValue();
}
throw new ArithmeticException("BigInteger out of long range");
}

/**
* Ports {@link Type#getTypeName()}.
*/
public static String getTypeName(Type type) {
if (type instanceof Class) {
return getClassName((Class)type);
}
return type.toString();

}

/**
* Copied from {@link Class#getTypeName()}.
*/
private static String getClassName(Class type) {
if (type.isArray()) {
try {
Class<?> cl = type;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuilder sb = new StringBuilder();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
} catch (Throwable e) { /*FALLTHRU*/ }
}
return type.getName();
}

/**
* Ports {@link Boolean#hashCode(boolean)}.
*/
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
}
Loading

0 comments on commit 2270186

Please sign in to comment.