@@ -0,0 +1,274 @@ | |||
# 合约编译插件使用教程 | |||
### 1、maven引入 | |||
在pom.xml文件中引入合约编译插件: | |||
```xml | |||
<plugin> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>contract-maven-plugin</artifactId> | |||
<version>1.0.0.RELEASE</version> | |||
<executions> | |||
<execution> | |||
<id>make-contract</id> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>compile</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
<configuration> | |||
<archive> | |||
<manifest> | |||
<mainClass>com.jd.chain.contracts.ContractTestInfImpl</mainClass> | |||
</manifest> | |||
</archive> | |||
<finalName>contract</finalName> | |||
</configuration> | |||
</plugin> | |||
``` | |||
需要说明的几点如下: | |||
+ 1)version:请根据实际JDChain发布版本确认,不同版本会有区别; | |||
+ 2)executions->execution->id:该值请随意指定; | |||
+ 3)executions->execution->phase:建议使用package及其后续阶段(若不了解phase含义,请自行查阅相关信息); | |||
+ 4)executions->execution->goals->goal:必须使用compile; | |||
+ 5)mainClass:必填,该类为需要发布的合约执行类(注意此处是类,不是接口),必须正确配置; | |||
+ 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-jdchain-contract.jar文件,只有该文件是可以发布到JDChain的合约包; | |||
### 2、执行命令 | |||
使用mvn执行命令,下面两种方式均可: | |||
方式一:只执行contract插件命令 | |||
```shell | |||
mvn clean compile contract:compile | |||
``` | |||
方式二:直接执行打包命令: | |||
```shell | |||
mvn clean package | |||
``` | |||
### 3、合约编写要求 | |||
合约的执行结果会对整条链产生比较深刻的影响,为了使用户能够更好、更合理的使用合约,目前JDChain约定合约编写规则包括以下几点: | |||
(违反其中任何一点都可能导致合约编译失败,但即使合约编译通过也不能保证合约可百分百运行正常) | |||
+ 1)合约工程必须引入com.jd.blockchain:sdk-pack:该包中有合约正常编写需要使用的基本类; | |||
+ 2)com.jd.blockchain:sdk-pack的scope必须定义为provided; | |||
+ 3)合约发布必须通过合约编译插件进行打包:合约编译插件不但会对Jar包进行校验,同时也会加入JDChain独有的特征,只有具有该特征的Jar才能正常发布; | |||
+ 4)合约中严禁使用随机数、IO、NIO等操作; | |||
+ 5)合约打包时,请使用<scope>provided</scope>排除常用的工具包,例如FastJson、apache下的一些工具包等; | |||
+ 6)合约必须有一个接口和该接口的实现类,详细要求如下: | |||
- a. 接口必须有@Contract注解; | |||
- b. 接口的可调用方法上必须有@ContractEvent注解,且每个注解中的name属性不能重复; | |||
- c. 合约方法支持入参和返回值,其主要包括所有基本类型; | |||
### 4、合约案例 | |||
#### 4.1、代码实例 | |||
以下是一个可创建银行账户,指定具体金额,并可以转账的合约代码(逻辑较简单,仅供参考): | |||
合约接口代码如下: | |||
```java | |||
package com.jd.chain.contract; | |||
@Contract | |||
public interface TransferContract { | |||
@ContractEvent(name = "create") | |||
String create(String address, String account, long money); | |||
@ContractEvent(name = "transfer") | |||
String transfer(String address, String from, String to, long money); | |||
@ContractEvent(name = "read") | |||
long read(String address, String account); | |||
@ContractEvent(name = "readAll") | |||
String readAll(String address, String account); | |||
} | |||
``` | |||
合约实现类代码如下: | |||
```java | |||
package com.jd.chain.contract; | |||
import com.alibaba.fastjson.JSON; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.KVDataEntry; | |||
import com.jd.blockchain.ledger.KVDataVO; | |||
import com.jd.blockchain.ledger.KVInfoVO; | |||
public class TransferContractImpl implements EventProcessingAware, TransferContract { | |||
private ContractEventContext eventContext; | |||
private HashDigest ledgerHash; | |||
@Override | |||
public String create(String address, String account, long money) { | |||
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
// 肯定有返回值,但若不存在则返回version=-1 | |||
if (kvDataEntries != null && kvDataEntries.length > 0) { | |||
long currVersion = kvDataEntries[0].getVersion(); | |||
if (currVersion > -1) { | |||
throw new IllegalStateException(String.format("%s -> %s already have created !!!", address, account)); | |||
} | |||
eventContext.getLedger().dataAccount(address).setInt64(account, money, -1L); | |||
} else { | |||
throw new IllegalStateException(String.format("Ledger[%s] inner Error !!!", ledgerHash.toBase58())); | |||
} | |||
return String.format("DataAccountAddress[%s] -> Create(By Contract Operation) Account = %s and Money = %s Success!!! \r\n", | |||
address, account, money); | |||
} | |||
@Override | |||
public String transfer(String address, String from, String to, long money) { | |||
// 首先查询余额 | |||
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to); | |||
if (kvDataEntries == null || kvDataEntries.length != 2) { | |||
throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to)); | |||
} else { | |||
// 判断from账号中钱数量是否足够 | |||
long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L; | |||
for (KVDataEntry kvDataEntry : kvDataEntries) { | |||
if (kvDataEntry.getKey().equals(from)) { | |||
fromMoney = (long) kvDataEntry.getValue(); | |||
fromVersion = kvDataEntry.getVersion(); | |||
} else { | |||
toMoney = (long) kvDataEntry.getValue(); | |||
toVersion = kvDataEntry.getVersion(); | |||
} | |||
} | |||
if (fromMoney < money) { | |||
throw new IllegalStateException(String.format("%s -> %s not have enough money !!!", address, from)); | |||
} | |||
long fromNewMoney = fromMoney - money; | |||
long toNewMoney = toMoney + money; | |||
// 重新设置 | |||
eventContext.getLedger().dataAccount(address).setInt64(from, fromNewMoney, fromVersion); | |||
eventContext.getLedger().dataAccount(address).setInt64(to, toNewMoney, toVersion); | |||
} | |||
return String.format("DataAccountAddress[%s] transfer from [%s] to [%s] and [money = %s] Success !!!", address, from, to, money); | |||
} | |||
@Override | |||
public long read(String address, String account) { | |||
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
return -1; | |||
} | |||
return (long)kvDataEntries[0].getValue(); | |||
} | |||
@Override | |||
public String readAll(String address, String account) { | |||
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
// 获取最新的版本号 | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
return ""; | |||
} | |||
long newestVersion = kvDataEntries[0].getVersion(); | |||
if (newestVersion == -1) { | |||
return ""; | |||
} | |||
KVDataVO[] kvDataVOS = new KVDataVO[1]; | |||
long[] versions = new long[(int)newestVersion + 1]; | |||
for (int i = 0; i < versions.length; i++) { | |||
versions[i] = i; | |||
} | |||
KVDataVO kvDataVO = new KVDataVO(account, versions); | |||
kvDataVOS[0] = kvDataVO; | |||
KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS); | |||
KVDataEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO); | |||
return JSON.toJSONString(allEntries); | |||
} | |||
@Override | |||
public void beforeEvent(ContractEventContext eventContext) { | |||
this.eventContext = eventContext; | |||
this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
} | |||
@Override | |||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||
} | |||
} | |||
``` | |||
#### 4.2、pom.xml文件实例 | |||
```xml | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<groupId>com.jd.chain</groupId> | |||
<version>1.0.0.RELEASE</version> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>contract-samples</artifactId> | |||
<name>contract-samples</name> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-pack</artifactId> | |||
<version>1.0.0.RELEASE</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
<version>1.2.32</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>contract-maven-plugin</artifactId> | |||
<version>1.0.0.RELEASE</version> | |||
<executions> | |||
<execution> | |||
<id>make-contract</id> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>compile</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
<configuration> | |||
<archive> | |||
<manifest> | |||
<mainClass>com.jd.chain.contract.TransferContractImpl</mainClass> | |||
</manifest> | |||
</archive> | |||
<finalName>contract</finalName> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> | |||
``` |
@@ -10,10 +10,6 @@ | |||
<artifactId>contract-maven-plugin</artifactId> | |||
<packaging>maven-plugin</packaging> | |||
<properties> | |||
<maven.version>3.3.9</maven.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
@@ -42,56 +38,24 @@ | |||
<dependency> | |||
<groupId>com.github.javaparser</groupId> | |||
<artifactId>javaparser-core</artifactId> | |||
<version>${javaparser.version}</version> | |||
</dependency> | |||
<!-- new --> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-plugin-api</artifactId> | |||
<version>3.3.9</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-core</artifactId> | |||
<version>3.3.9</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-artifact</artifactId> | |||
<version>3.3.9</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-compat</artifactId> | |||
<version>3.3.9</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<version>4.12</version> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven.plugin-testing</groupId> | |||
<artifactId>maven-plugin-testing-harness</artifactId> | |||
<scope>test</scope> | |||
<version>3.3.0</version> | |||
</dependency> | |||
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugin-tools/maven-plugin-annotations --> | |||
<dependency> | |||
<groupId>org.apache.maven.plugin-tools</groupId> | |||
<artifactId>maven-plugin-annotations</artifactId> | |||
<version>3.6.0</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven.shared</groupId> | |||
<artifactId>maven-invoker</artifactId> | |||
<version>3.0.1</version> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-assembly-plugin</artifactId> | |||
<version>2.6</version> | |||
</dependency> | |||
</dependencies> | |||
@@ -103,27 +67,6 @@ | |||
<artifactId>maven-plugin-plugin</artifactId> | |||
<version>3.5</version> | |||
</plugin> | |||
<!-- | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<configuration> | |||
<source>1.8</source> | |||
<target>1.8</target> | |||
<encoding>UTF-8</encoding> | |||
<optimize>false</optimize> | |||
<debug>true</debug> | |||
<showDeprecation>false</showDeprecation> | |||
<showWarnings>false</showWarnings> | |||
</configuration> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-surefire-plugin</artifactId> | |||
<configuration> | |||
<skipTests>true</skipTests> | |||
</configuration> | |||
</plugin>--> | |||
</plugins> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -1,216 +1,216 @@ | |||
package com.jd.blockchain.contract.maven; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.maven.model.Model; | |||
import org.apache.maven.model.Plugin; | |||
import org.apache.maven.model.PluginExecution; | |||
import org.apache.maven.model.io.xpp3.MavenXpp3Reader; | |||
import org.apache.maven.model.io.xpp3.MavenXpp3Writer; | |||
import org.apache.maven.plugin.AbstractMojo; | |||
import org.apache.maven.plugin.MojoFailureException; | |||
import org.apache.maven.plugins.annotations.Mojo; | |||
import org.apache.maven.plugins.annotations.Parameter; | |||
import org.apache.maven.project.MavenProject; | |||
import org.apache.maven.shared.invoker.*; | |||
import org.codehaus.plexus.util.xml.Xpp3Dom; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
@Mojo(name = "contractCheck") | |||
public class ContractCheckMojo extends AbstractMojo { | |||
Logger LOG = LoggerFactory.getLogger(ContractCheckMojo.class); | |||
public static final String CONTRACT_VERIFY = "contractVerify"; | |||
private static final String CONTRACT_MAVEN_PLUGIN = "contract-maven-plugin"; | |||
private static final String MAVEN_ASSEMBLY_PLUGIN = "maven-assembly-plugin"; | |||
private static final String JDCHAIN_PACKAGE = "com.jd.blockchain"; | |||
private static final String APACHE_MAVEN_PLUGINS = "org.apache.maven.plugins"; | |||
private static final String GOALS_VERIFY = "package"; | |||
private static final String GOALS_PACKAGE = "package"; | |||
private static final String OUT_POM_XML = "ContractPom.xml"; | |||
@Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
private MavenProject project; | |||
/** | |||
* jar's name; | |||
*/ | |||
@Parameter | |||
private String finalName; | |||
/** | |||
* mainClass; | |||
*/ | |||
@Parameter | |||
private String mainClass; | |||
/** | |||
* ledgerVersion; | |||
*/ | |||
@Parameter | |||
private String ledgerVersion; | |||
/** | |||
* mvnHome; | |||
*/ | |||
@Parameter | |||
private String mvnHome; | |||
/** | |||
* first compile the class, then parse it; | |||
*/ | |||
@Override | |||
public void execute() throws MojoFailureException { | |||
compileFiles(); | |||
} | |||
private void compileFiles() throws MojoFailureException { | |||
try (FileInputStream fis = new FileInputStream(project.getFile())) { | |||
MavenXpp3Reader reader = new MavenXpp3Reader(); | |||
Model model = reader.read(fis); | |||
//delete this plugin(contractCheck) from destination pom.xml;then add the proper plugins; | |||
Plugin plugin = model.getBuild().getPluginsAsMap() | |||
.get(JDCHAIN_PACKAGE + ":" + CONTRACT_MAVEN_PLUGIN); | |||
if(plugin == null){ | |||
plugin = model.getBuild().getPluginsAsMap() | |||
.get(APACHE_MAVEN_PLUGINS + ":" + CONTRACT_MAVEN_PLUGIN); | |||
} | |||
if(plugin == null) { | |||
return; | |||
} | |||
model.getBuild().removePlugin(plugin); | |||
List<Plugin> plugins = new ArrayList<>(); | |||
plugins.add(createAssembly()); | |||
plugins.add(createContractVerify()); | |||
model.getBuild().setPlugins(plugins); | |||
handle(model); | |||
} catch (Exception e) { | |||
LOG.error(e.getMessage()); | |||
throw new MojoFailureException(e.getMessage()); | |||
} | |||
} | |||
private void invokeCompile(File file) { | |||
InvocationRequest request = new DefaultInvocationRequest(); | |||
Invoker invoker = new DefaultInvoker(); | |||
try { | |||
request.setPomFile(file); | |||
request.setGoals(Collections.singletonList(GOALS_VERIFY)); | |||
invoker.setMavenHome(new File(mvnHome)); | |||
invoker.execute(request); | |||
} catch (MavenInvocationException e) { | |||
LOG.error(e.getMessage()); | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
private Plugin createContractVerify() { | |||
Plugin plugin = new Plugin(); | |||
plugin.setGroupId(JDCHAIN_PACKAGE); | |||
plugin.setArtifactId(CONTRACT_MAVEN_PLUGIN); | |||
plugin.setVersion(ledgerVersion); | |||
Xpp3Dom finalNameNode = new Xpp3Dom("finalName"); | |||
finalNameNode.setValue(finalName); | |||
Xpp3Dom configuration = new Xpp3Dom("configuration"); | |||
configuration.addChild(finalNameNode); | |||
plugin.setConfiguration(configuration); | |||
plugin.setExecutions(pluginExecution("make-assembly", GOALS_VERIFY, CONTRACT_VERIFY)); | |||
return plugin; | |||
} | |||
private Plugin createAssembly() { | |||
Plugin plugin = new Plugin(); | |||
plugin.setArtifactId(MAVEN_ASSEMBLY_PLUGIN); | |||
Xpp3Dom configuration = new Xpp3Dom("configuration"); | |||
Xpp3Dom mainClassNode = new Xpp3Dom("mainClass"); | |||
mainClassNode.setValue(mainClass); | |||
Xpp3Dom manifest = new Xpp3Dom("manifest"); | |||
manifest.addChild(mainClassNode); | |||
Xpp3Dom archive = new Xpp3Dom("archive"); | |||
archive.addChild(manifest); | |||
Xpp3Dom finalNameNode = new Xpp3Dom("finalName"); | |||
finalNameNode.setValue(finalName); | |||
Xpp3Dom appendAssemblyId = new Xpp3Dom("appendAssemblyId"); | |||
appendAssemblyId.setValue("false"); | |||
Xpp3Dom descriptorRef = new Xpp3Dom("descriptorRef"); | |||
descriptorRef.setValue("jar-with-dependencies"); | |||
Xpp3Dom descriptorRefs = new Xpp3Dom("descriptorRefs"); | |||
descriptorRefs.addChild(descriptorRef); | |||
configuration.addChild(finalNameNode); | |||
configuration.addChild(appendAssemblyId); | |||
configuration.addChild(archive); | |||
configuration.addChild(descriptorRefs); | |||
plugin.setConfiguration(configuration); | |||
plugin.setExecutions(pluginExecution("make-assembly", GOALS_PACKAGE, "single")); | |||
return plugin; | |||
} | |||
private List<PluginExecution> pluginExecution(String id, String phase, String goal) { | |||
PluginExecution pluginExecution = new PluginExecution(); | |||
pluginExecution.setId(id); | |||
pluginExecution.setPhase(phase); | |||
List<String> goals = new ArrayList<>(); | |||
goals.add(goal); | |||
pluginExecution.setGoals(goals); | |||
List<PluginExecution> pluginExecutions = new ArrayList<>(); | |||
pluginExecutions.add(pluginExecution); | |||
return pluginExecutions; | |||
} | |||
private void handle(Model model) throws IOException { | |||
MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer(); | |||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | |||
mavenXpp3Writer.write(outputStream, model); | |||
byte[] buffer = outputStream.toByteArray(); | |||
File outPom = new File(project.getBasedir().getPath(), OUT_POM_XML); | |||
FileUtils.writeByteArrayToFile(outPom, buffer); | |||
invokeCompile(outPom); | |||
} | |||
} | |||
//package com.jd.blockchain.contract.maven; | |||
// | |||
//import org.apache.commons.io.FileUtils; | |||
//import org.apache.maven.model.Model; | |||
//import org.apache.maven.model.Plugin; | |||
//import org.apache.maven.model.PluginExecution; | |||
//import org.apache.maven.model.io.xpp3.MavenXpp3Reader; | |||
//import org.apache.maven.model.io.xpp3.MavenXpp3Writer; | |||
//import org.apache.maven.plugin.AbstractMojo; | |||
//import org.apache.maven.plugin.MojoFailureException; | |||
//import org.apache.maven.plugins.annotations.Mojo; | |||
//import org.apache.maven.plugins.annotations.Parameter; | |||
//import org.apache.maven.project.MavenProject; | |||
//import org.apache.maven.shared.invoker.*; | |||
//import org.codehaus.plexus.util.xml.Xpp3Dom; | |||
//import org.slf4j.Logger; | |||
//import org.slf4j.LoggerFactory; | |||
// | |||
//import java.io.ByteArrayOutputStream; | |||
//import java.io.File; | |||
//import java.io.FileInputStream; | |||
//import java.io.IOException; | |||
//import java.util.ArrayList; | |||
//import java.util.Collections; | |||
//import java.util.List; | |||
// | |||
// | |||
//@Mojo(name = "contractCheck") | |||
//public class ContractCheckMojo extends AbstractMojo { | |||
// | |||
// Logger LOG = LoggerFactory.getLogger(ContractCheckMojo.class); | |||
// | |||
// public static final String CONTRACT_VERIFY = "contractVerify"; | |||
// | |||
// private static final String CONTRACT_MAVEN_PLUGIN = "contract-maven-plugin"; | |||
// | |||
// private static final String MAVEN_ASSEMBLY_PLUGIN = "maven-assembly-plugin"; | |||
// | |||
// private static final String JDCHAIN_PACKAGE = "com.jd.blockchain"; | |||
// | |||
// private static final String APACHE_MAVEN_PLUGINS = "org.apache.maven.plugins"; | |||
// | |||
// private static final String GOALS_VERIFY = "package"; | |||
// | |||
// private static final String GOALS_PACKAGE = "package"; | |||
// | |||
// private static final String OUT_POM_XML = "ContractPom.xml"; | |||
// | |||
// @Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
// private MavenProject project; | |||
// | |||
// /** | |||
// * jar's name; | |||
// */ | |||
// @Parameter | |||
// private String finalName; | |||
// | |||
// /** | |||
// * mainClass; | |||
// */ | |||
// @Parameter | |||
// private String mainClass; | |||
// /** | |||
// * ledgerVersion; | |||
// */ | |||
// @Parameter | |||
// private String ledgerVersion; | |||
// | |||
// /** | |||
// * mvnHome; | |||
// */ | |||
// @Parameter | |||
// private String mvnHome; | |||
// | |||
// /** | |||
// * first compile the class, then parse it; | |||
// */ | |||
// @Override | |||
// public void execute() throws MojoFailureException { | |||
// compileFiles(); | |||
// } | |||
// | |||
// private void compileFiles() throws MojoFailureException { | |||
// try (FileInputStream fis = new FileInputStream(project.getFile())) { | |||
// | |||
// MavenXpp3Reader reader = new MavenXpp3Reader(); | |||
// Model model = reader.read(fis); | |||
// | |||
// //delete this plugin(contractCheck) from destination pom.xml;then add the proper plugins; | |||
// Plugin plugin = model.getBuild().getPluginsAsMap() | |||
// .get(JDCHAIN_PACKAGE + ":" + CONTRACT_MAVEN_PLUGIN); | |||
// if(plugin == null){ | |||
// plugin = model.getBuild().getPluginsAsMap() | |||
// .get(APACHE_MAVEN_PLUGINS + ":" + CONTRACT_MAVEN_PLUGIN); | |||
// } | |||
// | |||
// if(plugin == null) { | |||
// return; | |||
// } | |||
// | |||
// model.getBuild().removePlugin(plugin); | |||
// | |||
// List<Plugin> plugins = new ArrayList<>(); | |||
// plugins.add(createAssembly()); | |||
// plugins.add(createContractVerify()); | |||
// | |||
// model.getBuild().setPlugins(plugins); | |||
// | |||
// handle(model); | |||
// | |||
// } catch (Exception e) { | |||
// LOG.error(e.getMessage()); | |||
// throw new MojoFailureException(e.getMessage()); | |||
// } | |||
// } | |||
// | |||
// private void invokeCompile(File file) { | |||
// InvocationRequest request = new DefaultInvocationRequest(); | |||
// | |||
// Invoker invoker = new DefaultInvoker(); | |||
// try { | |||
// request.setPomFile(file); | |||
// | |||
// request.setGoals(Collections.singletonList(GOALS_VERIFY)); | |||
// invoker.setMavenHome(new File(mvnHome)); | |||
// invoker.execute(request); | |||
// } catch (MavenInvocationException e) { | |||
// LOG.error(e.getMessage()); | |||
// throw new IllegalStateException(e); | |||
// } | |||
// } | |||
// | |||
// private Plugin createContractVerify() { | |||
// Plugin plugin = new Plugin(); | |||
// plugin.setGroupId(JDCHAIN_PACKAGE); | |||
// plugin.setArtifactId(CONTRACT_MAVEN_PLUGIN); | |||
// plugin.setVersion(ledgerVersion); | |||
// | |||
// Xpp3Dom finalNameNode = new Xpp3Dom("finalName"); | |||
// finalNameNode.setValue(finalName); | |||
// Xpp3Dom configuration = new Xpp3Dom("configuration"); | |||
// configuration.addChild(finalNameNode); | |||
// | |||
// plugin.setConfiguration(configuration); | |||
// plugin.setExecutions(pluginExecution("make-assembly", GOALS_VERIFY, CONTRACT_VERIFY)); | |||
// | |||
// return plugin; | |||
// } | |||
// | |||
// private Plugin createAssembly() { | |||
// Plugin plugin = new Plugin(); | |||
// plugin.setArtifactId(MAVEN_ASSEMBLY_PLUGIN); | |||
// | |||
// Xpp3Dom configuration = new Xpp3Dom("configuration"); | |||
// | |||
// Xpp3Dom mainClassNode = new Xpp3Dom("mainClass"); | |||
// mainClassNode.setValue(mainClass); | |||
// | |||
// Xpp3Dom manifest = new Xpp3Dom("manifest"); | |||
// manifest.addChild(mainClassNode); | |||
// | |||
// Xpp3Dom archive = new Xpp3Dom("archive"); | |||
// archive.addChild(manifest); | |||
// | |||
// Xpp3Dom finalNameNode = new Xpp3Dom("finalName"); | |||
// finalNameNode.setValue(finalName); | |||
// | |||
// Xpp3Dom appendAssemblyId = new Xpp3Dom("appendAssemblyId"); | |||
// appendAssemblyId.setValue("false"); | |||
// | |||
// Xpp3Dom descriptorRef = new Xpp3Dom("descriptorRef"); | |||
// descriptorRef.setValue("jar-with-dependencies"); | |||
// Xpp3Dom descriptorRefs = new Xpp3Dom("descriptorRefs"); | |||
// descriptorRefs.addChild(descriptorRef); | |||
// | |||
// configuration.addChild(finalNameNode); | |||
// configuration.addChild(appendAssemblyId); | |||
// configuration.addChild(archive); | |||
// configuration.addChild(descriptorRefs); | |||
// | |||
// plugin.setConfiguration(configuration); | |||
// plugin.setExecutions(pluginExecution("make-assembly", GOALS_PACKAGE, "single")); | |||
// | |||
// return plugin; | |||
// } | |||
// | |||
// private List<PluginExecution> pluginExecution(String id, String phase, String goal) { | |||
// PluginExecution pluginExecution = new PluginExecution(); | |||
// pluginExecution.setId(id); | |||
// pluginExecution.setPhase(phase); | |||
// List<String> goals = new ArrayList<>(); | |||
// goals.add(goal); | |||
// pluginExecution.setGoals(goals); | |||
// List<PluginExecution> pluginExecutions = new ArrayList<>(); | |||
// pluginExecutions.add(pluginExecution); | |||
// | |||
// return pluginExecutions; | |||
// } | |||
// | |||
// private void handle(Model model) throws IOException { | |||
// | |||
// MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer(); | |||
// | |||
// ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | |||
// | |||
// mavenXpp3Writer.write(outputStream, model); | |||
// | |||
// byte[] buffer = outputStream.toByteArray(); | |||
// | |||
// File outPom = new File(project.getBasedir().getPath(), OUT_POM_XML); | |||
// | |||
// FileUtils.writeByteArrayToFile(outPom, buffer); | |||
// | |||
// invokeCompile(outPom); | |||
// } | |||
//} |
@@ -0,0 +1,30 @@ | |||
package com.jd.blockchain.contract.maven; | |||
import org.apache.maven.plugin.MojoExecutionException; | |||
import org.apache.maven.plugin.MojoFailureException; | |||
import org.apache.maven.plugin.assembly.mojos.SingleAssemblyMojo; | |||
import org.apache.maven.plugins.annotations.Mojo; | |||
@Mojo(name = "compile") | |||
public class ContractCompileMojo extends SingleAssemblyMojo { | |||
public static final String JAR_DEPENDENCE = "jar-with-dependencies"; | |||
@Override | |||
public void execute() throws MojoExecutionException, MojoFailureException { | |||
// 要求必须有MainClass | |||
try { | |||
String mainClass = super.getJarArchiveConfiguration().getManifest().getMainClass(); | |||
super.getLog().debug("MainClass is " + mainClass); | |||
} catch (Exception e) { | |||
throw new MojoFailureException("MainClass is null: " + e.getMessage(), e ); | |||
} | |||
super.setDescriptorRefs(new String[]{JAR_DEPENDENCE}); | |||
super.execute(); | |||
ContractResolveEngine engine = new ContractResolveEngine(getLog(), getProject(), getFinalName()); | |||
engine.compileAndVerify(); | |||
} | |||
} |
@@ -1,176 +1,176 @@ | |||
package com.jd.blockchain.contract.maven; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.codec.Base58Utils; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
/** | |||
* @Author zhaogw | |||
* @Date 2018/11/2 10:18 | |||
*/ | |||
public enum ContractDeployExeUtil { | |||
instance; | |||
private BlockchainService bcsrv; | |||
private Bytes contractAddress; | |||
public BlockchainKeypair getKeyPair(String pubPath, String prvPath, String rawPassword){ | |||
PubKey pub = null; | |||
PrivKey prv = null; | |||
try { | |||
prv = KeyGenCommand.readPrivKey(prvPath, KeyGenCommand.encodePassword(rawPassword)); | |||
pub = KeyGenCommand.readPubKey(pubPath); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return new BlockchainKeypair(pub, prv); | |||
} | |||
public PubKey getPubKey(String pubPath){ | |||
PubKey pub = null; | |||
try { | |||
if(pubPath == null){ | |||
BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate(); | |||
pub = contractKeyPair.getPubKey(); | |||
}else { | |||
pub = KeyGenCommand.readPubKey(pubPath); | |||
} | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return pub; | |||
} | |||
public byte[] getChainCode(String path){ | |||
byte[] chainCode = null; | |||
File file = null; | |||
InputStream input = null; | |||
try { | |||
file = new File(path); | |||
input = new FileInputStream(file); | |||
chainCode = new byte[input.available()]; | |||
input.read(chainCode); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} finally { | |||
try { | |||
if(input!=null){ | |||
input.close(); | |||
} | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
return chainCode; | |||
} | |||
private void register(){ | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
DataContractRegistry.register(DataAccountKVSetOperation.class); | |||
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); | |||
DataContractRegistry.register(Operation.class); | |||
DataContractRegistry.register(ContractCodeDeployOperation.class); | |||
DataContractRegistry.register(ContractEventSendOperation.class); | |||
DataContractRegistry.register(DataAccountRegisterOperation.class); | |||
DataContractRegistry.register(UserRegisterOperation.class); | |||
} | |||
public BlockchainService initBcsrv(String host, int port) { | |||
if(bcsrv!=null){ | |||
return bcsrv; | |||
} | |||
NetworkAddress addr = new NetworkAddress(host, port); | |||
GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(addr); | |||
bcsrv = gwsrvFact.getBlockchainService(); | |||
return bcsrv; | |||
} | |||
public boolean deploy(HashDigest ledgerHash, BlockchainIdentity contractIdentity, BlockchainKeypair ownerKey, byte[] chainCode){ | |||
register(); | |||
TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash); | |||
txTpl.contracts().deploy(contractIdentity, chainCode); | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
ptx.sign(ownerKey); | |||
// 提交并等待共识返回; | |||
TransactionResponse txResp = ptx.commit(); | |||
// 验证结果; | |||
contractAddress = contractIdentity.getAddress(); | |||
this.setContractAddress(contractAddress); | |||
System.out.println("contract's address="+contractAddress); | |||
return txResp.isSuccess(); | |||
} | |||
public boolean deploy(String host, int port, HashDigest ledgerHash, BlockchainKeypair ownerKey, byte[] chainCode){ | |||
register(); | |||
BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity(); | |||
initBcsrv(host,port); | |||
return deploy(ledgerHash, contractIdentity, ownerKey, chainCode); | |||
} | |||
// 根据用户指定的公钥生成合约地址 | |||
public boolean deploy(String host, int port, String ledger,String ownerPubPath, String ownerPrvPath, | |||
String ownerPassword, String chainCodePath,String pubPath){ | |||
PubKey pubKey = getPubKey(pubPath); | |||
BlockchainIdentity contractIdentity = new BlockchainIdentityData(pubKey); | |||
byte[] chainCode = getChainCode(chainCodePath); | |||
BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword); | |||
HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
initBcsrv(host,port); | |||
return deploy(ledgerHash, contractIdentity, ownerKey, chainCode); | |||
} | |||
// 暂不支持从插件执行合约;此外,由于合约参数调用的格式发生变化,故此方法被废弃;by: huanghaiquan at 2019-04-30; | |||
// public boolean exeContract(String ledger,String ownerPubPath, String ownerPrvPath, | |||
// String ownerPassword,String event,String contractArgs){ | |||
// BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword); | |||
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
//package com.jd.blockchain.contract.maven; | |||
// | |||
// // 定义交易,传输最简单的数字、字符串、提取合约中的地址; | |||
// TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash); | |||
// txTpl.contractEvents().send(getContractAddress(),event,contractArgs.getBytes()); | |||
//import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
//import com.jd.blockchain.crypto.HashDigest; | |||
//import com.jd.blockchain.crypto.PrivKey; | |||
//import com.jd.blockchain.crypto.PubKey; | |||
//import com.jd.blockchain.ledger.*; | |||
//import com.jd.blockchain.sdk.BlockchainService; | |||
//import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
//import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
//import com.jd.blockchain.utils.Bytes; | |||
//import com.jd.blockchain.utils.codec.Base58Utils; | |||
//import com.jd.blockchain.utils.net.NetworkAddress; | |||
// | |||
//import java.io.File; | |||
//import java.io.FileInputStream; | |||
//import java.io.IOException; | |||
//import java.io.InputStream; | |||
// | |||
///** | |||
// * @Author zhaogw | |||
// * @Date 2018/11/2 10:18 | |||
// */ | |||
//public enum ContractDeployExeUtil { | |||
// instance; | |||
// private BlockchainService bcsrv; | |||
// private Bytes contractAddress; | |||
// | |||
// public BlockchainKeypair getKeyPair(String pubPath, String prvPath, String rawPassword){ | |||
// PubKey pub = null; | |||
// PrivKey prv = null; | |||
// try { | |||
// prv = KeyGenCommand.readPrivKey(prvPath, KeyGenCommand.encodePassword(rawPassword)); | |||
// pub = KeyGenCommand.readPubKey(pubPath); | |||
// | |||
// } catch (Exception e) { | |||
// e.printStackTrace(); | |||
// } | |||
// | |||
// return new BlockchainKeypair(pub, prv); | |||
// } | |||
// | |||
// public PubKey getPubKey(String pubPath){ | |||
// PubKey pub = null; | |||
// try { | |||
// if(pubPath == null){ | |||
// BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate(); | |||
// pub = contractKeyPair.getPubKey(); | |||
// }else { | |||
// pub = KeyGenCommand.readPubKey(pubPath); | |||
// } | |||
// | |||
// } catch (Exception e) { | |||
// e.printStackTrace(); | |||
// } | |||
// | |||
// return pub; | |||
// } | |||
// public byte[] getChainCode(String path){ | |||
// byte[] chainCode = null; | |||
// File file = null; | |||
// InputStream input = null; | |||
// try { | |||
// file = new File(path); | |||
// input = new FileInputStream(file); | |||
// chainCode = new byte[input.available()]; | |||
// input.read(chainCode); | |||
// | |||
// } catch (IOException e) { | |||
// e.printStackTrace(); | |||
// } finally { | |||
// try { | |||
// if(input!=null){ | |||
// input.close(); | |||
// } | |||
// } catch (IOException e) { | |||
// e.printStackTrace(); | |||
// } | |||
// } | |||
// return chainCode; | |||
// } | |||
// | |||
// private void register(){ | |||
// DataContractRegistry.register(TransactionContent.class); | |||
// DataContractRegistry.register(TransactionContentBody.class); | |||
// DataContractRegistry.register(TransactionRequest.class); | |||
// DataContractRegistry.register(NodeRequest.class); | |||
// DataContractRegistry.register(EndpointRequest.class); | |||
// DataContractRegistry.register(TransactionResponse.class); | |||
// DataContractRegistry.register(DataAccountKVSetOperation.class); | |||
// DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); | |||
// DataContractRegistry.register(Operation.class); | |||
// DataContractRegistry.register(ContractCodeDeployOperation.class); | |||
// DataContractRegistry.register(ContractEventSendOperation.class); | |||
// DataContractRegistry.register(DataAccountRegisterOperation.class); | |||
// DataContractRegistry.register(UserRegisterOperation.class); | |||
// } | |||
// | |||
// public BlockchainService initBcsrv(String host, int port) { | |||
// if(bcsrv!=null){ | |||
// return bcsrv; | |||
// } | |||
// NetworkAddress addr = new NetworkAddress(host, port); | |||
// GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(addr); | |||
// bcsrv = gwsrvFact.getBlockchainService(); | |||
// return bcsrv; | |||
// } | |||
// | |||
// public boolean deploy(HashDigest ledgerHash, BlockchainIdentity contractIdentity, BlockchainKeypair ownerKey, byte[] chainCode){ | |||
// register(); | |||
// | |||
// // 签名; | |||
// TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash); | |||
// txTpl.contracts().deploy(contractIdentity, chainCode); | |||
// PreparedTransaction ptx = txTpl.prepare(); | |||
// ptx.sign(ownerKey); | |||
// | |||
// // 提交并等待共识返回; | |||
// TransactionResponse txResp = ptx.commit(); | |||
// | |||
// // 验证结果; | |||
// contractAddress = contractIdentity.getAddress(); | |||
// this.setContractAddress(contractAddress); | |||
// System.out.println("contract's address="+contractAddress); | |||
// return txResp.isSuccess(); | |||
// } | |||
public Bytes getContractAddress() { | |||
return contractAddress; | |||
} | |||
public void setContractAddress(Bytes contractAddress) { | |||
this.contractAddress = contractAddress; | |||
} | |||
} | |||
// public boolean deploy(String host, int port, HashDigest ledgerHash, BlockchainKeypair ownerKey, byte[] chainCode){ | |||
// register(); | |||
// | |||
// BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity(); | |||
// initBcsrv(host,port); | |||
// return deploy(ledgerHash, contractIdentity, ownerKey, chainCode); | |||
// } | |||
// | |||
// // 根据用户指定的公钥生成合约地址 | |||
// public boolean deploy(String host, int port, String ledger,String ownerPubPath, String ownerPrvPath, | |||
// String ownerPassword, String chainCodePath,String pubPath){ | |||
// PubKey pubKey = getPubKey(pubPath); | |||
// BlockchainIdentity contractIdentity = new BlockchainIdentityData(pubKey); | |||
// byte[] chainCode = getChainCode(chainCodePath); | |||
// | |||
// BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword); | |||
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
// initBcsrv(host,port); | |||
// return deploy(ledgerHash, contractIdentity, ownerKey, chainCode); | |||
// } | |||
// | |||
// | |||
//// 暂不支持从插件执行合约;此外,由于合约参数调用的格式发生变化,故此方法被废弃;by: huanghaiquan at 2019-04-30; | |||
// | |||
//// public boolean exeContract(String ledger,String ownerPubPath, String ownerPrvPath, | |||
//// String ownerPassword,String event,String contractArgs){ | |||
//// BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword); | |||
//// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
//// | |||
//// // 定义交易,传输最简单的数字、字符串、提取合约中的地址; | |||
//// TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash); | |||
//// txTpl.contractEvents().send(getContractAddress(),event,contractArgs.getBytes()); | |||
//// | |||
//// // 签名; | |||
//// PreparedTransaction ptx = txTpl.prepare(); | |||
//// ptx.sign(ownerKey); | |||
//// | |||
//// // 提交并等待共识返回; | |||
//// TransactionResponse txResp = ptx.commit(); | |||
//// | |||
//// // 验证结果; | |||
//// return txResp.isSuccess(); | |||
//// } | |||
// | |||
// public Bytes getContractAddress() { | |||
// return contractAddress; | |||
// } | |||
// | |||
// public void setContractAddress(Bytes contractAddress) { | |||
// this.contractAddress = contractAddress; | |||
// } | |||
//} |
@@ -1,119 +1,120 @@ | |||
package com.jd.blockchain.contract.maven; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
import com.jd.blockchain.utils.StringUtils; | |||
import com.jd.blockchain.utils.codec.Base58Utils; | |||
import com.jd.blockchain.utils.io.FileUtils; | |||
import org.apache.maven.plugin.AbstractMojo; | |||
import org.apache.maven.plugin.MojoFailureException; | |||
import org.apache.maven.plugins.annotations.Mojo; | |||
import org.apache.maven.plugins.annotations.Parameter; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.Properties; | |||
/** | |||
* for contract remote deploy; | |||
* @goal contractDeploy | |||
* @phase process-sources | |||
* @Author zhaogw | |||
* @Date 2018/10/18 10:12 | |||
*/ | |||
@Mojo(name = "deploy") | |||
public class ContractDeployMojo extends AbstractMojo { | |||
Logger logger = LoggerFactory.getLogger(ContractDeployMojo.class); | |||
@Parameter | |||
private File config; | |||
@Override | |||
public void execute()throws MojoFailureException { | |||
Properties prop = new Properties(); | |||
InputStream input = null; | |||
try { | |||
input = new FileInputStream(config); | |||
prop.load(input); | |||
} catch (IOException ex) { | |||
logger.error(ex.getMessage()); | |||
throw new MojoFailureException("io error"); | |||
} finally { | |||
if (input != null) { | |||
try { | |||
input.close(); | |||
} catch (IOException e) { | |||
logger.error(e.getMessage()); | |||
} | |||
} | |||
} | |||
int port; | |||
try { | |||
port = Integer.parseInt(prop.getProperty("port")); | |||
}catch (NumberFormatException e){ | |||
logger.error(e.getMessage()); | |||
throw new MojoFailureException("invalid port"); | |||
} | |||
String host = prop.getProperty("host"); | |||
String ledger = prop.getProperty("ledger"); | |||
String pubKey = prop.getProperty("pubKey"); | |||
String prvKey = prop.getProperty("prvKey"); | |||
String password = prop.getProperty("password"); | |||
String contractPath = prop.getProperty("contractPath"); | |||
if(StringUtils.isEmpty(host)){ | |||
logger.info("host不能为空"); | |||
return; | |||
} | |||
if(StringUtils.isEmpty(ledger)){ | |||
logger.info("ledger不能为空."); | |||
return; | |||
} | |||
if(StringUtils.isEmpty(pubKey)){ | |||
logger.info("pubKey不能为空."); | |||
return; | |||
} | |||
if(StringUtils.isEmpty(prvKey)){ | |||
logger.info("prvKey不能为空."); | |||
return; | |||
} | |||
if(StringUtils.isEmpty(contractPath)){ | |||
logger.info("contractPath不能为空."); | |||
return; | |||
} | |||
File contract = new File(contractPath); | |||
if (!contract.isFile()){ | |||
logger.info("文件"+contractPath+"不存在"); | |||
return; | |||
} | |||
byte[] contractBytes = FileUtils.readBytes(contractPath); | |||
PrivKey prv = KeyGenCommand.decodePrivKeyWithRawPassword(prvKey, password); | |||
PubKey pub = KeyGenCommand.decodePubKey(pubKey); | |||
BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(pub, prv); | |||
HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("host:"+ host).append(",port:"+port).append(",ledgerHash:"+ledgerHash.toBase58()). | |||
append(",pubKey:"+pubKey).append(",prvKey:"+prv).append(",contractPath:"+contractPath); | |||
logger.info(sb.toString()); | |||
ContractDeployExeUtil.instance.deploy(host,port,ledgerHash, blockchainKeyPair, contractBytes); | |||
} | |||
} | |||
//package com.jd.blockchain.contract.maven; | |||
// | |||
//import com.jd.blockchain.crypto.HashDigest; | |||
//import com.jd.blockchain.crypto.PrivKey; | |||
//import com.jd.blockchain.crypto.PubKey; | |||
//import com.jd.blockchain.ledger.BlockchainKeypair; | |||
//import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
//import com.jd.blockchain.utils.StringUtils; | |||
//import com.jd.blockchain.utils.codec.Base58Utils; | |||
//import com.jd.blockchain.utils.io.FileUtils; | |||
//import org.apache.maven.plugin.AbstractMojo; | |||
//import org.apache.maven.plugin.MojoFailureException; | |||
//import org.apache.maven.plugins.annotations.Mojo; | |||
//import org.apache.maven.plugins.annotations.Parameter; | |||
//import org.slf4j.Logger; | |||
//import org.slf4j.LoggerFactory; | |||
// | |||
//import java.io.File; | |||
//import java.io.FileInputStream; | |||
//import java.io.IOException; | |||
//import java.io.InputStream; | |||
//import java.util.Properties; | |||
// | |||
///** | |||
// * for contract remote deploy; | |||
// * @goal contractDeploy | |||
// * @phase process-sources | |||
// * @Author zhaogw | |||
// * @Date 2018/10/18 10:12 | |||
// */ | |||
// | |||
//@Mojo(name = "deploy") | |||
//public class ContractDeployMojo extends AbstractMojo { | |||
// Logger logger = LoggerFactory.getLogger(ContractDeployMojo.class); | |||
// | |||
// @Parameter | |||
// private File config; | |||
// | |||
// @Override | |||
// public void execute()throws MojoFailureException { | |||
// | |||
// Properties prop = new Properties(); | |||
// InputStream input = null; | |||
// | |||
// try { | |||
// input = new FileInputStream(config); | |||
// prop.load(input); | |||
// | |||
// } catch (IOException ex) { | |||
// logger.error(ex.getMessage()); | |||
// throw new MojoFailureException("io error"); | |||
// } finally { | |||
// if (input != null) { | |||
// try { | |||
// input.close(); | |||
// } catch (IOException e) { | |||
// logger.error(e.getMessage()); | |||
// } | |||
// } | |||
// } | |||
// int port; | |||
// try { | |||
// port = Integer.parseInt(prop.getProperty("port")); | |||
// }catch (NumberFormatException e){ | |||
// logger.error(e.getMessage()); | |||
// throw new MojoFailureException("invalid port"); | |||
// } | |||
// String host = prop.getProperty("host"); | |||
// String ledger = prop.getProperty("ledger"); | |||
// String pubKey = prop.getProperty("pubKey"); | |||
// String prvKey = prop.getProperty("prvKey"); | |||
// String password = prop.getProperty("password"); | |||
// String contractPath = prop.getProperty("contractPath"); | |||
// | |||
// | |||
// if(StringUtils.isEmpty(host)){ | |||
// logger.info("host不能为空"); | |||
// return; | |||
// } | |||
// | |||
// if(StringUtils.isEmpty(ledger)){ | |||
// logger.info("ledger不能为空."); | |||
// return; | |||
// } | |||
// if(StringUtils.isEmpty(pubKey)){ | |||
// logger.info("pubKey不能为空."); | |||
// return; | |||
// } | |||
// if(StringUtils.isEmpty(prvKey)){ | |||
// logger.info("prvKey不能为空."); | |||
// return; | |||
// } | |||
// if(StringUtils.isEmpty(contractPath)){ | |||
// logger.info("contractPath不能为空."); | |||
// return; | |||
// } | |||
// | |||
// File contract = new File(contractPath); | |||
// if (!contract.isFile()){ | |||
// logger.info("文件"+contractPath+"不存在"); | |||
// return; | |||
// } | |||
// byte[] contractBytes = FileUtils.readBytes(contractPath); | |||
// | |||
// | |||
// PrivKey prv = KeyGenCommand.decodePrivKeyWithRawPassword(prvKey, password); | |||
// PubKey pub = KeyGenCommand.decodePubKey(pubKey); | |||
// BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(pub, prv); | |||
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
// | |||
// StringBuffer sb = new StringBuffer(); | |||
// sb.append("host:"+ host).append(",port:"+port).append(",ledgerHash:"+ledgerHash.toBase58()). | |||
// append(",pubKey:"+pubKey).append(",prvKey:"+prv).append(",contractPath:"+contractPath); | |||
// logger.info(sb.toString()); | |||
// ContractDeployExeUtil.instance.deploy(host,port,ledgerHash, blockchainKeyPair, contractBytes); | |||
// } | |||
// | |||
//} | |||
// | |||
// |
@@ -6,13 +6,9 @@ import com.github.javaparser.ast.ImportDeclaration; | |||
import com.github.javaparser.ast.visitor.VoidVisitorAdapter; | |||
import com.jd.blockchain.contract.ContractType; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.maven.plugin.AbstractMojo; | |||
import org.apache.maven.plugin.MojoExecutionException; | |||
import org.apache.maven.plugins.annotations.Mojo; | |||
import org.apache.maven.plugins.annotations.Parameter; | |||
import org.apache.maven.plugin.MojoFailureException; | |||
import org.apache.maven.plugin.logging.Log; | |||
import org.apache.maven.project.MavenProject; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.File; | |||
import java.io.IOException; | |||
@@ -24,32 +20,11 @@ import java.util.jar.Attributes; | |||
import java.util.jar.JarEntry; | |||
import java.util.jar.JarFile; | |||
import static com.jd.blockchain.contract.maven.ContractCheckMojo.CONTRACT_VERIFY; | |||
import static com.jd.blockchain.contract.maven.ContractCompileMojo.JAR_DEPENDENCE; | |||
import static com.jd.blockchain.utils.decompiler.utils.DecompilerUtils.decompileJarFile; | |||
import static com.jd.blockchain.utils.jar.ContractJarUtils.*; | |||
/** | |||
* first step, we want to parse the source code by javaParse. But it's repeated and difficult to parse the source. | |||
* This is a try of "from Initail to Abandoned". | |||
* Since we are good at the class, why not? | |||
* Now we change a way of thinking, first we pre-compile the source code, then parse the *.jar. | |||
* | |||
* by zhaogw | |||
* date 2019-06-05 16:17 | |||
*/ | |||
@Mojo(name = CONTRACT_VERIFY) | |||
public class ContractVerifyMojo extends AbstractMojo { | |||
Logger LOG = LoggerFactory.getLogger(ContractVerifyMojo.class); | |||
@Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
private MavenProject project; | |||
/** | |||
* jar's name; | |||
*/ | |||
@Parameter | |||
private String finalName; | |||
public class ContractResolveEngine { | |||
private static final String JAVA_SUFFIX = ".java"; | |||
@@ -66,19 +41,49 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
private static final String BLACK_NAME_LIST = "black.name.list"; | |||
@Override | |||
public void execute() throws MojoExecutionException { | |||
private Log LOGGER; | |||
private MavenProject project; | |||
private String finalName; | |||
public ContractResolveEngine(Log LOGGER, MavenProject project, String finalName) { | |||
this.LOGGER = LOGGER; | |||
this.project = project; | |||
this.finalName = finalName; | |||
} | |||
public void compileAndVerify() throws MojoFailureException { | |||
try { | |||
jarCopy(); | |||
verify(compileCustomJar()); | |||
} catch (IOException e) { | |||
throw new MojoFailureException("IO Error : " + e.getMessage(), e); | |||
} catch (MojoFailureException ex) { | |||
throw ex; | |||
} | |||
} | |||
File jarFile = copyAndManage(); | |||
private void jarCopy() throws IOException { | |||
String srcJarPath = project.getBuild().getDirectory() + | |||
File.separator + finalName + "-" + JAR_DEPENDENCE + ".jar"; | |||
String dstJarPath = project.getBuild().getDirectory() + | |||
File.separator + finalName + ".jar"; | |||
FileUtils.copyFile(new File(srcJarPath), new File(dstJarPath)); | |||
} | |||
private File compileCustomJar() throws IOException { | |||
return copyAndManage(project, finalName); | |||
} | |||
private void verify(File jarFile) throws MojoFailureException { | |||
try { | |||
// 首先校验MainClass | |||
try { | |||
verifyMainClass(jarFile); | |||
} catch (Exception e) { | |||
jarFile.delete(); | |||
LOG.error(e.getMessage()); | |||
LOGGER.error(e.getMessage()); | |||
throw e; | |||
} | |||
@@ -101,9 +106,13 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
boolean isOK = true; | |||
for (String clazz : totalClassList) { | |||
LOGGER.debug(String.format("Verify Class[%s] start......", clazz)); | |||
// 获取其包名 | |||
String packageName = packageName(clazz); | |||
LOGGER.debug(String.format("Class[%s] 's package name = %s", clazz, packageName)); | |||
// 包的名字黑名单,不能打包该类进入Jar包中,或者合约不能命名这样的名字 | |||
boolean isNameBlack = false; | |||
for (ContractPackage blackName : blackNameList) { | |||
@@ -116,7 +125,7 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
// 假设是黑名单则打印日志 | |||
if (isNameBlack) { | |||
// 打印信息供检查 | |||
LOG.error(String.format("Class[%s]'s Package-Name belong to BlackNameList !!!", clazz)); | |||
LOGGER.error(String.format("Class[%s]'s Package-Name belong to BlackNameList !!!", clazz)); | |||
isOK = false; | |||
continue; | |||
} | |||
@@ -126,6 +135,7 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
boolean isNeedDelete = false; | |||
if (!javaFile.exists()) { | |||
LOGGER.debug(String.format("Class[%s] -> Java[%s] is not exist, start decompile ...", clazz, jarFile.getPath())); | |||
// 表明不是项目中的内容,需要通过反编译获取该文件 | |||
String source = null; | |||
try { | |||
@@ -134,15 +144,18 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
throw new IllegalStateException(); | |||
} | |||
} catch (Exception e) { | |||
LOG.warn(String.format("Decompile Jar[%s]->Class[%s] Fail !!!", jarFile.getPath(), clazz)); | |||
LOGGER.warn(String.format("Decompile Jar[%s]->Class[%s] Fail !!!", jarFile.getPath(), clazz)); | |||
} | |||
// 将source写入Java文件 | |||
File sourceTempJavaFile = new File(tempPath(codeBaseDir, clazz)); | |||
FileUtils.writeStringToFile(sourceTempJavaFile, source == null ? "" : source); | |||
javaFile = sourceTempJavaFile; | |||
isNeedDelete = true; | |||
} else { | |||
LOGGER.debug(String.format("Class[%s] -> Java[%s] is exist", clazz, jarFile.getPath())); | |||
} | |||
LOGGER.info(String.format("Parse Java File [%s] start......", javaFile.getPath())); | |||
// 解析文件中的内容 | |||
CompilationUnit compilationUnit = JavaParser.parse(javaFile); | |||
@@ -154,13 +167,14 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
if (!imports.isEmpty()) { | |||
for (String importClass : imports) { | |||
LOGGER.debug(String.format("Class[%s] read import -> [%s]", clazz, importClass)); | |||
if (importClass.endsWith("*")) { | |||
// 导入的是包 | |||
for (ContractPackage blackPackage : blackPackageList) { | |||
String importPackageName = importClass.substring(0, importClass.length() - 2); | |||
if (verifyPackage(importPackageName, blackPackage)) { | |||
// 打印信息供检查 | |||
LOG.error(String.format("Class[%s]'s import class [%s] belong to BlackPackageList !!!", clazz, importClass)); | |||
LOGGER.error(String.format("Class[%s]'s import class [%s] belong to BlackPackageList !!!", clazz, importClass)); | |||
isOK = false; | |||
break; | |||
} | |||
@@ -169,13 +183,13 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
// 导入的是具体的类,则判断类黑名单 + 包黑名单 | |||
if (blackClassSet.contains(importClass)) { | |||
// 包含导入类,该方式无法通过验证 | |||
LOG.error(String.format("Class[%s]'s import class [%s] belong to BlackClassList !!!", clazz, importClass)); | |||
LOGGER.error(String.format("Class[%s]'s import class [%s] belong to BlackClassList !!!", clazz, importClass)); | |||
isOK = false; | |||
} else { | |||
// 判断导入的该类与黑名单导入包的对应关系 | |||
for (ContractPackage blackPackage : blackPackageList) { | |||
if (verifyClass(importClass, blackPackage)) { | |||
LOG.error(String.format("Class[%s]'s import class [%s] belong to BlackPackageList !!!", clazz, importClass)); | |||
LOGGER.error(String.format("Class[%s]'s import class [%s] belong to BlackPackageList !!!", clazz, importClass)); | |||
isOK = false; | |||
break; | |||
} | |||
@@ -187,6 +201,7 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
if (isNeedDelete) { | |||
javaFile.delete(); | |||
} | |||
LOGGER.debug(String.format("Verify Class[%s] end......", clazz)); | |||
} | |||
if (!isOK) { | |||
// 需要将该Jar删除 | |||
@@ -198,19 +213,21 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
throw new IllegalStateException("There is none class !!!"); | |||
} | |||
} catch (Exception e) { | |||
LOG.error(e.getMessage()); | |||
throw new MojoExecutionException(e.getMessage()); | |||
LOGGER.error(e.getMessage()); | |||
throw new MojoFailureException(e.getMessage(), e); | |||
} | |||
} | |||
private void verifyMainClass(File jarFile) throws Exception { | |||
// 加载main-class,开始校验类型 | |||
LOGGER.debug(String.format("Verify Jar [%s] 's MainClass start...", jarFile.getName())); | |||
URL jarURL = jarFile.toURI().toURL(); | |||
ClassLoader classLoader = new URLClassLoader(new URL[]{jarURL}, this.getClass().getClassLoader()); | |||
Attributes m = new JarFile(jarFile).getManifest().getMainAttributes(); | |||
String contractMainClass = m.getValue(Attributes.Name.MAIN_CLASS); | |||
Class mainClass = classLoader.loadClass(contractMainClass); | |||
ContractType.resolve(mainClass); | |||
LOGGER.debug(String.format("Verify Jar [%s] 's MainClass end...", jarFile.getName())); | |||
} | |||
private List<ContractPackage> blackNameList(Properties config) { | |||
@@ -223,6 +240,7 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
if (attrProp != null && attrProp.length() > 0) { | |||
String[] attrPropArray = attrProp.split(","); | |||
for (String attr : attrPropArray) { | |||
LOGGER.info(String.format("Config [%s] -> [%s]", BLACK_CLASS_LIST, attr)); | |||
blackClassSet.add(attr.trim()); | |||
} | |||
} | |||
@@ -239,6 +257,7 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
if (attrProp != null || attrProp.length() > 0) { | |||
String[] attrPropArray = attrProp.split(","); | |||
for (String attr : attrPropArray) { | |||
LOGGER.info(String.format("Config [%s] -> [%s]", attrName, attr)); | |||
list.add(new ContractPackage(attr)); | |||
} | |||
} | |||
@@ -310,7 +329,7 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
return packageName.replaceAll("/", "."); | |||
} | |||
private File copyAndManage() throws IOException { | |||
private File copyAndManage(MavenProject project, String finalName) throws IOException { | |||
// 首先将Jar包转换为指定的格式 | |||
String srcJarPath = project.getBuild().getDirectory() + | |||
File.separator + finalName + ".jar"; | |||
@@ -320,8 +339,10 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
File srcJar = new File(srcJarPath), dstJar = new File(dstJarPath); | |||
LOGGER.debug(String.format("Jar from [%s] to [%s] Copying", srcJarPath, dstJarPath)); | |||
// 首先进行Copy处理 | |||
copy(srcJar, dstJar); | |||
LOGGER.debug(String.format("Jar from [%s] to [%s] Copied", srcJarPath, dstJarPath)); | |||
byte[] txtBytes = contractMF(FileUtils.readFileToByteArray(dstJar)).getBytes(StandardCharsets.UTF_8); | |||
@@ -376,24 +397,6 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
private List<String> importClasses = new ArrayList<>(); | |||
// @Override | |||
// public void visit(MethodDeclaration n, Void arg) { | |||
// /* here you can access the attributes of the method. | |||
// this method will be called for all methods in this | |||
// CompilationUnit, including inner class methods */ | |||
// super.visit(n, arg); | |||
// } | |||
// | |||
// @Override | |||
// public void visit(ClassOrInterfaceDeclaration n, Void arg) { | |||
// super.visit(n, arg); | |||
// } | |||
// | |||
// @Override | |||
// public void visit(PackageDeclaration n, Void arg) { | |||
// super.visit(n, arg); | |||
// } | |||
@Override | |||
public void visit(ImportDeclaration n, Void arg) { | |||
importClasses.add(parseClass(n.toString())); |
@@ -1,19 +0,0 @@ | |||
#PROJECT_BASE_DIR | |||
PROJECT_BASE_DIR=E:\\gitCode\\block\\prototype\\ | |||
#LEDGER_BASE_CLASS_PATH | |||
LEDGER_BASE_CLASS_PATH=E:\\gitCode\\block\\prototype\\libs\\ | |||
#deploy and execute the contract; | |||
cParam=com.jd.blockchain.contract.AssetContract3 | |||
sParam=E:\\gitCode\\block\\prototype\\source\\sdk\\contract-sample\\src\\main\\java\\ | |||
eParam=utf-8 | |||
oParam=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\src\\test\\resources\\ | |||
host=127.0.0.1 | |||
port=8081 | |||
event = issue-asset | |||
ownerPassword=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\conf\\ownerPassword.txt | |||
ownerPubPath=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\conf\\jd-com.pub | |||
ownerPrvPath=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\conf\\jd-com.priv | |||
chainCodePath=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\src\\test\\resources\\AssetContract3.contract | |||
ledgerHash=6FEQDTQMnBGANpfX4haXuWHKHw5cZ6P1h2ocqwckYBxp4 | |||
contractArgs=101##999##abc |
@@ -1,21 +1,21 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.contract.maven.ContractDeployMojo; | |||
import java.lang.reflect.Field; | |||
/** | |||
* for contract deploy and exe; | |||
* @Author zhaogw | |||
* @Date 2018/11/02 09:06 | |||
*/ | |||
public class ContractDeployMojoTest { | |||
private ContractDeployMojo contractDeployMojo = new ContractDeployMojo(); | |||
private void fieldHandle(String fieldName,Object objValue) throws NoSuchFieldException, IllegalAccessException { | |||
Field field = contractDeployMojo.getClass().getDeclaredField(fieldName);//name为类Instance中的private属性 | |||
field.setAccessible(true);//=true,可访问私有变量。 | |||
Class<?> typeClass = field.getType(); | |||
field.set(contractDeployMojo, objValue); | |||
} | |||
} | |||
//package com.jd.blockchain.ledger; | |||
// | |||
//import com.jd.blockchain.contract.maven.ContractDeployMojo; | |||
// | |||
//import java.lang.reflect.Field; | |||
// | |||
///** | |||
// * for contract deploy and exe; | |||
// * @Author zhaogw | |||
// * @Date 2018/11/02 09:06 | |||
// */ | |||
//public class ContractDeployMojoTest { | |||
// private ContractDeployMojo contractDeployMojo = new ContractDeployMojo(); | |||
// | |||
// private void fieldHandle(String fieldName,Object objValue) throws NoSuchFieldException, IllegalAccessException { | |||
// Field field = contractDeployMojo.getClass().getDeclaredField(fieldName);//name为类Instance中的private属性 | |||
// field.setAccessible(true);//=true,可访问私有变量。 | |||
// Class<?> typeClass = field.getType(); | |||
// field.set(contractDeployMojo, objValue); | |||
// } | |||
//} |
@@ -1,50 +1,50 @@ | |||
package com.jd.blockchain.ledger; | |||
import org.apache.maven.model.Build; | |||
import org.apache.maven.project.MavenProject; | |||
import org.junit.Test; | |||
import org.springframework.core.io.ClassPathResource; | |||
import java.io.File; | |||
public class ContractTestBase { | |||
public static MavenProject mavenProjectInit() { | |||
MavenProject mavenProject = new MavenProject(); | |||
mavenProject.setBuild(buildInit()); | |||
mavenProject.setFile(file()); | |||
return mavenProject; | |||
} | |||
public static File file() { | |||
String resDir = resourceDir(); | |||
File file = new File(resDir); | |||
String path = file.getParentFile().getParentFile().getPath(); | |||
return new File(path + File.separator + "src"); | |||
} | |||
public static Build buildInit() { | |||
Build build = new Build(); | |||
build.setDirectory(resourceDir()); | |||
return build; | |||
} | |||
public static String resourceDir() { | |||
try { | |||
ClassPathResource classPathResource = new ClassPathResource("complex.jar"); | |||
return classPathResource.getFile().getParentFile().getPath(); | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
@Test | |||
public void testResourceDir() { | |||
System.out.println(resourceDir()); | |||
} | |||
@Test | |||
public void testFile() { | |||
System.out.println(file().getPath()); | |||
} | |||
} | |||
//package com.jd.blockchain.ledger; | |||
// | |||
//import org.apache.maven.model.Build; | |||
//import org.apache.maven.project.MavenProject; | |||
//import org.junit.Test; | |||
//import org.springframework.core.io.ClassPathResource; | |||
// | |||
//import java.io.File; | |||
// | |||
//public class ContractTestBase { | |||
// | |||
// public static MavenProject mavenProjectInit() { | |||
// MavenProject mavenProject = new MavenProject(); | |||
// mavenProject.setBuild(buildInit()); | |||
// mavenProject.setFile(file()); | |||
// return mavenProject; | |||
// } | |||
// | |||
// public static File file() { | |||
// String resDir = resourceDir(); | |||
// File file = new File(resDir); | |||
// String path = file.getParentFile().getParentFile().getPath(); | |||
// return new File(path + File.separator + "src"); | |||
// } | |||
// | |||
// public static Build buildInit() { | |||
// Build build = new Build(); | |||
// build.setDirectory(resourceDir()); | |||
// return build; | |||
// } | |||
// | |||
// public static String resourceDir() { | |||
// try { | |||
// ClassPathResource classPathResource = new ClassPathResource("complex.jar"); | |||
// return classPathResource.getFile().getParentFile().getPath(); | |||
// } catch (Exception e) { | |||
// throw new IllegalStateException(e); | |||
// } | |||
// } | |||
// | |||
// @Test | |||
// public void testResourceDir() { | |||
// System.out.println(resourceDir()); | |||
// } | |||
// | |||
// @Test | |||
// public void testFile() { | |||
// System.out.println(file().getPath()); | |||
// } | |||
//} |
@@ -1,28 +1,28 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.contract.maven.ContractVerifyMojo; | |||
import org.apache.maven.plugin.testing.AbstractMojoTestCase; | |||
import org.junit.Test; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.File; | |||
/** | |||
* @Author zhaogw | |||
* @Date 2019/3/1 21:27 | |||
*/ | |||
public class ContractVerifyMojoTest extends AbstractMojoTestCase { | |||
Logger logger = LoggerFactory.getLogger(ContractVerifyMojoTest.class); | |||
@Test | |||
public void test1() throws Exception { | |||
File pom = getTestFile( "src/test/resources/project-to-test/pom.xml" ); | |||
assertNotNull( pom ); | |||
assertTrue( pom.exists() ); | |||
ContractVerifyMojo myMojo = (ContractVerifyMojo) lookupMojo( "contractVerify", pom ); | |||
assertNotNull( myMojo ); | |||
myMojo.execute(); | |||
} | |||
} | |||
//package com.jd.blockchain.ledger; | |||
// | |||
//import com.jd.blockchain.contract.maven.ContractVerifyMojo; | |||
//import org.apache.maven.plugin.testing.AbstractMojoTestCase; | |||
//import org.junit.Test; | |||
//import org.slf4j.Logger; | |||
//import org.slf4j.LoggerFactory; | |||
// | |||
//import java.io.File; | |||
// | |||
///** | |||
// * @Author zhaogw | |||
// * @Date 2019/3/1 21:27 | |||
// */ | |||
//public class ContractVerifyMojoTest extends AbstractMojoTestCase { | |||
// Logger logger = LoggerFactory.getLogger(ContractVerifyMojoTest.class); | |||
// | |||
// @Test | |||
// public void test1() throws Exception { | |||
// File pom = getTestFile( "src/test/resources/project-to-test/pom.xml" ); | |||
// assertNotNull( pom ); | |||
// assertTrue( pom.exists() ); | |||
// | |||
// ContractVerifyMojo myMojo = (ContractVerifyMojo) lookupMojo( "contractVerify", pom ); | |||
// assertNotNull( myMojo ); | |||
// myMojo.execute(); | |||
// } | |||
//} |
@@ -1,47 +1,47 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.contract.maven.ContractVerifyMojo; | |||
import org.apache.maven.project.MavenProject; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import java.lang.reflect.Field; | |||
import static com.jd.blockchain.ledger.ContractTestBase.mavenProjectInit; | |||
public class ContractVerifyTest_ { | |||
private MavenProject project; | |||
private String finalName; | |||
@Before | |||
public void testInit() { | |||
project = mavenProjectInit(); | |||
finalName = "complex"; | |||
} | |||
@Test | |||
public void test() throws Exception { | |||
ContractVerifyMojo contractVerifyMojo = contractVerifyMojoConf(); | |||
contractVerifyMojo.execute(); | |||
} | |||
private ContractVerifyMojo contractVerifyMojoConf() throws Exception { | |||
ContractVerifyMojo contractVerifyMojo = new ContractVerifyMojo(); | |||
// 为不影响其内部结构,通过反射进行私有变量赋值 | |||
Class<?> clazz = contractVerifyMojo.getClass(); | |||
Field projectField = clazz.getDeclaredField("project"); | |||
Field finalNameField = clazz.getDeclaredField("finalName"); | |||
// 更新权限 | |||
projectField.setAccessible(true); | |||
finalNameField.setAccessible(true); | |||
// 设置具体值 | |||
projectField.set(contractVerifyMojo, project); | |||
finalNameField.set(contractVerifyMojo, finalName); | |||
return contractVerifyMojo; | |||
} | |||
} | |||
//package com.jd.blockchain.ledger; | |||
// | |||
//import com.jd.blockchain.contract.maven.ContractVerifyMojo; | |||
//import org.apache.maven.project.MavenProject; | |||
//import org.junit.Before; | |||
//import org.junit.Test; | |||
// | |||
//import java.lang.reflect.Field; | |||
// | |||
//import static com.jd.blockchain.ledger.ContractTestBase.mavenProjectInit; | |||
// | |||
//public class ContractVerifyTest_ { | |||
// | |||
// private MavenProject project; | |||
// | |||
// private String finalName; | |||
// | |||
// @Before | |||
// public void testInit() { | |||
// project = mavenProjectInit(); | |||
// finalName = "complex"; | |||
// } | |||
// | |||
// @Test | |||
// public void test() throws Exception { | |||
// ContractVerifyMojo contractVerifyMojo = contractVerifyMojoConf(); | |||
// contractVerifyMojo.execute(); | |||
// } | |||
// | |||
// private ContractVerifyMojo contractVerifyMojoConf() throws Exception { | |||
// ContractVerifyMojo contractVerifyMojo = new ContractVerifyMojo(); | |||
// // 为不影响其内部结构,通过反射进行私有变量赋值 | |||
// Class<?> clazz = contractVerifyMojo.getClass(); | |||
// Field projectField = clazz.getDeclaredField("project"); | |||
// Field finalNameField = clazz.getDeclaredField("finalName"); | |||
// | |||
// // 更新权限 | |||
// projectField.setAccessible(true); | |||
// finalNameField.setAccessible(true); | |||
// | |||
// // 设置具体值 | |||
// projectField.set(contractVerifyMojo, project); | |||
// finalNameField.set(contractVerifyMojo, finalName); | |||
// | |||
// return contractVerifyMojo; | |||
// } | |||
//} |
@@ -1,67 +1,67 @@ | |||
package com.jd.blockchain.ledger; | |||
import org.apache.maven.model.Build; | |||
import org.apache.maven.model.Model; | |||
import org.apache.maven.model.io.xpp3.MavenXpp3Reader; | |||
import org.apache.maven.plugin.testing.stubs.MavenProjectStub; | |||
import org.codehaus.plexus.util.ReaderFactory; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* @author zhaogw | |||
* date 2019/6/4 18:33 | |||
*/ | |||
public class MyProjectStub extends MavenProjectStub | |||
{ | |||
/** | |||
* Default constructor | |||
*/ | |||
public MyProjectStub() | |||
{ | |||
MavenXpp3Reader pomReader = new MavenXpp3Reader(); | |||
Model model; | |||
try | |||
{ | |||
model = pomReader.read( ReaderFactory.newXmlReader( new File( getBasedir(), "pom.xml" ) ) ); | |||
setModel( model ); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
throw new RuntimeException( e ); | |||
} | |||
setGroupId( model.getGroupId() ); | |||
setArtifactId( model.getArtifactId() ); | |||
setVersion( model.getVersion() ); | |||
setName( model.getName() ); | |||
setUrl( model.getUrl() ); | |||
setPackaging( model.getPackaging() ); | |||
Build build = new Build(); | |||
build.setFinalName( model.getArtifactId() ); | |||
build.setDirectory( getBasedir() + "/target" ); | |||
build.setSourceDirectory( getBasedir() + "/src/main/java" ); | |||
build.setOutputDirectory( getBasedir() + "/target/classes" ); | |||
build.setTestSourceDirectory( getBasedir() + "/src/test/java" ); | |||
build.setTestOutputDirectory( getBasedir() + "/target/test-classes" ); | |||
setBuild( build ); | |||
List compileSourceRoots = new ArrayList(); | |||
compileSourceRoots.add( getBasedir() + "/src/main/java" ); | |||
setCompileSourceRoots( compileSourceRoots ); | |||
List testCompileSourceRoots = new ArrayList(); | |||
testCompileSourceRoots.add( getBasedir() + "/src/test/java" ); | |||
setTestCompileSourceRoots( testCompileSourceRoots ); | |||
} | |||
/** {@inheritDoc} */ | |||
public File getBasedir() | |||
{ | |||
return new File( super.getBasedir() + "/src/test/resources/project-to-test/" ); | |||
} | |||
} | |||
//package com.jd.blockchain.ledger; | |||
// | |||
//import org.apache.maven.model.Build; | |||
//import org.apache.maven.model.Model; | |||
//import org.apache.maven.model.io.xpp3.MavenXpp3Reader; | |||
//import org.apache.maven.plugin.testing.stubs.MavenProjectStub; | |||
//import org.codehaus.plexus.util.ReaderFactory; | |||
// | |||
//import java.io.File; | |||
//import java.util.ArrayList; | |||
//import java.util.List; | |||
// | |||
///** | |||
// * @author zhaogw | |||
// * date 2019/6/4 18:33 | |||
// */ | |||
// | |||
//public class MyProjectStub extends MavenProjectStub | |||
//{ | |||
// /** | |||
// * Default constructor | |||
// */ | |||
// public MyProjectStub() | |||
// { | |||
// MavenXpp3Reader pomReader = new MavenXpp3Reader(); | |||
// Model model; | |||
// try | |||
// { | |||
// model = pomReader.read( ReaderFactory.newXmlReader( new File( getBasedir(), "pom.xml" ) ) ); | |||
// setModel( model ); | |||
// } | |||
// catch ( Exception e ) | |||
// { | |||
// throw new RuntimeException( e ); | |||
// } | |||
// | |||
// setGroupId( model.getGroupId() ); | |||
// setArtifactId( model.getArtifactId() ); | |||
// setVersion( model.getVersion() ); | |||
// setName( model.getName() ); | |||
// setUrl( model.getUrl() ); | |||
// setPackaging( model.getPackaging() ); | |||
// | |||
// Build build = new Build(); | |||
// build.setFinalName( model.getArtifactId() ); | |||
// build.setDirectory( getBasedir() + "/target" ); | |||
// build.setSourceDirectory( getBasedir() + "/src/main/java" ); | |||
// build.setOutputDirectory( getBasedir() + "/target/classes" ); | |||
// build.setTestSourceDirectory( getBasedir() + "/src/test/java" ); | |||
// build.setTestOutputDirectory( getBasedir() + "/target/test-classes" ); | |||
// setBuild( build ); | |||
// | |||
// List compileSourceRoots = new ArrayList(); | |||
// compileSourceRoots.add( getBasedir() + "/src/main/java" ); | |||
// setCompileSourceRoots( compileSourceRoots ); | |||
// | |||
// List testCompileSourceRoots = new ArrayList(); | |||
// testCompileSourceRoots.add( getBasedir() + "/src/test/java" ); | |||
// setTestCompileSourceRoots( testCompileSourceRoots ); | |||
// } | |||
// | |||
// /** {@inheritDoc} */ | |||
// public File getBasedir() | |||
// { | |||
// return new File( super.getBasedir() + "/src/test/resources/project-to-test/" ); | |||
// } | |||
//} |