代码改变世界

生成kafka内部请求与响应的接口文档

2019-08-08 09:00  chen.simon  阅读(598)  评论(0编辑  收藏  举报

生成kafka内部请求与响应的接口文档

/**
 */
package com.code260.ss.kafka10demo;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.kafka.common.protocol.types.BoundField;
import org.apache.kafka.common.protocol.types.Schema;
import org.apache.kafka.common.requests.AbstractRequest;
import org.apache.kafka.common.requests.AbstractResponse;

/**
 * @since 2019-08-07
 *
 */
public class GenKafkaRequestDoc {

	/**
	 * @param args
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {

		collect(AbstractRequest.class);
		System.out.println("=======");
		collect(AbstractResponse.class);
	}

	/**
	 * @param sedClazz
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static void collect(Class<?> sedClazz) throws IOException, ClassNotFoundException {
		List<Class<?>> children = getAllChildrenClass("org.apache.kafka", sedClazz);
		List<Class<?>> childrenOfAbstractRequest = filter(children, sedClazz);
		for (Class<?> rquestClazz : childrenOfAbstractRequest) {
			System.out.println("\n## " + rquestClazz.getSimpleName());
			try {
				Schema[] schemas = (Schema[]) rquestClazz.getDeclaredMethod("schemaVersions").invoke(null);
				for (int i = 0; i < schemas.length; i++) {
					Schema schema = schemas[i];
					System.out.println("\n### version:" + i);
					StringBuffer sb = new StringBuffer();
					sb.append(
							"<table><tr><td style=\"width:160px\">name</td><td>type</td><td  style=\"width:80px\">defaultValue</td><td>docString</td></tr>");
					for (int j = 0; j < schema.fields().length; j++) {
						BoundField field = schema.fields()[j];

						sb.append("<tr><td>").append(field.def.name).append("</td>");
						sb.append("<td>").append(field.def.type).append("</td>");
						sb.append("<td>").append(field.def.defaultValue).append("</td>");
						sb.append("<td>").append(field.def.docString).append("</td></tr>").append("\n");

					}
					sb.append("</table>  \n  \n  ");
					System.out.println(sb.toString());
				}
//				System.out.println(schemas);
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			}
		}
	}

	private static List<Class<?>> filter(List<Class<?>> children, Class<?> parentClazz) {
		List<Class<?>> result = new ArrayList<Class<?>>();
		if (children == null || children.isEmpty()) {
			return result;
		}
		for (Class<?> child : children) {
			if (isAssignedFrom(child, parentClazz)) {
				result.add(child);
			}
		}
		return result;
	}

	private static boolean isAssignedFrom(Class<?> currentClazz, Class<?> targetParentClazz) {
		if (targetParentClazz == null || currentClazz == null) {
			return false;
		}

//		Class<?>[] parentInterfaces = currentClazz.getInterfaces();
		Class<?> parentClazz = currentClazz.getSuperclass();
		while (parentClazz != null) {
			if (parentClazz.equals(targetParentClazz)) {
				return true;
			} else {
				parentClazz = parentClazz.getSuperclass();
			}
		}

		Class<?>[] parentInterfaces = currentClazz.getInterfaces();
		return isAssignedFrom(parentInterfaces, targetParentClazz);
	}

	private static boolean isAssignedFrom(Class<?>[] parentInterfaces, Class<?> targetParentClazz) {
		if (parentInterfaces == null) {
			return false;
		}
		for (Class<?> ppInterface : parentInterfaces) {
			if (ppInterface != null && ppInterface.equals(targetParentClazz)) {
				return true;
			} else {
				boolean result = isAssignedFrom(ppInterface.getInterfaces(), targetParentClazz);
				if (result) {
					return true;
				}
			}
		}
		return false;
	}

	private static List<Class<?>> getAllChildrenClass(String scanPackageStr, Class<?> parentClazz)
			throws IOException, ClassNotFoundException {
		List<Class<?>> children = new ArrayList<Class<?>>();
		Enumeration<URL> packageLocations = parentClazz.getClassLoader().getResources(scanPackageStr.replace(".", "/"));
		while (packageLocations.hasMoreElements()) {
			URL packageLocation = packageLocations.nextElement();
			String protocol = packageLocation.getProtocol();
			if ("file".equals(protocol)) {
				String filePath = URLDecoder.decode(packageLocation.getFile(), "UTF-8");
				findAndAddClassesInPackageByFile(filePath, scanPackageStr, children);
			} else if ("jar".equals(protocol)) {
				findAndAddClassesInPackageByJar(packageLocation.getPath(), scanPackageStr, children);

			}
		}
		return children;
	}

	private static void findAndAddClassesInPackageByJar(String packageLocation, String packageName,
			List<Class<?>> clazzList) throws IOException, ClassNotFoundException {
		String[] segs = packageLocation.split("!");
		String jarFilePath = segs[0].substring(segs[0].indexOf("/"));
		jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
		String packagePath = segs[1].substring(1);
		JarFile jarFile = null;
		try {
			jarFile = new JarFile(jarFilePath);
			Enumeration<JarEntry> entrys = jarFile.entries();
			while (entrys.hasMoreElements()) {
				JarEntry jarEntry = entrys.nextElement();
				String entryName = jarEntry.getName();
				if (entryName.endsWith(".class")) {
					if (entryName.startsWith(packagePath)) {
						entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
						Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(entryName);
						clazzList.add(clazz);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}	
		finally {
			if (jarFile != null) {
				jarFile.close();
			}
		}

	}

	private static void findAndAddClassesInPackageByFile(String filePath, String packageName,
			List<Class<?>> clazzList) {
		File file = new File(filePath);
		File[] children = file.listFiles();
		for (File child : children) {
			if (child.isDirectory()) {
				findAndAddClassesInPackageByFile(child.getAbsolutePath(), packageName + "." + child.getName(),
						clazzList);
			}
			if (child.isFile()) {
				if (!child.getName().endsWith(".class")) {
					continue;
				}
			}
			String childName = child.getName();
			if (!childName.endsWith(".class")) {
				continue;
			}
			String className = packageName + "." + childName.substring(0, childName.length() - ".class".length());
			try {
				Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
				clazzList.add(clazz);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}

}