/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jef.codegen; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.net.URL; import jef.codegen.support.RegexpNameFilter; import jef.common.log.LogUtil; import jef.tools.ArrayUtils; import jef.tools.ClassScanner; import jef.tools.IOUtils; import jef.tools.StringUtils; import jef.tools.URLFile; import jef.tools.resource.IResource; /** * JEF中的Entity静态增强任务类 * <h3>作用</h3> * 这个类中提供了{@link #enhance(String...)}方法,可以对当前classpath下的Entity类进行字节码增强。 * * * @author jiyi * @Date 2011-4-6 */ public class EntityEnhancer { private String includePattern; private String[] excludePatter; private File[] roots; PrintStream out = System.out; public void setOut(PrintStream out) { this.out = out; } /** * 在当前的classpath目录下扫描Entity类(.clsss文件),使用字节码增强修改这些class文件。 * @param pkgNames */ public void enhance(final String... pkgNames) { if (roots == null || roots.length == 0) { StackTraceElement[] eles = Thread.currentThread().getStackTrace(); StackTraceElement last = eles[1]; try { Class<?> clz=Class.forName(last.getClassName()); roots = IOUtils.urlToFile(ArrayUtils.toArray(clz.getClassLoader().getResources("."), URL.class)); } catch (IOException e) { LogUtil.exception(e); } catch (ClassNotFoundException e) { //do nothing } } if(roots==null){ return; } int n = 0; for (File root : roots) { IResource[] clss = ClassScanner.listClassNameInPackage(root, pkgNames, true); for (IResource cls : clss) { if(!cls.isFile()){ continue; } try { if(processEnhance(root,cls)){ n++; } } catch (Exception e) { LogUtil.exception(e); LogUtil.error("Enhance error: " + cls + ": " + e.getMessage()); continue; } } } out.println(n + " classes enhanced."); } public boolean enhanceClass(String string) { URL url=this.getClass().getClassLoader().getResource(string.replace('.', '/')+".class"); if(url==null){ throw new IllegalArgumentException("not found "+string); } URLFile file=new URLFile(url); if(!file.isLocalFile()){ throw new IllegalArgumentException("not a local file."+string); } try { return enhance(file.getLocalFile(),string); } catch (Exception e) { throw new RuntimeException(e); } } private boolean enhance(File f,String cls) throws IOException, Exception { EnhanceTaskASM enhancer=new EnhanceTaskASM(null,roots); File sub = new File(f.getParentFile(), StringUtils.substringAfterLastIfExist(cls, ".").concat("$Field.class")); byte[] result=enhancer.doEnhance(IOUtils.toByteArray(f), (sub.exists()?IOUtils.toByteArray(sub):null)); if(result!=null){ if(result.length==0){ out.println(cls + " is already enhanced."); }else{ IOUtils.saveAsFile(f,result); out.println("enhanced class:" + cls);// 增强完成 return true; } } return false; } private boolean processEnhance(File root,IResource cls) throws Exception { EnhanceTaskASM enhancer=new EnhanceTaskASM(root,roots); File f = cls.getFile(); File sub = new File(IOUtils.removeExt(f.getAbsolutePath()).concat("$Field.class")); if (!f.exists()) { // out.println("class file " + f.getAbsolutePath() + " is not found"); return false; } // RegexpNameFilter filter = new RegexpNameFilter(includePattern, excludePatter); // if (!filter.accept(cls)) { // continue; // } // if (cls.startsWith("org.apache")||cls.startsWith("javax.")) // continue; // if(cls.endsWith("$Field")) // continue; byte[] result=enhancer.doEnhance(IOUtils.toByteArray(f), (sub.exists()?IOUtils.toByteArray(sub):null)); if(result!=null){ if(result.length==0){ out.println(cls + " is already enhanced."); }else{ IOUtils.saveAsFile(f,result); out.println("enhanced class:" + cls);// 增强完成 return true; } } return false; } /** * 设置类名Pattern * @return */ public String getIncludePattern() { return includePattern; } public EntityEnhancer setIncludePattern(String includePattern) { this.includePattern = includePattern; return this; } public String[] getExcludePatter() { return excludePatter; } public EntityEnhancer setExcludePatter(String[] excludePatter) { this.excludePatter = excludePatter; return this; } public File[] getRoot() { return roots; } public void setRoot(File... roots) { this.roots = roots; } }