From c1edd431900ea16187f9cccf3b73f27646e4d0cd Mon Sep 17 00:00:00 2001 From: timd Date: Sat, 6 Jan 2018 18:22:26 -0500 Subject: [PATCH 1/3] Added: generic Asset.data object instead of Map generic MetaData object instead of Map Custom TypeAdapters can be added for custom serializers and deserializers. AssetSerializer to work with arbitrary Asset.data objects Removed library json.org and replaced with GSON. TransactionIdExclusionStrategy the gson way of excluding parameters on demand transaction now has toHashInput() to generate the json string for hashing. Removed json prettyprinting Assorted cleanup --- pom.xml | 5 - .../com/authenteq/api/TransactionsApi.java | 7 +- .../builders/BigchainDbConfigBuilder.java | 11 +- .../BigchainDbTransactionBuilder.java | 211 ++++++------------ .../json/strategy/AssetSerializer.java | 32 +++ .../json/strategy/AssetsDeserializer.java | 7 +- .../strategy/TransactionDeserializer.java | 37 ++- .../TransactionIdExclusionStrategy.java | 18 ++ .../strategy/TransactionsDeserializer.java | 30 ++- src/main/java/com/authenteq/model/Asset.java | 46 ++-- .../java/com/authenteq/model/Transaction.java | 46 ++-- .../com/authenteq/model/TransactionModel.java | 152 ++++++------- .../java/com/authenteq/util/DriverUtils.java | 94 ++++---- .../java/com/authenteq/util/JsonUtils.java | 140 +++++++++--- .../java/com/authenteq/util/TypeAdapter.java | 57 +++++ .../authenteq/BigchaindbTransactionTest.java | 57 +++-- .../java/com/authenteq/api/AssetsApiTest.java | 12 +- .../java/com/authenteq/api/BlocksApiTest.java | 24 +- .../com/authenteq/api/OutputsApiTest.java | 1 - .../com/authenteq/api/TransactionApiTest.java | 92 ++++++-- 20 files changed, 602 insertions(+), 477 deletions(-) create mode 100644 src/main/java/com/authenteq/json/strategy/AssetSerializer.java create mode 100644 src/main/java/com/authenteq/json/strategy/TransactionIdExclusionStrategy.java create mode 100644 src/main/java/com/authenteq/util/TypeAdapter.java diff --git a/pom.xml b/pom.xml index d48bf7f..78b399b 100644 --- a/pom.xml +++ b/pom.xml @@ -68,11 +68,6 @@ commons-codec 1.10 - - org.json - json - 20170516 - com.google.code.gson gson diff --git a/src/main/java/com/authenteq/api/TransactionsApi.java b/src/main/java/com/authenteq/api/TransactionsApi.java index 3874258..bfb6a27 100644 --- a/src/main/java/com/authenteq/api/TransactionsApi.java +++ b/src/main/java/com/authenteq/api/TransactionsApi.java @@ -10,7 +10,6 @@ import com.authenteq.util.NetworkUtils; import okhttp3.RequestBody; import okhttp3.Response; -import org.json.JSONException; import java.io.IOException; import java.util.logging.Logger; @@ -75,20 +74,16 @@ public static Transaction getTransactionById(String id) throws IOException { * @param operation * the operation * @return the transactions by asset id - * @throws JSONException - * the JSON exception * @throws IOException * Signals that an I/O exception has occurred. */ public static Transactions getTransactionsByAssetId(String assetId, Operations operation) - throws JSONException, IOException { + throws IOException { LOGGER.info("getTransactionsByAssetId Call :" + assetId + " operation " + operation); Response response = NetworkUtils.sendGetRequest( BigChainDBGlobals.getBaseUrl() + BigchainDbApi.TRANSACTIONS + "?asset_id=" + assetId + "&operation=" + operation); String body = response.body().string(); response.close(); return JsonUtils.fromJson(body, Transactions.class); - } - } diff --git a/src/main/java/com/authenteq/builders/BigchainDbConfigBuilder.java b/src/main/java/com/authenteq/builders/BigchainDbConfigBuilder.java index 92729fd..4752f50 100644 --- a/src/main/java/com/authenteq/builders/BigchainDbConfigBuilder.java +++ b/src/main/java/com/authenteq/builders/BigchainDbConfigBuilder.java @@ -8,7 +8,6 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; -import com.authenteq.api.AccountApi; import com.authenteq.constants.BigchainDbApi; import com.authenteq.model.ApiEndpoints; import com.authenteq.model.BigChainDBGlobals; @@ -25,9 +24,8 @@ * The Class BigchainDbConfigBuilder. */ public class BigchainDbConfigBuilder { - - private static final Logger LOGGER = Logger.getLogger(AccountApi.class.getName()); - + + private static final Logger LOGGER = Logger.getLogger(BigchainDbConfigBuilder.class.getName()); /** * Instantiates a new bigchain db config builder. */ @@ -74,11 +72,6 @@ public interface ITokens { * Setup. */ void setup(); - - /** - * Setup. - */ - } /** diff --git a/src/main/java/com/authenteq/builders/BigchainDbTransactionBuilder.java b/src/main/java/com/authenteq/builders/BigchainDbTransactionBuilder.java index f221dc5..daf8f45 100644 --- a/src/main/java/com/authenteq/builders/BigchainDbTransactionBuilder.java +++ b/src/main/java/com/authenteq/builders/BigchainDbTransactionBuilder.java @@ -1,24 +1,24 @@ package com.authenteq.builders; import java.io.IOException; -import java.lang.reflect.Type; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; -import java.util.Map; -import java.util.TreeMap; +import java.util.logging.Logger; + +import com.authenteq.json.strategy.TransactionDeserializer; +import com.authenteq.json.strategy.TransactionsDeserializer; +import com.google.gson.*; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jcajce.provider.digest.SHA3; import org.interledger.cryptoconditions.types.Ed25519Sha256Condition; import org.interledger.cryptoconditions.types.Ed25519Sha256Fulfillment; -import org.json.JSONObject; import com.authenteq.api.TransactionsApi; import com.authenteq.constants.Operations; import com.authenteq.model.Asset; import com.authenteq.model.Condition; -import com.authenteq.model.DataModel; import com.authenteq.model.Details; import com.authenteq.model.FulFill; import com.authenteq.model.Input; @@ -28,8 +28,6 @@ import com.authenteq.util.DriverUtils; import com.authenteq.util.JsonUtils; import com.authenteq.util.KeyPairUtils; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; import net.i2p.crypto.eddsa.EdDSAEngine; import net.i2p.crypto.eddsa.EdDSAPrivateKey; import net.i2p.crypto.eddsa.EdDSAPublicKey; @@ -38,7 +36,8 @@ * The Class BigchainDbTransactionBuilder. */ public class BigchainDbTransactionBuilder { - + private static final Logger LOGGER = Logger.getLogger( BigchainDbTransactionBuilder.class.getName() ); + /** * Instantiates a new bigchain db transaction builder. */ @@ -68,7 +67,7 @@ public interface ITransactionAttributes { */ ITransactionAttributes operation(Operations operation); - /** + /* * Adds the asset. * * @param key @@ -77,7 +76,9 @@ public interface ITransactionAttributes { * the value * @return the i asset meta data */ - ITransactionAttributes addAsset(String key, String value); + //ITransactionAttributes addAsset(String key, String value); + + ITransactionAttributes addAssetDataClass( Class assetDataClass, JsonDeserializer jsonDeserializer ); ITransactionAttributes addOutput(String amount, EdDSAPublicKey... publicKey); @@ -91,17 +92,6 @@ public interface ITransactionAttributes { ITransactionAttributes addInput(String fullfillment, FulFill fullFill, EdDSAPublicKey publicKey); - /** - * Adds the meta data. - * - * @param key - * the key - * @param value - * the value - * @return the i asset meta data - */ - ITransactionAttributes addMetaData(String key, String value); - /** * Adds the assets. * @@ -109,43 +99,34 @@ public interface ITransactionAttributes { * the assets * @return the i asset meta data */ - ITransactionAttributes addAssets(Map assets); - - /** - * Adds the assets. - * - * @param obj - * the obj - * @return the i asset meta data - */ - ITransactionAttributes addAssets(DataModel obj); + ITransactionAttributes addAssets( Object assets, Class assetsDataClass ); /** * Adds the meta data. * - * @param metadata - * the metadata + * @param metaData + * the json object * @return the i asset meta data */ - ITransactionAttributes addMetaData(Map metadata); + ITransactionAttributes addMetaData( Object metaData ); /** - * Adds the meta data. + * Add the class and deserializer for metadata * - * @param obj - * the obj - * @return the i asset meta data + * @param metaDataClass the class of the metadata object + * @param jsonDeserializer the deserializer + * @return */ - ITransactionAttributes addMetaData(DataModel obj); + ITransactionAttributes addMetaDataClassDeserializer( Class metaDataClass, JsonDeserializer jsonDeserializer ); /** - * Adds the meta data. + * Add the class and serializer for metadata * - * @param jsonObject - * the json object - * @return the i asset meta data + * @param metaDataClass the class of the metadata object + * @param jsonSerializer the deserializer + * @return */ - ITransactionAttributes addMetaData(JsonObject jsonObject); + ITransactionAttributes addMetaDataClassSerializer( Class metaDataClass, JsonSerializer jsonSerializer ); /** * Builds the. @@ -220,9 +201,11 @@ public interface IBuild { public static class Builder implements ITransactionAttributes, IBuild { /** The metadata. */ - private Map metadata = null; + private Object metadata = null; + /** The assets. */ - private Map assets = new TreeMap(); + private Object assets = null; + private Class assetsDataClass = null; /** The public key. */ private EdDSAPublicKey publicKey; @@ -280,12 +263,7 @@ public ITransactionAttributes addOutput(String amount, EdDSAPublicKey... publicK @Override public ITransactionAttributes addInput(String fullfillment, FulFill fullFill) { - Input input = new Input(); - input.setFullFillment(fullfillment); - input.setFulFills(fullFill); - input.addOwner(KeyPairUtils.encodePublicKeyInBase58(publicKey)); - this.transaction.addInput(input); - return this; + return addInput( fullfillment, fullFill, this.publicKey ); } @Override @@ -310,71 +288,35 @@ public ITransactionAttributes addInput(String fullfillment, FulFill fullFill, Ed return this; } - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addAsset(java.lang.String, java.lang.String) - */ - @Override - public ITransactionAttributes addAsset(String key, String value) { - this.assets.put(key, value); - return this; - } - - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addMetaData(java.lang.String, java.lang.String) - */ - @Override - public ITransactionAttributes addMetaData(String key, String value) { - if (this.metadata == null) - this.metadata = new TreeMap(); - this.metadata.put(key, value); + public ITransactionAttributes addAssetDataClass( Class assetDataClass, JsonDeserializer jsonDeserializer ) + { return this; } - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addAssets(java.util.Map) + /** + * Add + * @param metaDataClass the class of the metadata object + * @param jsonDeserializer the deserializer + * @return self */ @Override - public ITransactionAttributes addAssets(Map assets) { - this.assets.putAll(assets); + public ITransactionAttributes addMetaDataClassDeserializer( Class metaDataClass, JsonDeserializer jsonDeserializer ) + { + TransactionDeserializer.setMetaDataClass( metaDataClass ); + TransactionsDeserializer.setMetaDataClass( metaDataClass ); + JsonUtils.addTypeAdapterDeserializer( metaDataClass, jsonDeserializer ); return this; } - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addMetaData(java.util.Map) - */ - @Override - public ITransactionAttributes addMetaData(Map metadata) { - if( this.metadata == null ) - this.metadata = new TreeMap(); - this.metadata.putAll(metadata); + public ITransactionAttributes addMetaDataClassSerializer( Class metaDataClass, JsonSerializer jsonSerializer ) + { + JsonUtils.addTypeAdapterSerializer( metaDataClass, jsonSerializer ); return this; } - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addMetaData(com.google.gson.JsonObject) - */ - @Override - public ITransactionAttributes addMetaData(JsonObject jsonObject) { + public ITransactionAttributes addMetaData( Object object ) + { + this.metadata = object; return this; } @@ -415,22 +357,19 @@ public IBuild build(EdDSAPublicKey publicKey) { this.transaction.setOperation("CREATE"); } - this.transaction.setAsset(new Asset(this.assets)); + this.transaction.setAsset(new Asset(this.assets, this.assetsDataClass)); this.transaction.setMetaData(this.metadata); this.transaction.setVersion("1.0"); - // Workaround to pop out the field. - JSONObject transactionJObject = DriverUtils.makeSelfSorting(new JSONObject(this.transaction.toString())); - transactionJObject.remove("id"); // no need before we sign + String temp = this.transaction.toHashInput(); + LOGGER.info( "TO BE HASHED ---->\n" + temp + "\n<" ); + JsonObject transactionJObject = DriverUtils.makeSelfSortingGson( temp ); SHA3.DigestSHA3 md = new SHA3.DigestSHA3(256); md.update(transactionJObject.toString().getBytes()); String id = DriverUtils.getHex(md.digest()); this.transaction.setId(id); - // we need it after. - transactionJObject.accumulate("id", id); - this.transaction = JsonUtils.fromJson(DriverUtils.makeSelfSorting(transactionJObject).toString(), - Transaction.class); + return this; } @@ -450,7 +389,7 @@ private void sign(EdDSAPrivateKey privateKey) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException { // signing the transaction - JSONObject transactionJObject = DriverUtils.makeSelfSorting(new JSONObject(this.transaction.toString())); + JsonObject transactionJObject = DriverUtils.makeSelfSortingGson(this.transaction.toString()); Signature edDsaSigner = new EdDSAEngine(MessageDigest.getInstance("SHA-512")); edDsaSigner.initSign(privateKey); edDsaSigner.update(transactionJObject.toString().getBytes()); @@ -459,7 +398,6 @@ private void sign(EdDSAPrivateKey privateKey) this.transaction.getInputs().get(0) .setFullFillment(Base64.encodeBase64URLSafeString(fulfillment.getEncoded())); this.transaction.setSigned(true); - } /* @@ -532,37 +470,18 @@ public Transaction sendTransaction() throws IOException { return this.transaction; } - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addAssets(com.authenteq.model.DataModel) - */ - @Override - public ITransactionAttributes addAssets(DataModel obj) { - Type mapType = new TypeToken>() { - }.getType(); - Map son = JsonUtils.getGson().fromJson(JsonUtils.toJson(obj), mapType); - this.assets.putAll(son); - return this; - } - - /* - * (non-Javadoc) - * - * @see - * com.authenteq.builders.BigchainDbTransactionBuilder.IAssetMetaData# - * addMetaData(com.authenteq.model.DataModel) + /** + * Add an asset along with the assetDataClass + * + * @param obj the asset data + * @param assetsDataClass the type of the asset data class + * + * @return self */ - @Override - public ITransactionAttributes addMetaData(DataModel obj) { - Type mapType = new TypeToken>() { - }.getType(); - Map son = JsonUtils.getGson().fromJson(JsonUtils.toJson(obj), mapType); - if (this.metadata == null) - this.metadata = new TreeMap(); - this.metadata.putAll(son); + public ITransactionAttributes addAssets( Object obj, Class assetsDataClass ) + { + this.assets = obj; + this.assetsDataClass = assetsDataClass; return this; } diff --git a/src/main/java/com/authenteq/json/strategy/AssetSerializer.java b/src/main/java/com/authenteq/json/strategy/AssetSerializer.java new file mode 100644 index 0000000..622250f --- /dev/null +++ b/src/main/java/com/authenteq/json/strategy/AssetSerializer.java @@ -0,0 +1,32 @@ +package com.authenteq.json.strategy; + +import com.authenteq.model.Asset; +import com.authenteq.util.JsonUtils; +import com.google.gson.*; + +import java.lang.reflect.Type; + +public class AssetSerializer implements JsonSerializer +{ + /** + * Serialize an asset object to json object + * Note: given the type of the asset.data it maybe necessary to + * to add a type adapter {@link JsonSerializer} and/or {@link JsonDeserializer} with {@link JsonUtils} and + * {@link com.authenteq.util.JsonUtils#addTypeAdapterSerializer} + * + * TODO test user.data with custom serializer + * + * @param src object to serialize + * @param typeOfSrc type of src + * @param context the json context + * @return the json object + */ + public JsonElement serialize( Asset src, Type typeOfSrc, JsonSerializationContext context ) + { + Gson gson = JsonUtils.getGson(); + JsonObject asset = new JsonObject(); + asset.add( "data", gson.toJsonTree( src.getData(), src.getDataClass() ) ); + + return asset; + } +} diff --git a/src/main/java/com/authenteq/json/strategy/AssetsDeserializer.java b/src/main/java/com/authenteq/json/strategy/AssetsDeserializer.java index be78fbd..9463d21 100644 --- a/src/main/java/com/authenteq/json/strategy/AssetsDeserializer.java +++ b/src/main/java/com/authenteq/json/strategy/AssetsDeserializer.java @@ -9,9 +9,6 @@ import com.google.gson.JsonParseException; import java.lang.reflect.Type; -import java.util.Iterator; - - /** * The Class AssetsDeserializer. @@ -26,9 +23,7 @@ public Assets deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon throws JsonParseException { Assets assets = new Assets(); - Iterator jsonIter = json.getAsJsonArray().iterator(); - while(jsonIter.hasNext()) { - JsonElement jElement = jsonIter.next(); + for( JsonElement jElement: json.getAsJsonArray() ) { assets.addAsset(JsonUtils.fromJson(jElement.getAsJsonObject().toString(), Asset.class)); } return assets; diff --git a/src/main/java/com/authenteq/json/strategy/TransactionDeserializer.java b/src/main/java/com/authenteq/json/strategy/TransactionDeserializer.java index 4d8daa1..3e91e42 100644 --- a/src/main/java/com/authenteq/json/strategy/TransactionDeserializer.java +++ b/src/main/java/com/authenteq/json/strategy/TransactionDeserializer.java @@ -10,13 +10,23 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import java.lang.reflect.Type; -import java.util.Iterator; import java.util.Map; /** * The Class TransactionsDeserializer. */ public class TransactionDeserializer implements JsonDeserializer { + private static Class metaDataClass = Map.class; + + /** + * Set a custom metadata class the class that is serialized should be symmetrical with the class that is deserialized. + * + * @param metaDataType the metaData class + */ + public static void setMetaDataClass( Class metaDataType ) + { + metaDataClass = metaDataType; + } /* * (non-Javadoc) @@ -27,37 +37,26 @@ public class TransactionDeserializer implements JsonDeserializer { */ @SuppressWarnings("unchecked") @Override - public Transaction deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - - // while(jsonIter.hasNext()) { + public Transaction deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { Transaction transaction = new Transaction(); JsonElement jElement = json.getAsJsonObject(); - transaction.setAsset(JsonUtils.fromJson(jElement.getAsJsonObject().get("asset").toString(), Asset.class)); - transaction.setMetaData((Map) JsonUtils - .fromJson(jElement.getAsJsonObject().get("metadata").toString(), Map.class)); + transaction.setAsset( JsonUtils.fromJson(jElement.getAsJsonObject().get("asset").toString(), Asset.class)); + transaction.setMetaData( JsonUtils.fromJson( jElement.getAsJsonObject().get("metadata").toString(), metaDataClass )); transaction.setId(jElement.getAsJsonObject().get("id").toString().replace("\"", "")); - Iterator jInputElementIter = jElement.getAsJsonObject().get("inputs").getAsJsonArray().iterator(); - - while (jInputElementIter.hasNext()) { - JsonElement jInputElement = jInputElementIter.next(); + for( JsonElement jInputElement: jElement.getAsJsonObject().get("inputs").getAsJsonArray() ) { transaction.addInput(JsonUtils.fromJson(jInputElement.toString(), Input.class)); } - Iterator jOutputElementIter = jElement.getAsJsonObject().get("outputs").getAsJsonArray() - .iterator(); - - while (jOutputElementIter.hasNext()) { - JsonElement jOutputElement = jOutputElementIter.next(); + for( JsonElement jOutputElement: jElement.getAsJsonObject().get("outputs").getAsJsonArray() ) { transaction.addOutput(JsonUtils.fromJson(jOutputElement.toString(), Output.class)); } transaction.setOperation(jElement.getAsJsonObject().get("operation").toString()); transaction.setVersion(jElement.getAsJsonObject().get("version").toString()); - - // } + return transaction; } } diff --git a/src/main/java/com/authenteq/json/strategy/TransactionIdExclusionStrategy.java b/src/main/java/com/authenteq/json/strategy/TransactionIdExclusionStrategy.java new file mode 100644 index 0000000..0916f23 --- /dev/null +++ b/src/main/java/com/authenteq/json/strategy/TransactionIdExclusionStrategy.java @@ -0,0 +1,18 @@ +package com.authenteq.json.strategy; + +import com.authenteq.model.Transaction; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; + +public class TransactionIdExclusionStrategy implements ExclusionStrategy +{ + public boolean shouldSkipClass( Class klass ) + { + return false; + } + + public boolean shouldSkipField( FieldAttributes f ) + { + return f.getDeclaringClass() == Transaction.class && f.getName().equals( "id" ); + } +} diff --git a/src/main/java/com/authenteq/json/strategy/TransactionsDeserializer.java b/src/main/java/com/authenteq/json/strategy/TransactionsDeserializer.java index 4f7da2e..88d400c 100644 --- a/src/main/java/com/authenteq/json/strategy/TransactionsDeserializer.java +++ b/src/main/java/com/authenteq/json/strategy/TransactionsDeserializer.java @@ -8,15 +8,18 @@ import com.google.gson.JsonParseException; import java.lang.reflect.Type; -import java.util.Iterator; import java.util.Map; - - /** * The Class TransactionsDeserializer. */ public class TransactionsDeserializer implements JsonDeserializer { + private static Class metaDataClass = Map.class; + + public static void setMetaDataClass( Class metaDataType ) + { + metaDataClass = metaDataType; + } /* (non-Javadoc) * @see com.google.gson.JsonDeserializer#deserialize(com.google.gson.JsonElement, java.lang.reflect.Type, com.google.gson.JsonDeserializationContext) @@ -27,26 +30,19 @@ public Transactions deserialize(JsonElement json, Type typeOfT, JsonDeserializat throws JsonParseException { Transactions transactions = new Transactions(); - Iterator jsonIter = json.getAsJsonArray().iterator(); - while(jsonIter.hasNext()) { + + for( JsonElement jElement: json.getAsJsonArray() ) { Transaction transaction = new Transaction(); - JsonElement jElement = jsonIter.next(); transaction.setAsset(JsonUtils.fromJson(jElement.getAsJsonObject().get("asset").toString(), Asset.class)); - transaction.setMetaData((Map)JsonUtils.fromJson(jElement.getAsJsonObject().get("metadata").toString(), Map.class)); + transaction.setMetaData( JsonUtils.fromJson( jElement.getAsJsonObject().get("metadata").toString(), metaDataClass )); transaction.setId(jElement.getAsJsonObject().get("id").toString()); - - Iterator jInputElementIter = jElement.getAsJsonObject().get("inputs").getAsJsonArray().iterator(); - - while(jInputElementIter.hasNext()) { - JsonElement jInputElement = jInputElementIter.next(); + + for( JsonElement jInputElement: jElement.getAsJsonObject().get("inputs").getAsJsonArray() ) { transaction.addInput(JsonUtils.fromJson(jInputElement.toString(), Input.class)); } - - Iterator jOutputElementIter = jElement.getAsJsonObject().get("outputs").getAsJsonArray().iterator(); - - while(jOutputElementIter.hasNext()) { - JsonElement jOutputElement = jOutputElementIter.next(); + + for( JsonElement jOutputElement: jElement.getAsJsonObject().get("outputs").getAsJsonArray() ) { transaction.addOutput(JsonUtils.fromJson(jOutputElement.toString(), Output.class)); } diff --git a/src/main/java/com/authenteq/model/Asset.java b/src/main/java/com/authenteq/model/Asset.java index 8e01021..92b15ac 100644 --- a/src/main/java/com/authenteq/model/Asset.java +++ b/src/main/java/com/authenteq/model/Asset.java @@ -4,12 +4,8 @@ import com.google.gson.annotations.SerializedName; import java.io.Serializable; -import java.util.Map; -import java.util.TreeMap; - - -/** +/* * The Class Asset. */ public class Asset implements Serializable { @@ -26,7 +22,11 @@ public class Asset implements Serializable { /** The data. */ @SerializedName("data") - private Map data; + private Object data; + + /** the data class the type of the data class needed for serialization/deserialization */ + @Exclude + private Class dataClass; /** * Instantiates a new asset. @@ -37,9 +37,11 @@ public Asset() {} * Instantiates a new asset. * * @param data the data + * @param dataClass due to type erasure the data class needs to be provided for serialization/deserialization */ - public Asset(Map data) { + public Asset(Object data, Class dataClass ) { this.data = data; + this.dataClass = dataClass; } /** @@ -47,17 +49,18 @@ public Asset(Map data) { * * @return the data */ - public Map getData() { + public Object getData() { return data; } /** - * Sets the data. + * return the type of the Asset data class * - * @param data the data + * @return the data class type */ - public void setData(Map data) { - this.data = data; + public Class getDataClass() + { + return dataClass; } /** @@ -77,23 +80,4 @@ public String getId() { public void setId(String id) { this.id = id; } - - - /** - * Adds the asset. - * - * @param key the key - * @param value the value - * @return the asset - */ - public Asset addAsset(String key, String value) { - if(this.data == null) { - this.data = new TreeMap(); - } - this.data.put(key, value); - return this; - } - - - } diff --git a/src/main/java/com/authenteq/model/Transaction.java b/src/main/java/com/authenteq/model/Transaction.java index 05a7d5f..332f375 100644 --- a/src/main/java/com/authenteq/model/Transaction.java +++ b/src/main/java/com/authenteq/model/Transaction.java @@ -1,16 +1,13 @@ package com.authenteq.model; import com.authenteq.annotations.Exclude; +import com.authenteq.json.strategy.TransactionIdExclusionStrategy; import com.authenteq.util.JsonUtils; import com.google.gson.annotations.SerializedName; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.TreeMap; - - /** * The Class Transaction. @@ -27,11 +24,11 @@ public class Transaction implements Serializable { /** The inputs. */ @SerializedName("inputs") - private List inputs = new ArrayList(); + private List inputs = new ArrayList<>(); /** The meta data. */ @SerializedName("metadata") - private Map metaData = null; + private Object metaData = null; /** The operation. */ @SerializedName("operation") @@ -39,7 +36,7 @@ public class Transaction implements Serializable { /** The outputs. */ @SerializedName("outputs") - private List outputs = new ArrayList(); + private List outputs = new ArrayList<>(); /** The version. */ @SerializedName("version") @@ -126,17 +123,18 @@ public void setInputs(List inputs) { * * @return the meta data */ - public Map getMetaData() { + public Object getMetaData() { return metaData; } /** - * Sets the meta data. + * Set the metaData object * - * @param metaData the meta data + * @param obj the metadata object */ - public void setMetaData(Map metaData) { - this.metaData = metaData; + public void setMetaData( Object obj ) + { + this.metaData = obj; } /** @@ -211,20 +209,6 @@ public void addOutput(Output output) { this.outputs.add(output); } - /** - * Adds the meta data. - * - * @param key the key - * @param value the value - * @return the transaction - */ - public Transaction addMetaData(String key, String value) { - if( this.metaData == null ) - this.metaData = new TreeMap(); - this.metaData.put(key, value); - return this; - } - /* (non-Javadoc) * @see java.lang.Object#toString() */ @@ -232,4 +216,14 @@ public Transaction addMetaData(String key, String value) { public String toString() { return JsonUtils.toJson(this); } + + /** + * Return the transaction suitable for hashing. + * + * @return the transaction as a json string + */ + public String toHashInput() + { + return JsonUtils.toJson( this, new TransactionIdExclusionStrategy() ); + } } diff --git a/src/main/java/com/authenteq/model/TransactionModel.java b/src/main/java/com/authenteq/model/TransactionModel.java index c1bd25b..c800498 100644 --- a/src/main/java/com/authenteq/model/TransactionModel.java +++ b/src/main/java/com/authenteq/model/TransactionModel.java @@ -22,6 +22,10 @@ import com.authenteq.util.Base58; import com.authenteq.util.DriverUtils; import com.authenteq.util.KeyPairUtils; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; import net.i2p.crypto.eddsa.EdDSAEngine; import net.i2p.crypto.eddsa.EdDSAPrivateKey; import net.i2p.crypto.eddsa.EdDSAPublicKey; @@ -32,16 +36,11 @@ import org.bouncycastle.jcajce.provider.digest.SHA3; import org.interledger.cryptoconditions.types.Ed25519Sha256Condition; import org.interledger.cryptoconditions.types.Ed25519Sha256Fulfillment; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import java.security.*; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; - /** * The Class Transaction. */ @@ -51,13 +50,13 @@ public class TransactionModel { private EdDSAPublicKey publicKey; /** The data. */ - private JSONObject data; + private JsonObject data; /** The metadata. */ - private JSONObject metadata; + private JsonObject metadata; /** The transaction json. */ - private JSONObject transactionJson; + private JsonObject transactionJson; /** The signed. */ private boolean signed; @@ -70,10 +69,10 @@ public class TransactionModel { * (can be `null` if not needed) * @param publicKey the public key */ - public TransactionModel(JSONObject data, JSONObject metadata, EdDSAPublicKey publicKey) { + public TransactionModel(JsonObject data, JsonObject metadata, EdDSAPublicKey publicKey) { this.publicKey = publicKey; - this.data = DriverUtils.makeSelfSorting(data); - this.metadata = DriverUtils.makeSelfSorting(metadata); + this.data = DriverUtils.makeSelfSortingGson(data); + this.metadata = DriverUtils.makeSelfSortingGson(metadata); buildTransactionJson(); } @@ -86,12 +85,12 @@ public TransactionModel(JSONObject data, JSONObject metadata, EdDSAPublicKey pub * @param publicKey the public key * @param signed the signed */ - private TransactionModel(JSONObject data, JSONObject metadata, JSONObject transactionJson, - EdDSAPublicKey publicKey, boolean signed) { + private TransactionModel( JsonObject data, JsonObject metadata, JsonObject transactionJson, + EdDSAPublicKey publicKey, boolean signed) { this.publicKey = publicKey; - this.data = DriverUtils.makeSelfSorting(data); - this.metadata = DriverUtils.makeSelfSorting(metadata); - this.transactionJson = DriverUtils.makeSelfSorting(transactionJson); + this.data = DriverUtils.makeSelfSortingGson(data); + this.metadata = DriverUtils.makeSelfSortingGson(metadata); + this.transactionJson = DriverUtils.makeSelfSortingGson(transactionJson); this.signed = signed; } @@ -99,50 +98,50 @@ private TransactionModel(JSONObject data, JSONObject metadata, JSONObject transa * Builds the transaction JSON without actually signing it. */ protected void buildTransactionJson() { - JSONObject asset = DriverUtils.getSelfSortingJson(); - JSONObject outputs = DriverUtils.getSelfSortingJson(); - JSONObject inputs = DriverUtils.getSelfSortingJson(); - JSONObject condition = DriverUtils.getSelfSortingJson(); - JSONObject details = DriverUtils.getSelfSortingJson(); - JSONArray inputsArr = new JSONArray(); - JSONArray outputsArr = new JSONArray(); + JsonObject asset = DriverUtils.getSelfSortingJson(); + JsonObject outputs = DriverUtils.getSelfSortingJson(); + JsonObject inputs = DriverUtils.getSelfSortingJson(); + JsonObject condition = DriverUtils.getSelfSortingJson(); + JsonObject details = DriverUtils.getSelfSortingJson(); + JsonArray inputsArr = new JsonArray(); + JsonArray outputsArr = new JsonArray(); Ed25519Sha256Condition condition1 = new Ed25519Sha256Condition(publicKey); - JSONObject rootObject = DriverUtils.getSelfSortingJson(); + JsonObject rootObject = DriverUtils.getSelfSortingJson(); try { if (metadata == null) { - rootObject.put("metadata", JSONObject.NULL); + rootObject.add("metadata", null); } else { - rootObject.put("metadata", metadata); + rootObject.add("metadata", metadata); } - rootObject.put("operation", "CREATE"); - rootObject.put("version", "1.0"); - asset.put("data", data); - rootObject.put("asset", asset); - - outputs.put("amount", "1"); - JSONArray publicKeys = new JSONArray(); - publicKeys.put(KeyPairUtils.encodePublicKeyInBase58(publicKey)); - outputs.put("public_keys", publicKeys); - outputsArr.put(outputs); - rootObject.put("outputs", outputsArr); - - condition.put("uri", condition1.getUri().toString()); - - details.put("public_key", KeyPairUtils.encodePublicKeyInBase58(publicKey)); - details.put("type", "ed25519-sha-256"); - condition.put("details", details); - outputs.put("condition", condition); - - inputs.put("fulfillment", JSONObject.NULL); - inputs.put("fulfills", JSONObject.NULL); - JSONArray ownersBefore = new JSONArray(); - ownersBefore.put(KeyPairUtils.encodePublicKeyInBase58(publicKey)); - inputs.put("owners_before", ownersBefore); - inputsArr.put(inputs); - rootObject.put("inputs", inputsArr); + rootObject.addProperty("operation", "CREATE"); + rootObject.addProperty("version", "1.0"); + asset.add("data", data); + rootObject.add("asset", asset); + + outputs.addProperty("amount", "1"); + JsonArray publicKeys = new JsonArray(); + publicKeys.add(KeyPairUtils.encodePublicKeyInBase58(publicKey)); + outputs.add("public_keys", publicKeys); + outputsArr.add(outputs); + rootObject.add("outputs", outputsArr); + + condition.addProperty("uri", condition1.getUri().toString()); + + details.addProperty("public_key", KeyPairUtils.encodePublicKeyInBase58(publicKey)); + details.addProperty("type", "ed25519-sha-256"); + condition.add("details", details); + outputs.add("condition", condition); + + inputs.add("fulfillment", null); + inputs.add("fulfills", null); + JsonArray ownersBefore = new JsonArray(); + ownersBefore.add(KeyPairUtils.encodePublicKeyInBase58(publicKey)); + inputs.add("owners_before", ownersBefore); + inputsArr.add(inputs); + rootObject.add("inputs", inputsArr); // getting SHA3 hash of the current JSON object SHA3.DigestSHA3 md = new SHA3.DigestSHA3(256); @@ -150,8 +149,8 @@ protected void buildTransactionJson() { String id = DriverUtils.getHex(md.digest()); // putting the hash as id field - rootObject.put("id", id); - } catch (JSONException e) { + rootObject.addProperty("id", id); + } catch (Exception e) { e.printStackTrace(); } @@ -166,7 +165,7 @@ protected void buildTransactionJson() { * fulfillment */ public String getTransactionId() { - return transactionJson.getString("id"); + return transactionJson.get("id").getAsString(); } /** @@ -184,10 +183,10 @@ public void signTransaction(EdDSAPrivateKey privateKey) throws InvalidKeyExcepti edDsaSigner.update(transactionJson.toString().getBytes()); byte[] signature = edDsaSigner.sign(); Ed25519Sha256Fulfillment fulfillment = new Ed25519Sha256Fulfillment(publicKey, signature); - JSONObject inputs = transactionJson.getJSONArray("inputs").getJSONObject(0); - inputs.put("fulfillment", Base64.encodeBase64URLSafeString(fulfillment.getEncoded())); + JsonObject inputs = transactionJson.get("inputs").getAsJsonArray().get( 0 ).getAsJsonObject();// getJsonArray("inputs").getJSONObject(0); + inputs.addProperty("fulfillment", Base64.encodeBase64URLSafeString(fulfillment.getEncoded())); signed = true; - } catch (JSONException | NoSuchAlgorithmException e) { + } catch ( NoSuchAlgorithmException e) { e.printStackTrace(); } } @@ -206,7 +205,7 @@ public boolean isSigned() { * * @return The JSON representation of the transaction */ - public JSONObject getTransactionJson() { + public JsonObject getTransactionJson() { return transactionJson; } @@ -236,7 +235,7 @@ public EdDSAPublicKey getPublicKey() { * * @return the data */ - public JSONObject getData() { + public JsonObject getData() { return data; } @@ -245,7 +244,7 @@ public JSONObject getData() { * * @return the metadata */ - public JSONObject getMetadata() { + public JsonObject getMetadata() { return metadata; } @@ -257,21 +256,20 @@ public JSONObject getMetadata() { * @param jsonObject the json object * @return the transaction */ - public static TransactionModel createFromJson(JSONObject jsonObject) { - JSONObject data = jsonObject.getJSONObject("asset").getJSONObject("data"); - JSONObject metadata = jsonObject.getJSONObject("metadata"); - String publicKeyEncoded = jsonObject.getJSONArray("outputs").getJSONObject(0).getJSONArray("public_keys") - .getString(0); + public static TransactionModel createFromJson(JsonObject jsonObject) { + JsonObject data = jsonObject.get("asset").getAsJsonObject().get("data").getAsJsonObject(); + JsonObject metadata = jsonObject.get("metadata").getAsJsonObject(); + String publicKeyEncoded = jsonObject.get("outputs").getAsJsonArray().get(0).getAsJsonObject().get("public_keys").getAsJsonArray().get(0).getAsString(); byte[] publicKey = Base58.decode(publicKeyEncoded); EdDSAParameterSpec keySpecs = EdDSANamedCurveTable.getByName("Ed25519"); EdDSAPublicKeySpec spec = new EdDSAPublicKeySpec(publicKey, keySpecs); EdDSAPublicKey edDSAPublicKey = new EdDSAPublicKey(spec); // TODO: validate the signature - Object fulfObject = jsonObject.getJSONArray("inputs").getJSONObject(0).get("fulfillment"); + JsonElement fulfObject = jsonObject.get("inputs").getAsJsonArray().get(0).getAsJsonObject().get("fulfillment"); boolean signed = false; - if (!JSONObject.NULL.equals(fulfObject)) + if ( ! fulfObject.equals( JsonNull.INSTANCE ) ) signed = true; return new TransactionModel(data, metadata, jsonObject, edDSAPublicKey, signed); @@ -283,25 +281,23 @@ public static TransactionModel createFromJson(JSONObject jsonObject) { * @param jsonArray the json array * @return the list */ - public static List createFromJsonArray(JSONArray jsonArray) { + public static List createFromJsonArray(JsonArray jsonArray) { List bigChaindbTransactionList = new ArrayList(); - Iterator jsonObjectIter = jsonArray.iterator(); - while (jsonObjectIter.hasNext()) { - JSONObject jsonObject = (JSONObject)jsonObjectIter.next(); - JSONObject data = jsonObject.getJSONObject("asset").getJSONObject("data"); - JSONObject metadata = jsonObject.getJSONObject("metadata"); - String publicKeyEncoded = jsonObject.getJSONArray("outputs").getJSONObject(0).getJSONArray("public_keys") - .getString(0); + for( JsonElement jsonElement: jsonArray ) { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + JsonObject data = jsonObject.get("asset").getAsJsonObject().get("data").getAsJsonObject(); + JsonObject metadata = jsonObject.get("metadata").getAsJsonObject(); + String publicKeyEncoded = jsonObject.get("outputs").getAsJsonArray().get(0).getAsJsonObject().get("public_keys").getAsJsonArray().get(0).getAsString(); byte[] publicKey = Base58.decode(publicKeyEncoded); EdDSAParameterSpec keySpecs = EdDSANamedCurveTable.getByName("Ed25519"); EdDSAPublicKeySpec spec = new EdDSAPublicKeySpec(publicKey, keySpecs); EdDSAPublicKey edDSAPublicKey = new EdDSAPublicKey(spec); // TODO: validate the signature - Object fulfObject = jsonObject.getJSONArray("inputs").getJSONObject(0).get("fulfillment"); + JsonElement fulfObject = jsonObject.get("inputs").getAsJsonArray().get(0).getAsJsonObject().get("fulfillment"); boolean signed = false; - if (!JSONObject.NULL.equals(fulfObject)) + if ( ! fulfObject.equals( JsonNull.INSTANCE ) ) signed = true; bigChaindbTransactionList.add(new TransactionModel(data, metadata, jsonObject, edDSAPublicKey, signed)); diff --git a/src/main/java/com/authenteq/util/DriverUtils.java b/src/main/java/com/authenteq/util/DriverUtils.java index 9f81505..18e46a1 100644 --- a/src/main/java/com/authenteq/util/DriverUtils.java +++ b/src/main/java/com/authenteq/util/DriverUtils.java @@ -19,14 +19,10 @@ package com.authenteq.util; -import net.i2p.crypto.eddsa.EdDSAPublicKey; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.lang.reflect.Field; -import java.util.*; - +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; /** * The Class DriverUtils. @@ -54,6 +50,22 @@ public static String getHex(byte[] data) { return new String(outData); } + /** + * To conform with BigchainDB serialization + * + * @param input the json string to sort the properties for + * + * @return the json object + */ + public static JsonObject makeSelfSortingGson( String input ) + { + if( input == null ) + return null; + + JsonParser jsonParser = new JsonParser(); + return makeSelfSortingGson( jsonParser.parse( input ).getAsJsonObject() ); + } + /** * Make self sorting. * @@ -64,54 +76,31 @@ public static String getHex(byte[] data) { We are using a hack to make stardard org.json be automatically sorted by key desc alphabetically */ - public static JSONObject makeSelfSorting(JSONObject input) { + public static JsonObject makeSelfSortingGson(JsonObject input ) { if (input == null) return null; - JSONObject json = new JSONObject(); - Field map = null; - try { - map = json.getClass().getDeclaredField("map"); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - if (map == null) { - return json; - } + JsonObject json = new JsonObject(); - map.setAccessible(true);//because the field is private final... - try { - map.set(json, new TreeMap<>()); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - map.setAccessible(false); - - Iterator flavoursIter = input.keys(); - while (flavoursIter.hasNext()) { - String key = flavoursIter.next(); - try { - Object j = input.get(key); - if (j instanceof JSONObject) { - json.put(key, makeSelfSorting((JSONObject) j)); - } else if (j instanceof JSONArray) { - JSONArray h = (JSONArray) j; - List oList = new ArrayList(); - for (int i = 0; i < h.length(); i++) { - Object joi = h.get(i); - if (joi instanceof JSONObject) { - oList.add(makeSelfSorting((JSONObject) joi)); - json.put(key, oList); - } else { - oList.add((String) joi); - json.put(key, oList); - } + for( String key: input.keySet() ) { + JsonElement j = input.get(key); + if (j instanceof JsonObject) { + json.add(key, makeSelfSortingGson((JsonObject) j)); + } else if (j instanceof JsonArray ) { + JsonArray h = (JsonArray) j; + JsonArray oList = new JsonArray(); + for (int i = 0; i < h.size(); i++) { + JsonElement joi = h.get( i ); + if (joi instanceof JsonObject) { + oList.add(makeSelfSortingGson((JsonObject) joi)); + json.add(key, oList); + } else { + oList.add(joi); + json.add(key, oList); } - } else { - json.put(key, j); } - } catch (JSONException e) { - e.printStackTrace(); + } else { + json.add(key, j); } } @@ -126,8 +115,7 @@ public static JSONObject makeSelfSorting(JSONObject input) { /* We need to sort the keys in alphabetical order to sign the transaction successfully. */ - public static JSONObject getSelfSortingJson() { - JSONObject json = makeSelfSorting(new JSONObject()); - return json; + public static JsonObject getSelfSortingJson() { + return makeSelfSortingGson(new JsonObject()); } } diff --git a/src/main/java/com/authenteq/util/JsonUtils.java b/src/main/java/com/authenteq/util/JsonUtils.java index b12fa1f..aea469f 100644 --- a/src/main/java/com/authenteq/util/JsonUtils.java +++ b/src/main/java/com/authenteq/util/JsonUtils.java @@ -2,28 +2,53 @@ import com.authenteq.json.factory.GsonEmptyCheckTypeAdapterFactory; import com.authenteq.json.strategy.*; -import com.authenteq.model.Assets; -import com.authenteq.model.Outputs; -import com.authenteq.model.Transactions; -import com.authenteq.model.Votes; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import com.authenteq.model.*; +import com.google.gson.*; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Utility class for handling JSON serialization and deserialization. - * */ public class JsonUtils { /** The gson. */ - private static Gson gson; + private static String jsonDateFormat = "yyyy-MM-dd'T'HH:mm:ssX"; // Assumes Java 7 or higher + + private static Map typeAdaptersDeserialize = new ConcurrentHashMap(16) + {{ + put( Transaction.class.getCanonicalName(), new TypeAdapter( Transaction.class, new TransactionDeserializer() ) ); + put( Transactions.class.getCanonicalName(), new TypeAdapter( Transactions.class, new TransactionsDeserializer() ) ); + put( Assets.class.getCanonicalName(), new TypeAdapter( Assets.class, new AssetsDeserializer() ) ); + put( Outputs.class.getCanonicalName(), new TypeAdapter( Outputs.class, new OutputsDeserializer() ) ); + put( Votes.class.getCanonicalName(), new TypeAdapter( Votes.class, new VoteDeserializer() ) ); + }}; + + private static Map typeAdaptersSerialize = new ConcurrentHashMap(16) + {{ + put( Asset.class.getCanonicalName(), new TypeAdapter( Asset.class, new AssetSerializer() ) ); + }}; /** * Instantiates a new json utils. */ private JsonUtils() { } + + private static synchronized GsonBuilder base() + { + GsonBuilder builder = new GsonBuilder(); + + builder = builder + .serializeNulls() + .disableHtmlEscaping() + .setDateFormat( jsonDateFormat ) + .registerTypeAdapterFactory(new GsonEmptyCheckTypeAdapterFactory()) + .addSerializationExclusionStrategy(new CustomExclusionStrategy()); + + return builder; + } /** * Gets the gson. @@ -31,21 +56,74 @@ private JsonUtils() { * @return the gson */ public static Gson getGson() { - if (gson == null) { - GsonBuilder builder = new GsonBuilder(); - - gson = builder.setPrettyPrinting() - .serializeNulls() - .disableHtmlEscaping() - .setPrettyPrinting() - .registerTypeAdapter(Transactions.class, new TransactionsDeserializer()) - .registerTypeAdapter(Assets.class, new AssetsDeserializer()) - .registerTypeAdapter(Outputs.class, new OutputsDeserializer()) - .registerTypeAdapter(Votes.class, new VoteDeserializer()) - .registerTypeAdapterFactory(new GsonEmptyCheckTypeAdapterFactory()) - .addSerializationExclusionStrategy(new CustomExclusionStrategy()).create(); + GsonBuilder builder = base(); + + for( TypeAdapter value : typeAdaptersDeserialize.values() ) + builder.registerTypeAdapter( value.getType(), value.getSerializer() ); + + for( TypeAdapter value : typeAdaptersSerialize.values() ) + builder.registerTypeAdapter( value.getType(), value.getSerializer() ); + + return builder.create(); + } + + /** + * + * @return the gson + */ + public static Gson getGson( ExclusionStrategy... exclusionStrategies ) { + return getGson( null, exclusionStrategies ); + } + + /** + * + * @return the gson + */ + public static Gson getGson( Class ignoreClass, ExclusionStrategy... exclusionStrategies ) + { + GsonBuilder builder = base(); + + for( TypeAdapter value : typeAdaptersDeserialize.values() ) { + if( ignoreClass != null && value.getType().equals( ignoreClass ) ) + continue; + builder.registerTypeAdapter( value.getType(), value.getSerializer() ); + } + + for( TypeAdapter value : typeAdaptersSerialize.values() ) { + if( ignoreClass != null && value.getType().equals( ignoreClass ) ) + continue; + + builder.registerTypeAdapter( value.getType(), value.getSerializer() ); } - return gson; + + return builder.setExclusionStrategies( exclusionStrategies ).create(); + } + + public static void setJsonDateFormat( final String dateFormat ) + { + jsonDateFormat = dateFormat; + } + + /** + * Add a type adapter + * + * @param type the type (@Class) we're adapting + * @param jsonDeserializer the type's deserializer + */ + public static void addTypeAdapterDeserializer( Class type, JsonDeserializer jsonDeserializer ) + { + typeAdaptersDeserialize.put( type.getCanonicalName(), new TypeAdapter( type, jsonDeserializer ) ); + } + + /** + * Add a type adapter + * + * @param type the type (@Class) we're adapting + * @param jsonSerializer the type's deserializer + */ + public static void addTypeAdapterSerializer( Class type, JsonSerializer jsonSerializer ) + { + typeAdaptersSerialize.put( type.getCanonicalName(), new TypeAdapter( type, jsonSerializer ) ); } /** @@ -77,7 +155,20 @@ public static T fromJson(String json, Class T) { public static String toJson(Object src) { return getGson().toJson(src); } - + + /** + * To json. + * + * @param src + * the object for which Json representation is to be created + * setting for Gson . + * @return Json representation of src. + * @see Gson#toJson(Object) + */ + public static String toJson(Object src, ExclusionStrategy ... exclusionStrategies) { + return getGson( exclusionStrategies ).toJson(src); + } + /* * (non-Javadoc) * @@ -87,5 +178,4 @@ public static String toJson(Object src) { public String toString() { return "JsonUtils []"; } - } diff --git a/src/main/java/com/authenteq/util/TypeAdapter.java b/src/main/java/com/authenteq/util/TypeAdapter.java new file mode 100644 index 0000000..220ac51 --- /dev/null +++ b/src/main/java/com/authenteq/util/TypeAdapter.java @@ -0,0 +1,57 @@ +package com.authenteq.util; + +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonSerializer; + +/** + * container for storing type sdapter information + */ +public class TypeAdapter +{ + private Class type; + private Object serializer; + + /** + * Contruct a type adapter + * + * @param type the class + * @param serializer its serializer + */ + TypeAdapter( Class type, JsonDeserializer serializer ) + { + this.type = type; + this.serializer = serializer; + } + + /** + * Contruct a type adapter + * + * @param type the class + * @param serializer its serializer + */ + TypeAdapter( Class type, JsonSerializer serializer ) + { + this.type = type; + this.serializer = serializer; + } + + /** + * Get the deserializer + * + * @return the deserializer + */ + public Object getSerializer() + { + return this.serializer; + } + + /** + * Get the class for the deserializer + * + * @return the class + */ + public Class getType() + { + return type; + } +} \ No newline at end of file diff --git a/src/test/java/com/authenteq/BigchaindbTransactionTest.java b/src/test/java/com/authenteq/BigchaindbTransactionTest.java index b28e1b5..a4c92eb 100644 --- a/src/test/java/com/authenteq/BigchaindbTransactionTest.java +++ b/src/test/java/com/authenteq/BigchaindbTransactionTest.java @@ -262,6 +262,8 @@ import com.authenteq.model.TransactionModel; import com.authenteq.util.JsonUtils; import com.authenteq.util.KeyPairUtils; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import net.i2p.crypto.eddsa.EdDSAEngine; import net.i2p.crypto.eddsa.EdDSAPrivateKey; import net.i2p.crypto.eddsa.EdDSAPublicKey; @@ -274,11 +276,10 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.interledger.cryptoconditions.types.Ed25519Sha256Condition; import org.interledger.cryptoconditions.types.Ed25519Sha256Fulfillment; -import org.json.JSONObject; import org.junit.Test; -import sun.security.util.KeyUtil; import java.security.*; +import java.util.TreeMap; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -289,9 +290,10 @@ * The Class BigchaindbTransactionTest. */ public class BigchaindbTransactionTest { - + private JsonParser jsonParser = new JsonParser(); + /** The Constant SHOULD_BE_FULFILMENT. */ - static final String SHOULD_BE_FULFILMENT = "pGSAIOJUaCNTxPOZO2g7x0h6cFHt4LmgrN1LNGXh9q7IDOKxgUDSvX-fMwu6b-VdHQj9plPncX-XiS-VIgBWHPd13hNlB3G-C6grKqzHYGjEGvcJ_fcfD9wy-QHwN4hEfyvebkAM"; + static final String SHOULD_BE_FULFILMENT = "pGSAIOJUaCNTxPOZO2g7x0h6cFHt4LmgrN1LNGXh9q7IDOKxgUAATCXo2r_eqIeRotaioUYOQzoaZTedmFMzQVfY4VOcCd5VO69SkFO3R6dJ8y-qQ0pEzuHDIOGKILoGOU87iWkI"; /** The Constant JSON_REPR_SIGNED. */ static final String JSON_REPR_SIGNED = "{\n" + @@ -381,16 +383,16 @@ public class BigchaindbTransactionTest { */ @Test public void transactionGenerationTest() throws Exception { - JSONObject data = new JSONObject(); - data.put("expiration", "NLpPB8MpOkQLZJuyn4rXacdQBXOt4OAwQUSAEpipi2Y=\\n"); - data.put("lat", "DP\\/p9q4D7L0IBZr53Dh98N1huD5BGG\\/nZ9zs\\/ydEUzc=\\n"); - data.put("lon", "ZPleIXiR3W4RWzjrdXcqXDYUjPGGQn6JKmMF5OH7T6U=\\n"); - data.put("firstname", "NLpPB8MpOkQLZJuyn4rXacdQBXOt4OAwQUSAEpipi2Y=\\n"); - data.put("lastname", "N4iDURp+thKsn1Mn7csSoU63QJnJxqyz+VNOPUikMMk=\\n"); - data.put("dob", "ZBJhOnJgC\\/E\\/iD2eyh15qWqD3jsyj+k9+2XIDJXvhEE=\\n"); - data.put("sex", "lg52\\/gnwsTWdwUW4teyj4SGQOF7y5C435on9HtW3DwI=\\n"); - data.put("nationality", "MjpcaVsVoR+5E5ov4Z2gAal1cUfYLUypL52nFqx7pyM=\\n"); - data.put("idNumber", "hsDKi81fiXWuNHoZrzezzTMHykjDIrAtiPozzPTkkbM=\\n"); + JsonObject data = new JsonObject(); + data.addProperty("expiration", "NLpPB8MpOkQLZJuyn4rXacdQBXOt4OAwQUSAEpipi2Y=\\n"); + data.addProperty("lat", "DP\\/p9q4D7L0IBZr53Dh98N1huD5BGG\\/nZ9zs\\/ydEUzc=\\n"); + data.addProperty("lon", "ZPleIXiR3W4RWzjrdXcqXDYUjPGGQn6JKmMF5OH7T6U=\\n"); + data.addProperty("firstname", "NLpPB8MpOkQLZJuyn4rXacdQBXOt4OAwQUSAEpipi2Y=\\n"); + data.addProperty("lastname", "N4iDURp+thKsn1Mn7csSoU63QJnJxqyz+VNOPUikMMk=\\n"); + data.addProperty("dob", "ZBJhOnJgC\\/E\\/iD2eyh15qWqD3jsyj+k9+2XIDJXvhEE=\\n"); + data.addProperty("sex", "lg52\\/gnwsTWdwUW4teyj4SGQOF7y5C435on9HtW3DwI=\\n"); + data.addProperty("nationality", "MjpcaVsVoR+5E5ov4Z2gAal1cUfYLUypL52nFqx7pyM=\\n"); + data.addProperty("idNumber", "hsDKi81fiXWuNHoZrzezzTMHykjDIrAtiPozzPTkkbM=\\n"); KeyPair keyPair = retrieveKeyPair(); @@ -405,20 +407,18 @@ public void transactionGenerationTest() throws Exception { (EdDSAPublicKey) keyPair.getPublic()); Signature edDsaSigner = new EdDSAEngine(MessageDigest.getInstance("SHA-512")); - JSONObject rootObject = new JSONObject(bigchaindbTransaction.getTransactionJson().toString()); - String fulfilmentVal = rootObject.getJSONArray("inputs").getJSONObject(0).getString("fulfillment"); - rootObject.getJSONArray("inputs").getJSONObject(0).put("fulfillment", JSONObject.NULL); + JsonObject rootObject = jsonParser.parse( bigchaindbTransaction.getTransactionJson().toString()).getAsJsonObject(); + String fulfilmentVal = rootObject.get("inputs").getAsJsonArray().get(0).getAsJsonObject().get("fulfillment").getAsString(); + rootObject.get("inputs").getAsJsonArray().get(0).getAsJsonObject().add("fulfillment", null); edDsaSigner.initSign(keyPair.getPrivate()); edDsaSigner.update(rootObject.toString().getBytes()); byte[] signature = edDsaSigner.sign(); - Ed25519Sha256Fulfillment fulfillment - = new Ed25519Sha256Fulfillment((EdDSAPublicKey) keyPair.getPublic(), signature); - assertEquals("4eff006ca203061d6bc1100959018f008c0f61a4b53c5d8a333159adf69a7c46", rootObject.getString("id")); - assertEquals("4eff006ca203061d6bc1100959018f008c0f61a4b53c5d8a333159adf69a7c46", bigchaindbTransaction.getTransactionId()); + Ed25519Sha256Fulfillment fulfillment = new Ed25519Sha256Fulfillment((EdDSAPublicKey) keyPair.getPublic(), signature); + assertEquals("7a9f2830564b8d21acb1579a09c34904b694aeeabe670df20752d4d731ec96ea", rootObject.get("id").getAsString()); + assertEquals("7a9f2830564b8d21acb1579a09c34904b694aeeabe670df20752d4d731ec96ea", bigchaindbTransaction.getTransactionId()); assertEquals(SHOULD_BE_FULFILMENT, fulfilmentVal); assertTrue(fulfillment.verify(condition1, rootObject.toString().getBytes())); -// return rootObject.toString(); } /** @@ -428,10 +428,8 @@ public void transactionGenerationTest() throws Exception { */ @Test public void transactionFromJson() throws Exception { - TransactionModel transactionSigned - = TransactionModel.createFromJson(new JSONObject(JSON_REPR_SIGNED)); - TransactionModel transactionUnsigned - = TransactionModel.createFromJson(new JSONObject(JSON_REPR_UNSIGNED)); + TransactionModel transactionSigned = TransactionModel.createFromJson(jsonParser.parse(JSON_REPR_SIGNED).getAsJsonObject()); + TransactionModel transactionUnsigned = TransactionModel.createFromJson(jsonParser.parse(JSON_REPR_UNSIGNED).getAsJsonObject()); String publicEncoded = KeyPairUtils.encodePublicKeyInBase58(transactionSigned.getPublicKey()); assertEquals(SHOULD_BE_PUBLIC_KEY, publicEncoded); @@ -445,12 +443,13 @@ public void transactionFromJson() throws Exception { @Test public void transactionMetaDataIsNull() { KeyPair alice = KeyPairUtils.generateNewKeyPair(); - + + TreeMap assetData = new TreeMap() {{ put( "owner", "alice" ); }}; Transaction transaction = BigchainDbTransactionBuilder.init() - .addAsset( "owner", "alice" ) + .addAssets( assetData, assetData.getClass() ) .buildAndSignOnly( (EdDSAPublicKey) alice.getPublic(), (EdDSAPrivateKey) alice.getPrivate() ); - assertTrue( transaction.toString().contains( "\"metadata\": null" ) ); + assertTrue( transaction.toString().contains( "\"metadata\":null" ) ); Transaction tx = JsonUtils.fromJson( transaction.toString(), Transaction.class ); assertNull( tx.getMetaData() ); } diff --git a/src/test/java/com/authenteq/api/AssetsApiTest.java b/src/test/java/com/authenteq/api/AssetsApiTest.java index aee93d4..202cb99 100644 --- a/src/test/java/com/authenteq/api/AssetsApiTest.java +++ b/src/test/java/com/authenteq/api/AssetsApiTest.java @@ -4,19 +4,19 @@ import java.io.IOException; import java.security.KeyPair; +import java.util.Map; +import java.util.TreeMap; -import com.authenteq.AbstractTest; import com.authenteq.builders.BigchainDbTransactionBuilder; +import com.authenteq.json.strategy.AssetSerializer; +import com.authenteq.model.Asset; import com.authenteq.model.Assets; import com.authenteq.model.StatusCode; import com.authenteq.model.Transaction; import net.i2p.crypto.eddsa.EdDSAPrivateKey; import net.i2p.crypto.eddsa.EdDSAPublicKey; -import org.junit.BeforeClass; import org.junit.Test; -import com.authenteq.builders.BigchainDbConfigBuilder; - import static org.junit.Assert.assertEquals; /** @@ -24,7 +24,6 @@ */ public class AssetsApiTest extends AbstractApiTest { - /** * Test asset search. */ @@ -37,10 +36,11 @@ public void testAssetSearch() // create transaction with unique asset net.i2p.crypto.eddsa.KeyPairGenerator edDsaKpg = new net.i2p.crypto.eddsa.KeyPairGenerator(); KeyPair alice = edDsaKpg.generateKeyPair(); + TreeMap assetData = new TreeMap() {{ put( "uuid", uuid ); }}; Transaction transaction = BigchainDbTransactionBuilder .init() - .addAsset( "uuid", uuid ) + .addAssets( assetData, Map.class ) .buildAndSign( (EdDSAPublicKey) alice.getPublic(), (EdDSAPrivateKey) alice.getPrivate() ) .sendTransaction(); assertEquals( StatusCode.VALID, getStatus( transaction ).getStatus() ); // wait for the transaction to be marked VALID diff --git a/src/test/java/com/authenteq/api/BlocksApiTest.java b/src/test/java/com/authenteq/api/BlocksApiTest.java index 6f05185..cd342da 100644 --- a/src/test/java/com/authenteq/api/BlocksApiTest.java +++ b/src/test/java/com/authenteq/api/BlocksApiTest.java @@ -7,6 +7,8 @@ import java.io.IOException; import java.security.KeyPair; import java.security.spec.InvalidKeySpecException; +import java.util.Map; +import java.util.TreeMap; import com.authenteq.AbstractTest; import org.junit.BeforeClass; @@ -38,13 +40,21 @@ public class BlocksApiTest extends AbstractApiTest @Test public void testBlockSearch() throws InterruptedException { try { - - Transaction transaction = BigchainDbTransactionBuilder.init().addAsset("middlename", "mname") - .addAsset("firstname", "John").addAsset("giddlename", "mname").addAsset("ziddlename", "mname") - .addAsset("lastname", "Smith").addMetaData("what", "My first BigchainDB transaction") - .operation(Operations.CREATE).buildAndSign((EdDSAPublicKey) Account.publicKeyFromHex(publicKey), - (EdDSAPrivateKey) Account.privateKeyFromHex(privateKey)) - .sendTransaction(); + Map metaData = new TreeMap() {{ put( "what", "My first BigchainDB transaction" ); }}; + Map assetData = new TreeMap() {{ + put( "middlename", "mname" ); + put("firstname", "John"); + put( "giddlename", "mname" ); + put( "ziddlename", "mname" ); + put( "lastname", "Smith" ); + }}; + + Transaction transaction = BigchainDbTransactionBuilder + .init() + .addAssets(assetData, TreeMap.class) + .operation(Operations.CREATE) + .buildAndSign((EdDSAPublicKey) Account.publicKeyFromHex(publicKey), (EdDSAPrivateKey) Account.privateKeyFromHex(privateKey)) + .sendTransaction(); assertFalse(BlocksApi.getBlocks(transaction.getId(), BlockStatus.VALID).isEmpty()); diff --git a/src/test/java/com/authenteq/api/OutputsApiTest.java b/src/test/java/com/authenteq/api/OutputsApiTest.java index 6373689..56b0cc1 100644 --- a/src/test/java/com/authenteq/api/OutputsApiTest.java +++ b/src/test/java/com/authenteq/api/OutputsApiTest.java @@ -29,7 +29,6 @@ public class OutputsApiTest extends AbstractApiTest /** * Test. - * @throws InvalidKeySpecException */ @Test public void testOutput() throws InvalidKeySpecException { diff --git a/src/test/java/com/authenteq/api/TransactionApiTest.java b/src/test/java/com/authenteq/api/TransactionApiTest.java index cefe2b0..be93d1c 100644 --- a/src/test/java/com/authenteq/api/TransactionApiTest.java +++ b/src/test/java/com/authenteq/api/TransactionApiTest.java @@ -1,8 +1,9 @@ package com.authenteq.api; -import com.authenteq.AbstractTest; import com.authenteq.builders.BigchainDbTransactionBuilder; import com.authenteq.constants.Operations; +import com.authenteq.json.strategy.TransactionDeserializer; +import com.authenteq.json.strategy.TransactionsDeserializer; import com.authenteq.model.Account; import com.authenteq.model.DataModel; import com.authenteq.model.GenericCallback; @@ -11,11 +12,17 @@ import net.i2p.crypto.eddsa.EdDSAPrivateKey; import net.i2p.crypto.eddsa.EdDSAPublicKey; import okhttp3.Response; +import org.junit.Assert; import org.junit.Test; import java.io.IOException; +import java.math.BigDecimal; import java.security.KeyPair; import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; +import java.util.Date; +import java.util.Map; +import java.util.TreeMap; import static org.junit.Assert.assertNotNull; @@ -51,15 +58,25 @@ public void testPostTransactionUsingBuilder() throws InvalidKeySpecException { dummyAsset.setDescription("asset"); try { - - Transaction transaction = BigchainDbTransactionBuilder.init().addAsset("middlename", "mname") - .addAsset("firstname", "John").addAsset("giddlename", "mname").addAsset("ziddlename", "mname") - .addAsset("lastname", "Smith").addMetaData("what", "My first BigchainDB transaction") - .addAsset("aa", JsonUtils.toJson(dummyAsset)) - .addMetaData("asa",JsonUtils.toJson(dummyAsset)) - .operation(Operations.CREATE) - .buildAndSign((EdDSAPublicKey)Account.publicKeyFromHex(publicKey), (EdDSAPrivateKey)Account.privateKeyFromHex(privateKey)) - .sendTransaction(); + Map metaData = new TreeMap() {{ + put( "what", "My first BigchainDB transaction" ); + put( "aaa", JsonUtils.toJson( dummyAsset )); + }}; + Map assetData = new TreeMap() {{ + put("middlename", "mname"); + put("firstname", "John"); + put("giddlename", "mname"); + put("ziddlename", "mname"); + put("lastname", "Smith"); + put("aa", JsonUtils.toJson(dummyAsset)); + }}; + Transaction transaction = BigchainDbTransactionBuilder + .init() + .addAssets(assetData, TreeMap.class) + .addMetaData(metaData) + .operation(Operations.CREATE) + .buildAndSign((EdDSAPublicKey)Account.publicKeyFromHex(publicKey), (EdDSAPrivateKey)Account.privateKeyFromHex(privateKey)) + .sendTransaction(); assertNotNull(transaction.toString()); } catch (IOException e) { @@ -81,7 +98,7 @@ public void testPostTransactionOfObjectUsingBuilder() { dummyMeta.setId("id"); dummyMeta.setDescription("meta"); - Transaction transaction = BigchainDbTransactionBuilder.init().addAssets(dummyAsset).addMetaData(dummyMeta) + Transaction transaction = BigchainDbTransactionBuilder.init().addAssets(dummyAsset, ObjectDummy.class).addMetaData(dummyMeta) .operation(Operations.CREATE) .buildAndSign((EdDSAPublicKey) keyPair.getPublic(), (EdDSAPrivateKey) keyPair.getPrivate()) .sendTransaction(); @@ -99,7 +116,13 @@ public void testPostTransactionUsingBuilderWithCallBack() { net.i2p.crypto.eddsa.KeyPairGenerator edDsaKpg = new net.i2p.crypto.eddsa.KeyPairGenerator(); KeyPair keyPair = edDsaKpg.generateKeyPair(); try { - BigchainDbTransactionBuilder.init().addAsset("firstname", "alvin").addMetaData("what", "bigchaintrans") + Map metaData = new TreeMap() {{ put( "what", "bigchaintrans" ); }}; + Map assetData = new TreeMap() {{ + put("firstname", "alvin"); + }}; + BigchainDbTransactionBuilder.init() + .addAssets(assetData, TreeMap.class) + .addMetaData(metaData) .operation(Operations.CREATE) .buildAndSign((EdDSAPublicKey) keyPair.getPublic(), (EdDSAPrivateKey) keyPair.getPrivate()) .sendTransaction(new GenericCallback() { @@ -127,6 +150,40 @@ public void otherError(Response response) { } } + @Test + public void testPostTransactionOfObjectMetaDataUsingBuilder() { + net.i2p.crypto.eddsa.KeyPairGenerator edDsaKpg = new net.i2p.crypto.eddsa.KeyPairGenerator(); + KeyPair keyPair = edDsaKpg.generateKeyPair(); + try { + ObjectDummy dummyAsset = new ObjectDummy(); + dummyAsset.setId("id"); + dummyAsset.setDescription("asset"); + System.out.println(dummyAsset.toMapString()); + + SomeMetaData metaData = new SomeMetaData(); + + Transaction transaction = BigchainDbTransactionBuilder + .init() + .addAssets(dummyAsset, ObjectDummy.class) + .addMetaData(metaData) + .operation(Operations.CREATE) + .buildAndSign((EdDSAPublicKey) keyPair.getPublic(), (EdDSAPrivateKey) keyPair.getPrivate()) + .sendTransaction(); + assertNotNull(transaction.getId()); + + String jsonString = JsonUtils.toJson( transaction ); + TransactionsDeserializer.setMetaDataClass( SomeMetaData.class ); + TransactionDeserializer.setMetaDataClass( SomeMetaData.class ); + Transaction x = JsonUtils.fromJson( jsonString,Transaction.class ); + SomeMetaData resultMetaData = ( SomeMetaData) x.getMetaData(); + Assert.assertEquals( 2, resultMetaData.porperty2.intValue() ); + Assert.assertEquals( 3, resultMetaData.properties.size() ); + Assert.assertEquals( "three", resultMetaData.properties.get( 2 ) ); + } catch (IOException e) { + e.printStackTrace(); + } + } + /** * Test transaction by asset id create. */ @@ -145,7 +202,7 @@ public void testTransactionByAssetIdCreate() { dummyMeta.setId("id"); dummyMeta.setDescription("meta"); - Transaction transaction = BigchainDbTransactionBuilder.init().addAssets(dummyAsset).addMetaData(dummyMeta) + Transaction transaction = BigchainDbTransactionBuilder.init().addAssets(dummyAsset, ObjectDummy.class).addMetaData(dummyMeta) .operation(Operations.CREATE) .buildAndSign((EdDSAPublicKey) keyPair.getPublic(), (EdDSAPrivateKey) keyPair.getPrivate()) .sendTransaction(); @@ -183,6 +240,15 @@ public String getDescription() { public void setDescription(String description) { this.description = description; } + } + public class SomeMetaData + { + public String property1 = "property1"; + public Integer porperty2 = 2; + public BigDecimal property3 = new BigDecimal( "3.3" ); + public int property4 = 4; + public ArrayList properties = new ArrayList() {{ add( "one" ); add( "two" ); add( "three"); }}; + public Date date = new Date(); } } From 36992f464a68e34848055ecb01cc67526e34307e Mon Sep 17 00:00:00 2001 From: timd Date: Fri, 12 Jan 2018 14:54:45 -0500 Subject: [PATCH 2/3] Trying to fix java-crypto-conditions dependency in Travis-CI --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9c5679b..eab0e9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,12 @@ jdk: - oraclejdk8 install: true +before_script: + - mvn install:install-file -Dfile=$TRAVIS_BUILD_DIR/libs/java-crypto-conditions-2.0.0-SNAPSHOT.jar -DgroupId=org.interledger -DartifactId=java-crypto-conditions -Dversion=2.0.0-SNAPSHOT -Dpackaging=jar + branches: only: - - master + - AssetAndMetaData-as-Obj-Issue-36 script: - mvn clean install From e189a8f5f44b4b0ea2936cebb47a7eff744b7082 Mon Sep 17 00:00:00 2001 From: agwego Date: Fri, 12 Jan 2018 15:02:13 -0500 Subject: [PATCH 3/3] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index eab0e9f..3b15523 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ before_script: branches: only: - - AssetAndMetaData-as-Obj-Issue-36 + - master script: - mvn clean install