Java tutorial
package com.tower.service.test; /* * Copyright 2001-2005 The Apache Software Foundation. * * 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. */ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.HashMap; import java.util.List; import java.util.Map; import javassist.NotFoundException; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import com.tower.service.annotation.SoaFwTest; import com.tower.service.util.MD5Util; /** * Goal which gen a timestamp file. * * @goal gen * @requiresDependencyResolution compile+runtime * @phase process-sources */ public class SoafwTesterMojo extends AbstractMojo { /** * * @parameter property="project.artifactId" */ private String artifactId; /** * &??? */ private Map<String, Integer> defines = new HashMap<String, Integer>(); /** * ???&&? */ private Map<String, Integer> testImpl = new HashMap<String, Integer>(); private Map<String, Integer> errorImpl = new HashMap<String, Integer>(); private MavenProject project = null; private ClassLoader cl = null; private String basedPath = null; /** * ???? * @parameter property="test.gen.skip" */ private String test_gen_skip = "false"; /** * ? * @parameter property="config" */ private boolean config = false; /** * ? * @parameter property="configFileLocations" */ private String configFileLocations = "classpath*:/META-INF/config/spring/spring-service.xml"; /** * ? * @parameter property="classpath" */ private String classpath = "target" + File.separator + "classes"; /** * ? * @parameter property="testClasspath" */ private String testClasspath = "target" + File.separator + "test-classes"; public void execute() throws MojoExecutionException { String flg = test_gen_skip; this.getLog().info("" + this.getPluginContext()); project = (MavenProject) getPluginContext().get("project"); this.getLog().info("ProjectName: " + project.getName()); File basedir = project.getBasedir(); basedPath = basedir.getAbsolutePath(); artifactId = project.getArtifactId(); this.getLog().info("basedPath:" + basedPath); if ("true".equalsIgnoreCase(flg)) { this.getLog().info("test.gen.skip: " + artifactId); return; } this.getLog().info("start unit test file gen&check: " + artifactId); try { List<String> classpaths = project.getCompileClasspathElements(); List<String> testClasspaths = project.getTestClasspathElements(); URL[] runtimeUrls = new URL[classpaths.size() + testClasspaths.size()]; for (int i = 0; i < classpaths.size(); i++) { String classpath = (String) classpaths.get(i); runtimeUrls[i] = new File(classpath).toURI().toURL(); } for (int i = 0; i < testClasspaths.size(); i++) { String classpath = (String) testClasspaths.get(i); runtimeUrls[classpaths.size() + i] = new File(classpath).toURI().toURL(); } // ?classpath runtimeUrls[classpaths.size()] = new File(basedPath + File.separator + testClasspath).toURI().toURL(); this.cl = new URLClassLoader(runtimeUrls, Thread.currentThread().getContextClassLoader()); } catch (Exception e2) { } String classesDir = basedPath + File.separator + classpath; this.getLog().info(": " + new File(classesDir).exists()); int length = classesDir.length() + 1; // load(classesDir, new File(classesDir), length);// map /** * */ String testClassesDir = basedPath + File.separator + testClasspath; this.getLog().info("?: " + new File(testClassesDir).exists()); length = testClassesDir.length() + 1; // load(testClassesDir, new File(testClassesDir), length);// map int size = defines.size(); String[] definesArray = new String[size]; defines.keySet().toArray(definesArray); if (size == 0) { this.getLog().info("??"); } for (int i = 0; i < size; i++) { boolean hasmethod = false; if (!testImpl.containsKey(definesArray[i] + "Test")) { this.getLog().info("?" + definesArray[i] + "Test"); genTest(basedPath, definesArray[i]); } else {// ? appendTest(definesArray[i]); } } for (int i = 0; i < size; i++) { if (testImpl.containsKey(definesArray[i] + "Test")) { defines.remove(definesArray[i]); } } this.getLog().info("&???" + defines); this.getLog().info("???||?" + testImpl); this.getLog().error("??" + errorImpl); } private void genTest(String basedPath, String className) { // this.getLog().info("" + className + ""); Map<String, Integer> methodCnt = new HashMap<String, Integer>(); boolean hasmethod = false; try { Class cls = cl.loadClass(className); String testJFileName = cls.getSimpleName() + "Test.java"; String pkgPath = cls.getPackage().getName().replace(".", File.separator); String testJFilePath = basedPath + File.separator + "src" + File.separator + "test" + File.separator + "java" + File.separator + pkgPath; int len = 0; Class[] inters = cls.getInterfaces(); if (inters == null || (len = inters.length) == 0) { return; } /** * package import */ StringBuffer jHeadBuf = createTestJHeadByClass(cls); StringBuffer testJBuf = new StringBuffer(); testJBuf.append(jHeadBuf); Map<String, String> methodDefs = new HashMap<String, String>(); for (int j = 0; j < len; j++) { /** * ? */ Class interCls = inters[j]; this.getLog().info("@interface: " + interCls.getName()); String name = project.getName(); Method[] methods = null; if (name.endsWith("-dao")) { methods = interCls.getDeclaredMethods(); } else { methods = interCls.getMethods(); } int mlen = 0; if (methods != null && (mlen = methods.length) > 0) { this.getLog().info("?" + className + "Test?"); StringBuffer methodBuf = new StringBuffer(); for (int m = 0; m < mlen; m++) { Method method = methods[m]; int modf = method.getModifiers(); if (modf == 1025) {// ?? hasmethod = true; /** * ??????Test ???=??+Test * ??:basedPath+File.separator * +src+File.separator+test+File.separator * +pkg+definesArray[i]+Test+.java */ if (methodCnt.containsKey(method.getName())) { methodCnt.put(method.getName(), methodCnt.get(method.getName()) + 1); } else { methodCnt.put(method.getName(), 0); } int cnt = methodCnt.get(method.getName()); addMethod(methodDefs, methodBuf, method, cnt); } } testJBuf.append(methodBuf); } else { this.getLog().info(className + ""); } } String testJFile = testJBuf.append("}").toString(); if (hasmethod) { write(testJFilePath, testJFileName, testJFile); } } catch (Exception e) { this.getLog().error(e); } catch (Error er) { this.getLog().error(er); } } /** * * @param className * */ private void appendTest(String className) { /** * ?? ?public * ?MojoExecutionException?????? */ try { Map<String, Integer> methodCnt = new HashMap<String, Integer>(); boolean hasmethod = false; Map<String, String> methodDefs = new HashMap<String, String>(); Class cls = cl.loadClass(className);// Class[] inters = cls.getInterfaces(); int len = 0; if (inters == null || (len = inters.length) == 0) { return; } for (int i = 0; i < len; i++) { Class interCls = inters[i]; this.getLog().info("@interface: " + interCls.getName()); String name = project.getName(); Method[] methods = null; if (name.endsWith("-dao")) { methods = interCls.getDeclaredMethods(); } else { methods = interCls.getMethods(); } int mlen = 0; if (methods != null && (mlen = methods.length) > 0) { StringBuffer methodBuf = new StringBuffer(); for (int m = 0; m < mlen; m++) { Method method = methods[m]; int modf = method.getModifiers(); if (modf == 1025) {// ?? hasmethod = true; /** * ??????Test ???=??+Test * ??:basedPath+File.separator * +src+File.separator+test+File.separator * +pkg+definesArray[i]+Test+.java */ if (methodCnt.containsKey(method.getName())) { methodCnt.put(method.getName(), methodCnt.get(method.getName()) + 1); } else { methodCnt.put(method.getName(), 0); } int cnt = methodCnt.get(method.getName()); addMethod(methodDefs, methodBuf, method, cnt); } } } } Class tstCls = cl.loadClass(className + "Test");// Method[] methods = tstCls.getDeclaredMethods(); len = methods == null ? 0 : methods.length; this.getLog().info("" + tstCls.getSimpleName() + "?" + len); /** * ??public */ for (int m = 0; m < len; m++) { Method method = methods[m]; SoaFwTest test = method.getAnnotation(SoaFwTest.class); if (test == null) { this.getLog() .info(tstCls.getSimpleName() + " method " + method.getName() + "SoaFwTest"); continue; } String id = test.id(); if (methodDefs.containsKey(id)) { methodDefs.remove(id); } } if ((len = methodDefs.size()) == 0) { return; } String[] methodImpls = new String[len]; methodDefs.keySet().toArray(methodImpls); // TODO ??? StringBuilder src = new StringBuilder(); String srcs = readTestSrc(className); int index = srcs.lastIndexOf("}"); // this.getLog().info(srcs); //this.getLog().info("lastIndexOf(}):" + index); String impls = srcs.substring(0, index - 1); src.append(impls); src.append("\n"); this.getLog().info("?: " + className + "Test"); StringBuilder appends = new StringBuilder(); this.getLog().info("?"); for (int i = 0; i < len; i++) { String methodId = methodImpls[i]; String method = methodDefs.get(methodId); appends.append(method); appends.append("\n"); } src.append(appends.toString()); src.append("}"); Package pkg = tstCls.getPackage(); String pkgName = pkg.getName(); String pkgPath = pkgName.replace(".", File.separator); String testBaseSrcPath = basedPath + File.separator + "src" + File.separator + "test" + File.separator + "java"; String testSrcFullPath = testBaseSrcPath + File.separator + pkgPath; write(testSrcFullPath, tstCls.getSimpleName() + ".java", src.toString()); } catch (Exception e) { this.getLog().error(e); } catch (Error er) { this.getLog().error(er); } } private String readTestSrc(String className) { BufferedReader br = null; String test = className + "Test"; StringBuilder testSrc = new StringBuilder(); try { Class tstCls = cl.loadClass(test); Package pkg = tstCls.getPackage(); String pkgName = pkg.getName(); String relativePath = pkgName.replace(".", File.separator); String testBaseSrcPath = basedPath + File.separator + "src" + File.separator + "test" + File.separator + "java"; String testSrcFullPath = testBaseSrcPath + File.separator + relativePath + File.separator + tstCls.getSimpleName() + ".java"; br = new BufferedReader(new InputStreamReader(new FileInputStream(testSrcFullPath), "UTF-8")); String line = null; while ((line = br.readLine()) != null) { testSrc.append(line); testSrc.append("\n"); } } catch (Exception e) { this.getLog().error(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { } } return testSrc.toString(); } } /** * ??&& public protected * * @param file * @return */ private void load(String classesDir, File file, int length) { if (file.isDirectory()) { File[] files = file.listFiles(); int len = files.length; for (int i = 0; i < len; i++) { load(classesDir, files[i], length); } } else { String path = file.getAbsolutePath(); if (path.indexOf(classesDir) == 0 && path.length() > length) { String pkgPath = path.substring(length); try { String os = System.getProperty("os.name"); String exp = File.separator; if (os.toLowerCase().indexOf("window") >= 0) { exp = "\\\\"; } String tmpFile = null; if (pkgPath.endsWith(".class")) { tmpFile = pkgPath.replaceAll(exp, "."); if (tmpFile.endsWith(".class") && !tmpFile.endsWith("Mapper.class")) { String clsName = tmpFile.replaceAll(".class", ""); Class cls = cl.loadClass(clsName); int modf = cls.getModifiers(); if (modf != 1537 && modf != 1025) {// ?? && if (clsName.endsWith("ImplTest")) { testImpl.put(clsName, 1); } else if (clsName.endsWith("Impl")) { defines.put(clsName, 1); } else {// ?? errorImpl.put(clsName, 1); } } } } } catch (Exception e) { this.getLog().error(e); } catch (Error er) { this.getLog().error(er); } } } } private void write(String dest, String template, String tpl) throws MojoExecutionException { // FileWriter fw = null; OutputStreamWriter osw = null; try { new File(dest).mkdirs(); osw = new OutputStreamWriter(new FileOutputStream(dest + File.separator + template), "UTF-8"); // fw = new FileWriter(dest + File.separator + template); osw.write(tpl); } catch (IOException e) { throw new MojoExecutionException("", e); } finally { try { if (osw != null) { osw.close(); } } catch (IOException e) { } } } private void addMethod(Map<String, String> methodMap, StringBuffer methodBuffer, Method method, int cnt) throws NotFoundException { String methodName = method.getName(); StringBuilder tmpMethodBuffer = new StringBuilder(); tmpMethodBuffer.append("\t@Test\n"); Class[] types = method.getParameterTypes(); int size = types == null ? 0 : types.length; StringBuffer paramsSb = new StringBuffer("\"" + methodName + "\""); for (int i = 0; i < size; i++) { paramsSb.append(","); paramsSb.append("\"" + types[i].getSimpleName() + "\""); } String id = MD5Util.md5Hex("\"" + methodName + "\"" + paramsSb.toString() + ")"); tmpMethodBuffer.append("\t@SoaFwTest(id=\"" + id + "\", method=\"" + methodName + "\", params={" + paramsSb.toString() + "})\n"); if (cnt > 0) { methodName = methodName + "$" + cnt; } tmpMethodBuffer.append("\tpublic void " + methodName + "() {\n"); size = types == null ? 0 : types.length; if (size > 0) { tmpMethodBuffer.append("\t\t//?? "); } for (int i = 0; i < size; i++) { tmpMethodBuffer.append(types[i].getSimpleName() + "\t"); } tmpMethodBuffer.append("\n"); tmpMethodBuffer.append("\t\tthrow new RuntimeException(\"" + methodName + " test not implemented\");\n"); tmpMethodBuffer.append("\t}\n\n"); methodMap.put(id, tmpMethodBuffer.toString()); methodBuffer.append(tmpMethodBuffer); } private StringBuffer createTestJHeadByClass(Class cls) { StringBuffer jHeadBuf = new StringBuffer(); jHeadBuf.append("package " + cls.getPackage().getName() + "; \n"); jHeadBuf.append("\n"); jHeadBuf.append("import org.junit.Test;\n"); jHeadBuf.append("import org.junit.runner.RunWith;\n"); jHeadBuf.append("import org.springframework.test.context.ContextConfiguration;\n"); jHeadBuf.append("import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n"); jHeadBuf.append("import com.tower.service.annotation.SoaFwTest;\n"); jHeadBuf.append("@RunWith(SpringJUnit4ClassRunner.class)\n"); String name = project.getName(); if (config) { jHeadBuf.append("@ContextConfiguration( locations = { \"" + configFileLocations + "\"})\n"); } else { String suffix = "dao"; if (name.endsWith("-common")) { suffix = "common"; } else if (name.endsWith("-config")) { suffix = "config"; } else if (name.endsWith("-cache")) { suffix = "cache"; } else if (name.endsWith("-dao")) { suffix = "dao"; } else if (name.endsWith("-mq")) { suffix = "mq"; } else if (name.endsWith("-rpc")) { suffix = "rpc"; } else if (name.endsWith("-job")) { suffix = "job"; } else if (name.endsWith("-web")) { suffix = "dubbo"; } else if (name.endsWith("-domain") || name.endsWith("-service") || name.endsWith("-service-impl")) { suffix = "service"; } jHeadBuf.append("@ContextConfiguration( locations = { \"classpath*:/META-INF/config/spring/spring-" + suffix + ".xml\"})\n"); } jHeadBuf.append("public class " + cls.getSimpleName() + "Test {\n"); return jHeadBuf; } }