Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.jd.blockchain.maven.plugins.contract.analysis.MavenPluginContractProcessor Maven / Gradle / Ivy
package com.jd.blockchain.maven.plugins.contract.analysis;
import com.jd.blockchain.contract.Contract;
import com.jd.blockchain.contract.ContractEntrance;
import com.jd.blockchain.contract.ContractJarUtils;
import com.jd.blockchain.contract.ContractProcessor;
import com.jd.blockchain.contract.ContractType;
import com.jd.blockchain.maven.plugins.contract.analysis.asm.ASMClassVisitor;
import com.jd.blockchain.maven.plugins.contract.analysis.contract.AbstractContract;
import com.jd.blockchain.maven.plugins.contract.analysis.contract.ContractClass;
import com.jd.blockchain.maven.plugins.contract.analysis.contract.ContractField;
import com.jd.blockchain.maven.plugins.contract.analysis.contract.ContractMethod;
import com.jd.blockchain.maven.plugins.contract.analysis.rule.BlackList;
import com.jd.blockchain.maven.plugins.contract.analysis.rule.WhiteList;
import com.jd.blockchain.maven.plugins.contract.analysis.util.ContractClassLoader;
import com.jd.blockchain.maven.plugins.contract.analysis.util.ContractClassLoaderUtil;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.objectweb.asm.ClassReader;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static com.jd.blockchain.contract.ContractJarUtils.BLACK_CONF;
import static com.jd.blockchain.maven.plugins.contract.analysis.util.ContractClassLoaderUtil.classNameToSeparator;
import static com.jd.blockchain.maven.plugins.contract.analysis.util.ContractClassLoaderUtil.resolveConfig;
public class MavenPluginContractProcessor implements ContractProcessor {
private static BlackList BLACKLIST;
private static WhiteList WHITELIST;
private Set haveManagedMethods = new HashSet<>();
private Set haveManagedFields = new HashSet<>();
static {
init();
}
private Log logger;
private Set libraries;
public MavenPluginContractProcessor (Log logger, Set libraries) {
this .logger = logger;
this .libraries = libraries;
}
@Override
public boolean verify (File carFile) {
return false ;
}
@Override
public boolean verify (byte [] chainCode) {
return false ;
}
@Override
public ContractEntrance analyse (File classesDirectory) throws MojoExecutionException {
ContractLoaderData loaderData = loadAllContractClasses(classesDirectory);
if (loaderData == null || loaderData.isEmpty()) {
throw new MojoExecutionException("Can not find any interface have @Contract !!!" );
}
List urls = new ArrayList<>();
Map total = new HashMap<>(loaderData.getClassLoader().classesBySeparator());
for (Artifact artifact : libraries) {
try {
File jarFile = artifact.getFile();
urls.add(jarFile.toURI().toURL());
Map map = ContractJarUtils.loadAllClasses(jarFile);
total.putAll(map);
} catch (Exception e) {
throw new MojoExecutionException("Load artifact error !!!" , e);
}
}
URL[] jarUrls = urls.toArray(new URL[urls.size()]);
URLClassLoader urlClassLoader = new URLClassLoader(jarUrls,
loaderData.getClassLoader());
Map allContractClasses = resolveClasses(total);
Class contractClass = loaderData.getContractClass();
verify(urlClassLoader, allContractClasses, contractClass.getName());
try {
urlClassLoader.close();
} catch (Exception e) {
logger.debug(e);
}
return new ContractEntrance(loaderData.getContractInterface().getName(),
loaderData.getContractClass().getName());
}
@Override
public ContractEntrance analyse (byte [] chainCode) {
return null ;
}
@Override
public String decompileEntranceClass (byte [] chainCode) {
return null ;
}
@Override
public String decompileEntranceClass (File carFile) {
return null ;
}
private ContractLoaderData loadAllContractClasses (File classesDirectory) throws MojoExecutionException {
ContractClassLoader classLoader = ContractClassLoaderUtil.loadAllClassUnderDirectory(
classesDirectory, Thread.currentThread().getContextClassLoader(), false );
if (classLoader == null ) {
throw new MojoExecutionException("Init classloader error !!!" );
}
Set classNames = classLoader.classNames();
if (classNames.isEmpty()) {
throw new MojoExecutionException("Can not load any class !!!" );
}
ContractLoaderData loaderData = new ContractLoaderData(classLoader);
Class contractInterface = null ;
for (String className : classNames) {
try {
Class clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Contract.class) && clazz.isInterface()) {
if (contractInterface != null ) {
throw new MojoExecutionException("Contract must have one interface of @Contract only !!!" );
} else {
if (clazz.getName().startsWith("com.jd.blockchain." )) {
throw new MojoExecutionException(String.format(
"Interface[%s] can not use package [com.jd.blockchain] !!!" , clazz.getName()));
}
try {
ContractType.resolve(clazz);
} catch (Exception e) {
throw new MojoExecutionException(
String.format("Verify contract interface %s !!!" , clazz.getName()), e);
}
contractInterface = clazz;
}
}
} catch (ClassNotFoundException e) {
logger.debug("Load class error !!!" , e);
}
}
if (contractInterface == null ) {
return null ;
}
loaderData.initContractInterface(contractInterface);
for (String className : classNames) {
try {
Class clazz = classLoader.loadClass(className);
if (!clazz.isInterface()) {
Class[] interfaces = clazz.getInterfaces();
for (Class intf : interfaces) {
if (intf == contractInterface) {
if (!loaderData.isEmpty()) {
throw new MojoExecutionException(String.format(
"Interface %s can have one implementation class only !!!" , contractInterface.getName()));
} else {
if (clazz.getName().startsWith("com.jd.blockchain." )) {
throw new MojoExecutionException(String.format(
"%s can not use package [com.jd.blockchain] !!!" , clazz));
}
logger.debug(String.format("Find implementation class[%s] of contract interface %s !!!" ,
clazz.getName(), contractInterface.getName()));
loaderData.initContractClass(clazz);
}
}
}
}
} catch (ClassNotFoundException e) {
logger.debug("Load class error !!!" , e);
}
}
return loaderData;
}
private Map resolveClasses (Map allClasses) {
Map allContractClasses = new ConcurrentHashMap<>();
for (Map.Entry entry : allClasses.entrySet()) {
byte [] classContent = entry.getValue();
if (classContent == null || classContent.length == 0 ) {
continue ;
}
String className = classNameToSeparator(entry.getKey());
String dotClassName = ContractJarUtils.dotClassName(className);
if (WHITELIST.isWhite(dotClassName) || BLACKLIST.isBlackClass(dotClassName)) {
continue ;
}
ContractClass contractClass = new ContractClass(className);
ClassReader cr = new ClassReader(classContent);
cr.accept(new ASMClassVisitor(contractClass), ClassReader.SKIP_DEBUG);
allContractClasses.put(className, contractClass);
}
return allContractClasses;
}
private void verify (URLClassLoader urlClassLoader, Map allContractClasses, String contractClass) throws MojoExecutionException {
String mainClassKey = classNameToSeparator(contractClass);
if (!allContractClasses.containsKey(mainClassKey)) {
throw new MojoExecutionException(String.format("Load contract class = [%s] null !!!" , contractClass));
}
for (ContractClass clazz : allContractClasses.values()) {
Map methods = clazz.getMethods();
if (!methods.isEmpty()) {
for (Map.Entry entry : methods.entrySet()) {
ContractMethod method = entry.getValue();
verify(urlClassLoader, allContractClasses, method);
}
}
}
}
private void verify (URLClassLoader urlClassLoader, Map allContractClasses, ContractMethod method) throws MojoExecutionException {
String managedKey = managedKey(method);
if (haveManagedMethods.contains(managedKey)) {
return ;
}
haveManagedMethods.add(managedKey);
String dotClassName = method.getDotClassName();
Class dotClass = null ;
try {
dotClass = urlClassLoader.loadClass(dotClassName);
} catch (Exception e) {
logger.debug(e);
}
if (dotClass == null ) {
return ;
}
String dotClassLoader = null ;
ClassLoader classLoader = dotClass.getClassLoader();
if (classLoader != null ) {
dotClassLoader = dotClass.getClassLoader().toString();
}
if (dotClassLoader != null && (dotClassLoader.contains("URLClassLoader" ) ||
dotClassLoader.contains("ContractClassLoader" ))) {
if (BLACKLIST.isBlack(dotClass, method.getMethodName())) {
throw new MojoExecutionException(String.format("Class [%s] method [%s] is black !!!" , dotClassName, method.getMethodName()));
} else {
if (WHITELIST.isWhite(dotClass)) {
return ;
}
List innerMethods = method.getMethodList();
if (!innerMethods.isEmpty()) {
for (ContractMethod innerMethod : innerMethods) {
ContractClass innerClass = allContractClasses.get(innerMethod.getClassName());
if (innerClass != null ) {
ContractMethod verifyMethod = innerClass.method(innerMethod.getMethodName());
verify(urlClassLoader, allContractClasses, verifyMethod);
} else {
verify(urlClassLoader, allContractClasses, innerMethod);
}
}
}
List innerFields = method.getAllFieldList();
if (!innerFields.isEmpty()) {
for (ContractField innerField : innerFields) {
verify(urlClassLoader, innerField);
}
}
}
} else {
if (WHITELIST.isWhite(dotClass)) {
if (BLACKLIST.isBlack(dotClass, method.getMethodName())) {
throw new MojoExecutionException(String.format("Class [%s] method [%s] is black !!!" , dotClassName, method.getMethodName()));
}
return ;
}
if (BLACKLIST.isBlack(dotClass, method.getMethodName())) {
throw new MojoExecutionException(String.format("Class [%s] method [%s] is black !!!" , dotClassName, method.getMethodName()));
}
}
}
private void verify (URLClassLoader urlClassLoader, ContractField field) {
String managedKey = managedKey(field);
if (haveManagedFields.contains(managedKey)) {
return ;
}
haveManagedFields.add(managedKey);
try {
Class dotClass = urlClassLoader.loadClass(field.getDotClassName());
if (dotClass == null ) {
return ;
}
if (BLACKLIST.isBlackField(dotClass)) {
throw new MojoExecutionException(String.format("Class [%s] field [%s] is black !!!" , field.getDotClassName(), field.getFieldName()));
}
} catch (Exception e) {
logger.debug(e);
}
}
private String managedKey (ContractMethod method) {
return method.getDotClassName() + "-" + method.getMethodName();
}
private String managedKey (ContractField field) {
return field.getDotClassName() + "- -" + field.getFieldName();
}
private static void init () {
WHITELIST = AbstractContract.initWhite(loadWhiteConf());
BLACKLIST = AbstractContract.initBlack(loadBlackConf());
}
private static List loadWhiteConf () {
List whiteList = new ArrayList<>();
whiteList.add("com.jd.blockchain.*" );
return whiteList;
}
private static List loadBlackConf () {
return resolveConfig(BLACK_CONF);
}
static final class ContractLoaderData {
private Class contractClass = null ;
private Class contractInterface = null ;
private ContractClassLoader classLoader;
public ContractLoaderData (ContractClassLoader classLoader) {
this .classLoader = classLoader;
}
public void initContractClass (Class clazz) {
contractClass = clazz;
}
public void initContractInterface (Class clazz) {
contractInterface = clazz;
}
public boolean isEmpty () {
return contractClass == null ;
}
public Class getContractClass () {
return contractClass;
}
public Class getContractInterface () {
return contractInterface;
}
public ContractClassLoader getClassLoader () {
return classLoader;
}
}
}