| @@ -90,6 +90,7 @@ public interface DataCodes { | |||
| public static final int CONTRACT_BIG_INT = 0xA07; | |||
| //...0xA19 | |||
| public static final int CONTRACT_BIZ_CONTENT = 0xA20; | |||
| public static final int CONTRACT_ARGS = 0xA21; | |||
| public static final int HASH = 0xB00; | |||
| @@ -10,6 +10,10 @@ | |||
| <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> | |||
| @@ -35,32 +39,54 @@ | |||
| <version>${project.version}</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> | |||
| <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>2.0</version> | |||
| <version>3.3.9</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.apache.maven</groupId> | |||
| <artifactId>maven-project</artifactId> | |||
| <version>2.0.6</version> | |||
| <artifactId>maven-core</artifactId> | |||
| <version>3.3.9</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.github.javaparser</groupId> | |||
| <artifactId>javaparser-core</artifactId> | |||
| <version>${javaparser.version}</version> | |||
| <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> | |||
| </dependencies> | |||
| <build> | |||
| @@ -49,6 +49,7 @@ public class CheckImportsMojo extends AbstractMojo { | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } catch (IOException exception) { | |||
| logger.error(exception.getMessage()); | |||
| @@ -1,32 +1,28 @@ | |||
| package com.jd.blockchain.ledger; | |||
| import com.jd.blockchain.CheckImportsMojo; | |||
| import org.apache.maven.plugin.testing.AbstractMojoTestCase; | |||
| import org.junit.Test; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Arrays; | |||
| import java.util.Properties; | |||
| import java.io.File; | |||
| /** | |||
| * @Author zhaogw | |||
| * @Date 2019/3/1 21:27 | |||
| */ | |||
| public class CheckImportsMojoTest { | |||
| public class CheckImportsMojoTest extends AbstractMojoTestCase { | |||
| Logger logger = LoggerFactory.getLogger(CheckImportsMojo.class); | |||
| @Test | |||
| public void test1() { | |||
| try { | |||
| InputStream inputStream = CheckImportsMojo.class.getClassLoader().getResourceAsStream("config.properties"); | |||
| Properties properties = new Properties(); | |||
| properties.load(inputStream); | |||
| String result[] = properties.getProperty("blacklist").split(","); | |||
| logger.info(Arrays.toString(result).toString()); | |||
| } catch (IOException e) { | |||
| logger.error(e.getMessage()); | |||
| } | |||
| public void test1() throws Exception { | |||
| File pom = getTestFile( "src/test/resources/project-to-test/pom.xml" ); | |||
| assertNotNull( pom ); | |||
| assertTrue( pom.exists() ); | |||
| CheckImportsMojo myMojo = (CheckImportsMojo) lookupMojo( "checkImports", pom ); | |||
| assertNotNull( myMojo ); | |||
| myMojo.execute(); | |||
| } | |||
| } | |||
| @@ -0,0 +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/" ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,40 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.jd.blockchain.ledger.ContractBizContent; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| /** | |||
| * 示例:一个“资产管理”智能合约; | |||
| * | |||
| * @author zhaogw | |||
| */ | |||
| @Contract | |||
| public interface AssetContract2 { | |||
| /** | |||
| * 发行资产; | |||
| * 新发行的资产数量; | |||
| * @param assetHolderAddress | |||
| * 新发行的资产的持有账户; | |||
| */ | |||
| @ContractEvent(name = "issue-asset-0") | |||
| void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
| /** | |||
| * 发行资产; | |||
| * 新发行的资产数量; | |||
| * @param assetHolderAddress | |||
| * 新发行的资产的持有账户; | |||
| */ | |||
| @ContractEvent(name = "issue-asset") | |||
| void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
| @ContractEvent(name = "issue-asset-2") | |||
| void issue(Bytes bytes, String assetHolderAddress, long cashNumber); | |||
| @ContractEvent(name = "issue-asset-3") | |||
| void issue(Byte byteObj, String assetHolderAddress, long cashNumber); | |||
| @ContractEvent(name = "issue-asset-4") | |||
| void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.jd.blockchain.ledger.ContractBizContent; | |||
| import com.jd.blockchain.ledger.KVDataEntry; | |||
| import com.jd.blockchain.ledger.KVDataObject; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import java.util.Arrays; | |||
| /** | |||
| * 示例:一个“资产管理”智能合约的实现; | |||
| * | |||
| * 注: 1、实现 EventProcessingAwire 接口以便合约实例在运行时可以从上下文获得合约生命周期事件的通知; 2、实现 | |||
| * AssetContract 接口定义的合约方法; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| @Contract | |||
| public class AssetContractImpl2 implements EventProcessingAwire, AssetContract2 { | |||
| public static String KEY_TOTAL = "total"; | |||
| // 合约事件上下文; | |||
| private ContractEventContext eventContext; | |||
| @Override | |||
| @ContractEvent(name = "issue-asset-0") | |||
| public void issue(ContractBizContent contractBizContent, String assetHolderAddress) { | |||
| System.out.println("input addr="+ Arrays.toString(contractBizContent.getAttrs())); | |||
| } | |||
| @Override | |||
| @ContractEvent(name = "issue-asset") | |||
| public void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber) { | |||
| System.out.println("eventContext="+eventContext.getCurrentLedgerHash().toBase58()); | |||
| System.out.println("getAttrs: "+Arrays.toString(contractBizContent.getAttrs())+",address="+assetHolderAddress+",cashNumber="+cashNumber); | |||
| eventContext.getLedger().dataAccount(assetHolderAddress).set(contractBizContent.getAttrs()[0], "value1",-1); | |||
| eventContext.getLedger().dataAccount(assetHolderAddress).set(contractBizContent.getAttrs()[1], 888,-1); | |||
| } | |||
| @Override | |||
| @ContractEvent(name = "issue-asset-2") | |||
| public void issue(Bytes bytes, String assetHolderAddress, long cashNumber){ | |||
| System.out.println(String.format("bytes=%s,assetHolderAddress=%s,cashNumber=%d",new String(bytes.toBytes()),assetHolderAddress,cashNumber)); | |||
| } | |||
| @ContractEvent(name = "issue-asset-3") | |||
| @Override | |||
| public void issue(Byte byteObj, String assetHolderAddress, long cashNumber) { | |||
| System.out.println(String.format("issue(),bytes=%d,assetHolderAddress=%s,cashNumber=%d",byteObj.intValue(),assetHolderAddress,cashNumber)); | |||
| } | |||
| @ContractEvent(name = "issue-asset-4") | |||
| @Override | |||
| public void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber) { | |||
| System.out.println(String.format("issue(),bytes=%d,assetHolderAddress=%s,cashNumber=%s",byteObj.intValue(),assetHolderAddress,cashNumber.toString())); | |||
| System.out.println("current LedgerHash="+eventContext.getCurrentLedgerHash().toBase58()); | |||
| // 查询当前值; | |||
| KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), assetHolderAddress, KEY_TOTAL); | |||
| // 计算资产的发行总数; | |||
| KVDataObject curTotal = (KVDataObject) kvEntries[0]; | |||
| System.out.println("currTotal version="+curTotal.getVersion()+",value="+curTotal.getValue().toString()); | |||
| eventContext.getLedger().dataAccount(assetHolderAddress).set(KEY_TOTAL, 100,curTotal.getVersion()); | |||
| } | |||
| /* | |||
| * (non-Javadoc) | |||
| * | |||
| * @see | |||
| * com.jd.blockchain.contract.model.EventProcessingAwire#beforeEvent(com.jd. | |||
| * blockchain.contract.model.ContractEventContext) | |||
| */ | |||
| @Override | |||
| public void beforeEvent(ContractEventContext eventContext) { | |||
| this.eventContext = eventContext; | |||
| } | |||
| /* | |||
| * (non-Javadoc) | |||
| * | |||
| * @see com.jd.blockchain.contract.model.EventProcessingAwire#postEvent(com.jd. | |||
| * blockchain.contract.model.ContractEventContext, | |||
| * com.jd.blockchain.contract.model.ContractError) | |||
| */ | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, ContractException error) { | |||
| this.eventContext = null; | |||
| } | |||
| @Override | |||
| public void postEvent(ContractException error) { | |||
| } | |||
| @Override | |||
| public void postEvent() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| package com.jd.blockchain.ledger; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.consts.DataCodes; | |||
| import java.lang.reflect.Method; | |||
| /** | |||
| * contract's args; | |||
| */ | |||
| @DataContract(code = DataCodes.CONTRACT_ARGS) | |||
| public interface ContractArgs { | |||
| Method getMethod(); | |||
| Object[] getArgs(); | |||
| } | |||
| @@ -18,10 +18,12 @@ import org.junit.Test; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import org.springframework.util.ReflectionUtils; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| import java.lang.reflect.Method; | |||
| import static org.junit.Assert.*; | |||
| @@ -351,4 +353,24 @@ public class SDK_Contract_Test { | |||
| ContractBizContent actualObj = BinaryProtocol.decodeAs(bizBytes,ContractBizContent.class); | |||
| assertArrayEquals(contractBizContent.getAttrs(),actualObj.getAttrs()); | |||
| } | |||
| @Test | |||
| public void testContractArgs(){ | |||
| ContractBizContent contractBizContent = () -> new String[]{"param1"}; | |||
| Method method = ReflectionUtils.findMethod(AssetContract2.class,"issue",ContractBizContent.class,String.class); | |||
| ContractArgs contractArgs = new ContractArgs() { | |||
| @Override | |||
| public Method getMethod() { | |||
| return method; | |||
| } | |||
| @Override | |||
| public Object[] getArgs() { | |||
| return new Object[]{contractBizContent,"hello"}; | |||
| } | |||
| }; | |||
| //add the annotation; | |||
| } | |||
| } | |||