diff --git a/pom.xml b/pom.xml index 05a452f4ef26d175a20d083895475b4eeb9037e0..246a4e95055b1bd5f8cdf3a8bab69d7029dce489 100644 --- a/pom.xml +++ b/pom.xml @@ -398,6 +398,15 @@ <plugin> <artifactId>maven-jar-plugin</artifactId> <version>2.2</version> + <configuration> + <archive> + <manifest> + <!-- This is need to override the option version, in configuration classes --> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> + </manifest> + </archive> + </configuration> </plugin> <plugin> diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/config/Configuration.java b/ucoinj-core/src/main/java/io/ucoin/client/core/config/Configuration.java index 6838eee81e5021e2e83b549c528730e9ea877796..2819860ba16b37dc66ef83bcb011339b8f9ca459 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/config/Configuration.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/config/Configuration.java @@ -72,6 +72,9 @@ public class Configuration { super(); this.applicationConfig = applicationConfig; this.optionKeyToNotSave = null; + + // Override application version + initVersion(applicationConfig); } public Configuration(String file, String... args) { @@ -99,6 +102,9 @@ public class Configuration { // Define Alias addAlias(applicationConfig); + // Override application version + initVersion(applicationConfig); + // get all transient and final option keys Set<String> optionToSkip = ApplicationConfigHelper.getTransientOptionKeys(providers); @@ -137,12 +143,20 @@ public class Configuration { applicationConfig.setOption( ConfigurationOption.BASEDIR.getKey(), appBasedir.getAbsolutePath()); + } + /** + * Override the version default option, from the MANIFEST implementation version (if any) + * @param applicationConfig + */ + protected void initVersion(ApplicationConfig applicationConfig) { // Override application version String implementationVersion = this.getClass().getPackage().getSpecificationVersion(); - applicationConfig.setOption( - ConfigurationOption.VERSION.getKey(), - implementationVersion); + if (implementationVersion != null) { + applicationConfig.setDefaultOption( + ConfigurationOption.VERSION.getKey(), + implementationVersion); + } } /** @@ -250,6 +264,10 @@ public class Configuration { return applicationConfig.getOptionAsInt(ConfigurationOption.NODE_ELASTICSEARCH_PORT.getKey()); } + public URL getNodeElasticSearchRestUrl() { + return applicationConfig.getOptionAsURL(ConfigurationOption.NODE_ELASTICSEARCH_REST_URL.getKey()); + } + public boolean isNodeElasticSearchLocal() { return applicationConfig.getOptionAsBoolean(ConfigurationOption.NODE_ELASTICSEARCH_LOCAL.getKey()); } diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/config/ConfigurationOption.java b/ucoinj-core/src/main/java/io/ucoin/client/core/config/ConfigurationOption.java index 22577583ac53d71a5e265d6da02ac3d4dcbbe4d2..4dd36a7d9efbae7a00d63e2aba26f40411f7c9aa 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/config/ConfigurationOption.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/config/ConfigurationOption.java @@ -168,6 +168,13 @@ public enum ConfigurationOption implements ConfigOptionDef { Integer.class, false), + NODE_ELASTICSEARCH_PROTOCOL( + "ucoinj.node.elasticsearch.protocol", + n("ucoinj.config.option.node.elasticsearch.protocol.description"), + "http", + String.class, + false), + NODE_ELASTICSEARCH_HOST( "ucoinj.node.elasticsearch.host", n("ucoinj.config.option.node.elasticsearch.host.description"), @@ -182,6 +189,34 @@ public enum ConfigurationOption implements ConfigOptionDef { Integer.class, false), + NODE_ELASTICSEARCH_REST_PROTOCOL( + "ucoinj.node.elasticsearch.rest.protocol", + n("ucoinj.config.option.node.elasticsearch.rest.protocol.description"), + "http", + String.class, + false), + + NODE_ELASTICSEARCH_REST_HOST( + "ucoinj.node.elasticsearch.rest.host", + n("ucoinj.config.option.node.elasticsearch.rest.host.description"), + "localhost", + String.class, + false), + + NODE_ELASTICSEARCH_REST_PORT( + "ucoinj.node.elasticsearch.rest.port", + n("ucoinj.config.option.node.elasticsearch.rest.port.description"), + "9200", + Integer.class, + false), + + NODE_ELASTICSEARCH_REST_URL( + "ucoinj.node.elasticsearch.rest.url", + n("ucoinj.config.option.node.elasticsearch.rest.url.description"), + "${ucoinj.node.elasticsearch.rest.protocol}://${ucoinj.node.elasticsearch.rest.host}:${ucoinj.node.elasticsearch.rest.port}", + URL.class, + false), + NODE_ELASTICSEARCH_LOCAL( "ucoinj.node.elasticsearch.local", n("ucoinj.config.option.node.elasticsearch.local.description"), diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/model/BlockchainBlock.java b/ucoinj-core/src/main/java/io/ucoin/client/core/model/BlockchainBlock.java index ab743cf7a9a4f57989cd30cabfa8248e322ce400..e0428b0f1169fe06d15b94d4b019c6902907d6af 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/model/BlockchainBlock.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/model/BlockchainBlock.java @@ -38,6 +38,7 @@ public class BlockchainBlock implements Serializable { private String version; private Integer nonce; + private Integer powMin; private Integer number; private Integer time; private Integer medianTime; @@ -76,6 +77,14 @@ public class BlockchainBlock implements Serializable { this.nonce = nonce; } + public Integer getPowMin() { + return powMin; + } + + public void setPowMin(Integer powMin) { + this.powMin = powMin; + } + public Integer getNumber() { return number; } diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/service/AbstractNetworkService.java b/ucoinj-core/src/main/java/io/ucoin/client/core/service/AbstractNetworkService.java index 8baf59e4ff0c5d7e24c888aa1b7ffbd8c6b181f8..ab2b3c554838d4173e39d32c622f448c6038a04e 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/service/AbstractNetworkService.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/service/AbstractNetworkService.java @@ -30,6 +30,7 @@ import com.google.gson.Gson; import io.ucoin.client.core.config.Configuration; import io.ucoin.client.core.technical.UCoinTechnicalException; import io.ucoin.client.core.technical.gson.GsonUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.http.HttpStatus; @@ -91,13 +92,29 @@ public class AbstractNetworkService extends BaseService implements Closeable { } } + protected URIBuilder getURIBuilder(String... path) { + String pathToAppend = Joiner.on('/').skipNulls().join(path); + + int customQueryStartIndex = pathToAppend.indexOf('?'); + String customQuery = null; + if (customQueryStartIndex != -1) { + customQuery = pathToAppend.substring(customQueryStartIndex+1); + pathToAppend = pathToAppend.substring(0, customQueryStartIndex); + } + + URIBuilder builder = new URIBuilder(baseUri); + + builder.setPath(baseUri.getPath() + pathToAppend); + if (StringUtils.isNotBlank(customQuery)) { + builder.setCustomQuery(customQuery); + } + + return builder; + } + protected URI getAppendedPath(String... path) { try { - String pathToAppend = Joiner.on('/').skipNulls().join(path); - - URIBuilder builder = new URIBuilder(baseUri); - builder.setPath(baseUri.getPath() + pathToAppend); - return builder.build(); + return getURIBuilder(path).build(); } catch(URISyntaxException e) { throw new UCoinTechnicalException(e); @@ -201,6 +218,10 @@ public class AbstractNetworkService extends BaseService implements Closeable { } return result.toString(); } + + protected Gson getGson() { + return gson; + } } diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/service/CryptoService.java b/ucoinj-core/src/main/java/io/ucoin/client/core/service/CryptoService.java index 4a66a1be0b3e7795be21c93386b0e57c5383d5ed..e29f9248e225a8b0b339ca11ca84aed9f25bc355 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/service/CryptoService.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/service/CryptoService.java @@ -112,6 +112,14 @@ public class CryptoService extends BaseService { ); } + public String sign(String message, String secretKey) { + byte[] messageBinary = decodeUTF8(message); + byte[] secretKeyBinary = decodeBase58(secretKey); + return encodeBase64( + sign(messageBinary, secretKeyBinary) + ); + } + public boolean verify(String message, String signature, String publicKey) { byte[] messageBinary = decodeUTF8(message); byte[] signatureBinary = decodeBase64(signature); diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/service/ServiceLocator.java b/ucoinj-core/src/main/java/io/ucoin/client/core/service/ServiceLocator.java index e8991b4894720e15397b4953a97997bbcedfedcb..591b1e378b6097d3be60191ea3d05f8791b67bb5 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/service/ServiceLocator.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/service/ServiceLocator.java @@ -26,6 +26,7 @@ package io.ucoin.client.core.service; import io.ucoin.client.core.service.search.BlockIndexerService; import io.ucoin.client.core.service.search.CurrencyIndexerService; import io.ucoin.client.core.service.search.ElasticSearchService; +import io.ucoin.client.core.service.search.client.CurrencyIndexerRestClientService; import io.ucoin.client.core.technical.UCoinTechnicalException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -113,9 +114,15 @@ public class ServiceLocator implements Closeable { return getService(BlockIndexerService.class); } + public CurrencyIndexerRestClientService getCurrencyIndexerRestClientService() { + return getService(CurrencyIndexerRestClientService.class); + } + + + /* -- Internal methods -- */ protected <S extends BaseService> S getService(Class<S> clazz) { - if (serviceCache.containsKey(clazz)) { + if (serviceCache.containsKey(clazz)) { return (S)serviceCache.get(clazz); } try { diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/CurrencyIndexerService.java b/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/CurrencyIndexerService.java index 628ac0faadfee8ed52264a9d379fb2a65aebd2d1..01643e36c8dbcfe912f786af7aee1db208663f49 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/CurrencyIndexerService.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/CurrencyIndexerService.java @@ -24,11 +24,15 @@ package io.ucoin.client.core.service.search; import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; +import com.google.gson.Gson; import io.ucoin.client.core.model.Currency; +import io.ucoin.client.core.service.CryptoService; import io.ucoin.client.core.service.ServiceLocator; import io.ucoin.client.core.technical.ObjectUtils; import io.ucoin.client.core.technical.UCoinTechnicalException; +import io.ucoin.client.core.technical.gson.GsonUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; @@ -70,7 +74,22 @@ public class CurrencyIndexerService extends BaseIndexerService { public static final String INDEX_TYPE_SIMPLE = "simple"; + public static final String REGEX_WORD_SEPARATOR = "[-\\t@# ]+"; + public static final String REGEX_SPACE = "[\\t\\n\\r ]+"; + + private CryptoService cryptoService; + private Gson gson; + public CurrencyIndexerService() { + super(); + this.gson = GsonUtils.newBuilder().create(); + } + + @Override + public void initialize() { + super.initialize(); + + this.cryptoService = ServiceLocator.instance().getCryptoService(); } public void deleteIndex() throws JsonProcessingException { @@ -125,9 +144,9 @@ public class CurrencyIndexerService extends BaseIndexerService { // Fill tags if (ArrayUtils.isEmpty(currency.getTags())) { String currencyName = currency.getCurrencyName(); - String[] tags = currencyName.split("[-\\t@#_ ]+"); + String[] tags = currencyName.split(REGEX_WORD_SEPARATOR); List<String> tagsList = Lists.newArrayList(tags); - tagsList.add(currencyName.replaceAll("[-\\t@#_ ]+", " ")); + tagsList.add(currencyName.replaceAll(REGEX_WORD_SEPARATOR, " ")); currency.setTags(tagsList.toArray(new String[tagsList.size()])); } @@ -168,7 +187,7 @@ public class CurrencyIndexerService extends BaseIndexerService { } public List<Currency> searchCurrencies(String query) { - String[] queryParts = query.split("[\\t ]+"); + String[] queryParts = query.split(REGEX_SPACE); // Prepare request SearchRequestBuilder searchRequest = getClient() @@ -226,32 +245,14 @@ public class CurrencyIndexerService extends BaseIndexerService { return CollectionUtils.extractSingleton(currencies); } - /* -- Internal methods -- */ - - protected void createCurrency(Currency currency) throws DuplicateIndexIdException, JsonProcessingException { - ObjectUtils.checkNotNull(currency, "currency could not be null") ; - ObjectUtils.checkNotNull(currency.getCurrencyName(), "currency attribute 'currencyName' could not be null"); - - Currency existingCurrency = getCurrencyById(currency.getCurrencyName()); - if (existingCurrency != null) { - throw new DuplicateIndexIdException(String.format("Currency with name [%s] already exists.", currency.getCurrencyName())); - } - - // register to currency - indexCurrency(currency); - - // Create sub indexes - ServiceLocator.instance().getBlockIndexerService().createIndex(currency.getCurrencyName()); - } - - protected void saveCurrency(Currency currency, String senderPubkey) throws DuplicateIndexIdException { + public void saveCurrency(Currency currency, String senderPubkey) throws DuplicateIndexIdException { ObjectUtils.checkNotNull(currency, "currency could not be null") ; ObjectUtils.checkNotNull(currency.getCurrencyName(), "currency attribute 'currencyName' could not be null"); Currency existingCurrency = getCurrencyById(currency.getCurrencyName()); // Currency not exists, so create it - if (existingCurrency == null) { + if (existingCurrency == null || currency.getSenderPubkey() == null) { // make sure to fill the sender currency.setSenderPubkey(senderPubkey); @@ -273,7 +274,64 @@ public class CurrencyIndexerService extends BaseIndexerService { } } + public List<String> getAllCurrencyNames() { + // Prepare request + SearchRequestBuilder searchRequest = getClient() + .prepareSearch(INDEX_NAME) + .setTypes(INDEX_TYPE_SIMPLE); + + // Sort as score/memberCount + searchRequest.addSort("currencyName", SortOrder.ASC) + .addField("_id"); + + // Execute query + SearchResponse searchResponse = searchRequest.execute().actionGet(); + // Read query result + return toCurrencyNames(searchResponse, true); + } + + public void registerCurrency(String pubkey, String jsonCurrency, String signature) { + Preconditions.checkNotNull(pubkey); + Preconditions.checkNotNull(jsonCurrency); + Preconditions.checkNotNull(signature); + + if (!cryptoService.verify(jsonCurrency, signature, pubkey)) { + String currencyName = GsonUtils.getValueFromJSONAsString(jsonCurrency, "currencyName"); + log.warn(String.format("Currency not added, because bad signature. currency [%s]", currencyName)); + throw new InvalidSignatureException("Bad signature"); + } + + Currency currency = null; + try { + currency = gson.fromJson(jsonCurrency, Currency.class); + Preconditions.checkNotNull(currency); + Preconditions.checkNotNull(currency.getCurrencyName()); + } catch(Throwable t) { + log.error("Error while reading currency JSON: " + jsonCurrency); + throw new UCoinTechnicalException("Error while reading currency JSON: " + jsonCurrency, t); + } + + saveCurrency(currency, pubkey); + } + + /* -- Internal methods -- */ + + protected void createCurrency(Currency currency) throws DuplicateIndexIdException, JsonProcessingException { + ObjectUtils.checkNotNull(currency, "currency could not be null") ; + ObjectUtils.checkNotNull(currency.getCurrencyName(), "currency attribute 'currencyName' could not be null"); + + Currency existingCurrency = getCurrencyById(currency.getCurrencyName()); + if (existingCurrency != null) { + throw new DuplicateIndexIdException(String.format("Currency with name [%s] already exists.", currency.getCurrencyName())); + } + + // register to currency + indexCurrency(currency); + + // Create sub indexes + ServiceLocator.instance().getBlockIndexerService().createIndex(currency.getCurrencyName()); + } protected List<Currency> toCurrencies(SearchResponse response, boolean withHighlight) { try { @@ -328,4 +386,15 @@ public class CurrencyIndexerService extends BaseIndexerService { return result; } + + protected List<String> toCurrencyNames(SearchResponse response, boolean withHighlight) { + // Read query result + SearchHit[] searchHits = response.getHits().getHits(); + List<String> result = Lists.newArrayListWithCapacity(searchHits.length); + for (SearchHit searchHit : searchHits) { + result.add(searchHit.getId()); + } + + return result; + } } diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/InvalidSignatureException.java b/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/InvalidSignatureException.java similarity index 96% rename from ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/InvalidSignatureException.java rename to ucoinj-core/src/main/java/io/ucoin/client/core/service/search/InvalidSignatureException.java index e33df6ea7aacf15af9a4e8a865b1f7c63a83f034..d5df0cf6bb7e2563067a738177ad07ebc99f0b0d 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/InvalidSignatureException.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/InvalidSignatureException.java @@ -1,4 +1,4 @@ -package io.ucoin.client.ui.service.rest; +package io.ucoin.client.core.service.search; /* * #%L diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/client/CurrencyIndexerRestClientService.java b/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/client/CurrencyIndexerRestClientService.java new file mode 100644 index 0000000000000000000000000000000000000000..b3e224d32773856e7f2a3ae0b3c5fe7a0d63c690 --- /dev/null +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/service/search/client/CurrencyIndexerRestClientService.java @@ -0,0 +1,122 @@ +package io.ucoin.client.core.service.search.client; + +import io.ucoin.client.core.config.Configuration; +import io.ucoin.client.core.model.Currency; +import io.ucoin.client.core.model.Wallet; +import io.ucoin.client.core.service.AbstractNetworkService; +import io.ucoin.client.core.service.CryptoService; +import io.ucoin.client.core.service.ServiceLocator; +import io.ucoin.client.core.technical.UCoinTechnicalException; +import io.ucoin.client.core.technical.gson.GsonUtils; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.List; + +/** + * Created by Benoit on 06/05/2015. + */ +public class CurrencyIndexerRestClientService extends AbstractNetworkService{ + private static final Logger log = LoggerFactory.getLogger(CurrencyIndexerRestClientService.class); + + public CurrencyIndexerRestClientService() { + super(); + } + + public boolean isNodeAlive() { + if (log.isDebugEnabled()) { + log.debug("Check if node is alive..."); + } + + // get currency + HttpGet httpGet = new HttpGet(getAppendedPath("/")); + String jsonString = executeRequest(httpGet, String.class); + + int statusCode = GsonUtils.getValueFromJSONAsInt(jsonString, "status"); + + return statusCode == HttpStatus.SC_OK; + } + + public List<String> getAllCurrencyNames() { + if (log.isDebugEnabled()) { + log.debug("Getting all currency names..."); + } + + // get currency + HttpGet httpGet = new HttpGet(getAppendedPath("/currency/simple/_search?_source=currencyName")); + String jsonString = executeRequest(httpGet, String.class); + + List<String> currencyNames = GsonUtils.getValuesFromJSONAsString(jsonString, "currencyName"); + + // Sort into alphabetical order + Collections.sort(currencyNames); + + return currencyNames; + } + + public void registerNewCurrency(Wallet wallet, Currency currency) { + if (log.isDebugEnabled()) { + log.debug("Registering a new currency..."); + } + + String currencyJson = getGson().toJson(currency); + CryptoService cryptoService = ServiceLocator.instance().getCryptoService(); + String signature = cryptoService.sign(currencyJson, wallet.getSecKey()); + + registerNewCurrency( + wallet.getPubKeyHash(), + currencyJson, + signature); + + // get currency + //HttpGet httpGet = new HttpGet(getAppendedPath("/currency/simple/_search?_source=currencyName")); + //String jsonString = executeRequest(httpGet, String.class); + + } + + public void registerNewCurrency(String pubkey, String jsonCurrency, String signature) { + if (log.isDebugEnabled()) { + log.debug("Registering a new currency..."); + } + + + URIBuilder builder = getURIBuilder("/rest/currency/add"); + builder.addParameter("pubkey", pubkey); + builder.addParameter("currency", jsonCurrency); + builder.addParameter("sig", signature); + + HttpGet httpGet; + try { + httpGet = new HttpGet(builder.build()); + } + catch(URISyntaxException e) { + throw new UCoinTechnicalException(e); + } + + String result = executeRequest(httpGet, String.class); + + if (log.isDebugEnabled()) { + log.debug("Server response, after currency registration: " + result); + } + + } + + /* -- -- */ + + protected URI initNodeURI(Configuration config) { + try { + URI nodeURI = config.getNodeElasticSearchRestUrl().toURI(); + + return nodeURI; + } catch (URISyntaxException ex) { + throw new UCoinTechnicalException(ex); + } + } + +} diff --git a/ucoinj-core/src/main/java/io/ucoin/client/core/technical/gson/GsonUtils.java b/ucoinj-core/src/main/java/io/ucoin/client/core/technical/gson/GsonUtils.java index d8dc0544721681ff0ab519c0f4cb5f9268314d20..084661bc0fbf955a778da5fd14e02edeff37e3e1 100644 --- a/ucoinj-core/src/main/java/io/ucoin/client/core/technical/gson/GsonUtils.java +++ b/ucoinj-core/src/main/java/io/ucoin/client/core/technical/gson/GsonUtils.java @@ -23,24 +23,90 @@ package io.ucoin.client.core.technical.gson; */ +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.gson.GsonBuilder; import io.ucoin.client.core.model.Identity; import io.ucoin.client.core.model.Member; +import io.ucoin.client.core.technical.UCoinTechnicalException; + +import java.text.DecimalFormat; +import java.text.ParseException; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class GsonUtils { public static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss"; - + + public static final String REGEX_ATTRIBUTE_STRING_VALUE = "\\\"%s\\\"\\s*:\\s*\"([^\"]+)\\\""; + + public static final String REGEX_ATTRIBUTE_NUMERIC_VALUE = "\\\"%s\\\"\\s*:\\s*([\\d]+(?:[.][\\d]+)?)"; + public static GsonBuilder newBuilder() { return new GsonBuilder() // make sure date will be serialized .setDateFormat(DATE_PATTERN) - // REgister Multimap adapter + // Register Multimap adapter .registerTypeAdapter(Multimap.class, new MultimapTypeAdapter()) // Register identity adapter .registerTypeAdapter(Identity.class, new IdentityTypeAdapter()) .registerTypeAdapter(Member.class, new MemberTypeAdapter()) ; } + + public static List<String> getValuesFromJSONAsString(String jsonString, String attributeName) { + Pattern pattern = Pattern.compile(String.format(REGEX_ATTRIBUTE_STRING_VALUE, attributeName)); + Matcher matcher = pattern.matcher(jsonString); + List<String> result = Lists.newArrayList(); + while (matcher.find()) { + String group = matcher.group(1); + result.add(group); + } + + return result; + } + + public static String getValueFromJSONAsString(String jsonString, String attributeName) { + Pattern pattern = Pattern.compile(String.format(REGEX_ATTRIBUTE_STRING_VALUE, attributeName)); + Matcher matcher = pattern.matcher(jsonString); + if (!matcher.find()) { + return null; + } + + return matcher.group(1); + } + + public static Number getValueFromJSONAsNumber(String jsonString, String attributeName) { + Preconditions.checkNotNull(jsonString); + Preconditions.checkNotNull(attributeName); + + Pattern pattern = Pattern.compile(String.format(REGEX_ATTRIBUTE_NUMERIC_VALUE, attributeName)); + Matcher matcher = pattern.matcher(jsonString); + + DecimalFormat decimalFormat = new DecimalFormat(); + decimalFormat.getDecimalFormatSymbols().setDecimalSeparator('.'); + + if (!matcher.find()) { + return null; + } + String group = matcher.group(1); + try { + Number result = decimalFormat.parse(group); + return result; + } catch (ParseException e) { + throw new UCoinTechnicalException(String.format("Error while parsing json numeric value, for attribute [%s]: %s", attributeName,e.getMessage()), e); + } + + } + + public static int getValueFromJSONAsInt(String jsonString, String attributeName) { + Number numberValue = getValueFromJSONAsNumber(jsonString, attributeName); + if (numberValue == null) { + return 0; + } + return numberValue.intValue(); + } } diff --git a/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/CurrencyIndexerServiceTest.java b/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/CurrencyIndexerServiceTest.java index a186af0336c0ba8a51f24b09ffc78e8dab20310b..7fb5515187a432a2b9a5f6d77adec57c03d7e982 100644 --- a/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/CurrencyIndexerServiceTest.java +++ b/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/CurrencyIndexerServiceTest.java @@ -127,6 +127,15 @@ public class CurrencyIndexerServiceTest { //assertResults(queryText, currencies); } + @Test + public void getAllCurrencyNames() { + List<String> currencyNames = service.getAllCurrencyNames(); + for (String currencyName: currencyNames) { + log.info(" - " + currencyName); + } + + } + /* -- internal methods */ protected void assertResults(String queryText, List<Currency> result) { diff --git a/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/client/CurrencyIndexerRestClientServiceTest.java b/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/client/CurrencyIndexerRestClientServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7765efd3ef8be610933a75ce884360290249b5b9 --- /dev/null +++ b/ucoinj-core/src/test/java/io/ucoin/client/core/service/indexer/client/CurrencyIndexerRestClientServiceTest.java @@ -0,0 +1,80 @@ +package io.ucoin.client.core.service.indexer.client; + +import io.ucoin.client.core.TestResource; +import io.ucoin.client.core.config.Configuration; +import io.ucoin.client.core.model.Currency; +import io.ucoin.client.core.model.Wallet; +import io.ucoin.client.core.service.CryptoService; +import io.ucoin.client.core.service.ServiceLocator; +import io.ucoin.client.core.service.search.client.CurrencyIndexerRestClientService; +import io.ucoin.client.core.technical.crypto.CryptoUtils; +import io.ucoin.client.core.technical.gson.GsonUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by Benoit on 06/05/2015. + */ +public class CurrencyIndexerRestClientServiceTest { + private static final Logger log = LoggerFactory.getLogger(CurrencyIndexerRestClientServiceTest.class); + + @ClassRule + public static final TestResource resource = TestResource.create(); + + private CurrencyIndexerRestClientService service; + private Configuration config; + + @Before + public void setUp() { + service = ServiceLocator.instance().getCurrencyIndexerRestClientService(); + config = Configuration.instance(); + } + + @Test + public void isNodeAlive() { + boolean isNodeAlive = service.isNodeAlive(); + Assert.assertTrue(isNodeAlive); + } + + @Test + public void getAllCurrencyNames() { + List<String> currencyNames = service.getAllCurrencyNames(); + for (String currencyName: currencyNames) { + log.info(" - " + currencyName); + } + } + + @Test + public void registerCurrency() { + Currency currency = new Currency(); + currency.setCurrencyName("register-test-" + System.currentTimeMillis()); + + String currencyJson = GsonUtils.newBuilder().create().toJson(currency); + + String pubKey = resource.getFixtures().getUserPublicKey(); + String secretKey = resource.getFixtures().getUserSecretKey(); + + CryptoService cryptoService = ServiceLocator.instance().getCryptoService(); + String signature = cryptoService.sign(currencyJson, secretKey); + + service.registerNewCurrency(pubKey, currencyJson, signature); + } + + /* -- -- */ + + protected Wallet createTestWallet() { + Wallet wallet = new Wallet( + resource.getFixtures().getCurrency(), + resource.getFixtures().getUid(), + CryptoUtils.decodeBase58(resource.getFixtures().getUserPublicKey()), + CryptoUtils.decodeBase58(resource.getFixtures().getUserSecretKey())); + + return wallet; + } +} diff --git a/ucoinj-core/src/test/resources/log4j.properties b/ucoinj-core/src/test/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..c3e49a9511ad13aaf4a1c992440c8590e12bba3e --- /dev/null +++ b/ucoinj-core/src/test/resources/log4j.properties @@ -0,0 +1,23 @@ +### +# Global logging configuration +log4j.rootLogger=ERROR, stdout, file + +# Console output +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %5p (%c:%L) - %m%n + +# ucoin levels +log4j.logger.io.ucoin=DEBUG +#log4j.logger.io.ucoin.client.core.service.AbstractNetworkService=WARN +log4j.logger.io.ucoin.client.core.service.AbstractNetworkService=TRACE + +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.file=ucoin-client.log +log4j.appender.file.MaxFileSize=10MB +log4j.appender.file.MaxBackupIndex=4 + +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ISO8601} %5p %c - %m%n + + diff --git a/ucoinj-core/src/test/resources/ucoinj-test.properties b/ucoinj-core/src/test/resources/ucoinj-test.properties index 52ed01bdef710ee4f5b0d9f66e01b375ead21e8a..dfda70024410f3c2de9d979ad64f38c7066888af 100644 --- a/ucoinj-core/src/test/resources/ucoinj-test.properties +++ b/ucoinj-core/src/test/resources/ucoinj-test.properties @@ -8,4 +8,10 @@ ucoinj.node.port=9201 ucoinj.node.elasticsearch.local.clusterName=data.ucoin.fr ucoinj.node.elasticsearch.host=192.168.0.5 -ucoinj.node.elasticsearch.port=9300 \ No newline at end of file +ucoinj.node.elasticsearch.port=9300 + +#ucoinj.node.elasticsearch.rest.host=www.data.ucoin.fr +#ucoinj.node.elasticsearch.rest.port=80 + +ucoinj.node.elasticsearch.rest.host=localhost +ucoinj.node.elasticsearch.rest.port=8080 \ No newline at end of file diff --git a/ucoinj-web/pom.xml b/ucoinj-web/pom.xml index 4515cbeacea22ea67713ea078e7f52fe50376444..a313a440bc88018dd67226038c26eb214b10e62a 100644 --- a/ucoinj-web/pom.xml +++ b/ucoinj-web/pom.xml @@ -245,13 +245,17 @@ <name>jetty.port</name> <value>8080</value> </systemProperty> + <systemProperty> + <name>log4j.configuration</name> + <value>${project.basedir}/src/test/resources/log4j.properties</value> + </systemProperty> </systemProperties> <jvmArgs>${jetty.forked.jvmArgs}</jvmArgs> <reload>${jetty.reload}</reload> <useProvidedScope>true</useProvidedScope> <webXml>${jetty.docroot}/WEB-INF/web.xml</webXml> - <!-- Add test-classes (to use test log4j.properties) --> - <extraClasspath>${project.build.directory}/test-classes/log4j.properties;</extraClasspath> + <!-- Add log4j.properties (from test resources) + <extraClasspath>${project.basedir}/src/test/resources/log4j.properties</extraClasspath>--> <scanTargetPatterns> <scanTargetPattern> <directory>${project.basedir}/target/classes</directory> @@ -267,6 +271,16 @@ </scanTargetPatterns> </configuration> <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j.version}</version> + </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> diff --git a/ucoinj-web/src/main/filtered-resources/log4j.properties b/ucoinj-web/src/main/filtered-resources/log4j.properties index 2b49a9d04312ccaa776af7d055198af2bd5622c0..3be3d3902d4f7ede17b6a4a70ae598ee9fd95c4c 100644 --- a/ucoinj-web/src/main/filtered-resources/log4j.properties +++ b/ucoinj-web/src/main/filtered-resources/log4j.properties @@ -13,6 +13,7 @@ log4j.logger.io.ucoin.client.core.config=WARN log4j.logger.org.nuiton.util=WARN log4j.logger.org.nuiton.config=WARN +log4j.logger.org.nuiton.converter=WARN log4j.logger.org.apache.commons.beanutils=WARN # file logging (compatible with Ifremer/RIC) diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication.java b/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication.java index d9fa2f83b5e01d857ae35711ba88e7956df14109..f832a14b0299d90ef50dad9b4c71fa01357cdf0b 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication.java +++ b/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication.java @@ -26,6 +26,7 @@ package io.ucoin.client.ui.application; import io.ucoin.client.ui.config.WebConfiguration; import io.ucoin.client.ui.pages.home.HomePage; import io.ucoin.client.ui.pages.login.LoginPage; +import io.ucoin.client.ui.pages.registry.CurrencyRegistryPage; import io.ucoin.client.ui.pages.wallet.WalletPage; import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession; import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication; @@ -58,12 +59,12 @@ public class UcoinApplication extends AuthenticatedWebApplication { mountPage("home", getHomePage()); mountPage("login", LoginPage.class); mountPage("wallet", WalletPage.class); + mountPage("register-currency", CurrencyRegistryPage.class); // Mount rest service, from annotations PackageScanner.scanPackage("io.ucoin.client.ui.service.rest"); getMarkupSettings().setStripWicketTags(true); - } /** diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication_fr.utf8.properties b/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication_fr.utf8.properties index 3f1b41d03fc55de33493ecb94f0311a440d38d9b..49a77ecbcc80fc536d80c6e6f61fdb0a69303886 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication_fr.utf8.properties +++ b/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinApplication_fr.utf8.properties @@ -5,4 +5,8 @@ home.title=uCoin registry - Discover free currencies home.search.hint=Rechercher une monnaie home.searchButton=Rechercher home.result.divider.currency=Monnaies -searchText=Rechercher \ No newline at end of file +searchText=Rechercher + +currency.register.pubkey=Votre clef publique (dans la monnaie) +currency.register.currencyJson=Information (format JSON) de la monnaie +currency.register.signature=Signature (du champ pr�c�dent) \ No newline at end of file diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinSession.java b/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinSession.java index d67561102faa3ef2ca8d863a20ef6d54256a7382..de0753180a3850282345f2b9ba225e453c2ec649 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinSession.java +++ b/ucoinj-web/src/main/java/io/ucoin/client/ui/application/UcoinSession.java @@ -37,13 +37,11 @@ public class UcoinSession extends AuthenticatedWebSession { @Override public boolean authenticate(String username, String password) { - // TODO Auto-generated method stub return false; } @Override public Roles getRoles() { - // TODO Auto-generated method stub return null; } } \ No newline at end of file diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/config/WebConfiguration.java b/ucoinj-web/src/main/java/io/ucoin/client/ui/config/WebConfiguration.java index accc05f3730dde72f1f4857268ee5d5a58756592..dc4beb74e746b3c419e28fa79ea76bfc19bf86cb 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/config/WebConfiguration.java +++ b/ucoinj-web/src/main/java/io/ucoin/client/ui/config/WebConfiguration.java @@ -25,24 +25,20 @@ package io.ucoin.client.ui.config; */ import io.ucoin.client.core.config.Configuration; -import org.apache.commons.io.FileUtils; +import io.ucoin.client.core.service.ServiceLocator; +import io.ucoin.client.core.technical.UCoinTechnicalException; import org.apache.commons.lang3.StringUtils; import org.nuiton.config.ApplicationConfig; -import org.nuiton.i18n.I18n; -import org.nuiton.i18n.init.DefaultI18nInitializer; -import org.nuiton.i18n.init.UserI18nInitializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.InitialContext; import javax.naming.NamingException; import java.io.File; -import java.io.IOException; -import java.util.Locale; public class WebConfiguration extends Configuration { - private static final String CONFIG_FILE_NAME = "ucoin-web.config"; + private static final String CONFIG_FILE_NAME = "ucoinj-web.config"; private static final String CONFIG_FILE_ENV_PROPERTY = CONFIG_FILE_NAME; @@ -53,7 +49,14 @@ public class WebConfiguration extends Configuration { private static final Logger log = LoggerFactory.getLogger(WebConfiguration.class); static { - instance = new WebConfiguration(getWebConfigFile()); + String configFile = getWebConfigFile(); + if (log.isDebugEnabled()) { + log.debug(String.format("Loading configuration from file [%s]", configFile)); + } + if (new File(configFile).exists() == false) { + log.warn(String.format("Configuration file not found [%s]. Make sure the path is correct.", configFile)); + } + instance = new WebConfiguration(configFile); initDefault(); } @@ -74,12 +77,8 @@ public class WebConfiguration extends Configuration { public WebConfiguration(String file, String... args) { super(file, args); - // Init i18n - /*try { - initI18n(); - } catch (IOException e) { - throw new UCoinTechnicalException("i18n initialization failed", e); - }*/ + // Init Crypto (NaCL lib...) + initCrypto(); } public String getVersionAsString() { @@ -109,36 +108,16 @@ public class WebConfiguration extends Configuration { return configFile; } - protected void initI18n() throws IOException { - - // --------------------------------------------------------------------// - // init i18n - // --------------------------------------------------------------------// - File i18nDirectory = new File(getDataDirectory(), "i18n"); - if (i18nDirectory.exists()) { - // clean i18n cache - FileUtils.cleanDirectory(i18nDirectory); - } - - FileUtils.forceMkdir(i18nDirectory); - - if (log.isDebugEnabled()) { - log.debug("I18N directory: " + i18nDirectory); - } - - Locale i18nLocale = getI18nLocale(); - + protected void initCrypto() { if (log.isInfoEnabled()) { - log.info(String.format("Starts i18n with locale [%s] at [%s]", - i18nLocale, i18nDirectory)); + log.info("Starts Sodium (NaCL) library"); } - I18n.init(new UserI18nInitializer( - i18nDirectory, new DefaultI18nInitializer(getI18nBundleName())), - i18nLocale); - } - protected static String getI18nBundleName() { - return "ucoin-web-i18n"; + try { + // This call will load the sodium library + ServiceLocator.instance().getCryptoService(); + } catch (Throwable e) { + throw new UCoinTechnicalException("Crypto lib (NaCL) initialization failed. Make sure sodium has been installed (or add library into a ./lib directory).", e); + } } - } diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/pages/registry/CurrencyRegistryPage.html b/ucoinj-web/src/main/java/io/ucoin/client/ui/pages/registry/CurrencyRegistryPage.html index 483c09f8021ee9548faa5ccb63cbdd539ffb9b9c..6e2cdab117edac78d9a237f95a3a58cd75b1b33b 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/pages/registry/CurrencyRegistryPage.html +++ b/ucoinj-web/src/main/java/io/ucoin/client/ui/pages/registry/CurrencyRegistryPage.html @@ -26,9 +26,18 @@ <body> <wicket:extend> - <label for="text-3"><wicket:message key="login.username"/></label> - <input type="text" data-clear-btn="true" name="text-3" id="text-3" value=""> - + <form action="http://localhost:8080/rest/currency/add" method="get"> + <label for="text-pubkey"><wicket:message key="currency.register.pubkey"/></label> + <input type="text" data-clear-btn="true" name="pubkey" id="text-pubkey" value=""/> + + <label for="text-currency"><wicket:message key="currency.register.currencyJson"/></label> + <input type="text" data-clear-btn="true" name="currency" id="text-currency" value=""/> + + <label for="text-sig"><wicket:message key="currency.register.signature"/></label> + <input type="text" data-clear-btn="true" name="sig" id="text-sig" value=""/> + <input type="submit"/> + </form> + </wicket:extend> </body> </html> \ No newline at end of file diff --git a/ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/CurrencyRestService.java b/ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/CurrencyRestService.java index d52b4694eebb154fb5e842710d391ef26faa78ae..93a87ba0d0636e4d5c86372825d888f5e14f7e3f 100644 --- a/ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/CurrencyRestService.java +++ b/ucoinj-web/src/main/java/io/ucoin/client/ui/service/rest/CurrencyRestService.java @@ -23,27 +23,23 @@ package io.ucoin.client.ui.service.rest; */ -import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; import io.ucoin.client.core.model.Currency; -import io.ucoin.client.core.service.CryptoService; import io.ucoin.client.core.service.ServiceLocator; import io.ucoin.client.core.service.search.CurrencyIndexerService; -import io.ucoin.client.core.technical.UCoinTechnicalException; -import io.ucoin.client.core.technical.crypto.CryptoUtils; -import io.ucoin.client.core.technical.jackson.JacksonUtils; +import io.ucoin.client.core.service.search.InvalidSignatureException; +import io.ucoin.client.core.technical.gson.GsonUtils; import io.ucoin.client.ui.application.UcoinSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.wicketstuff.rest.annotations.MethodMapping; import org.wicketstuff.rest.annotations.ResourcePath; import org.wicketstuff.rest.annotations.parameters.PathParam; -import org.wicketstuff.rest.contenthandling.json.objserialdeserial.JacksonObjectSerialDeserial; +import org.wicketstuff.rest.annotations.parameters.RequestParam; +import org.wicketstuff.rest.contenthandling.json.objserialdeserial.GsonObjectSerialDeserial; import org.wicketstuff.rest.contenthandling.mimetypes.RestMimeTypes; import org.wicketstuff.rest.contenthandling.webserialdeserial.TextualWebSerialDeserial; import org.wicketstuff.rest.resource.AbstractRestResource; -import org.wicketstuff.rest.utils.http.HttpMethod; - -import java.io.IOException; @ResourcePath("/rest/currency") public class CurrencyRestService extends AbstractRestResource<TextualWebSerialDeserial> { @@ -54,20 +50,20 @@ public class CurrencyRestService extends AbstractRestResource<TextualWebSerialDe private static final long serialVersionUID = 1L; private boolean debug; - private ObjectMapper objectMapper; - private static ObjectMapper staticObjectMapper; + + private static Gson gson; public CurrencyRestService() { super(new TextualWebSerialDeserial("UTF-8", RestMimeTypes.APPLICATION_JSON, - new JacksonObjectSerialDeserial(initObjectMapper()))); + new GsonObjectSerialDeserial(initGson()))); debug = log.isDebugEnabled(); - objectMapper = staticObjectMapper; - staticObjectMapper = null; } - protected static ObjectMapper initObjectMapper() { - staticObjectMapper = JacksonUtils.newObjectMapper(); - return staticObjectMapper; + private static Gson initGson() { + if (gson == null) { + gson = GsonUtils.newBuilder().create(); + } + return gson; } @MethodMapping("/{currencyId}") @@ -76,24 +72,38 @@ public class CurrencyRestService extends AbstractRestResource<TextualWebSerialDe return service.getCurrencyById(currencyId); } - @MethodMapping(value = "/add", httpMethod = HttpMethod.POST) - public void saveCurrency(@PathParam("pubkey") String pubkey, @PathParam("currency") String jsonCurrency, @PathParam("sig") String signature) throws InvalidSignatureException { + @MethodMapping(value = "/add", produces = RestMimeTypes.TEXT_PLAIN) + public String saveCurrency(@RequestParam("pubkey") String pubkey, @RequestParam("currency") String jsonCurrency, @RequestParam("sig") String signature) throws InvalidSignatureException { + if (log.isDebugEnabled()) { + log.debug(String.format("Asking to add new currency:\n - pubkey: %s\n - currency: %s\n - signature: %s", pubkey, jsonCurrency, signature)); + } + + CurrencyIndexerService service = ServiceLocator.instance().getCurrencyIndexerService(); + service.registerCurrency(pubkey, jsonCurrency, signature); + + /*CryptoService cryptoService = ServiceLocator.instance().getCryptoService(); - // Check the signature - CryptoService cryptoService = ServiceLocator.instance().getCryptoService(); if (!cryptoService.verify(jsonCurrency, signature, pubkey)) { + String currencyName = GsonUtils.getValueFromJSONAsString(jsonCurrency, "currencyName"); + log.warn(String.format("Currency not added, because bad signature. currency [%s]", currencyName)); throw new InvalidSignatureException("Bad signature"); } - // Apply the save (will check if pubkey match the owner public key) Currency currency = null; try { - currency = objectMapper.readValue(CryptoUtils.decodeUTF8(jsonCurrency), Currency.class); - } catch (IOException e) { - throw new UCoinTechnicalException(e.getMessage(), e); + currency = gson.fromJson(jsonCurrency, Currency.class); + Preconditions.checkNotNull(currency); + Preconditions.checkNotNull(currency.getCurrencyName()); + } catch(Throwable t) { + log.error("Error while reading currency JSON: " + jsonCurrency); + return "Parse error. Currency not readable."; } + CurrencyIndexerService service = ServiceLocator.instance().getCurrencyIndexerService(); service.saveCurrency(currency, pubkey); + */ + + return "Currency added"; } /* -- Internal methods -- */ diff --git a/ucoinj-web/src/main/test/resources/ucoinj-web.config b/ucoinj-web/src/main/test/resources/ucoinj-web.config deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000