com.ideaaedi.commonds.clazz.ClassNameGrabber Maven / Gradle / Ivy
The newest version!
package com.ideaaedi.commonds.clazz;
import com.google.common.collect.Sets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.CharArrayReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 全类名抓取器
*
* 全类名形如:com.ideaaedi.commonds.clazz.ClassNameGrabber
*
*
* @author JustryDeng
* @since 1.0.0
*/
public class ClassNameGrabber {
/** class类名,必须匹配此正则 */
public static final Pattern CLASS_NAME_PATTERN =
Pattern.compile("\\s*(public\\s+|protected\\s+|private\\s+)?(static\\s+)?(final\\s+|abstract\\s+)?(static\\s+)?(class|interface|enum|@interface)\\s+");
/** class类名所在行的前缀 */
public static final Set CLASS_NAME_LINE_PREFIX_SET =
Sets.newHashSet("public", "protected", "private", "static", "final", "abstract", "class", "interface", "enums", "@interface");
/** java文件类型 */
public static final Set JAVA_FILE_TYPE = Sets.newHashSet("class", "interface", "enums", "@interface");
/**
* @see ClassNameGrabber#obtainFromSourceCode(String)
*/
public static String obtainFromSourceCode(final byte[] sourceCodeBytes) {
return ClassNameGrabber.obtainFromSourceCode(new String(sourceCodeBytes, StandardCharsets.UTF_8));
}
/**
* 获取全类名
*
* @param sourceCode
* 源码
* @return 全类名
*/
public static String obtainFromSourceCode(final String sourceCode) {
List lines = IOUtils.readLines(new CharArrayReader(sourceCode.toCharArray()));
String packageName = null;
int packageNameLine = 1;
for (String line : lines) {
// 后面可能有注释,先把可能存在的注释去掉
int idx = line.indexOf("/");
if (idx >= 0) {
line = line.substring(0, idx);
}
// 包名形如: package com.ideaaedi.hot.clazz.update;
line = line.trim().replace("\\r", "").replace("\\n", "");
if (line.startsWith("package") && line.endsWith(";")) {
packageName = line.substring("package".length(), line.length() - 1).trim();
break;
}
packageNameLine++;
}
if (packageName == null) {
throw new IllegalStateException("Cannot parse packageName from follow sourceCode: \n" + sourceCode);
}
String className = null;
String line;
StringBuilder suspectLine = new StringBuilder(4);
for (int i = packageNameLine; i < lines.size(); i++) {
line = lines.get(i);
// 后面可能有注释,先把可能存在的注释去掉
int idx = line.indexOf("/");
if (idx >= 0) {
line = line.substring(0, idx);
}
line = line.trim().replace("\\r", "").replace("\\n", "");
if (StringUtils.isBlank(line)) {
continue;
}
List segment = Arrays.stream(line.split(" ")).map(String::trim).filter(StringUtils::isNotBlank).collect(Collectors.toList());
String head = segment.get(0);
// 可疑行,可疑行可能是类名行
boolean suspect = CLASS_NAME_LINE_PREFIX_SET.contains(head) && segment.stream().anyMatch(JAVA_FILE_TYPE::contains);
if (suspect) {
suspectLine.append(line).append("\n");
}
if (suspect && CLASS_NAME_PATTERN.matcher(line).find()) {
boolean preSegmentIsType = false;
for (String seg : segment) {
seg = seg.trim();
if (preSegmentIsType) {
int haveGenericIndex = seg.indexOf("<");
if (haveGenericIndex >= 0) {
seg = seg.substring(0, haveGenericIndex);
}
className = seg;
break;
}
preSegmentIsType = JAVA_FILE_TYPE.contains(seg.trim());
}
break;
}
}
if (StringUtils.isBlank(className)) {
throw new IllegalStateException("Cannot parse className from sourceCde."
+ (suspectLine.length() == 0 ? "" : "suspectLine:\n" + suspectLine) + "\nsourceCode:\n" + sourceCode);
}
return packageName + "." + className;
}
}