diff --git a/pom.xml b/pom.xml index e9a0931..dbaf405 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 pw.yumc MiaoScript - 0.6.6 + 0.7.0 502647092 @@ -53,6 +53,7 @@ DEV + §620-05-28 §afeat: 新增 Spring 的支持; §620-05-02 §afeat: 调整 scope 为 @ccms; §620-04-10 §afeat: 默认从 classpath 加载内建的js模块; §620-04-07 §afeat: 默认初始化 内建 nodejs 模块; @@ -180,11 +181,13 @@ org.spigotmc spigot-api 1.15.2-R0.1-SNAPSHOT + compile org.spongepowered spongeapi 7.1.0 + compile net.md-5 @@ -195,6 +198,19 @@ cn.nukkit nukkit 1.0-SNAPSHOT + compile + + + org.springframework + spring-websocket + 5.2.6.RELEASE + compile + + + org.apache.tomcat + tomcat-websocket + 9.0.35 + compile - \ No newline at end of file + diff --git a/src/main/java/pw/yumc/MiaoScript/Base.java b/src/main/java/pw/yumc/MiaoScript/Base.java index 6315b31..7568d80 100644 --- a/src/main/java/pw/yumc/MiaoScript/Base.java +++ b/src/main/java/pw/yumc/MiaoScript/Base.java @@ -21,7 +21,7 @@ public class Base { this.instance = instance; } - public Class getClass(String name) throws ClassNotFoundException { + public Class getClass(String name) throws ClassNotFoundException { return Class.forName(name); } @@ -29,7 +29,7 @@ public class Base { return this.instance; } - public Class getProxyClass() { + public Class getProxyClass() { return ProxyClass.class; } diff --git a/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java b/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java new file mode 100644 index 0000000..1e1eb8e --- /dev/null +++ b/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java @@ -0,0 +1,34 @@ +package pw.yumc.MiaoScript; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +import java.io.File; +import javax.annotation.PreDestroy; + +@Slf4j +@Component +public class MiaoScriptSpring { + private ScriptEngine engine; + + @Bean + @SneakyThrows + public ScriptEngine buildScriptEngine(ApplicationContext applicationContext) { + return new ScriptEngine(new File("MiaoScript").getCanonicalPath(), log, applicationContext); + } + + @Bean + public ServerEndpointExporter serverEndpointExporter() { + return new ServerEndpointExporter(); + } + + @PreDestroy + public void disableEngine() { + engine.disableEngine(); + engine = null; + } +} diff --git a/src/main/java/pw/yumc/MiaoScript/ScriptEngine.java b/src/main/java/pw/yumc/MiaoScript/ScriptEngine.java index d846c5e..3f856dc 100644 --- a/src/main/java/pw/yumc/MiaoScript/ScriptEngine.java +++ b/src/main/java/pw/yumc/MiaoScript/ScriptEngine.java @@ -1,6 +1,5 @@ package pw.yumc.MiaoScript; -import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -12,8 +11,7 @@ import lombok.SneakyThrows; /** * Created with IntelliJ IDEA * - * @author 喵♂呜 - * Created on 2017/10/25 21:01. + * @author 喵♂呜 Created on 2017/10/25 21:01. */ public class ScriptEngine { private String root; @@ -30,24 +28,28 @@ public class ScriptEngine { } @SneakyThrows - public void enableEngine() { - this.engine = new MiaoScriptEngine(manager, "nashorn"); - this.engine.put("base", this.base); - this.engine.put("ScriptEngineContextHolder", this); - Path bios = Paths.get(root, "bios.js"); - // 如果存在自定义bios就加载自定义的 - if (Files.exists(bios)) { - this.engine.eval("load('" + bios.toFile().getCanonicalPath() + "')"); - } else { - this.engine.eval("load('classpath:bios.js')"); + public synchronized void enableEngine() { + if (this.engine == null) { + this.engine = new MiaoScriptEngine(manager, "nashorn"); + this.engine.put("base", this.base); + this.engine.put("ScriptEngineContextHolder", this); + Path bios = Paths.get(root, "bios.js"); + // 如果存在自定义bios就加载自定义的 + if (Files.exists(bios)) { + this.engine.eval("load('" + bios.toFile().getCanonicalPath() + "')"); + } else { + this.engine.eval("load('classpath:bios.js')"); + } + engine.invokeFunction("boot", root, logger); } - engine.invokeFunction("boot", root, logger); } @SneakyThrows - public void disableEngine() { - this.engine.invokeFunction("engineDisable"); - this.engine = null; + public synchronized void disableEngine() { + if (this.engine != null) { + this.engine.invokeFunction("engineDisable"); + this.engine = null; + } } public MiaoScriptEngine getEngine() { diff --git a/src/main/java/pw/yumc/MiaoScript/websocket/WebSocketServer.java b/src/main/java/pw/yumc/MiaoScript/websocket/WebSocketServer.java new file mode 100644 index 0000000..12bb3df --- /dev/null +++ b/src/main/java/pw/yumc/MiaoScript/websocket/WebSocketServer.java @@ -0,0 +1,70 @@ +package pw.yumc.MiaoScript.websocket; + +import lombok.SneakyThrows; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import javax.websocket.*; +import javax.websocket.server.ServerEndpoint; + +@Component +@ServerEndpoint("/ws/") +public class WebSocketServer implements ApplicationContextAware { + private static ApplicationContext context; + private WebSocketServerProxy proxy; + + private boolean checkProxy(Session session) { + try { + if (this.proxy == null) { + this.proxy = context.getBean(WebSocketServerProxy.class); + } + return true; + } catch (Exception ex) { + try { + session.close(); + } catch (Exception ignore) { + } + return false; + } + } + + @OnOpen + @SneakyThrows + public void onOpen(Session session, EndpointConfig config) { + if (this.checkProxy(session)) { + this.proxy.onOpen(session, config); + } + } + + @OnMessage + @SneakyThrows + public void onMessage(Session session, String message) { + if (this.checkProxy(session)) { + this.proxy.onMessage(session, message); + } + } + + @OnClose + @SneakyThrows + public void onClose(Session session, CloseReason reason) { + if (this.checkProxy(session)) { + this.proxy.onClose(session, reason); + } + } + + @OnError + @SneakyThrows + public void onError(Session session, Throwable error) { + if (this.checkProxy(session)) { + this.proxy.onError(session, error); + } + } + + @Override + public void setApplicationContext(ApplicationContext ctx) throws BeansException { + context = ctx; + } +} diff --git a/src/main/java/pw/yumc/MiaoScript/websocket/WebSocketServerProxy.java b/src/main/java/pw/yumc/MiaoScript/websocket/WebSocketServerProxy.java new file mode 100644 index 0000000..65c73a6 --- /dev/null +++ b/src/main/java/pw/yumc/MiaoScript/websocket/WebSocketServerProxy.java @@ -0,0 +1,15 @@ +package pw.yumc.MiaoScript.websocket; + +import javax.websocket.CloseReason; +import javax.websocket.EndpointConfig; +import javax.websocket.Session; + +public interface WebSocketServerProxy { + void onOpen(Session session, EndpointConfig config); + + void onMessage(Session session, String message); + + void onClose(Session session, CloseReason reason); + + void onError(Session session, Throwable error); +} diff --git a/src/main/resources/bios.js b/src/main/resources/bios.js index 1c6e42b..2ea2e2b 100644 --- a/src/main/resources/bios.js +++ b/src/main/resources/bios.js @@ -32,11 +32,9 @@ var global = this; }, "MiaoScript thread").start() }; - var pluginYml; function checkClassLoader() { var classLoader = java.lang.Thread.currentThread().contextClassLoader; - pluginYml = classLoader.getResource("plugin.yml"); - if (pluginYml === null) { + if (classLoader.getResource("bios.js") === null) { throw Error("Error class loader: " + classLoader.class.name + " Please contact the author MiaoWoo!"); } else { log.info("Class loader compatible: " + classLoader.class.name);