Skip to content
Snippets Groups Projects
Commit 098dd748 authored by Benoit Lavenier's avatar Benoit Lavenier
Browse files

- [web] implement rest/currency/add

- [web] Load NaCL library at startup
- [client] add a REST client to registernew currency
- [client] add a REST client to get all currency names
parent 53cdf02a
No related branches found
No related tags found
No related merge requests found
Showing
with 542 additions and 42 deletions
...@@ -398,6 +398,15 @@ ...@@ -398,6 +398,15 @@
<plugin> <plugin>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>2.2</version> <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>
<plugin> <plugin>
......
...@@ -72,6 +72,9 @@ public class Configuration { ...@@ -72,6 +72,9 @@ public class Configuration {
super(); super();
this.applicationConfig = applicationConfig; this.applicationConfig = applicationConfig;
this.optionKeyToNotSave = null; this.optionKeyToNotSave = null;
// Override application version
initVersion(applicationConfig);
} }
public Configuration(String file, String... args) { public Configuration(String file, String... args) {
...@@ -99,6 +102,9 @@ public class Configuration { ...@@ -99,6 +102,9 @@ public class Configuration {
// Define Alias // Define Alias
addAlias(applicationConfig); addAlias(applicationConfig);
// Override application version
initVersion(applicationConfig);
// get all transient and final option keys // get all transient and final option keys
Set<String> optionToSkip = Set<String> optionToSkip =
ApplicationConfigHelper.getTransientOptionKeys(providers); ApplicationConfigHelper.getTransientOptionKeys(providers);
...@@ -137,13 +143,21 @@ public class Configuration { ...@@ -137,13 +143,21 @@ public class Configuration {
applicationConfig.setOption( applicationConfig.setOption(
ConfigurationOption.BASEDIR.getKey(), ConfigurationOption.BASEDIR.getKey(),
appBasedir.getAbsolutePath()); appBasedir.getAbsolutePath());
}
/**
* Override the version default option, from the MANIFEST implementation version (if any)
* @param applicationConfig
*/
protected void initVersion(ApplicationConfig applicationConfig) {
// Override application version // Override application version
String implementationVersion = this.getClass().getPackage().getSpecificationVersion(); String implementationVersion = this.getClass().getPackage().getSpecificationVersion();
applicationConfig.setOption( if (implementationVersion != null) {
applicationConfig.setDefaultOption(
ConfigurationOption.VERSION.getKey(), ConfigurationOption.VERSION.getKey(),
implementationVersion); implementationVersion);
} }
}
/** /**
* Add alias to the given ApplicationConfig. <p/> * Add alias to the given ApplicationConfig. <p/>
...@@ -250,6 +264,10 @@ public class Configuration { ...@@ -250,6 +264,10 @@ public class Configuration {
return applicationConfig.getOptionAsInt(ConfigurationOption.NODE_ELASTICSEARCH_PORT.getKey()); return applicationConfig.getOptionAsInt(ConfigurationOption.NODE_ELASTICSEARCH_PORT.getKey());
} }
public URL getNodeElasticSearchRestUrl() {
return applicationConfig.getOptionAsURL(ConfigurationOption.NODE_ELASTICSEARCH_REST_URL.getKey());
}
public boolean isNodeElasticSearchLocal() { public boolean isNodeElasticSearchLocal() {
return applicationConfig.getOptionAsBoolean(ConfigurationOption.NODE_ELASTICSEARCH_LOCAL.getKey()); return applicationConfig.getOptionAsBoolean(ConfigurationOption.NODE_ELASTICSEARCH_LOCAL.getKey());
} }
......
...@@ -168,6 +168,13 @@ public enum ConfigurationOption implements ConfigOptionDef { ...@@ -168,6 +168,13 @@ public enum ConfigurationOption implements ConfigOptionDef {
Integer.class, Integer.class,
false), false),
NODE_ELASTICSEARCH_PROTOCOL(
"ucoinj.node.elasticsearch.protocol",
n("ucoinj.config.option.node.elasticsearch.protocol.description"),
"http",
String.class,
false),
NODE_ELASTICSEARCH_HOST( NODE_ELASTICSEARCH_HOST(
"ucoinj.node.elasticsearch.host", "ucoinj.node.elasticsearch.host",
n("ucoinj.config.option.node.elasticsearch.host.description"), n("ucoinj.config.option.node.elasticsearch.host.description"),
...@@ -182,6 +189,34 @@ public enum ConfigurationOption implements ConfigOptionDef { ...@@ -182,6 +189,34 @@ public enum ConfigurationOption implements ConfigOptionDef {
Integer.class, Integer.class,
false), 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( NODE_ELASTICSEARCH_LOCAL(
"ucoinj.node.elasticsearch.local", "ucoinj.node.elasticsearch.local",
n("ucoinj.config.option.node.elasticsearch.local.description"), n("ucoinj.config.option.node.elasticsearch.local.description"),
......
...@@ -38,6 +38,7 @@ public class BlockchainBlock implements Serializable { ...@@ -38,6 +38,7 @@ public class BlockchainBlock implements Serializable {
private String version; private String version;
private Integer nonce; private Integer nonce;
private Integer powMin;
private Integer number; private Integer number;
private Integer time; private Integer time;
private Integer medianTime; private Integer medianTime;
...@@ -76,6 +77,14 @@ public class BlockchainBlock implements Serializable { ...@@ -76,6 +77,14 @@ public class BlockchainBlock implements Serializable {
this.nonce = nonce; this.nonce = nonce;
} }
public Integer getPowMin() {
return powMin;
}
public void setPowMin(Integer powMin) {
this.powMin = powMin;
}
public Integer getNumber() { public Integer getNumber() {
return number; return number;
} }
......
...@@ -30,6 +30,7 @@ import com.google.gson.Gson; ...@@ -30,6 +30,7 @@ import com.google.gson.Gson;
import io.ucoin.client.core.config.Configuration; import io.ucoin.client.core.config.Configuration;
import io.ucoin.client.core.technical.UCoinTechnicalException; import io.ucoin.client.core.technical.UCoinTechnicalException;
import io.ucoin.client.core.technical.gson.GsonUtils; 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.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
...@@ -91,13 +92,29 @@ public class AbstractNetworkService extends BaseService implements Closeable { ...@@ -91,13 +92,29 @@ public class AbstractNetworkService extends BaseService implements Closeable {
} }
} }
protected URI getAppendedPath(String... path) { protected URIBuilder getURIBuilder(String... path) {
try {
String pathToAppend = Joiner.on('/').skipNulls().join(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); URIBuilder builder = new URIBuilder(baseUri);
builder.setPath(baseUri.getPath() + pathToAppend); builder.setPath(baseUri.getPath() + pathToAppend);
return builder.build(); if (StringUtils.isNotBlank(customQuery)) {
builder.setCustomQuery(customQuery);
}
return builder;
}
protected URI getAppendedPath(String... path) {
try {
return getURIBuilder(path).build();
} }
catch(URISyntaxException e) { catch(URISyntaxException e) {
throw new UCoinTechnicalException(e); throw new UCoinTechnicalException(e);
...@@ -201,6 +218,10 @@ public class AbstractNetworkService extends BaseService implements Closeable { ...@@ -201,6 +218,10 @@ public class AbstractNetworkService extends BaseService implements Closeable {
} }
return result.toString(); return result.toString();
} }
protected Gson getGson() {
return gson;
}
} }
...@@ -112,6 +112,14 @@ public class CryptoService extends BaseService { ...@@ -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) { public boolean verify(String message, String signature, String publicKey) {
byte[] messageBinary = decodeUTF8(message); byte[] messageBinary = decodeUTF8(message);
byte[] signatureBinary = decodeBase64(signature); byte[] signatureBinary = decodeBase64(signature);
......
...@@ -26,6 +26,7 @@ package io.ucoin.client.core.service; ...@@ -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.BlockIndexerService;
import io.ucoin.client.core.service.search.CurrencyIndexerService; import io.ucoin.client.core.service.search.CurrencyIndexerService;
import io.ucoin.client.core.service.search.ElasticSearchService; 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 io.ucoin.client.core.technical.UCoinTechnicalException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -113,6 +114,12 @@ public class ServiceLocator implements Closeable { ...@@ -113,6 +114,12 @@ public class ServiceLocator implements Closeable {
return getService(BlockIndexerService.class); return getService(BlockIndexerService.class);
} }
public CurrencyIndexerRestClientService getCurrencyIndexerRestClientService() {
return getService(CurrencyIndexerRestClientService.class);
}
/* -- Internal methods -- */ /* -- Internal methods -- */
protected <S extends BaseService> S getService(Class<S> clazz) { protected <S extends BaseService> S getService(Class<S> clazz) {
if (serviceCache.containsKey(clazz)) { if (serviceCache.containsKey(clazz)) {
......
...@@ -24,11 +24,15 @@ package io.ucoin.client.core.service.search; ...@@ -24,11 +24,15 @@ package io.ucoin.client.core.service.search;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gson.Gson;
import io.ucoin.client.core.model.Currency; 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.ServiceLocator;
import io.ucoin.client.core.technical.ObjectUtils; import io.ucoin.client.core.technical.ObjectUtils;
import io.ucoin.client.core.technical.UCoinTechnicalException; 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.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
...@@ -70,7 +74,22 @@ public class CurrencyIndexerService extends BaseIndexerService { ...@@ -70,7 +74,22 @@ public class CurrencyIndexerService extends BaseIndexerService {
public static final String INDEX_TYPE_SIMPLE = "simple"; 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() { public CurrencyIndexerService() {
super();
this.gson = GsonUtils.newBuilder().create();
}
@Override
public void initialize() {
super.initialize();
this.cryptoService = ServiceLocator.instance().getCryptoService();
} }
public void deleteIndex() throws JsonProcessingException { public void deleteIndex() throws JsonProcessingException {
...@@ -125,9 +144,9 @@ public class CurrencyIndexerService extends BaseIndexerService { ...@@ -125,9 +144,9 @@ public class CurrencyIndexerService extends BaseIndexerService {
// Fill tags // Fill tags
if (ArrayUtils.isEmpty(currency.getTags())) { if (ArrayUtils.isEmpty(currency.getTags())) {
String currencyName = currency.getCurrencyName(); String currencyName = currency.getCurrencyName();
String[] tags = currencyName.split("[-\\t@#_ ]+"); String[] tags = currencyName.split(REGEX_WORD_SEPARATOR);
List<String> tagsList = Lists.newArrayList(tags); 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()])); currency.setTags(tagsList.toArray(new String[tagsList.size()]));
} }
...@@ -168,7 +187,7 @@ public class CurrencyIndexerService extends BaseIndexerService { ...@@ -168,7 +187,7 @@ public class CurrencyIndexerService extends BaseIndexerService {
} }
public List<Currency> searchCurrencies(String query) { public List<Currency> searchCurrencies(String query) {
String[] queryParts = query.split("[\\t ]+"); String[] queryParts = query.split(REGEX_SPACE);
// Prepare request // Prepare request
SearchRequestBuilder searchRequest = getClient() SearchRequestBuilder searchRequest = getClient()
...@@ -226,32 +245,14 @@ public class CurrencyIndexerService extends BaseIndexerService { ...@@ -226,32 +245,14 @@ public class CurrencyIndexerService extends BaseIndexerService {
return CollectionUtils.extractSingleton(currencies); return CollectionUtils.extractSingleton(currencies);
} }
/* -- Internal methods -- */ public void saveCurrency(Currency currency, String senderPubkey) throws DuplicateIndexIdException {
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 {
ObjectUtils.checkNotNull(currency, "currency could not be null") ; ObjectUtils.checkNotNull(currency, "currency could not be null") ;
ObjectUtils.checkNotNull(currency.getCurrencyName(), "currency attribute 'currencyName' could not be null"); ObjectUtils.checkNotNull(currency.getCurrencyName(), "currency attribute 'currencyName' could not be null");
Currency existingCurrency = getCurrencyById(currency.getCurrencyName()); Currency existingCurrency = getCurrencyById(currency.getCurrencyName());
// Currency not exists, so create it // Currency not exists, so create it
if (existingCurrency == null) { if (existingCurrency == null || currency.getSenderPubkey() == null) {
// make sure to fill the sender // make sure to fill the sender
currency.setSenderPubkey(senderPubkey); currency.setSenderPubkey(senderPubkey);
...@@ -273,7 +274,64 @@ public class CurrencyIndexerService extends BaseIndexerService { ...@@ -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) { protected List<Currency> toCurrencies(SearchResponse response, boolean withHighlight) {
try { try {
...@@ -328,4 +386,15 @@ public class CurrencyIndexerService extends BaseIndexerService { ...@@ -328,4 +386,15 @@ public class CurrencyIndexerService extends BaseIndexerService {
return result; 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;
}
} }
package io.ucoin.client.ui.service.rest; package io.ucoin.client.core.service.search;
/* /*
* #%L * #%L
......
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);
}
}
}
...@@ -23,24 +23,90 @@ package io.ucoin.client.core.technical.gson; ...@@ -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.common.collect.Multimap;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import io.ucoin.client.core.model.Identity; import io.ucoin.client.core.model.Identity;
import io.ucoin.client.core.model.Member; 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 class GsonUtils {
public static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss"; 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() { public static GsonBuilder newBuilder() {
return new GsonBuilder() return new GsonBuilder()
// make sure date will be serialized // make sure date will be serialized
.setDateFormat(DATE_PATTERN) .setDateFormat(DATE_PATTERN)
// REgister Multimap adapter // Register Multimap adapter
.registerTypeAdapter(Multimap.class, new MultimapTypeAdapter()) .registerTypeAdapter(Multimap.class, new MultimapTypeAdapter())
// Register identity adapter // Register identity adapter
.registerTypeAdapter(Identity.class, new IdentityTypeAdapter()) .registerTypeAdapter(Identity.class, new IdentityTypeAdapter())
.registerTypeAdapter(Member.class, new MemberTypeAdapter()) .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();
}
} }
...@@ -127,6 +127,15 @@ public class CurrencyIndexerServiceTest { ...@@ -127,6 +127,15 @@ public class CurrencyIndexerServiceTest {
//assertResults(queryText, currencies); //assertResults(queryText, currencies);
} }
@Test
public void getAllCurrencyNames() {
List<String> currencyNames = service.getAllCurrencyNames();
for (String currencyName: currencyNames) {
log.info(" - " + currencyName);
}
}
/* -- internal methods */ /* -- internal methods */
protected void assertResults(String queryText, List<Currency> result) { protected void assertResults(String queryText, List<Currency> result) {
......
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;
}
}
###
# 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
...@@ -9,3 +9,9 @@ ucoinj.node.elasticsearch.local.clusterName=data.ucoin.fr ...@@ -9,3 +9,9 @@ ucoinj.node.elasticsearch.local.clusterName=data.ucoin.fr
ucoinj.node.elasticsearch.host=192.168.0.5 ucoinj.node.elasticsearch.host=192.168.0.5
ucoinj.node.elasticsearch.port=9300 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
...@@ -245,13 +245,17 @@ ...@@ -245,13 +245,17 @@
<name>jetty.port</name> <name>jetty.port</name>
<value>8080</value> <value>8080</value>
</systemProperty> </systemProperty>
<systemProperty>
<name>log4j.configuration</name>
<value>${project.basedir}/src/test/resources/log4j.properties</value>
</systemProperty>
</systemProperties> </systemProperties>
<jvmArgs>${jetty.forked.jvmArgs}</jvmArgs> <jvmArgs>${jetty.forked.jvmArgs}</jvmArgs>
<reload>${jetty.reload}</reload> <reload>${jetty.reload}</reload>
<useProvidedScope>true</useProvidedScope> <useProvidedScope>true</useProvidedScope>
<webXml>${jetty.docroot}/WEB-INF/web.xml</webXml> <webXml>${jetty.docroot}/WEB-INF/web.xml</webXml>
<!-- Add test-classes (to use test log4j.properties) --> <!-- Add log4j.properties (from test resources)
<extraClasspath>${project.build.directory}/test-classes/log4j.properties;</extraClasspath> <extraClasspath>${project.basedir}/src/test/resources/log4j.properties</extraClasspath>-->
<scanTargetPatterns> <scanTargetPatterns>
<scanTargetPattern> <scanTargetPattern>
<directory>${project.basedir}/target/classes</directory> <directory>${project.basedir}/target/classes</directory>
...@@ -267,6 +271,16 @@ ...@@ -267,6 +271,16 @@
</scanTargetPatterns> </scanTargetPatterns>
</configuration> </configuration>
<dependencies> <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> <dependency>
<groupId>log4j</groupId> <groupId>log4j</groupId>
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
......
...@@ -13,6 +13,7 @@ log4j.logger.io.ucoin.client.core.config=WARN ...@@ -13,6 +13,7 @@ log4j.logger.io.ucoin.client.core.config=WARN
log4j.logger.org.nuiton.util=WARN log4j.logger.org.nuiton.util=WARN
log4j.logger.org.nuiton.config=WARN log4j.logger.org.nuiton.config=WARN
log4j.logger.org.nuiton.converter=WARN
log4j.logger.org.apache.commons.beanutils=WARN log4j.logger.org.apache.commons.beanutils=WARN
# file logging (compatible with Ifremer/RIC) # file logging (compatible with Ifremer/RIC)
......
...@@ -26,6 +26,7 @@ package io.ucoin.client.ui.application; ...@@ -26,6 +26,7 @@ package io.ucoin.client.ui.application;
import io.ucoin.client.ui.config.WebConfiguration; import io.ucoin.client.ui.config.WebConfiguration;
import io.ucoin.client.ui.pages.home.HomePage; import io.ucoin.client.ui.pages.home.HomePage;
import io.ucoin.client.ui.pages.login.LoginPage; 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 io.ucoin.client.ui.pages.wallet.WalletPage;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession; import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication; import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
...@@ -58,12 +59,12 @@ public class UcoinApplication extends AuthenticatedWebApplication { ...@@ -58,12 +59,12 @@ public class UcoinApplication extends AuthenticatedWebApplication {
mountPage("home", getHomePage()); mountPage("home", getHomePage());
mountPage("login", LoginPage.class); mountPage("login", LoginPage.class);
mountPage("wallet", WalletPage.class); mountPage("wallet", WalletPage.class);
mountPage("register-currency", CurrencyRegistryPage.class);
// Mount rest service, from annotations // Mount rest service, from annotations
PackageScanner.scanPackage("io.ucoin.client.ui.service.rest"); PackageScanner.scanPackage("io.ucoin.client.ui.service.rest");
getMarkupSettings().setStripWicketTags(true); getMarkupSettings().setStripWicketTags(true);
} }
/** /**
......
...@@ -6,3 +6,7 @@ home.search.hint=Rechercher une monnaie ...@@ -6,3 +6,7 @@ home.search.hint=Rechercher une monnaie
home.searchButton=Rechercher home.searchButton=Rechercher
home.result.divider.currency=Monnaies home.result.divider.currency=Monnaies
searchText=Rechercher 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 prcdent)
\ No newline at end of file
...@@ -37,13 +37,11 @@ public class UcoinSession extends AuthenticatedWebSession { ...@@ -37,13 +37,11 @@ public class UcoinSession extends AuthenticatedWebSession {
@Override @Override
public boolean authenticate(String username, String password) { public boolean authenticate(String username, String password) {
// TODO Auto-generated method stub
return false; return false;
} }
@Override @Override
public Roles getRoles() { public Roles getRoles() {
// TODO Auto-generated method stub
return null; return null;
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment