插件运行时动态加载jar--解决jet2模板动态添加问题

昨天在编写代码生成器时遇到一个问题:用JET2模板引擎不能够动态编译代码模板文件,也就意味着我不能都动态的添加自定义代码模板,这和我希望的开放式式的代码生成器不符合。我最看中的就是jet2模板里能由模板编写者自己控制生成哪些代码文件,很开发灵活。如果放弃jet2的话我还没找到更好的代替者,所以我只能想方设法使代码生成器能动态加载用户添加的模板。想到的办法是:让用户编写好代码模板后,将模板文件和编译好的模板类一起打包成jar,然后由代码生成运行时动态加载。

插件动态加载jar方法:自定义类加载器继承URLClassLoader,重写addURl方法使之变为public,方便多次添加jar。

代码:

public class DynamicClassLoader extends URLClassLoader {
	
	/**
	 * 类加载器实例化后,再添加单个jar
	 */
	@Override
	public void addURL(URL url) {
		super.addURL(url);
	}

	static final URL[] EMPTY_URLS = new URL[]{};

	public DynamicClassLoader(){
		super(EMPTY_URLS);
	}
	
	public DynamicClassLoader(URL[] urls){
		super(urls ,(Thread.currentThread().getContextClassLoader() == null ||
	                Thread.currentThread().getContextClassLoader() == ClassLoader.getSystemClassLoader())?
	                Compiler.class.getClassLoader():Thread.currentThread().getContextClassLoader());
	}

	public DynamicClassLoader(ClassLoader parent){
		super(EMPTY_URLS,parent);
	}
	
	/**
	 * 创建类加载器
	 * @param urls 待加载的jarUrl集合
	 * @param parent 父类加载器
	 */
	public DynamicClassLoader(URL[] urls, ClassLoader parent){
		super(urls,parent);
	}

}
 

在需要的地方实例化调用(如插件启动时实例化),调用代码如下:

代码:

	/**
	 * 动态加载指定jar
	 * @param jarURL
	 */
	public void loadJar(File jar){
		if(jar != null){
			try {
				dynamicClassLoader.addURL(jar.toURI().toURL());
			} catch (MalformedURLException e) {
				LogUtil.logError(e.getMessage(),e);
			}
			setPathToTemplateClassMapByJar(jar);
		}
	}

	/**
	 * 根据模板jar文件设置代码模板路径和类映射集合
	 * @param jar 模板jar文件,必须包含模板源码和编译后的模板类
	 */
	public void setPathToTemplateClassMapByJar(File jar){
		if(jar == null){
			return;
		}
		try {
			JarFile jf = new JarFile(jar);
			final Enumeration<JarEntry> entries = jf.entries();
			//保存所有模板源文件
			List<String> templatePathList = new ArrayList<String>();
			//保存编译的模板类名和类全路径映射集合
			Map<String, String> classMap = new HashMap<String, String>();
	        while (entries.hasMoreElements()) {
	            final JarEntry entry = entries.nextElement();
	            final String entryName = entry.getName();
	            if (entryName.startsWith("templates")) {
	            	templatePathList.add(entryName);
	            }else if(entryName.endsWith(".class")){
	            	int lastspindex = entryName.lastIndexOf("/"); 
	            	String key = entryName.substring(lastspindex + 1, entryName.length() - 6);
	            	String className = entryName.substring(0, entryName.length() - 6).replace("/", ".");
	            	classMap.put(key, className);
	            }
	        }
	        
	        for(String templatePath : templatePathList){
	        	int lastspindex = templatePath.lastIndexOf("/"); 
	        	int lastpoindex = templatePath.lastIndexOf("."); 
	        	String key = "_jet_"+templatePath.substring(lastspindex + 1, lastpoindex).replace(".", "");
	        	String className = classMap.get(key);
	        	if(className != null){
	        		pathToTemplateClassMap.put(templatePath, className);
	        	}
	        }

		} catch (IOException e) {
			LogUtil.logError(e.getMessage(),e);
		}
	}
 

 

还要修改代码生成器插件的jet2扩展中的模板加载器类,使之能根据模板路径用自定义类加载器来实例化模板对象。

代码如下:

/**
 * 自定义模板加载器
 * CreatorTemplateLoader
 */
public class CreatorTemplateLoader implements JET2TemplateLoader,
        JET2TemplateLoaderExtension {

    private JET2TemplateLoader delegate = null;

     /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jet.JET2TemplateLoader#getTemplate(java.lang.String)
     */
    public JET2Template getTemplate(final String templatePath) {
        final String ordinal = CodeGenActivator.pathToTemplateClassMap.get(templatePath);
        if(ordinal != null) {
        	try {
				return (JET2Template)CodeGenActivator.getDefault().getDynamicClassLoader().loadClass(ordinal).newInstance();
			} catch (InstantiationException e) {
				LogUtil.logError(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				LogUtil.logError(e.getMessage(), e);
			} catch (ClassNotFoundException e) {
				LogUtil.logError(e.getMessage(), e);
			}
        }
        return this.delegate != null ? this.delegate.getTemplate(templatePath) : null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jet.JET2TemplateLoaderExtension#getDelegateLoader()
     */
    public JET2TemplateLoader getDelegateLoader() {
        return this.delegate;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.jet.JET2TemplateLoaderExtension#setDelegateLoader(org.eclipse
     * .jet.JET2TemplateLoader)
     */
    public void setDelegateLoader(final JET2TemplateLoader loader) {
        this.delegate = loader;
    }
}
 

隔了好久才记起这个文章没写完,今天记起后赶紧补充完整了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值