All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.onetwo.dbm.richmodel.RichModelEnhanceProcessor Maven / Gradle / Ivy

The newest version!
package org.onetwo.dbm.richmodel;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javassist.CannotCompileException;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.Modifier;

import org.onetwo.common.log.JFishLoggerFactory;
import org.onetwo.common.reflect.ReflectUtils;
import org.onetwo.common.utils.ClassUtils;
import org.onetwo.dbm.exception.DbmException;
import org.onetwo.dbm.mapping.ScanedClassContext;
import org.slf4j.Logger;

import com.google.common.collect.Maps;

public class RichModelEnhanceProcessor implements PackageScanedProcessor {

	private final Logger logger = JFishLoggerFactory.getLogger(this.getClass());
	
	private MultiEnhancer enhancer = new MultiEnhancer();
	private ClassPool classPool;
	private Map classes = new HashMap<>(50);
	
	public RichModelEnhanceProcessor() {
		super();
		classPool = ClassPool.getDefault();
		this.classPool.insertClassPath(new ClassClassPath(this.getClass()));
//		this.classPool.insertClassPath(new LoaderClassPath(ClassUtils.getDefaultClassLoader()));
		this.enhancer.addEnhancer(new StaticMethodsEnhancer());
	}
	

	public void processClasses(Collection clssNameList) {
		CtClass ctclass = null;
		for(ScanedClassContext ctx : clssNameList){
			if(classes.containsKey(ctx.getClassName())){
				continue;
			}
			try {
				ctclass = enhanceClass(ctx);
				if(ctclass==null){
					continue;
				}
				ctclass.toClass(ClassUtils.getDefaultClassLoader(), ClassUtils.class.getProtectionDomain());
				classes.put(ctx.getClassName(), null);
			} catch (Exception e) {
//				throw new DbmException("enchan model["+ctx.getClassName()+"] error : "+e.getMessage(), e);
				logger.error("enchan model["+ctx.getClassName()+"] error : "+e.getMessage());
			}
		}
	}

	@Deprecated
	void processClasses2(Collection clssNameList) {
		CtClass ctclass = null;
		boolean enableSubClassEnhance = false;
		for(ScanedClassContext ctx : clssNameList){
			if(classes.containsKey(ctx.getClassName())){
				continue;
			}
			try {
				ctclass = enhanceClass(ctx);
				if(ctclass==null){
					continue;
				}
				ModelInfo info = new ModelInfo(ctx.getClassName());
				if(!enableSubClassEnhance){
					try {
						info.actualClass = ctclass.toClass(ClassUtils.getDefaultClassLoader(), ClassUtils.class.getProtectionDomain());
					} catch (CannotCompileException e) {
						enableSubClassEnhance = true;
						logger.warn("enhance RichModel error, enable SubClass enhance...");
					}
				}
				if(enableSubClassEnhance){
					String subClassName = ctx.getClassName()+"$$Dbm";
					info.subClassName = subClassName;
					ctclass = createSubCtClass(ctx.getClassName(), subClassName);
					ctclass = enhanceClass(subClassName, ctclass);
					info.actualClass = ctclass.toClass(ClassUtils.getDefaultClassLoader(), ClassUtils.class.getProtectionDomain());
				}
				info.enhanceSubClass = enableSubClassEnhance;
				info.ctClass = ctclass;
				classes.put(info.getModelClassName(), info);
			} catch (Exception e) {
				throw new DbmException("enchan model["+ctx.getClassName()+"] error : "+e.getMessage(), e);
			}
		}
		RichModels.setModelMapping(classes.values());
	}
	
	protected CtClass createSubCtClass(String superClass, String subClassName){
		try {
			CtClass subCtClass = this.classPool.makeClass(subClassName);
			CtClass superCtClass = this.classPool.get(superClass);
			subCtClass.setSuperclass(superCtClass);
			subCtClass.setModifiers(Modifier.PUBLIC);
			return subCtClass;
		} catch (Exception e) {
			throw new DbmException("enhance RichModel error for model class: " + superClass, e);
		}
	}
	
	protected CtClass enhanceClass(ScanedClassContext classCtx) throws Exception{
		String className = classCtx.getClassName();
		CtClass ctclass = classPool.makeClassIfNew(classCtx.getInputStream());
		return enhanceClass(className, ctclass);
	}
	
	protected CtClass enhanceClass(String className, CtClass ctclass) throws Exception{
		if(!ctclass.subtypeOf(classPool.get(RichModel.class.getName()))){
			return null;
		}
		if(ctclass.isFrozen())
			return ctclass;
		EnhanceContext context = new EnhanceContext(className, ctclass);
		enhancer.enhance(context);
//		ctclass.toClass();
		logger.info("enhance model : " + className);
		return ctclass;
	}

	public static class ModelInfo {
		private String modelClassName;
		private boolean enhanceSubClass;
		private String subClassName;
		private CtClass ctClass;
		private Class actualClass;
		public ModelInfo(String modelClassName) {
			this.modelClassName = modelClassName;
		}
		public String getModelClassName() {
			return modelClassName;
		}
		public boolean isEnhanceSubClass() {
			return enhanceSubClass;
		}
		public String getSubClassName() {
			return subClassName;
		}
		public CtClass getCtClass() {
			return ctClass;
		}
		public Class getActualClass() {
			return actualClass;
		}
		
	}

	@Deprecated
	static private final class RichModels {
		
		static private Map MODEL_MAPPING = Maps.newHashMap();
		
		@SuppressWarnings({ "unchecked", "unused" })
		public static  S get(Class clazz){
			ModelInfo info = MODEL_MAPPING.get(clazz.getName());
			return (S) ReflectUtils.newInstance(info.getActualClass());
		}

		static void addMapping(ModelInfo info){
			String className = info.getModelClassName();
			if(MODEL_MAPPING.containsKey(className)){
				throw new DbmException("mapping has be exists : " + className);
			}
			MODEL_MAPPING.put(className, info);
		}
		static void setModelMapping(Collection classes){
			MODEL_MAPPING = Maps.newHashMapWithExpectedSize(classes.size());
			classes.stream().forEach(cls->{
				addMapping(cls);
			});
		}
		private RichModels(){
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy