| @@ -123,11 +123,11 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| return; | |||
| } | |||
| protected void initConfig(int id, String systemConfig, String hostsConfig) { | |||
| this.tomConfig = new TOMConfiguration(id, systemConfig, hostsConfig); | |||
| } | |||
| // protected void initConfig(int id, String systemConfig, String hostsConfig) { | |||
| // | |||
| // this.tomConfig = new TOMConfiguration(id, systemConfig, hostsConfig); | |||
| // | |||
| // } | |||
| protected void initConfig(int id, Properties systemsConfig, HostsConfig hostConfig) { | |||
| this.tomConfig = new TOMConfiguration(id, systemsConfig, hostConfig); | |||
| @@ -309,6 +309,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| try { | |||
| LOGGER.debug("Start replica...[ID=" + getId() + "]"); | |||
| // 调整绑定Host | |||
| this.replica = new ServiceReplica(tomConfig, this, this); | |||
| this.topology = new BftsmartTopology(replica.getReplicaContext().getCurrentView()); | |||
| status = Status.RUNNING; | |||
| @@ -1,128 +1,128 @@ | |||
| package com.jd.blockchain; | |||
| import com.github.javaparser.JavaParser; | |||
| import com.github.javaparser.ast.CompilationUnit; | |||
| import com.github.javaparser.ast.ImportDeclaration; | |||
| import com.github.javaparser.ast.NodeList; | |||
| import com.github.javaparser.ast.PackageDeclaration; | |||
| import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; | |||
| import com.github.javaparser.ast.body.MethodDeclaration; | |||
| import com.github.javaparser.ast.visitor.VoidVisitorAdapter; | |||
| import com.jd.blockchain.contract.ContractType; | |||
| import com.jd.blockchain.utils.IllegalDataException; | |||
| 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.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.net.URL; | |||
| import java.net.URLClassLoader; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.Path; | |||
| import java.util.List; | |||
| import java.util.Properties; | |||
| import java.util.jar.Attributes; | |||
| import java.util.jar.JarFile; | |||
| import java.util.stream.Collectors; | |||
| /** | |||
| * 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 = "checkImports") | |||
| public class CheckImportsMojo extends AbstractMojo { | |||
| Logger logger = LoggerFactory.getLogger(CheckImportsMojo.class); | |||
| @Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
| private MavenProject project; | |||
| /** | |||
| * jar's name; | |||
| */ | |||
| @Parameter | |||
| private String finalName; | |||
| @Override | |||
| public void execute() throws MojoFailureException { | |||
| List<Path> sources; | |||
| try { | |||
| InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties"); | |||
| Properties properties = new Properties(); | |||
| properties.load(inputStream); | |||
| String[] packageBlackList = properties.getProperty("blacklist").split(","); | |||
| Path baseDirPath = project.getBasedir().toPath(); | |||
| sources = Files.find(baseDirPath, Integer.MAX_VALUE, (file, attrs) -> (file.toString().endsWith(".java"))).collect(Collectors.toList()); | |||
| for (Path path : sources) { | |||
| CompilationUnit compilationUnit = JavaParser.parse(path); | |||
| compilationUnit.accept(new MethodVisitor(), null); | |||
| NodeList<ImportDeclaration> imports = compilationUnit.getImports(); | |||
| for (ImportDeclaration imp : imports) { | |||
| String importName = imp.getName().asString(); | |||
| for (String item : packageBlackList) { | |||
| if (importName.startsWith(item)) { | |||
| throw new MojoFailureException("在源码中不允许包含此引入包:" + importName); | |||
| } | |||
| } | |||
| } | |||
| //now we parse the jar; | |||
| String jarPath = project.getBuild().getDirectory()+ File.separator+finalName+".jar"; | |||
| File jarFile = new File(jarPath); | |||
| 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); | |||
| try { | |||
| Class mainClass = classLoader.loadClass(contractMainClass); | |||
| ContractType.resolve(mainClass); | |||
| } catch (ClassNotFoundException e) { | |||
| throw new IllegalDataException(e.getMessage()); | |||
| } | |||
| } | |||
| } catch (IOException exception) { | |||
| logger.error(exception.getMessage()); | |||
| throw new MojoFailureException("IO ERROR"); | |||
| } catch (NullPointerException e) { | |||
| logger.error(e.getMessage()); | |||
| } | |||
| } | |||
| private class MethodVisitor extends VoidVisitorAdapter<Void> { | |||
| @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 */ | |||
| logger.info("method:"+n.getName()); | |||
| super.visit(n, arg); | |||
| } | |||
| @Override | |||
| public void visit(ClassOrInterfaceDeclaration n, Void arg) { | |||
| logger.info("class:"+n.getName()+" extends:"+n.getExtendedTypes()+" implements:"+n.getImplementedTypes()); | |||
| super.visit(n, arg); | |||
| } | |||
| @Override | |||
| public void visit(PackageDeclaration n, Void arg) { | |||
| logger.info("package:"+n.getName()); | |||
| super.visit(n, arg); | |||
| } | |||
| } | |||
| } | |||
| //package com.jd.blockchain; | |||
| // | |||
| //import com.github.javaparser.JavaParser; | |||
| //import com.github.javaparser.ast.CompilationUnit; | |||
| //import com.github.javaparser.ast.ImportDeclaration; | |||
| //import com.github.javaparser.ast.NodeList; | |||
| //import com.github.javaparser.ast.PackageDeclaration; | |||
| //import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; | |||
| //import com.github.javaparser.ast.body.MethodDeclaration; | |||
| //import com.github.javaparser.ast.visitor.VoidVisitorAdapter; | |||
| //import com.jd.blockchain.contract.ContractType; | |||
| //import com.jd.blockchain.utils.IllegalDataException; | |||
| //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.slf4j.Logger; | |||
| //import org.slf4j.LoggerFactory; | |||
| // | |||
| //import java.io.File; | |||
| //import java.io.IOException; | |||
| //import java.io.InputStream; | |||
| //import java.net.URL; | |||
| //import java.net.URLClassLoader; | |||
| //import java.nio.file.Files; | |||
| //import java.nio.file.Path; | |||
| //import java.util.List; | |||
| //import java.util.Properties; | |||
| //import java.util.jar.Attributes; | |||
| //import java.util.jar.JarFile; | |||
| //import java.util.stream.Collectors; | |||
| // | |||
| ///** | |||
| // * 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 = "checkImports") | |||
| //public class CheckImportsMojo extends AbstractMojo { | |||
| // | |||
| // Logger logger = LoggerFactory.getLogger(CheckImportsMojo.class); | |||
| // | |||
| // @Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
| // private MavenProject project; | |||
| // | |||
| // /** | |||
| // * jar's name; | |||
| // */ | |||
| // @Parameter | |||
| // private String finalName; | |||
| // | |||
| // @Override | |||
| // public void execute() throws MojoFailureException { | |||
| // List<Path> sources; | |||
| // try { | |||
| // InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties"); | |||
| // Properties properties = new Properties(); | |||
| // properties.load(inputStream); | |||
| // String[] packageBlackList = properties.getProperty("blacklist").split(","); | |||
| // Path baseDirPath = project.getBasedir().toPath(); | |||
| // sources = Files.find(baseDirPath, Integer.MAX_VALUE, (file, attrs) -> (file.toString().endsWith(".java"))).collect(Collectors.toList()); | |||
| // for (Path path : sources) { | |||
| // CompilationUnit compilationUnit = JavaParser.parse(path); | |||
| // | |||
| // compilationUnit.accept(new MethodVisitor(), null); | |||
| // | |||
| // NodeList<ImportDeclaration> imports = compilationUnit.getImports(); | |||
| // for (ImportDeclaration imp : imports) { | |||
| // String importName = imp.getName().asString(); | |||
| // for (String item : packageBlackList) { | |||
| // if (importName.startsWith(item)) { | |||
| // throw new MojoFailureException("在源码中不允许包含此引入包:" + importName); | |||
| // } | |||
| // } | |||
| // } | |||
| // | |||
| // //now we parse the jar; | |||
| // String jarPath = project.getBuild().getDirectory()+ File.separator+finalName+".jar"; | |||
| // File jarFile = new File(jarPath); | |||
| // 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); | |||
| // try { | |||
| // Class mainClass = classLoader.loadClass(contractMainClass); | |||
| // ContractType.resolve(mainClass); | |||
| // } catch (ClassNotFoundException e) { | |||
| // throw new IllegalDataException(e.getMessage()); | |||
| // } | |||
| // } | |||
| // } catch (IOException exception) { | |||
| // logger.error(exception.getMessage()); | |||
| // throw new MojoFailureException("IO ERROR"); | |||
| // } catch (NullPointerException e) { | |||
| // logger.error(e.getMessage()); | |||
| // } | |||
| // } | |||
| // | |||
| // private class MethodVisitor extends VoidVisitorAdapter<Void> { | |||
| // @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 */ | |||
| // logger.info("method:"+n.getName()); | |||
| // super.visit(n, arg); | |||
| // } | |||
| // | |||
| // @Override | |||
| // public void visit(ClassOrInterfaceDeclaration n, Void arg) { | |||
| // logger.info("class:"+n.getName()+" extends:"+n.getExtendedTypes()+" implements:"+n.getImplementedTypes()); | |||
| // | |||
| // super.visit(n, arg); | |||
| // } | |||
| // | |||
| // @Override | |||
| // public void visit(PackageDeclaration n, Void arg) { | |||
| // logger.info("package:"+n.getName()); | |||
| // super.visit(n, arg); | |||
| // } | |||
| // | |||
| // } | |||
| //} | |||
| @@ -1,6 +1,7 @@ | |||
| package com.jd.blockchain; | |||
| import com.jd.blockchain.utils.ConsoleUtils; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import org.apache.commons.io.FileUtils; | |||
| import org.apache.maven.model.Model; | |||
| import org.apache.maven.model.Plugin; | |||
| import org.apache.maven.model.PluginExecution; | |||
| @@ -12,7 +13,6 @@ 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; | |||
| @@ -22,9 +22,25 @@ import java.util.Collections; | |||
| import java.util.List; | |||
| @Mojo(name = "contractCheck") | |||
| @Mojo(name = "Contract.Check") | |||
| public class ContractCheckMojo extends AbstractMojo { | |||
| Logger logger = LoggerFactory.getLogger(ContractCheckMojo.class); | |||
| Logger LOG = LoggerFactory.getLogger(ContractCheckMojo.class); | |||
| public static final String CONTRACT_VERIFY = "Contract.Verify"; | |||
| 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 = "verify"; | |||
| private static final String GOALS_PACKAGE = "package"; | |||
| private static final String OUT_POM_XML = "OutPom.xml"; | |||
| @Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
| private MavenProject project; | |||
| @@ -58,27 +74,21 @@ public class ContractCheckMojo extends AbstractMojo { | |||
| */ | |||
| @Override | |||
| public void execute() { | |||
| this.compileFiles(); | |||
| 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"; | |||
| try (FileInputStream fis = new FileInputStream(project.getFile())) { | |||
| 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"); | |||
| Plugin plugin = model.getBuild().getPluginsAsMap() | |||
| .get(JDCHAIN_PACKAGE + ":" + CONTRACT_MAVEN_PLUGIN); | |||
| if(plugin == null){ | |||
| plugin = model.getBuild().getPluginsAsMap().get("org.apache.maven.plugins:contract-maven-plugin"); | |||
| plugin = model.getBuild().getPluginsAsMap() | |||
| .get(APACHE_MAVEN_PLUGINS + ":" + CONTRACT_MAVEN_PLUGIN); | |||
| } | |||
| if(plugin == null) { | |||
| @@ -86,26 +96,18 @@ public class ContractCheckMojo extends AbstractMojo { | |||
| } | |||
| model.getBuild().removePlugin(plugin); | |||
| // model.getBuild().setPlugins(null); | |||
| // ConsoleUtils.info("----- 不携带Plugin -----"); | |||
| // print(model); | |||
| List<Plugin> plugins = new ArrayList<>(); | |||
| plugins.add(createAssembly()); | |||
| plugins.add(createCheckImports()); | |||
| plugins.add(createContractVerify()); | |||
| 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(); | |||
| } catch (Exception e) { | |||
| LOG.error(e.getMessage()); | |||
| throw new IllegalStateException(e); | |||
| } | |||
| } | |||
| @@ -116,43 +118,35 @@ public class ContractCheckMojo extends AbstractMojo { | |||
| try { | |||
| request.setPomFile(file); | |||
| request.setGoals( Collections.singletonList( "verify" ) ); | |||
| // request.setMavenOpts("-DmainClass="+mainClass); | |||
| request.setGoals(Collections.singletonList(GOALS_VERIFY)); | |||
| invoker.setMavenHome(new File(mvnHome)); | |||
| invoker.execute(request); | |||
| } catch (MavenInvocationException e) { | |||
| e.printStackTrace(); | |||
| LOG.error(e.getMessage()); | |||
| throw new IllegalStateException(e); | |||
| } | |||
| } | |||
| private Plugin createCheckImports() { | |||
| private Plugin createContractVerify() { | |||
| Plugin plugin = new Plugin(); | |||
| plugin.setGroupId("com.jd.blockchain"); | |||
| plugin.setArtifactId("contract-maven-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); | |||
| PluginExecution pluginExecution = new PluginExecution(); | |||
| pluginExecution.setId("make-assembly"); | |||
| pluginExecution.setPhase("verify"); | |||
| List <String> goals = new ArrayList<>(); | |||
| goals.add("JDChain.Verify"); | |||
| pluginExecution.setGoals(goals); | |||
| List<PluginExecution> pluginExecutions = new ArrayList<>(); | |||
| pluginExecutions.add(pluginExecution); | |||
| plugin.setExecutions(pluginExecutions); | |||
| 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"); | |||
| plugin.setArtifactId(MAVEN_ASSEMBLY_PLUGIN); | |||
| Xpp3Dom configuration = new Xpp3Dom("configuration"); | |||
| @@ -180,21 +174,28 @@ public class ContractCheckMojo extends AbstractMojo { | |||
| 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("make-assembly"); | |||
| pluginExecution.setPhase("package"); | |||
| pluginExecution.setId(id); | |||
| pluginExecution.setPhase(phase); | |||
| List <String> goals = new ArrayList<>(); | |||
| goals.add("single"); | |||
| goals.add(goal); | |||
| pluginExecution.setGoals(goals); | |||
| List<PluginExecution> pluginExecutions = new ArrayList<>(); | |||
| pluginExecutions.add(pluginExecution); | |||
| plugin.setExecutions(pluginExecutions); | |||
| return plugin; | |||
| return pluginExecutions; | |||
| } | |||
| private void handle(Model model) throws IOException { | |||
| MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer(); | |||
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | |||
| @@ -203,20 +204,10 @@ public class ContractCheckMojo extends AbstractMojo { | |||
| 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); | |||
| fos.flush(); | |||
| fos.close(); | |||
| invokeCompile(fileOutput); | |||
| File outPom = new File(project.getBasedir().getPath(), OUT_POM_XML); | |||
| FileUtils.writeByteArrayToFile(outPom, buffer); | |||
| invokeCompile(outPom); | |||
| } | |||
| } | |||
| @@ -20,6 +20,7 @@ import org.apache.maven.plugins.annotations.Parameter; | |||
| import org.apache.maven.project.MavenProject; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.util.ResourceUtils; | |||
| import java.io.*; | |||
| import java.net.URL; | |||
| @@ -27,15 +28,15 @@ import java.net.URLClassLoader; | |||
| import java.nio.charset.StandardCharsets; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.Path; | |||
| import java.util.Enumeration; | |||
| import java.util.List; | |||
| import java.util.Properties; | |||
| import java.util.*; | |||
| import java.util.jar.Attributes; | |||
| import java.util.jar.JarEntry; | |||
| import java.util.jar.JarFile; | |||
| import java.util.jar.JarOutputStream; | |||
| import java.util.stream.Collectors; | |||
| import static com.jd.blockchain.ContractCheckMojo.CONTRACT_VERIFY; | |||
| import static com.jd.blockchain.utils.decompiler.utils.DecompilerUtils.decompileJarFile; | |||
| import static com.jd.blockchain.utils.jar.ContractJarUtils.*; | |||
| /** | |||
| @@ -47,10 +48,10 @@ import static com.jd.blockchain.utils.jar.ContractJarUtils.*; | |||
| * by zhaogw | |||
| * date 2019-06-05 16:17 | |||
| */ | |||
| @Mojo(name = "JDChain.Verify") | |||
| @Mojo(name = CONTRACT_VERIFY) | |||
| public class ContractVerifyMojo extends AbstractMojo { | |||
| Logger logger = LoggerFactory.getLogger(ContractVerifyMojo.class); | |||
| Logger LOG = LoggerFactory.getLogger(ContractVerifyMojo.class); | |||
| @Parameter(defaultValue = "${project}", required = true, readonly = true) | |||
| private MavenProject project; | |||
| @@ -61,53 +62,249 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
| @Parameter | |||
| private String finalName; | |||
| private static final String JAVA_SUFFIX = ".java"; | |||
| private static final String PATH_DIRECT = | |||
| "src" + File.separator + | |||
| "main" + File.separator + | |||
| "java" + File.separator; | |||
| private static final String CONFIG = "config.properties"; | |||
| private static final String BLACK_PACKAGE_LIST = "black.package.list"; | |||
| private static final String BLACK_CLASS_LIST = "black.class.list"; | |||
| private static final String BLACK_NAME_LIST = "black.name.list"; | |||
| @Override | |||
| public void execute() throws MojoFailureException { | |||
| List<Path> sources; | |||
| try { | |||
| File jarFile = copyAndManage(); | |||
| InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties"); | |||
| Properties properties = new Properties(); | |||
| properties.load(inputStream); | |||
| String[] packageBlackList = properties.getProperty("blacklist").split(","); | |||
| Path baseDirPath = project.getBasedir().toPath(); | |||
| sources = Files.find(baseDirPath, Integer.MAX_VALUE, (file, attrs) -> (file.toString().endsWith(".java"))).collect(Collectors.toList()); | |||
| for (Path path : sources) { | |||
| CompilationUnit compilationUnit = JavaParser.parse(path); | |||
| compilationUnit.accept(new MethodVisitor(), null); | |||
| NodeList<ImportDeclaration> imports = compilationUnit.getImports(); | |||
| for (ImportDeclaration imp : imports) { | |||
| String importName = imp.getName().asString(); | |||
| for (String item : packageBlackList) { | |||
| if (importName.startsWith(item)) { | |||
| throw new MojoFailureException("在源码中不允许包含此引入包:" + importName); | |||
| Properties config = loadConfig(); | |||
| List<ContractPackage> blackNameList = blackNameList(config); | |||
| List<ContractPackage> blackPackageList = blackPackageList(config); | |||
| Set<String> blackClassSet = blackClassSet(config); | |||
| LinkedList<String> totalClassList = loadAllClass(jarFile); | |||
| // 该项目路径 | |||
| String projectDir = project.getBasedir().getPath(); | |||
| // 代码路径 | |||
| String codeBaseDir = projectDir + File.separator + PATH_DIRECT; | |||
| if (!totalClassList.isEmpty()) { | |||
| boolean isOK = true; | |||
| for (String clazz : totalClassList) { | |||
| // 获取其包名 | |||
| String packageName = packageName(clazz); | |||
| // 包的名字黑名单,不能打包该类进入Jar包中,或者合约不能命名这样的名字 | |||
| boolean isNameBlack = false; | |||
| for (ContractPackage blackName : blackNameList) { | |||
| isNameBlack = verifyPackage(packageName, blackName); | |||
| if (isNameBlack) { | |||
| break; | |||
| } | |||
| } | |||
| // 假设是黑名单则打印日志 | |||
| if (isNameBlack) { | |||
| // 打印信息供检查 | |||
| LOG.error(String.format("Class[%s]'s Package-Name belong to BlackNameList !!!", clazz)); | |||
| isOK = false; | |||
| continue; | |||
| } | |||
| // 获取该Class对应的Java文件 | |||
| File javaFile = new File(codeBaseDir + clazz + JAVA_SUFFIX); | |||
| boolean isNeedDelete = false; | |||
| if (!javaFile.exists()) { | |||
| // 表明不是项目中的内容,需要通过反编译获取该文件 | |||
| String source = null; | |||
| try { | |||
| source = decompileJarFile(jarFile.getPath(), clazz, true, StandardCharsets.UTF_8.name()); | |||
| if (source == null || source.length() == 0) { | |||
| throw new IllegalStateException(); | |||
| } | |||
| } catch (Exception e) { | |||
| LOG.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; | |||
| } | |||
| // 解析文件中的内容 | |||
| CompilationUnit compilationUnit = JavaParser.parse(javaFile); | |||
| MethodVisitor methodVisitor = new MethodVisitor(); | |||
| compilationUnit.accept(methodVisitor, null); | |||
| List<String> imports = methodVisitor.importClasses; | |||
| if (!imports.isEmpty()) { | |||
| for (String importClass : imports) { | |||
| 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)); | |||
| isOK = false; | |||
| break; | |||
| } | |||
| } | |||
| } else { | |||
| // 导入的是具体的类,则判断类黑名单 + 包黑名单 | |||
| if (blackClassSet.contains(importClass)) { | |||
| // 包含导入类,该方式无法通过验证 | |||
| LOG.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)); | |||
| isOK = false; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| if (isNeedDelete) { | |||
| javaFile.delete(); | |||
| } | |||
| } | |||
| if (!isOK) { | |||
| throw new IllegalStateException("There are many Illegal information, please check !!!"); | |||
| } | |||
| //now we parse the jar; | |||
| // 加载main-class,开始校验类型 | |||
| URL jarURL = jarFile.toURI().toURL(); | |||
| ClassLoader classLoader = new URLClassLoader(new URL[]{jarURL},this.getClass().getClassLoader()); | |||
| 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); | |||
| try { | |||
| Class mainClass = classLoader.loadClass(contractMainClass); | |||
| ContractType.resolve(mainClass); | |||
| } catch (ClassNotFoundException e) { | |||
| throw new IllegalDataException(e.getMessage()); | |||
| } | |||
| Class mainClass = classLoader.loadClass(contractMainClass); | |||
| ContractType.resolve(mainClass); | |||
| } else { | |||
| throw new IllegalStateException("There is none class !!!"); | |||
| } | |||
| } catch (Exception e) { | |||
| LOG.error(e.getMessage()); | |||
| throw new MojoFailureException(e.getMessage()); | |||
| } | |||
| } | |||
| private List<ContractPackage> blackNameList(Properties config) { | |||
| return blackList(config, BLACK_NAME_LIST); | |||
| } | |||
| private Set<String> blackClassSet(Properties config) { | |||
| Set<String> blackClassSet = new HashSet<>(); | |||
| String attrProp = config.getProperty(BLACK_CLASS_LIST); | |||
| if (attrProp != null && attrProp.length() > 0) { | |||
| String[] attrPropArray = attrProp.split(","); | |||
| for (String attr : attrPropArray) { | |||
| blackClassSet.add(attr.trim()); | |||
| } | |||
| } | |||
| return blackClassSet; | |||
| } | |||
| private List<ContractPackage> blackPackageList(Properties config) { | |||
| return blackList(config, BLACK_PACKAGE_LIST); | |||
| } | |||
| private List<ContractPackage> blackList(Properties config, String attrName) { | |||
| List<ContractPackage> list = new ArrayList<>(); | |||
| String attrProp = config.getProperty(attrName); | |||
| if (attrProp != null || attrProp.length() > 0) { | |||
| String[] attrPropArray = attrProp.split(","); | |||
| for (String attr : attrPropArray) { | |||
| list.add(new ContractPackage(attr)); | |||
| } | |||
| } | |||
| return list; | |||
| } | |||
| private boolean verifyPackage(String packageName, ContractPackage contractPackage) { | |||
| boolean verify = false; | |||
| if (packageName.equals(contractPackage.packageName)) { | |||
| // 完全相同 | |||
| verify = true; | |||
| } else if (packageName.startsWith(contractPackage.packageName) && | |||
| contractPackage.isTotal) { | |||
| // 以某个包开头 | |||
| verify = true; | |||
| } | |||
| return verify; | |||
| } | |||
| private boolean verifyClass(String className, ContractPackage contractPackage) { | |||
| boolean verify = false; | |||
| if (contractPackage.isTotal) { | |||
| // 表示该包下面的其他所有包都会受限制,此处需要判断起始 | |||
| if (className.startsWith(contractPackage.packageName)) { | |||
| verify = true; | |||
| } | |||
| } else { | |||
| // 表示该包必须完整匹配ClassName所在包 | |||
| // 获取ClassName所在包 | |||
| String packageName = packageNameByDot(className); | |||
| if (packageName.equals(contractPackage.packageName)) { | |||
| verify = true; | |||
| } | |||
| } catch (IOException exception) { | |||
| logger.error(exception.getMessage()); | |||
| throw new MojoFailureException("IO ERROR"); | |||
| } catch (NullPointerException e) { | |||
| logger.error(e.getMessage()); | |||
| } | |||
| return verify; | |||
| } | |||
| private String packageNameByDot(String className) { | |||
| String[] array = className.split("."); | |||
| if (Character.isLowerCase(array[array.length - 2].charAt(0))) { | |||
| // 如果是小写,表示非内部类 | |||
| // 获取完整包名 | |||
| return className.substring(0, className.lastIndexOf(".")); | |||
| } | |||
| // 表示为内部类,该包拼装组成 | |||
| StringBuilder buffer = new StringBuilder(); | |||
| for (String s : array) { | |||
| if (buffer.length() > 0) { | |||
| buffer.append("."); | |||
| } | |||
| if (Character.isUpperCase(s.charAt(0))) { | |||
| // 表明已经到具体类 | |||
| break; | |||
| } | |||
| buffer.append(s); | |||
| } | |||
| if (buffer.length() == 0) { | |||
| throw new IllegalStateException(String.format("Import Class [%s] Illegal !!!", className)); | |||
| } | |||
| return buffer.toString(); | |||
| } | |||
| private String packageName(String clazz) { | |||
| int index = clazz.lastIndexOf("/"); | |||
| String packageName = clazz.substring(0, index); | |||
| return packageName.replaceAll("/", "."); | |||
| } | |||
| private File copyAndManage() throws IOException { | |||
| @@ -138,30 +335,104 @@ public class ContractVerifyMojo extends AbstractMojo { | |||
| return finalJar; | |||
| } | |||
| private Properties loadConfig() throws Exception { | |||
| Properties properties = new Properties(); | |||
| properties.load(this.getClass().getClassLoader().getResourceAsStream(CONFIG)); | |||
| return properties; | |||
| } | |||
| private LinkedList<String> loadAllClass(File file) throws Exception { | |||
| JarFile jarFile = new JarFile(file); | |||
| LinkedList<String> allClass = new LinkedList<>(); | |||
| Enumeration<JarEntry> jarEntries = jarFile.entries(); | |||
| while (jarEntries.hasMoreElements()) { | |||
| JarEntry jarEntry = jarEntries.nextElement(); | |||
| String entryName = jarEntry.getName(); | |||
| if (entryName.endsWith(".class")) { | |||
| // 内部类,不需要处理 | |||
| if (!entryName.contains("$")) { | |||
| allClass.addLast(entryName.substring(0, entryName.length() - 6)); | |||
| } | |||
| } | |||
| } | |||
| return allClass; | |||
| } | |||
| private String tempPath(String codeBaseDir, String clazz) { | |||
| // 获取最后的名称 | |||
| String[] classArray = clazz.split("/"); | |||
| String tempPath = codeBaseDir + classArray[classArray.length - 1] + "_" + | |||
| System.currentTimeMillis() + "_" + System.nanoTime() + JAVA_SUFFIX; | |||
| return tempPath; | |||
| } | |||
| private static class MethodVisitor extends VoidVisitorAdapter<Void> { | |||
| 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); | |||
| // } | |||
| private class MethodVisitor extends VoidVisitorAdapter<Void> { | |||
| @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 */ | |||
| logger.info("method:"+n.getName()); | |||
| public void visit(ImportDeclaration n, Void arg) { | |||
| importClasses.add(parseClass(n.toString())); | |||
| super.visit(n, arg); | |||
| } | |||
| @Override | |||
| public void visit(ClassOrInterfaceDeclaration n, Void arg) { | |||
| logger.info("class:"+n.getName()+" extends:"+n.getExtendedTypes()+" implements:"+n.getImplementedTypes()); | |||
| private String parseClass(String importInfo) { | |||
| String className = importInfo.substring(7, importInfo.length() - 2); | |||
| if (importInfo.startsWith("import static ")) { | |||
| // 获取静态方法的类信息 | |||
| className = importInfo.substring(14, importInfo.lastIndexOf(".")); | |||
| } | |||
| if (!className.contains(".")) { | |||
| throw new IllegalStateException(String.format("Import Class [%s] is Illegal !!", className)); | |||
| } | |||
| return className; | |||
| } | |||
| } | |||
| super.visit(n, arg); | |||
| private static class ContractPackage { | |||
| private String packageName; | |||
| private boolean isTotal = false; | |||
| public ContractPackage() { | |||
| } | |||
| @Override | |||
| public void visit(PackageDeclaration n, Void arg) { | |||
| logger.info("package:"+n.getName()); | |||
| super.visit(n, arg); | |||
| public ContractPackage(String totalPackage) { | |||
| if (totalPackage.endsWith("*")) { | |||
| this.packageName = totalPackage.substring(0, totalPackage.length() - 2).trim(); | |||
| this.isTotal = true; | |||
| } | |||
| this.packageName = totalPackage; | |||
| } | |||
| public String getPackageName() { | |||
| return packageName; | |||
| } | |||
| public boolean isTotal() { | |||
| return isTotal; | |||
| } | |||
| } | |||
| } | |||
| @@ -1 +1,8 @@ | |||
| blacklist=java.io,java.net,java.util.Random | |||
| #black.name.list:打包为合约Jar后,每个Class文件不允许使用的名称,默认不允许使用com.jd.blockchain.* | |||
| black.name.list=com.jd.blockchain.* | |||
| #black.package.list:打包为合约中的每个Class都不允许使用的包列表,某个包下面的所有包通过.*表示 | |||
| black.package.list=java.io.*, java.net.*, org.apache.commons.io.* | |||
| #black.class.list:打包为合约中的每个Class都不允许使用的类列表 | |||
| black.class.list=java.util.Random, com.jd.blockchain.ledger.BlockchainKeyGenerator | |||
| @@ -1,28 +0,0 @@ | |||
| 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.File; | |||
| /** | |||
| * @Author zhaogw | |||
| * @Date 2019/3/1 21:27 | |||
| */ | |||
| public class CheckImportsMojoTest extends AbstractMojoTestCase { | |||
| Logger logger = LoggerFactory.getLogger(CheckImportsMojoTest.class); | |||
| @Test | |||
| 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,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()); | |||
| } | |||
| } | |||
| @@ -1,6 +1,5 @@ | |||
| package com.jd.blockchain.ledger; | |||
| import com.jd.blockchain.CheckImportsMojo; | |||
| import com.jd.blockchain.ContractVerifyMojo; | |||
| import org.apache.maven.plugin.testing.AbstractMojoTestCase; | |||
| import org.junit.Test; | |||
| @@ -22,7 +21,7 @@ public class ContractVerifyMojoTest extends AbstractMojoTestCase { | |||
| assertNotNull( pom ); | |||
| assertTrue( pom.exists() ); | |||
| ContractVerifyMojo myMojo = (ContractVerifyMojo) lookupMojo( "JDChain.Verify", pom ); | |||
| ContractVerifyMojo myMojo = (ContractVerifyMojo) lookupMojo( "Contract.Verify", pom ); | |||
| assertNotNull( myMojo ); | |||
| myMojo.execute(); | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| package com.jd.blockchain.ledger; | |||
| import com.jd.blockchain.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.jar"; | |||
| } | |||
| @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; | |||
| } | |||
| } | |||
| @@ -78,22 +78,7 @@ | |||
| <version>${commons-io.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-core</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-expressions</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-reflection</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-compilertools</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| @@ -3,11 +3,8 @@ package com.jd.blockchain.gateway.service; | |||
| import com.jd.blockchain.consensus.ConsensusProvider; | |||
| import com.jd.blockchain.consensus.ConsensusProviders; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; | |||
| import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.gateway.PeerService; | |||
| import com.jd.blockchain.gateway.decompiler.utils.DecompilerUtils; | |||
| import com.jd.blockchain.ledger.ContractInfo; | |||
| import com.jd.blockchain.ledger.LedgerMetadata; | |||
| import com.jd.blockchain.ledger.ParticipantNode; | |||
| @@ -15,6 +12,7 @@ import com.jd.blockchain.sdk.ContractSettings; | |||
| import com.jd.blockchain.sdk.LedgerInitSettings; | |||
| import com.jd.blockchain.utils.QueryUtil; | |||
| import com.jd.blockchain.utils.codec.HexUtils; | |||
| import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.Arrays; | |||
| @@ -43,6 +43,23 @@ | |||
| <artifactId>spring-beans</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-core</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-expressions</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-reflection</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bitbucket.mstrobel</groupId> | |||
| <artifactId>procyon-compilertools</artifactId> | |||
| </dependency> | |||
| <!--<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> | |||
| </dependency> --> | |||
| @@ -1,4 +1,4 @@ | |||
| package com.jd.blockchain.gateway.decompiler.loads; | |||
| package com.jd.blockchain.utils.decompiler.loads; | |||
| import com.strobel.assembler.ir.ConstantPool; | |||
| import com.strobel.assembler.metadata.Buffer; | |||
| @@ -1,6 +1,6 @@ | |||
| package com.jd.blockchain.gateway.decompiler.utils; | |||
| package com.jd.blockchain.utils.decompiler.utils; | |||
| import com.jd.blockchain.gateway.decompiler.loads.BytesTypeLoader; | |||
| import com.jd.blockchain.utils.decompiler.loads.BytesTypeLoader; | |||
| import com.strobel.assembler.metadata.JarTypeLoader; | |||
| import com.strobel.decompiler.Decompiler; | |||
| import com.strobel.decompiler.DecompilerSettings; | |||
| @@ -15,7 +15,7 @@ import java.util.jar.JarOutputStream; | |||
| public class ContractJarUtils { | |||
| private static final String JDCHAIN_META = "META-INF/JDCHAIN.TXT"; | |||
| private static final String JDCHAIN_META = "META-INF/CONTRACT.MF"; | |||
| private static final int JDCHAIN_HASH_LENGTH = 69; | |||