From 078e9d7bf64d3915d28df1c82ab2536de66f0fd9 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 13 Mar 2024 16:20:45 +0100 Subject: [PATCH] gradle: implement dev server task --- tools/core/build.gradle.kts | 2 + .../devserver}/TeaVMDevServerRunner.java | 11 +++- .../teavm/tooling/util/FileSystemWatcher.java | 6 +- .../java/org/teavm/devserver/CodeServlet.java | 19 +++++- .../java/org/teavm/devserver/DevServer.java | 6 ++ .../teavm/gradle/tasks/CodeServerTask.java | 65 +++++++++++++++++++ 6 files changed, 104 insertions(+), 5 deletions(-) rename tools/{cli/src/main/java/org/teavm/cli => core/src/main/java/org/teavm/tooling/devserver}/TeaVMDevServerRunner.java (94%) create mode 100644 tools/gradle/src/main/java/org/teavm/gradle/tasks/CodeServerTask.java diff --git a/tools/core/build.gradle.kts b/tools/core/build.gradle.kts index dbb34a34d..63ea51f6c 100644 --- a/tools/core/build.gradle.kts +++ b/tools/core/build.gradle.kts @@ -26,8 +26,10 @@ dependencies { compileOnly(project(":jso:apis")) api(project(":core")) + implementation(project(":tools:devserver")) implementation(libs.commons.io) + implementation(libs.commons.cli) } teavmPublish { diff --git a/tools/cli/src/main/java/org/teavm/cli/TeaVMDevServerRunner.java b/tools/core/src/main/java/org/teavm/tooling/devserver/TeaVMDevServerRunner.java similarity index 94% rename from tools/cli/src/main/java/org/teavm/cli/TeaVMDevServerRunner.java rename to tools/core/src/main/java/org/teavm/tooling/devserver/TeaVMDevServerRunner.java index 6feb20380..3d19f2451 100644 --- a/tools/cli/src/main/java/org/teavm/cli/TeaVMDevServerRunner.java +++ b/tools/core/src/main/java/org/teavm/tooling/devserver/TeaVMDevServerRunner.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Alexey Andreev. + * Copyright 2024 Alexey Andreev. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.cli; +package org.teavm.tooling.devserver; import java.util.Arrays; import org.apache.commons.cli.CommandLine; @@ -94,6 +94,10 @@ private static void setupOptions() { .desc("delegate requests from path") .longOpt("proxy-path") .build()); + options.addOption(Option.builder() + .desc("don't watch file system changes") + .longOpt("no-watch") + .build()); } private TeaVMDevServerRunner(CommandLine commandLine) { @@ -144,6 +148,9 @@ private void parseArguments() { if (commandLine.hasOption("proxy-path")) { devServer.setProxyPath(commandLine.getOptionValue("proxy-path")); } + if (commandLine.hasOption("no-watch")) { + devServer.setFileSystemWatched(false); + } String[] args = commandLine.getArgs(); if (args.length != 1) { diff --git a/tools/core/src/main/java/org/teavm/tooling/util/FileSystemWatcher.java b/tools/core/src/main/java/org/teavm/tooling/util/FileSystemWatcher.java index 6676206f8..edc24bf49 100644 --- a/tools/core/src/main/java/org/teavm/tooling/util/FileSystemWatcher.java +++ b/tools/core/src/main/java/org/teavm/tooling/util/FileSystemWatcher.java @@ -102,8 +102,10 @@ public void waitForChange(int timeout) throws InterruptedException, IOException if (!hasChanges()) { take(); } - while (poll(timeout)) { - // continue polling + if (timeout > 0) { + while (poll(timeout)) { + // continue polling + } } while (pollNow()) { // continue polling diff --git a/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java b/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java index a24cac187..8bc52d39c 100644 --- a/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java +++ b/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java @@ -148,6 +148,7 @@ public class CodeServlet extends HttpServlet { private InMemorySymbolTable fileSymbolTable = new InMemorySymbolTable(); private InMemorySymbolTable variableSymbolTable = new InMemorySymbolTable(); private ReferenceCache referenceCache = new ReferenceCache(); + private boolean fileSystemWatched = true; public CodeServlet(String mainClass, String[] classPath) { this.mainClass = mainClass; @@ -201,6 +202,10 @@ public void setProxyPath(String proxyPath) { this.proxyPath = normalizePath(proxyPath); } + public void setFileSystemWatched(boolean fileSystemWatched) { + this.fileSystemWatched = fileSystemWatched; + } + public void addProgressHandler(ProgressHandler handler) { synchronized (progressHandlers) { progressHandlers.add(handler); @@ -737,7 +742,19 @@ private void runTeaVM() { synchronized (statusLock) { waiting = true; } - watcher.waitForChange(750); + if (fileSystemWatched) { + log.info("Waiting for changes in filesystem"); + watcher.waitForChange(750); + } else { + log.info("Waiting for rebuild request"); + while (true) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + watcher.waitForChange(0); + } + } + } synchronized (statusLock) { waiting = false; } diff --git a/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java b/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java index 1992ed424..4cca50f44 100644 --- a/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java +++ b/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java @@ -32,6 +32,7 @@ public class DevServer { private boolean indicator; private boolean deobfuscateStack; private boolean reloadedAutomatically; + private boolean fileSystemWatched = true; private TeaVMToolLog log; private CodeServlet servlet; private List listeners = new ArrayList<>(); @@ -88,6 +89,10 @@ public void setReloadedAutomatically(boolean reloadedAutomatically) { this.reloadedAutomatically = reloadedAutomatically; } + public void setFileSystemWatched(boolean fileSystemWatched) { + this.fileSystemWatched = fileSystemWatched; + } + public void setProxyUrl(String proxyUrl) { this.proxyUrl = proxyUrl; } @@ -137,6 +142,7 @@ public void start() { servlet.setDebugPort(debugPort); servlet.setProxyUrl(proxyUrl); servlet.setProxyPath(proxyPath); + servlet.setFileSystemWatched(fileSystemWatched); for (DevServerListener listener : listeners) { servlet.addListener(listener); } diff --git a/tools/gradle/src/main/java/org/teavm/gradle/tasks/CodeServerTask.java b/tools/gradle/src/main/java/org/teavm/gradle/tasks/CodeServerTask.java new file mode 100644 index 000000000..c467acee9 --- /dev/null +++ b/tools/gradle/src/main/java/org/teavm/gradle/tasks/CodeServerTask.java @@ -0,0 +1,65 @@ +/* + * Copyright 2024 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.gradle.tasks; + +import javax.inject.Inject; +import org.gradle.api.DefaultTask; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.Optional; +import org.gradle.internal.logging.progress.ProgressLoggerFactory; + +public abstract class CodeServerTask extends DefaultTask { + @Classpath + public abstract ConfigurableFileCollection getClasspath(); + + @Input + @Optional + public abstract Property getTargetFileName(); + + @Input + @Optional + public abstract Property getTargetFilePath(); + + @Input + @Optional + public abstract MapProperty getProperties(); + + @Input + @Optional + public abstract ListProperty getPreservedClasses(); + + @Input + public abstract Property getMainClass(); + + @Input + @Optional + public abstract Property getProcessMemory(); + + @Classpath + public abstract ConfigurableFileCollection getServerClasspath(); + + @Internal + public abstract Property getServerDebugPort(); + + @Inject + protected abstract ProgressLoggerFactory getProgressLoggerFactory(); +}