From 20c7feccb8adb18ee0cacd872ad78bf63d4c15e0 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Thu, 27 Jun 2019 13:54:43 +0800 Subject: [PATCH] add the ContractCheckMojo for contract-maven-plugin; --- source/contract/contract-maven-plugin/pom.xml | 55 +---- .../java/com/jd/blockchain/ContractCheckMojo.java | 221 +++++++++++++++++++++ .../src/test/resources/project-to-test/pom.xml | 2 +- .../resources/project-to-test/target/contract.jar | Bin 8016 -> 5330 bytes 4 files changed, 229 insertions(+), 49 deletions(-) create mode 100644 source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java diff --git a/source/contract/contract-maven-plugin/pom.xml b/source/contract/contract-maven-plugin/pom.xml index 75349275..7ba6a4f4 100644 --- a/source/contract/contract-maven-plugin/pom.xml +++ b/source/contract/contract-maven-plugin/pom.xml @@ -87,6 +87,13 @@ 3.6.0 provided + + + org.apache.maven.shared + maven-invoker + 3.0.1 + + @@ -110,31 +117,6 @@ false - - - - - - - - - - - - - - - - - - - - - - - - org.apache.maven.plugins maven-surefire-plugin @@ -142,29 +124,6 @@ true - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - - - - - - - - - - - - - - diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java new file mode 100644 index 00000000..a47e4eb6 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java @@ -0,0 +1,221 @@ +package com.jd.blockchain; + +import com.jd.blockchain.utils.ConsoleUtils; +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.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.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Mojo(name = "contractCheck") +public class ContractCheckMojo extends AbstractMojo { + Logger logger = LoggerFactory.getLogger(ContractCheckMojo.class); + + @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() { + this.compileFiles(); + + } + + private void compileFiles(){ + // 获取当前项目pom.xml文件所在路径 +// URL targetClasses = this.getClass().getClassLoader().getResource(""); +// File file = new File(targetClasses.getPath()); +// String pomXmlPath = file.getParentFile().getParent() + File.separator + "pom.xml"; + + FileInputStream fis = null; + try { +// fis = new FileInputStream(new File(pomXmlPath)); + 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("com.jd.blockchain:contract-maven-plugin"); + if(plugin == null){ + plugin = model.getBuild().getPluginsAsMap().get("org.apache.maven.plugins:contract-maven-plugin"); + } + + if(plugin == null) { + return; + } + + model.getBuild().removePlugin(plugin); +// model.getBuild().setPlugins(null); + +// ConsoleUtils.info("----- 不携带Plugin -----"); +// print(model); + + List plugins = new ArrayList<>(); + plugins.add(createAssembly()); + plugins.add(createCheckImports()); + + model.getBuild().setPlugins(plugins); + + ConsoleUtils.info("----- add Plugin -----"); + handle(model); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (XmlPullParserException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void invokeCompile(File file) { + InvocationRequest request = new DefaultInvocationRequest(); + + Invoker invoker = new DefaultInvoker(); + try { + request.setPomFile(file); + + request.setGoals( Collections.singletonList( "verify" ) ); +// request.setMavenOpts("-DmainClass="+mainClass); + invoker.setMavenHome(new File(mvnHome)); + invoker.execute(request); + } catch (MavenInvocationException e) { + e.printStackTrace(); + } + } + + private Plugin createCheckImports() { + Plugin plugin = new Plugin(); + plugin.setGroupId("com.jd.blockchain"); + 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); + + PluginExecution pluginExecution = new PluginExecution(); + pluginExecution.setId("make-assembly"); + pluginExecution.setPhase("verify"); + List goals = new ArrayList<>(); + goals.add("checkImports"); + pluginExecution.setGoals(goals); + List pluginExecutions = new ArrayList<>(); + pluginExecutions.add(pluginExecution); + plugin.setExecutions(pluginExecutions); + + 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); + + PluginExecution pluginExecution = new PluginExecution(); + pluginExecution.setId("make-assembly"); + pluginExecution.setPhase("package"); + List goals = new ArrayList<>(); + goals.add("single"); + pluginExecution.setGoals(goals); + List pluginExecutions = new ArrayList<>(); + pluginExecutions.add(pluginExecution); + plugin.setExecutions(pluginExecutions); + return plugin; + } + + private void handle(Model model) throws IOException { + MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + mavenXpp3Writer.write(outputStream, model); + + byte[] buffer = outputStream.toByteArray(); + + //输出文件 +// File fileOutput = new File("fileOut.xml"); +// File fileOutput = File.createTempFile("fileOut",".xml"); + File fileOutput = new File(project.getBasedir().getPath(),"fileOut.xml"); + fileOutput.createNewFile(); + + ConsoleUtils.info("fileOutput's path="+fileOutput.getPath()); + //创建文件输出流对象 + FileOutputStream fos = new FileOutputStream(fileOutput); + //将字节数组fileInput中的内容输出到文件fileOut.xml中; + ConsoleUtils.info(new String(buffer)); + fos.write(buffer); + invokeCompile(fileOutput); + fos.close(); + } +} diff --git a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/pom.xml b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/pom.xml index ea7962e8..80bf8e27 100644 --- a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/pom.xml +++ b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/pom.xml @@ -16,7 +16,7 @@ - contract1 + contract diff --git a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/target/contract.jar b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/target/contract.jar index 7c172d0edcb2a34e5aeecddac90a767afd4c204a..8e693437b273ffb193daabddc9ba9a683c034e26 100644 GIT binary patch delta 4713 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