java脚本意思_Java脚本的语法解析示例

早期搞了一个解析Java脚本的功能,其中有一处是需要解析Java语法,下面的代码贴了一下主要功能, 主要用到了tools中的一些类,但是代码使用tools.jar需要在maven中做一些额外配置:

com.sun

tools

1.8

system

${JAVA_HOME}/lib/tools.jar

上面的maven配置就是为了能够在代码中使用tools.jar中的类。import com.google.common.base.Charsets;

import com.google.common.base.Joiner;

import com.google.common.base.Preconditions;

import com.google.common.base.Strings;

import com.google.common.collect.Maps;

import com.sun.tools.javac.file.JavacFileManager;

import com.sun.tools.javac.parser.JavacParser;

import com.sun.tools.javac.parser.ParserFactory;

import com.sun.tools.javac.tree.JCTree;

import com.sun.tools.javac.util.Context;

import com.sun.tools.javac.util.Name;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.util.CollectionUtils;

import javax.tools.JavaFileManager;

import java.nio.file.Files;

import java.nio.file.Path;

import java.util.List;

import java.util.Map;

public class JavaSourceCodeParser {

private static final Logger logger = LoggerFactory.getLogger(JavaSourceCodeParser.class);

private static final Joiner JOINER = Joiner.on("\n").skipNulls();

public static String parseFullyQualifiedClassName(String fileName, String scriptSourceCode) {

Preconditions.checkArgument(!Strings.isNullOrEmpty(scriptSourceCode));

JCTree.JCCompilationUnit jcCompilationUnit;

try {

Context context = new Context();

JavacFileManager javacFileManager = new JavacFileManager(context, false, Charsets.UTF_8);

context.put(JavaFileManager.class, javacFileManager);

JavacParser javacParser = ParserFactory.instance(context).newParser(scriptSourceCode, false, true, false);

jcCompilationUnit = javacParser.parseCompilationUnit();

}

catch (Exception e) {

throw new RuntimeException("脚本语法解析失败,请检查脚本内容是否正确");

}

String packageName = parsePackageName(jcCompilationUnit);

String className = parseClassName(fileName, jcCompilationUnit);

return Strings.isNullOrEmpty(packageName) ? className : packageName + "." + className;

}

private static String parsePackageName(JCTree.JCCompilationUnit jcCompilationUnit) {

JCTree.JCExpression packageName = jcCompilationUnit.getPackageName();

if (packageName == null) {

return "";

}

return packageName.toString();

}

private static String parseClassName(String fileName, JCTree.JCCompilationUnit jcCompilationUnit) {

com.sun.tools.javac.util.List typeDecls = jcCompilationUnit.getTypeDecls();

if (!CollectionUtils.isEmpty(typeDecls)) {

//如果脚本中只有一个class,就使用这个class

if (typeDecls.size() == 1) {

for (JCTree typeDecl : typeDecls) {

if (typeDecl instanceof JCTree.JCClassDecl) {

JCTree.JCClassDecl classDecl = (JCTree.JCClassDecl) typeDecl;

Name simpleName = classDecl.getSimpleName();

return simpleName.toString();

}

}

}

else {

Map jcClassDeclMap = Maps.newHashMap();

for (JCTree typeDecl : typeDecls) {

if (typeDecl instanceof JCTree.JCClassDecl) {

JCTree.JCClassDecl jcClassDecl = (JCTree.JCClassDecl) typeDecl;

jcClassDeclMap.put(jcClassDecl.getSimpleName().toString(), jcClassDecl);

}

}

//如果脚本中有多个同级的class定义,则先看谁有public

for (Map.Entry entry : jcClassDeclMap.entrySet()) {

//public/public abstract 。。。

String modifiers = entry.getValue().getModifiers().toString();

if (modifiers.contains("public")) {

return entry.getKey();

}

}

//如果都没有public的话,就使用文件名来判断, 之所以不一开始就使用文件名判断是为了降低文件名权重,避免写错

JCTree.JCClassDecl jcClassDecl = jcClassDeclMap.get(tryRemoveJavaSuffix(fileName));

if (jcClassDecl != null) {

return jcClassDecl.getSimpleName().toString();

}

throw new RuntimeException("脚本中定义了多个class,而且都没有public修饰符,同时基于脚本文件名称也无法精确确定主类,建议修改一下脚本内容,便于系统识别!");

}

}

throw new RuntimeException("从脚本内容中不能正确的解析出className,请检查脚本内容的正确性");

}

public static String readSourceCode(Path sourceCodeFilePath) {

Preconditions.checkNotNull(sourceCodeFilePath);

try {

List allLines = Files.readAllLines(sourceCodeFilePath);

return JOINER.join(allLines);

}

catch (Exception e) {

String error = String.format("readSourceCode error, sourceCodeFilePath:[%s]", sourceCodeFilePath);

logger.error(error);

throw new RuntimeException(error);

}

}

private static String tryRemoveJavaSuffix(String fileName) {

fileName = Strings.nullToEmpty(fileName).trim();

if (fileName.endsWith(".java")) {

try {

return fileName.substring(0, fileName.length() - 5);

}

catch (Exception e) {

return fileName;

}

}

return fileName;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值