package com.easyooo.framework.rule.impl; import java.io.File; import java.io.IOException; import java.net.URL; import java.text.MessageFormat; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.easyooo.framework.common.util.IoUtil; import com.easyooo.framework.common.util.MapUtil; import com.easyooo.framework.common.util.TemplateUtil; import com.easyooo.framework.rule.Language; import com.easyooo.framework.rule.Names; import com.easyooo.framework.rule.Rule; import com.easyooo.framework.rule.RuleException; /** * 脚本内部类,封装写入等 * @author Killer */ public class ScriptWriter{ protected static final Logger logger = LoggerFactory.getLogger(ScriptWriter.class); static final String TEMPLATE_NAME = "rule/rule.template"; static final String DEFAULT_NAME_PREFFIX = "Rule_{0}_{1}"; static final String PACKAGE; static final String rootClassPath; static final String ruleClasspath; static String templateFileName; // template content // Need to be initialized private static String template; // class name private String shortName; // outside properties private Rule rule; static { // template file path ClassLoader cl = ScriptWriter.class.getClassLoader(); URL turl = cl.getResource(TEMPLATE_NAME); if(turl != null){ templateFileName = turl.getFile(); // read template try { template = IoUtil.readLines(templateFileName); } catch (IOException e) { logger.error("IOException", e); } }else{ logger.error("RuleTemplate file not found"); } // pkg to path PACKAGE = getPackage(); rootClassPath = cl.getResource("").getPath(); ruleClasspath = rootClassPath + File.separator + PACKAGE.replace(".", File.separator) + File.separator; if(new File(ruleClasspath).mkdirs()){ // do nothing } logger.info(String.format("Rule Class output: %s", ruleClasspath)); } public ScriptWriter(Rule rule){ this.rule = rule; this.shortName = MessageFormat.format(DEFAULT_NAME_PREFFIX, rule.getRuleId(), rule.getVersion()); } private static String getPackage(){ Pattern p = Pattern.compile("(package\\s*[\\w\\.]+\\s*;)"); Matcher m = p.matcher(template); if(m.find()){ String group = m.group(); String pkg = group.substring(7); return pkg.replace(";", "").trim(); }else{ logger.error("Rule Template without package."); return null; } } public Class<?> getScriptClass()throws RuleException{ File file = new File(ruleClasspath + shortName + getClassExtension()); if(!file.exists()){ logger.debug("No rule["+ shortName +"] stub, recompile"); return null; } String className = PACKAGE + "." + shortName; try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new RuleException(e); } } public File createOrRead() throws RuleException { File script = buildScriptFile(); try { if(!script.exists()){ script.createNewFile(); } writeScript(script); } catch (IOException e) { throw new RuleException("An error occurred when writing script file" , e); } return script; } /** * 删除字节码文件,<b>谨慎操作</b> * @throws IOException */ public boolean deleteClass()throws IOException{ File file = new File(ruleClasspath + shortName + getClassExtension()); if(file.exists()){ return file.delete(); } return false; } private void writeScript(File script)throws IOException{ // template with args Map<String, Object> args = MapUtil.gmap( "className", shortName, "globalPropertyName", Names.GLOBAL, "localPropertyName", Names.LOCAL, "methodBody", rule.getRuleText()); String source = TemplateUtil.format(template, args); if(logger.isDebugEnabled()){ logger.debug("script path: " + script); } // write script and not append IoUtil.write(script, source, false); } private File buildScriptFile(){ String fileName = shortName + getKind(rule); StringBuffer scriptBuffer = new StringBuffer(ruleClasspath); scriptBuffer.append(fileName); return new File(scriptBuffer.toString()); } public String getKind(Rule rule){ if(rule.getLanguage() == Language.GROOVY){ return Kinds.GROOVY_EXTENSION; }else if(rule.getLanguage() == Language.JAVA){ return Kinds.JAVA_EXTENSION; }else{ return Kinds.JAVASCRIPT_EXTENSION; } } public String getClassExtension(){ return Kinds.CLASS_EXTENSION; } public String getRootDirectory(){ return rootClassPath; } private class Kinds{ static final String GROOVY_EXTENSION = ".groovy"; static final String JAVA_EXTENSION = ".java"; static final String JAVASCRIPT_EXTENSION = ".js"; static final String CLASS_EXTENSION = ".class"; } }