@@ -36,34 +36,26 @@ public enum LedgerPermission { | |||||
REGISTER_PARTICIPANT((byte) 0x04), | REGISTER_PARTICIPANT((byte) 0x04), | ||||
/** | /** | ||||
* 设置参与方的权限;<br> | |||||
* 注册用户;<br> | |||||
* | * | ||||
* 如果不具备此项权限,则无法设置参与方的“提交交易”、“参与共识”的权限; | |||||
* 如果不具备此项权限,则无法注册用户; | |||||
*/ | */ | ||||
SET_PARTICIPANT_PERMISSION((byte) 0x05), | |||||
REGISTER_USER((byte) 0x05), | |||||
/** | /** | ||||
* 参与方核准交易;<br> | |||||
* | |||||
* 如果不具备此项权限,则无法作为节点签署由终端提交的交易; | |||||
* <p> | |||||
* 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响; | |||||
* 注册数据账户;<br> | |||||
*/ | */ | ||||
APPROVE_TX((byte) 0x06), | |||||
REGISTER_DATA_ACCOUNT((byte) 0x06), | |||||
/** | /** | ||||
* 参与方共识交易;<br> | |||||
* | |||||
* 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识; | |||||
* 注册合约;<br> | |||||
*/ | */ | ||||
CONSENSUS_TX((byte) 0x07), | |||||
REGISTER_CONTRACT((byte) 0x07), | |||||
/** | /** | ||||
* 注册用户;<br> | |||||
* | |||||
* 如果不具备此项权限,则无法注册用户; | |||||
* 升级合约 | |||||
*/ | */ | ||||
REGISTER_USER((byte) 0x08), | |||||
UPGRADE_CONTRACT((byte) 0x08), | |||||
/** | /** | ||||
* 设置用户属性;<br> | * 设置用户属性;<br> | ||||
@@ -71,24 +63,27 @@ public enum LedgerPermission { | |||||
SET_USER_ATTRIBUTES((byte) 0x09), | SET_USER_ATTRIBUTES((byte) 0x09), | ||||
/** | /** | ||||
* 注册数据账户;<br> | |||||
*/ | |||||
REGISTER_DATA_ACCOUNT((byte) 0x0A), | |||||
/** | |||||
* 写入数据账户;<br> | * 写入数据账户;<br> | ||||
*/ | */ | ||||
WRITE_DATA_ACCOUNT((byte) 0x0B), | |||||
WRITE_DATA_ACCOUNT((byte) 0x0A), | |||||
/** | /** | ||||
* 注册合约;<br> | |||||
* 参与方核准交易;<br> | |||||
* | |||||
* 如果不具备此项权限,则无法作为节点签署由终端提交的交易; | |||||
* <p> | |||||
* 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响; | |||||
*/ | */ | ||||
REGISTER_CONTRACT((byte) 0x0C), | |||||
APPROVE_TX((byte) 0x0B), | |||||
/** | /** | ||||
* 升级合约 | |||||
* 参与方共识交易;<br> | |||||
* | |||||
* 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识; | |||||
*/ | */ | ||||
UPGRADE_CONTRACT((byte) 0x0D); | |||||
CONSENSUS_TX((byte) 0x0C); | |||||
@EnumField(type = PrimitiveType.INT8) | @EnumField(type = PrimitiveType.INT8) | ||||
public final byte CODE; | public final byte CODE; | ||||
@@ -5,7 +5,7 @@ import java.util.List; | |||||
public class SecurityInitData implements SecurityInitSettings { | public class SecurityInitData implements SecurityInitSettings { | ||||
private List<RoleInitSettings> roles = new ArrayList<RoleInitSettings>(); | |||||
private List<RoleInitData> roles = new ArrayList<RoleInitData>(); | |||||
@Override | @Override | ||||
public RoleInitData[] getRoles() { | public RoleInitData[] getRoles() { | ||||
@@ -13,8 +13,8 @@ public class SecurityInitData implements SecurityInitSettings { | |||||
} | } | ||||
public void setRoles(RoleInitData[] roles) { | public void setRoles(RoleInitData[] roles) { | ||||
List<RoleInitSettings> list = new ArrayList<RoleInitSettings>(); | |||||
for (RoleInitSettings r : roles) { | |||||
List<RoleInitData> list = new ArrayList<RoleInitData>(); | |||||
for (RoleInitData r : roles) { | |||||
list.add(r); | list.add(r); | ||||
} | } | ||||
this.roles = list; | this.roles = list; | ||||
@@ -29,6 +29,18 @@ public class SecurityInitDataTest { | |||||
assertEquals(LedgerPermission.REGISTER_USER, permissions2[0]); | assertEquals(LedgerPermission.REGISTER_USER, permissions2[0]); | ||||
assertEquals(LedgerPermission.REGISTER_DATA_ACCOUNT, permissions2[1]); | assertEquals(LedgerPermission.REGISTER_DATA_ACCOUNT, permissions2[1]); | ||||
LedgerPermission[] allLedgerPermissions = LedgerPermission.values(); | |||||
String jsonLedgerPersioms = JSONSerializeUtils.serializeToJSON(allLedgerPermissions); | |||||
TransactionPermission[] allTransactionPermissions = TransactionPermission.values(); | |||||
String jsonTransactionPersioms = JSONSerializeUtils.serializeToJSON(allTransactionPermissions); | |||||
System.out.println("----------- Ledger Permissions JSON ------------"); | |||||
System.out.println(jsonLedgerPersioms); | |||||
System.out.println("-----------------------"); | |||||
System.out.println("----------- Transaction Permissions JSON ------------"); | |||||
System.out.println(jsonTransactionPersioms); | |||||
System.out.println("-----------------------"); | |||||
} | } | ||||
@Test | @Test | ||||
@@ -13,8 +13,6 @@ import org.junit.Test; | |||||
import org.springframework.core.io.ClassPathResource; | import org.springframework.core.io.ClassPathResource; | ||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.consensus.ConsensusProvider; | |||||
import com.jd.blockchain.consensus.ConsensusSettings; | |||||
import com.jd.blockchain.crypto.AddressEncoding; | import com.jd.blockchain.crypto.AddressEncoding; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.Crypto; | import com.jd.blockchain.crypto.Crypto; | ||||
@@ -7,15 +7,23 @@ import java.text.ParseException; | |||||
import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | |||||
import java.util.Properties; | import java.util.Properties; | ||||
import java.util.TreeMap; | |||||
import com.jd.blockchain.consts.Global; | import com.jd.blockchain.consts.Global; | ||||
import com.jd.blockchain.crypto.AddressEncoding; | import com.jd.blockchain.crypto.AddressEncoding; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.ledger.RoleInitData; | |||||
import com.jd.blockchain.ledger.RoleInitSettings; | |||||
import com.jd.blockchain.ledger.RolesPolicy; | |||||
import com.jd.blockchain.ledger.TransactionPermission; | |||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | import com.jd.blockchain.tools.keygen.KeyGenCommand; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.PropertiesUtils; | import com.jd.blockchain.utils.PropertiesUtils; | ||||
import com.jd.blockchain.utils.StringUtils; | |||||
import com.jd.blockchain.utils.codec.HexUtils; | import com.jd.blockchain.utils.codec.HexUtils; | ||||
import com.jd.blockchain.utils.io.FileUtils; | import com.jd.blockchain.utils.io.FileUtils; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
@@ -33,6 +41,13 @@ public class LedgerInitProperties { | |||||
// 创建时间的格式; | // 创建时间的格式; | ||||
public static final String CREATED_TIME_FORMAT = Global.DEFAULT_TIME_FORMAT; | public static final String CREATED_TIME_FORMAT = Global.DEFAULT_TIME_FORMAT; | ||||
// 角色清单; | |||||
public static final String ROLES = "security.roles"; | |||||
// 角色的账本权限;用角色名称替代占位符; | |||||
public static final String ROLE_LEDGER_PRIVILEGES_PATTERN = "security.role.%s.ledger-privileges"; | |||||
// 角色的交易权限;用角色名称替代占位符; | |||||
public static final String ROLE_TX_PRIVILEGES_PATTERN = "security.role.%s.tx-privileges"; | |||||
// 共识参与方的个数,后续以 part.id 分别标识每一个参与方的配置; | // 共识参与方的个数,后续以 part.id 分别标识每一个参与方的配置; | ||||
public static final String PART_COUNT = "cons_parti.count"; | public static final String PART_COUNT = "cons_parti.count"; | ||||
// 共识参与方的名称的模式; | // 共识参与方的名称的模式; | ||||
@@ -43,6 +58,10 @@ public class LedgerInitProperties { | |||||
public static final String PART_PUBKEY_PATH = "pubkey-path"; | public static final String PART_PUBKEY_PATH = "pubkey-path"; | ||||
// 参与方的公钥文件路径; | // 参与方的公钥文件路径; | ||||
public static final String PART_PUBKEY = "pubkey"; | public static final String PART_PUBKEY = "pubkey"; | ||||
// 参与方的角色清单; | |||||
public static final String PART_ROLES = "roles"; | |||||
// 参与方的角色权限策略; | |||||
public static final String PART_ROLES_POLICY = "roles-policy"; | |||||
// 共识参与方的账本初始服务的主机; | // 共识参与方的账本初始服务的主机; | ||||
public static final String PART_INITIALIZER_HOST = "initializer.host"; | public static final String PART_INITIALIZER_HOST = "initializer.host"; | ||||
@@ -66,6 +85,8 @@ public class LedgerInitProperties { | |||||
private String ledgerName; | private String ledgerName; | ||||
private RoleInitData[] roles; | |||||
private List<ConsensusParticipantConfig> consensusParticipants = new ArrayList<>(); | private List<ConsensusParticipantConfig> consensusParticipants = new ArrayList<>(); | ||||
private String consensusProvider; | private String consensusProvider; | ||||
@@ -143,7 +164,7 @@ public class LedgerInitProperties { | |||||
consensusParticipants.add(participant); | consensusParticipants.add(participant); | ||||
} | } | ||||
private static String getKeyOfCsParti(int partId, String partPropKey) { | |||||
private static String getKeyOfParticipant(int partId, String partPropKey) { | |||||
String partAddrStr = String.format(PART_ID_PATTERN, partId); | String partAddrStr = String.format(PART_ID_PATTERN, partId); | ||||
return String.format("%s.%s", partAddrStr, partPropKey); | return String.format("%s.%s", partAddrStr, partPropKey); | ||||
} | } | ||||
@@ -162,12 +183,20 @@ public class LedgerInitProperties { | |||||
public static LedgerInitProperties resolve(Properties props) { | public static LedgerInitProperties resolve(Properties props) { | ||||
return resolve(null, props); | return resolve(null, props); | ||||
} | } | ||||
public static LedgerInitProperties resolve(String dir, Properties props) { | |||||
/** | |||||
* 从属性表解析账本初始化参数; | |||||
* | |||||
* @param baseDirectory 基础路径;属性中涉及文件位置的相对路径以此参数指定的目录为父目录; | |||||
* @param props 要解析的属性表; | |||||
* @return | |||||
*/ | |||||
public static LedgerInitProperties resolve(String baseDirectory, Properties props) { | |||||
String hexLedgerSeed = PropertiesUtils.getRequiredProperty(props, LEDGER_SEED).replace("-", ""); | String hexLedgerSeed = PropertiesUtils.getRequiredProperty(props, LEDGER_SEED).replace("-", ""); | ||||
byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed); | byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed); | ||||
LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed); | LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed); | ||||
// 解析账本信息; | |||||
// 账本名称 | // 账本名称 | ||||
String ledgerName = PropertiesUtils.getRequiredProperty(props, LEDGER_NAME); | String ledgerName = PropertiesUtils.getRequiredProperty(props, LEDGER_NAME); | ||||
initProps.ledgerName = ledgerName; | initProps.ledgerName = ledgerName; | ||||
@@ -180,11 +209,35 @@ public class LedgerInitProperties { | |||||
throw new IllegalArgumentException(ex.getMessage(), ex); | throw new IllegalArgumentException(ex.getMessage(), ex); | ||||
} | } | ||||
// 解析角色清单; | |||||
String strRoleNames = PropertiesUtils.getOptionalProperty(props, ROLES); | |||||
String[] roles = StringUtils.splitToArray(strRoleNames, ","); | |||||
Map<String, RoleInitData> rolesInitSettingMap = new TreeMap<String, RoleInitData>(); | |||||
// 解析角色权限表; | |||||
for (String role : roles) { | |||||
String ledgerPrivilegeKey = getKeyOfRoleLedgerPrivilege(role); | |||||
String strLedgerPermissions = PropertiesUtils.getOptionalProperty(props, ledgerPrivilegeKey); | |||||
LedgerPermission[] ledgerPermissions = resolveLedgerPermissions(strLedgerPermissions); | |||||
String txPrivilegeKey = getKeyOfRoleTxPrivilege(role); | |||||
String strTxPermissions = PropertiesUtils.getOptionalProperty(props, txPrivilegeKey); | |||||
TransactionPermission[] txPermissions = resolveTransactionPermissions(strTxPermissions); | |||||
if (ledgerPermissions.length > 0 || txPermissions.length > 0) { | |||||
RoleInitData rolesSettings = new RoleInitData(role, ledgerPermissions, txPermissions); | |||||
rolesInitSettingMap.put(role, rolesSettings); | |||||
} | |||||
} | |||||
RoleInitData[] rolesInitDatas = rolesInitSettingMap.values() | |||||
.toArray(new RoleInitData[rolesInitSettingMap.size()]); | |||||
initProps.setRoles(rolesInitDatas); | |||||
// 解析共识相关的属性; | // 解析共识相关的属性; | ||||
initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER); | initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER); | ||||
String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG); | String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG); | ||||
try { | try { | ||||
File consensusConfigFile = FileUtils.getFile(dir, consensusConfigFilePath); | |||||
File consensusConfigFile = FileUtils.getFile(baseDirectory, consensusConfigFilePath); | |||||
initProps.consensusConfig = FileUtils.readProperties(consensusConfigFile); | initProps.consensusConfig = FileUtils.readProperties(consensusConfigFile); | ||||
} catch (FileNotFoundException e) { | } catch (FileNotFoundException e) { | ||||
throw new IllegalArgumentException( | throw new IllegalArgumentException( | ||||
@@ -212,13 +265,13 @@ public class LedgerInitProperties { | |||||
parti.setId(i); | parti.setId(i); | ||||
String nameKey = getKeyOfCsParti(i, PART_NAME); | |||||
String nameKey = getKeyOfParticipant(i, PART_NAME); | |||||
parti.setName(PropertiesUtils.getRequiredProperty(props, nameKey)); | parti.setName(PropertiesUtils.getRequiredProperty(props, nameKey)); | ||||
String pubkeyPathKey = getKeyOfCsParti(i, PART_PUBKEY_PATH); | |||||
String pubkeyPathKey = getKeyOfParticipant(i, PART_PUBKEY_PATH); | |||||
String pubkeyPath = PropertiesUtils.getProperty(props, pubkeyPathKey, false); | String pubkeyPath = PropertiesUtils.getProperty(props, pubkeyPathKey, false); | ||||
String pubkeyKey = getKeyOfCsParti(i, PART_PUBKEY); | |||||
String pubkeyKey = getKeyOfParticipant(i, PART_PUBKEY); | |||||
String base58PubKey = PropertiesUtils.getProperty(props, pubkeyKey, false); | String base58PubKey = PropertiesUtils.getProperty(props, pubkeyKey, false); | ||||
if (base58PubKey != null) { | if (base58PubKey != null) { | ||||
PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey); | PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey); | ||||
@@ -231,13 +284,27 @@ public class LedgerInitProperties { | |||||
String.format("Property[%s] and property[%s] are all empty!", pubkeyKey, pubkeyPathKey)); | String.format("Property[%s] and property[%s] are all empty!", pubkeyKey, pubkeyPathKey)); | ||||
} | } | ||||
String initializerHostKey = getKeyOfCsParti(i, PART_INITIALIZER_HOST); | |||||
// 解析参与方的角色权限配置; | |||||
String partiRolesKey = getKeyOfParticipant(i, PART_ROLES); | |||||
String strPartiRoles = PropertiesUtils.getOptionalProperty(props, partiRolesKey); | |||||
String[] partiRoles = StringUtils.splitToArray(strPartiRoles, ","); | |||||
parti.setRoles(partiRoles); | |||||
String partiRolePolicyKey = getKeyOfParticipant(i, PART_ROLES_POLICY); | |||||
String strPartiPolicy = PropertiesUtils.getOptionalProperty(props, partiRolePolicyKey); | |||||
RolesPolicy policy = strPartiPolicy == null ? RolesPolicy.UNION | |||||
: RolesPolicy.valueOf(strPartiPolicy.trim()); | |||||
policy = policy == null ? RolesPolicy.UNION : policy; | |||||
parti.setRolesPolicy(policy); | |||||
// 解析参与方的网络配置参数; | |||||
String initializerHostKey = getKeyOfParticipant(i, PART_INITIALIZER_HOST); | |||||
String initializerHost = PropertiesUtils.getRequiredProperty(props, initializerHostKey); | String initializerHost = PropertiesUtils.getRequiredProperty(props, initializerHostKey); | ||||
String initializerPortKey = getKeyOfCsParti(i, PART_INITIALIZER_PORT); | |||||
String initializerPortKey = getKeyOfParticipant(i, PART_INITIALIZER_PORT); | |||||
int initializerPort = getInt(PropertiesUtils.getRequiredProperty(props, initializerPortKey)); | int initializerPort = getInt(PropertiesUtils.getRequiredProperty(props, initializerPortKey)); | ||||
String initializerSecureKey = getKeyOfCsParti(i, PART_INITIALIZER_SECURE); | |||||
String initializerSecureKey = getKeyOfParticipant(i, PART_INITIALIZER_SECURE); | |||||
boolean initializerSecure = Boolean | boolean initializerSecure = Boolean | ||||
.parseBoolean(PropertiesUtils.getRequiredProperty(props, initializerSecureKey)); | .parseBoolean(PropertiesUtils.getRequiredProperty(props, initializerSecureKey)); | ||||
NetworkAddress initializerAddress = new NetworkAddress(initializerHost, initializerPort, initializerSecure); | NetworkAddress initializerAddress = new NetworkAddress(initializerHost, initializerPort, initializerSecure); | ||||
@@ -249,10 +316,54 @@ public class LedgerInitProperties { | |||||
return initProps; | return initProps; | ||||
} | } | ||||
private static TransactionPermission[] resolveTransactionPermissions(String strTxPermissions) { | |||||
String[] strPermissions = StringUtils.splitToArray(strTxPermissions, ","); | |||||
List<TransactionPermission> permissions = new ArrayList<TransactionPermission>(); | |||||
if (strPermissions != null) { | |||||
for (String pm : strPermissions) { | |||||
TransactionPermission permission = TransactionPermission.valueOf(pm); | |||||
if (permission != null) { | |||||
permissions.add(permission); | |||||
} | |||||
} | |||||
} | |||||
return permissions.toArray(new TransactionPermission[permissions.size()]); | |||||
} | |||||
private static LedgerPermission[] resolveLedgerPermissions(String strLedgerPermissions) { | |||||
String[] strPermissions = StringUtils.splitToArray(strLedgerPermissions, ","); | |||||
List<LedgerPermission> permissions = new ArrayList<LedgerPermission>(); | |||||
if (strPermissions != null) { | |||||
for (String pm : strPermissions) { | |||||
LedgerPermission permission = LedgerPermission.valueOf(pm); | |||||
if (permission != null) { | |||||
permissions.add(permission); | |||||
} | |||||
} | |||||
} | |||||
return permissions.toArray(new LedgerPermission[permissions.size()]); | |||||
} | |||||
private static String getKeyOfRoleLedgerPrivilege(String role) { | |||||
return String.format(ROLE_LEDGER_PRIVILEGES_PATTERN, role); | |||||
} | |||||
private static String getKeyOfRoleTxPrivilege(String role) { | |||||
return String.format(ROLE_TX_PRIVILEGES_PATTERN, role); | |||||
} | |||||
private static int getInt(String strInt) { | private static int getInt(String strInt) { | ||||
return Integer.parseInt(strInt.trim()); | return Integer.parseInt(strInt.trim()); | ||||
} | } | ||||
public RoleInitData[] getRoles() { | |||||
return roles; | |||||
} | |||||
public void setRoles(RoleInitData[] roles) { | |||||
this.roles = roles; | |||||
} | |||||
/** | /** | ||||
* 参与方配置信息; | * 参与方配置信息; | ||||
* | * | ||||
@@ -267,10 +378,12 @@ public class LedgerInitProperties { | |||||
private String name; | private String name; | ||||
// private String pubKeyPath; | |||||
private PubKey pubKey; | private PubKey pubKey; | ||||
private String[] roles; | |||||
private RolesPolicy rolesPolicy; | |||||
// private NetworkAddress consensusAddress; | // private NetworkAddress consensusAddress; | ||||
private NetworkAddress initializerAddress; | private NetworkAddress initializerAddress; | ||||
@@ -321,6 +434,22 @@ public class LedgerInitProperties { | |||||
this.address = AddressEncoding.generateAddress(pubKey); | this.address = AddressEncoding.generateAddress(pubKey); | ||||
} | } | ||||
public String[] getRoles() { | |||||
return roles; | |||||
} | |||||
public void setRoles(String[] roles) { | |||||
this.roles = roles; | |||||
} | |||||
public RolesPolicy getRolesPolicy() { | |||||
return rolesPolicy; | |||||
} | |||||
public void setRolesPolicy(RolesPolicy rolesPolicy) { | |||||
this.rolesPolicy = rolesPolicy; | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,12 +1,18 @@ | |||||
package test.com.jd.blockchain.tools.initializer; | package test.com.jd.blockchain.tools.initializer; | ||||
import static org.junit.Assert.assertArrayEquals; | |||||
import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||
import static org.junit.Assert.assertNull; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.text.ParseException; | import java.text.ParseException; | ||||
import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||
import java.util.Arrays; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import java.util.TimeZone; | import java.util.TimeZone; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
@@ -14,6 +20,10 @@ import org.springframework.core.io.ClassPathResource; | |||||
import com.jd.blockchain.crypto.AddressEncoding; | import com.jd.blockchain.crypto.AddressEncoding; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.RoleInitData; | |||||
import com.jd.blockchain.ledger.RolesPolicy; | |||||
import com.jd.blockchain.ledger.TransactionPermission; | |||||
import com.jd.blockchain.tools.initializer.LedgerInitProperties; | import com.jd.blockchain.tools.initializer.LedgerInitProperties; | ||||
import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; | import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | import com.jd.blockchain.tools.keygen.KeyGenCommand; | ||||
@@ -22,19 +32,20 @@ import com.jd.blockchain.utils.codec.HexUtils; | |||||
public class LedgerInitPropertiesTest { | public class LedgerInitPropertiesTest { | ||||
private static String expectedCreatedTimeStr = "2019-08-01 14:26:58.069+0800"; | private static String expectedCreatedTimeStr = "2019-08-01 14:26:58.069+0800"; | ||||
private static String expectedCreatedTimeStr1 = "2019-08-01 13:26:58.069+0700"; | private static String expectedCreatedTimeStr1 = "2019-08-01 13:26:58.069+0700"; | ||||
@Test | @Test | ||||
public void testTimeFormat() throws ParseException { | public void testTimeFormat() throws ParseException { | ||||
SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT); | SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT); | ||||
// timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00")); | |||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00")); | |||||
timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00")); | |||||
// 或者设置全局的默认时区; | |||||
// TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00")); | |||||
Date time = timeFormat.parse(expectedCreatedTimeStr); | Date time = timeFormat.parse(expectedCreatedTimeStr); | ||||
String actualTimeStr = timeFormat.format(time); | String actualTimeStr = timeFormat.format(time); | ||||
assertEquals(expectedCreatedTimeStr, actualTimeStr); | assertEquals(expectedCreatedTimeStr, actualTimeStr); | ||||
Date time1 = timeFormat.parse(expectedCreatedTimeStr1); | Date time1 = timeFormat.parse(expectedCreatedTimeStr1); | ||||
String actualTimeStr1 = timeFormat.format(time1); | String actualTimeStr1 = timeFormat.format(time1); | ||||
assertEquals(expectedCreatedTimeStr, actualTimeStr1); | assertEquals(expectedCreatedTimeStr, actualTimeStr1); | ||||
@@ -42,11 +53,13 @@ public class LedgerInitPropertiesTest { | |||||
@Test | @Test | ||||
public void testProperties() throws IOException, ParseException { | public void testProperties() throws IOException, ParseException { | ||||
// 加载用于测试的账本初始化配置; | |||||
ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init"); | ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init"); | ||||
InputStream in = ledgerInitSettingResource.getInputStream(); | InputStream in = ledgerInitSettingResource.getInputStream(); | ||||
try { | try { | ||||
LedgerInitProperties initProps = LedgerInitProperties.resolve(in); | LedgerInitProperties initProps = LedgerInitProperties.resolve(in); | ||||
assertEquals(4, initProps.getConsensusParticipantCount()); | |||||
// 验证账本信息; | |||||
String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe" | String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe" | ||||
.replace("-", ""); | .replace("-", ""); | ||||
String actualLedgerSeed = HexUtils.encode(initProps.getLedgerSeed()); | String actualLedgerSeed = HexUtils.encode(initProps.getLedgerSeed()); | ||||
@@ -56,10 +69,54 @@ public class LedgerInitPropertiesTest { | |||||
timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00")); | timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00")); | ||||
long expectedTs = timeFormat.parse(expectedCreatedTimeStr).getTime(); | long expectedTs = timeFormat.parse(expectedCreatedTimeStr).getTime(); | ||||
assertEquals(expectedTs, initProps.getCreatedTime()); | assertEquals(expectedTs, initProps.getCreatedTime()); | ||||
String createdTimeStr = timeFormat.format(new Date(initProps.getCreatedTime())); | String createdTimeStr = timeFormat.format(new Date(initProps.getCreatedTime())); | ||||
assertEquals(expectedCreatedTimeStr, createdTimeStr); | assertEquals(expectedCreatedTimeStr, createdTimeStr); | ||||
// 验证角色配置; | |||||
RoleInitData[] roles = initProps.getRoles(); | |||||
assertEquals(4, roles.length); | |||||
Map<String, RoleInitData> rolesInitDatas = new HashMap<String, RoleInitData>(); | |||||
for (RoleInitData r : roles) { | |||||
rolesInitDatas.put(r.getRoleName(), r); | |||||
} | |||||
// 初始化配置的角色最终也是有序排列的,按照角色名称的自然顺序; | |||||
String[] expectedRolesNames = { "DEFAULT", "ADMIN", "MANAGER", "GUEST" }; | |||||
Arrays.sort(expectedRolesNames); | |||||
assertEquals(expectedRolesNames[0], roles[0].getRoleName()); | |||||
assertEquals(expectedRolesNames[1], roles[1].getRoleName()); | |||||
assertEquals(expectedRolesNames[2], roles[2].getRoleName()); | |||||
assertEquals(expectedRolesNames[3], roles[3].getRoleName()); | |||||
RoleInitData roleDefault = rolesInitDatas.get("DEFAULT"); | |||||
assertArrayEquals( | |||||
new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT }, | |||||
roleDefault.getLedgerPermissions()); | |||||
assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION, | |||||
TransactionPermission.CONTRACT_OPERATION }, roleDefault.getTransactionPermissions()); | |||||
RoleInitData roleAdmin = rolesInitDatas.get("ADMIN"); | |||||
assertArrayEquals(new LedgerPermission[] { LedgerPermission.AUTHORIZE_ROLES, LedgerPermission.SET_CONSENSUS, | |||||
LedgerPermission.SET_CRYPTO, LedgerPermission.REGISTER_PARTICIPANT, | |||||
LedgerPermission.REGISTER_USER }, roleAdmin.getLedgerPermissions()); | |||||
assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION }, | |||||
roleAdmin.getTransactionPermissions()); | |||||
RoleInitData roleManager = rolesInitDatas.get("MANAGER"); | |||||
assertArrayEquals( | |||||
new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT, | |||||
LedgerPermission.REGISTER_CONTRACT, LedgerPermission.UPGRADE_CONTRACT, | |||||
LedgerPermission.SET_USER_ATTRIBUTES, LedgerPermission.WRITE_DATA_ACCOUNT }, | |||||
roleManager.getLedgerPermissions()); | |||||
assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION, | |||||
TransactionPermission.CONTRACT_OPERATION }, roleManager.getTransactionPermissions()); | |||||
RoleInitData roleGuest = rolesInitDatas.get("GUEST"); | |||||
assertTrue(roleGuest.getLedgerPermissions() == null || roleGuest.getLedgerPermissions().length == 0); | |||||
assertArrayEquals(new TransactionPermission[] { TransactionPermission.CONTRACT_OPERATION }, | |||||
roleGuest.getTransactionPermissions()); | |||||
// 验证共识和密码配置; | |||||
assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", | assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", | ||||
initProps.getConsensusProvider()); | initProps.getConsensusProvider()); | ||||
@@ -68,6 +125,9 @@ public class LedgerInitPropertiesTest { | |||||
assertEquals("com.jd.blockchain.crypto.service.classic.ClassicCryptoService", cryptoProviders[0]); | assertEquals("com.jd.blockchain.crypto.service.classic.ClassicCryptoService", cryptoProviders[0]); | ||||
assertEquals("com.jd.blockchain.crypto.service.sm.SMCryptoService", cryptoProviders[1]); | assertEquals("com.jd.blockchain.crypto.service.sm.SMCryptoService", cryptoProviders[1]); | ||||
// 验证参与方信息; | |||||
assertEquals(4, initProps.getConsensusParticipantCount()); | |||||
ConsensusParticipantConfig part0 = initProps.getConsensusParticipant(0); | ConsensusParticipantConfig part0 = initProps.getConsensusParticipant(0); | ||||
assertEquals("jd.com", part0.getName()); | assertEquals("jd.com", part0.getName()); | ||||
PubKey pubKey0 = KeyGenCommand.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"); | PubKey pubKey0 = KeyGenCommand.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"); | ||||
@@ -75,14 +135,27 @@ public class LedgerInitPropertiesTest { | |||||
assertEquals("127.0.0.1", part0.getInitializerAddress().getHost()); | assertEquals("127.0.0.1", part0.getInitializerAddress().getHost()); | ||||
assertEquals(8800, part0.getInitializerAddress().getPort()); | assertEquals(8800, part0.getInitializerAddress().getPort()); | ||||
assertEquals(true, part0.getInitializerAddress().isSecure()); | assertEquals(true, part0.getInitializerAddress().isSecure()); | ||||
assertArrayEquals(new String[] {"ADMIN", "MANAGER"}, part0.getRoles()); | |||||
assertEquals(RolesPolicy.UNION, part0.getRolesPolicy()); | |||||
ConsensusParticipantConfig part1 = initProps.getConsensusParticipant(1); | ConsensusParticipantConfig part1 = initProps.getConsensusParticipant(1); | ||||
assertEquals(false, part1.getInitializerAddress().isSecure()); | assertEquals(false, part1.getInitializerAddress().isSecure()); | ||||
PubKey pubKey1 = KeyGenCommand.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX"); | PubKey pubKey1 = KeyGenCommand.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX"); | ||||
assertEquals(pubKey1, part1.getPubKey()); | assertEquals(pubKey1, part1.getPubKey()); | ||||
assertArrayEquals(new String[] { "MANAGER"}, part1.getRoles()); | |||||
assertEquals(RolesPolicy.UNION, part1.getRolesPolicy()); | |||||
ConsensusParticipantConfig part2 = initProps.getConsensusParticipant(2); | ConsensusParticipantConfig part2 = initProps.getConsensusParticipant(2); | ||||
assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58()); | assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58()); | ||||
assertArrayEquals(new String[] { "MANAGER"}, part2.getRoles()); | |||||
assertEquals(RolesPolicy.UNION, part2.getRolesPolicy()); | |||||
ConsensusParticipantConfig part3 = initProps.getConsensusParticipant(3); | |||||
PubKey pubKey3 = KeyGenCommand.decodePubKey("3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"); | |||||
assertEquals(pubKey3, part3.getPubKey()); | |||||
assertArrayEquals(new String[] { "GUEST"}, part3.getRoles()); | |||||
assertEquals(RolesPolicy.INTERSECT, part3.getRolesPolicy()); | |||||
} finally { | } finally { | ||||
in.close(); | in.close(); | ||||
@@ -5,9 +5,52 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323 | |||||
#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; | #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; | ||||
ledger.name=test | ledger.name=test | ||||
#声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区 | |||||
#声明账本的创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区 | |||||
created-time=2019-08-01 14:26:58.069+0800 | created-time=2019-08-01 14:26:58.069+0800 | ||||
#----------------------------------------------- | |||||
# 初始的角色名称列表;可选项; | |||||
# 角色名称不区分大小写,最长不超过20个字符;多个角色名称之间用半角的逗点“,”分隔; | |||||
# 系统会预置一个默认角色“DEFAULT”,所有未指定角色的用户都以赋予该角色的权限;若初始化时未配置默认角色的权限,则为默认角色分配所有权限; | |||||
# | |||||
# 注:如果声明了角色,但未声明角色对应的权限清单,这会忽略该角色的初始化; | |||||
# | |||||
security.roles=DEFAULT, ADMIN, MANAGER, GUEST | |||||
# 赋予角色的账本权限清单;可选项; | |||||
# 可选的权限如下; | |||||
# AUTHORIZE_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT, | |||||
# REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT, | |||||
# SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT, | |||||
# APPROVE_TX, CONSENSUS_TX | |||||
# 多项权限之间用逗点“,”分隔; | |||||
# | |||||
security.role.DEFAULT.ledger-privileges=REGISTER_USER, REGISTER_DATA_ACCOUNT | |||||
# 赋予角色的交易权限清单;可选项; | |||||
# 可选的权限如下; | |||||
# DIRECT_OPERATION, CONTRACT_OPERATION | |||||
# 多项权限之间用逗点“,”分隔; | |||||
# | |||||
security.role.DEFAULT.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION | |||||
# 其它角色的配置示例; | |||||
# 系统管理员角色:只能操作全局性的参数配置和用户注册,只能执行直接操作指令; | |||||
security.role.ADMIN.ledger-privileges=AUTHORIZE_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT, REGISTER_USER | |||||
security.role.ADMIN.tx-privileges=DIRECT_OPERATION | |||||
# 业务主管角色:只能够执行账本数据相关的操作,包括注册用户、注册数据账户、注册合约、升级合约、写入数据等;能够执行直接操作指令和调用合约; | |||||
security.role.MANAGER.ledger-privileges=REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT, SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT, | |||||
security.role.MANAGER.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION | |||||
# 访客角色:不具备任何的账本权限,只有数据读取的操作;也只能够通过调用合约来读取数据; | |||||
security.role.GUEST.ledger-privileges= | |||||
security.role.GUEST.tx-privileges=CONTRACT_OPERATION | |||||
#----------------------------------------------- | |||||
#共识服务提供者;必须; | #共识服务提供者;必须; | ||||
consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider | consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider | ||||
@@ -28,6 +71,10 @@ cons_parti.0.name=jd.com | |||||
cons_parti.0.pubkey-path=keys/jd-com.pub | cons_parti.0.pubkey-path=keys/jd-com.pub | ||||
#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | #第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | ||||
cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 | cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 | ||||
#第0个参与方的角色清单;可选项; | |||||
cons_parti.0.roles=ADMIN, MANAGER | |||||
#第0个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; | |||||
cons_parti.0.roles-policy=UNION | |||||
#第0个参与方的共识服务的主机地址; | #第0个参与方的共识服务的主机地址; | ||||
cons_parti.0.consensus.host=127.0.0.1 | cons_parti.0.consensus.host=127.0.0.1 | ||||
#第0个参与方的共识服务的端口; | #第0个参与方的共识服务的端口; | ||||
@@ -47,6 +94,10 @@ cons_parti.1.name=at.com | |||||
cons_parti.1.pubkey-path=keys/at-com.pub | cons_parti.1.pubkey-path=keys/at-com.pub | ||||
#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | #第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | ||||
cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX | cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX | ||||
#第1个参与方的角色清单;可选项; | |||||
cons_parti.1.roles=MANAGER | |||||
#第1个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; | |||||
cons_parti.1.roles-policy=UNION | |||||
#第1个参与方的共识服务的主机地址; | #第1个参与方的共识服务的主机地址; | ||||
cons_parti.1.consensus.host=127.0.0.1 | cons_parti.1.consensus.host=127.0.0.1 | ||||
#第1个参与方的共识服务的端口; | #第1个参与方的共识服务的端口; | ||||
@@ -66,6 +117,10 @@ cons_parti.2.name=bt.com | |||||
cons_parti.2.pubkey-path=classpath:keys/parti2.pub | cons_parti.2.pubkey-path=classpath:keys/parti2.pub | ||||
#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | #第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | ||||
cons_parti.2.pubkey= | cons_parti.2.pubkey= | ||||
#第2个参与方的角色清单;可选项; | |||||
cons_parti.2.roles=MANAGER | |||||
#第2个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; | |||||
cons_parti.2.roles-policy=UNION | |||||
#第2个参与方的共识服务的主机地址; | #第2个参与方的共识服务的主机地址; | ||||
cons_parti.2.consensus.host=127.0.0.1 | cons_parti.2.consensus.host=127.0.0.1 | ||||
#第2个参与方的共识服务的端口; | #第2个参与方的共识服务的端口; | ||||
@@ -85,6 +140,10 @@ cons_parti.3.name=xt.com | |||||
cons_parti.3.pubkey-path=keys/xt-com.pub | cons_parti.3.pubkey-path=keys/xt-com.pub | ||||
#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | #第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | ||||
cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk | cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk | ||||
#第3个参与方的角色清单;可选项; | |||||
cons_parti.3.roles=GUEST | |||||
#第3个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; | |||||
cons_parti.3.roles-policy=INTERSECT | |||||
#第3个参与方的共识服务的主机地址; | #第3个参与方的共识服务的主机地址; | ||||
cons_parti.3.consensus.host=127.0.0.1 | cons_parti.3.consensus.host=127.0.0.1 | ||||
#第3个参与方的共识服务的端口; | #第3个参与方的共识服务的端口; | ||||
@@ -263,6 +263,10 @@ public abstract class PropertiesUtils { | |||||
public static String getRequiredProperty(Properties props, String key) { | public static String getRequiredProperty(Properties props, String key) { | ||||
return getProperty(props, key, true); | return getProperty(props, key, true); | ||||
} | } | ||||
public static String getOptionalProperty(Properties props, String key) { | |||||
return getProperty(props, key, false); | |||||
} | |||||
/** | /** | ||||
* 返回指定的属性; <br> | * 返回指定的属性; <br> | ||||
@@ -1,24 +1,75 @@ | |||||
package com.jd.blockchain.utils; | package com.jd.blockchain.utils; | ||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.StringTokenizer; | |||||
import java.util.regex.Pattern; | import java.util.regex.Pattern; | ||||
/** | /** | ||||
* @Author zhaogw | |||||
* date 2018/11/26 20:46 | |||||
* @Author zhaogw date 2018/11/26 20:46 | |||||
*/ | */ | ||||
public class StringUtils { | public class StringUtils { | ||||
public static boolean isEmpty(Object str) { | |||||
return str == null || "".equals(str); | |||||
} | |||||
/* | |||||
* 判断是否为整数 | |||||
* @param str 传入的字符串 | |||||
* @return 是整数返回true,否则返回false | |||||
*/ | |||||
public static boolean isNumber(String str) { | |||||
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); | |||||
return pattern.matcher(str).matches(); | |||||
} | |||||
public static final String[] EMPTY_ARRAY = {}; | |||||
public static boolean isEmpty(Object str) { | |||||
return str == null || "".equals(str); | |||||
} | |||||
/* | |||||
* 判断是否为整数 | |||||
* | |||||
* @param str 传入的字符串 | |||||
* | |||||
* @return 是整数返回true,否则返回false | |||||
*/ | |||||
public static boolean isNumber(String str) { | |||||
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); | |||||
return pattern.matcher(str).matches(); | |||||
} | |||||
/** | |||||
* 按照指定的分隔符把字符串分解为字符数组,同时截掉每一个元素两端的空白字符,并忽略掉空字符元素; | |||||
* | |||||
* @param str 要被截断的字符串; | |||||
* @param delimiter 分隔符; | |||||
* @return | |||||
*/ | |||||
public static String[] splitToArray(String str, String delimiter) { | |||||
return splitToArray(str, delimiter, true, true); | |||||
} | |||||
/** | |||||
* 按照指定的分隔符把字符串分解为字符数组 | |||||
* | |||||
* @param str 要被截断的字符串; | |||||
* @param delimiter 分隔符; | |||||
* @param trimElement 是否截断元素两端的空白字符; | |||||
* @param ignoreEmptyElement 是否忽略空字符元素; | |||||
* @return | |||||
*/ | |||||
public static String[] splitToArray(String str, String delimiter, boolean trimElement, boolean ignoreEmptyElement) { | |||||
if (str == null) { | |||||
return null; | |||||
} | |||||
if (trimElement) { | |||||
str = str.trim(); | |||||
} | |||||
if (str.length() == 0) { | |||||
return EMPTY_ARRAY; | |||||
} | |||||
StringTokenizer tokenizer = new StringTokenizer(str, delimiter); | |||||
List<String> tokens = new ArrayList<>(); | |||||
while (tokenizer.hasMoreTokens()) { | |||||
String token = tokenizer.nextToken(); | |||||
if (trimElement) { | |||||
token = token.trim(); | |||||
} | |||||
if ((!ignoreEmptyElement) || token.length() > 0) { | |||||
tokens.add(token); | |||||
} | |||||
} | |||||
return tokens.toArray(new String[tokens.size()]); | |||||
} | |||||
} | } |